diff --git a/src/BaselineOfMolecule/BaselineOfMolecule.class.st b/src/BaselineOfMolecule/BaselineOfMolecule.class.st index 537ff170..92982409 100644 --- a/src/BaselineOfMolecule/BaselineOfMolecule.class.st +++ b/src/BaselineOfMolecule/BaselineOfMolecule.class.st @@ -2,7 +2,7 @@ Class { #name : #BaselineOfMolecule, #superclass : #BaselineOf, #instVars : [ - 'previousDynamicContractUpdateActivated' + 'isPreviouslyAutoComponentTypeUpdateActivated' ], #category : #BaselineOfMolecule } @@ -31,12 +31,17 @@ BaselineOfMolecule >> baseline: spec [ BaselineOfMolecule >> postload: loader package: packageSpec [ "Reload new Molecule tools" - (Smalltalk globals includesKey: #MolComponentManager) ifFalse:[ ^self ]. - (Smalltalk globals classNamed: #MolComponentManager) cleanUp. - "Rebuild all components" + | componentManagerClass | + componentManagerClass := RGClassDefinition named: #MolComponentManager. + componentManagerClass isDefined ifFalse:[ ^ self ]. + componentManagerClass realClass cleanUp. + + "Define all components after loading" MolComponentFactory defineAllComponents. - "Reactive dynamic contract update if necessary" - (previousDynamicContractUpdateActivated ifNil:[false]) ifFalse:[ + MolSystemObserver active. + + "Active auto ComponentType update if necessary" + (isPreviouslyAutoComponentTypeUpdateActivated ifNil:[ false ]) ifFalse:[ MolComponentFactory default activateDynamicContractUpdate. ]. ] @@ -45,9 +50,12 @@ BaselineOfMolecule >> postload: loader package: packageSpec [ BaselineOfMolecule >> preload: loader package: packageSpec [ "If a Molecule component system is running, confirm loading and cleanUp before installation of the new version" - (Smalltalk globals includesKey: #MolComponentManager) ifFalse:[ ^self ]. - previousDynamicContractUpdateActivated := false. - (Smalltalk globals classNamed: #MolComponentManager) isRunningComponents ifTrue:[ + | componentManagerClass | + componentManagerClass := RGClassDefinition named: #MolComponentManager. + componentManagerClass isDefined ifFalse:[ ^ self ]. + + isPreviouslyAutoComponentTypeUpdateActivated := false. + componentManagerClass realClass isRunningComponents ifTrue:[ (Smalltalk ui theme proceedIn: Morph new text: 'Warning, you are going to modify Molecule then components are started, do you want to continue ?' @@ -57,7 +65,8 @@ BaselineOfMolecule >> preload: loader package: packageSpec [ ]. ]. - (Smalltalk globals classNamed: #MolComponentManager) cleanUp. - previousDynamicContractUpdateActivated := MolComponentFactory default isDynamicContractUpdateActivated. + componentManagerClass realClass cleanUp. + isPreviouslyAutoComponentTypeUpdateActivated := MolComponentFactory default isDynamicContractUpdateActivated. MolComponentFactory default deactivateDynamicContractUpdate. + MolSystemObserver deactive. ] diff --git a/src/Molecule-IDE/MolWorld.class.st b/src/Molecule-IDE/MolWorld.class.st index 18cb0912..2ba99745 100644 --- a/src/Molecule-IDE/MolWorld.class.st +++ b/src/Molecule-IDE/MolWorld.class.st @@ -7,6 +7,17 @@ Class { #category : #'Molecule-IDE-Menus' } +{ #category : #accessing } +MolWorld class >> componentFactoryClass [ + + | class | + class := RGClassDefinition named: #MolComponentFactory. + + class isDefined + ifTrue: [ ^ class realClass ] + ifFalse: [ ^ nil ] +] + { #category : #scripts } MolWorld class >> defineAComponent [ @@ -171,6 +182,17 @@ MolWorld class >> menu60ReportBugOn: aBuilder [ action: [WebBrowser openOn: 'https://github.com/OpenSmock/Molecule/issues/new'] ] +{ #category : #accessing } +MolWorld class >> molUtilsClass [ + + | class | + class := RGClassDefinition named: #MolUtils. + + class isDefined + ifTrue: [ ^ class realClass ] + ifFalse: [ ^ nil ] +] + { #category : #scripts } MolWorld class >> openDefineComponentDialog [ @@ -234,7 +256,10 @@ This action may be necessary if your system is broken.' { #category : #'menu - tools' } MolWorld class >> toolsMenu20ToggleLogsOn: aBuilder [ - MolUtils isLogActive + + | utilsClass | + utilsClass := self molUtilsClass ifNil:[ ^ self ]. + utilsClass isLogActive ifFalse: [ (aBuilder item: #TurnOffMolLogs) parent: #MoleculeDebug; @@ -256,7 +281,10 @@ MolWorld class >> toolsMenu20ToggleLogsOn: aBuilder [ { #category : #'menu - tools' } MolWorld class >> toolsMenu30ToggleDynamicContractUpdate: aBuilder [ - MolComponentFactory default isDynamicContractUpdateActivated + + | factoryClass | + factoryClass := self componentFactoryClass ifNil:[ ^ self ]. + factoryClass default isDynamicContractUpdateActivated ifFalse: [ (aBuilder item: #TurnOffMolLogs) parent: #MoleculeDebug; diff --git a/src/Molecule-Tests/MolComponentFactoryTest.class.st b/src/Molecule-Tests/MolComponentFactoryTest.class.st index 49da2911..71f207f4 100644 --- a/src/Molecule-Tests/MolComponentFactoryTest.class.st +++ b/src/Molecule-Tests/MolComponentFactoryTest.class.st @@ -798,17 +798,19 @@ MolComponentFactoryTest >> testDefineComponentTypeImplementors [ { #category : #tests } MolComponentFactoryTest >> testDefineDirtyComponents [ - self assert: MolComponentFactory default dirtyComponentTypes isEmpty. + + self assert: MolComponentFactory dirtyComponentTypeList isEmpty. "Add a dirty component type manually" - MolComponentFactory default dirtyComponentTypes add: MolMyClientComponent. - MolComponentFactory default dirtyComponents add: MolMyClientComponentImpl. - self assert: MolComponentFactory default dirtyComponentTypes notEmpty. - self assert: MolComponentFactory default dirtyComponents notEmpty. - + MolComponentFactory dirtyComponentTypeList add: MolMyClientComponent. + MolComponentFactory dirtyComponentImplList add: + MolMyClientComponentImpl. + self assert: MolComponentFactory dirtyComponentTypeList notEmpty. + self assert: MolComponentFactory dirtyComponentImplList notEmpty. + MolComponentFactory defineDirtyComponents. - self assert: MolComponentFactory default dirtyComponentTypes isEmpty. - self assert: MolComponentFactory default dirtyComponents isEmpty. + self assert: MolComponentFactory dirtyComponentTypeList isEmpty. + self assert: MolComponentFactory dirtyComponentImplList isEmpty ] { #category : #tests } diff --git a/src/Molecule/MCPackageLoader.extension.st b/src/Molecule/MCPackageLoader.extension.st new file mode 100644 index 00000000..b94bb10e --- /dev/null +++ b/src/Molecule/MCPackageLoader.extension.st @@ -0,0 +1,40 @@ +Extension { #name : #MCPackageLoader } + +{ #category : #'*Molecule' } +MCPackageLoader >> announceLoad: aString do: aBlock [ + | returnValue | + returnValue := nil. + [ self announceLoadStart: aString ] ensure: [ + [ returnValue := aBlock value ] ensure: [ + self announceLoadStop: aString ] ]. + ^ returnValue +] + +{ #category : #'*Molecule' } +MCPackageLoader >> announceLoadStart: aString [ + SystemAnnouncer uniqueInstance announce: (MCPackageLoaderStarted new + packageLoader: self; + label: aString; + yourself) +] + +{ #category : #'*Molecule' } +MCPackageLoader >> announceLoadStop: aString [ + SystemAnnouncer uniqueInstance announce: (MCPackageLoaderStarted new + packageLoader: self; + label: aString; + yourself) +] + +{ #category : #'*Molecule' } +MCPackageLoader >> basicLoadWithNameLike: baseName [ + + self validate. + self useNewChangeSetNamedLike: baseName during: [self basicLoad]. +] + +{ #category : #'*Molecule' } +MCPackageLoader >> loadWithNameLike: aString [ + + ^ self announceLoad: aString do: [ self basicLoadWithNameLike: aString ] +] diff --git a/src/Molecule/MCPackageLoaderStarted.class.st b/src/Molecule/MCPackageLoaderStarted.class.st new file mode 100644 index 00000000..fb31c67f --- /dev/null +++ b/src/Molecule/MCPackageLoaderStarted.class.st @@ -0,0 +1,33 @@ +Class { + #name : #MCPackageLoaderStarted, + #superclass : #Announcement, + #instVars : [ + 'packageLoader', + 'label' + ], + #category : #'Molecule-Announcers' +} + +{ #category : #accessing } +MCPackageLoaderStarted >> label [ + + ^ label +] + +{ #category : #accessing } +MCPackageLoaderStarted >> label: anObject [ + + label := anObject +] + +{ #category : #accessing } +MCPackageLoaderStarted >> packageLoader [ + + ^ packageLoader +] + +{ #category : #accessing } +MCPackageLoaderStarted >> packageLoader: anObject [ + + packageLoader := anObject +] diff --git a/src/Molecule/MCPackageLoaderStopped.class.st b/src/Molecule/MCPackageLoaderStopped.class.st new file mode 100644 index 00000000..285d11a4 --- /dev/null +++ b/src/Molecule/MCPackageLoaderStopped.class.st @@ -0,0 +1,31 @@ +Class { + #name : #MCPackageLoaderStopped, + #superclass : #Announcement, + #instVars : [ + 'packageLoader', + 'label' + ], + #category : #'Molecule-Announcers' +} + +{ #category : #accessing } +MCPackageLoaderStopped >> label [ + ^ label +] + +{ #category : #accessing } +MCPackageLoaderStopped >> label: anObject [ + label := anObject +] + +{ #category : #accessing } +MCPackageLoaderStopped >> packageLoader [ + + ^ packageLoader +] + +{ #category : #accessing } +MCPackageLoaderStopped >> packageLoader: anObject [ + + packageLoader := anObject +] diff --git a/src/Molecule/MolComponentFactory.class.st b/src/Molecule/MolComponentFactory.class.st index eeda758a..b4d3e35e 100644 --- a/src/Molecule/MolComponentFactory.class.st +++ b/src/Molecule/MolComponentFactory.class.st @@ -17,6 +17,11 @@ Class { #classVars : [ 'Default' ], + #classInstVars : [ + 'isAutoComponentTypeUpdateActivated', + 'dirtyComponentTypeList', + 'dirtyComponentImplList' + ], #category : #'Molecule-Tools' } @@ -140,10 +145,14 @@ MolComponentFactory class >> addUsedServices: aComponentServices in: aComponentT self compileContractSelector: 'usedComponentServices' protocol: self protocolForComponentServices interfaces: declaredUsedComponentServices type: aComponentType ] -{ #category : #accessing } +{ #category : #cleanup } MolComponentFactory class >> cleanUp [ + isAutoComponentTypeUpdateActivated := nil. + dirtyComponentTypeList := nil. + dirtyComponentImplList := nil. + Default ifNil: [ ^ self ]. Default release. Default := nil @@ -179,7 +188,7 @@ MolComponentFactory class >> compileContractSelector: aSelector protocol: aProto { #category : #pragma } MolComponentFactory class >> componentContractPragmaSymbol [ - ^#componentContract + ^ #componentContract ] { #category : #'component - creation' } @@ -344,12 +353,48 @@ MolComponentFactory class >> defineDirtyComponents [ self default defineDirtyComponents ] +{ #category : #accessing } +MolComponentFactory class >> dirtyComponentImplList [ + + ^ dirtyComponentImplList ifNil:[ dirtyComponentImplList := Set new ] +] + +{ #category : #accessing } +MolComponentFactory class >> dirtyComponentImplList: anObject [ + + dirtyComponentImplList := anObject +] + +{ #category : #accessing } +MolComponentFactory class >> dirtyComponentTypeList [ + + ^ dirtyComponentTypeList ifNil:[ dirtyComponentTypeList := Set new ] +] + +{ #category : #accessing } +MolComponentFactory class >> dirtyComponentTypeList: anObject [ + + dirtyComponentTypeList := anObject +] + { #category : #'class initialization' } MolComponentFactory class >> initialize [ self default ] +{ #category : #accessing } +MolComponentFactory class >> isAutoComponentTypeUpdateActivated [ + + ^ isAutoComponentTypeUpdateActivated ifNil:[ isAutoComponentTypeUpdateActivated := true ] +] + +{ #category : #accessing } +MolComponentFactory class >> isAutoComponentTypeUpdateActivated: anObject [ + + isAutoComponentTypeUpdateActivated := anObject +] + { #category : #'class initialization' } MolComponentFactory class >> isInitialized [ "Test if the Component Factory is initialized" @@ -447,7 +492,7 @@ MolComponentFactory >> componentChanged: aChangedClass [ self isDynamicContractUpdateActivated ifTrue: [ aChangedClass isObsolete ifFalse:[self defineComponent: aChangedClass] ] ifFalse: [ - dirtyComponents add: aChangedClass + self dirtyComponents add: aChangedClass ]. ] @@ -474,7 +519,7 @@ MolComponentFactory >> contractChanged: aComponentType [ self isDynamicContractUpdateActivated ifTrue: [ self defineComponentTypeImplementors: aComponentType ] ifFalse: [ - dirtyComponentTypes add: aComponentType + self dirtyComponentTypes add: aComponentType ] ] @@ -554,24 +599,65 @@ MolComponentFactory >> defineComponentTypeImplementors: aComponentType [ { #category : #'dirty components' } MolComponentFactory >> defineDirtyComponents [ "Get all dirty Types and Components for defining them" - - dirtyComponentTypes do: [ :e | self defineComponentTypeImplementors: e ]. - dirtyComponentTypes := Set new. - - dirtyComponents do: [ :e | self defineComponent: e ]. - dirtyComponents := Set new. + + MolComponentFactory dirtyComponentTypeList do: [ :e | + self defineComponentTypeImplementors: e ]. + MolComponentFactory dirtyComponentTypeList: Set new. + MolComponentFactory dirtyComponentImplList do: [ :e | + self defineComponent: e ]. + MolComponentFactory dirtyComponentImplList: Set new ] { #category : #'dirty components' } MolComponentFactory >> dirtyComponentTypes [ - ^dirtyComponentTypes + self + deprecated:'Use self class dirtyComponentTypeList' + transformWith: ' + `@receiver dirtyComponentTypes' + -> + 'MolComponentFactory dirtyComponentTypeList'. + + ^ self class dirtyComponentTypeList +] + +{ #category : #'dirty components' } +MolComponentFactory >> dirtyComponentTypes: aSet [ + + self + deprecated:'Use self class dirtyComponentTypeList:' + transformWith: ' + `@receiver dirtyComponentTypes: `@argument' + -> + 'MolComponentFactory dirtyComponentTypeList: `@argument'. + + self class dirtyComponentTypeList: aSet ] { #category : #'dirty components' } MolComponentFactory >> dirtyComponents [ - ^dirtyComponents + self + deprecated:'Use self class dirtyComponentImplList' + transformWith: ' + `@receiver dirtyComponents' + -> + 'MolComponentFactory dirtyComponentImplList'. + + ^ self class dirtyComponentImplList +] + +{ #category : #'dirty components' } +MolComponentFactory >> dirtyComponents: aSet [ + + self + deprecated:'Use self class dirtyComponentImplList:' + transformWith: ' + `@receiver dirtyComponents: `@argument' + -> + 'MolComponentFactory dirtyComponentImplList: `@argument'. + + self class dirtyComponentImplList: aSet ] { #category : #'private - code generation' } @@ -786,16 +872,17 @@ MolComponentFactory >> initialize [ super initialize. - dirtyComponentTypes := Set new. - dirtyComponents := Set new. - self initializePragmaAnnouncements. - self initializeSystemAnnouncements + "dirtyComponentTypes := Set new. + dirtyComponents := Set new." + "self initializePragmaAnnouncements. + self initializeSystemAnnouncements" ] { #category : #'initialize - release' } MolComponentFactory >> initializePragmaAnnouncements [ "Component Type Observer" + self deprecated:'not used'. pragmaCollector := (PragmaCollector new filter: [ :prg | prg selector = self class componentContractPragmaSymbol ]) reset. pragmaCollector announcer @@ -808,6 +895,8 @@ MolComponentFactory >> initializePragmaAnnouncements [ MolComponentFactory >> initializeSystemAnnouncements [ "Activate (or desactivate) component contract update when iceberge is used (or not)" | announcer | + + self deprecated:'not used'. announcer := SystemAnnouncer uniqueInstance weak. announcer ifNil: [ MolUtils log: 'Error on Systems announcements initialization, system Announcer is nil'. @@ -827,14 +916,27 @@ MolComponentFactory >> initializeSystemAnnouncements [ { #category : #accessing } MolComponentFactory >> isDynamicContractUpdateActivated [ - isDynamicContractUpdateActivated ifNil: [ isDynamicContractUpdateActivated := true ]. - ^ isDynamicContractUpdateActivated + self + deprecated:'Use self class isAutoComponentTypeUpdateActivated' + transformWith: ' + `@receiver isDynamicContractUpdateActivated' + -> + 'MolComponentFactory isAutoComponentTypeUpdateActivated'. + + ^ self class isAutoComponentTypeUpdateActivated ] { #category : #accessing } MolComponentFactory >> isDynamicContractUpdateActivated: aBoolean [ - isDynamicContractUpdateActivated := aBoolean + self + deprecated:'Use self class isAutoComponentTypeUpdateActivated' + transformWith: ' + `@receiver isDynamicContractUpdateActivated: `@argument' + -> + 'MolComponentFactory isAutoComponentTypeUpdateActivated: `@argument'. + + self class isAutoComponentTypeUpdateActivated: aBoolean ] { #category : #'private - code generation' } @@ -862,11 +964,11 @@ MolComponentFactory >> rebuildComponent: aComponentClass traitsAdding: aTraitsLi { #category : #'initialize - release' } MolComponentFactory >> release [ - self releaseSystemAnnouncements. - self releasePragmaAnnouncements. - isDynamicContractUpdateActivated := false. - dirtyComponentTypes := nil. - dirtyComponents := nil. + "self releaseSystemAnnouncements. + self releasePragmaAnnouncements." + "isDynamicContractUpdateActivated := false." + "dirtyComponentTypes := nil. + dirtyComponents := nil." super release ] @@ -874,6 +976,7 @@ MolComponentFactory >> release [ { #category : #'initialize - release' } MolComponentFactory >> releasePragmaAnnouncements [ + self deprecated:'not used'. pragmaCollector release. pragmaCollector := nil ] @@ -882,6 +985,7 @@ MolComponentFactory >> releasePragmaAnnouncements [ MolComponentFactory >> releaseSystemAnnouncements [ | announcer | + self deprecated:'not used'. announcer := SystemAnnouncer uniqueInstance. announcer ifNil: [ ^ self ]. announcer unsubscribe: self diff --git a/src/Molecule/MolSystemObserver.class.st b/src/Molecule/MolSystemObserver.class.st new file mode 100644 index 00000000..30d7259f --- /dev/null +++ b/src/Molecule/MolSystemObserver.class.st @@ -0,0 +1,209 @@ +" +This classe observe Pharo evolution (source code modifications, iceberg, etc.) and control all components contract generation. +" +Class { + #name : #MolSystemObserver, + #superclass : #Object, + #classInstVars : [ + 'pragmaCollector', + 'isActive' + ], + #category : #'Molecule-Core' +} + +{ #category : #'class initialization' } +MolSystemObserver class >> active [ +