UNPKG

dockerfile-language-service

Version:

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

225 lines (224 loc) 11.2 kB
(function (factory) { if (typeof module === "object" && typeof module.exports === "object") { var v = factory(require, exports); if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { define(["require", "exports", "vscode-languageserver-types", "dockerfile-ast", "./docker"], 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.DockerHover = void 0; var vscode_languageserver_types_1 = require("vscode-languageserver-types"); var dockerfile_ast_1 = require("dockerfile-ast"); var docker_1 = require("./docker"); var DockerHover = /** @class */ (function () { function DockerHover(markdown, plainText) { this.markdown = markdown; this.plainText = plainText; } DockerHover.prototype.onHover = function (content, position, markupKind) { var dockerfile = dockerfile_ast_1.DockerfileParser.parse(content); var image = dockerfile.getContainingImage(position); if (!image) { // position is invalid, not inside the Dockerfile return null; } var key = this.computeHoverKey(dockerfile, position); if (key) { // if it's not a raw value, apply markup if necessary if (markupKind && markupKind.length > 0) { switch (markupKind[0]) { case vscode_languageserver_types_1.MarkupKind.Markdown: var markdownDocumentation = this.markdown.getMarkdown(key); if (markdownDocumentation) { return { contents: { kind: vscode_languageserver_types_1.MarkupKind.Markdown, value: markdownDocumentation.contents } }; } return null; case vscode_languageserver_types_1.MarkupKind.PlainText: var plainTextDocumentation = this.plainText.getDocumentation(key); if (plainTextDocumentation) { return { contents: { kind: vscode_languageserver_types_1.MarkupKind.PlainText, value: plainTextDocumentation } }; } } return null; } var hover = this.markdown.getMarkdown(key); return hover === undefined ? null : hover; } for (var _i = 0, _a = image.getInstructions(); _i < _a.length; _i++) { var instruction = _a[_i]; if (instruction instanceof dockerfile_ast_1.Arg) { // hovering over an argument defined by ARG var property = instruction.getProperty(); if (property && docker_1.Util.isInsideRange(position, property.getNameRange()) && property.getValue() !== null) { return { contents: property.getValue() }; } } if (instruction instanceof dockerfile_ast_1.Env) { // hovering over an argument defined by ENV for (var _b = 0, _c = instruction.getProperties(); _b < _c.length; _b++) { var property = _c[_b]; if (docker_1.Util.isInsideRange(position, property.getNameRange()) && property.getValue() !== null) { return { contents: property.getValue() }; } } } } for (var _d = 0, _e = image.getInstructions(); _d < _e.length; _d++) { var instruction = _e[_d]; for (var _f = 0, _g = instruction.getVariables(); _f < _g.length; _f++) { var variable = _g[_f]; // are we hovering over a variable if (docker_1.Util.isInsideRange(position, variable.getNameRange())) { var resolved = dockerfile.resolveVariable(variable.getName(), variable.getNameRange().start.line); if (resolved || resolved === "") { return { contents: resolved }; } else if (resolved === null) { return null; } } } } return null; }; /** * Analyzes the Dockerfile at the given position to determine if the user * is hovering over a keyword, a flag, or a directive. * * @param dockerfile the Dockerfile to check * @param position the place that the user is hovering over * @return the string key value for the keyword, flag, or directive that's * being hovered over, or null if the user isn't hovering over * such a word */ DockerHover.prototype.computeHoverKey = function (dockerfile, position) { for (var _i = 0, _a = dockerfile.getDirectives(); _i < _a.length; _i++) { var directive = _a[_i]; var range = directive.getNameRange(); switch (directive.getDirective()) { case dockerfile_ast_1.Directive.escape: if (docker_1.Util.isInsideRange(position, range)) { return dockerfile_ast_1.Directive.escape; } break; case dockerfile_ast_1.Directive.syntax: if (docker_1.Util.isInsideRange(position, range)) { return dockerfile_ast_1.Directive.syntax; } break; } } var image = dockerfile.getContainingImage(position); for (var _b = 0, _c = image.getInstructions(); _b < _c.length; _b++) { var instruction = _c[_b]; var instructionRange = instruction.getInstructionRange(); if (docker_1.Util.isInsideRange(position, instructionRange)) { return instruction.getKeyword(); } if (instruction instanceof dockerfile_ast_1.Onbuild) { // hovering over a trigger instruction of an ONBUILD var range = instruction.getTriggerRange(); if (docker_1.Util.isInsideRange(position, range)) { return instruction.getTrigger(); } } var hover = this.getFlagsHover(position, instruction); if (hover !== null) { return hover; } } return null; }; DockerHover.prototype.getFlagsHover = function (position, instruction) { switch (instruction.getKeyword()) { case "ADD": var addFlags = instruction.getFlags(); for (var _i = 0, addFlags_1 = addFlags; _i < addFlags_1.length; _i++) { var flag = addFlags_1[_i]; if (docker_1.Util.isInsideRange(position, flag.getNameRange())) { switch (flag.getName()) { case "chown": return "ADD_FlagChown"; } } } break; case "COPY": var copyFlags = instruction.getFlags(); for (var _a = 0, copyFlags_1 = copyFlags; _a < copyFlags_1.length; _a++) { var flag = copyFlags_1[_a]; if (docker_1.Util.isInsideRange(position, flag.getNameRange())) { switch (flag.getName()) { case "chown": return "COPY_FlagChown"; case "from": return "COPY_FlagFrom"; } } } break; case "FROM": var fromFlags = instruction.getFlags(); for (var _b = 0, fromFlags_1 = fromFlags; _b < fromFlags_1.length; _b++) { var flag = fromFlags_1[_b]; if (docker_1.Util.isInsideRange(position, flag.getNameRange())) { if (flag.getName() === "platform") { return "FROM_FlagPlatform"; } return null; } } break; case "HEALTHCHECK": var flags = instruction.getFlags(); for (var _c = 0, flags_1 = flags; _c < flags_1.length; _c++) { var flag = flags_1[_c]; if (docker_1.Util.isInsideRange(position, flag.getNameRange())) { switch (flag.getName()) { case "interval": return "HEALTHCHECK_FlagInterval"; case "retries": return "HEALTHCHECK_FlagRetries"; case "start-interval": return "HEALTHCHECK_FlagStartInterval"; case "start-period": return "HEALTHCHECK_FlagStartPeriod"; case "timeout": return "HEALTHCHECK_FlagTimeout"; } return null; } } break; case "ONBUILD": var trigger = instruction.getTriggerInstruction(); if (trigger !== null) { return this.getFlagsHover(position, trigger); } break; } return null; }; return DockerHover; }()); exports.DockerHover = DockerHover; });