diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..af515502 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + + // List of extensions which should be recommended for users of this workspace. + "recommendations": [ + "dbaeumer.vscode-eslint" + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..241aa6d9 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,20 @@ +// See https://go.microsoft.com/fwlink/?LinkId=733558 +// for the documentation about the tasks.json format +{ + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "watch", + "problemMatcher": "$tsc-watch", + "isBackground": true, + "presentation": { + "reveal": "never" + }, + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} \ No newline at end of file diff --git a/vscode/DscExt/.vscode/extensions.json b/vscode/DscExt/.vscode/extensions.json new file mode 100644 index 00000000..af515502 --- /dev/null +++ b/vscode/DscExt/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + + // List of extensions which should be recommended for users of this workspace. + "recommendations": [ + "dbaeumer.vscode-eslint" + ] +} \ No newline at end of file diff --git a/vscode/DscExt/.vscode/launch.json b/vscode/DscExt/.vscode/launch.json new file mode 100644 index 00000000..e9e60976 --- /dev/null +++ b/vscode/DscExt/.vscode/launch.json @@ -0,0 +1,22 @@ +// A launch configuration that compiles the extension and then opens it inside a new window +// Use IntelliSense to learn about possible attributes. +// Hover to view descriptions of existing attributes. +// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Run Extension", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}" + ], + "outFiles": [ + "${workspaceFolder}/out/**/*.js" + ], + "preLaunchTask": "npm: watch" + } + ] +} diff --git a/vscode/DscExt/.vscode/settings.json b/vscode/DscExt/.vscode/settings.json new file mode 100644 index 00000000..9ff231af --- /dev/null +++ b/vscode/DscExt/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.insertSpaces": true +} \ No newline at end of file diff --git a/vscode/DscExt/.vscode/tasks.json b/vscode/DscExt/.vscode/tasks.json new file mode 100644 index 00000000..241aa6d9 --- /dev/null +++ b/vscode/DscExt/.vscode/tasks.json @@ -0,0 +1,20 @@ +// See https://go.microsoft.com/fwlink/?LinkId=733558 +// for the documentation about the tasks.json format +{ + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "watch", + "problemMatcher": "$tsc-watch", + "isBackground": true, + "presentation": { + "reveal": "never" + }, + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} \ No newline at end of file diff --git a/vscode/DscExt/LICENSE b/vscode/DscExt/LICENSE new file mode 100644 index 00000000..b2f52a2b --- /dev/null +++ b/vscode/DscExt/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) Microsoft Corporation. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vscode/DscExt/README.md b/vscode/DscExt/README.md new file mode 100644 index 00000000..e435031c --- /dev/null +++ b/vscode/DscExt/README.md @@ -0,0 +1,25 @@ +# DSCv3 extension + +This is a prototype VS Code DSCv3 completion provider. +Completions are displayed when `type:` is typed in a `*.dsc.yaml` files. +This requires latest dsc build from `main` branch and relies on PS Adapter cache, which can be generated by `dsc resource list * -a Microsoft.DSC/PowerShell`. + +### Build +1) Make sure you have Node.js installed. +2) `npm install -g @vscode/vsce` +3) `cd \vscode\DscExt` +4) `vsce package` +5) `dscv3*.vsix` generated + +### Install + +To install a .vsix file in VS Code: + +1) Go to the Extensions view. +2) Click Views and More Actions... +3) Select Install from VSIX... + +or + +in your terminal, run: +`code --install-extension dscv3-completion-provider-0.0.1.vsix` \ No newline at end of file diff --git a/vscode/DscExt/package.json b/vscode/DscExt/package.json new file mode 100644 index 00000000..d37eed25 --- /dev/null +++ b/vscode/DscExt/package.json @@ -0,0 +1,36 @@ +{ + "name": "dscv3-completion-provider", + "displayName": "DSCv3 Completion Provider", + "version": "0.0.1", + "publisher": "Microsoft", + "private": true, + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/PowerShell/DSC" + }, + "engines": { + "vscode": "^1.73.0" + }, + "categories": [ + "Other" + ], + "activationEvents": [ + "onLanguage:yaml" + ], + "main": "./out/extension.js", + "scripts": { + "vscode:prepublish": "npm run compile", + "compile": "tsc -p ./", + "lint": "eslint \"src/**/*.ts\"", + "watch": "tsc -watch -p ./" + }, + "devDependencies": { + "@types/node": "^18", + "@types/vscode": "^1.73.0", + "@typescript-eslint/eslint-plugin": "^6.7.0", + "@typescript-eslint/parser": "^6.7.0", + "eslint": "^8.26.0", + "typescript": "^5.4.2" + } +} diff --git a/vscode/DscExt/src/extension.ts b/vscode/DscExt/src/extension.ts new file mode 100644 index 00000000..d98b1790 --- /dev/null +++ b/vscode/DscExt/src/extension.ts @@ -0,0 +1,67 @@ +/*--------------------------------------------------------- + * Copyright (C) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import * as fs from 'fs'; + +export function activate(context: vscode.ExtensionContext) { + + const dsc_type_provider = vscode.languages.registerCompletionItemProvider({ language: 'yaml', pattern: '**/*.dsc.yaml' }, + { + provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) { + + const linePrefix = document.lineAt(position).text.slice(0, position.character); + if (!linePrefix.endsWith('type:')) { + return undefined; + } + + let ps_cache_file_path: string = ''; + if (process.platform==='win32') + { + ps_cache_file_path = process.env.LocalAppData + '\\dsc\\PSAdapterCache.json'; + } + else + { + ps_cache_file_path = process.env.HOME + '/.dsc/PSAdapterCache.json'; + } + console.log("Using cache path " + ps_cache_file_path); + + if (!fs.existsSync(ps_cache_file_path)) { + console.log("Cache file does not exist"); + return []; + } + + const dataArray = JSON.parse(fs.readFileSync(ps_cache_file_path, 'utf-8')); + var completions:vscode.CompletionItem[] = []; + dataArray.ResourceCache.forEach(function (resouce: any) { + + const all_props_completion = new vscode.CompletionItem(resouce.Type); + const key_props_completion = new vscode.CompletionItem(resouce.Type + " [keys only]"); + + let all_props_comp_text: string = ' ' + resouce.Type; + let key_props_comp_text: string = ' ' + resouce.Type; + all_props_comp_text += '\nproperties:'; + key_props_comp_text += '\nproperties:'; + resouce.DscResourceInfo.Properties.forEach(function (prop: any) { + all_props_comp_text += '\n ' + prop.Name + ': '; + if (prop.IsMandatory) + { + key_props_comp_text += '\n ' + prop.Name + ': '; + } + }); + all_props_completion.insertText = new vscode.SnippetString(all_props_comp_text); + key_props_completion.insertText = new vscode.SnippetString(key_props_comp_text); + + completions.push(all_props_completion); + completions.push(key_props_completion); + }); + + return completions; + } + }, + ':' // triggered whenever a ':' is being typed + ); + + context.subscriptions.push(dsc_type_provider); +} diff --git a/vscode/DscExt/tsconfig.json b/vscode/DscExt/tsconfig.json new file mode 100644 index 00000000..bbe3dc3c --- /dev/null +++ b/vscode/DscExt/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2020", + "lib": ["es2020"], + "outDir": "out", + "sourceMap": true, + "strict": true, + "rootDir": "src" + }, + "exclude": [ + "node_modules", + ".vscode-test" + ] +}