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
JavaScript
(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