-
Notifications
You must be signed in to change notification settings - Fork 30
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
VS Code DSCv3 completion provider #448
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} | ||
} | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" | ||
} | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"editor.insertSpaces": true | ||
} | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} | ||
} | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <EnlistmentRoot>\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` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm going to suggest that this belongs in a separate repo from DSC in order to make building and releasing easier...are there any good reasons not to do that? |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We probably don't want it to activate for all YAML files so we'll want to figure out how to scope it to DSCv3 resources. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Say There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually I think we'd want to define
and then this would be |
||
], | ||
"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" | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From my construction of https://github.com/microsoft/vscode-azurearcenabledmachines we can review and pull in a few more settings before getting this published as a preview. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. E.g. publisher is actually an identity and probably |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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:')) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm unsure how VS Code handles filtering provided completions based on partial input (which we're discarding here)...something to look into. Like, are we the provider supposed to filter it or not? |
||
return undefined; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there more completion we want to do in the future, or is after "type:" really the only thing we want to / can provide completions for? |
||
} | ||
|
||
let ps_cache_file_path: string = ''; | ||
if (process.platform==='win32') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's setup ESLint 😆 |
||
{ | ||
ps_cache_file_path = process.env.LocalAppData + '\\dsc\\PSAdapterCache.json'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. JavaScript/TypeScript's got a |
||
} | ||
else | ||
{ | ||
ps_cache_file_path = process.env.HOME + '/.dsc/PSAdapterCache.json'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok so |
||
} | ||
console.log("Using cache path " + ps_cache_file_path); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Before preview release let's get VS Code logging API setup. |
||
|
||
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')); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the reason we made this synchronous? If not let's use |
||
var completions:vscode.CompletionItem[] = []; | ||
dataArray.ResourceCache.forEach(function (resouce: any) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just noting There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's just an optimization but since (to my eye) everything in the lambda is...I don't know, is the word stateless? Not quite idempotent? But like the closure doesn't mutate anything, so we could fire all these completion builders off at once with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok so technically you're pushing onto |
||
|
||
const all_props_completion = new vscode.CompletionItem(resouce.Type); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we specify a kind for the completion items? (One of these: https://vscode-api.js.org/enums/vscode.CompletionItemKind.html) |
||
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 + ': '; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you want, it's probably a lot more readable to write this snippet as multiple strings ("which will be joined as multiple lines upon insertion") and is there any insertions or variables we might want to provide inside the completion snippet? https://code.visualstudio.com/docs/editor/userdefinedsnippets#_create-your-own-snippets |
||
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); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"compilerOptions": { | ||
"module": "commonjs", | ||
"target": "es2020", | ||
"lib": ["es2020"], | ||
"outDir": "out", | ||
"sourceMap": true, | ||
"strict": true, | ||
"rootDir": "src" | ||
}, | ||
"exclude": [ | ||
"node_modules", | ||
".vscode-test" | ||
] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can remove this and just set a personal preference. The default indentation detection should just take care of it.