diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7d869c719..da4f9cff8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -41,4 +41,5 @@ jobs: run: npx semantic-release env: GITHUB_TOKEN: ${{ secrets.PAT || secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} VSCE_PAT: ${{ secrets.VSCE_PAT }} diff --git a/package-lock.json b/package-lock.json index 085ee27da..d59c38f94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12645,8 +12645,7 @@ "chalk": "^5.3.0", "commander": "^11.1.0", "esbuild": "^0.19.5", - "langium": "^2.0.2", - "safe-ds": "^0.2.0" + "langium": "^2.0.2" }, "bin": { "safe-ds": "bin/cli" diff --git a/packages/safe-ds-cli/README.md b/packages/safe-ds-cli/README.md index 1a6b3867a..af5116859 100644 --- a/packages/safe-ds-cli/README.md +++ b/packages/safe-ds-cli/README.md @@ -1 +1,13 @@ # Safe-DS CLI + +```txt +Usage: cli [options] [command] + +Options: +-V, --version output the version number +-h, --help display help for command + +Commands: +generate [options] generate Python code +help [command] display help for command +``` diff --git a/packages/safe-ds-cli/esbuild.mjs b/packages/safe-ds-cli/esbuild.mjs index dbb3cba65..a03bc5479 100644 --- a/packages/safe-ds-cli/esbuild.mjs +++ b/packages/safe-ds-cli/esbuild.mjs @@ -39,7 +39,6 @@ const ctx = await esbuild.context({ '.js': '.cjs', }, loader: { '.ts': 'ts' }, - external: ['vscode'], platform: 'node', sourcemap: !minify, minify, diff --git a/packages/safe-ds-cli/package.json b/packages/safe-ds-cli/package.json index a5121c35f..f4d50f2a6 100644 --- a/packages/safe-ds-cli/package.json +++ b/packages/safe-ds-cli/package.json @@ -1,7 +1,6 @@ { "name": "@safe-ds/cli", - "version": "0.2.0", - "private": true, + "version": "0.2.2", "description": "A command line interface for the Safe-DS DSL.", "author": { "name": "Lars Reimann", @@ -26,22 +25,20 @@ }, "type": "module", "bin": { - "safe-ds": "./bin/cli" + "safe-ds": "./bin/cli.js" }, "exports": null, "files": [ "bin", - "dist", - "src" + "dist" ], "scripts": { "clean": "shx rm -rf dist lib tsconfig.tsbuildinfo", "build": "tsc -b tsconfig.json && node esbuild.mjs", "build:clean": "npm run clean && npm run build", - "watch": "concurrently -n tsc,esbuild -c blue,yellow \"tsc -b tsconfig.json --watch\" \"node esbuild.mjs --watch\"", - "start": "node ./bin/cli" + "watch": "concurrently -n tsc,esbuild -c blue,yellow \"tsc -b tsconfig.json --watch\" \"node esbuild.mjs --watch\"" }, - "dependencies": { + "devDependencies": { "chalk": "^5.3.0", "commander": "^11.1.0", "esbuild": "^0.19.5", diff --git a/packages/safe-ds-cli/src/generate.ts b/packages/safe-ds-cli/src/generate.ts index fa62be3f1..4cd1446e3 100644 --- a/packages/safe-ds-cli/src/generate.ts +++ b/packages/safe-ds-cli/src/generate.ts @@ -10,12 +10,12 @@ import { createSafeDsServices } from 'safe-ds'; export const generate = async (fileName: string, opts: GenerateOptions): Promise => { const services = createSafeDsServices(NodeFileSystem).SafeDs; const document = await extractDocument(fileName, services); - const generatedFiles = services.generation.PythonGenerator.generate(document, opts.destination); + const destination = opts.destination ?? path.join(path.dirname(fileName), 'generated'); + const generatedFiles = services.generation.PythonGenerator.generate(document, URI.file(path.resolve(destination))); for (const file of generatedFiles) { const fsPath = URI.parse(file.uri).fsPath; const parentDirectoryPath = path.dirname(fsPath); - if (!fs.existsSync(parentDirectoryPath)) { fs.mkdirSync(parentDirectoryPath, { recursive: true }); } diff --git a/packages/safe-ds-vscode/src/language/generation/safe-ds-python-generator.ts b/packages/safe-ds-vscode/src/language/generation/safe-ds-python-generator.ts index bbdc3f674..fe630fd0d 100644 --- a/packages/safe-ds-vscode/src/language/generation/safe-ds-python-generator.ts +++ b/packages/safe-ds-vscode/src/language/generation/safe-ds-python-generator.ts @@ -100,7 +100,7 @@ export class SafeDsPythonGenerator { this.partialEvaluator = services.evaluation.PartialEvaluator; } - generate(document: LangiumDocument, destination: string | undefined): TextDocument[] { + generate(document: LangiumDocument, destination: URI): TextDocument[] { const node = document.parseResult.value; // Do not generate stub files @@ -108,24 +108,23 @@ export class SafeDsPythonGenerator { return []; } - const filePath = document.uri.fsPath; - const data = extractDestinationAndName(filePath, destination); + const name = path.parse(document.uri.fsPath).name; const pythonModuleName = this.builtinAnnotations.getPythonModule(node); const packagePath = pythonModuleName === undefined ? node.name.split('.') : [pythonModuleName]; - const parentDirectoryPath = path.join(data.destination, ...packagePath); + const parentDirectoryPath = path.join(destination.fsPath, ...packagePath); const generatedFiles = new Map(); generatedFiles.set( - `${path.join(parentDirectoryPath, this.formatGeneratedFileName(data.name))}.py`, + `${path.join(parentDirectoryPath, this.formatGeneratedFileName(name))}.py`, this.generateModule(node), ); for (const pipeline of streamAllContents(node).filter(isSdsPipeline)) { const entryPointFilename = `${path.join( parentDirectoryPath, - `${this.formatGeneratedFileName(data.name)}_${this.getPythonNameOrDefault(pipeline)}`, + `${this.formatGeneratedFileName(name)}_${this.getPythonNameOrDefault(pipeline)}`, )}.py`; const entryPointContent = expandToStringWithNL`from ${this.formatGeneratedFileName( - data.name, + name, )} import ${this.getPythonNameOrDefault( pipeline, )}\n\nif __name__ == '__main__':\n${PYTHON_INDENT}${this.getPythonNameOrDefault(pipeline)}()`; @@ -600,16 +599,3 @@ class GenerationInfoFrame { return `${BLOCK_LAMBDA_PREFIX}${this.blockLambdaManager.assignId(lambda)}`; } } - -interface FilePathData { - destination: string; - name: string; -} - -const extractDestinationAndName = function (filePath: string, destination: string | undefined): FilePathData { - const baseFilePath = path.basename(filePath, path.extname(filePath)).replace(/[.-]/gu, ''); - return { - destination: destination ?? path.join(path.dirname(baseFilePath), 'generated'), - name: path.basename(baseFilePath), - }; -}; diff --git a/packages/safe-ds-vscode/tests/language/generation/testGeneration.test.ts b/packages/safe-ds-vscode/tests/language/generation/testGeneration.test.ts index 2b6e6393e..b5b700314 100644 --- a/packages/safe-ds-vscode/tests/language/generation/testGeneration.test.ts +++ b/packages/safe-ds-vscode/tests/language/generation/testGeneration.test.ts @@ -31,7 +31,7 @@ describe('generation', async () => { // Generate code for all documents const actualOutputs = stream(documents) - .flatMap((document) => pythonGenerator.generate(document, test.actualOutputRoot.fsPath)) + .flatMap((document) => pythonGenerator.generate(document, test.actualOutputRoot)) .map((textDocument) => [textDocument.uri, textDocument.getText()]) .toMap( (entry) => entry[0],