Merge pull request #121 from github/cschleiden/expression-hover

Add support for `hover`ing on expressions
This commit is contained in:
Christopher Schleiden
2023-02-02 15:20:14 -08:00
committed by GitHub
26 changed files with 972 additions and 137 deletions
@@ -55,7 +55,7 @@ jobs:
steps:
- run: |
echo \${{ github.event_name }}
echo 'hello' \${{ github.ref }}`
echo 'hello' \${{github.ref }}`
}
],
nullTrace
@@ -81,19 +81,27 @@ jobs:
}
expect(stepRun.originalExpressions).toHaveLength(2);
expect(stepRun.originalExpressions!.map(x => [x.toDisplayString(), x.range])).toEqual([
expect(stepRun.originalExpressions!.map(x => [x.toDisplayString(), x.range, x.expressionRange])).toEqual([
[
"${{ github.event_name }}",
{
start: {line: 7, column: 16},
end: {line: 7, column: 40}
},
{
start: {line: 7, column: 20},
end: {line: 7, column: 37}
}
],
[
"${{ github.ref }}",
{
start: {line: 8, column: 24},
end: {line: 8, column: 41}
end: {line: 8, column: 40}
},
{
start: {line: 8, column: 27},
end: {line: 8, column: 37}
}
]
]);
@@ -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, undefined),
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, undefined);
for (const item of mapping) {
const key = item.key.assertString("steps item key");
switch (key.value) {
@@ -607,7 +607,8 @@ class TemplateReader {
token.range,
`format('${format.join("")}'${args.join("")})`,
token.definitionInfo,
expressionTokens
expressionTokens,
undefined
);
}
@@ -615,10 +616,10 @@ class TemplateReader {
tr: TokenRange,
rawExpression: string,
allowedContext: string[],
token: TemplateToken,
token: StringToken,
definitionInfo: DefinitionInfo | undefined
): ExpressionToken | undefined {
const parseExpressionResult = this.parseExpression(tr, rawExpression, allowedContext, definitionInfo);
const parseExpressionResult = this.parseExpression(tr, token, rawExpression, allowedContext, definitionInfo);
// Check for error
if (parseExpressionResult.error) {
@@ -630,7 +631,8 @@ class TemplateReader {
}
private parseExpression(
range: TokenRange | undefined,
range: TokenRange,
token: StringToken,
value: string,
allowedContext: string[],
definitionInfo: DefinitionInfo | undefined
@@ -665,9 +667,31 @@ class TemplateReader {
};
}
const startTrim = value.length - value.trimStart().length;
const endTrim = value.length - value.trimEnd().length;
const expressionRange: TokenRange = {
start: {
...range.start,
column: range.start.column + OPEN_EXPRESSION.length + startTrim
},
end: {
...range.end,
column: range.end.column - CLOSE_EXPRESSION.length - endTrim
}
};
// Return the expression
return <ParseExpressionResult>{
expression: new BasicExpressionToken(this._fileId, range, trimmed, definitionInfo, undefined),
expression: new BasicExpressionToken(
this._fileId,
range,
trimmed,
definitionInfo,
undefined,
token.source,
expressionRange
),
error: undefined
};
}
@@ -11,8 +11,18 @@ import {TokenType} from "./types";
export class BasicExpressionToken extends ExpressionToken {
private readonly expr: string;
public readonly source: string | undefined;
public readonly originalExpressions: BasicExpressionToken[] | undefined;
/**
* The range of the expression within the source string.
*
* `range` is the range of the entire expression, including the `${{` and `}}`. `expression` is only the expression
* without any ${{ }} markers. `expressionRange` is the range of just the expression within the document.
*/
public readonly expressionRange: TokenRange | undefined;
/**
* @param originalExpressions If the basic expression was transformed from individual expressions, these will be the original ones
*/
@@ -21,11 +31,15 @@ export class BasicExpressionToken extends ExpressionToken {
range: TokenRange | undefined,
expression: string,
definitionInfo: DefinitionInfo | undefined,
originalExpressions: BasicExpressionToken[] | undefined
originalExpressions: BasicExpressionToken[] | undefined,
source: string | undefined,
expressionRange?: TokenRange | undefined
) {
super(TokenType.BasicExpression, file, range, undefined, definitionInfo);
this.expr = expression;
this.source = source;
this.originalExpressions = originalExpressions;
this.expressionRange = expressionRange;
}
public get expression(): string {
@@ -34,8 +48,24 @@ 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,
this.expressionRange
)
: new BasicExpressionToken(
this.file,
this.range,
this.expr,
this.definitionInfo,
this.originalExpressions,
this.source,
this.expressionRange
);
}
public override toString(): string {
@@ -2,6 +2,7 @@
export type Position = {
/** The one-based line value */
line: number;
/** The one-based column value */
column: number;
};