Complete multi-segment expressions
This commit is contained in:
@@ -262,6 +262,13 @@ jobs:
|
||||
expect(result.map(x => x.label)).toEqual(["event"]);
|
||||
});
|
||||
|
||||
it("auto-complete complex partial", async () => {
|
||||
const input = 'run-name: "run ${{ github.ev| }} run"';
|
||||
const result = await complete(...getPositionFromCursor(input), undefined, contextProviderConfig);
|
||||
|
||||
expect(result.map(x => x.label)).toEqual(["event"]);
|
||||
});
|
||||
|
||||
it("using default context provider", async () => {
|
||||
const input =
|
||||
"on: push\njobs:\n build:\n runs-on: ubuntu-latest\n environment:\n url: ${{ runner.| }}\n steps:\n - run: echo";
|
||||
|
||||
@@ -205,20 +205,18 @@ function getExpressionCompletionItems(
|
||||
context: DescriptionDictionary,
|
||||
pos: Position
|
||||
): CompletionItem[] {
|
||||
let expressionInput = "";
|
||||
let currentInput = "";
|
||||
let relCharPos: number = 0;
|
||||
|
||||
if (isBasicExpression(token)) {
|
||||
expressionInput = currentInput = token.expression;
|
||||
relCharPos = getRelCharPos(token.range!, expressionInput, pos);
|
||||
currentInput = token.source || token.expression;
|
||||
} else {
|
||||
const stringToken = token.assertString("Expected string token for expression completion");
|
||||
currentInput = stringToken.source || stringToken.value;
|
||||
relCharPos = getRelCharPos(stringToken.range!, currentInput, pos);
|
||||
expressionInput = (getExpressionInput(currentInput, relCharPos) || "").trim();
|
||||
}
|
||||
|
||||
const relCharPos = getRelCharPos(token.range!, currentInput, pos);
|
||||
const expressionInput = (getExpressionInput(currentInput, relCharPos) || "").trim();
|
||||
|
||||
try {
|
||||
return completeExpression(expressionInput, context, [], validatorFunctions).map(item =>
|
||||
mapExpressionCompletionItem(item, currentInput[relCharPos])
|
||||
|
||||
@@ -45,7 +45,7 @@ function stringToToken(value: string) {
|
||||
}
|
||||
|
||||
function expressionToToken(expr: string) {
|
||||
return new BasicExpressionToken(undefined, undefined, expr, undefined, undefined);
|
||||
return new BasicExpressionToken(undefined, undefined, expr, undefined, undefined, expr);
|
||||
}
|
||||
|
||||
function contextFromStrategy(strategy?: TemplateToken) {
|
||||
|
||||
@@ -111,7 +111,7 @@ function convertJob(context: TemplateContext, jobKey: StringToken, token: Mappin
|
||||
id: jobKey,
|
||||
name: undefined,
|
||||
needs: undefined,
|
||||
if: new BasicExpressionToken(undefined, undefined, "success()", undefined, undefined),
|
||||
if: new BasicExpressionToken(undefined, undefined, "success()", undefined, undefined, "success()"),
|
||||
env: undefined,
|
||||
concurrency: undefined,
|
||||
environment: undefined,
|
||||
|
||||
@@ -52,7 +52,7 @@ function convertStep(context: TemplateContext, idBuilder: IdBuilder, step: Templ
|
||||
let uses: StringToken | undefined;
|
||||
let continueOnError: boolean | undefined;
|
||||
let env: MappingToken | undefined;
|
||||
const ifCondition = new BasicExpressionToken(undefined, undefined, "success()", undefined, undefined);
|
||||
const ifCondition = new BasicExpressionToken(undefined, undefined, "success()", undefined, undefined, "success()");
|
||||
for (const item of mapping) {
|
||||
const key = item.key.assertString("steps item key");
|
||||
switch (key.value) {
|
||||
|
||||
@@ -606,8 +606,9 @@ class TemplateReader {
|
||||
this._fileId,
|
||||
token.range,
|
||||
`format('${format.join("")}'${args.join("")})`,
|
||||
token.definitionInfo,
|
||||
expressionTokens
|
||||
definitionInfo,
|
||||
expressionTokens,
|
||||
raw
|
||||
);
|
||||
}
|
||||
|
||||
@@ -667,7 +668,7 @@ class TemplateReader {
|
||||
|
||||
// Return the expression
|
||||
return <ParseExpressionResult>{
|
||||
expression: new BasicExpressionToken(this._fileId, range, trimmed, definitionInfo, undefined),
|
||||
expression: new BasicExpressionToken(this._fileId, range, trimmed, definitionInfo, undefined, value),
|
||||
error: undefined
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ export class BasicExpressionToken extends ExpressionToken {
|
||||
|
||||
public readonly originalExpressions: BasicExpressionToken[] | undefined;
|
||||
|
||||
public readonly source: string;
|
||||
|
||||
/**
|
||||
* @param originalExpressions If the basic expression was transformed from individual expressions, these will be the original ones
|
||||
*/
|
||||
@@ -21,11 +23,13 @@ export class BasicExpressionToken extends ExpressionToken {
|
||||
range: TokenRange | undefined,
|
||||
expression: string,
|
||||
definitionInfo: DefinitionInfo | undefined,
|
||||
originalExpressions: BasicExpressionToken[] | undefined
|
||||
originalExpressions: BasicExpressionToken[] | undefined,
|
||||
source: string
|
||||
) {
|
||||
super(TokenType.BasicExpression, file, range, undefined, definitionInfo);
|
||||
this.expr = expression;
|
||||
this.originalExpressions = originalExpressions;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public get expression(): string {
|
||||
@@ -34,8 +38,22 @@ export class BasicExpressionToken extends ExpressionToken {
|
||||
|
||||
public override clone(omitSource?: boolean): TemplateToken {
|
||||
return omitSource
|
||||
? new BasicExpressionToken(undefined, undefined, this.expr, this.definitionInfo, this.originalExpressions)
|
||||
: new BasicExpressionToken(this.file, this.range, this.expr, this.definitionInfo, this.originalExpressions);
|
||||
? new BasicExpressionToken(
|
||||
undefined,
|
||||
undefined,
|
||||
this.expr,
|
||||
this.definitionInfo,
|
||||
this.originalExpressions,
|
||||
this.source
|
||||
)
|
||||
: new BasicExpressionToken(
|
||||
this.file,
|
||||
this.range,
|
||||
this.expr,
|
||||
this.definitionInfo,
|
||||
this.originalExpressions,
|
||||
this.source
|
||||
);
|
||||
}
|
||||
|
||||
public override toString(): string {
|
||||
|
||||
Reference in New Issue
Block a user