@actions/languageserver 0.3.42 → 0.3.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.bundle.cjs +109 -113
  2. package/package.json +4 -4
@@ -18757,39 +18757,6 @@ function objectAccess(obj, idx) {
18757
18757
  return new Null();
18758
18758
  }
18759
18759
 
18760
- // ../expressions/dist/features.js
18761
- var allFeatureKeys = [
18762
- "missingInputsQuickfix",
18763
- "blockScalarChompingWarning",
18764
- "allowCaseFunction"
18765
- ];
18766
- var FeatureFlags = class {
18767
- constructor(features) {
18768
- this.features = features ?? {};
18769
- }
18770
- /**
18771
- * Check if an experimental feature is enabled.
18772
- *
18773
- * Resolution order:
18774
- * 1. Explicit feature flag (if set)
18775
- * 2. `all` flag (if set)
18776
- * 3. false (default)
18777
- */
18778
- isEnabled(feature) {
18779
- const explicit = this.features[feature];
18780
- if (explicit !== void 0) {
18781
- return explicit;
18782
- }
18783
- return this.features.all ?? false;
18784
- }
18785
- /**
18786
- * Returns list of all enabled experimental features.
18787
- */
18788
- getEnabledFeatures() {
18789
- return allFeatureKeys.filter((key) => this.isEnabled(key));
18790
- }
18791
- };
18792
-
18793
18760
  // ../expressions/dist/parser.js
18794
18761
  var Parser = class {
18795
18762
  /**
@@ -19068,7 +19035,7 @@ function complete(input, context, extensionFunctions, functions, featureFlags) {
19068
19035
  }
19069
19036
  if (tokenIdx < 0) {
19070
19037
  const result2 = contextKeys(context);
19071
- result2.push(...functionItems(extensionFunctions, featureFlags));
19038
+ result2.push(...functionItems(extensionFunctions));
19072
19039
  return result2;
19073
19040
  }
19074
19041
  const pathTokenVector = tokenInputVector.slice(0, tokenIdx);
@@ -19079,13 +19046,9 @@ function complete(input, context, extensionFunctions, functions, featureFlags) {
19079
19046
  const result = ev.evaluate();
19080
19047
  return contextKeys(result);
19081
19048
  }
19082
- function functionItems(extensionFunctions, featureFlags) {
19049
+ function functionItems(extensionFunctions) {
19083
19050
  const result = [];
19084
- const flags = featureFlags ?? new FeatureFlags();
19085
19051
  for (const fdef of [...Object.values(wellKnownFunctions), ...extensionFunctions]) {
19086
- if (fdef.name === "case" && !flags.isEnabled("allowCaseFunction")) {
19087
- continue;
19088
- }
19089
19052
  result.push({
19090
19053
  label: fdef.name,
19091
19054
  description: fdef.description,
@@ -19173,6 +19136,35 @@ var DescriptionDictionary = class extends Dictionary {
19173
19136
  }
19174
19137
  };
19175
19138
 
19139
+ // ../expressions/dist/features.js
19140
+ var allFeatureKeys = ["missingInputsQuickfix", "blockScalarChompingWarning"];
19141
+ var FeatureFlags = class {
19142
+ constructor(features) {
19143
+ this.features = features ?? {};
19144
+ }
19145
+ /**
19146
+ * Check if an experimental feature is enabled.
19147
+ *
19148
+ * Resolution order:
19149
+ * 1. Explicit feature flag (if set)
19150
+ * 2. `all` flag (if set)
19151
+ * 3. false (default)
19152
+ */
19153
+ isEnabled(feature) {
19154
+ const explicit = this.features[feature];
19155
+ if (explicit !== void 0) {
19156
+ return explicit;
19157
+ }
19158
+ return this.features.all ?? false;
19159
+ }
19160
+ /**
19161
+ * Returns list of all enabled experimental features.
19162
+ */
19163
+ getEnabledFeatures() {
19164
+ return allFeatureKeys.filter((key) => this.isEnabled(key));
19165
+ }
19166
+ };
19167
+
19176
19168
  // ../workflow-parser/dist/templates/tokens/types.js
19177
19169
  var TokenType2;
