-
Notifications
You must be signed in to change notification settings - Fork 0
/
Cypress-Structure.pck
1598 lines (1341 loc) · 50.5 KB
/
Cypress-Structure.pck
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
'From Cuis 4.0 of 21 April 2012 [latest update: #1308] on 6 October 2012 at 10:37:02 pm'!
'Description Install after Cypress-Definitions. Includes package reader and writer.
View class comments for CypressPackageReader and CypressPackageWriter'!
!classDefinition: #CypressJsonParser category: #'Cypress-Structure'!
Object subclass: #CypressJsonParser
instanceVariableNames: 'stream'
classVariableNames: ''
poolDictionaries: ''
category: 'Cypress-Structure'!
!classDefinition: 'CypressJsonParser class' category: #'Cypress-Structure'!
CypressJsonParser class
instanceVariableNames: ''!
!classDefinition: #CypressPackageReader category: #'Cypress-Structure'!
Object subclass: #CypressPackageReader
instanceVariableNames: 'packageDirectory packageStructure properties'
classVariableNames: ''
poolDictionaries: ''
category: 'Cypress-Structure'!
!classDefinition: 'CypressPackageReader class' category: #'Cypress-Structure'!
CypressPackageReader class
instanceVariableNames: ''!
!classDefinition: #CypressPackageWriter category: #'Cypress-Structure'!
Object subclass: #CypressPackageWriter
instanceVariableNames: 'packageStructure rootDirectory packageDirectory'
classVariableNames: ''
poolDictionaries: ''
category: 'Cypress-Structure'!
!classDefinition: 'CypressPackageWriter class' category: #'Cypress-Structure'!
CypressPackageWriter class
instanceVariableNames: 'specials'!
!classDefinition: #CypressStructure category: #'Cypress-Structure'!
Object subclass: #CypressStructure
instanceVariableNames: 'name properties packageStructure'
classVariableNames: ''
poolDictionaries: ''
category: 'Cypress-Structure'!
!classDefinition: 'CypressStructure class' category: #'Cypress-Structure'!
CypressStructure class
instanceVariableNames: ''!
!classDefinition: #CypressClassStructure category: #'Cypress-Structure'!
CypressStructure subclass: #CypressClassStructure
instanceVariableNames: 'instanceMethods classMethods comment isClassExtension'
classVariableNames: ''
poolDictionaries: ''
category: 'Cypress-Structure'!
!classDefinition: 'CypressClassStructure class' category: #'Cypress-Structure'!
CypressClassStructure class
instanceVariableNames: ''!
!classDefinition: #CypressMethodStructure category: #'Cypress-Structure'!
CypressStructure subclass: #CypressMethodStructure
instanceVariableNames: 'source isMetaclass classStructure timeStamp'
classVariableNames: ''
poolDictionaries: ''
category: 'Cypress-Structure'!
!classDefinition: 'CypressMethodStructure class' category: #'Cypress-Structure'!
CypressMethodStructure class
instanceVariableNames: ''!
!classDefinition: #CypressPackageStructure category: #'Cypress-Structure'!
CypressStructure subclass: #CypressPackageStructure
instanceVariableNames: 'classes extensions'
classVariableNames: ''
poolDictionaries: ''
category: 'Cypress-Structure'!
!classDefinition: 'CypressPackageStructure class' category: #'Cypress-Structure'!
CypressPackageStructure class
instanceVariableNames: ''!
!CypressPackageReader commentStamp: '<historical>' prior: 0!
Reader for the Cypress multi-dialect file format for Smalltalk packages
CypressPackageReader installAsCodePackage: (FileDirectory default directoryNamed: 'Cypress-Mocks.package')!
!CypressPackageWriter commentStamp: 'jmv 6/13/2012 09:13' prior: 0!
Writer for the Cypress multi-dialect file format for Smalltalk packages
CypressPackageWriter writeCodePackage: (CodePackage named: 'Cypress-Mocks' createIfAbsent: true registerIfNew: false)
CypressPackageWriter writeCodePackage: (CodePackage named: 'Cypress-Structure' createIfAbsent: true registerIfNew: false)
CypressPackageWriter writeCodePackage: (CodePackage named: 'Morphic' createIfAbsent: true registerIfNew: false)!
!Array methodsFor: '*Cypress-Structure'!
asCypressPropertyObject
^self collect: [:each | each asCypressPropertyObject ]
! !
!Array methodsFor: '*Cypress-Structure' stamp: 'jmv 6/14/2012 23:07'!
writeCypressJsonOn: aStream forHtml: forHtml indent: startIndent
| indent |
aStream
nextPutAll: '[';
newLine.
indent := startIndent + 1.
1 to: self size do: [:index | | item |
item := self at: index.
aStream tab: indent.
item writeCypressJsonOn: aStream forHtml: forHtml indent: indent.
index < self size ifTrue: [ aStream nextPutAll: ','; newLine ]].
self size = 0 ifTrue: [ aStream tab: indent ].
aStream nextPutAll: ' ]'
! !
!Boolean methodsFor: '*Cypress-Structure' stamp: 'jmv 6/14/2012 23:07'!
writeCypressJsonOn: aStream forHtml: forHtml indent: startIndent
aStream
nextPutAll: self printString
! !
!Character methodsFor: '*Cypress-Structure' stamp: 'dkh 4/23/2012 23:50'!
isSafeForHTTP
"whether a character is 'safe', or needs to be escaped when used, eg, in a URL"
^ value < 128
and: [ self isAlphaNumeric
or: [ '.-_' includes: self ]]
! !
!CypressClassStructure methodsFor: 'converting'!
asCypressClassDefinition
self isClassExtension ifTrue: [ ^nil ].
^CypressClassDefinition
name: self className
superclassName: self superclassName
category: self category
instVarNames: self instanceVariableNames
classInstVarNames: self classInstanceVariableNames
comment: self comment
! !
!CypressClassStructure methodsFor: 'accessing'!
category
^self packageStructure packageName
! !
!CypressClassStructure methodsFor: 'accessing'!
classInstanceVariableNames
^self properties at: 'classinstvars' ifAbsent: ['']
! !
!CypressClassStructure methodsFor: 'accessing'!
classInstanceVariableNames: aString
^self properties at: 'classinstvars' put: aString
! !
!CypressClassStructure methodsFor: 'querying'!
classMethodNamed: methodName
^self classMethods
at: methodName
ifAbsent: [ self classMethods at: methodName put: (CypressMethodStructure new name: methodName) ]
! !
!CypressClassStructure methodsFor: 'accessing'!
classMethods
classMethods ifNil: [ classMethods := Dictionary new ].
^classMethods
! !
!CypressClassStructure methodsFor: 'accessing'!
className
^self name
! !
!CypressClassStructure methodsFor: 'accessing'!
comment
comment ifNil: [ comment := '' ].
^comment
! !
!CypressClassStructure methodsFor: 'accessing'!
comment: aString
comment := aString
! !
!CypressClassStructure methodsFor: 'initialization'!
fromClassDefinition: classDefinition
self isClassExtension: false.
self name: classDefinition name.
self comment: classDefinition comment.
self superclassName: classDefinition superclassName.
self instanceVariableNames: classDefinition instVarNames.
self classInstanceVariableNames: classDefinition classInstVarNames.
! !
!CypressClassStructure methodsFor: 'initialization'!
fromJs: jsObject
properties := jsObject at: 'properties.json'.
(jsObject at: 'class' ifAbsent: [#()]) do: [:jsMethodObject | | methodNameParts |
methodNameParts := self splitMethodNameFor: jsMethodObject.
(self classMethodNamed: (methodNameParts at: 1))
packageStructure: self packageStructure;
classStructure: self;
isMetaclass: true;
fromJs: jsMethodObject named: methodNameParts ].
(jsObject at: 'instance' ifAbsent: [#()]) do: [:jsMethodObject | | methodNameParts |
methodNameParts := self splitMethodNameFor: jsMethodObject.
(self instanceMethodNamed: (methodNameParts at: 1))
packageStructure: self packageStructure;
classStructure: self;
fromJs: jsMethodObject named: methodNameParts ].
comment := jsObject at: 'README.md' ifAbsent: ['']
! !
!CypressClassStructure methodsFor: 'querying'!
instanceMethodNamed: methodName
^self instanceMethods
at: methodName
ifAbsent: [ self instanceMethods at: methodName put: (CypressMethodStructure new name: methodName) ]
! !
!CypressClassStructure methodsFor: 'accessing'!
instanceMethods
instanceMethods ifNil: [ instanceMethods := Dictionary new ].
^instanceMethods
! !
!CypressClassStructure methodsFor: 'accessing'!
instanceVariableNames
^self properties at: 'instvars' ifAbsent: ['']
! !
!CypressClassStructure methodsFor: 'accessing'!
instanceVariableNames: aString
^self properties at: 'instvars' put: aString
! !
!CypressClassStructure methodsFor: 'accessing'!
isClassExtension
isClassExtension ifNil: [ isClassExtension := true ].
^isClassExtension
! !
!CypressClassStructure methodsFor: 'accessing'!
isClassExtension: aBoolean
isClassExtension := aBoolean
! !
!CypressClassStructure methodsFor: 'accessing'!
name
^self properties at: 'name'
! !
!CypressClassStructure methodsFor: 'accessing'!
name: aString
self properties at: 'name' put: aString
! !
!CypressClassStructure methodsFor: 'accessing' stamp: 'jmv 6/6/2012 23:07'!
properties: classPropertiesDict
properties _ classPropertiesDict! !
!CypressClassStructure methodsFor: 'private' stamp: 'dkh 4/23/2012 23:25'!
splitMethodName: methodName
| ext |
ext := '.json'.
( '*' , ext match: methodName)
ifFalse: [
ext := '.st'.
('*' , ext match: methodName)
ifFalse: [ self error: 'invalid structure element: ', methodName ] ].
^{methodName copyFrom: 1 to: (methodName size - ext size). ext}
! !
!CypressClassStructure methodsFor: 'private' stamp: 'dkh 4/23/2012 23:24'!
splitMethodNameFor: jsMethodObject
^self splitMethodName: (jsMethodObject at: 'name')! !
!CypressClassStructure methodsFor: 'accessing'!
superclassName
^self properties at: 'super'
! !
!CypressClassStructure methodsFor: 'accessing'!
superclassName: aString
^self properties at: 'super' put: aString
! !
!CypressClassStructure methodsFor: 'writing' stamp: 'jmv 6/14/2012 23:09'!
writeJsonOn: aStream indent: startIndent
| indent methods |
indent := startIndent.
aStream
tab: indent;
nextPutAll: '{';
newLine.
indent := indent + 1.
aStream
tab: indent;
nextPutAll: '"name"';
nextPutAll: ' : ';
nextPutAll: '"', self name, (self isClassExtension ifTrue: [ '.extension' ] ifFalse: [ '.class' ]), '",';
newLine.
aStream
tab: indent;
nextPutAll: '"instance" : [';
newLine;
yourself.
methods := self instanceMethods values asArray sorted: [:a :b | a selector <= b selector].
1 to: methods size do: [:index | | methodStructure |
methodStructure := methods at: index.
methodStructure writeJsonOn: aStream indent: indent + 1.
index < methods size ifTrue: [ aStream nextPutAll: ','; newLine ]].
aStream
tab: indent;
nextPutAll: '],';
newLine;
yourself.
aStream
tab: indent;
nextPutAll: '"class" : [';
newLine;
yourself.
methods := self classMethods values asArray sorted: [:a :b | a selector <= b selector].
1 to: methods size do: [:index | | methodStructure |
methodStructure := methods at: index.
methodStructure writeJsonOn: aStream indent: indent + 1.
index < methods size ifTrue: [ aStream nextPutAll: ','; newLine ]].
aStream
tab: indent;
nextPutAll: ']'.
self isClassExtension
ifFalse: [
aStream
nextPutAll: ',';
newLine;
tab: indent;
nextPutAll: '"README.md" : ';
yourself.
self comment writeCypressJsonOn: aStream forHtml: true indent: indent ].
aStream
nextPutAll: ',';
newLine;
tab: indent;
nextPutAll: '"properties.json" : ';
yourself.
self properties writeCypressJsonOn: aStream forHtml: true indent: indent.
indent := indent - 1.
aStream
newLine;
tab: indent;
nextPutAll: ' }'
! !
!CypressClassStructure class methodsFor: 'instance creation'!
fromClassDefinition: classDefinition
^self new
fromClassDefinition: classDefinition;
yourself
! !
!CypressJsonParser methodsFor: 'adding' stamp: 'dkh 2/16/2012 14:39:25'!
addProperty: anAssociation to: anObject
"Add the property anAssociation described with key and value to anObject. Subclasses might want to refine this implementation."
^ anObject
add: anAssociation;
yourself! !
!CypressJsonParser methodsFor: 'adding' stamp: 'dkh 2/16/2012 14:39:25'!
addValue: anObject to: aCollection
"Add anObject to aCollection. Subclasses might want to refine this implementation."
^ aCollection copyWith: anObject! !
!CypressJsonParser methodsFor: 'creating' stamp: 'dkh 2/16/2012 14:39:25'!
createArray
"Create an empty collection. Subclasses might want to refine this implementation."
^ Array new! !
!CypressJsonParser methodsFor: 'creating' stamp: 'dkh 2/16/2012 14:39:25'!
createFalse
"Create the false literal. Subclasses might want to refine this implementation."
^ false! !
!CypressJsonParser methodsFor: 'creating' stamp: 'dkh 2/16/2012 14:39:25'!
createNull
"Create the null literal. Subclasses might want to refine this implementation."
^ nil! !
!CypressJsonParser methodsFor: 'creating' stamp: 'dkh 2/16/2012 14:39:25'!
createNumber: aString
"Create a number literal. Subclasses might want to refine this implementation."
^ aString asNumber! !
!CypressJsonParser methodsFor: 'creating' stamp: 'dkh 2/16/2012 14:39:25'!
createObject
"Create an empty object. Subclasses might want to refine this implementation."
^ Dictionary new! !
!CypressJsonParser methodsFor: 'creating' stamp: 'dkh 2/16/2012 14:39:25'!
createProperty: aKey with: aValue
"Create an empty attribute value pair. Subclasses might want to refine this implementation."
^ aKey -> aValue! !
!CypressJsonParser methodsFor: 'creating' stamp: 'dkh 2/16/2012 14:39:25'!
createString: aString
"Create a string literal. Subclasses might want to refine this implementation."
^ aString! !
!CypressJsonParser methodsFor: 'creating' stamp: 'dkh 2/16/2012 14:39:25'!
createTrue
"Create the true literal. Subclasses might want to refine this implementation."
^ true! !
!CypressJsonParser methodsFor: 'private' stamp: 'dkh 2/16/2012 14:39:25'!
expect: aString
"Expects aString and consume input, throw an error otherwise."
^ (self match: aString) ifFalse: [ self error: aString , ' expected' ]! !
!CypressJsonParser methodsFor: 'initialization' stamp: 'dkh 2/16/2012 14:39:25'!
initializeOn: aStream
self initialize.
stream := aStream! !
!CypressJsonParser methodsFor: 'private' stamp: 'dkh 2/16/2012 14:39:25'!
match: aString
"Tries to match aString, consume input and answer true if successful."
| position |
position := stream position.
aString do: [ :each |
(stream atEnd or: [ stream next ~= each ]) ifTrue: [
stream position: position.
^ false ] ].
self whitespace.
^ true! !
!CypressJsonParser methodsFor: 'parsing' stamp: 'dkh 2/16/2012 14:39:25'!
parse
| result |
result := self whitespace; parseValue.
stream atEnd
ifFalse: [ self error: 'end of input expected' ].
^ result! !
!CypressJsonParser methodsFor: 'parsing' stamp: 'dkh 2/16/2012 14:39:25'!
parseArray
| result |
self expect: '['.
result := self createArray.
(self match: ']')
ifTrue: [ ^ result ].
[ stream atEnd ] whileFalse: [
result := self
addValue: self parseValue
to: result.
(self match: ']')
ifTrue: [ ^ result ].
self expect: ',' ].
self error: 'end of array expected'! !
!CypressJsonParser methodsFor: 'parsing-internal' stamp: 'dkh 4/23/2012 23:39'!
parseCharacter
| char |
(char := stream next) = $\
ifFalse: [ ^ char ].
(char := stream next) = $"
ifTrue: [ ^ char ].
char = $\
ifTrue: [ ^ char ].
char = $/
ifTrue: [ ^ char ].
char = $b
ifTrue: [ ^ Character backspace ].
char = $f
ifTrue: [ ^ Character newPage ].
char = $n
ifTrue: [ ^ Character lfCharacter ].
char = $r
ifTrue: [ ^ Character crCharacter ].
char = $t
ifTrue: [ ^ Character tab ].
char = $u
ifTrue: [ ^ self parseCharacterHex ].
self error: 'invalid escape character \' , (String with: char)! !
!CypressJsonParser methodsFor: 'parsing-internal' stamp: 'jmv 6/6/2012 11:57'!
parseCharacterHex
| value |
value := self parseCharacterHexDigit.
3 timesRepeat: [ value := (value << 4) + self parseCharacterHexDigit ].
^ Character unicodeCodePoint: value! !
!CypressJsonParser methodsFor: 'parsing-internal' stamp: 'jmv 6/6/2012 11:56'!
parseCharacterHexDigit
| digit |
stream atEnd ifFalse: [
digit _ stream next asUppercase digitValue.
"accept hex digits"
(digit >= 0 and: [ digit < 16 ]) ifTrue: [ ^ digit ]].
self error: 'hex-digit expected'.! !
!CypressJsonParser methodsFor: 'parsing-internal' stamp: 'dkh 2/16/2012 14:39:25'!
parseNumber
| negated number |
negated := stream peek = $-.
negated ifTrue: [ stream next ].
number := self parseNumberInteger.
(stream peek = $.) ifTrue: [
stream next.
number := number + self parseNumberFraction ].
(stream peek = $e or: [ stream peek = $E ]) ifTrue: [
stream next.
number := number * self parseNumberExponent ].
negated ifTrue: [ number := number negated ].
^ self whitespace; createNumber: number! !
!CypressJsonParser methodsFor: 'parsing-internal' stamp: 'jmv 6/6/2012 11:57'!
parseNumberExponent
| number negated |
number := 0.
negated := stream peek = $-.
(negated or: [ stream peek = $+ ])
ifTrue: [ stream next ].
[ stream atEnd not and: [ stream peek isDigit ] ] whileTrue: [ number := 10 * number + (stream next digitValue) ].
negated
ifTrue: [ number := number negated ].
^ 10 raisedTo: number! !
!CypressJsonParser methodsFor: 'parsing-internal' stamp: 'jmv 6/6/2012 11:57'!
parseNumberFraction
| number power |
number := 0.
power := 1.0.
[ stream atEnd not and: [ stream peek isDigit ] ]
whileTrue: [
number := 10 * number + (stream next digitValue).
power := power * 10.0 ].
^ number / power! !
!CypressJsonParser methodsFor: 'parsing-internal' stamp: 'dkh 4/23/2012 23:35'!
parseNumberInteger
| number |
number := 0.
[ stream atEnd not and: [ stream peek isDigit ] ] whileTrue: [ number := 10 * number + (stream next asciiValue - 48) ].
^ number! !
!CypressJsonParser methodsFor: 'parsing' stamp: 'dkh 2/16/2012 14:39:25'!
parseObject
| result |
self expect: '{'.
result := self createObject.
(self match: '}')
ifTrue: [ ^ result ].
[ stream atEnd ] whileFalse: [
result := self
addProperty: self parseProperty
to: result.
(self match: '}')
ifTrue: [ ^ result ].
self expect: ',' ].
self error: 'end of object expected'! !
!CypressJsonParser methodsFor: 'parsing-internal' stamp: 'dkh 2/16/2012 14:39:25'!
parseProperty
| name value |
name := self parseString.
self expect: ':'.
value := self parseValue.
^ self createProperty: name with: value.! !
!CypressJsonParser methodsFor: 'parsing-internal' stamp: 'dkh 2/16/2012 14:39:25'!
parseString
| result |
self expect: '"'.
result := WriteStream on: String new.
[ stream atEnd or: [ stream peek = $" ] ]
whileFalse: [ result nextPut: self parseCharacter ].
^ self expect: '"'; createString: result contents! !
!CypressJsonParser methodsFor: 'parsing' stamp: 'dkh 2/16/2012 14:39:25'!
parseValue
| char |
stream atEnd ifFalse: [
char := stream peek.
char = ${
ifTrue: [ ^ self parseObject ].
char = $[
ifTrue: [ ^ self parseArray ].
char = $"
ifTrue: [ ^ self parseString ].
(char = $- or: [ char between: $0 and: $9 ])
ifTrue: [ ^ self parseNumber ].
(self match: 'true')
ifTrue: [ ^ self createTrue ].
(self match: 'false')
ifTrue: [ ^ self createFalse ].
(self match: 'null')
ifTrue: [ ^ self createNull ] ].
self error: 'invalid input'! !
!CypressJsonParser methodsFor: 'private' stamp: 'dkh 2/16/2012 14:39:25'!
whitespace
"Strip whitespaces from the input stream."
[ stream atEnd not and: [ stream peek isSeparator ] ]
whileTrue: [ stream next ]! !
!CypressJsonParser class methodsFor: 'instance creation' stamp: 'dkh 2/16/2012 14:39:25'!
new
self error: 'Instantiate the parser with a stream.'! !
!CypressJsonParser class methodsFor: 'instance creation' stamp: 'dkh 2/16/2012 14:39:25'!
on: aStream
^ self basicNew initializeOn: aStream! !
!CypressJsonParser class methodsFor: 'accessing' stamp: 'dkh 2/16/2012 14:39:25'!
parse: aString
^ self parseStream: aString readStream! !
!CypressJsonParser class methodsFor: 'accessing' stamp: 'dkh 2/16/2012 14:39:25'!
parseStream: aStream
^ (self on: aStream) parse! !
!CypressMethodStructure methodsFor: 'converting' stamp: 'jmv 6/14/2012 23:50'!
asCypressMethodDefinition
^CypressMethodDefinition
className: self classStructure className
classIsMeta: self isMetaclass
selector: self selector
category: self category
source: self source
timeStamp: self timeStamp! !
!CypressMethodStructure methodsFor: 'accessing'!
category
^self properties at: 'category'
! !
!CypressMethodStructure methodsFor: 'accessing'!
category: aString
self properties at: 'category' put: aString
! !
!CypressMethodStructure methodsFor: 'accessing'!
classStructure
^classStructure
! !
!CypressMethodStructure methodsFor: 'accessing'!
classStructure: aCypressClassStructure
classStructure := aCypressClassStructure
! !
!CypressMethodStructure methodsFor: 'accessing' stamp: 'dkh 4/23/2012 23:37'!
cypressSource
| stream |
stream := WriteStream on: String new.
stream
nextPutAll: self category;
newLine;
nextPutAll: self source.
^stream contents
! !
!CypressMethodStructure methodsFor: 'private' stamp: 'dkh 4/23/2012 23:28'!
extractCypressSource: aString
| stream categoryStream sourceStream readingCategory |
stream := ReadStream on: aString.
categoryStream := WriteStream on: String new.
sourceStream := WriteStream on: String new.
readingCategory := true.
[ stream atEnd ]
whileFalse: [
| char |
char := stream next.
readingCategory
ifTrue: [
char = Character lfCharacter
ifTrue: [ readingCategory := false ]
ifFalse: [ categoryStream nextPut: char ] ]
ifFalse: [ sourceStream nextPut: char ] ].
self category: categoryStream contents.
self source: sourceStream contents! !
!CypressMethodStructure methodsFor: 'initialization'!
fromJs: jsObject named: methodNameParts
| ext |
(ext := methodNameParts at: 2) = '.st'
ifTrue: [ self extractCypressSource: (jsObject at: 'contents') ]
ifFalse: [ ext = '.json' ifTrue: [ properties := jsObject at: 'contents' ] ]
! !
!CypressMethodStructure methodsFor: 'initialization' stamp: 'jmv 6/15/2012 00:21'!
fromMethodDefinition: methodDefinition
self isMetaclass: methodDefinition classIsMeta.
self selector: methodDefinition selector.
self category: methodDefinition category.
self source: methodDefinition source.
self timeStamp: methodDefinition timeStamp.! !
!CypressMethodStructure methodsFor: 'accessing'!
isMetaclass
isMetaclass ifNil: [ isMetaclass := false ].
^isMetaclass
! !
!CypressMethodStructure methodsFor: 'accessing'!
isMetaclass: aBoolean
isMetaclass := aBoolean
! !
!CypressMethodStructure methodsFor: 'accessing' stamp: 'dkh 4/24/2012 00:07'!
selector
^ String
streamContents: [ :stream |
self name
do: [ :chara |
stream
nextPut:
(chara = $.
ifTrue: [ $: ]
ifFalse: [ chara ]) ] ]! !
!CypressMethodStructure methodsFor: 'accessing' stamp: 'dkh 4/24/2012 00:06'!
selector: aString
name := String
streamContents: [ :stream |
aString
do: [ :chara |
stream
nextPut:
(chara = $:
ifTrue: [ $. ]
ifFalse: [ chara ]) ] ]! !
!CypressMethodStructure methodsFor: 'accessing'!
source
^source
! !
!CypressMethodStructure methodsFor: 'accessing'!
source: aString
source := aString
! !
!CypressMethodStructure methodsFor: 'accessing' stamp: 'jmv 6/14/2012 23:50'!
timeStamp
^timeStamp
! !
!CypressMethodStructure methodsFor: 'accessing' stamp: 'jmv 6/14/2012 23:51'!
timeStamp: aTimeStamp
timeStamp := aTimeStamp! !
!CypressMethodStructure methodsFor: 'writing' stamp: 'jmv 6/14/2012 23:09'!
writeJsonOn: aStream indent: startIndent
| indent |
indent := startIndent.
aStream
tab: indent;
nextPutAll: '{';
newLine.
indent := indent + 1.
aStream
tab: indent;
nextPutAll: '"name"';
nextPutAll: ' : ';
nextPutAll: '"', self name, '.st",';
newLine.
aStream
tab: indent;
nextPutAll: '"contents"';
nextPutAll: ' : '.
self cypressSource writeCypressJsonOn: aStream forHtml: true indent: indent.
indent := indent - 1.
aStream
newLine;
tab: indent;
nextPutAll: ' }'
! !
!CypressMethodStructure class methodsFor: 'instance creation'!
fromMethodDefinition: methodDefinition
^self new
fromMethodDefinition: methodDefinition;
yourself
! !
!CypressPackageReader methodsFor: 'private' stamp: 'jmv 6/6/2012 23:24'!
classStructureFrom: classPropertiesDict
^(CypressClassStructure new)
isClassExtension: true;
properties: classPropertiesDict;
packageStructure: packageStructure;
yourself! !
!CypressPackageReader methodsFor: 'private' stamp: 'dkh 4/22/2012 13:24:15'!
classStructureFrom: classPropertiesDict comment: classComment.
^(self classStructureFrom: classPropertiesDict)
isClassExtension: false;
comment: classComment;
yourself! !
!CypressPackageReader methodsFor: 'accessing' stamp: 'dkh 4/22/2012 13:24:15'!
packageDirectory
^packageDirectory! !
!CypressPackageReader methodsFor: 'accessing' stamp: 'dkh 4/22/2012 13:24:15'!
packageDirectory: aDirectory
packageDirectory := aDirectory! !
!CypressPackageReader methodsFor: 'accessing' stamp: 'dkh 4/22/2012 13:24:15'!
packageStructure
^packageStructure! !
!CypressPackageReader methodsFor: 'accessing' stamp: 'dkh 4/22/2012 13:24:15'!
packageStructure: aPackageStructure
packageStructure := aPackageStructure! !
!CypressPackageReader methodsFor: 'reading' stamp: 'dkh 4/22/2012 13:24:15'!
read
self readPropertiesFile.
self readPackageStructure! !
!CypressPackageReader methodsFor: 'reading' stamp: 'jmv 6/14/2012 23:45'!
readClassStructureFromEntry: classEntry
| classDirectory methodPropertiesDict classPropertiesDict classComment entries classStructure |
classDirectory _ classEntry asFileDirectory.
entries _ classDirectory entries.
(entries
detect: [ :entry | entry name = 'methodProperties.json' ]
ifNone: [ ]) ifNotNil: [ :propertyEntry |
propertyEntry readStreamDo: [ :fileStream |
methodPropertiesDict _ CypressJsonParser parseStream: fileStream ]].
(entries
detect: [ :entry | entry name = 'properties.json' ]
ifNone: [ ]) ifNotNil: [ :propertyEntry |
propertyEntry readStreamDo: [ :fileStream |
classPropertiesDict _ CypressJsonParser parseStream: fileStream ]].
(entries
detect: [ :entry | entry name = 'README.md' ]
ifNone: [ ]) ifNotNil: [ :commentEntry |
commentEntry readStreamDo: [ :fileStream |
classComment _ fileStream contents ]].
classStructure _ self
classStructureFrom: classPropertiesDict
comment: classComment.
self
readMethodStructureFor: classStructure
in: entries
methodProperties: methodPropertiesDict.
^ classStructure.! !
!CypressPackageReader methodsFor: 'reading' stamp: 'jmv 6/14/2012 23:45'!
readExtensionClassStructureFromEntry: classEntry
| classDirectory methodPropertiesDict classPropertiesDict entries classStructure |
classDirectory _ classEntry asFileDirectory.
entries _ classDirectory entries.
(entries
detect: [ :entry | entry name = 'methodProperties.json' ]
ifNone: [ ]) ifNotNil: [ :propertyEntry |
propertyEntry readStreamDo: [ :fileStream |
methodPropertiesDict _ CypressJsonParser parseStream: fileStream ]].
(entries
detect: [ :entry | entry name = 'properties.json' ]
ifNone: [ ]) ifNotNil: [ :propertyEntry |
propertyEntry readStreamDo: [ :fileStream |
classPropertiesDict _ CypressJsonParser parseStream: fileStream ]].
classStructure _ self classStructureFrom: classPropertiesDict.
self
readMethodStructureFor: classStructure
in: entries
methodProperties: methodPropertiesDict.
^ classStructure! !
!CypressPackageReader methodsFor: 'reading' stamp: 'jmv 6/14/2012 23:54'!
readMethodStructureFor: classStructure in: entries methodProperties: methodPropertiesDict
entries do: [ :entry | | methods isMeta |
isMeta _ false.
methods _ entry name = 'class'
ifTrue: [
isMeta _ true.
classStructure classMethods ]
ifFalse: [ classStructure instanceMethods ].
(entry name = 'instance' or: [ entry name = 'class' ]) ifTrue: [
(entry asFileDirectory entries select: [ :each |
each name first ~= $. and: [ each name endsWith: '.st' ]]) do: [ :methodEntry |
methodEntry readStreamDo: [ :fileStream | | category source selector timeStamp |
category _ fileStream nextLine.
source _ fileStream upToEnd.
selector _ Parser new parseSelector: source.
timeStamp _ (methodPropertiesDict
at: (isMeta ifTrue: ['class'] ifFalse: ['instance']))
at: selector.
methods
at: selector
put:
(CypressMethodStructure new
classStructure: classStructure;
name: selector;
isMetaclass: isMeta;
selector: selector;
category: category;
source: source;
timeStamp: timeStamp
yourself) ]]]]! !
!CypressPackageReader methodsFor: 'reading' stamp: 'jmv 6/6/2012 23:06'!
readPackageStructure
packageStructure _ CypressPackageStructure new name: self packageDirectory localName.
self packageDirectory entries do: [ :entry |
entry name first ~= $. ifTrue: [
(entry name endsWith: '.class') ifTrue: [
self packageStructure classes add: (self readClassStructureFromEntry: entry) ].
(entry name endsWith: '.extension') ifTrue: [
self packageStructure extensions add: (self readExtensionClassStructureFromEntry: entry) ]]]! !
!CypressPackageReader methodsFor: 'reading' stamp: 'dkh 4/23/2012 20:20'!
readPropertiesFile
self packageDirectory
readOnlyFileNamed: 'properties.json'
do: [:fileStream |
properties := CypressJsonParser parseStream: fileStream ]! !
!CypressPackageReader class methodsFor: 'services' stamp: 'jmv 6/13/2012 09:10'!
installAsCodePackage: aCypressPackageDirectory
"
For example:
CypressPackageReader installAsCodePackage: (FileDirectory default directoryNamed: 'Cypress-Mocks.package')
"
| reader cypressStructure incomingSnapshot |
reader _ CypressPackageReader readPackageStructureFrom: aCypressPackageDirectory.
cypressStructure _ reader packageStructure.
incomingSnapshot _ cypressStructure snapshot.
incomingSnapshot updatePackage: (CypressPackageDefinition new name: cypressStructure packageName).
CodePackage named: cypressStructure packageName createIfAbsent: true registerIfNew: true! !
!CypressPackageReader class methodsFor: 'instance creation' stamp: 'dkh 4/22/2012 13:24:15'!
readPackageStructureFrom: aPackagesDirectory
^(self new)
packageDirectory: aPackagesDirectory;
read;
yourself! !
!CypressPackageStructure methodsFor: 'accessing'!
classes
classes ifNil: [ classes := OrderedCollection new ].