dockerfile-language-service
Version:
A language service for Dockerfiles to enable the creation of feature-rich Dockerfile editors.
849 lines • 52.6 kB
JavaScript
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