From 38fd8987ef54e5b36854f88ee3fcdd7c6e9ba433 Mon Sep 17 00:00:00 2001 From: Remy Suen Date: Fri, 27 Mar 2020 08:01:12 -0400 Subject: [PATCH] Fix #65 Support multiple directives in symbols Signed-off-by: Remy Suen --- CHANGELOG.md | 5 + src/dockerSymbols.ts | 3 +- test/dockerSymbols.test.ts | 391 ++++++++++++++++++++----------------- 3 files changed, 223 insertions(+), 176 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe1e32c..603b983 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Changelog All notable changes to this project will be documented in this file. +## [Unreleased] +### Added +- support multiple directives when calculating a Dockerfile's symbols ([#65](https://github.com/rcjsuen/dockerfile-language-service/issues/65)) + ## [0.0.10] - 2020-03-25 ### Added - all tokens are now assigned a semantic meaning for the experimental support of semantic tokens ([#54](https://github.com/rcjsuen/dockerfile-language-service/issues/54)) @@ -278,6 +282,7 @@ let workspaceEdit = { - textDocument/rename - textDocument/hover +[Unreleased]: https://github.com/rcjsuen/dockerfile-language-service/compare/v0.0.10...HEAD [0.0.10]: https://github.com/rcjsuen/dockerfile-language-service/compare/v0.0.9...v0.0.10 [0.0.9]: https://github.com/rcjsuen/dockerfile-language-service/compare/v0.0.8...v0.0.9 [0.0.8]: https://github.com/rcjsuen/dockerfile-language-service/compare/v0.0.7...v0.0.8 diff --git a/src/dockerSymbols.ts b/src/dockerSymbols.ts index 4b0d0a8..744c8ef 100644 --- a/src/dockerSymbols.ts +++ b/src/dockerSymbols.ts @@ -33,9 +33,8 @@ export class DockerSymbols { public parseSymbolInformation(textDocument: TextDocumentIdentifier, content: string): SymbolInformation[] { let dockerfile = DockerfileParser.parse(content); - let directive = dockerfile.getDirective(); let symbols: SymbolInformation[] = []; - if (directive !== null) { + for (const directive of dockerfile.getDirectives()) { symbols.push(this.createSymbolInformation(directive.getName(), textDocument.uri, directive.getNameRange(), SymbolKind.Property, false)); } for (let instruction of dockerfile.getInstructions()) { diff --git a/test/dockerSymbols.test.ts b/test/dockerSymbols.test.ts index 3d26cd4..7ff937d 100644 --- a/test/dockerSymbols.test.ts +++ b/test/dockerSymbols.test.ts @@ -31,192 +31,235 @@ describe("Dockerfile document symbols", function () { }); describe("directives", function () { - it("escape directive", function () { - let symbols = computeSymbols("#escape=`"); - assert.equal(symbols.length, 1); - assert.equal(symbols[0].containerName, undefined); - assert.equal(symbols[0].deprecated, undefined); - assert.equal(symbols[0].name, "escape"); - assert.equal(symbols[0].kind, SymbolKind.Property); - assert.equal(symbols[0].location.uri, uri); - assert.equal(symbols[0].location.range.start.line, 0); - assert.equal(symbols[0].location.range.start.character, 1); - assert.equal(symbols[0].location.range.end.line, 0); - assert.equal(symbols[0].location.range.end.character, 7); - }); + describe("escape", function () { + it("no space", function () { + let symbols = computeSymbols("#escape=`"); + assert.equal(symbols.length, 1); + assert.equal(symbols[0].containerName, undefined); + assert.equal(symbols[0].deprecated, undefined); + assert.equal(symbols[0].name, "escape"); + assert.equal(symbols[0].kind, SymbolKind.Property); + assert.equal(symbols[0].location.uri, uri); + assert.equal(symbols[0].location.range.start.line, 0); + assert.equal(symbols[0].location.range.start.character, 1); + assert.equal(symbols[0].location.range.end.line, 0); + assert.equal(symbols[0].location.range.end.character, 7); + }); - it("space", function () { - let symbols = computeSymbols("# escape=`"); - assert.equal(symbols.length, 1); - assert.equal(symbols[0].containerName, undefined); - assert.equal(symbols[0].deprecated, undefined); - assert.equal(symbols[0].name, "escape"); - assert.equal(symbols[0].kind, SymbolKind.Property); - assert.equal(symbols[0].location.uri, uri); - assert.equal(symbols[0].location.range.start.line, 0); - assert.equal(symbols[0].location.range.start.character, 2); - assert.equal(symbols[0].location.range.end.line, 0); - assert.equal(symbols[0].location.range.end.character, 8); - - symbols = computeSymbols("#\tescape=`"); - assert.equal(symbols.length, 1); - assert.equal(symbols[0].containerName, undefined); - assert.equal(symbols[0].deprecated, undefined); - assert.equal(symbols[0].name, "escape"); - assert.equal(symbols[0].kind, SymbolKind.Property); - assert.equal(symbols[0].location.uri, uri); - assert.equal(symbols[0].location.range.start.line, 0); - assert.equal(symbols[0].location.range.start.character, 2); - assert.equal(symbols[0].location.range.end.line, 0); - assert.equal(symbols[0].location.range.end.character, 8); - - symbols = computeSymbols("# escape= `"); - assert.equal(symbols.length, 1); - assert.equal(symbols[0].containerName, undefined); - assert.equal(symbols[0].deprecated, undefined); - assert.equal(symbols[0].name, "escape"); - assert.equal(symbols[0].kind, SymbolKind.Property); - assert.equal(symbols[0].location.uri, uri); - assert.equal(symbols[0].location.range.start.line, 0); - assert.equal(symbols[0].location.range.start.character, 2); - assert.equal(symbols[0].location.range.end.line, 0); - assert.equal(symbols[0].location.range.end.character, 8); - - symbols = computeSymbols("# escape=\t`"); - assert.equal(symbols.length, 1); - assert.equal(symbols[0].containerName, undefined); - assert.equal(symbols[0].deprecated, undefined); - assert.equal(symbols[0].name, "escape"); - assert.equal(symbols[0].kind, SymbolKind.Property); - assert.equal(symbols[0].location.uri, uri); - assert.equal(symbols[0].location.range.start.line, 0); - assert.equal(symbols[0].location.range.start.character, 2); - assert.equal(symbols[0].location.range.end.line, 0); - assert.equal(symbols[0].location.range.end.character, 8); - - symbols = computeSymbols("# escape=` "); - assert.equal(symbols.length, 1); - assert.equal(symbols[0].containerName, undefined); - assert.equal(symbols[0].deprecated, undefined); - assert.equal(symbols[0].name, "escape"); - assert.equal(symbols[0].kind, SymbolKind.Property); - assert.equal(symbols[0].location.uri, uri); - assert.equal(symbols[0].location.range.start.line, 0); - assert.equal(symbols[0].location.range.start.character, 2); - assert.equal(symbols[0].location.range.end.line, 0); - assert.equal(symbols[0].location.range.end.character, 8); - }); + it("space", function () { + let symbols = computeSymbols("# escape=`"); + assert.equal(symbols.length, 1); + assert.equal(symbols[0].containerName, undefined); + assert.equal(symbols[0].deprecated, undefined); + assert.equal(symbols[0].name, "escape"); + assert.equal(symbols[0].kind, SymbolKind.Property); + assert.equal(symbols[0].location.uri, uri); + assert.equal(symbols[0].location.range.start.line, 0); + assert.equal(symbols[0].location.range.start.character, 2); + assert.equal(symbols[0].location.range.end.line, 0); + assert.equal(symbols[0].location.range.end.character, 8); - it("leading whitespace", function () { - let symbols = computeSymbols(" #escape=`"); - assert.equal(symbols.length, 1); - assert.equal(symbols[0].containerName, undefined); - assert.equal(symbols[0].deprecated, undefined); - assert.equal(symbols[0].name, "escape"); - assert.equal(symbols[0].kind, SymbolKind.Property); - assert.equal(symbols[0].location.uri, uri); - assert.equal(symbols[0].location.range.start.line, 0); - assert.equal(symbols[0].location.range.start.character, 2); - assert.equal(symbols[0].location.range.end.line, 0); - assert.equal(symbols[0].location.range.end.character, 8); - - symbols = computeSymbols("\t#escape=`"); - assert.equal(symbols.length, 1); - assert.equal(symbols[0].containerName, undefined); - assert.equal(symbols[0].deprecated, undefined); - assert.equal(symbols[0].name, "escape"); - assert.equal(symbols[0].kind, SymbolKind.Property); - assert.equal(symbols[0].location.uri, uri); - assert.equal(symbols[0].location.range.start.line, 0); - assert.equal(symbols[0].location.range.start.character, 2); - assert.equal(symbols[0].location.range.end.line, 0); - assert.equal(symbols[0].location.range.end.character, 8); - - symbols = computeSymbols("# escape\t=\t` "); - assert.equal(symbols.length, 1); - assert.equal(symbols[0].containerName, undefined); - assert.equal(symbols[0].deprecated, undefined); - assert.equal(symbols[0].name, "escape"); - assert.equal(symbols[0].kind, SymbolKind.Property); - assert.equal(symbols[0].location.uri, uri); - assert.equal(symbols[0].location.range.start.line, 0); - assert.equal(symbols[0].location.range.start.character, 2); - assert.equal(symbols[0].location.range.end.line, 0); - assert.equal(symbols[0].location.range.end.character, 8); - }); + symbols = computeSymbols("#\tescape=`"); + assert.equal(symbols.length, 1); + assert.equal(symbols[0].containerName, undefined); + assert.equal(symbols[0].deprecated, undefined); + assert.equal(symbols[0].name, "escape"); + assert.equal(symbols[0].kind, SymbolKind.Property); + assert.equal(symbols[0].location.uri, uri); + assert.equal(symbols[0].location.range.start.line, 0); + assert.equal(symbols[0].location.range.start.character, 2); + assert.equal(symbols[0].location.range.end.line, 0); + assert.equal(symbols[0].location.range.end.character, 8); - it("directive becomes a comment if not at the top", function () { - let symbols = computeSymbols("\r#escape=`"); - assert.equal(symbols.length, 0); + symbols = computeSymbols("# escape= `"); + assert.equal(symbols.length, 1); + assert.equal(symbols[0].containerName, undefined); + assert.equal(symbols[0].deprecated, undefined); + assert.equal(symbols[0].name, "escape"); + assert.equal(symbols[0].kind, SymbolKind.Property); + assert.equal(symbols[0].location.uri, uri); + assert.equal(symbols[0].location.range.start.line, 0); + assert.equal(symbols[0].location.range.start.character, 2); + assert.equal(symbols[0].location.range.end.line, 0); + assert.equal(symbols[0].location.range.end.character, 8); - symbols = computeSymbols("\n#escape=`"); - assert.equal(symbols.length, 0); + symbols = computeSymbols("# escape=\t`"); + assert.equal(symbols.length, 1); + assert.equal(symbols[0].containerName, undefined); + assert.equal(symbols[0].deprecated, undefined); + assert.equal(symbols[0].name, "escape"); + assert.equal(symbols[0].kind, SymbolKind.Property); + assert.equal(symbols[0].location.uri, uri); + assert.equal(symbols[0].location.range.start.line, 0); + assert.equal(symbols[0].location.range.start.character, 2); + assert.equal(symbols[0].location.range.end.line, 0); + assert.equal(symbols[0].location.range.end.character, 8); - symbols = computeSymbols("\r\n#escape=`"); - assert.equal(symbols.length, 0); - }); + symbols = computeSymbols("# escape=` "); + assert.equal(symbols.length, 1); + assert.equal(symbols[0].containerName, undefined); + assert.equal(symbols[0].deprecated, undefined); + assert.equal(symbols[0].name, "escape"); + assert.equal(symbols[0].kind, SymbolKind.Property); + assert.equal(symbols[0].location.uri, uri); + assert.equal(symbols[0].location.range.start.line, 0); + assert.equal(symbols[0].location.range.start.character, 2); + assert.equal(symbols[0].location.range.end.line, 0); + assert.equal(symbols[0].location.range.end.character, 8); + }); - it("invalid directive definition with leading comment", function () { - let symbols = computeSymbols("#\n#escape=`"); - assert.equal(symbols.length, 0); + it("leading whitespace", function () { + let symbols = computeSymbols(" #escape=`"); + assert.equal(symbols.length, 1); + assert.equal(symbols[0].containerName, undefined); + assert.equal(symbols[0].deprecated, undefined); + assert.equal(symbols[0].name, "escape"); + assert.equal(symbols[0].kind, SymbolKind.Property); + assert.equal(symbols[0].location.uri, uri); + assert.equal(symbols[0].location.range.start.line, 0); + assert.equal(symbols[0].location.range.start.character, 2); + assert.equal(symbols[0].location.range.end.line, 0); + assert.equal(symbols[0].location.range.end.character, 8); - symbols = computeSymbols("#\r\n#escape=`"); - assert.equal(symbols.length, 0); + symbols = computeSymbols("\t#escape=`"); + assert.equal(symbols.length, 1); + assert.equal(symbols[0].containerName, undefined); + assert.equal(symbols[0].deprecated, undefined); + assert.equal(symbols[0].name, "escape"); + assert.equal(symbols[0].kind, SymbolKind.Property); + assert.equal(symbols[0].location.uri, uri); + assert.equal(symbols[0].location.range.start.line, 0); + assert.equal(symbols[0].location.range.start.character, 2); + assert.equal(symbols[0].location.range.end.line, 0); + assert.equal(symbols[0].location.range.end.character, 8); - symbols = computeSymbols("#comment\n#escape=`"); - assert.equal(symbols.length, 0); + symbols = computeSymbols("# escape\t=\t` "); + assert.equal(symbols.length, 1); + assert.equal(symbols[0].containerName, undefined); + assert.equal(symbols[0].deprecated, undefined); + assert.equal(symbols[0].name, "escape"); + assert.equal(symbols[0].kind, SymbolKind.Property); + assert.equal(symbols[0].location.uri, uri); + assert.equal(symbols[0].location.range.start.line, 0); + assert.equal(symbols[0].location.range.start.character, 2); + assert.equal(symbols[0].location.range.end.line, 0); + assert.equal(symbols[0].location.range.end.character, 8); + }); + + it("directive becomes a comment if not at the top", function () { + let symbols = computeSymbols("\r#escape=`"); + assert.equal(symbols.length, 0); + + symbols = computeSymbols("\n#escape=`"); + assert.equal(symbols.length, 0); + + symbols = computeSymbols("\r\n#escape=`"); + assert.equal(symbols.length, 0); + }); + + it("invalid directive definition with leading comment", function () { + let symbols = computeSymbols("#\n#escape=`"); + assert.equal(symbols.length, 0); + + symbols = computeSymbols("#\r\n#escape=`"); + assert.equal(symbols.length, 0); + + symbols = computeSymbols("#comment\n#escape=`"); + assert.equal(symbols.length, 0); + }); + + it("invalid directive definition with nothing", function () { + let symbols = computeSymbols("#escape="); + assert.equal(symbols.length, 1); + assert.equal(symbols[0].containerName, undefined); + assert.equal(symbols[0].deprecated, undefined); + assert.equal(symbols[0].name, "escape"); + assert.equal(symbols[0].kind, SymbolKind.Property); + assert.equal(symbols[0].location.uri, uri); + assert.equal(symbols[0].location.range.start.line, 0); + assert.equal(symbols[0].location.range.start.character, 1); + assert.equal(symbols[0].location.range.end.line, 0); + assert.equal(symbols[0].location.range.end.character, 7); + + symbols = computeSymbols("#escape=\r"); + assert.equal(symbols.length, 1); + assert.equal(symbols[0].containerName, undefined); + assert.equal(symbols[0].deprecated, undefined); + assert.equal(symbols[0].name, "escape"); + assert.equal(symbols[0].kind, SymbolKind.Property); + assert.equal(symbols[0].location.uri, uri); + assert.equal(symbols[0].location.range.start.line, 0); + assert.equal(symbols[0].location.range.start.character, 1); + assert.equal(symbols[0].location.range.end.line, 0); + assert.equal(symbols[0].location.range.end.character, 7); + + symbols = computeSymbols("#escape=\n"); + assert.equal(symbols.length, 1); + assert.equal(symbols[0].containerName, undefined); + assert.equal(symbols[0].deprecated, undefined); + assert.equal(symbols[0].name, "escape"); + assert.equal(symbols[0].kind, SymbolKind.Property); + assert.equal(symbols[0].location.uri, uri); + assert.equal(symbols[0].location.range.start.line, 0); + assert.equal(symbols[0].location.range.start.character, 1); + assert.equal(symbols[0].location.range.end.line, 0); + assert.equal(symbols[0].location.range.end.character, 7); + }); + + it("invalid directive name", function () { + let symbols = computeSymbols("#eskape=`"); + assert.equal(symbols.length, 1); + assert.equal(symbols[0].containerName, undefined); + assert.equal(symbols[0].deprecated, undefined); + assert.equal(symbols[0].name, "eskape"); + assert.equal(symbols[0].kind, SymbolKind.Property); + assert.equal(symbols[0].location.uri, uri); + assert.equal(symbols[0].location.range.start.line, 0); + assert.equal(symbols[0].location.range.start.character, 1); + assert.equal(symbols[0].location.range.end.line, 0); + assert.equal(symbols[0].location.range.end.character, 7); + }); }); - it("invalid directive definition with nothing", function () { - let symbols = computeSymbols("#escape="); - assert.equal(symbols.length, 1); - assert.equal(symbols[0].containerName, undefined); - assert.equal(symbols[0].deprecated, undefined); - assert.equal(symbols[0].name, "escape"); - assert.equal(symbols[0].kind, SymbolKind.Property); - assert.equal(symbols[0].location.uri, uri); - assert.equal(symbols[0].location.range.start.line, 0); - assert.equal(symbols[0].location.range.start.character, 1); - assert.equal(symbols[0].location.range.end.line, 0); - assert.equal(symbols[0].location.range.end.character, 7); - - symbols = computeSymbols("#escape=\r"); - assert.equal(symbols.length, 1); - assert.equal(symbols[0].containerName, undefined); - assert.equal(symbols[0].deprecated, undefined); - assert.equal(symbols[0].name, "escape"); - assert.equal(symbols[0].kind, SymbolKind.Property); - assert.equal(symbols[0].location.uri, uri); - assert.equal(symbols[0].location.range.start.line, 0); - assert.equal(symbols[0].location.range.start.character, 1); - assert.equal(symbols[0].location.range.end.line, 0); - assert.equal(symbols[0].location.range.end.character, 7); - - symbols = computeSymbols("#escape=\n"); - assert.equal(symbols.length, 1); - assert.equal(symbols[0].containerName, undefined); - assert.equal(symbols[0].deprecated, undefined); - assert.equal(symbols[0].name, "escape"); - assert.equal(symbols[0].kind, SymbolKind.Property); - assert.equal(symbols[0].location.uri, uri); - assert.equal(symbols[0].location.range.start.line, 0); - assert.equal(symbols[0].location.range.start.character, 1); - assert.equal(symbols[0].location.range.end.line, 0); - assert.equal(symbols[0].location.range.end.character, 7); + describe("syntax", function () { + it("no space", function () { + let symbols = computeSymbols("#syntax=docker/dockerfile:experimental"); + assert.equal(symbols.length, 1); + assert.equal(symbols[0].containerName, undefined); + assert.equal(symbols[0].deprecated, undefined); + assert.equal(symbols[0].name, "syntax"); + assert.equal(symbols[0].kind, SymbolKind.Property); + assert.equal(symbols[0].location.uri, uri); + assert.equal(symbols[0].location.range.start.line, 0); + assert.equal(symbols[0].location.range.start.character, 1); + assert.equal(symbols[0].location.range.end.line, 0); + assert.equal(symbols[0].location.range.end.character, 7); + }); }); - it("invalid directive name", function () { - let symbols = computeSymbols("#eskape=`"); - assert.equal(symbols.length, 1); - assert.equal(symbols[0].containerName, undefined); - assert.equal(symbols[0].deprecated, undefined); - assert.equal(symbols[0].name, "eskape"); - assert.equal(symbols[0].kind, SymbolKind.Property); - assert.equal(symbols[0].location.uri, uri); - assert.equal(symbols[0].location.range.start.line, 0); - assert.equal(symbols[0].location.range.start.character, 1); - assert.equal(symbols[0].location.range.end.line, 0); - assert.equal(symbols[0].location.range.end.character, 7); + describe("multiple directives", function () { + it("escape and syntax", function () { + let symbols = computeSymbols("#escape=`\n#syntax=docker/dockerfile:experimental"); + assert.equal(symbols.length, 2); + assert.equal(symbols[0].containerName, undefined); + assert.equal(symbols[0].deprecated, undefined); + assert.equal(symbols[0].name, "escape"); + assert.equal(symbols[0].kind, SymbolKind.Property); + assert.equal(symbols[0].location.uri, uri); + assert.equal(symbols[0].location.range.start.line, 0); + assert.equal(symbols[0].location.range.start.character, 1); + assert.equal(symbols[0].location.range.end.line, 0); + assert.equal(symbols[0].location.range.end.character, 7); + assert.equal(symbols[1].containerName, undefined); + assert.equal(symbols[1].deprecated, undefined); + assert.equal(symbols[1].name, "syntax"); + assert.equal(symbols[1].kind, SymbolKind.Property); + assert.equal(symbols[1].location.uri, uri); + assert.equal(symbols[1].location.range.start.line, 1); + assert.equal(symbols[1].location.range.start.character, 1); + assert.equal(symbols[1].location.range.end.line, 1); + assert.equal(symbols[1].location.range.end.character, 7); + }); }); });