dockerfile-language-service
Version:
A language service for Dockerfiles to enable the creation of feature-rich Dockerfile editors.
205 lines (204 loc) • 10.2 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-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.DockerDefinition = void 0;
var vscode_languageserver_types_1 = require("vscode-languageserver-types");
var docker_1 = require("./docker");
var dockerfile_ast_1 = require("dockerfile-ast");
var DockerDefinition = /** @class */ (function () {
function DockerDefinition() {
}
DockerDefinition.prototype.computeBuildStageDefinition = function (dockerfile, position) {
var source = undefined;
for (var _i = 0, _a = dockerfile.getCOPYs(); _i < _a.length; _i++) {
var instruction = _a[_i];
var flag = instruction.getFromFlag();
if (flag) {
var range = flag.getValueRange();
if (range && range.start.line === position.line && range.start.character <= position.character && position.character <= range.end.character) {
source = flag.getValue();
break;
}
}
}
for (var _b = 0, _c = dockerfile.getFROMs(); _b < _c.length; _b++) {
var instruction = _c[_b];
var range = instruction.getBuildStageRange();
if (range) {
if (range.start.line === position.line && range.start.character <= position.character && position.character <= range.end.character) {
// cursor in FROM's build stage itself
return range;
}
else if (source !== undefined && instruction.getBuildStage().toLowerCase() === source.toLowerCase()) {
// FROM's build stage matches what's in COPY
return range;
}
}
range = instruction.getImageNameRange();
if (docker_1.Util.isInsideRange(position, range)) {
var stageName = instruction.getImageName();
for (var _d = 0, _e = dockerfile.getFROMs(); _d < _e.length; _d++) {
var from = _e[_d];
if (stageName === from.getBuildStage() && from.getRange().start.line < range.start.line) {
return from.getBuildStageRange();
}
}
return null;
}
}
return null;
};
DockerDefinition.computeVariableDefinition = function (image, position) {
var variableName = null;
for (var _i = 0, _a = image.getARGs(); _i < _a.length; _i++) {
var arg = _a[_i];
var property = arg.getProperty();
// might be an ARG with no arguments
if (property) {
// is the caret inside the definition itself
if (docker_1.Util.isInsideRange(position, property.getNameRange())) {
variableName = property.getName();
break;
}
}
}
if (variableName === null) {
variableCheck: for (var _b = 0, _c = image.getENVs(); _b < _c.length; _b++) {
var env = _c[_b];
var properties = env.getProperties();
for (var _d = 0, properties_1 = properties; _d < properties_1.length; _d++) {
var property = properties_1[_d];
// is the caret inside the definition itself
if (docker_1.Util.isInsideRange(position, property.getNameRange())) {
variableName = property.getName();
break variableCheck;
}
}
}
}
if (variableName === null) {
variableCheck: for (var _e = 0, _f = image.getInstructions(); _e < _f.length; _e++) {
var instruction = _f[_e];
for (var _g = 0, _h = instruction.getVariables(); _g < _h.length; _g++) {
var variable = _h[_g];
if (docker_1.Util.isInsideRange(position, variable.getNameRange())) {
variableName = variable.getName();
break variableCheck;
}
}
}
}
for (var _j = 0, _k = image.getInstructions(); _j < _k.length; _j++) {
var instruction = _k[_j];
if (instruction instanceof dockerfile_ast_1.Arg) {
var property = instruction.getProperty();
// might be an ARG with no arguments
if (property && property.getName() === variableName) {
return property;
}
}
else if (instruction instanceof dockerfile_ast_1.Env) {
var properties = instruction.getProperties();
for (var _l = 0, properties_2 = properties; _l < properties_2.length; _l++) {
var property = properties_2[_l];
if (property.getName() === variableName) {
return property;
}
}
}
}
return null;
};
DockerDefinition.findDefinition = function (dockerfile, position) {
for (var _i = 0, _a = dockerfile.getFROMs(); _i < _a.length; _i++) {
var from = _a[_i];
for (var _b = 0, _c = from.getVariables(); _b < _c.length; _b++) {
var variable = _c[_b];
if (docker_1.Util.isInsideRange(position, variable.getNameRange())) {
for (var _d = 0, _e = dockerfile.getInitialARGs(); _d < _e.length; _d++) {
var arg = _e[_d];
var property = arg.getProperty();
if (property && property.getName() === variable.getName()) {
return property;
}
}
return null;
}
}
}
var image = dockerfile.getContainingImage(position);
if (image === null) {
return null;
}
return DockerDefinition.computeVariableDefinition(image, position);
};
DockerDefinition.checkHeredocs = function (heredocs, position) {
for (var _i = 0, heredocs_1 = heredocs; _i < heredocs_1.length; _i++) {
var heredoc = heredocs_1[_i];
var nameRange = heredoc.getNameRange();
if (docker_1.Util.isInsideRange(position, nameRange)) {
return docker_1.Util.isEmpty(nameRange) ? null : nameRange;
}
var delimiterRange = heredoc.getDelimiterRange();
if (delimiterRange !== null && docker_1.Util.isInsideRange(position, delimiterRange)) {
return nameRange;
}
}
return null;
};
DockerDefinition.computeHeredocDefinition = function (dockerfile, position) {
for (var _i = 0, _a = dockerfile.getInstructions(); _i < _a.length; _i++) {
var instruction = _a[_i];
if (instruction instanceof dockerfile_ast_1.Copy) {
var range = DockerDefinition.checkHeredocs(instruction.getHeredocs(), position);
if (range !== null) {
return range;
}
}
else if (instruction instanceof dockerfile_ast_1.Run) {
var range = DockerDefinition.checkHeredocs(instruction.getHeredocs(), position);
if (range !== null) {
return range;
}
}
}
return null;
};
DockerDefinition.prototype.computeVariableDefinition = function (dockerfile, position) {
var property = DockerDefinition.findDefinition(dockerfile, position);
return property ? property.getNameRange() : null;
};
DockerDefinition.prototype.computeDefinitionRange = function (content, position) {
var dockerfile = dockerfile_ast_1.DockerfileParser.parse(content);
var range = this.computeBuildStageDefinition(dockerfile, position);
if (range === null) {
range = this.computeVariableDefinition(dockerfile, position);
if (range === null) {
return DockerDefinition.computeHeredocDefinition(dockerfile, position);
}
}
return range;
};
DockerDefinition.prototype.computeDefinition = function (textDocument, content, position) {
var range = this.computeDefinitionRange(content, position);
if (range !== null) {
return vscode_languageserver_types_1.Location.create(textDocument.uri, range);
}
return null;
};
return DockerDefinition;
}());
exports.DockerDefinition = DockerDefinition;
});