Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import files #35

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/cli/cli-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import colors from 'colors';
import { AstNode, LangiumDocument, LangiumServices } from 'langium';
import path from 'path';
import { URI } from 'vscode-uri';
import { WorkspaceFolder } from 'vscode-languageserver';

export async function extractDocument(fileName: string, extensions: string[], services: LangiumServices): Promise<LangiumDocument> {
if (!extensions.includes(path.extname(fileName))) {
Expand Down Expand Up @@ -39,6 +40,20 @@ export async function extractAstNode<T extends AstNode>(fileName: string, extens
return document.parseResult?.value as T
}


export async function setRootFolder(fileName: string, services: LangiumServices, root?: string): Promise<void> {
const folders: WorkspaceFolder[] = [];
if(!root) {
root = path.dirname(fileName);
}
folders.push({
name: path.basename(root),
uri: path.resolve(root)
});
await services.shared.workspace.IndexManager.initializeWorkspace(folders);
}


interface FilePathData {
destination: string,
name: string
Expand Down
17 changes: 8 additions & 9 deletions src/cli/generator-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type GeneratorContext = {
argumentStack: Object[][]
}


export function generateHTML(model: SimpleUi, filePath: string, destination: string | undefined): string {
const data = extractDestinationAndName(filePath, destination);
const generatedFilePath = `${data.destination}index.html`;
Expand Down Expand Up @@ -107,7 +108,6 @@ const textboxFunc = (textboxEL: AstNode, ctx:GeneratorContext) => {
else {
labelOrder.push(`<input type='text' id='${el.name}' placeholder='${generateExpression(el.placeholdertext, ctx)}'>`);
};
console.log(typeof el.labelAfter)
if (typeof el.labeltext !== 'undefined' && !el.labelAfter) {
labelOrder.unshift(`<label for='${el.name}'>${generateExpression(el.labeltext, ctx)}</label>`, NL);
}
Expand Down Expand Up @@ -148,14 +148,14 @@ const useComponentFunc = (UseComponentEL: AstNode, ctx:GeneratorContext) => {
const el = UseComponentEL as UseComponent;
const componentNode = new CompositeGeneratorNode()
const refContent = el.component.ref?.content as SimpleUi
const refParameters = (refContent.$container as Component).parameters;
const refParameters = (refContent.$container as Component).parameters;
const argumentList = refParameters.map(function (refEl: Parameter, index:integer) {
return ({name: refEl.name, type: refEl.type, value: generateExpression(el.arguments[index], ctx)})
})
ctx.argumentStack.push(argumentList)
generateComponent(refContent, componentNode, ctx)
ctx.argumentStack.pop()
return componentNode
ctx.argumentStack.push(argumentList);
generateComponent(refContent, componentNode, ctx);
ctx.argumentStack.pop();
return componentNode;
}

const topbarFunc = (TopbarEl: AstNode, ctx:GeneratorContext) => {
Expand Down Expand Up @@ -322,14 +322,13 @@ export function generateBody(model: SimpleUi, bodyNode: CompositeGeneratorNode,
if(isInstance) {
const func = generateBodyFunctions[t];
if(func) {
const content = func(el, ctx);
const content = func(el, ctx);
bodyNode.append(content, NL);
}
}
})
})
}

// Check for Type and call body functions
export function generateComponent(model: SimpleUi, bodyNode: CompositeGeneratorNode, ctx:GeneratorContext) {
const suiTypes = reflection.getAllTypes();
Expand All @@ -340,7 +339,7 @@ export function generateComponent(model: SimpleUi, bodyNode: CompositeGeneratorN
if(isInstance) {
const func = generateBodyFunctions[t];
if(func) {
const content = func(el, ctx);
const content = func(el, ctx);
bodyNode.append(content, NL);
}
}
Expand Down
7 changes: 5 additions & 2 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import colors from 'colors';

import { Command } from 'commander';
import { SimpleUiLanguageMetaData } from '../language-server/generated/module';
import { SimpleUi } from '../language-server/generated/ast';
import { createSimpleUiServices } from '../language-server/simple-ui-module';
import { extractAstNode } from './cli-util';
import { extractAstNode, setRootFolder } from './cli-util';
import { generateHTML } from './generator-html';
import { generateCSS } from './generator-css';
import { generateJS } from './generator-js';
Expand All @@ -20,7 +21,9 @@ program
.option('-d, --destination <dir>', 'destination directory of generating')
.description('generates HTML code based on the input')
.action(async (fileName: string, opts: GenerateOptions) => {
const model = await extractAstNode<SimpleUi>(fileName, SimpleUiLanguageMetaData.fileExtensions, createSimpleUiServices().simpleUi);
let simpleUi = createSimpleUiServices().simpleUi;
await setRootFolder(fileName, simpleUi);
const model = await extractAstNode<SimpleUi>(fileName, SimpleUiLanguageMetaData.fileExtensions, simpleUi);
const generatedHTMLFilePath = generateHTML(model, fileName, opts.destination);
const generatedCSSFilePath = generateCSS(model, fileName, opts.destination);
const generatedJSFilePath = generateJS(model, fileName, opts.destination);
Expand Down
30 changes: 22 additions & 8 deletions src/language-server/simple-ui-validator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ValidationAcceptor, ValidationCheck, ValidationRegistry } from 'langium';
import { SimpleUi, SimpleUIAstType, UseComponent, Component, isStringExpression, isNumberExpression, Button, Heading } from './generated/ast';
import { SimpleUi, SimpleUIAstType, UseComponent, Component, isStringExpression, isNumberExpression, Button, Heading, Import } from './generated/ast';
import { SimpleUiServices } from './simple-ui-module';
import fs from 'fs';

/**
* Map AST node types to validation checks.
Expand All @@ -16,6 +17,7 @@ export class SimpleUiValidationRegistry extends ValidationRegistry {
const validator = services.validation.SimpleUiValidator;
const checks: SimpleUiChecks = {
UseComponent: validator.checkUseComponent,
Import: validator.checkImportFile,
Button: validator.checkButton,
Heading: validator.checkHeadingLevel
};
Expand All @@ -31,7 +33,7 @@ export class SimpleUiValidator {
const refContent = el.component.ref?.content as SimpleUi
const refParameters = (refContent.$container as Component).parameters;
if (el.arguments.length !== refParameters?.length) {
accept('error', `Number of parameters not matching (${el.arguments.length}), expected (${refParameters?.length}).`, {node: el, property: 'arguments'})
accept('error', `Error: Number of parameters not matching (${el.arguments.length}), expected (${refParameters?.length}).`, {node: el, property: 'arguments'})
} else {
// Check type of parameters
el.arguments.forEach(function (el, index) {
Expand All @@ -40,7 +42,7 @@ export class SimpleUiValidator {
return
}
else {
accept('error', `Wrong parameter type 'number', expected parameter of type '${refParameters[index].type}'.`, { node: el, property: 'value'})
accept('error', `Error: Wrong parameter type 'number', expected parameter of type '${refParameters[index].type}'.`, { node: el, property: 'value'})
return
}
}
Expand All @@ -49,26 +51,38 @@ export class SimpleUiValidator {
return
}
else {
accept('error', `Wrong parameter type 'string', expected parameter of type '${refParameters[index].type}'.`, { node: el, property: 'value'});
accept('error', `Error: Wrong parameter type 'string', expected parameter of type '${refParameters[index].type}'.`, { node: el, property: 'value'});
return
}
}
})
}
}
checkImportFile(el: Import, accept: ValidationAcceptor): void {
el.filenames.forEach((filename, index) => {
if(el.filenames.includes(filename, index + 1)) {
accept('warning', `Warning: Multiple import is not necessary: '${filename}'.`, { node: el, property: 'filenames'});
}
filename += ".sui";
if(!fs.existsSync(filename)) {
accept('error', `Error: File was not found '${filename}'.`, { node: el, property: 'filenames'});
return
}
});
}
checkButton(el: Button, accept: ValidationAcceptor): void {
const refParameters = el.onclickaction?.ref?.parameters
// Check for the same number of parameters
if (el.arguments.length !== refParameters?.length) {
accept('error', `Number of parameters not matching (${el.arguments.length}), expected (${refParameters?.length}).`, {node: el, property: 'arguments'})
accept('error', `Error: Number of parameters not matching (${el.arguments.length}), expected (${refParameters?.length}).`, {node: el, property: 'arguments'})
} else {
// Check type of parameters
el.arguments.forEach(function (el, index) {
if (isNumberExpression(el)) {
if (refParameters![index].type === 'number') {
return
} else {
accept('error', `Wrong parameter type 'number', expected parameter of type '${refParameters![index].type}'.`, {node: el, property: 'value'})
accept('error', `Error: Wrong parameter type 'number', expected parameter of type '${refParameters![index].type}'.`, {node: el, property: 'value'})
return
}
}
Expand All @@ -77,15 +91,15 @@ export class SimpleUiValidator {
return
}
else {
accept('error', `Wrong parameter type 'string', expected parameter of type '${refParameters![index].type}'.`, { node: el, property: 'value'});
accept('error', `Error: Wrong parameter type 'string', expected parameter of type '${refParameters![index].type}'.`, { node: el, property: 'value'});
}
}
})
}
}
checkHeadingLevel(el: Heading, accept: ValidationAcceptor): void {
if (el.level > 6 || el.level < 1) {
accept('error', `Wrong headinglevel ${el.level}, expected value between 1 and 6.`, { node: el, property: 'level' })
accept('error', `Error: Wrong headinglevel ${el.level}, expected value between 1 and 6.`, { node: el, property: 'level' })
}
else {
return
Expand Down