diff --git a/.vscode/settings.json b/.vscode/settings.json index c8bb013..7df28c7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -32,5 +32,6 @@ "PATH": "/usr/local/opt/llvm/bin/:$PATH", "CC": "/usr/local/opt/llvm/bin/clang", "AR": "/usr/local/opt/llvm/bin/llvm-ar" - } + }, + "git.alwaysSignOff": true } diff --git a/CHANGELOG.md b/CHANGELOG.md index eb8e783..c1176db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## v0.7.5 (Pre-release) 2024-05-17 + +- Update to Cedar 3.1.4 +- Fix human-readable schema display bugs + ## v0.7.4 (Pre-release) 2024-04-26 - Problems contain additional help text diff --git a/package-lock.json b/package-lock.json index 4ac8dbe..26c04c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vscode-cedar", - "version": "0.7.4", + "version": "0.7.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vscode-cedar", - "version": "0.7.4", + "version": "0.7.5", "license": "Apache-2.0", "dependencies": { "jsonc-parser": "^3.2.1", @@ -19,8 +19,8 @@ "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", "@vscode/test-cli": "^0.0.4", - "@vscode/test-electron": "^2.3.9", - "@vscode/vsce": "^2.26.0", + "@vscode/test-electron": "^2.3.10", + "@vscode/vsce": "^2.26.1", "eslint": "^8.57.0", "js-yaml": "^4.1.0", "mocha": "^10.4.0", @@ -30,15 +30,6 @@ "vscode": "^1.82.0" } }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@azure/abort-controller": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz", @@ -108,15 +99,15 @@ } }, "node_modules/@azure/core-rest-pipeline": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.15.2.tgz", - "integrity": "sha512-BmWfpjc/QXc2ipHOh6LbUzp3ONCaa6xzIssTU0DwH9bbYNXJlGUL6tujx5TrbVd/QQknmS+vlQJGrCq2oL1gZA==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.16.0.tgz", + "integrity": "sha512-CeuTvsXxCUmEuxH5g/aceuSl6w2EugvNHKAtKKVdiX915EjJJxAwfzNNWZreNnbxHZ2fi0zaM6wwS23x2JVqSQ==", "dev": true, "dependencies": { "@azure/abort-controller": "^2.0.0", "@azure/core-auth": "^1.4.0", "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.3.0", + "@azure/core-util": "^1.9.0", "@azure/logger": "^1.0.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", @@ -214,9 +205,9 @@ } }, "node_modules/@azure/identity": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.1.0.tgz", - "integrity": "sha512-BhYkF8Xr2gXjyDxocm0pc9RI5J5a1jw8iW0dw6Bx95OGdYbuMyFZrrwNw4eYSqQ2BB6FZOqpJP3vjsAqRcvDhw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.2.0.tgz", + "integrity": "sha512-ve3aYv79qXOJ8wRxQ5jO0eIz2DZ4o0TyME4m4vlGV5YyePddVZ+pFMzusAMODNAflYAAv1cBIhKnd4xytmXyig==", "dev": true, "dependencies": { "@azure/abort-controller": "^1.0.0", @@ -251,33 +242,33 @@ } }, "node_modules/@azure/msal-browser": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.13.0.tgz", - "integrity": "sha512-fD906nmJei3yE7la6DZTdUtXKvpwzJURkfsiz9747Icv4pit77cegSm6prJTKLQ1fw4iiZzrrWwxnhMLrTf5gQ==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.14.0.tgz", + "integrity": "sha512-Un85LhOoecJ3HDTS3Uv3UWnXC9/43ZSO+Kc+anSqpZvcEt58SiO/3DuVCAe1A3I5UIBYJNMgTmZPGXQ0MVYrwA==", "dev": true, "dependencies": { - "@azure/msal-common": "14.9.0" + "@azure/msal-common": "14.10.0" }, "engines": { "node": ">=0.8.0" } }, "node_modules/@azure/msal-common": { - "version": "14.9.0", - "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.9.0.tgz", - "integrity": "sha512-yzBPRlWPnTBeixxLNI3BBIgF5/bHpbhoRVuuDBnYjCyWRavaPUsKAHUDYLqpGkBLDciA6TCc6GOxN4/S3WiSxg==", + "version": "14.10.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.10.0.tgz", + "integrity": "sha512-Zk6DPDz7e1wPgLoLgAp0349Yay9RvcjPM5We/ehuenDNsz/t9QEFI7tRoHpp/e47I4p20XE3FiDlhKwAo3utDA==", "dev": true, "engines": { "node": ">=0.8.0" } }, "node_modules/@azure/msal-node": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.7.0.tgz", - "integrity": "sha512-wXD8LkUvHICeSWZydqg6o8Yvv+grlBEcmLGu+QEI4FcwFendbTEZrlSygnAXXSOCVaGAirWLchca35qrgpO6Jw==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.8.1.tgz", + "integrity": "sha512-VcZZM+5VvCWRBTOF7SxMKaxrz+EXjntx2u5AQe7QE06e6FuPJElGBrImgNgCh5QmFaNCfVFO+3qNR7UoFD/Gfw==", "dev": true, "dependencies": { - "@azure/msal-common": "14.9.0", + "@azure/msal-common": "14.10.0", "jsonwebtoken": "^9.0.0", "uuid": "^8.3.0" }, @@ -759,9 +750,9 @@ } }, "node_modules/@vscode/test-electron": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.9.tgz", - "integrity": "sha512-z3eiChaCQXMqBnk2aHHSEkobmC2VRalFQN0ApOAtydL172zXGxTwGrRtviT5HnUB+Q+G3vtEYFtuQkYqBzYgMA==", + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.10.tgz", + "integrity": "sha512-FxMqrvUm6a8S5tP4CymNJ40e6kD+wUTWTc6K32U629yrCCa+kl/rmpkC2gKpN4F4zjg1r+0Hnk9sl0+N2atsYA==", "dev": true, "dependencies": { "http-proxy-agent": "^4.0.1", @@ -774,9 +765,9 @@ } }, "node_modules/@vscode/vsce": { - "version": "2.26.0", - "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.26.0.tgz", - "integrity": "sha512-v54ltgMzUG8lGY0kAgaOlry57xse1RlWzes9FotfGEx+Fr05KeR8rZicQzEMDmi9QnOgVWHuiEq+xA2HWkAz+Q==", + "version": "2.26.1", + "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.26.1.tgz", + "integrity": "sha512-QOG6Ht7V93nhwcBxPWcG33UK0qDGEoJdg0xtVeaTN27W6PGdMJUJGTPhB/sNHUIFKwvwzv/zMAHvDgMNXbcwlA==", "dev": true, "dependencies": { "@azure/identity": "^4.1.0", @@ -1337,9 +1328,9 @@ } }, "node_modules/cockatiel": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/cockatiel/-/cockatiel-3.1.2.tgz", - "integrity": "sha512-5yARKww0dWyWg2/3xZeXgoxjHLwpVqFptj9Zy7qioJ6+/L0ARM184sgMUrQDjxw7ePJWlGhV998mKhzrxT0/Kg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/cockatiel/-/cockatiel-3.1.3.tgz", + "integrity": "sha512-xC759TpZ69d7HhfDp8m2WkRwEUiCkxY8Ee2OQH/3H6zmy2D/5Sm+zSTbPRa+V2QyjDtpMvjOIAOVjA2gp6N1kQ==", "dev": true, "engines": { "node": ">=16" @@ -2251,22 +2242,22 @@ "optional": true }, "node_modules/glob": { - "version": "10.3.12", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", - "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", + "version": "10.3.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.15.tgz", + "integrity": "sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^2.3.6", "minimatch": "^9.0.1", "minipass": "^7.0.4", - "path-scurry": "^1.10.2" + "path-scurry": "^1.11.0" }, "bin": { "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -3141,9 +3132,9 @@ } }, "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.1.tgz", + "integrity": "sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==", "dev": true, "engines": { "node": ">=16 || 14 >=14.17" @@ -3498,17 +3489,17 @@ } }, "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -3633,25 +3624,25 @@ } }, "node_modules/path-scurry": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", - "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.1.tgz", - "integrity": "sha512-tS24spDe/zXhWbNPErCHs/AGOzbKGHT+ybSBqmdLm8WZ1xXLWvH8Qn71QPAlqVhd0qUTWjy+Kl9JmISgDdEjsA==", + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", "dev": true, "engines": { "node": "14 || >=16.14" @@ -3996,13 +3987,10 @@ "dev": true }, "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -4518,6 +4506,15 @@ "node": ">= 8" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/workerpool": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", @@ -4796,9 +4793,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "vscode-cedar-wasm/pkg": { - "version": "0.7.3", - "license": "SEE LICENSE IN LICENSE" - } + "vscode-cedar-wasm/pkg": {} } } diff --git a/package.json b/package.json index 7cc7fe5..f086165 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "url": "https://github.com/cedar-policy/vscode-cedar/issues" }, "qna": "https://github.com/cedar-policy/vscode-cedar/issues", - "version": "0.7.4", + "version": "0.7.5", "preview": true, "icon": "icons/cedar-policy.png", "engines": { @@ -92,6 +92,11 @@ "category": "Cedar", "title": "About Cedar extension" }, + { + "command": "cedar.documentation", + "category": "Cedar", + "title": "Open docs.cedarpolicy.com" + }, { "command": "cedar.export", "category": "Cedar", @@ -270,8 +275,8 @@ "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", "@vscode/test-cli": "^0.0.4", - "@vscode/test-electron": "^2.3.9", - "@vscode/vsce": "^2.26.0", + "@vscode/test-electron": "^2.3.10", + "@vscode/vsce": "^2.26.1", "eslint": "^8.57.0", "js-yaml": "^4.1.0", "mocha": "^10.4.0", diff --git a/src/commands.ts b/src/commands.ts index 8e865e9..93aa2c5 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -4,6 +4,7 @@ // strings need to match commands in package.json export const COMMAND_CEDAR_ACTIVATE = 'cedar.activate'; export const COMMAND_CEDAR_ABOUT = 'cedar.about'; +export const COMMAND_CEDAR_DOCUMENTATION = 'cedar.documentation'; export const COMMAND_CEDAR_VALIDATE = 'cedar.validate'; export const COMMAND_CEDAR_EXPORT = 'cedar.export'; export const COMMAND_CEDAR_SCHEMAVALIDATE = 'cedar.schemavalidate'; diff --git a/src/completion.ts b/src/completion.ts index a761d58..d134c86 100644 --- a/src/completion.ts +++ b/src/completion.ts @@ -626,3 +626,183 @@ export class CedarCompletionItemProvider return undefined; } } + +// Cedar schema +export class CedarSchemaCompletionItemProvider + implements vscode.CompletionItemProvider +{ + async provideCompletionItems( + document: vscode.TextDocument, + position: vscode.Position, + token: vscode.CancellationToken, + context: vscode.CompletionContext + ) { + if (context.triggerKind === vscode.CompletionTriggerKind.TriggerCharacter) { + return await this.provideTriggerCharacterCompletionItems( + document, + position, + token, + context + ); + } else if (context.triggerKind === vscode.CompletionTriggerKind.Invoke) { + return await this.provideInvokeCompletionItems( + document, + position, + token, + context + ); + } + + return undefined; + } + + async provideTriggerCharacterCompletionItems( + document: vscode.TextDocument, + position: vscode.Position, + token: vscode.CancellationToken, + context: vscode.CompletionContext + ) { + return undefined; + } + + async provideInvokeCompletionItems( + document: vscode.TextDocument, + position: vscode.Position, + token: vscode.CancellationToken, + context: vscode.CompletionContext + ) { + const lineText = document.lineAt(position).text; + const linePrefix = lineText.substring(0, position.character); + const lineSuffix = lineText.substring(position.character); + const range = new vscode.Range( + new vscode.Position(position.line, position.character - 1), + position + ); + + // some completion items are only suggests at beginning of line + if (position.line === document.lineCount - 1 && linePrefix.length === 1) { + switch (linePrefix) { + case 'n': + return createNamespaceSnippetItems(range); + default: + break; + } + } + + if (linePrefix.trim().length === 1) { + const definitionRanges = parseCedarSchemaDoc(document).definitionRanges; + for (let i = 0; i < definitionRanges.length; i++) { + const definitionRange = definitionRanges[i]; + if (definitionRange.range.contains(position)) { + return undefined; + } + } + switch (linePrefix.trim()) { + case 'a': + return createActionSnippetItems( + range, + linePrefix.substring(0, linePrefix.length - 1) + ); + case 'e': + return createEntitySnippetItems( + range, + linePrefix.substring(0, linePrefix.length - 1) + ); + case 't': + return createTypeSnippetItems( + range, + linePrefix.substring(0, linePrefix.length - 1) + ); + default: + break; + } + } + + return undefined; + } +} + +const createNamespaceSnippetItems = ( + range: vscode.Range +): vscode.CompletionItem[] => { + const item1 = createSnippetItem( + 'namespace', + 'namespace', + new vscode.SnippetString('namespace ${1:NS} {\n' + ' $0' + '\n}'), + range + ); + return [item1]; +}; + +const createTypeSnippetItems = ( + range: vscode.Range, + prefix = ' ' +): vscode.CompletionItem[] => { + const item1 = createSnippetItem( + 'type', + 'type', + new vscode.SnippetString( + ['type ${1:T} = {', ' $0', '};'].join(prefix + '\n') + ), + range + ); + return [item1]; +}; + +const createEntitySnippetItems = ( + range: vscode.Range, + prefix = ' ' +): vscode.CompletionItem[] => { + const item1 = createSnippetItem( + 'entity', + 'entity', + new vscode.SnippetString( + ['entity ${1:E} {', ' $0', '};'].join(prefix + '\n') + ), + range + ); + const item2 = createSnippetItem( + 'entity', + 'entity in', + new vscode.SnippetString( + ['entity ${1:E} in [${2:E}] {', ' $0', '};'].join(prefix + '\n') + ), + range + ); + return [item1, item2]; +}; + +const createActionSnippetItems = ( + range: vscode.Range, + prefix = ' ' +): vscode.CompletionItem[] => { + const item1 = createSnippetItem( + 'action', + 'action', + new vscode.SnippetString( + [ + 'action "${1:a}" appliesTo {', + ' principal: [${3:P}],', + ' resource: [${4:R}],', + ' context: {$0}', + '};', + ].join(prefix + '\n') + ), + range + ); + const item2 = createSnippetItem( + 'action', + 'action in', + new vscode.SnippetString( + [ + 'action "${1:a}" in [${2:a}] appliesTo {', + ' principal: [${3:P}],', + ' resource: [${4:R}],', + ' context: {$0}', + '};', + ].join(prefix + '\n') + ), + range + ); + return [item1, item2]; +}; diff --git a/src/extension.ts b/src/extension.ts index 93a7bcc..d49026c 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -34,6 +34,7 @@ import { COMMAND_CEDAR_ABOUT, COMMAND_CEDAR_ACTIVATE, COMMAND_CEDAR_CLEARPROBLEMS, + COMMAND_CEDAR_DOCUMENTATION, COMMAND_CEDAR_ENTITIESVALIDATE, COMMAND_CEDAR_EXPORT, COMMAND_CEDAR_SCHEMAEXPORT, @@ -67,7 +68,10 @@ import { cedarJsonTokensProvider, } from './parser'; import { exportCedarDocPolicyById, getPolicyQuickPickItems } from './policy'; -import { CedarCompletionItemProvider } from './completion'; +import { + CedarCompletionItemProvider, + CedarSchemaCompletionItemProvider, +} from './completion'; import { CedarHoverProvider } from './hover'; import { aboutExtension } from './about'; import * as cedar from 'vscode-cedar-wasm'; @@ -213,6 +217,16 @@ export async function activate(context: vscode.ExtensionContext) { aboutExtension(); }) ); + context.subscriptions.push( + vscode.commands.registerCommand( + COMMAND_CEDAR_DOCUMENTATION, + (args: any[]) => { + vscode.env.openExternal( + vscode.Uri.parse('https://docs.cedarpolicy.com/', true) + ); + } + ) + ); context.subscriptions.push( vscode.commands.registerTextEditorCommand( COMMAND_CEDAR_ACTIVATE, @@ -566,6 +580,12 @@ export async function activate(context: vscode.ExtensionContext) { schemaDefinitionProvider ) ); + context.subscriptions.push( + vscode.languages.registerCompletionItemProvider( + { language: 'cedarschema' }, + new CedarSchemaCompletionItemProvider() + ) + ); // context.subscriptions.push( // vscode.languages.registerCodeLensProvider( diff --git a/src/parser.ts b/src/parser.ts index 83d5196..088c932 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -1325,15 +1325,15 @@ const parseCedarSchemaNaturalDoc = ( textLine: string, i: number, match: string, - offset: number = 0, + startPos: number = 0, margin: number = 0 ): vscode.Range | null { let range = null; - const idx = textLine.indexOf(' ' + match, offset); + const idx = textLine.indexOf(match, startPos); if (idx > -1) { range = new vscode.Range( - new vscode.Position(i, idx + 1 + margin), - new vscode.Position(i, idx + 1 + match.length - margin) + new vscode.Position(i, idx + margin), + new vscode.Position(i, idx + match.length - margin) ); } return range; @@ -1416,7 +1416,7 @@ const parseCedarSchemaNaturalDoc = ( /^type\s+([_a-zA-Z][_a-zA-Z0-9]*)\s*=/ ); if (match) { - const range = determineRange(textLine, i, match[1]); + const range = determineRange(textLine, i, match[1], match.index || 0); if (range) { tokensBuilder.push(range, 'struct', ['declaration']); } @@ -1432,49 +1432,45 @@ const parseCedarSchemaNaturalDoc = ( /^entity\s+(([_a-zA-Z][_a-zA-Z0-9]*,\s*)*[_a-zA-Z][_a-zA-Z0-9]*)\s*( in|=|{|;|$)/ ); if (match) { + let startPos = match.index || 0; const types = match[1].split(','); types.forEach((type) => { - const range = determineRange(textLine, i, type.trim()); + const range = determineRange(textLine, i, type.trim(), startPos); if (range) { tokensBuilder.push(range, 'type', ['declaration']); } declarations[namespace + type.trim()] = range; + startPos = startPos + type.length + 1; }); } } // https://docs.cedarpolicy.com/schema/human-readable-schema.html#schema-actions if (linePreComment.startsWith('action')) { - let padding = textLine.indexOf('action') + 6; declarationStartLine = i; symbol = vscode.SymbolKind.Function; collection = 'actions'; let match = linePreComment.match(/^action\s+(("(.+?)",\s*)*"(.+?)")/); + match = linePreComment.match( + /^action\s+([_a-zA-Z0-9, "]*)( in| appliesTo|;|$)/ + ); if (match) { + let startPos = match.index || textLine.indexOf('action') + 6; const ids = match[1].split(','); ids.forEach((id) => { - declarations[`${namespace}Action::${id.trim()}`] = determineRange( - textLine, - i, - id.trim(), - padding, - 1 - ); - }); - } else { - match = linePreComment.match( - /^action\s+([_a-zA-Z0-9, ]*)( in| appliesTo|;|$)/ - ); - if (match) { - const ids = match[1].split(','); - ids.forEach((id) => { - id = id.trim().split(' ')[0]; - const range = determineRange(textLine, i, id, padding); - if (range) { - tokensBuilder.push(range, 'string', []); - } + id = id.trim(); + const isQuoted = id.startsWith('"') && id.endsWith('"'); + if (isQuoted) { + var range = determineRange(textLine, i, id, startPos, 1); + id = id.substring(1, id.length - 1); + } else { + var range = determineRange(textLine, i, id, startPos); + } + if (range) { + tokensBuilder.push(range, 'string', []); declarations[`${namespace}Action::"${id}"`] = range; - }); - } + } + startPos = startPos + id.length + (isQuoted ? 3 : 1); + }); } } const leftBracketIndex = linePreComment.indexOf('['); @@ -1523,14 +1519,14 @@ const parseCedarSchemaNaturalDoc = ( if (declarationStartLine !== -1 && colonIndex > -1) { // inside a declaration const match = textLine.match( - /^\s*(?:("[^"]+"|[_a-zA-Z][_a-zA-Z0-9]*))[?]?\s*:\s*(?:Set\s*<\s*)?(?([_a-zA-Z][_a-zA-Z0-9]*::)*[_a-zA-Z][_a-zA-Z0-9]*)\s*(?:\s*>\s*)?,?$/ + /^\s*(?:("[^"]+"|[_a-zA-Z][_a-zA-Z0-9]*))[?]?\s*:\s*(?:Set\s*<\s*)?(?([_a-zA-Z][_a-zA-Z0-9]*::)*[_a-zA-Z][_a-zA-Z0-9]*)\s*(?:\s*>\s*)?/ ); if (match && match.groups?.type) { let type = match.groups?.type; if ( !( type.startsWith('__cedar::') || - ['Long', 'String', 'Bool'].includes(type) + ['Long', 'String', 'Bool', 'Set'].includes(type) ) ) { const idx = textLine.indexOf(type, colonIndex); @@ -1541,7 +1537,6 @@ const parseCedarSchemaNaturalDoc = ( } else { tokensBuilder.push(range, 'type', []); - declarations[namespace + match.groups.type] = range; referencedTypes.push({ name: ensureNamespace(type, namespace), range: range, diff --git a/vscode-cedar-wasm/Cargo.lock b/vscode-cedar-wasm/Cargo.lock index 18b2e1a..e2b313b 100644 --- a/vscode-cedar-wasm/Cargo.lock +++ b/vscode-cedar-wasm/Cargo.lock @@ -43,15 +43,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "base64" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "beef" @@ -100,15 +100,15 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.95" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" [[package]] name = "cedar-policy" -version = "3.1.3" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84828571547bbcba6905d4cc95b261d8bf42052ec565b15da1c500fc02628ce5" +checksum = "7e84c5e10f913e444771642d4e008fdb17332b10950ff93a5ef9433da4aa9749" dependencies = [ "cedar-policy-core", "cedar-policy-validator", @@ -126,9 +126,9 @@ dependencies = [ [[package]] name = "cedar-policy-core" -version = "3.1.3" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73d01b4edcae13933522bd27cf6dbd81a080a3c26b387659fe8caf9dc42265c3" +checksum = "9fb7d4510875be7a4429813c3f213471f1e82607225dda3061b99ba99f338d9b" dependencies = [ "either", "itertools 0.12.1", @@ -149,9 +149,9 @@ dependencies = [ [[package]] name = "cedar-policy-formatter" -version = "3.1.3" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad4b7ab58e3922e718240d657adea27ac1e9606bf3842782132f14a7f4d13788" +checksum = "c60f48a430485ece45a8fdf1eda729d5417419b5df81ad0385118c0a73af653a" dependencies = [ "cedar-policy-core", "itertools 0.12.1", @@ -164,9 +164,9 @@ dependencies = [ [[package]] name = "cedar-policy-validator" -version = "3.1.3" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0239eb21f48b4d4abe0ee764aa188f52cf7fde00dd7dc83fc240e4bb2921e4d0" +checksum = "ff278098322bdf805733dd86ac2f8df9127357fe220d79c6501e6e7ce825551d" dependencies = [ "cedar-policy-core", "itertools 0.12.1", @@ -299,9 +299,9 @@ checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" [[package]] name = "ena" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" +checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" dependencies = [ "log", ] @@ -335,9 +335,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -352,9 +352,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hex" @@ -419,7 +419,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "serde", ] @@ -495,9 +495,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" [[package]] name = "libredox" @@ -608,9 +608,9 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -652,9 +652,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "petgraph" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", "indexmap 2.2.6", @@ -700,9 +700,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" dependencies = [ "unicode-ident", ] @@ -747,18 +747,18 @@ dependencies = [ [[package]] name = "ref-cast" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4846d4c50d1721b1a3bef8af76924eef20d5e723647333798c1b519b3a9473f" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", @@ -805,15 +805,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" +checksum = "092474d1a01ea8278f69e6a358998405fae5b8b963ddaeb2b0b04a128bf1dfb0" [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -838,27 +838,27 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.198" +version = "1.0.201" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" +checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.198" +version = "1.0.201" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" +checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" dependencies = [ "proc-macro2", "quote", @@ -867,9 +867,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "indexmap 2.2.6", "itoa", @@ -879,9 +879,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.8.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c85f8e96d1d6857f13768fcbd895fcb06225510022a2774ed8b5150581847b0" +checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" dependencies = [ "base64", "chrono", @@ -897,9 +897,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.8.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8b3a576c4eb2924262d5951a3b737ccaf16c931e39a2810c36f9a7e25575557" +checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" dependencies = [ "darling", "proc-macro2", @@ -962,9 +962,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "2.0.60" +version = "2.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "c993ed8ccba56ae856363b1845da7266a7cb78e1d146c8a32d54b45a8b831fc9" dependencies = [ "proc-macro2", "quote", @@ -984,18 +984,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" dependencies = [ "proc-macro2", "quote", @@ -1111,9 +1111,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" [[package]] name = "unicode-xid" @@ -1134,7 +1134,7 @@ dependencies = [ [[package]] name = "vscode-cedar-wasm" -version = "0.7.4" +version = "0.7.5" dependencies = [ "cargo-lock", "cedar-policy", diff --git a/vscode-cedar-wasm/Cargo.toml b/vscode-cedar-wasm/Cargo.toml index 0a0bf54..e9f129e 100644 --- a/vscode-cedar-wasm/Cargo.toml +++ b/vscode-cedar-wasm/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "vscode-cedar-wasm" -version = "0.7.4" +version = "0.7.5" edition = "2021" -description = "WASM bindgen bindings for cedar-policy 3.1.3" +description = "WASM bindgen bindings for cedar-policy 3.1.4" license-file = "LICENSE" homepage = "https://cedarpolicy.com" repository = "https://github.com/cedar-policy/vscode-cedar" @@ -29,10 +29,10 @@ serde_json = "1.0.96" console_error_panic_hook = { version = "0.1.6", optional = true } # cedar -cedar-policy = { version = "=3.1.3" } -cedar-policy-core = { version = "=3.1.3" } -cedar-policy-formatter = { version = "=3.1.3" } -cedar-policy-validator = { version = "=3.1.3" } +cedar-policy = { version = "=3.1.4" } +cedar-policy-core = { version = "=3.1.4" } +cedar-policy-formatter = { version = "=3.1.4" } +cedar-policy-validator = { version = "=3.1.4" } miette = "7.2.0" [dev-dependencies]