Skip to content
Merged
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
20 changes: 7 additions & 13 deletions src/language/commands/GeneratorCommandExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,40 +14,34 @@ export class GeneratorCommandExecutor {
this.serviceRegistry = serviceRegistry
}

async execute (generator: ContextMapperGenerator, args: unknown[], cancelToken: CancellationToken): Promise<string[] | undefined> {
async execute (generator: ContextMapperGenerator, args: unknown[], cancelToken: CancellationToken): Promise<string[]> {
const filePath = args[0] as string

const model = await this.extractModel(filePath)
if (cancelToken.isCancellationRequested) {
return undefined
return []
}

if (model == null) {
return undefined
}
args.shift()
args.shift() // remove source file from args array
return await generator.generate(model, filePath, args, cancelToken)
}

private async extractModel (filePath: string): Promise<ContextMappingModel | undefined> {
private async extractModel (filePath: string): Promise<ContextMappingModel> {
const extensions = ContextMapperDslLanguageMetaData.fileExtensions as readonly string[]
if (!extensions.includes(path.extname(filePath))) {
console.error('Unsupported file extension on file', filePath)
return undefined
throw new Error(`Unsupported file extension on file ${filePath}`)
}

if (!fs.existsSync(filePath)) {
console.error(`File ${filePath} does not exist.`)
return undefined
throw new Error(`File ${filePath} does not exist.`)
}

const document = await this.getServices().shared.workspace.LangiumDocuments.getOrCreateDocument(URI.file(path.resolve(filePath)))
await this.getServices().shared.workspace.DocumentBuilder.build([document], { validation: true })

const validationErrors = (document.diagnostics ?? []).filter(e => e.severity === 1)
if (validationErrors.length > 0) {
console.error(`File ${filePath} is invalid`)
return undefined
throw new Error(`File ${filePath} is invalid`)
}

return document.parseResult.value as ContextMappingModel
Expand Down
2 changes: 1 addition & 1 deletion src/language/commands/generators/ContextMapperGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import { ContextMappingModel } from '../../generated/ast.js'
import { CancellationToken } from 'vscode-languageserver'

export interface ContextMapperGenerator {
generate(model: ContextMappingModel, filePath: string, args: unknown[], cancelToken: CancellationToken): Promise<string[] | undefined>
generate(model: ContextMappingModel, filePath: string, args: unknown[], cancelToken: CancellationToken): Promise<string[]>
}
7 changes: 3 additions & 4 deletions src/language/commands/generators/PlantUMLGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ import { ComponentDiagramGenerator } from './plantuml/ComponentDiagramGenerator.
import { CancellationToken } from 'vscode-languageserver'

export class PlantUMLGenerator implements ContextMapperGenerator {
async generate (model: ContextMappingModel, filePath: string, args: unknown[], cancelToken: CancellationToken): Promise<string[] | undefined> {
async generate (model: ContextMappingModel, filePath: string, args: unknown[], cancelToken: CancellationToken): Promise<string[]> {
// there must not be any extra spaces especially at the start, since the path will be treated as relative otherwise
const destination = (args[0] as string)?.trim()
if (destination == null || destination === '') {
console.log('Destination must be specified')
return undefined
throw Error('Destination must be specified')
}

if (cancelToken.isCancellationRequested) {
return undefined
return []
}
const fileName = filePath.split('/').pop()!.split('.')[0]

Expand All @@ -30,7 +30,6 @@ export class PlantUMLGenerator implements ContextMapperGenerator {
diagrams.push(componentDiagram)
}

console.log('Successfully generated PlantUML diagrams')
return diagrams
}

Expand Down
25 changes: 19 additions & 6 deletions test/commands/CommandExecution.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { afterEach, beforeAll, describe, expect, test } from 'vitest'
import { NodeFileSystem } from 'langium/node'
import fs from 'node:fs'
import path from 'node:path'
import { fail } from 'node:assert'

const outDir = path.join(__dirname, 'out')

Expand Down Expand Up @@ -38,8 +39,12 @@ describe('Command execution tests', () => {
test('test plantUML command with invalid file extension', async () => {
const file = path.join(__dirname, '..', 'invalid-files', 'test.txt')

const result = await commandHandler.executeCommand('org.contextmapper.GeneratePlantUML', [file, outDir])
expect(result).toBeUndefined()
try {
await commandHandler.executeCommand('org.contextmapper.GeneratePlantUML', [file, outDir])
fail('Expected generator to fail')
} catch (e) {
expect(e).not.toBeUndefined()
}

const outContentExists = fs.existsSync(outDir)
expect(outContentExists).toEqual(false)
Expand All @@ -48,8 +53,12 @@ describe('Command execution tests', () => {
test('test plantUML command with invalid file', async () => {
const file = path.join(__dirname, '..', 'invalid-files', 'invalid.cml')

const result = await commandHandler.executeCommand('org.contextmapper.GeneratePlantUML', [file, outDir])
expect(result).toBeUndefined()
try {
await commandHandler.executeCommand('org.contextmapper.GeneratePlantUML', [file, outDir])
fail('Expected generator to fail')
} catch (e) {
expect(e).not.toBeUndefined()
}

const outContentExists = fs.existsSync(outDir)
expect(outContentExists).toEqual(false)
Expand All @@ -58,8 +67,12 @@ describe('Command execution tests', () => {
test('test plantUML command with non-existing file', async () => {
const file = path.join(__dirname, '..', 'invalid-files', 'non-existing.cml')

const result = await commandHandler.executeCommand('org.contextmapper.GeneratePlantUML', [file, outDir])
expect(result).toBeUndefined()
try {
await commandHandler.executeCommand('org.contextmapper.GeneratePlantUML', [file, outDir])
fail('Expected generator to fail')
} catch (e) {
expect(e).not.toBeUndefined()
}

const outContentExists = fs.existsSync(outDir)
expect(outContentExists).toEqual(false)
Expand Down
Loading