Skip to content

Commit

Permalink
WIP #162 Add signature help for LABEL
Browse files Browse the repository at this point in the history
Signed-off-by: Remy Suen <[email protected]>
  • Loading branch information
rcjsuen committed Aug 26, 2017
1 parent 2a91f2b commit 139d2c9
Show file tree
Hide file tree
Showing 5 changed files with 344 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ All notable changes to this project will be documented in this file.
- ARG
- EXPOSE
- FROM
- LABEL
- SHELL
- STOPSIGNAL
- USER
Expand Down
14 changes: 14 additions & 0 deletions src/dockerPlainText.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ export class PlainTextDocumentation {
"signatureFrom_Signature3_Param2": "The name of this build stage.",
"signatureFrom_Param2": "The name of this build stage.",
"signatureHealthcheck": "Define how Docker should test the container to check that it is still working.",
"signatureLabel_Signature0": "Set metadata to an image.",
"signatureLabel_Signature0_Param0": "The name of the metadata.",
"signatureLabel_Signature0_Param1": "The value of the metadata.",
"signatureShell": "Override default shell used for the shell form of commands.",
"signatureShell_Param1": "The shell executable to use.",
"signatureShell_Param2": "The parameters to the shell executable.",
Expand Down Expand Up @@ -227,6 +230,17 @@ export class PlainTextDocumentation {
signatureHealthcheckFlagRetries_Param: this.dockerMessages["hoverHealthcheckFlagRetries"],
signatureHealthcheckFlagStartPeriod_Param: this.dockerMessages["hoverHealthcheckFlagStartPeriod"],
signatureHealthcheckFlagTimeout_Param: this.dockerMessages["hoverHealthcheckFlagTimeout"],
signatureLabel_Signature0: this.dockerMessages["signatureLabel_Signature0"],
signatureLabel_Signature0_Param0: this.dockerMessages["signatureLabel_Signature0_Param0"],
signatureLabel_Signature0_Param1: this.dockerMessages["signatureLabel_Signature0_Param1"],
signatureLabel_Signature1: this.dockerMessages["signatureLabel_Signature0"],
signatureLabel_Signature1_Param0: this.dockerMessages["signatureLabel_Signature0_Param0"],
signatureLabel_Signature1_Param1: this.dockerMessages["signatureLabel_Signature0_Param1"],
signatureLabel_Signature2: this.dockerMessages["signatureLabel_Signature0"],
signatureLabel_Signature2_Param0: this.dockerMessages["signatureLabel_Signature0_Param0"],
signatureLabel_Signature2_Param1: this.dockerMessages["signatureLabel_Signature0_Param1"],
signatureLabel_Signature2_Param2: this.dockerMessages["signatureLabel_Signature0_Param0"],
signatureLabel_Signature2_Param3: this.dockerMessages["signatureLabel_Signature0_Param1"],
signatureShell: this.dockerMessages["signatureShell"],
signatureShell_Param1: this.dockerMessages["signatureShell_Param1"],
signatureShell_Param2: this.dockerMessages["signatureShell_Param2"],
Expand Down
107 changes: 107 additions & 0 deletions src/dockerSignatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import {
import { Dockerfile } from './parser/dockerfile';
import { Argument } from './parser/argument';
import { Instruction } from './parser/instruction';
import { Property } from './parser/property';
import { Arg } from './parser/instructions/arg';
import { Copy } from './parser/instructions/copy';
import { From } from './parser/instructions/from';
import { Healthcheck } from './parser/instructions/healthcheck';
import { Label } from './parser/instructions/label';
import { Shell } from './parser/instructions/shell';
import { PlainTextDocumentation } from './dockerPlainText';
import { DockerfileParser } from './parser/dockerfileParser';
Expand Down Expand Up @@ -156,6 +158,60 @@ export class DockerSignatures {
}
}
break;
case "LABEL":
const labelSignatures = [
{
label: "LABEL key value",
documentation: this.documentation.getDocumentation("signatureLabel_Signature0"),
parameters: [
{
label: "key",
documentation: this.documentation.getDocumentation("signatureLabel_Signature0_Param0")
},
{
label: "value",
documentation: this.documentation.getDocumentation("signatureLabel_Signature0_Param1")
}
]
},
{
label: "LABEL key=value",
documentation: this.documentation.getDocumentation("signatureLabel_Signature1"),
parameters: [
{
label: "key",
documentation: this.documentation.getDocumentation("signatureLabel_Signature1_Param0")
},
{
label: "value",
documentation: this.documentation.getDocumentation("signatureLabel_Signature1_Param1")
}
]
},
{
label: "LABEL key=value key2=value2",
documentation: this.documentation.getDocumentation("signatureLabel_Signature2"),
parameters: [
{
label: "key",
documentation: this.documentation.getDocumentation("signatureLabel_Signature2_Param0")
},
{
label: "value",
documentation: this.documentation.getDocumentation("signatureLabel_Signature2_Param1")
},
{
label: "key2",
documentation: this.documentation.getDocumentation("signatureLabel_Signature2_Param2")
},
{
label: "value2",
documentation: this.documentation.getDocumentation("signatureLabel_Signature2_Param3")
}
]
}
];
return this.getPropertySignatureHelp(document, position, labelSignatures, (instruction as Label).getProperties());
case "EXPOSE":
let exposeSignatureHelp = {
signatures: [
Expand Down Expand Up @@ -624,4 +680,55 @@ export class DockerSignatures {
}
return inTag || inDigest ? 1 : 0;
}

private getPropertySignatureHelp(document: TextDocument, position: Position, signatures: SignatureInformation[], properties: Property[]): SignatureHelp {
return {
signatures: this.getPropertySignatures(document, position, signatures, properties),
activeSignature: 0,
activeParameter: this.getPropertySignatureActiveParameter(document, position, signatures, properties)
};
}

private getPropertySignatures(document: TextDocument, position: Position, signatures: SignatureInformation[], properties: Property[]): SignatureInformation[] {
if (properties.length === 0) {
return signatures;
} else if (properties.length === 1) {
const valueRange = properties[0].getValueRange();
if (valueRange === null) {
return properties[0].isNameBefore(position) ? [ signatures[0] ] : signatures;
}

const delimiter = document.getText().substring(document.offsetAt(properties[0].getNameRange().end), document.offsetAt(valueRange.start));
if (delimiter.indexOf('=') === -1) {
return [ signatures[0] ];
} else if (properties[0].isValueBefore(position)) {
return [ signatures[2] ];
}
} else {
return [ signatures[2] ];
}
return [ signatures[1], signatures[2] ];
}

private getPropertySignatureActiveParameter(document: TextDocument, position: Position, signatures: SignatureInformation[], properties: Property[]): number {
if (properties.length === 0) {
return 0;
}

for (let i = properties.length - 1; i > 0; i--) {
if (properties[i].isInValue(position)) {
return 3;
} else if (properties[i].isNameBefore(position) || properties[i].isInName(position)) {
return 2;
}
}

if (properties[0].isInValue(position)) {
return 1;
} else if (properties[0].isValueBefore(position)) {
const delimiter = document.getText().substring(document.offsetAt(properties[0].getNameRange().end), document.offsetAt(properties[0].getValueRange().start));
return delimiter.indexOf('=') === -1 ? 1 : 2;
}
return properties[0].isNameBefore(position) ? 1 : 0;
}
}
28 changes: 27 additions & 1 deletion src/parser/property.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright (c) Remy Suen. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import { TextDocument, Range } from 'vscode-languageserver';
import { TextDocument, Range, Position } from 'vscode-languageserver';

import { Argument } from './argument';
import { Util } from '../docker';
Expand Down Expand Up @@ -59,6 +59,32 @@ export class Property {
return this.valueRange;
}

public isInName(position: Position): boolean {
return Util.isInsideRange(position, this.nameRange);
}

public isNameBefore(position: Position): boolean {
if (this.isInName(position)) {
return false;
} else if (this.nameRange.start.line < position.line) {
return true;
}
return this.nameRange.start.line === position.line ? this.nameRange.end.character < position.character : false;
}

public isValueBefore(position: Position): boolean {
if (this.valueRange === null) {
return false;
} else if (this.valueRange.start.line < position.line) {
return true;
}
return this.valueRange.start.line === position.line ? this.valueRange.end.character < position.character : false;
}

public isInValue(position: Position): boolean {
return this.valueRange === null ? false : Util.isInsideRange(position, this.valueRange);
}

public getRawValue(): string {
let rawValue = "";
let value = this.document.getText().substring(this.document.offsetAt(this.valueRange.start), this.document.offsetAt(this.valueRange.end));
Expand Down
Loading

0 comments on commit 139d2c9

Please sign in to comment.