Kernel-Classes.st 24 KB

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