diff --git a/src/language-server/universal-data-definition-language-formatter.ts b/src/language-server/universal-data-definition-language-formatter.ts index 9bf0734..2a44fd2 100644 --- a/src/language-server/universal-data-definition-language-formatter.ts +++ b/src/language-server/universal-data-definition-language-formatter.ts @@ -1,9 +1,8 @@ -import { AbstractFormatter, AstNode, Formatting, Module, PartialLangiumServices } from 'langium'; +import { AbstractFormatter, AstNode, Formatting, Module, PartialLangiumServices, } from 'langium'; import * as ast from './generated/ast'; import { UniversalDataDefinitionLanguageServices } from './universal-data-definition-language-module'; export class UniversalDataDefinitionLanguageFormatter extends AbstractFormatter { - protected formatContainer(node: AstNode): void { const formatter = this.getNodeFormatter(node); const open = formatter.keyword('{'); @@ -22,11 +21,57 @@ export class UniversalDataDefinitionLanguageFormatter extends AbstractFormatter close.surround(Formatting.noSpace()).prepend(Formatting.newLine({allowMore: true})).append(Formatting.newLine({allowMore: true})); } - protected format(node: AstNode): void { + protected formatNode(node: AstNode): void { + const formatter = this.getNodeFormatter(node); + formatter.property('name').prepend(Formatting.newLine()).surround(Formatting.oneSpace({allowMore: true})) + } + + protected format(node: AstNode): void { // This method is called for every AstNode in a document if (ast.isDataModel(node)) { this.formatDataModel(node); - + } + else if(ast.isConceptualAssociation(node)){ + this.formatConceptualAssociation(node) + } + else if(ast.isConceptualEntity(node)){ + this.formatConceptualEntity(node) + } + else if(ast.isLogicalEnumerated(node)){ + this.formatLogicalEnumerated(node) + } + else if(ast.isLogicalMeasurement(node)){ + this.formatLogicalMeasurement(node) + } + else if(ast.isLogicalMeasurementSystemAxis(node)){ + this.formatLogicalMeasurementSystemAxis(node) + } + else if(ast.isLogicalValueTypeUnit(node)){ + this.formatLogicalValueTypeUnit(node) + } + else if(ast.isLogicalMeasurement(node)){ + this.formatLogicalMeasurement(node) + } + else if(ast.isLogicalAssociation(node)){ + this.formatLogicalAssociation(node) + } + else if(ast.isLogicalEntity(node)){ + this.formatLogicalEntity(node) + } + else if(ast.isLogicalParticipantPathNode(node)){ + this.formatLogicalParticipantPathNode(node) + } + else if(ast.isPlatformAssociation(node)){ + this.formatPlatformAssociation(node); + } + else if(ast.isPlatformEntity(node)){ + this.formatPlatformEntity(node) + } + else if(ast.isPlatformStruct(node)){ + this.formatPlatformStruct(node) + } + else if(ast.isPlatformCompositeQuery(node)){ + this.formatPlatformCompositeQuery(node); } } @@ -50,10 +95,10 @@ export class UniversalDataDefinitionLanguageFormatter extends AbstractFormatter protected formatConceptualDataModel(cdm: ast.ConceptualDataModel): void { this.formatContainer(cdm); - cdm.cdm.forEach(dm => { + cdm.cdm.forEach(dm => { this.formatConceptualDataModel(dm); }) - cdm.element.forEach( elem => { + cdm.element.forEach( elem => { this.formatConceptualElement(elem); }) } @@ -64,7 +109,7 @@ export class UniversalDataDefinitionLanguageFormatter extends AbstractFormatter this.formatLogicalDataModel(dm) }) ldm.element.forEach( elem => { - this.formatElement(elem) + this.formatLogicalElement(elem) }) } @@ -74,21 +119,166 @@ export class UniversalDataDefinitionLanguageFormatter extends AbstractFormatter this.formatPlatfornDataModel(dm) }) pdm.element.forEach(elem => { - this.formatElement(elem) + this.formatPlatformElement(elem) }) } - protected formatConceptualElement(elem: ast.ConceptualElement): void { + /**Formatting conceptuals */ + protected formatConceptualElement(elem: ast.ConceptualElement): void { const formatter = this.getNodeFormatter(elem); - formatter.property('name').prepend(Formatting.newLine()).surround(Formatting.oneSpace({allowMore: true})); + formatter.property('name').prepend(Formatting.newLine({allowMore: true})).surround(Formatting.oneSpace({allowMore: true})); this.formatObj(elem); } - protected formatElement(elem: ast.LogicalElement | ast.PlatformElement): void { + protected formatConceptualEntity(entity: ast.ConceptualEntity): void { + this.formatContainer(entity) + entity.composition.forEach(comp => { + this.formatConceptualComposition(comp) + }) + } + + protected formatConceptualAssociation(cassoc: ast.ConceptualAssociation): void { + this.formatContainer(cassoc) + cassoc.composition.forEach(comp => { + this.formatConceptualComposition(comp) + }) + } + + protected formatConceptualComposition(comp: ast.ConceptualComposition ): void { + this.formatContainer(comp) + } + + protected formatConceptualParticipant(participant: ast.ConceptualParticipant): void { + this.formatContainer(participant) + if(participant?.type){ + this.formatConceptualEntity(participant.type.ref!) + } + } + + /**Formatting logicals */ + protected formatLogicalElement(elem: ast.LogicalElement): void { + const formatter = this.getNodeFormatter(elem); + formatter.property('name').prepend(Formatting.newLine()).surround(Formatting.oneSpace({allowMore: true})); + this.formatObj(elem); + } + + protected formatLogicalEnumerated(lenum: ast.LogicalEnumerated): void { + this.formatContainer(lenum) + lenum.label.forEach(label => { + this.formatContainer(label) + }) + } + + protected formatLogicalMeasurementSystem(sys: ast.LogicalMeasurementSystem): void { + this.formatContainer(sys); + sys.constraint.forEach(sysConst => { + this.formatContainer(sysConst) + }) + sys.referencePoint.forEach(ref => { + this.formatLogicalReferencePoint(ref); + }) + } + + protected formatLogicalMeasurementSystemAxis(sysAxis: ast.LogicalMeasurementSystemAxis): void { + this.formatContainer(sysAxis); + sysAxis.constraint.forEach(sysConst => { + this.formatContainer(sysConst); + }) + } + + protected formatLogicalReferencePoint(refPoint: ast.LogicalReferencePoint): void { + this.formatContainer(refPoint); + refPoint.referencePointPart.forEach(pointPart => { + this.formatContainer(pointPart); + }) + } + + protected formatLogicalValueTypeUnit(typeUnit: ast.LogicalValueTypeUnit):void { + this.formatContainer(typeUnit); + if(typeUnit.constraint){ + this.formatContainer(typeUnit); + } + } + + protected formatLogicalMeasurement(measure: ast.LogicalMeasurement): void { + this.formatContainer(measure); + measure.attribute.forEach(attr => { + this.formatContainer(attr) + }) + measure.constraint.forEach(mesConst => { + this.formatContainer(mesConst) + }) + } + + protected formatLogicalEntity(entity: ast.LogicalEntity): void { + this.formatContainer(entity); + entity.composition.forEach(comp => { + this.formatContainer(comp); + }) + } + + protected formatLogicalAssociation(asso: ast.LogicalAssociation): void { + this.formatContainer(asso); + asso.composition.forEach(comp => { + this.formatContainer(comp); + }) + asso.participant.forEach(part => { + this.formatLogicalParticipant(part); + }) + } + + protected formatLogicalParticipant(part: ast.LogicalParticipant): void { + this.formatContainer(part) + } + + protected formatLogicalParticipantPathNode(pathBode: ast.LogicalParticipantPathNode): void { + this.formatContainer(pathBode) + } + + protected formatLogicalCompositeQuery(query: ast.LogicalCompositeQuery): void { + this.formatContainer(query) + query.composition.forEach(comp => { + this.formatContainer(query) + }) + } + + protected formatPlatformElement(elem: ast.PlatformElement): void { const formatter = this.getNodeFormatter(elem); formatter.property('name').prepend(Formatting.newLine()).surround(Formatting.oneSpace({allowMore: true})); this.formatObj(elem); } + + protected formatPlatformEntity(entity: ast.PlatformEntity): void { + this.formatContainer(entity) + entity.composition.forEach(comp => { + this.formatContainer(comp) + }) + } + + protected formatPlatformStruct(str: ast.PlatformStruct): void { + this.formatContainer(str) + str.member.forEach(mem => { + this.formatContainer(mem) + }) + } + + protected formatPlatformAssociation(asso: ast.PlatformAssociation): void { + this.formatContainer(asso) + asso.participant.forEach(part => { + this.formatPlatformParticipant(part); + }) + } + + protected formatPlatformParticipant(part: ast.PlatformParticipant): void { + this.formatContainer(part) + } + + protected formatPlatformCompositeQuery(query: ast.PlatformCompositeQuery): void { + this.formatContainer(query) + query.composition.forEach(comp => { + this.formatContainer(comp); + }) + } } @@ -97,5 +287,4 @@ export const UniversalDataDefinitionLanguageModule: Module new UniversalDataDefinitionLanguageFormatter() } -}; - +}; \ No newline at end of file diff --git a/uddl_test/uddl_test_formatting/universal-data-definition-language-formatter.test.ts b/uddl_test/uddl_test_formatting/universal-data-definition-language-formatter.test.ts index 4bf07ab..15debac 100644 --- a/uddl_test/uddl_test_formatting/universal-data-definition-language-formatter.test.ts +++ b/uddl_test/uddl_test_formatting/universal-data-definition-language-formatter.test.ts @@ -2,24 +2,217 @@ import { createUniversalDataDefinitionLanguageServices } from "../../src/languag import { EmptyFileSystem } from "langium"; import { expectFormatting } from "langium/test"; -const universalDataDefinitionLanguageService =createUniversalDataDefinitionLanguageServices({...EmptyFileSystem,}).UniversalDataDefinitionLanguage; -const universalDataDefinitionLanguageFormatting = expectFormatting(universalDataDefinitionLanguageService +const universalDataDefinitionLanguageService = + createUniversalDataDefinitionLanguageServices({ + ...EmptyFileSystem, + }).UniversalDataDefinitionLanguage; +const universalDataDefinitionLanguageFormatting = expectFormatting( + universalDataDefinitionLanguageService ); describe("Universal Data Definition Language Formatter", () => { - it("should indent correctly", async () => { + it("should format cdm array", async () => { await universalDataDefinitionLanguageFormatting({ before: - 'dm PPT "Base data structures to support People, Places and Things"{cdm Conceptual "Need to start at Conceptual Level"{}}', + 'dm PPT "Base data structures to support People, Places and Things"{cdm Conceptual "Need to start at Conceptual Level"{cdm anothercdm "A cdm with another data" {observable Information "Something a party can learn";}}}', after: `dm PPT "Base data structures to support People, Places and Things" { cdm Conceptual "Need to start at Conceptual Level" { + cdm anothercdm "A cdm with another data" + { + + observable Information "Something a party can learn"; + } + + } + +}`, + }); + }); + + it("should format cdm with conceptual association", async () => { + await universalDataDefinitionLanguageFormatting({ + before: + 'dm PPT "Base data structures to support People, Places and Things"{cdm Conceptual "Need to start at Conceptual Level"{cassoc Training "Information delivered over time from one party to another " {};}}', + after: `dm PPT "Base data structures to support People, Places and Things" +{ + + cdm Conceptual "Need to start at Conceptual Level" + { + + cassoc Training "Information delivered over time from one party to another " + { + + }; + + } + +}`, + }); + }); + + it("should format cdm with conceptual entity", async () => { + await universalDataDefinitionLanguageFormatting({ + before: + 'dm PPT "Base data structures to support People, Places and Things"{cdm Conceptual "Need to start at Conceptual Level"{centity AddressableEntity "Any entity that is addressable in some way" {};}}', + after: `dm PPT "Base data structures to support People, Places and Things" +{ + + cdm Conceptual "Need to start at Conceptual Level" + { + + centity AddressableEntity "Any entity that is addressable in some way" + { + + }; + + } + +}`, + }); + }); + + it("should format cdm with conceptual basis", async () => { + await universalDataDefinitionLanguageFormatting({ + before: + 'dm PPT "Base data structures to support People, Places and Things"{cdm Conceptual "Need to start at Conceptual Level"{basis uddlBasis "Formating conceptual basis entity"; }}', + after: `dm PPT "Base data structures to support People, Places and Things" +{ + + cdm Conceptual "Need to start at Conceptual Level" + { + + basis uddlBasis "Formating conceptual basis entity"; + } + +}`, + }); + }); + + it("should format cdm with conceptual domain", async () => { + await universalDataDefinitionLanguageFormatting({ + before: + 'dm PPT "Base data structures to support People, Places and Things"{cdm Conceptual "Need to start at Conceptual Level"{domain NaturalPerson "Base definition of a natural person"; }}', + after: `dm PPT "Base data structures to support People, Places and Things" +{ + + cdm Conceptual "Need to start at Conceptual Level" + { + + domain NaturalPerson "Base definition of a natural person"; + } + +}`, + }); + }); + + it("should format ldm array", async () => { + await universalDataDefinitionLanguageFormatting({ + before: + 'dm Book "Base definition for book requirement" {ldm library "contains available books" {ldm BookShelf "Books related by category"{}}}', + after: `dm Book "Base definition for book requirement" +{ + + ldm library "contains available books" + { + + ldm BookShelf "Books related by category" + { + + } + + } + +}`, + }); + }); + + it("should format logical element", async () => { + await universalDataDefinitionLanguageFormatting({ + before: + 'dm logicalElement "Some logial element" {ldm logicalData "logical description"{lunit LengthUnit "Defines units of length";bool IsEnabled "Represents whether an item is enabled";nat NumberOfChildren "Represents the number of children a person has";}}', + after: `dm logicalElement "Some logial element" +{ + + ldm logicalData "logical description" + { + + lunit LengthUnit "Defines units of length"; + bool IsEnabled "Represents whether an item is enabled"; + nat NumberOfChildren "Represents the number of children a person has"; + } + +}`, + }); + }); + + it("should format logical relationships",async () => { + await universalDataDefinitionLanguageFormatting({ + before:'dm logicalElement "Some logial element" {ldm logicalData "logical description"{csa logicalCoordinate "Logical system axis";coord GeographicCoordinates "Represents geographic coordinates" {axis:"WGS84" angleEq:"lat = atan((exp(n) - exp(-n)) / (exp(n) + exp(-n)))" distanceEq:"distance = R * arctan(sqrt(1 - e^2) * tan(lat))"[logicalCoordinate]};}}', + after:`dm logicalElement "Some logial element" +{ + + ldm logicalData "logical description" + { + + csa logicalCoordinate "Logical system axis"; + coord GeographicCoordinates "Represents geographic coordinates" { + + axis: + "WGS84" + angleEq: + "lat = atan((exp(n) - exp(-n)) / (exp(n) + exp(-n)))" + distanceEq: + "distance = R * arctan(sqrt(1 - e^2) * tan(lat))" + [ + logicalCoordinate + ] + }; + } }` + }) + }) + + it("should format platform data model", async () => { + await universalDataDefinitionLanguageFormatting({ + before: + 'dm Library "Defint library collection" {pdm Collection "A collection of related books"{}}', + after: `dm Library "Defint library collection" +{ + + pdm Collection "A collection of related books" + { + + } + +}`, }); }); + + it('should format platform element', async () => { + await universalDataDefinitionLanguageFormatting({ + before:'dm MyDataModel {ldm MyLogicalDataModel {bool LogicalBoolean "Represents a logical boolean";}pdm MyPlatformDataModel {bool BooleanValue "Represents a boolean value" -> MyLogicalDataModel.LogicalBoolean;}}', + after:`dm MyDataModel +{ + + ldm MyLogicalDataModel + { + + bool LogicalBoolean "Represents a logical boolean"; + } + + pdm MyPlatformDataModel + { + + bool BooleanValue "Represents a boolean value" -> MyLogicalDataModel.LogicalBoolean; + } + +}` + }) + }) });