19178
19170
  (function(TokenType3) {
@@ -22291,6 +22283,16 @@ function walkTreeToFindStatusFunctionCalls(tree) {
22291
22283
  }
22292
22284
  return false;
22293
22285
  }
22286
+ function validateRunsIfCondition(context, token, condition) {
22287
+ const allowedContext = token.definitionInfo?.allowedContext || [];
22288
+ try {
22289
+ ExpressionToken.validateExpression(condition, allowedContext);
22290
+ } catch (err) {
22291
+ context.error(token, err);
22292
+ return void 0;
22293
+ }
22294
+ return condition;
22295
+ }
22294
22296
 
22295
22297
  // ../workflow-parser/dist/model/converter/container.js
22296
22298
  function convertToJobContainer(context, container) {
@@ -24992,7 +24994,7 @@ function convertRuns(context, token) {
24992
24994
  break;
24993
24995
  case "pre-if":
24994
24996
  if (isString(item.value)) {
24995
- preIf = item.value.value;
24997
+ preIf = validateRunsIfCondition(context, item.value, item.value.value);
24996
24998
  }
24997
24999
  break;
24998
25000
  case "post":
@@ -25002,7 +25004,7 @@ function convertRuns(context, token) {
25002
25004
  break;
25003
25005
  case "post-if":
25004
25006
  if (isString(item.value)) {
25005
- postIf = item.value.value;
25007
+ postIf = validateRunsIfCondition(context, item.value, item.value.value);
25006
25008
  }
25007
25009
  break;
25008
25010
  case "pre-entrypoint":
@@ -27130,6 +27132,12 @@ async function validateAction(textDocument, config) {
27130
27132
  if (!result) {
27131
27133
  return [];
27132
27134
  }
27135
+ let template;
27136
+ if (result.value) {
27137
+ template = getOrConvertActionTemplate(result.context, result.value, textDocument.uri, {
27138
+ errorPolicy: ErrorPolicy.TryConversion
27139
+ });
27140
+ }
27133
27141
  const schemaErrors = result.context.errors.getErrors();
27134
27142
  if (result.value) {
27135
27143
  diagnostics.push(...validateRunsKeysAndFilterErrors(result.value, schemaErrors));
@@ -27146,11 +27154,8 @@ async function validateAction(textDocument, config) {
27146
27154
  severity
27147
27155
  });
27148
27156
  }
27149
- if (result.value) {
27150
- const template = getOrConvertActionTemplate(result.context, result.value, textDocument.uri, {
27151
- errorPolicy: ErrorPolicy.TryConversion
27152
- });
27153
- if (template?.runs?.using === "composite") {
27157
+ if (result.value && template) {
27158
+ if (template.runs?.using === "composite") {
27154
27159
  const steps = template.runs.steps ?? [];
27155
27160
  const stepsSequence = findStepsSequence(result.value);
27156
27161
  if (stepsSequence) {
@@ -27161,39 +27166,66 @@ async function validateAction(textDocument, config) {
27161
27166
  await validateActionReference(diagnostics, stepToken, step, config);
27162
27167
  }
27163
27168
  if (isMapping(stepToken)) {
27164
- validateCompositeStepTokens(diagnostics, stepToken);
27169
+ validateStepUsesField(diagnostics, stepToken);
27165
27170
  }
27166
27171
  }
27167
27172
  }
27168
27173
  }
27169
- const runsMapping = findRunsMapping(result.value);
27170
- if (runsMapping) {
27171
- validateRunsIfConditions(diagnostics, runsMapping);
27172
- }
27173
- validateAllExpressions(diagnostics, result.value);
27174
+ validateAllTokens(diagnostics, result.value);
27174
27175
  }
27175
27176
  } catch (e) {
27176
27177
  error(`Unhandled error while validating action file: ${e.message}`);
27177
27178
  }
27178
27179
  return diagnostics;
27179
27180
  }
27180
- function validateCompositeStepTokens(diagnostics, stepToken) {
27181
+ function validateStepUsesField(diagnostics, stepToken) {
27181
27182
  for (let i = 0; i < stepToken.count; i++) {
27182
27183
  const { key, value } = stepToken.get(i);
27183
27184
  const keyStr = isString(key) ? key.value.toLowerCase() : "";
27184
27185
  if (keyStr === "uses" && isString(value)) {
27185
27186
  validateStepUsesFormat(diagnostics, value);
27186
27187
  }
27187
- if (keyStr === "if" && value.range) {
27188
- if (isString(value)) {
27189
- validateIfCondition(diagnostics, value);
27190
- } else if (isBasicExpression(value)) {
27191
- validateIfConditionExpression(diagnostics, value);
27188
+ }
27189
+ }
27190
+ function validateAllTokens(diagnostics, root) {
27191
+ for (const [parent, token] of TemplateToken.traverse(root)) {
27192
+ const definitionKey = token.definition?.key;
27193
+ if (token instanceof BasicExpressionToken && token.range) {
27194
+ if (definitionKey === "step-if") {
27195
+ validateIfLiteralText(diagnostics, token);
27196
+ }
27197
+ for (const expression of token.originalExpressions || [token]) {
27198
+ validateExpressionFormatCalls(diagnostics, expression);
27199
+ }
27200
+ if (definitionKey === "runs-if" && parent instanceof MappingToken) {
27201
+ let keyName;
27202
+ for (let i = 0; i < parent.count; i++) {
27203
+ const { key, value } = parent.get(i);
27204
+ if (value === token) {
27205
+ keyName = key.toString().toLowerCase();
27206
+ break;
27207
+ }
27208
+ }
27209
+ if (keyName) {
27210
+ diagnostics.push({
27211
+ message: `Explicit expression syntax \${{ }} is not supported for '${keyName}'. Remove the \${{ }} markers and use the expression directly.`,
27212
+ range: mapRange(token.range),
27213
+ severity: import_vscode_languageserver_types6.DiagnosticSeverity.Error,
27214
+ code: "explicit-expression-not-allowed"
27215
+ });
27216
+ }
27217
+ }
27218
+ }
27219
+ if (isString(token) && token.range) {
27220
+ if (definitionKey === "step-if" || definitionKey === "runs-if") {
27221
+ validateImplicitIfCondition(diagnostics, token);
27192
27222
  }
27193
27223
  }
27194
27224
  }
27195
27225
  }
27196
- function validateIfCondition(diagnostics, token) {
27226
+ var LITERAL_TEXT_IN_CONDITION_MESSAGE = "Conditional expression contains literal text outside replacement tokens. This will cause the expression to always evaluate to truthy. Did you mean to put the entire expression inside ${{ }}?";
27227
+ var LITERAL_TEXT_IN_CONDITION_CODE = "expression-literal-text-in-condition";
27228
+ function validateImplicitIfCondition(diagnostics, token) {
27197
27229
  const condition = token.value.trim();
27198
27230
  if (!condition) {
27199
27231
  return;
@@ -27201,25 +27233,24 @@ function validateIfCondition(diagnostics, token) {
27201
27233
  const allowedContext = token.definitionInfo?.allowedContext || [];
27202
27234
  const { namedContexts, functions } = splitAllowedContext(allowedContext);
27203
27235
  const finalCondition = ensureStatusFunction(condition, token.definitionInfo);
27204
- const expressionToken = new BasicExpressionToken(token.file, token.range, finalCondition, token.definitionInfo, void 0, token.source, void 0, token.blockScalarHeader);
27205
27236
  try {
27206
- const l = new Lexer(expressionToken.expression);
27237
+ const l = new Lexer(finalCondition);
27207
27238
  const lr = l.lex();
27208
27239
  const p = new Parser(lr.tokens, namedContexts, functions);
27209
27240
  const expr = p.parse();
27210
27241
  if (hasFormatWithLiteralText(expr)) {
27211
27242
  diagnostics.push({
27212
- message: "Conditional expression contains literal text outside replacement tokens. This will cause the expression to always evaluate to truthy. Did you mean to put the entire expression inside ${{ }}?",
27243
+ message: LITERAL_TEXT_IN_CONDITION_MESSAGE,
27213
27244
  range: mapRange(token.range),
27214
27245
  severity: import_vscode_languageserver_types6.DiagnosticSeverity.Error,
27215
- code: "expression-literal-text-in-condition"
27246
+ code: LITERAL_TEXT_IN_CONDITION_CODE
27216
27247
  });
27217
27248
  }
27218
27249
  validateFormatCallsAndAddDiagnostics(diagnostics, expr, token.range);
27219
27250
  } catch {
27220
27251
  }
27221
27252
  }
27222
- function validateIfConditionExpression(diagnostics, token) {
27253
+ function validateIfLiteralText(diagnostics, token) {
27223
27254
  const allowedContext = token.definitionInfo?.allowedContext || [];
27224
27255
  const { namedContexts, functions } = splitAllowedContext(allowedContext);
27225
27256
  try {
@@ -27229,15 +27260,27 @@ function validateIfConditionExpression(diagnostics, token) {
27229
27260
  const expr = p.parse();
27230
27261
  if (hasFormatWithLiteralText(expr)) {
27231
27262
  diagnostics.push({
27232
- message: "Conditional expression contains literal text outside replacement tokens. This will cause the expression to always evaluate to truthy. Did you mean to put the entire expression inside ${{ }}?",
27263
+ message: LITERAL_TEXT_IN_CONDITION_MESSAGE,
27233
27264
  range: mapRange(token.range),
27234
27265
  severity: import_vscode_languageserver_types6.DiagnosticSeverity.Error,
27235
- code: "expression-literal-text-in-condition"
27266
+ code: LITERAL_TEXT_IN_CONDITION_CODE
27236
27267
  });
27237
27268
  }
27238
27269
  } catch {
27239
27270
  }
27240
27271
  }
27272
+ function validateExpressionFormatCalls(diagnostics, token) {
27273
+ const allowedContext = token.definitionInfo?.allowedContext || [];
27274
+ const { namedContexts, functions } = splitAllowedContext(allowedContext);
27275
+ try {
27276
+ const l = new Lexer(token.expression);
27277
+ const lr = l.lex();
27278
+ const p = new Parser(lr.tokens, namedContexts, functions);
27279
+ const expr = p.parse();
27280
+ validateFormatCallsAndAddDiagnostics(diagnostics, expr, token.range);
27281
+ } catch {
27282
+ }
27283
+ }
27241
27284
  function validateFormatCallsAndAddDiagnostics(diagnostics, expr, range) {
27242
27285
  const formatErrors = validateFormatCalls(expr);
27243
27286
  for (const formatError of formatErrors) {
@@ -27266,53 +27309,6 @@ function findStepsSequence(root) {
27266
27309
  }
27267
27310
  return void 0;
27268
27311
  }
27269
- function findRunsMapping(root) {
27270
- if (root instanceof MappingToken) {
27271
- for (let i = 0; i < root.count; i++) {
27272
- const { key, value } = root.get(i);
27273
- if (key.toString().toLowerCase() === "runs" && value instanceof MappingToken) {
27274
- return value;
27275
- }
27276
- }
27277
- }
27278
- return void 0;
27279
- }
27280
- function validateRunsIfConditions(diagnostics, runsMapping) {
27281
- for (let i = 0; i < runsMapping.count; i++) {
27282
- const { key, value } = runsMapping.get(i);
27283
- const keyStr = key.toString().toLowerCase();
27284
- if ((keyStr === "pre-if" || keyStr === "post-if") && value.range) {
27285
- if (isString(value)) {
27286
- validateIfCondition(diagnostics, value);
27287
- } else if (isBasicExpression(value)) {
27288
- diagnostics.push({
27289
- message: `Explicit expression syntax \${{ }} is not supported for '${keyStr}'. Remove the \${{ }} markers and use the expression directly.`,
27290
- range: mapRange(value.range),
27291
- severity: import_vscode_languageserver_types6.DiagnosticSeverity.Error,
27292
- code: "explicit-expression-not-allowed"
27293
- });
27294
- }
27295
- }
27296
- }
27297
- }
27298
- function validateAllExpressions(diagnostics, root) {
27299
- for (const [, token] of TemplateToken.traverse(root)) {
27300
- if (token instanceof BasicExpressionToken) {
27301
- for (const expression of token.originalExpressions || [token]) {
27302
- const allowedContext = expression.definitionInfo?.allowedContext || [];
27303
- const { namedContexts, functions } = splitAllowedContext(allowedContext);
27304
- try {
27305
- const l = new Lexer(expression.expression);
27306
- const lr = l.lex();
27307
- const p = new Parser(lr.tokens, namedContexts, functions);
27308
- const expr = p.parse();
27309
- validateFormatCallsAndAddDiagnostics(diagnostics, expr, expression.range);
27310
- } catch {
27311
- }
27312
- }
27313
- }
27314
- }
27315
- }
27316
27312
  function validateRunsKeysAndFilterErrors(root, schemaErrors) {
27317
27313
  const diagnostics = [];
27318
27314
  let runsMapping;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actions/languageserver",
3
- "version": "0.3.42",
3
+ "version": "0.3.44",
4
4
  "description": "Language server for GitHub Actions",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -48,8 +48,8 @@
48
48
  "actions-languageserver": "./bin/actions-languageserver"
49
49
  },
50
50
  "dependencies": {
51
- "@actions/languageservice": "^0.3.42",
52
- "@actions/workflow-parser": "^0.3.42",
51
+ "@actions/languageservice": "^0.3.44",
52
+ "@actions/workflow-parser": "^0.3.44",
53
53
  "@octokit/rest": "^21.1.1",
54
54
  "@octokit/types": "^9.0.0",
55
55
  "vscode-languageserver": "^8.0.2",
@@ -78,5 +78,5 @@
78
78
  "ts-jest": "^29.0.3",
79
79
  "typescript": "^4.8.4"
80
80
  },
81
- "gitHead": "46b216a6dce39b5cc60bce9325785545fdbaba00"
81
+ "gitHead": "f29f508cecef1d6066ad5e699522f25c9fce2108"
82
82
  }