Skip to content

Commit

Permalink
Rewrote serializer, now dynamic and works with Yaml
Browse files Browse the repository at this point in the history
  • Loading branch information
ozcanxbreeze committed Aug 18, 2023
1 parent ac5ea1c commit df6a8b9
Show file tree
Hide file tree
Showing 26 changed files with 346 additions and 49 deletions.
16 changes: 15 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,20 @@
"${workspaceFolder}/node_modules/vscode-languageclient/**/*.js",
"${workspaceFolder}/node_modules/vscode-jsonrpc/**/*.js"
]
}
},
{
"name": "Debug Jest Tests",
"type": "node",
"request": "launch",
"runtimeArgs": [
"--inspect-brk",
"${workspaceRoot}/node_modules/jest/bin/jest.js",
"--runInBand",
"--config=extensions/crossmodel-lang/jest.config.js",
"--testPathPattern=extensions/crossmodel-lang/test/language-server/serializer/cross-model-serializer.test.ts"
],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
* Copyright (c) 2023 CrossBreeze.
********************************************************************************/

import { AstNode, isReference } from 'langium';
import { isReference } from 'langium';
import { Serializer } from '../model-server/serializer';
import { CrossModelServices } from './cross-model-module';
import { CrossModelRoot } from './generated/ast';
import { CrossModelRoot, Entity, Relationship, SystemDiagram } from './generated/ast';

/**
* Hand-written AST serializer as there is currently no out-of-the box serializer from Langium, but it is on the roadmap.
Expand All @@ -16,31 +16,15 @@ export class CrossModelSerializer implements Serializer<CrossModelRoot> {
constructor(protected services: CrossModelServices, protected refNameProvider = services.references.QualifiedNameProvider) {}

serialize(root: CrossModelRoot): string {
let newRoot: AstNode | undefined = this.toSerializableObject(root);

let startKey;

if (root.entity) {
startKey = 'entity';
newRoot = root.entity;
} else if (root.diagram) {
startKey = 'diagram';
newRoot = root.diagram;
} else if (root.relationship) {
startKey = 'relationship';
newRoot = root.diagram;
} else {
return '';
}

return startKey + ':' + '\n ' + this.serializeValue(newRoot, 0);
const newRoot: CrossModelRoot | Entity | Relationship | SystemDiagram = this.toSerializableObject(root);
return this.serializeValue(newRoot, -4);
}

private serializeValue(value: any, indentationLevel: number): string {
if (typeof value === 'object' && value !== undefined) {
if (Array.isArray(value)) {
return this.serializeArray(value, indentationLevel);
} else if (typeof value === 'object' && value !== undefined) {
return this.serializeObject(value, indentationLevel + 4);
} else if (Array.isArray(value)) {
return this.serializeArray(value, indentationLevel + 4);
} else {
return JSON.stringify(value);
}
Expand All @@ -49,19 +33,37 @@ export class CrossModelSerializer implements Serializer<CrossModelRoot> {
private serializeObject(obj: Record<string, any>, indentationLevel: number): string {
const indentation = ' '.repeat(indentationLevel);

const serializedProperties = Object.entries(obj).map(([key, value]) => {
const serializedValue = this.serializeValue(value, indentationLevel);
return `${indentation}${key}: ${serializedValue}`;
});

return serializedProperties.join(',\n') + '\n';
const serializedProperties = Object.entries(obj)
.map(([key, value]) => {
if (Array.isArray(value) && value.length === 0) {
return;
}

const serializedValue = this.serializeValue(value, indentationLevel);

if (key === 'name_val') {
key = 'name';
} else if (key === 'name') {
key = 'id';
}

if (typeof value === 'object') {
return `${indentation}${key}:\n${serializedValue}`;
} else {
return `${indentation}${key}: ${serializedValue}`;
}
})
.filter(item => item !== undefined);

return serializedProperties.join('\n');
}

private serializeArray(arr: any[], indentationLevel: number): string {
let serializedItems = arr.map(item => this.serializeValue(item, indentationLevel)).join('\n');
serializedItems = this.changeCharInString(serializedItems, indentationLevel - 2, '-');

return serializedItems + '\n';
const serializedItems = arr
.map(item => this.serializeValue(item, indentationLevel))
.map(item => this.changeCharInString(item, indentationLevel + 2, '-'))
.join('\n');
return serializedItems;
}

private changeCharInString(inputString: string, indexToChange: number, newChar: any): string {
Expand All @@ -80,18 +82,20 @@ export class CrossModelSerializer implements Serializer<CrossModelRoot> {
* @param obj semantic object
* @returns serializable semantic object
*/
toSerializableObject<T extends object>(obj?: T): T | undefined {
if (!obj) {
return;
}

toSerializableObject<T extends object>(obj: T): T {
return <T>Object.entries(obj)
.filter(([key, value]) => !key.startsWith('$'))
.reduce((acc, [key, value]) => ({ ...acc, [key]: this.cleanValue(value) }), {});
}

cleanValue(value: any): any {
return this.isContainedObject(value) ? this.toSerializableObject(value) : this.resolvedValue(value);
if (Array.isArray(value)) {
return value.map(item => this.cleanValue(item));
} else if (this.isContainedObject(value)) {
return this.toSerializableObject(value);
} else {
return this.resolvedValue(value);
}
}

isContainedObject(value: any): boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import { describe, expect, test } from '@jest/globals';
import { EmptyFileSystem, isReference } from 'langium';

import { parseDocument } from './utils/utils';
import { diagram1, diagram2, diagram3, diagram4, diagram5, diagram6 } from './utils/test-documents/diagram/index';
import { parseDocument } from './test-utils/utils';
import { diagram1, diagram2, diagram3, diagram4, diagram5, diagram6 } from './test-utils/test-documents/diagram/index';

import { CrossModelRoot } from '../../src/language-server/generated/ast';
import { createCrossModelServices } from '../../src/language-server/cross-model-module';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import { describe, expect, test } from '@jest/globals';
import { EmptyFileSystem } from 'langium';

import { parseDocument } from './utils/utils';
import { entity1, entity2, entity3, entity4 } from './utils/test-documents/entity/index';
import { parseDocument } from './test-utils/utils';
import { entity1, entity2, entity3, entity4 } from './test-utils/test-documents/entity/index';

import { CrossModelRoot } from '../../src/language-server/generated/ast';
import { createCrossModelServices } from '../../src/language-server/cross-model-module';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import { describe, expect, test } from '@jest/globals';
import { EmptyFileSystem, isReference } from 'langium';

import { parseDocument } from './utils/utils';
import { relationship1, relationship2 } from './utils/test-documents/relationship/index';
import { parseDocument } from './test-utils/utils';
import { relationship1, relationship2 } from './test-utils/test-documents/relationship/index';

import { CrossModelRoot } from '../../src/language-server/generated/ast';
import { createCrossModelServices } from '../../src/language-server/cross-model-module';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
import { describe, expect, test, beforeAll } from '@jest/globals';

import { Grammar } from 'langium';
import { ExampleGrammarWithIndent } from '../utils/example-grammar';
import { ExampleGrammarWithIndent } from '../test-utils/example-grammar';
import { TokenType } from 'chevrotain';

import { ExampleGrammarWithNoIndent } from '../utils/example-grammar-no-indent';
import { ExampleGrammarWithNoIndent } from '../test-utils/example-grammar-no-indent';
import { DEDENT, INDENT, NEWLINE, SPACES } from '../../../src/language-server/lexer/cross-model-indentation-tokens';
import { CrossModelTokenBuilder } from '../../../src/language-server/lexer/cross-model-token-generator';

Expand Down
Loading

0 comments on commit df6a8b9

Please sign in to comment.