UNPKG

dockerfile-language-service

Version:

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

849 lines 52.6 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; (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-types", "./docker", "dockerfile-ast"], factory); } })(function (require, exports) { /* -------------------------------------------------------------------------------------------- * Copyright (c) Remy Suen. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.DockerAssist = void 0; var vscode_languageserver_types_1 = require("vscode-languageserver-types"); var docker_1 = require("./docker"); var dockerfile_ast_1 = require("dockerfile-ast"); var DockerAssist = /** @class */ (function () { /** * Creates a content assist processor for suggesting completion items related to a Dockerfile. * * @param document the text document to provide suggestions for * @param dockerRegistryClient the client for communicating with a Docker registry * @param completionItemCapabilities the capabilities that should be set for the returned items */ function DockerAssist(document, dockerRegistryClient, completionItemCapabilities) { this.document = document; this.dockerRegistryClient = dockerRegistryClient; this.deprecatedSupport = completionItemCapabilities && completionItemCapabilities.deprecatedSupport; this.snippetSupport = completionItemCapabilities && completionItemCapabilities.snippetSupport; this.supportedTags = completionItemCapabilities && completionItemCapabilities.tagSupport && completionItemCapabilities.tagSupport.valueSet; } DockerAssist.prototype.computeProposals = function (position) { var buffer = this.document.getText(); var offset = this.document.offsetAt(position); var dockerfile = dockerfile_ast_1.DockerfileParser.parse(buffer); var escapeCharacter = dockerfile.getEscapeCharacter(); var lastDirectiveLine = -1; for (var _i = 0, _a = dockerfile.getDirectives(); _i < _a.length; _i++) { var directive = _a[_i]; var range = directive.getNameRange(); lastDirectiveLine = range.start.line; if (position.line === lastDirectiveLine) { if (position.character <= range.start.character) { // in whitespace before the directive's name return [ this.createEscape(0, offset, dockerfile_ast_1.Directive.escape), this.createSyntax(0, offset, dockerfile_ast_1.Directive.syntax) ]; } else if (position.character <= range.end.character) { // in the name var prefix_1 = directive.getName().substring(0, position.character - range.start.character); prefix_1 = prefix_1.toLowerCase(); if (dockerfile_ast_1.Directive.escape.indexOf(prefix_1) === 0) { return [this.createEscape(prefix_1.length, offset, dockerfile_ast_1.Directive.escape)]; } else if (dockerfile_ast_1.Directive.syntax.indexOf(prefix_1) === 0) { return [this.createSyntax(prefix_1.length, offset, dockerfile_ast_1.Directive.syntax)]; } } return []; } } // directive only possible on the first line var comments = dockerfile.getComments(); if (comments.length !== 0) { if (position.line === lastDirectiveLine + 1) { var commentRange = comments[0].getRange(); // check if the first comment is on the first line if (commentRange.start.line === position.line) { // is the user inside the comment if (commentRange.start.character < position.character) { var range = comments[0].getContentRange(); if (range === null || position.character <= range.start.character) { // in whitespace return [ this.createEscape(0, offset, dockerfile_ast_1.Directive.escape), this.createSyntax(0, offset, dockerfile_ast_1.Directive.syntax), ]; } var comment = comments[0].getContent(); if (position.character <= range.end.character) { // within the content var prefix_2 = comment.substring(0, position.character - range.start.character); // substring check if (dockerfile_ast_1.Directive.escape.indexOf(prefix_2.toLowerCase()) === 0) { return [this.createEscape(prefix_2.length, offset, dockerfile_ast_1.Directive.escape)]; } else if (dockerfile_ast_1.Directive.syntax.indexOf(prefix_2.toLowerCase()) === 0) { return [this.createSyntax(prefix_2.length, offset, dockerfile_ast_1.Directive.syntax)]; } } return []; } } } else { for (var _b = 0, comments_1 = comments; _b < comments_1.length; _b++) { var comment = comments_1[_b]; var range = comment.getRange(); if (range.start.line === position.line) { if (range.start.character < position.character && position.character <= range.end.character) { // inside a comment return []; } } } } } var prefix = this.calculateTruePrefix(dockerfile, buffer, offset, escapeCharacter); if (prefix.content !== "") { var index = prefix.content.lastIndexOf('$'); // $ exists so we're at a variable if (index !== -1) { // check that the variable $ wasn't escaped if (prefix.content.charAt(index - 1) !== '\\') { // get the variable's prefix thus far var variablePrefix = prefix.content.substring(index + 1).toLowerCase(); var prefixLength = variablePrefix.length + 1; var items = []; if (variablePrefix === "") { // empty prefix, return all variables for (var _c = 0, _d = dockerfile.getAvailableVariables(position.line); _c < _d.length; _c++) { var variable = _d[_c]; var doc = dockerfile.resolveVariable(variable, position.line); items.push(this.createVariableCompletionItem(variable, prefixLength, offset, true, doc)); } for (var _e = 0, DefaultVariables_1 = dockerfile_ast_1.DefaultVariables; _e < DefaultVariables_1.length; _e++) { var variable = DefaultVariables_1[_e]; var doc = dockerfile.resolveVariable(variable, position.line); items.push(this.createVariableCompletionItem(variable, prefixLength, offset, true, doc)); } } else { var brace = false; if (variablePrefix.charAt(0) === '{') { brace = true; variablePrefix = variablePrefix.substring(1); } // merge list of available variables with the defaults var variables = dockerfile.getAvailableVariables(position.line); for (var _f = 0, DefaultVariables_2 = dockerfile_ast_1.DefaultVariables; _f < DefaultVariables_2.length; _f++) { var variable = DefaultVariables_2[_f]; if (variables.indexOf(variable) === -1) { variables.push(variable); } } for (var _g = 0, variables_1 = variables; _g < variables_1.length; _g++) { var variable = variables_1[_g]; if (variable.toLowerCase().indexOf(variablePrefix) === 0) { var doc = dockerfile.resolveVariable(variable, position.line); items.push(this.createVariableCompletionItem(variable, prefixLength, offset, brace, doc)); } } } items.sort(function (a, b) { if (a.label.toLowerCase() === b.label.toLowerCase()) { // put uppercase variables first return a.label.localeCompare(b.label) * -1; } return a.label.localeCompare(b.label); }); return items; } } } var previousWord = ""; instructionsCheck: for (var _h = 0, _j = dockerfile.getInstructions(); _h < _j.length; _h++) { var instruction = _j[_h]; if (docker_1.Util.isInsideRange(position, instruction.getInstructionRange()) || prefix.content === instruction.getKeyword()) { break; } else if (docker_1.Util.isInsideRange(position, instruction.getRange())) { switch (instruction.getKeyword()) { case "ADD": return this.createAddProposals(dockerfile, instruction, position, offset, prefix.content); case "COPY": return this.createCopyProposals(dockerfile, instruction, position, offset, prefix.content); case "FROM": return this.createFromProposals(instruction, position, offset, prefix.content); case "HEALTHCHECK": var subcommand = instruction.getSubcommand(); if (subcommand && subcommand.isBefore(position)) { return []; } return this.createHealthcheckProposals(offset, prefix.content); case "ONBUILD": var onbuildArgs = instruction.getArguments(); if (onbuildArgs.length === 0 || docker_1.Util.isInsideRange(position, onbuildArgs[0].getRange())) { // no trigger instructions or the cursor is in the trigger instruction previousWord = "ONBUILD"; break instructionsCheck; } else { var trigger = instruction.getTriggerInstruction(); switch (trigger.getKeyword()) { case "ADD": return this.createAddProposals(dockerfile, trigger, position, offset, prefix.content); case "COPY": return this.createCopyProposals(dockerfile, trigger, position, offset, prefix.content); case "HEALTHCHECK": var subcommand_1 = trigger.getSubcommand(); if (subcommand_1 && subcommand_1.isBefore(position)) { return []; } return this.createHealthcheckProposals(offset, prefix.content); } } return []; default: return []; } } } if (prefix.content === "") { if (dockerfile.getInstructions().length === 0) { // if we don't have any instructions, only suggest FROM return [this.createFROM(0, offset, "FROM")]; } // no prefix, return all the proposals return this.createProposals(docker_1.KEYWORDS, previousWord, 0, offset); } var suggestions = []; var uppercasePrefix = prefix.content.toUpperCase(); for (var i = 0; i < docker_1.KEYWORDS.length; i++) { if (docker_1.KEYWORDS[i] === uppercasePrefix) { // prefix is a keyword already, nothing to suggest return []; } else if (docker_1.KEYWORDS[i].indexOf(uppercasePrefix) === 0) { suggestions.push(docker_1.KEYWORDS[i]); } } if (suggestions.length === 0) { // prefix doesn't match any keywords, nothing to suggest return []; } return this.createProposals(suggestions, previousWord, offset - prefix.offset, offset); }; DockerAssist.prototype.createProposals = function (keywords, previousWord, prefixLength, offset) { var proposals = []; for (var i = 0; i < keywords.length; i++) { switch (keywords[i]) { case "ARG": if (this.snippetSupport) { proposals.push(this.createARG_NameOnly(prefixLength, offset)); proposals.push(this.createARG_DefaultValue(prefixLength, offset)); } else { proposals.push(this.createARG(prefixLength, offset)); } break; case "HEALTHCHECK": proposals.push(this.createHEALTHCHECK_CMD(prefixLength, offset)); proposals.push(this.createHEALTHCHECK_NONE(prefixLength, offset)); break; case "FROM": case "MAINTAINER": case "ONBUILD": // can't have FROM, MAINTAINER, or ONBUILD follow an ONBUILD if (previousWord) { break; } default: proposals.push(this.createSingleProposals(keywords[i], prefixLength, offset)); break; } } return proposals; }; DockerAssist.prototype.createAddProposals = function (dockerfile, add, position, offset, prefix) { var fnMap = new Map(); fnMap.set("chown", this.createADD_FlagChown.bind(this)); var args = add.getArguments(); var flagProposals = this.createFlagProposals(add.getFlags(), args, position, offset, prefix, fnMap); if (flagProposals !== null) { return flagProposals; } return this.createTargetFolderProposals(dockerfile, args, position, offset, prefix); }; DockerAssist.prototype.createOtherFlagProposals = function (flagProposalsMap, allProposals, skipList, prefixLength, offset) { if (skipList.length === 0) { // have nothing, return everything return allProposals; } if (skipList.length === flagProposalsMap.size) { // have everything, return nothing return []; } var flagProposals = []; flagProposalsMap.forEach(function (_, key) { if (skipList.indexOf(key) === -1) { flagProposals.push(key); } }); return flagProposals.map(function (flag) { var func = flagProposalsMap.get(flag); return func(prefixLength, offset); }); }; DockerAssist.prototype.createFlagProposals = function (flags, args, position, offset, prefix, flagProposalsMap) { var allProposals = []; flagProposalsMap.forEach(function (createFlagProposalItem) { allProposals.push(createFlagProposalItem(prefix.length, offset)); }); var promptFlags = true; if (args.length > 0 && docker_1.Util.positionBefore(args[0].getRange().start, this.document.positionAt(offset))) { // current position is not before the first argument, don't prompt flags promptFlags = false; } var skipList = []; var insideFlag = false; for (var _i = 0, flags_1 = flags; _i < flags_1.length; _i++) { var flag = flags_1[_i]; var name = flag.getName(); if (flagProposalsMap.has(name)) { skipList.push(name); } if (docker_1.Util.isInsideRange(position, flag.getRange())) { insideFlag = true; } } if (insideFlag) { if (prefix === "--") { return this.createOtherFlagProposals(flagProposalsMap, allProposals, skipList, prefix.length, offset); } var item_1 = null; flagProposalsMap.forEach(function (fn, flagName) { if ("--".concat(flagName, "=").indexOf(prefix) === 0) { item_1 = fn(prefix.length, offset); } }); if (item_1 !== null) { return [item_1]; } } if (promptFlags || (args.length > 0 && docker_1.Util.isInsideRange(position, args[0].getRange()) && prefix === "-")) { return this.createOtherFlagProposals(flagProposalsMap, allProposals, skipList, prefix.length, offset); } return null; }; DockerAssist.prototype.createCopyProposals = function (dockerfile, copy, position, offset, prefix) { var flag = copy.getFromFlag(); // is the user in the --from= area if (flag && docker_1.Util.isInsideRange(position, flag.getValueRange())) { var names = {}; var items = []; var stageIndex = 0; // determines if the last build stage was named or not var lastNumber = false; // get the prefix var stagePrefix = this.document.getText().substring(this.document.offsetAt(flag.getValueRange().start), offset).toLowerCase(); for (var _i = 0, _a = dockerfile.getFROMs(); _i < _a.length; _i++) { var from = _a[_i]; if (copy.isAfter(from)) { var image = from.getImage(); var stage = from.getBuildStage(); if (stage) { var lowercase = stage.toLowerCase(); if (lowercase.indexOf(stagePrefix) === 0 && !names[lowercase]) { names[lowercase] = true; items.push(this.createSourceImageCompletionItem(stage, image, stageIndex, stagePrefix.length, offset)); } lastNumber = false; } else if (!names[stageIndex]) { names[stageIndex] = true; items.push(this.createSourceImageCompletionItem(stageIndex.toString(), image, stageIndex, stagePrefix.length, offset)); lastNumber = true; } stageIndex++; } else { break; } } // last build stage was not named, don't suggest it as it is recursive if (lastNumber && items.length > 0) { items.pop(); } return items; } var fnMap = new Map(); fnMap.set("chown", this.createCOPY_FlagChown.bind(this)); fnMap.set("from", this.createCOPY_FlagFrom.bind(this)); var args = copy.getArguments(); var flagProposals = this.createFlagProposals(copy.getFlags(), args, position, offset, prefix, fnMap); if (flagProposals !== null) { return flagProposals; } return this.createTargetFolderProposals(dockerfile, args, position, offset, prefix); }; DockerAssist.prototype.createTargetFolderProposals = function (dockerfile, args, position, offset, prefix) { if (args.length === 1) { // after the one and only argument, suggest folder names if (docker_1.Util.positionBefore(args[0].getRange().end, position)) { return this.createWorkdirPathProposals(dockerfile, position, offset, prefix); } return []; } var lastRange = args[args.length - 1].getRange(); if (docker_1.Util.isInsideRange(position, lastRange) || docker_1.Util.positionBefore(lastRange.end, position)) { // in the last argument or after the last argument return this.createWorkdirPathProposals(dockerfile, position, offset, prefix); } return []; }; DockerAssist.prototype.createWorkdirPathProposals = function (dockerfile, position, offset, prefix) { var items = []; for (var _i = 0, _a = dockerfile.getAvailableWorkingDirectories(position.line); _i < _a.length; _i++) { var directory = _a[_i]; if (directory.startsWith(prefix)) { items.push(this.createPlainTextCompletionItem(directory, prefix.length, offset, directory, vscode_languageserver_types_1.CompletionItemKind.Folder)); } } return items; }; DockerAssist.prototype.createFromProposals = function (from, position, offset, prefix) { var _this = this; // checks if the cursor is in the image's tag area if (docker_1.Util.isInsideRange(position, from.getImageTagRange())) { var index = prefix.indexOf(':'); var lastIndex = prefix.indexOf(':'); if (index === lastIndex) { prefix = prefix.substring(index + 1); } else { prefix = prefix.substring(index + 1, lastIndex); } var client_1 = this.dockerRegistryClient; return new Promise(function (resolve) { return __awaiter(_this, void 0, void 0, function () { var items, tags, _i, tags_1, tag; return __generator(this, function (_a) { switch (_a.label) { case 0: items = []; return [4 /*yield*/, client_1.getTags(from.getImageName())]; case 1: tags = _a.sent(); for (_i = 0, tags_1 = tags; _i < tags_1.length; _i++) { tag = tags_1[_i]; if (tag.indexOf(prefix) === 0) { items.push({ textEdit: this.createTextEdit(prefix.length, this.document.offsetAt(position), tag), label: tag, kind: vscode_languageserver_types_1.CompletionItemKind.Property, insertTextFormat: vscode_languageserver_types_1.InsertTextFormat.PlainText, }); } } resolve(items); return [2 /*return*/]; } }); }); }); } var args = from.getArguments(); if (args.length > 0 && args[0].isBefore(position)) { return []; } if ("--platform".indexOf(prefix) === 0) { return [this.createFROM_FlagPlatform(prefix.length, offset)]; } return []; }; DockerAssist.prototype.createHealthcheckProposals = function (offset, prefix) { var items = []; if (prefix.length < 3 && "CMD".indexOf(prefix.toUpperCase()) === 0) { items.push(this.createHEALTHCHECK_CMD_Subcommand(prefix.length, offset)); } if (prefix.length < 4 && "NONE".indexOf(prefix.toUpperCase()) === 0) { items.push(this.createHEALTHCHECK_NONE_Subcommand(prefix.length, offset)); } if ("--interval".indexOf(prefix) === 0) { items.push(this.createHEALTHCHECK_FlagInterval(prefix.length, offset)); } if ("--retries".indexOf(prefix) === 0) { items.push(this.createHEALTHCHECK_FlagRetries(prefix.length, offset)); } if ("--start-interval".indexOf(prefix) === 0) { items.push(this.createHEALTHCHECK_FlagStartInterval(prefix.length, offset)); } if ("--start-period".indexOf(prefix) === 0) { items.push(this.createHEALTHCHECK_FlagStartPeriod(prefix.length, offset)); } if ("--timeout".indexOf(prefix) === 0) { items.push(this.createHEALTHCHECK_FlagTimeout(prefix.length, offset)); } for (var i = 0; i < items.length; i++) { items[i].sortText = i.toString(); } return items; }; /** * Walks back in the text buffer to calculate the true prefix of the * current text caret offset. This function will handle the * Dockerfile escape characters to skip escaped newline characters * where applicable. * * @param buffer the content of the opened file * @param offset the current text caret's offset * @param escapeCharacter the escape character defined in this Dockerfile */ DockerAssist.prototype.calculateTruePrefix = function (dockerfile, buffer, offset, escapeCharacter) { var char = buffer.charAt(offset - 1); var checkEscape = true; switch (char) { case '\n': var escapedPrefix = ""; escapeCheck: for (var i = offset - 2; i >= 0; i--) { switch (buffer.charAt(i)) { case ' ': case '\t': if (!checkEscape) { break escapeCheck; } break; case '\r': case '\n': checkEscape = true; break; case escapeCharacter: if (checkEscape) { checkEscape = false; continue; } break; default: if (checkEscape) { break escapeCheck; } offset = i; escapedPrefix = buffer.charAt(i).toUpperCase() + escapedPrefix; break; } } if (escapedPrefix !== "") { return { content: escapedPrefix, offset: offset }; } break; case '\r': case ' ': case '\t': break; default: checkEscape = false; var truePrefix = char; for (var i_1 = offset - 2; i_1 >= 0; i_1--) { char = buffer.charAt(i_1); if (docker_1.Util.isNewline(char)) { checkEscape = true; } else if (docker_1.Util.isWhitespace(char)) { if (checkEscape) { continue; } break; } else { if (char === escapeCharacter) { if (checkEscape) { checkEscape = false; continue; } } else if (checkEscape) { break; } truePrefix = char + truePrefix; } } for (var _i = 0, _a = dockerfile.getInstructions(); _i < _a.length; _i++) { var instruction = _a[_i]; var instructionRange = instruction.getInstructionRange(); var startOffset = this.document.offsetAt(instructionRange.start); if (startOffset <= offset && offset <= this.document.offsetAt(instructionRange.end)) { return { content: truePrefix, offset: startOffset }; } for (var _b = 0, _c = instruction.getArguments(); _b < _c.length; _b++) { var arg = _c[_b]; var argRange = arg.getRange(); var startOffset_1 = this.document.offsetAt(argRange.start); if (startOffset_1 <= offset && offset <= this.document.offsetAt(argRange.end)) { return { content: truePrefix, offset: startOffset_1 }; } } if (instruction instanceof dockerfile_ast_1.ModifiableInstruction) { for (var _d = 0, _e = instruction.getFlags(); _d < _e.length; _d++) { var flag = _e[_d]; var flagRange = flag.getRange(); var startOffset_2 = this.document.offsetAt(flagRange.start); if (startOffset_2 <= offset && offset <= this.document.offsetAt(flagRange.end)) { return { content: truePrefix, offset: startOffset_2 }; } } } } } return { content: "", offset: offset }; }; DockerAssist.prototype.createSingleProposals = function (keyword, prefixLength, offset) { switch (keyword) { case "ADD": return this.createADD(prefixLength, offset, keyword); case "CMD": return this.createCMD(prefixLength, offset, keyword); case "COPY": return this.createCOPY(prefixLength, offset, keyword); case "ENTRYPOINT": return this.createENTRYPOINT(prefixLength, offset, keyword); case "ENV": return this.createENV(prefixLength, offset, keyword); case "EXPOSE": return this.createEXPOSE(prefixLength, offset, keyword); case "FROM": return this.createFROM(prefixLength, offset, keyword); case "LABEL": return this.createLABEL(prefixLength, offset, keyword); case "MAINTAINER": return this.createMAINTAINER(prefixLength, offset, keyword); case "ONBUILD": return this.createONBUILD(prefixLength, offset, keyword); case "RUN": return this.createRUN(prefixLength, offset, keyword); case "SHELL": return this.createSHELL(prefixLength, offset, keyword); case "STOPSIGNAL": return this.createSTOPSIGNAL(prefixLength, offset, keyword); case "WORKDIR": return this.createWORKDIR(prefixLength, offset, keyword); case "VOLUME": return this.createVOLUME(prefixLength, offset, keyword); case "USER": return this.createUSER(prefixLength, offset, keyword); } throw new Error("Unknown keyword found: " + keyword); }; DockerAssist.prototype.createADD = function (prefixLength, offset, markdown) { return this.createKeywordCompletionItem("ADD", "ADD source dest", prefixLength, offset, "ADD ${1:source} ${2:dest}", markdown); }; DockerAssist.prototype.createARG = function (prefixLength, offset) { return this.createKeywordCompletionItem("ARG", "ARG", prefixLength, offset, "ARG", "ARG"); }; DockerAssist.prototype.createARG_NameOnly = function (prefixLength, offset) { return this.createKeywordCompletionItem("ARG", "ARG name", prefixLength, offset, "ARG ${1:name}", "ARG_NameOnly"); }; DockerAssist.prototype.createARG_DefaultValue = function (prefixLength, offset) { return this.createKeywordCompletionItem("ARG", "ARG name=defaultValue", prefixLength, offset, "ARG ${1:name}=${2:defaultValue}", "ARG_DefaultValue"); }; DockerAssist.prototype.createCMD = function (prefixLength, offset, markdown) { return this.createKeywordCompletionItem("CMD", "CMD [ \"executable\" ]", prefixLength, offset, "CMD [ \"${1:executable}\" ]", markdown); }; DockerAssist.prototype.createCOPY = function (prefixLength, offset, markdown) { return this.createKeywordCompletionItem("COPY", "COPY source dest", prefixLength, offset, "COPY ${1:source} ${2:dest}", markdown); }; DockerAssist.prototype.createENTRYPOINT = function (prefixLength, offset, markdown) { return this.createKeywordCompletionItem("ENTRYPOINT", "ENTRYPOINT [ \"executable\" ]", prefixLength, offset, "ENTRYPOINT [ \"${1:executable}\" ]", markdown); }; DockerAssist.prototype.createENV = function (prefixLength, offset, markdown) { return this.createKeywordCompletionItem("ENV", "ENV key=value", prefixLength, offset, "ENV ${1:key}=${2:value}", markdown); }; DockerAssist.prototype.createEXPOSE = function (prefixLength, offset, markdown) { return this.createKeywordCompletionItem("EXPOSE", "EXPOSE port", prefixLength, offset, "EXPOSE ${1:port}", markdown); }; DockerAssist.prototype.createFROM = function (prefixLength, offset, markdown) { return this.createKeywordCompletionItem("FROM", "FROM baseImage", prefixLength, offset, "FROM ${1:baseImage}", markdown); }; DockerAssist.prototype.createHEALTHCHECK_CMD = function (prefixLength, offset) { if (this.snippetSupport) { return this.createKeywordCompletionItem("HEALTHCHECK", "HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 CMD [ \"executable\" ]", prefixLength, offset, "HEALTHCHECK --interval=${1:30s} --timeout=${2:30s} --start-period=${3:5s} --retries=${4:3} CMD [ \"${5:executable}\" ]", "HEALTHCHECK_CMD"); } var textEdit = this.createTextEdit(prefixLength, offset, "HEALTHCHECK CMD"); return { data: "HEALTHCHECK_CMD", textEdit: textEdit, label: "HEALTHCHECK CMD", kind: vscode_languageserver_types_1.CompletionItemKind.Keyword, insertTextFormat: vscode_languageserver_types_1.InsertTextFormat.PlainText, }; }; DockerAssist.prototype.createHEALTHCHECK_CMD_Subcommand = function (prefixLength, offset) { if (this.snippetSupport) { return this.createKeywordCompletionItem("CMD", "CMD [ \"executable\" ]", prefixLength, offset, "CMD [ \"${1:executable}\" ]", "HEALTHCHECK_CMD"); } var textEdit = this.createTextEdit(prefixLength, offset, "CMD"); return { data: "HEALTHCHECK_CMD", textEdit: textEdit, label: "CMD", kind: vscode_languageserver_types_1.CompletionItemKind.Keyword, insertTextFormat: vscode_languageserver_types_1.InsertTextFormat.PlainText, }; }; DockerAssist.prototype.createADD_FlagChown = function (prefixLength, offset) { if (this.snippetSupport) { return this.createFlagCompletionItem("--chown=user:group", prefixLength, offset, "--chown=${1:user\:group}", "ADD_FlagChown"); } return this.createFlagCompletionItem("--chown=", prefixLength, offset, "--chown=", "ADD_FlagChown"); }; DockerAssist.prototype.createCOPY_FlagChown = function (prefixLength, offset) { if (this.snippetSupport) { return this.createFlagCompletionItem("--chown=user:group", prefixLength, offset, "--chown=${1:user\:group}", "COPY_FlagChown"); } return this.createFlagCompletionItem("--chown=", prefixLength, offset, "--chown=", "COPY_FlagChown"); }; DockerAssist.prototype.createCOPY_FlagFrom = function (prefixLength, offset) { if (this.snippetSupport) { return this.createFlagCompletionItem("--from=stage", prefixLength, offset, "--from=${1:stage}", "COPY_FlagFrom"); } return this.createFlagCompletionItem("--from=", prefixLength, offset, "--from=", "COPY_FlagFrom"); }; DockerAssist.prototype.createFROM_FlagPlatform = function (prefixLength, offset) { if (this.snippetSupport) { return this.createFlagCompletionItem("--platform=arm64", prefixLength, offset, "--platform=${1:arm64}", "FROM_FlagPlatform"); } return this.createFlagCompletionItem("--platform=", prefixLength, offset, "--platform=", "FROM_FlagPlatform"); }; DockerAssist.prototype.createHEALTHCHECK_FlagInterval = function (prefixLength, offset) { if (this.snippetSupport) { return this.createFlagCompletionItem("--interval=30s", prefixLength, offset, "--interval=${1:30s}", "HEALTHCHECK_FlagInterval"); } return this.createFlagCompletionItem("--interval=", prefixLength, offset, "--interval=", "HEALTHCHECK_FlagInterval"); }; DockerAssist.prototype.createHEALTHCHECK_FlagRetries = function (prefixLength, offset) { if (this.snippetSupport) { return this.createFlagCompletionItem("--retries=3", prefixLength, offset, "--retries=${1:3}", "HEALTHCHECK_FlagRetries"); } return this.createFlagCompletionItem("--retries=", prefixLength, offset, "--retries=", "HEALTHCHECK_FlagRetries"); }; DockerAssist.prototype.createHEALTHCHECK_FlagStartInterval = function (prefixLength, offset) { if (this.snippetSupport) { return this.createFlagCompletionItem("--start-interval=5s", prefixLength, offset, "--start-interval=${1:5s}", "HEALTHCHECK_FlagStartInterval"); } return this.createFlagCompletionItem("--start-interval=", prefixLength, offset, "--start-interval=", "HEALTHCHECK_FlagStartInterval"); }; DockerAssist.prototype.createHEALTHCHECK_FlagStartPeriod = function (prefixLength, offset) { if (this.snippetSupport) { return this.createFlagCompletionItem("--start-period=5s", prefixLength, offset, "--start-period=${1:5s}", "HEALTHCHECK_FlagStartPeriod"); } return this.createFlagCompletionItem("--start-period=", prefixLength, offset, "--start-period=", "HEALTHCHECK_FlagStartPeriod"); }; DockerAssist.prototype.createHEALTHCHECK_FlagTimeout = function (prefixLength, offset) { if (this.snippetSupport) { return this.createFlagCompletionItem("--timeout=30s", prefixLength, offset, "--timeout=${1:30s}", "HEALTHCHECK_FlagTimeout"); } return this.createFlagCompletionItem("--timeout=", prefixLength, offset, "--timeout=", "HEALTHCHECK_FlagTimeout"); }; DockerAssist.prototype.createHEALTHCHECK_NONE = function (prefixLength, offset) { return this.createPlainTextCompletionItem("HEALTHCHECK NONE", prefixLength, offset, "HEALTHCHECK NONE", vscode_languageserver_types_1.CompletionItemKind.Keyword, "HEALTHCHECK_NONE"); }; DockerAssist.prototype.createHEALTHCHECK_NONE_Subcommand = function (prefixLength, offset) { return this.createPlainTextCompletionItem("NONE", prefixLength, offset, "NONE", vscode_languageserver_types_1.CompletionItemKind.Keyword, "HEALTHCHECK_NONE"); }; DockerAssist.prototype.createLABEL = function (prefixLength, offset, markdown) { return this.createKeywordCompletionItem("LABEL", "LABEL key=\"value\"", prefixLength, offset, "LABEL ${1:key}=\"${2:value}\"", markdown); }; DockerAssist.prototype.createMAINTAINER = function (prefixLength, offset, markdown) { var item = this.createKeywordCompletionItem("MAINTAINER", "MAINTAINER name", prefixLength, offset, "MAINTAINER ${1:name}", markdown); if (this.supportedTags !== undefined && this.supportedTags.length > 0 && this.supportedTags.indexOf(vscode_languageserver_types_1.CompletionItemTag.Deprecated) >= 0) { item.tags = [vscode_languageserver_types_1.CompletionItemTag.Deprecated]; } if (this.deprecatedSupport) { item.deprecated = true; } return item; }; DockerAssist.prototype.createONBUILD = function (prefixLength, offset, markdown) { return this.createKeywordCompletionItem("ONBUILD", "ONBUILD INSTRUCTION", prefixLength, offset, "ONBUILD ${1:INSTRUCTION}", markdown); }; DockerAssist.prototype.createRUN = function (prefixLength, offset, markdown) { return this.createKeywordCompletionItem("RUN", "RUN command", prefixLength, offset, "RUN ${1:command}", markdown); }; DockerAssist.prototype.createSHELL = function (prefixLength, offset, markdown) { return this.createKeywordCompletionItem("SHELL", "SHELL [ \"executable\" ]", prefixLength, offset, "SHELL [ \"${1:executable}\" ]", markdown); }; DockerAssist.prototype.createSTOPSIGNAL = function (prefixLength, offset, markdown) { return this.createKeywordCompletionItem("STOPSIGNAL", "STOPSIGNAL signal", prefixLength, offset, "STOPSIGNAL ${1:signal}", markdown); }; DockerAssist.prototype.createUSER = function (prefixLength, offset, markdown) { return this.createKeywordCompletionItem("USER", "USER daemon", prefixLength, offset, "USER ${1:daemon}", markdown); }; DockerAssist.prototype.createVOLUME = function (prefixLength, offset, markdown) { return this.createKeywordCompletionItem("VOLUME", "VOLUME [ \"/data\" ]", prefixLength, offset, "VOLUME [ \"${1:/data}\" ]", markdown); }; DockerAssist.prototype.createWORKDIR = function (prefixLength, offset, markdown) { return this.createKeywordCompletionItem("WORKDIR", "WORKDIR /the/workdir/path", prefixLength, offset, "WORKDIR ${1:/the/workdir/path}", markdown); }; DockerAssist.prototype.createEscape = function (prefixLength, offset, markdown) { return this.createKeywordCompletionItem(dockerfile_ast_1.Directive.escape, "escape=`", prefixLength, offset, "escape=${1:`}", markdown); }; DockerAssist.prototype.createSyntax = function (prefixLength, offset, markdown) { return this.createKeywordCompletionItem(dockerfile_ast_1.Directive.syntax, "syntax=docker/dockerfile:experimental", prefixLength, offset, "syntax=${1:docker/dockerfile:experimental}", markdown); }; DockerAssist.prototype.createKeywordCompletionItem = function (keyword, label, prefixLength, offset, insertText, markdown) { if (!this.snippetSupport) { // only inserting the keyword so set the label to the keyword label = keyword; // just insert the keyword if snippets are not supported by the client insertText = keyword; } var textEdit = this.createTextEdit(prefixLength, offset, insertText); return { data: markdown, textEdit: textEdit, label: label, kind: vscode_languageserver_types_1.CompletionItemKind.Keyword, insertTextFormat: this.snippetSupport ? vscode_languageserver_types_1.InsertTextFormat.Snippet : vscode_languageserver_types_1.InsertTextFormat.PlainText, }; }; DockerAssist.prototype.createPlainTextCompletionItem = function (label, prefixLength, offset, inser