Kernel-Classes.st 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090
  1. Smalltalk createPackage: 'Kernel-Classes'!
  2. Object subclass: #Behavior
  3. instanceVariableNames: ''
  4. package: 'Kernel-Classes'!
  5. !Behavior commentStamp!
  6. I am the superclass of all class objects.
  7. In addition to BehaviorBody, I define superclass/subclass relationships and instantiation.
  8. I define the protocol for creating instances of a class with `#basicNew` and `#new` (see `boot.js` for class constructors details).
  9. My instances know about the subclass/superclass relationships between classes and contain the description that instances are created from.
  10. I also provide iterating over the class hierarchy.!
  11. !Behavior methodsFor: 'accessing'!
  12. allInstanceVariableNames
  13. | result |
  14. result := self instanceVariableNames copy.
  15. self superclass ifNotNil: [
  16. result addAll: self superclass allInstanceVariableNames ].
  17. ^ result
  18. !
  19. allSelectors
  20. ^ self allSuperclasses
  21. inject: self selectors
  22. into: [ :acc :each | acc addAll: each selectors; yourself ]
  23. !
  24. allSubclasses
  25. "Answer an collection of the receiver's and the receiver's descendent's subclasses. "
  26. ^ Array streamContents: [ :str | self allSubclassesDo: [ :each | str nextPut: each ] ]
  27. !
  28. allSuperclasses
  29. self superclass ifNil: [ ^ #() ].
  30. ^ (OrderedCollection with: self superclass)
  31. addAll: self superclass allSuperclasses;
  32. yourself
  33. !
  34. basicOrganization
  35. ^ self basicAt: 'organization'
  36. !
  37. instanceVariableNames
  38. <inlineJS: 'return self.iVarNames'>
  39. !
  40. javascriptConstructor
  41. "Answer the JS constructor used to instantiate. See boot.js"
  42. <inlineJS: 'return self.fn'>
  43. !
  44. javascriptConstructor: aJavaScriptFunction
  45. "Set the JS constructor used to instantiate.
  46. See the JS counter-part in boot.js `$core.setClassConstructor'"
  47. <inlineJS: '$core.setClassConstructor(self, aJavaScriptFunction);'>
  48. !
  49. lookupSelector: selector
  50. "Look up the given selector in my methodDictionary.
  51. Return the corresponding method if found.
  52. Otherwise chase the superclass chain and try again.
  53. Return nil if no method is found."
  54. | lookupClass |
  55. lookupClass := self.
  56. [ lookupClass = nil ] whileFalse: [
  57. (lookupClass includesSelector: selector)
  58. ifTrue: [ ^ lookupClass methodAt: selector ].
  59. lookupClass := lookupClass superclass ].
  60. ^ nil
  61. !
  62. prototype
  63. <inlineJS: 'return self.fn.prototype'>
  64. !
  65. subclasses
  66. self subclassResponsibility
  67. !
  68. superclass
  69. <inlineJS: 'return self.superclass'>
  70. !
  71. theMetaClass
  72. self subclassResponsibility
  73. !
  74. theNonMetaClass
  75. self subclassResponsibility
  76. !
  77. withAllSubclasses
  78. ^ (Array with: self) addAll: self allSubclasses; yourself
  79. ! !
  80. !Behavior methodsFor: 'enumerating'!
  81. allSubclassesDo: aBlock
  82. "Evaluate the argument, aBlock, for each of the receiver's subclasses."
  83. <inlineJS: '$core.traverseClassTree(self, function(subclass) {
  84. if (subclass !!== self) aBlock._value_(subclass);
  85. })'>
  86. ! !
  87. !Behavior methodsFor: 'instance creation'!
  88. basicNew
  89. <inlineJS: 'return new self.fn()'>
  90. !
  91. new
  92. ^ self basicNew initialize
  93. ! !
  94. !Behavior methodsFor: 'testing'!
  95. canUnderstand: aSelector
  96. ^ (self includesSelector: aSelector asString) or: [
  97. self superclass notNil and: [ self superclass canUnderstand: aSelector ]]
  98. !
  99. includesBehavior: aClass
  100. ^ self == aClass or: [
  101. self inheritsFrom: aClass ]
  102. !
  103. inheritsFrom: aClass
  104. self superclass ifNil: [ ^ false ].
  105. ^ aClass == self superclass or: [
  106. self superclass inheritsFrom: aClass ]
  107. !
  108. isBehavior
  109. ^ true
  110. ! !
  111. Behavior subclass: #Class
  112. instanceVariableNames: ''
  113. package: 'Kernel-Classes'!
  114. !Class commentStamp!
  115. I am __the__ class object.
  116. My instances are the classes of the system.
  117. Class creation is done throught a `ClassBuilder` instance.!
  118. !Class methodsFor: 'accessing'!
  119. classTag
  120. "Returns a tag or general category for this class.
  121. Typically used to help tools do some reflection.
  122. Helios, for example, uses this to decide what icon the class should display."
  123. ^ 'class'
  124. !
  125. definition
  126. ^ String streamContents: [ :stream | stream
  127. print: self superclass; write: ' subclass: '; printSymbol: self name; lf;
  128. write: (self traitCompositionDefinition ifNotEmpty: [ :tcd | { String tab. 'uses: '. tcd. String lf }]);
  129. tab; write: 'instanceVariableNames: '; print: (' ' join: self instanceVariableNames); lf;
  130. tab; write: 'package: '; print: self category ]
  131. !
  132. rename: aString
  133. ClassBuilder new renameClass: self to: aString
  134. !
  135. subclasses
  136. <inlineJS: 'return self.subclasses._copy()'>
  137. !
  138. theMetaClass
  139. ^ self class
  140. ! !
  141. !Class methodsFor: 'testing'!
  142. isClass
  143. ^ true
  144. ! !
  145. Behavior subclass: #Metaclass
  146. instanceVariableNames: ''
  147. package: 'Kernel-Classes'!
  148. !Metaclass commentStamp!
  149. I am the root of the class hierarchy.
  150. My instances are metaclasses, one for each real class, and have a single instance, which they hold onto: the class that they are the metaclass of.!
  151. !Metaclass methodsFor: 'accessing'!
  152. definition
  153. ^ String streamContents: [ :stream | stream
  154. print: self;
  155. write: (self traitCompositionDefinition
  156. ifEmpty: [' ']
  157. ifNotEmpty: [ :tcd | { String lf. String tab. 'uses: '. tcd. String lf. String tab }]);
  158. write: 'instanceVariableNames: ';
  159. print: (' ' join: self instanceVariableNames) ]
  160. !
  161. instanceClass
  162. <inlineJS: 'return self.instanceClass'>
  163. !
  164. instanceVariableNames: aCollection
  165. ClassBuilder new
  166. class: self instanceVariableNames: aCollection.
  167. ^ self
  168. !
  169. name
  170. ^ self instanceClass name, ' class'
  171. !
  172. package
  173. ^ self instanceClass package
  174. !
  175. subclasses
  176. <inlineJS: 'return $core.metaSubclasses(self)'>
  177. !
  178. theMetaClass
  179. ^ self
  180. !
  181. theNonMetaClass
  182. ^ self instanceClass
  183. !
  184. uses: aTraitCompositionDescription instanceVariableNames: aCollection
  185. | metaclass |
  186. metaclass := self instanceVariableNames: aCollection.
  187. metaclass setTraitComposition: aTraitCompositionDescription asTraitComposition.
  188. ^ metaclass
  189. ! !
  190. !Metaclass methodsFor: 'converting'!
  191. asJavaScriptSource
  192. ^ '$globals.', self instanceClass name, '.a$cls'
  193. ! !
  194. !Metaclass methodsFor: 'testing'!
  195. isMetaclass
  196. ^ true
  197. ! !
  198. Object subclass: #ClassBuilder
  199. instanceVariableNames: ''
  200. package: 'Kernel-Classes'!
  201. !ClassBuilder commentStamp!
  202. I am responsible for compiling new classes or modifying existing classes in the system.
  203. Rather than using me directly to compile a class, use `Class >> subclass:instanceVariableNames:package:`.!
  204. !ClassBuilder methodsFor: 'accessing'!
  205. instanceVariableNamesFor: aString
  206. ^ (aString tokenize: ' ') reject: [ :each | each isEmpty ]
  207. ! !
  208. !ClassBuilder methodsFor: 'class definition'!
  209. addSubclassOf: aClass named: className instanceVariableNames: aCollection package: packageName
  210. | theClass thePackage |
  211. theClass := Smalltalk globals at: className.
  212. thePackage := Package named: packageName.
  213. theClass ifNotNil: [
  214. theClass package: thePackage.
  215. theClass superclass == aClass
  216. ifFalse: [ ^ self
  217. migrateClassNamed: className
  218. superclass: aClass
  219. instanceVariableNames: aCollection
  220. package: packageName ] ].
  221. ^ (self
  222. basicAddSubclassOf: aClass
  223. named: className
  224. instanceVariableNames: aCollection
  225. package: packageName) recompile; yourself
  226. !
  227. addTraitNamed: traitName package: packageName
  228. | theTrait thePackage |
  229. theTrait := Smalltalk globals at: traitName.
  230. thePackage := Package named: packageName.
  231. theTrait ifNotNil: [ ^ theTrait package: thePackage; recompile; yourself ].
  232. ^ self
  233. basicAddTraitNamed: traitName
  234. package: packageName
  235. !
  236. class: aClass instanceVariableNames: ivarNames
  237. self basicClass: aClass instanceVariableNames: ivarNames.
  238. SystemAnnouncer current
  239. announce: (ClassDefinitionChanged new
  240. theClass: aClass;
  241. yourself)
  242. !
  243. superclass: aClass subclass: className
  244. ^ self superclass: aClass subclass: className instanceVariableNames: '' package: nil
  245. !
  246. superclass: aClass subclass: className instanceVariableNames: ivarNames package: packageName
  247. | newClass |
  248. newClass := self addSubclassOf: aClass
  249. named: className instanceVariableNames: (self instanceVariableNamesFor: ivarNames)
  250. package: (packageName ifNil: [ 'unclassified' ]).
  251. SystemAnnouncer current
  252. announce: (ClassAdded new
  253. theClass: newClass;
  254. yourself).
  255. ^ newClass
  256. ! !
  257. !ClassBuilder methodsFor: 'class migration'!
  258. migrateClass: aClass superclass: anotherClass
  259. ^ self
  260. migrateClassNamed: aClass name
  261. superclass: anotherClass
  262. instanceVariableNames: aClass instanceVariableNames
  263. package: aClass package name
  264. !
  265. migrateClassNamed: className superclass: aClass instanceVariableNames: aCollection package: packageName
  266. | oldClass newClass tmp |
  267. tmp := 'new*', className.
  268. oldClass := Smalltalk globals at: className.
  269. newClass := self
  270. addSubclassOf: aClass
  271. named: tmp
  272. instanceVariableNames: aCollection
  273. package: packageName.
  274. self basicSwapClassNames: oldClass with: newClass.
  275. [ self copyClass: oldClass to: newClass ]
  276. on: Error
  277. do: [ :exception |
  278. self
  279. basicSwapClassNames: oldClass with: newClass;
  280. basicRemoveClass: newClass.
  281. exception resignal ].
  282. self
  283. rawRenameClass: oldClass to: tmp;
  284. rawRenameClass: newClass to: className.
  285. oldClass subclasses
  286. do: [ :each | self migrateClass: each superclass: newClass ].
  287. self basicRemoveClass: oldClass.
  288. SystemAnnouncer current announce: (ClassMigrated new
  289. theClass: newClass;
  290. oldClass: oldClass;
  291. yourself).
  292. ^ newClass
  293. !
  294. renameClass: aClass to: className
  295. self basicRenameClass: aClass to: className.
  296. "Recompile the class to fix potential issues with super sends"
  297. aClass recompile.
  298. SystemAnnouncer current
  299. announce: (ClassRenamed new
  300. theClass: aClass;
  301. yourself)
  302. ! !
  303. !ClassBuilder methodsFor: 'copying'!
  304. copyClass: aClass named: className
  305. | newClass |
  306. newClass := self
  307. addSubclassOf: aClass superclass
  308. named: className
  309. instanceVariableNames: aClass instanceVariableNames
  310. package: aClass package name.
  311. self copyClass: aClass to: newClass.
  312. SystemAnnouncer current
  313. announce: (ClassAdded new
  314. theClass: newClass;
  315. yourself).
  316. ^ newClass
  317. !
  318. copyClass: aClass to: anotherClass
  319. anotherClass comment: aClass comment.
  320. aClass methodDictionary valuesDo: [ :each |
  321. each methodClass = aClass ifTrue: [
  322. Compiler new install: each source forClass: anotherClass protocol: each protocol ] ].
  323. anotherClass setTraitComposition: aClass traitComposition.
  324. self basicClass: anotherClass class instanceVariables: aClass class instanceVariableNames.
  325. aClass class methodDictionary valuesDo: [ :each |
  326. each methodClass = aClass class ifTrue: [
  327. Compiler new install: each source forClass: anotherClass class protocol: each protocol ] ].
  328. anotherClass class setTraitComposition: aClass class traitComposition
  329. ! !
  330. !ClassBuilder methodsFor: 'method definition'!
  331. installMethod: aCompiledMethod forClass: aBehavior protocol: aString
  332. aCompiledMethod protocol: aString.
  333. aBehavior addCompiledMethod: aCompiledMethod.
  334. ^ aCompiledMethod
  335. ! !
  336. !ClassBuilder methodsFor: 'private'!
  337. basicAddSubclassOf: aClass named: aString instanceVariableNames: aCollection package: packageName
  338. <inlineJS: '
  339. return $core.addClass(aString, aClass, aCollection, packageName);
  340. '>
  341. !
  342. basicAddTraitNamed: aString package: anotherString
  343. <inlineJS: 'return $core.addTrait(aString, anotherString)'>
  344. !
  345. basicClass: aClass instanceVariableNames: aString
  346. self basicClass: aClass instanceVariables: (self instanceVariableNamesFor: aString)
  347. !
  348. basicClass: aClass instanceVariables: aCollection
  349. aClass isMetaclass ifFalse: [ self error: aClass name, ' is not a metaclass' ].
  350. aClass basicAt: 'iVarNames' put: aCollection
  351. !
  352. basicRemoveClass: aClass
  353. <inlineJS: '$core.removeClass(aClass)'>
  354. !
  355. basicRenameClass: aClass to: aString
  356. <inlineJS: '
  357. $globals[aString] = aClass;
  358. delete $globals[aClass.className];
  359. aClass.className = aString;
  360. '>
  361. !
  362. basicSwapClassNames: aClass with: anotherClass
  363. <inlineJS: '
  364. var tmp = aClass.className;
  365. aClass.className = anotherClass.className;
  366. anotherClass.className = tmp;
  367. '>
  368. !
  369. rawRenameClass: aClass to: aString
  370. <inlineJS: '
  371. $globals[aString] = aClass;
  372. '>
  373. ! !
  374. !ClassBuilder methodsFor: 'public'!
  375. setupClass: aClass
  376. self deprecatedAPI: 'Classes are now auto-inited.'
  377. ! !
  378. Object subclass: #ClassSorterNode
  379. instanceVariableNames: 'theClass level nodes'
  380. package: 'Kernel-Classes'!
  381. !ClassSorterNode commentStamp!
  382. I provide an algorithm for sorting classes alphabetically.
  383. See [Issue #143](https://lolg.it/amber/amber/issues/143).!
  384. !ClassSorterNode methodsFor: 'accessing'!
  385. getNodesFrom: aCollection
  386. | children others |
  387. children := #().
  388. others := #().
  389. aCollection do: [ :each |
  390. (each superclass = self theClass)
  391. ifTrue: [ children add: each ]
  392. ifFalse: [ others add: each ]].
  393. nodes:= children collect: [ :each |
  394. ClassSorterNode on: each classes: others level: self level + 1 ]
  395. !
  396. level
  397. ^ level
  398. !
  399. level: anInteger
  400. level := anInteger
  401. !
  402. nodes
  403. ^ nodes
  404. !
  405. theClass
  406. ^ theClass
  407. !
  408. theClass: aClass
  409. theClass := aClass
  410. ! !
  411. !ClassSorterNode methodsFor: 'visiting'!
  412. traverseClassesWith: aCollection
  413. "sort classes alphabetically Issue #143"
  414. aCollection add: self theClass.
  415. (self nodes sorted: [ :a :b | a theClass name <= b theClass name ]) do: [ :aNode |
  416. aNode traverseClassesWith: aCollection ].
  417. ! !
  418. !ClassSorterNode class methodsFor: 'instance creation'!
  419. on: aClass classes: aCollection level: anInteger
  420. ^ self new
  421. theClass: aClass;
  422. level: anInteger;
  423. getNodesFrom: aCollection;
  424. yourself
  425. ! !
  426. Trait named: #TBehaviorDefaults
  427. package: 'Kernel-Classes'!
  428. !TBehaviorDefaults methodsFor: 'accessing'!
  429. allInstanceVariableNames
  430. "Default for non-classes; to be able to send #allInstanceVariableNames to any class / trait."
  431. ^ #()
  432. !
  433. name
  434. ^ nil
  435. !
  436. superclass
  437. "Default for non-classes; to be able to send #superclass to any class / trait."
  438. ^ nil
  439. !
  440. traitUsers
  441. "Default for non-traits; to be able to send #traitUsers to any class / trait"
  442. ^ #()
  443. ! !
  444. !TBehaviorDefaults methodsFor: 'enumerating'!
  445. allSubclassesDo: aBlock
  446. "Default for non-classes; to be able to send #allSubclassesDo: to any class / trait."
  447. ! !
  448. !TBehaviorDefaults methodsFor: 'printing'!
  449. printOn: aStream
  450. self name
  451. ifNil: [ super printOn: aStream ]
  452. ifNotNil: [ :name | aStream nextPutAll: name ]
  453. ! !
  454. Trait named: #TBehaviorProvider
  455. package: 'Kernel-Classes'!
  456. !TBehaviorProvider commentStamp!
  457. I have method dictionary and organization.!
  458. !TBehaviorProvider methodsFor: 'accessing'!
  459. >> aString
  460. ^ self methodAt: aString
  461. !
  462. methodAt: aString
  463. ^ self methodDictionary at: aString
  464. !
  465. methodDictionary
  466. <inlineJS: 'var dict = $globals.HashedCollection._new();
  467. var methods = self.methods;
  468. Object.keys(methods).forEach(function(i) {
  469. if(methods[i].selector) {
  470. dict._at_put_(methods[i].selector, methods[i]);
  471. }
  472. });
  473. return dict'>
  474. !
  475. methodTemplate
  476. ^ String streamContents: [ :stream | stream
  477. write: 'messageSelectorAndArgumentNames'; lf;
  478. tab; write: '"comment stating purpose of message"'; lf;
  479. lf;
  480. tab; write: '| temporary variable names |'; lf;
  481. tab; write: 'statements' ]
  482. !
  483. methods
  484. ^ self methodDictionary values
  485. !
  486. methodsInProtocol: aString
  487. ^ self methods select: [ :each | each protocol = aString ]
  488. !
  489. organization
  490. ^ self basicOrganization
  491. !
  492. ownMethods
  493. "Answer the methods of the receiver that are not package extensions
  494. nor obtained via trait composition"
  495. ^ (self ownProtocols
  496. inject: OrderedCollection new
  497. into: [ :acc :each | acc, (self ownMethodsInProtocol: each) ])
  498. sorted: [ :a :b | a selector <= b selector ]
  499. !
  500. ownMethodsInProtocol: aString
  501. ^ (self methodsInProtocol: aString) select: [ :each | each methodClass = self ]
  502. !
  503. ownProtocols
  504. "Answer the protocols of the receiver that are not package extensions"
  505. ^ self protocols reject: [ :each |
  506. each match: '^\*' ]
  507. !
  508. packageOfProtocol: aString
  509. "Answer the package the method of receiver belongs to:
  510. - if it is an extension method, answer the corresponding package
  511. - else answer the receiver's package"
  512. (aString beginsWith: '*') ifFalse: [
  513. ^ self package ].
  514. ^ Package
  515. named: aString allButFirst
  516. ifAbsent: [ nil ]
  517. !
  518. protocols
  519. ^ self organization elements sorted
  520. !
  521. removeProtocolIfEmpty: aString
  522. self methods
  523. detect: [ :each | each protocol = aString ]
  524. ifNone: [ self organization removeElement: aString ]
  525. !
  526. selectors
  527. ^ self methodDictionary keys
  528. !
  529. traitComposition
  530. ^ (self basicAt: 'traitComposition')
  531. ifNil: [ #() ]
  532. ifNotNil: [ :aCollection | aCollection collect: [ :each | TraitTransformation fromJSON: each ] ]
  533. !
  534. traitCompositionDefinition
  535. ^ self traitComposition ifNotEmpty: [ :traitComposition |
  536. String streamContents: [ :str |
  537. str write: '{'.
  538. traitComposition
  539. do: [ :each | str write: each definition ]
  540. separatedBy: [ str write: '. ' ].
  541. str write: '}' ] ]
  542. ! !
  543. !TBehaviorProvider methodsFor: 'compiling'!
  544. addCompiledMethod: aMethod
  545. | oldMethod announcement |
  546. oldMethod := self methodDictionary
  547. at: aMethod selector
  548. ifAbsent: [ nil ].
  549. (self protocols includes: aMethod protocol)
  550. ifFalse: [ self organization addElement: aMethod protocol ].
  551. self basicAddCompiledMethod: aMethod.
  552. oldMethod ifNotNil: [
  553. self removeProtocolIfEmpty: oldMethod protocol ].
  554. announcement := oldMethod
  555. ifNil: [
  556. MethodAdded new
  557. method: aMethod;
  558. yourself ]
  559. ifNotNil: [
  560. MethodModified new
  561. oldMethod: oldMethod;
  562. method: aMethod;
  563. yourself ].
  564. SystemAnnouncer current
  565. announce: announcement
  566. !
  567. compile: aString protocol: anotherString
  568. ^ Compiler new
  569. install: aString
  570. forClass: self
  571. protocol: anotherString
  572. !
  573. recompile
  574. ^ Compiler new recompile: self
  575. !
  576. removeCompiledMethod: aMethod
  577. self basicRemoveCompiledMethod: aMethod.
  578. self removeProtocolIfEmpty: aMethod protocol.
  579. SystemAnnouncer current
  580. announce: (MethodRemoved new
  581. method: aMethod;
  582. yourself)
  583. !
  584. setTraitComposition: aTraitComposition
  585. <inlineJS: '$core.setTraitComposition(aTraitComposition._asJavaScriptObject(), self)'>
  586. ! !
  587. !TBehaviorProvider methodsFor: 'enumerating'!
  588. protocolsDo: aBlock
  589. "Execute aBlock for each method protocol with
  590. its collection of methods in the sort order of protocol name."
  591. | methodsByProtocol |
  592. methodsByProtocol := HashedCollection new.
  593. self methodDictionary valuesDo: [ :m |
  594. (methodsByProtocol at: m protocol ifAbsentPut: [ Array new ])
  595. add: m ].
  596. self protocols do: [ :protocol |
  597. aBlock value: protocol value: (methodsByProtocol at: protocol) ]
  598. ! !
  599. !TBehaviorProvider methodsFor: 'private'!
  600. basicAddCompiledMethod: aMethod
  601. <inlineJS: '$core.addMethod(aMethod, self)'>
  602. !
  603. basicRemoveCompiledMethod: aMethod
  604. <inlineJS: '$core.removeMethod(aMethod,self)'>
  605. ! !
  606. !TBehaviorProvider methodsFor: 'testing'!
  607. includesSelector: aString
  608. ^ self methodDictionary includesKey: aString
  609. ! !
  610. Trait named: #TMasterBehavior
  611. package: 'Kernel-Classes'!
  612. !TMasterBehavior commentStamp!
  613. I am the behavior on the instance-side of the browser.
  614. I define things like package, category, name, comment etc.
  615. as opposed to derived behaviors (metaclass, class trait, ...)
  616. that relate to me.!
  617. !TMasterBehavior methodsFor: 'accessing'!
  618. category
  619. ^ self package ifNil: [ 'Unclassified' ] ifNotNil: [ self package name ]
  620. !
  621. classTag
  622. "Every master behavior should define a class tag."
  623. ^ self subclassResponsibility
  624. !
  625. comment
  626. ^ (self basicAt: 'comment') ifNil: [ '' ]
  627. !
  628. comment: aString
  629. self basicAt: 'comment' put: aString.
  630. SystemAnnouncer current
  631. announce: (ClassCommentChanged new
  632. theClass: self;
  633. yourself)
  634. !
  635. enterOrganization
  636. Smalltalk ifNotNil: [
  637. self package isString ifTrue: [ self basicAt: 'pkg' put: (Package named: self package) ].
  638. self package organization addElement: self ]
  639. !
  640. leaveOrganization
  641. Smalltalk ifNotNil: [
  642. self package organization removeElement: self ]
  643. !
  644. name
  645. <inlineJS: 'return self.className'>
  646. !
  647. package
  648. ^ self basicAt: 'pkg'
  649. !
  650. package: aPackage
  651. | oldPackage |
  652. self package = aPackage ifTrue: [ ^ self ].
  653. oldPackage := self package.
  654. self
  655. leaveOrganization;
  656. basicAt: 'pkg' put: aPackage;
  657. enterOrganization.
  658. SystemAnnouncer current announce: (ClassMoved new
  659. theClass: self;
  660. oldPackage: oldPackage;
  661. yourself)
  662. !
  663. theNonMetaClass
  664. ^ self
  665. ! !
  666. !TMasterBehavior methodsFor: 'browsing'!
  667. browse
  668. Finder findClass: self
  669. ! !
  670. !TMasterBehavior methodsFor: 'converting'!
  671. asJavaScriptSource
  672. ^ '$globals.', self name
  673. ! !
  674. Object subclass: #Trait
  675. instanceVariableNames: ''
  676. package: 'Kernel-Classes'!
  677. !Trait methodsFor: 'accessing'!
  678. basicOrganization
  679. ^ self basicAt: 'organization'
  680. !
  681. classTag
  682. ^ 'trait'
  683. !
  684. definition
  685. ^ String streamContents: [ :stream | stream
  686. write: 'Trait named: '; printSymbol: self name; lf;
  687. write: (self traitCompositionDefinition ifNotEmpty: [ :tcd | { String tab. 'uses: '. tcd. String lf }]);
  688. tab; write: 'package: '; print: self category ]
  689. !
  690. theMetaClass
  691. ^ nil
  692. !
  693. traitUsers
  694. ^ (self basicAt: 'traitUsers') copy
  695. ! !
  696. !Trait methodsFor: 'composition'!
  697. - anArray
  698. ^ self asTraitTransformation - anArray
  699. !
  700. @ anArrayOfAssociations
  701. ^ self asTraitTransformation @ anArrayOfAssociations
  702. ! !
  703. !Trait methodsFor: 'converting'!
  704. asTraitComposition
  705. ^ self asTraitTransformation asTraitComposition
  706. !
  707. asTraitTransformation
  708. ^ TraitTransformation on: self
  709. ! !
  710. !Trait class methodsFor: 'instance creation'!
  711. named: aString package: anotherString
  712. ^ ClassBuilder new addTraitNamed: aString package: anotherString
  713. !
  714. named: aString uses: aTraitCompositionDescription package: anotherString
  715. | trait |
  716. trait := self named: aString package: anotherString.
  717. trait setTraitComposition: aTraitCompositionDescription asTraitComposition.
  718. ^ trait
  719. ! !
  720. Object subclass: #TraitTransformation
  721. instanceVariableNames: 'trait aliases exclusions'
  722. package: 'Kernel-Classes'!
  723. !TraitTransformation commentStamp!
  724. I am a single step in trait composition.
  725. I represent one trait including its aliases and exclusions.!
  726. !TraitTransformation methodsFor: 'accessing'!
  727. addAliases: anArrayOfAssociations
  728. anArrayOfAssociations do: [ :each |
  729. | key |
  730. key := each key.
  731. aliases at: key
  732. ifPresent: [ self error: 'Cannot use same alias name twice.' ]
  733. ifAbsent: [ aliases at: key put: each value ] ].
  734. ^ anArrayOfAssociations
  735. !
  736. addExclusions: anArray
  737. exclusions addAll: anArray.
  738. ^ anArray
  739. !
  740. aliases
  741. ^ aliases
  742. !
  743. definition
  744. ^ String streamContents: [ :str |
  745. str print: self trait.
  746. self aliases ifNotEmpty: [ :al |
  747. str write: ' @ {'.
  748. al associations
  749. do: [ :each | str printSymbol: each key; write: ' -> '; printSymbol: each value ]
  750. separatedBy: [ str write: '. ' ].
  751. str write: '}' ].
  752. self exclusions ifNotEmpty: [ :ex |
  753. str write: ' - #('.
  754. ex asArray sorted
  755. do: [ :each | str write: each symbolPrintString allButFirst ]
  756. separatedBy: [ str space ].
  757. str write: ')' ] ]
  758. !
  759. exclusions
  760. ^ exclusions
  761. !
  762. trait
  763. ^ trait
  764. !
  765. trait: anObject
  766. trait := anObject
  767. ! !
  768. !TraitTransformation methodsFor: 'composition'!
  769. - anArray
  770. ^ self copy addExclusions: anArray; yourself
  771. !
  772. @ anArrayOfAssociations
  773. ^ self copy addAliases: anArrayOfAssociations; yourself
  774. ! !
  775. !TraitTransformation methodsFor: 'converting'!
  776. asJavaScriptObject
  777. ^ #{
  778. 'trait' -> self trait.
  779. 'aliases' -> self aliases.
  780. 'exclusions' -> self exclusions asArray sorted }
  781. !
  782. asJavaScriptSource
  783. ^ String streamContents: [ :str | str write: {
  784. '{trait: '. self trait asJavaScriptSource.
  785. self aliases ifNotEmpty: [ :al |
  786. {', aliases: '. al asJSONString} ].
  787. self exclusions ifNotEmpty: [ :ex |
  788. {', exclusions: '. ex asArray sorted asJavaScriptSource} ].
  789. '}' } ]
  790. !
  791. asTraitComposition
  792. ^ { self }
  793. !
  794. asTraitTransformation
  795. ^ self
  796. ! !
  797. !TraitTransformation methodsFor: 'copying'!
  798. postCopy
  799. aliases := aliases copy.
  800. exclusions := exclusions copy
  801. ! !
  802. !TraitTransformation methodsFor: 'initialization'!
  803. initialize
  804. super initialize.
  805. aliases := #{}.
  806. exclusions := Set new.
  807. trait := nil
  808. ! !
  809. !TraitTransformation class methodsFor: 'instance creation'!
  810. fromJSON: aJSObject
  811. ^ super new
  812. trait: (aJSObject at: #trait);
  813. addAliases: (Smalltalk readJSObject: (aJSObject at: #aliases ifAbsent: [#{}])) associations;
  814. addExclusions: (aJSObject at: #exclusions ifAbsent: [#()]);
  815. yourself
  816. !
  817. on: aTrait
  818. ^ super new trait: aTrait; yourself
  819. ! !
  820. Behavior setTraitComposition: {TBehaviorDefaults. TBehaviorProvider} asTraitComposition!
  821. Class setTraitComposition: {TMasterBehavior. TSubclassable} asTraitComposition!
  822. Trait setTraitComposition: {TBehaviorDefaults. TBehaviorProvider. TMasterBehavior} asTraitComposition!
  823. ! !
  824. !Array methodsFor: '*Kernel-Classes'!
  825. asTraitComposition
  826. "not implemented yet, noop atm"
  827. ^ self collect: [ :each | each asTraitTransformation ]
  828. ! !