dockerfile-ast
Version:
Parse a Dockerfile into an array of instructions and comments.
215 lines (214 loc) • 8.97 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.From = void 0;
const vscode_languageserver_types_1 = require("vscode-languageserver-types");
const modifiableInstruction_1 = require("../modifiableInstruction");
class From extends modifiableInstruction_1.ModifiableInstruction {
constructor(document, range, dockerfile, escapeChar, instruction, instructionRange) {
super(document, range, dockerfile, escapeChar, instruction, instructionRange);
}
stopSearchingForFlags(argument) {
return argument.indexOf("--") === -1;
}
getImage() {
return this.getRangeContent(this.getImageRange());
}
/**
* Returns the name of the image that will be used as the base image.
*
* @return the base image's name, or null if unspecified
*/
getImageName() {
return this.getRangeContent(this.getImageNameRange());
}
/**
* Returns the range that covers the name of the image used by
* this instruction.
*
* @return the range of the name of this instruction's argument,
* or null if no image has been specified
*/
getImageNameRange() {
let range = this.getImageRange();
if (range) {
let registryRange = this.getRegistryRange();
if (registryRange) {
range.start = this.document.positionAt(this.document.offsetAt(registryRange.end) + 1);
}
let tagRange = this.getImageTagRange();
let digestRange = this.getImageDigestRange();
if (tagRange === null) {
if (digestRange !== null) {
range.end = this.document.positionAt(this.document.offsetAt(digestRange.start) - 1);
}
}
else {
range.end = this.document.positionAt(this.document.offsetAt(tagRange.start) - 1);
}
return range;
}
return null;
}
/**
* Returns the range that covers the image argument of this
* instruction. This includes the tag or digest of the image if
* it has been specified by the instruction.
*
* @return the range of the image argument, or null if no image
* has been specified
*/
getImageRange() {
let args = this.getArguments();
return args.length !== 0 ? args[0].getRange() : null;
}
getImageTag() {
return this.getRangeContent(this.getImageTagRange());
}
/**
* Returns the range in the document that the tag of the base
* image encompasses.
*
* @return the base image's tag's range in the document, or null
* if no tag has been specified
*/
getImageTagRange() {
const range = this.getImageRange();
if (range) {
const rangeStartOffset = this.document.offsetAt(range.start);
const content = this.getRangeContent(range);
const atIndex = this.indexOf(rangeStartOffset, content, '@');
const slashIndex = content.indexOf('/');
if (atIndex === -1) {
const colonIndex = this.lastIndexOf(rangeStartOffset, content, ':');
if (colonIndex > slashIndex) {
return vscode_languageserver_types_1.Range.create(range.start.line, range.start.character + colonIndex + 1, range.end.line, range.end.character);
}
}
const subcontent = content.substring(0, atIndex);
const subcolonIndex = subcontent.indexOf(':');
if (subcolonIndex === -1) {
return null;
}
if (slashIndex === -1) {
// slash not found suggests no registry and no namespace defined
return vscode_languageserver_types_1.Range.create(this.document.positionAt(rangeStartOffset + subcolonIndex + 1), this.document.positionAt(rangeStartOffset + atIndex));
}
// both colon and slash found, check if it is a port
if (subcolonIndex < slashIndex) {
return null;
}
return vscode_languageserver_types_1.Range.create(this.document.positionAt(rangeStartOffset + subcolonIndex + 1), this.document.positionAt(rangeStartOffset + subcontent.length));
}
return null;
}
getImageDigest() {
return this.getRangeContent(this.getImageDigestRange());
}
/**
* Returns the range in the document that the digest of the base
* image encompasses.
*
* @return the base image's digest's range in the document, or null
* if no digest has been specified
*/
getImageDigestRange() {
let range = this.getImageRange();
if (range) {
let content = this.getRangeContent(range);
let index = this.lastIndexOf(this.document.offsetAt(range.start), content, '@');
if (index !== -1) {
return vscode_languageserver_types_1.Range.create(range.start.line, range.start.character + index + 1, range.end.line, range.end.character);
}
}
return null;
}
indexOf(documentOffset, content, searchString) {
let index = content.indexOf(searchString);
const variables = this.getVariables();
for (let i = 0; i < variables.length; i++) {
const position = documentOffset + index;
const variableRange = variables[i].getRange();
if (this.document.offsetAt(variableRange.start) < position && position < this.document.offsetAt(variableRange.end)) {
const offset = this.document.offsetAt(variableRange.end) - documentOffset;
const substring = content.substring(offset);
const subIndex = substring.indexOf(searchString);
if (subIndex === -1) {
return -1;
}
index = subIndex + offset;
i = -1;
continue;
}
}
return index;
}
lastIndexOf(documentOffset, content, searchString) {
let index = content.lastIndexOf(searchString);
const variables = this.getVariables();
for (let i = 0; i < variables.length; i++) {
const position = documentOffset + index;
const variableRange = variables[i].getRange();
if (this.document.offsetAt(variableRange.start) < position && position < this.document.offsetAt(variableRange.end)) {
index = content.substring(0, index).lastIndexOf(searchString);
if (index === -1) {
return -1;
}
i = -1;
continue;
}
}
return index;
}
getRegistry() {
return this.getRangeContent(this.getRegistryRange());
}
getRegistryRange() {
const range = this.getImageRange();
if (range) {
const tagRange = this.getImageTagRange();
const digestRange = this.getImageDigestRange();
if (tagRange === null) {
if (digestRange !== null) {
range.end = this.document.positionAt(this.document.offsetAt(digestRange.start) - 1);
}
}
else {
range.end = this.document.positionAt(this.document.offsetAt(tagRange.start) - 1);
}
const content = this.getRangeContent(range);
const rangeStart = this.document.offsetAt(range.start);
const startingSlashIndex = this.indexOf(rangeStart, content, '/');
if (startingSlashIndex === -1) {
return null;
}
const portIndex = this.indexOf(rangeStart, content, ':');
const dotIndex = this.indexOf(rangeStart, content, '.');
// hostname detected
if (portIndex !== -1 || dotIndex !== -1) {
return vscode_languageserver_types_1.Range.create(range.start, this.document.positionAt(rangeStart + startingSlashIndex));
}
const registry = content.substring(0, startingSlashIndex);
// localhost registry detected
if (registry === 'localhost') {
return vscode_languageserver_types_1.Range.create(range.start, this.document.positionAt(rangeStart + startingSlashIndex));
}
}
return null;
}
getBuildStage() {
let range = this.getBuildStageRange();
return range === null ? null : this.getRangeContent(range);
}
getBuildStageRange() {
let args = this.getArguments();
if (args.length > 2 && args[1].getValue().toUpperCase() === "AS") {
return args[2].getRange();
}
return null;
}
getPlatformFlag() {
let flags = super.getFlags();
return flags.length === 1 && flags[0].getName() === "platform" ? flags[0] : null;
}
}
exports.From = From;