diff --git a/src/Molecule-IDE/MolCreateNewComponentCommand.class.st b/src/Molecule-IDE/MolCreateNewComponentCommand.class.st new file mode 100644 index 0000000..9a4669f --- /dev/null +++ b/src/Molecule-IDE/MolCreateNewComponentCommand.class.st @@ -0,0 +1,90 @@ +Class { + #name : #MolCreateNewComponentCommand, + #superclass : #MolClassesCmdCommand, + #instVars : [ + 'package', + 'packageTag', + 'browser' + ], + #category : #'Molecule-IDE-Commands' +} + +{ #category : #activation } +MolCreateNewComponentCommand class >> browserMenuActivation [ + + + ^ CmdContextMenuActivation + byItemOf: MolCmdMenuGroup + order: 80 + for: ClyFullBrowserClassContext +] + +{ #category : #testing } +MolCreateNewComponentCommand class >> canBeExecutedInContext: aBrowserContext [ + + ^self isAbstract not and:[aBrowserContext isPackageSelected] + +] + +{ #category : #accessing } +MolCreateNewComponentCommand >> defaultMenuIconName [ + ^#class +] + +{ #category : #accessing } +MolCreateNewComponentCommand >> defaultMenuItemName [ + + ^ 'New component' +] + +{ #category : #accessing } +MolCreateNewComponentCommand >> description [ + + ^ 'Initialize an empty component implementation with traits for class, events and services' +] + +{ #category : #execution } +MolCreateNewComponentCommand >> execute [ + + | componentDefinition classGeneratedComp traitType compImplName eventName serviceName traitServices traitEvents | + componentDefinition := self morphicUIManager request: 'Define component name:' initialAnswer: 'MyComponent'. + componentDefinition isEmptyOrNil ifTrue: [ ^ self ]. + + MolComponentFactory createComponentType: componentDefinition asSymbol in: package tag: packageTag. + + traitType := self class environment at: componentDefinition asSymbol. + + eventName := (componentDefinition, 'Events') asSymbol. + MolComponentFactory createComponentEvents: eventName in: package tag: packageTag. + traitEvents := self class environment at: eventName. + + serviceName := (componentDefinition, 'Services') asSymbol. + MolComponentFactory createComponentServices: serviceName in: package tag: packageTag. + traitServices := self class environment at: serviceName. + + compImplName := (componentDefinition, 'Impl') asSymbol. + MolComponentFactory createComponentNamed: compImplName in: package name tag: packageTag. + + classGeneratedComp := self class environment at: compImplName. + classGeneratedComp setTraitComposition: traitType. + + MolComponentFactory addProvidedServices: traitServices in: traitType. + MolComponentFactory addProducedEvents: traitEvents in: traitType +] + +{ #category : #execution } +MolCreateNewComponentCommand >> prepareFullExecutionInContext: aBrowserContext [ + + super prepareFullExecutionInContext: aBrowserContext. + + package := aBrowserContext lastSelectedPackage. + aBrowserContext isPackageTagSelected ifFalse:[^self]. + packageTag := aBrowserContext lastSelectedPackageTag + +] + +{ #category : #execution } +MolCreateNewComponentCommand >> readParametersFromContext: aToolContext [ + super readParametersFromContext: aToolContext. + browser := aToolContext browser +] diff --git a/src/Molecule-Tests/MolCompleteComponentOverloadImpl.class.st b/src/Molecule-Tests/MolCompleteComponentOverloadImpl.class.st index 9bc9e86..179a47c 100644 --- a/src/Molecule-Tests/MolCompleteComponentOverloadImpl.class.st +++ b/src/Molecule-Tests/MolCompleteComponentOverloadImpl.class.st @@ -4,8 +4,8 @@ I am a component impl overloading my contract for impl purpose Class { #name : #MolCompleteComponentOverloadImpl, #superclass : #MolAbstractComponentImpl, - #traits : 'MolCompleteComponent + MolUsedEvents + MolUsedEvents2 + MolUsedServices + MolUsedServices2 + MolUsedParameters + MolUsedParameters2', - #classTraits : 'MolCompleteComponent classTrait + MolUsedEvents classTrait + MolUsedEvents2 classTrait + MolUsedServices classTrait + MolUsedServices2 classTrait + MolUsedParameters classTrait + MolUsedParameters2 classTrait', + #traits : 'MolCompleteComponent + MolUsedEvents + MolUsedServices + MolUsedServices2 + MolUsedParameters + MolUsedParameters2 + MolUsedEvents2', + #classTraits : 'MolCompleteComponent classTrait + MolUsedEvents classTrait + MolUsedServices classTrait + MolUsedServices2 classTrait + MolUsedParameters classTrait + MolUsedParameters2 classTrait + MolUsedEvents2 classTrait', #category : #'Molecule-Tests-Resources - Components' } diff --git a/src/Molecule-Tests/MolComponentFactoryTest.class.st b/src/Molecule-Tests/MolComponentFactoryTest.class.st index 983399a..6b93a83 100644 --- a/src/Molecule-Tests/MolComponentFactoryTest.class.st +++ b/src/Molecule-Tests/MolComponentFactoryTest.class.st @@ -40,6 +40,15 @@ MolComponentFactoryTest >> cleanGeneratedMethods [ ]. ] +{ #category : #running } +MolComponentFactoryTest >> cleanGeneratedPackage [ + + | packageGenerated | + packageGenerated := PackageOrganizer packageOrganizer packages detect:[:p | p name = self generationPackage ] ifNone:[nil]. + packageGenerated ifNil:[^self]. + packageGenerated removeFromSystem +] + { #category : #utilities } MolComponentFactoryTest >> createInstanceMethod: aSelector in: aClassOrTrait protocol: aProtocolString withCode: aSourceCodeString [ "Create an instance method in a Class or Trait with source code implementation" @@ -115,9 +124,14 @@ MolComponentFactoryTest >> generatedComponentTypeTrait [ ^self class environment at: self generatedComponentTypeSymbolName ] +{ #category : #accessing } +MolComponentFactoryTest >> generationPackage [ + ^'Molecule-Tests-Resources' +] + { #category : #accessing } MolComponentFactoryTest >> generationTag [ - ^'Molecule-Tests-Resources - Generated' + ^'Generated' ] { #category : #utilities } @@ -129,6 +143,7 @@ MolComponentFactoryTest >> resetSourceCode [ self cleanGeneratedClassesAndTraits. self restoreRemovedThings. self cleanGeneratedMethods. + self cleanGeneratedPackage. MolComponentFactory default activateDynamicContractUpdate: false. @@ -274,7 +289,7 @@ MolComponentFactoryTest >> testComponentChangedOnComponentCreationWithoutType [ MolComponentFactory default deactivateDynamicContractUpdate: false. "remove the testing class, and create a new component without Type, when the type is added check if the component in on the dirty components list" - MolComponentFactory createComponentNamed: self generatedComponentClassSymbolName in: self generationTag. + MolComponentFactory createComponentNamed: self generatedComponentClassSymbolName in: self generationPackage. "Waiting for event callback" self assert: (MolComponentFactory default dirtyComponents includes: (self generatedComponentClass)). @@ -288,7 +303,7 @@ MolComponentFactoryTest >> testComponentChangedOnComponentCreationWithoutType [ "remove the testing class, and create a new component with Type, check if the component in on the dirty components list" (self class environment at: self generatedComponentClassSymbolName) removeFromSystem. - MolComponentFactory createComponentForType: MolCompleteComponent named: self generatedComponentClassSymbolName in: self generationTag. + MolComponentFactory createComponentForType: MolCompleteComponent named: self generatedComponentClassSymbolName in: self generationPackage. "Waiting for event callback" self assert: (MolComponentFactory default dirtyComponents includes: (self generatedComponentClass)). @@ -448,7 +463,7 @@ MolComponentFactoryTest >> testCreateComponentClassWithType [ (self class environment at: self generatedComponentClassSymbolName) removeFromSystem ]. - MolComponentFactory createComponentForType: MolCompleteComponent named: self generatedComponentClassSymbolName in: self generationTag. + MolComponentFactory createComponentForType: MolCompleteComponent named: self generatedComponentClassSymbolName in: self generationPackage. class := self class environment at: self generatedComponentClassSymbolName. self assert: class notNil. @@ -467,7 +482,7 @@ MolComponentFactoryTest >> testCreateComponentClassWithoutType [ (self class environment at: self generatedComponentClassSymbolName) removeFromSystem. ]. - MolComponentFactory createComponentNamed: self generatedComponentClassSymbolName in: self generationTag. + MolComponentFactory createComponentNamed: self generatedComponentClassSymbolName in: self generationPackage. class := self class environment at: self generatedComponentClassSymbolName. self assert: class notNil. @@ -654,6 +669,19 @@ MolComponentFactoryTest >> testCreateComponentForTypeNamedIn [ self assert: error equals: true. ] +{ #category : #'tests - component creation' } +MolComponentFactoryTest >> testCreateComponentForTypeNamedInTag [ + "Test errors cases" + | error | + error := false. + [MolComponentFactory createComponentForType: nil named: nil in: nil tag: nil] on: Error do:[ error := true ]. + self assert: error. + + error := false. + [MolComponentFactory createComponentForType: String named: #ClassName in: #packageName tag: #tagName ] on: NotAComponentTypeError do:[ error := true ]. + self assert: error. +] + { #category : #'tests - contract creation' } MolComponentFactoryTest >> testCreateComponentParameters [ "Create a Component Parameters from scratch" @@ -684,7 +712,7 @@ MolComponentFactoryTest >> testCreateComponentType [ (self class environment at: self generatedComponentTypeSymbolName) removeFromSystem. ]. - MolComponentFactory createComponentType: self generatedComponentTypeSymbolName in: self generationTag. + MolComponentFactory createComponentType: self generatedComponentTypeSymbolName in: self generationPackage. trait := self class environment at: self generatedComponentTypeSymbolName. self assert: trait notNil. @@ -708,7 +736,7 @@ MolComponentFactoryTest >> testCreateEmptyComponentEvents [ (self class environment at: self generatedComponentEventsSymbolName) removeFromSystem. ]. - MolComponentFactory createComponentEvents: self generatedComponentEventsSymbolName in: self generationTag. + MolComponentFactory createComponentEvents: self generatedComponentEventsSymbolName in: self generationPackage. trait := self class environment at: self generatedComponentEventsSymbolName. self assert: trait notNil. @@ -732,7 +760,7 @@ MolComponentFactoryTest >> testCreateEmptyComponentParameters [ (self class environment at: self generatedComponentParametersSymbolName) removeFromSystem. ]. - MolComponentFactory createComponentParameters: self generatedComponentParametersSymbolName in: self generationTag. + MolComponentFactory createComponentParameters: self generatedComponentParametersSymbolName in: self generationPackage. trait := self class environment at: self generatedComponentParametersSymbolName. self assert: trait notNil. @@ -756,7 +784,7 @@ MolComponentFactoryTest >> testCreateEmptyComponentServices [ (self class environment at: self generatedComponentServicesSymbolName) removeFromSystem. ]. - MolComponentFactory createComponentServices: self generatedComponentServicesSymbolName in: self generationTag. + MolComponentFactory createComponentServices: self generatedComponentServicesSymbolName in: self generationPackage. trait := self class environment at: self generatedComponentServicesSymbolName. self assert: trait notNil. @@ -972,7 +1000,7 @@ MolComponentFactoryTest >> testMakeAComponentAndAddATrait [ componentClassNameSymbol := self generatedComponentClass2SymbolName. - class := MolComponentFactory createComponentNamed: componentClassNameSymbol in: self generationTag. + class := MolComponentFactory createComponentNamed: componentClassNameSymbol in: self generationPackage. class := self class environment at: componentClassNameSymbol. class comment: 'I am added and removed by test: ', self printString. @@ -981,7 +1009,7 @@ MolComponentFactoryTest >> testMakeAComponentAndAddATrait [ self assert: (class canPerform: #methodOfNoComponentTrait). "Set the component type and check if the existing Trait is already functionnal" - MolComponentFactory createComponentType: self generatedComponentTypeSymbolName in: self generationTag. + MolComponentFactory createComponentType: self generatedComponentTypeSymbolName in: self generationPackage. class addToComposition: self generatedComponentTypeTrait. self assert: (class canPerform: #methodOfNoComponentTrait). @@ -1000,10 +1028,10 @@ MolComponentFactoryTest >> testMakeAComponentAndAddATraitWithCompleteContract [ componentClassNameSymbol := self generatedComponentClass2SymbolName. - MolComponentFactory createComponentNamed: componentClassNameSymbol in: self generationTag. + MolComponentFactory createComponentNamed: componentClassNameSymbol in: self generationPackage. componentClass := self class environment at: componentClassNameSymbol. - MolComponentFactory createComponentType: self generatedComponentTypeSymbolName in: self generationTag. + MolComponentFactory createComponentType: self generatedComponentTypeSymbolName in: self generationPackage. componentClass setTraitComposition: self generatedComponentTypeTrait. self testCreateEmptyComponentServices. @@ -1043,13 +1071,13 @@ MolComponentFactoryTest >> testMakeAComponentAndAddATraitWithCompleteContractAlt componentClassNameSymbol := self generatedComponentClass2SymbolName. - MolComponentFactory createComponentNamed: componentClassNameSymbol in: self generationTag. + MolComponentFactory createComponentNamed: componentClassNameSymbol in: self generationPackage. componentClass := self class environment at: componentClassNameSymbol. "Add a trait" componentClass setTraitComposition: MolTestNoComponentTraitA. - MolComponentFactory createComponentType: self generatedComponentTypeSymbolName in: self generationTag. + MolComponentFactory createComponentType: self generatedComponentTypeSymbolName in: self generationPackage. componentClass addToComposition: self generatedComponentTypeTrait. self testCreateEmptyComponentServices. @@ -1086,10 +1114,10 @@ MolComponentFactoryTest >> testMakeAComponentFromScratch [ componentClassNameSymbol := self generatedComponentClass2SymbolName. - MolComponentFactory createComponentNamed: componentClassNameSymbol in: self generationTag. + MolComponentFactory createComponentNamed: componentClassNameSymbol in: self generationPackage. componentClass := self class environment at: componentClassNameSymbol. - MolComponentFactory createComponentType: self generatedComponentTypeSymbolName in: self generationTag. + MolComponentFactory createComponentType: self generatedComponentTypeSymbolName in: self generationPackage. componentClass setTraitComposition: self generatedComponentTypeTrait. self testCreateEmptyComponentServices. @@ -1138,7 +1166,7 @@ MolComponentFactoryTest >> testMakeAComponentFromScratchAlternative2 [ componentClassNameSymbol := self generatedComponentClass2SymbolName. - MolComponentFactory createComponentType: self generatedComponentTypeSymbolName in: self generationTag. + MolComponentFactory createComponentType: self generatedComponentTypeSymbolName in: self generationPackage. self testCreateEmptyComponentServices. self testCreateEmptyComponentParameters. @@ -1158,7 +1186,7 @@ MolComponentFactoryTest >> testMakeAComponentFromScratchAlternative2 [ self createInstanceMethod: 'testGeneratedEventA' in: self generatedComponentEventsTrait protocol: 'events' withCode: nil. self createInstanceMethod: 'testGeneratedEventB' in: self generatedComponentEventsTrait protocol: 'events' withCode: nil. - MolComponentFactory createComponentForType: self generatedComponentTypeTrait named: componentClassNameSymbol in: self generationTag. + MolComponentFactory createComponentForType: self generatedComponentTypeTrait named: componentClassNameSymbol in: self generationPackage. componentClass := self class environment at: componentClassNameSymbol. "Check generated methods" @@ -1188,9 +1216,9 @@ MolComponentFactoryTest >> testMakeAComponentFromScratchAlternative3 [ componentClassNameSymbol := self generatedComponentClass2SymbolName. - MolComponentFactory createComponentType: self generatedComponentTypeSymbolName in: self generationTag. + MolComponentFactory createComponentType: self generatedComponentTypeSymbolName in: self generationPackage. - MolComponentFactory createComponentForType: self generatedComponentTypeTrait named: componentClassNameSymbol in: self generationTag. + MolComponentFactory createComponentForType: self generatedComponentTypeTrait named: componentClassNameSymbol in: self generationPackage. componentClass := self class environment at: componentClassNameSymbol. self testCreateComponentServices. @@ -1233,9 +1261,9 @@ MolComponentFactoryTest >> testMakeAComponentFromScratchAlternative4 [ componentClassNameSymbol := self generatedComponentClass2SymbolName. - MolComponentFactory createComponentType: self generatedComponentTypeSymbolName in: self generationTag. + MolComponentFactory createComponentType: self generatedComponentTypeSymbolName in: self generationPackage. - MolComponentFactory createComponentForType: self generatedComponentTypeTrait named: componentClassNameSymbol in: self generationTag. + MolComponentFactory createComponentForType: self generatedComponentTypeTrait named: componentClassNameSymbol in: self generationPackage. componentClass := self class environment at: componentClassNameSymbol. self testCreateComponentServices. @@ -1280,12 +1308,12 @@ MolComponentFactoryTest >> testMakeAComponentFromScratchAlternative5 [ | componentClassNameSymbol componentClass | self assert: MolComponentFactory default isDynamicContractUpdateActivated. - MolComponentFactory createComponentType: self generatedComponentTypeSymbolName in: self generationTag. + MolComponentFactory createComponentType: self generatedComponentTypeSymbolName in: self generationPackage. self testCreateEmptyComponentEvents. componentClassNameSymbol := self generatedComponentClass2SymbolName. - MolComponentFactory createComponentForType: self generatedComponentTypeTrait named: componentClassNameSymbol in: self generationTag. + MolComponentFactory createComponentForType: self generatedComponentTypeTrait named: componentClassNameSymbol in: self generationPackage. componentClass := self class environment at: componentClassNameSymbol. MolComponentFactory addProducedEvents: self generatedComponentEventsTrait in: self generatedComponentTypeTrait. diff --git a/src/Molecule-Tests/MolDirtyComponentTest.class.st b/src/Molecule-Tests/MolDirtyComponentTest.class.st index db65e60..23a2358 100644 --- a/src/Molecule-Tests/MolDirtyComponentTest.class.st +++ b/src/Molecule-Tests/MolDirtyComponentTest.class.st @@ -23,7 +23,7 @@ MolDirtyComponentTest >> generatedDirtyTypeImplementationSymbol [ ] { #category : #accessing } -MolDirtyComponentTest >> generationTag [ +MolDirtyComponentTest >> generationPackage [ ^ 'Molecule-Tests-Resources - Generated' ] @@ -51,7 +51,7 @@ MolDirtyComponentTest >> testDirtyTypeWithInstanceVariableInsteadOfComponentTrai "Create a component using a dirty Type: a type which is not correct (potentiels bugs)" | component | - MolComponentFactory createComponentForType: MolDirtyType named: self generatedDirtyTypeImplementationSymbol in: self generationTag. + MolComponentFactory createComponentForType: MolDirtyType named: self generatedDirtyTypeImplementationSymbol in: self generationPackage. component := self class environment at: self generatedDirtyTypeImplementationSymbol. "Check if the ComponentType is dirty" diff --git a/src/Molecule/MolComponentFactory.class.st b/src/Molecule/MolComponentFactory.class.st index 45af43a..9569c7e 100644 --- a/src/Molecule/MolComponentFactory.class.st +++ b/src/Molecule/MolComponentFactory.class.st @@ -200,9 +200,33 @@ MolComponentFactory class >> createComponentEvents: aSymbol in: aPackageName [ install ] +{ #category : #'component - creation' } +MolComponentFactory class >> createComponentEvents: aSymbol in: aPackageName tag: aTagName [ + "Create a ComponentEvents interface named aSymbol in a package" + + aSymbol ifNil: [ ^ self ]. + aPackageName ifNil: [ ^ self ]. + self class environment at: aSymbol ifPresent: [ + ^ self error: + '[Molecule] Do not create an existing component events interface, remove it before.' ]. + + "create the new Trait" + (Trait << aSymbol) + traits: MolComponentEvents; + package: aPackageName; + tag: aTagName; + install +] + { #category : #'component - creation' } MolComponentFactory class >> createComponentForType: aComponentType named: aSymbol in: aPackageName [ + ^self createComponentForType: aComponentType named: aSymbol in: aPackageName tag: nil +] + +{ #category : #'component - creation' } +MolComponentFactory class >> createComponentForType: aComponentType named: aSymbol in: aPackageName tag: aTagName [ + | builder | aComponentType ifNotNil: [ (aComponentType isTrait and: [ aComponentType isComponentType ]) @@ -220,7 +244,11 @@ MolComponentFactory class >> createComponentForType: aComponentType named: aSymb '[Molecule] Do not redefine an existing Component, remove it before.' ]. "create new component implementation class" - builder := MolAbstractComponentImpl << aSymbol package: aPackageName. + builder := (aTagName isEmptyOrNil) ifTrue:[ + MolAbstractComponentImpl << aSymbol package: aPackageName + ] ifFalse:[ + MolAbstractComponentImpl << aSymbol package: aPackageName; tag: aTagName + ]. aComponentType ifNotNil: [ builder traits: aComponentType ]. builder install ] @@ -233,6 +261,14 @@ MolComponentFactory class >> createComponentNamed: aSymbol in: aPackageName [ self createComponentForType: nil named: aSymbol in: aPackageName ] +{ #category : #'component - creation' } +MolComponentFactory class >> createComponentNamed: aSymbol in: aPackageName tag: aTagName [ + + aSymbol ifNil: [ ^ self ]. + aPackageName ifNil: [ ^ self ]. + self createComponentForType: nil named: aSymbol in: aPackageName tag: aTagName +] + { #category : #'component - creation' } MolComponentFactory class >> createComponentParameters: aSymbol in: aPackageName [ "Create a ComponentParameters interface named aSymbol in a package" @@ -267,6 +303,24 @@ MolComponentFactory class >> createComponentServices: aSymbol in: aPackageName [ install ] +{ #category : #'component - creation' } +MolComponentFactory class >> createComponentServices: aSymbol in: aPackageName tag: aTagName [ + "Create a ComponentServices interface named aSymbol in a package" + + aSymbol ifNil: [ ^ self ]. + aPackageName ifNil: [ ^ self ]. + self class environment at: aSymbol ifPresent: [ + ^ self error: + '[Molecule] Do not create an existing component services interface, remove it before.' ]. + + "create the new Trait" + (Trait << aSymbol) + traits: MolComponentServices; + package: aPackageName; + tag: aTagName; + install +] + { #category : #'component - creation' } MolComponentFactory class >> createComponentType: aSymbol in: aPackageName [ "Create a ComponentType named aSymbol in a package" @@ -284,6 +338,24 @@ MolComponentFactory class >> createComponentType: aSymbol in: aPackageName [ install ] +{ #category : #'component - creation' } +MolComponentFactory class >> createComponentType: aSymbol in: aPackageName tag: aTagName [ + "Create a ComponentType named aSymbol in a package" + + aSymbol ifNil: [ ^ self ]. + aPackageName ifNil: [ ^ self ]. + self class environment at: aSymbol ifPresent: [ + ^ self error: + '[Molecule] Do not create an existing component type, remove it before.' ]. + + "create the new Trait" + (Trait << aSymbol) + traits: MolComponentType; + package: aPackageName; + tag: aTagName; + install +] + { #category : #'component - contract management' } MolComponentFactory class >> createSourceCodeContractSelector: aSelector protocol: aProtocol interfaces: interfaceList type: aComponentType [ "Create source code for Component Type contract description method into a class selector, this method return an array of Molecule interfaces (Traits as Services or Events)"