dockerfile-language-service
Version:
A language service for Dockerfiles to enable the creation of feature-rich Dockerfile editors.
174 lines (173 loc) • 8.53 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", "vscode-languageserver-types", "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.DockerFormatter = void 0;
var vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
var vscode_languageserver_types_1 = require("vscode-languageserver-types");
var dockerfile_ast_1 = require("dockerfile-ast");
var DockerFormatter = /** @class */ (function () {
function DockerFormatter() {
}
DockerFormatter.prototype.getIndentation = function (formattingOptions) {
var indentation = "\t";
if (formattingOptions && formattingOptions.insertSpaces) {
indentation = "";
for (var i = 0; i < formattingOptions.tabSize; i++) {
indentation = indentation + " ";
}
}
return indentation;
};
/**
* Creates a TextEdit for formatting the given document.
*
* @param document the document being formatted
* @param start the start offset of the document's content to be replaced
* @param end the end offset of the document's content to be replaced
* @param indent true if this block should be replaced with an indentation, false otherwise
* @param indentation the string to use for an indentation
*/
DockerFormatter.prototype.createFormattingEdit = function (document, start, end, indent, indentation) {
if (indent) {
return vscode_languageserver_types_1.TextEdit.replace({
start: document.positionAt(start),
end: document.positionAt(end)
}, indentation);
}
else {
return vscode_languageserver_types_1.TextEdit.del({
start: document.positionAt(start),
end: document.positionAt(end)
});
}
};
DockerFormatter.prototype.formatOnType = function (content, position, ch, options) {
var dockerfile = dockerfile_ast_1.DockerfileParser.parse(content);
// check that the inserted character is the escape character
if (dockerfile.getEscapeCharacter() === ch) {
for (var _i = 0, _a = dockerfile.getComments(); _i < _a.length; _i++) {
var comment = _a[_i];
// ignore if we're in a comment
if (comment.getRange().start.line === position.line) {
return [];
}
}
var directive = dockerfile.getDirective();
// ignore if we're in the parser directive
if (directive && position.line === 0) {
return [];
}
var document = vscode_languageserver_textdocument_1.TextDocument.create("", "", 0, content);
validityCheck: for (var i = document.offsetAt(position); i < content.length; i++) {
switch (content.charAt(i)) {
case ' ':
case '\t':
break;
case '\r':
case '\n':
break validityCheck;
default:
// not escaping a newline, no need to format the next line
return [];
}
}
var lines = [position.line + 1];
var indentedLines = [];
indentedLines[lines[0]] = true;
return this.formatLines(document, document.getText(), lines, indentedLines, options);
}
return [];
};
DockerFormatter.prototype.formatRange = function (content, range, options) {
var lines = [];
for (var i = range.start.line; i <= range.end.line; i++) {
lines.push(i);
}
return this.format(content, lines, options);
};
/**
* Formats the specified lines of the given document based on the
* provided formatting options.
*
* @param document the text document to format
* @param lines the lines to format
* @param options the formatting options to use to perform the format
* @return the text edits to apply to format the lines of the document
*/
DockerFormatter.prototype.format = function (content, lines, options) {
var document = vscode_languageserver_textdocument_1.TextDocument.create("", "", 0, content);
var dockerfile = dockerfile_ast_1.DockerfileParser.parse(content);
var indentedLines = [];
for (var i = 0; i < document.lineCount; i++) {
indentedLines[i] = false;
}
for (var _i = 0, _a = dockerfile.getInstructions(); _i < _a.length; _i++) {
var instruction = _a[_i];
var range = instruction.getRange();
indentedLines[range.start.line] = false;
for (var i = range.start.line + 1; i <= range.end.line; i++) {
indentedLines[i] = true;
}
}
return this.formatLines(document, content, lines, indentedLines, options);
};
DockerFormatter.prototype.formatLines = function (document, content, lines, indentedLines, options) {
var indentation = this.getIndentation(options);
var edits = [];
lineCheck: for (var _i = 0, lines_1 = lines; _i < lines_1.length; _i++) {
var line = lines_1[_i];
var startOffset = document.offsetAt(vscode_languageserver_types_1.Position.create(line, 0));
for (var i = startOffset; i < content.length; i++) {
switch (content.charAt(i)) {
case ' ':
case '\t':
break;
case '\r':
case '\n':
if (i !== startOffset) {
// only whitespace on this line, trim it
var edit = vscode_languageserver_types_1.TextEdit.del({
start: document.positionAt(startOffset),
end: document.positionAt(i)
});
edits.push(edit);
}
// process the next line
continue lineCheck;
default:
// non-whitespace encountered
if (i !== startOffset || indentedLines[line]) {
var edit = this.createFormattingEdit(document, startOffset, i, indentedLines[line], indentation);
edits.push(edit);
}
// process the next line
continue lineCheck;
}
}
if (startOffset < content.length) {
// only whitespace on the last line, trim it
var edit = vscode_languageserver_types_1.TextEdit.del({
start: document.positionAt(startOffset),
end: document.positionAt(content.length)
});
edits.push(edit);
}
}
return edits;
};
return DockerFormatter;
}());
exports.DockerFormatter = DockerFormatter;
});