UNPKG

dockerfile-language-service

Version:

A language service for Dockerfiles to enable the creation of feature-rich Dockerfile editors.

868 lines (867 loc) 73.5 kB
(function (factory) { if (typeof module === "object" && typeof module.exports === "object") { var v = factory(require, exports); if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { define(["require", "exports", "vscode-languageserver-textdocument", "./dockerPlainText", "dockerfile-ast", "./docker"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DockerSignatures = void 0; /* -------------------------------------------------------------------------------------------- * Copyright (c) Remy Suen. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ var vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument"); var dockerPlainText_1 = require("./dockerPlainText"); var dockerfile_ast_1 = require("dockerfile-ast"); var docker_1 = require("./docker"); var DockerSignatures = /** @class */ (function () { function DockerSignatures() { this.documentation = new dockerPlainText_1.PlainTextDocumentation(); } DockerSignatures.prototype.computeSignatures = function (content, position) { var document = vscode_languageserver_textdocument_1.TextDocument.create("", "", 0, content); var dockerfile = dockerfile_ast_1.DockerfileParser.parse(document.getText()); if (position.line === 0) { var directive = dockerfile.getDirective(); if (directive !== null && directive.getDirective() === dockerfile_ast_1.Directive.escape) { return { signatures: [ { label: "escape=\\", documentation: this.documentation.getDocumentation("signatureEscape"), parameters: [ { label: "\\", documentation: this.documentation.getDocumentation("signatureEscape_Param") } ] } ], activeSignature: 0, activeParameter: 0 }; } } for (var _i = 0, _a = dockerfile.getComments(); _i < _a.length; _i++) { var comment = _a[_i]; if (docker_1.Util.isInsideRange(position, comment.getRange())) { return { signatures: [], activeSignature: null, activeParameter: null }; } } var signatureHelp = this.getInstructionSignatures(document, dockerfile.getOnbuildTriggers(), position); if (!signatureHelp) { signatureHelp = this.getInstructionSignatures(document, dockerfile.getInstructions(), position); if (!signatureHelp) { signatureHelp = { signatures: [], activeSignature: null, activeParameter: null }; } } return signatureHelp; }; DockerSignatures.prototype.getInstructionSignatures = function (document, instructions, position) { for (var _i = 0, instructions_1 = instructions; _i < instructions_1.length; _i++) { var instruction = instructions_1[_i]; if (!docker_1.Util.isInsideRange(position, instruction.getRange())) { continue; } else if (docker_1.Util.isInsideRange(position, instruction.getInstructionRange())) { return null; } switch (instruction.getKeyword()) { case "ADD": var add = instruction; var addShellSignature = { label: "ADD [flags] source ... dest", documentation: this.documentation.getDocumentation("signatureAdd_Signature0"), parameters: [ { label: "[flags]", documentation: this.documentation.getDocumentation("signatureAdd_Signature0_Param0") }, { label: "source", documentation: this.documentation.getDocumentation("signatureAdd_Signature0_Param1") }, { label: "...", documentation: this.documentation.getDocumentation("signatureAdd_Signature0_Param2") }, { label: "dest", documentation: this.documentation.getDocumentation("signatureAdd_Signature0_Param3") } ] }; var addJsonSignature = { label: "ADD [flags] [ \"source\", ..., \"dest\" ]", documentation: this.documentation.getDocumentation("signatureAdd_Signature1"), parameters: [ { label: "[flags]", documentation: this.documentation.getDocumentation("signatureAdd_Signature1_Param0") }, { label: "[" }, { label: "\"source\"", documentation: this.documentation.getDocumentation("signatureAdd_Signature1_Param2") }, { label: "...", documentation: this.documentation.getDocumentation("signatureAdd_Signature1_Param3") }, { label: "\"dest\"", documentation: this.documentation.getDocumentation("signatureAdd_Signature1_Param4") }, { label: "]" } ] }; return this.getJSONInstructionSignatureHelp(document, add, position, [addJsonSignature], addShellSignature, true, false, false, false); case "ARG": var argSignatureHelp = { signatures: [ { label: "ARG name", documentation: this.documentation.getDocumentation("signatureArg_Signature0"), parameters: [ { label: "name", documentation: this.documentation.getDocumentation("signatureArg_Signature0_Param") } ] }, { label: "ARG name=defaultValue", documentation: this.documentation.getDocumentation("signatureArg_Signature1"), parameters: [ { label: "name", documentation: this.documentation.getDocumentation("signatureArg_Signature1_Param0") }, { label: "defaultValue", documentation: this.documentation.getDocumentation("signatureArg_Signature1_Param1") } ] } ], activeSignature: 0, activeParameter: 0 }; var content = instruction.getTextContent(); var index = content.indexOf('='); if (index !== -1) { argSignatureHelp = { signatures: [ { label: "ARG name=defaultValue", documentation: this.documentation.getDocumentation("signatureArg_Signature1"), parameters: [ { label: "name", documentation: this.documentation.getDocumentation("signatureArg_Signature1_Param0") }, { label: "defaultValue", documentation: this.documentation.getDocumentation("signatureArg_Signature1_Param1") } ] } ], activeSignature: 0, activeParameter: 0 }; if (document.offsetAt(position) > document.offsetAt(instruction.getRange().start) + index) { argSignatureHelp.activeParameter = 1; } } return argSignatureHelp; case "CMD": var cmd = instruction; var cmdJsonExecutableSignature = { label: "CMD [ \"executable\", \"parameter\", ... ]", documentation: this.documentation.getDocumentation("signatureCmd_Signature0"), parameters: [ { label: "[" }, { label: "\"executable\"", documentation: this.documentation.getDocumentation("signatureCmd_Signature0_Param1") }, { label: "\"parameter\"", documentation: this.documentation.getDocumentation("signatureCmd_Signature0_Param2") }, { label: "...", documentation: this.documentation.getDocumentation("signatureCmd_Signature0_Param3") }, { label: "]" } ] }; var cmdJsonParameterSignature = { label: "CMD [ \"parameter\", \"parameter2\", ... ]", documentation: this.documentation.getDocumentation("signatureCmd_Signature1"), parameters: [ { label: "[" }, { label: "\"parameter\"", documentation: this.documentation.getDocumentation("signatureCmd_Signature1_Param1") }, { label: "\"parameter2\"", documentation: this.documentation.getDocumentation("signatureCmd_Signature1_Param2") }, { label: "...", documentation: this.documentation.getDocumentation("signatureCmd_Signature1_Param3") }, { label: "]" } ] }; var cmdShellSignature = { label: "CMD executable parameter ...", documentation: this.documentation.getDocumentation("signatureCmd_Signature2"), parameters: [ { label: "executable", documentation: this.documentation.getDocumentation("signatureCmd_Signature2_Param0") }, { label: "parameter", documentation: this.documentation.getDocumentation("signatureCmd_Signature2_Param1") }, { label: "...", documentation: this.documentation.getDocumentation("signatureCmd_Signature2_Param2") } ] }; return this.getJSONInstructionSignatureHelp(document, cmd, position, [cmdJsonExecutableSignature, cmdJsonParameterSignature], cmdShellSignature, false, true, false, true); case "COPY": var copy = instruction; var flag = copy.getFromFlag(); if (flag !== null) { var range = flag.getValueRange(); if (range !== null && docker_1.Util.isInsideRange(position, range)) { return { signatures: [ { label: "--from=stage", documentation: this.documentation.getDocumentation("signatureCopyFlagFrom"), parameters: [ { label: "stage", documentation: this.documentation.getDocumentation("signatureCopyFlagFrom_Param") } ] } ], activeSignature: 0, activeParameter: 0 }; } } var copyShellSignature = { label: "COPY [flags] source ... dest", documentation: this.documentation.getDocumentation("signatureCopy_Signature0"), parameters: [ { label: "[flags]", documentation: this.documentation.getDocumentation("signatureCopy_Signature0_Param0") }, { label: "source", documentation: this.documentation.getDocumentation("signatureCopy_Signature0_Param1") }, { label: "...", documentation: this.documentation.getDocumentation("signatureCopy_Signature0_Param2") }, { label: "dest", documentation: this.documentation.getDocumentation("signatureCopy_Signature0_Param3") } ] }; var copyJsonSignature = { label: "COPY [flags] [ \"source\", ..., \"dest\" ]", documentation: this.documentation.getDocumentation("signatureCopy_Signature1"), parameters: [ { label: "[flags]", documentation: this.documentation.getDocumentation("signatureCopy_Signature1_Param0") }, { label: "[" }, { label: "\"source\"", documentation: this.documentation.getDocumentation("signatureCopy_Signature1_Param2") }, { label: "...", documentation: this.documentation.getDocumentation("signatureCopy_Signature1_Param3") }, { label: "\"dest\"", documentation: this.documentation.getDocumentation("signatureCopy_Signature1_Param4") }, { label: "]" } ] }; return this.getJSONInstructionSignatureHelp(document, copy, position, [copyJsonSignature], copyShellSignature, true, false, false, false); case "ENTRYPOINT": var entrypoint = instruction; var entrypointJsonSignature = { label: "ENTRYPOINT [ \"executable\", \"parameter\", ... ]", documentation: this.documentation.getDocumentation("signatureEntrypoint_Signature0"), parameters: [ { label: "[" }, { label: "\"executable\"", documentation: this.documentation.getDocumentation("signatureEntrypoint_Signature0_Param1") }, { label: "\"parameter\"", documentation: this.documentation.getDocumentation("signatureEntrypoint_Signature0_Param2") }, { label: "...", documentation: this.documentation.getDocumentation("signatureEntrypoint_Signature0_Param3") }, { label: "]" } ] }; var entrypointShellSignature = { label: "ENTRYPOINT executable parameter ...", documentation: this.documentation.getDocumentation("signatureEntrypoint_Signature1"), parameters: [ { label: "executable", documentation: this.documentation.getDocumentation("signatureEntrypoint_Signature1_Param0") }, { label: "parameter", documentation: this.documentation.getDocumentation("signatureEntrypoint_Signature1_Param1") }, { label: "...", documentation: this.documentation.getDocumentation("signatureEntrypoint_Signature1_Param2") } ] }; return this.getJSONInstructionSignatureHelp(document, entrypoint, position, [entrypointJsonSignature], entrypointShellSignature, false, true, false, true); case "ENV": var envSignatures = [ { label: "ENV key value", documentation: this.documentation.getDocumentation("signatureEnv_Signature0"), parameters: [ { label: "key", documentation: this.documentation.getDocumentation("signatureEnv_Signature0_Param0") }, { label: "value", documentation: this.documentation.getDocumentation("signatureEnv_Signature0_Param1") } ] }, { label: "ENV key=value", documentation: this.documentation.getDocumentation("signatureEnv_Signature1"), parameters: [ { label: "key", documentation: this.documentation.getDocumentation("signatureEnv_Signature1_Param0") }, { label: "value", documentation: this.documentation.getDocumentation("signatureEnv_Signature1_Param1") } ] }, { label: "ENV key=value key2=value2", documentation: this.documentation.getDocumentation("signatureEnv_Signature2"), parameters: [ { label: "key", documentation: this.documentation.getDocumentation("signatureEnv_Signature2_Param0") }, { label: "value", documentation: this.documentation.getDocumentation("signatureEnv_Signature2_Param1") }, { label: "key2", documentation: this.documentation.getDocumentation("signatureEnv_Signature2_Param2") }, { label: "value2", documentation: this.documentation.getDocumentation("signatureEnv_Signature2_Param3") } ] } ]; return this.getPropertySignatureHelp(document, position, envSignatures, instruction.getProperties()); case "EXPOSE": var exposeSignatureHelp = { signatures: [ { label: "EXPOSE port ...", documentation: this.documentation.getDocumentation("signatureExpose"), parameters: [ { label: "port", documentation: this.documentation.getDocumentation("signatureExpose_Param0") }, { label: "...", documentation: this.documentation.getDocumentation("signatureExpose_Param1") } ] } ], activeSignature: 0, activeParameter: 0 }; var exposeArgs = instruction.getArguments(); if (exposeArgs.length > 0 && document.offsetAt(position) > document.offsetAt(exposeArgs[0].getRange().end)) { exposeSignatureHelp.activeParameter = 1; } return exposeSignatureHelp; case "FROM": return this.getFromSignatureHelp(position, instruction); case "HEALTHCHECK": var healthcheckCmdEmptySignature = { label: "HEALTHCHECK [flags] CMD ...", documentation: this.documentation.getDocumentation("signatureHealthcheck_Signature0"), parameters: [ { label: "CMD" } ] }; var healthcheckCmdNormalSignature = { label: "HEALTHCHECK [flags] CMD ...", documentation: this.documentation.getDocumentation("signatureHealthcheck_Signature1"), parameters: [ { label: "[flags]", documentation: this.documentation.getDocumentation("signatureHealthcheck_Signature1_Param0") }, { label: "CMD" }, { label: "...", documentation: this.documentation.getDocumentation("signatureHealthcheck_Signature1_Param2") } ] }; var healthcheckNoneSignature = { label: "HEALTHCHECK NONE", documentation: this.documentation.getDocumentation("signatureHealthcheck_Signature2"), parameters: [ { label: "NONE" } ] }; var healthcheck = instruction; var flags = healthcheck.getFlags(); for (var _a = 0, flags_1 = flags; _a < flags_1.length; _a++) { var flag_1 = flags_1[_a]; var range = flag_1.getValueRange(); if (range !== null && docker_1.Util.isInsideRange(position, range)) { switch (flag_1.getName()) { case "interval": return { signatures: [ { label: "HEALTHCHECK --interval=30s ...", documentation: this.documentation.getDocumentation("signatureHealthcheck"), parameters: [ { label: "30s", documentation: this.documentation.getDocumentation("signatureHealthcheckFlagInterval_Param") } ] } ], activeSignature: 0, activeParameter: 0 }; case "retries": return { signatures: [ { label: "HEALTHCHECK --retries=3 ...", documentation: this.documentation.getDocumentation("signatureHealthcheck"), parameters: [ { label: "3", documentation: this.documentation.getDocumentation("signatureHealthcheckFlagRetries_Param") } ] } ], activeSignature: 0, activeParameter: 0 }; case "start-period": return { signatures: [ { label: "HEALTHCHECK --start-period=5s ...", documentation: this.documentation.getDocumentation("signatureHealthcheck"), parameters: [ { label: "5s", documentation: this.documentation.getDocumentation("signatureHealthcheckFlagStartPeriod_Param") } ] } ], activeSignature: 0, activeParameter: 0 }; case "timeout": return { signatures: [ { label: "HEALTHCHECK --timeout=30s ...", documentation: this.documentation.getDocumentation("signatureHealthcheck"), parameters: [ { label: "30s", documentation: this.documentation.getDocumentation("signatureHealthcheckFlagTimeout_Param") } ] } ], activeSignature: 0, activeParameter: 0 }; } break; } } var healthcheckArgs = healthcheck.getArguments(); if (flags.length == 0 && healthcheckArgs.length === 0) { // no flags or args, suggest both CMD and NONE return { signatures: [ healthcheckCmdEmptySignature, healthcheckNoneSignature ], activeSignature: 0, activeParameter: 0 }; } var subcommand = healthcheck.getSubcommand(); if (subcommand === null) { return { signatures: [ healthcheckCmdNormalSignature ], activeSignature: 0, activeParameter: 0 }; } var beforeSubcommand = subcommand.isBefore(position); var afterSubcommand = subcommand.isAfter(position); var subcommandValue = subcommand.getValue(); if ("NONE".indexOf(subcommandValue.toUpperCase()) === 0) { if (beforeSubcommand) { // after a NONE, nothing to show return null; } return { signatures: [ healthcheckNoneSignature ], activeSignature: 0, activeParameter: 0 }; } var activeHealthcheckParameter = beforeSubcommand ? 2 : afterSubcommand ? 0 : 1; return { signatures: [ healthcheckCmdNormalSignature ], activeSignature: 0, activeParameter: activeHealthcheckParameter }; case "LABEL": var labelSignatures = [ { label: "LABEL key value", documentation: this.documentation.getDocumentation("signatureLabel_Signature0"), parameters: [ { label: "key", documentation: this.documentation.getDocumentation("signatureLabel_Signature0_Param0") }, { label: "value", documentation: this.documentation.getDocumentation("signatureLabel_Signature0_Param1") } ] }, { label: "LABEL key=value", documentation: this.documentation.getDocumentation("signatureLabel_Signature1"), parameters: [ { label: "key", documentation: this.documentation.getDocumentation("signatureLabel_Signature1_Param0") }, { label: "value", documentation: this.documentation.getDocumentation("signatureLabel_Signature1_Param1") } ] }, { label: "LABEL key=value key2=value2", documentation: this.documentation.getDocumentation("signatureLabel_Signature2"), parameters: [ { label: "key", documentation: this.documentation.getDocumentation("signatureLabel_Signature2_Param0") }, { label: "value", documentation: this.documentation.getDocumentation("signatureLabel_Signature2_Param1") }, { label: "key2", documentation: this.documentation.getDocumentation("signatureLabel_Signature2_Param2") }, { label: "value2", documentation: this.documentation.getDocumentation("signatureLabel_Signature2_Param3") } ] } ]; return this.getPropertySignatureHelp(document, position, labelSignatures, instruction.getProperties()); case "MAINTAINER": return { signatures: [ { label: "MAINTAINER name", documentation: this.documentation.getDocumentation("signatureMaintainer"), parameters: [ { label: "name", documentation: this.documentation.getDocumentation("signatureMaintainer_Param") } ] } ], activeSignature: 0, activeParameter: 0 }; case "ONBUILD": var onbuildArgs = instruction.getArguments(); if (onbuildArgs.length > 0 && onbuildArgs[0].isBefore(position)) { return null; } return { signatures: [ { label: "ONBUILD INSTRUCTION", documentation: this.documentation.getDocumentation("signatureOnbuild"), parameters: [ { label: "INSTRUCTION", documentation: this.documentation.getDocumentation("signatureOnbuild_Param") } ] } ], activeSignature: 0, activeParameter: 0 }; case "RUN": var run_1 = instruction; var runShellSignature = { label: "RUN command parameter ...", documentation: this.documentation.getDocumentation("signatureRun_Signature0"), parameters: [ { label: "command", documentation: this.documentation.getDocumentation("signatureRun_Signature0_Param0") }, { label: "parameter", documentation: this.documentation.getDocumentation("signatureRun_Signature0_Param1") }, { label: "...", documentation: this.documentation.getDocumentation("signatureRun_Signature0_Param2") } ] }; var runJsonSignature = { label: "RUN [ \"command\", \"parameter\", ... ]", documentation: this.documentation.getDocumentation("signatureRun_Signature1"), parameters: [ { label: "[" }, { label: "\"command\"", documentation: this.documentation.getDocumentation("signatureRun_Signature1_Param1") }, { label: "\"parameter\"", documentation: this.documentation.getDocumentation("signatureRun_Signature1_Param2") }, { label: "...", documentation: this.documentation.getDocumentation("signatureRun_Signature1_Param3") }, { label: "]" } ] }; return this.getJSONInstructionSignatureHelp(document, run_1, position, [runJsonSignature], runShellSignature, false, false, false, true); case "SHELL": var shell = instruction; var shellSignatureHelp = { signatures: [ { label: "SHELL [ \"executable\", \"parameter\", ... ]", documentation: this.documentation.getDocumentation("signatureShell"), parameters: [ { label: "[" }, { label: "\"executable\"", documentation: this.documentation.getDocumentation("signatureShell_Param1") }, { label: "\"parameter\"", documentation: this.documentation.getDocumentation("signatureShell_Param2") }, { label: "...", documentation: this.documentation.getDocumentation("signatureShell_Param3") }, { label: "]" } ] } ], activeSignature: 0, activeParameter: null }; shellSignatureHelp.activeParameter = this.getJSONSignatureActiveParameter(document, shell, position, false, false, true); return shellSignatureHelp.activeParameter === -1 ? null : shellSignatureHelp; case "STOPSIGNAL": return { signatures: [ { label: "STOPSIGNAL signal", documentation: this.documentation.getDocumentation("signatureStopsignal"), parameters: [ { label: "signal", documentation: this.documentation.getDocumentation("signatureStopsignal_Param") } ] } ], activeSignature: 0, activeParameter: 0 }; case "USER": var userSignatureHelp = { signatures: [ { label: "USER user", documentation: this.documentation.getDocumentation("signatureUser_Signature0"), parameters: [ { label: "user", documentation: this.documentation.getDocumentation("signatureUser_Signature0_Param") } ] }, { label: "USER user:group", documentation: this.documentation.getDocumentation("signatureUser_Signature1"), parameters: [ { label: "user", documentation: this.documentation.getDocumentation("signatureUser_Signature1_Param0") }, { label: "group", documentation: this.documentation.getDocumentation("signatureUser_Signature1_Param1") } ] }, { label: "USER uid", documentation: this.documentation.getDocumentation("signatureUser_Signature2"), parameters: [ { label: "uid", documentation: this.documentation.getDocumentation("signatureUser_Signature2_Param") } ] }, { label: "USER uid:gid", documentation: this.documentation.getDocumentation("signatureUser_Signature3"), parameters: [ { label: "uid", documentation: this.documentation.getDocumentation("signatureUser_Signature3_Param0") }, { label: "gid", documentation: this.documentation.getDocumentation("signatureUser_Signature3_Param1") } ] } ], activeSignature: 0, activeParameter: 0