@komaci/static-analyzer 242.1.5 → 242.1.6

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.
package/build/index.d.ts CHANGED
@@ -4,4 +4,5 @@ export { AnalyzerInput, PrimingDiagnostic, Range, Position } from './types';
4
4
  export { isSupportedNamespace, isImageComposition } from './shared';
5
5
  export { diagnosticMessages, getPrimingDiagnostic } from './rules';
6
6
  export * from './validateGetter';
7
+ export * from './validateRenderFunction';
7
8
  //# sourceMappingURL=index.d.ts.map
package/build/index.js CHANGED
@@ -34,4 +34,5 @@ var rules_1 = require("./rules");
34
34
  Object.defineProperty(exports, "diagnosticMessages", { enumerable: true, get: function () { return rules_1.diagnosticMessages; } });
35
35
  Object.defineProperty(exports, "getPrimingDiagnostic", { enumerable: true, get: function () { return rules_1.getPrimingDiagnostic; } });
36
36
  __exportStar(require("./validateGetter"), exports);
37
+ __exportStar(require("./validateRenderFunction"), exports);
37
38
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,7 @@
1
1
  import { NodePath } from '@babel/traverse';
2
2
  import * as t from '@babel/types';
3
3
  import { PrimingDiagnostic } from '../types';
4
+ import { ModuleMetadata } from '@komaci/common-shared';
4
5
  /**
5
6
  * Invariant function for checking if an getter defined in an external module has only a
6
7
  * statement in it, a return statement.
@@ -9,4 +10,19 @@ import { PrimingDiagnostic } from '../types';
9
10
  * @returns PrimingDiagnostic of the BlockStatement if the invariant is detected, or undefined if the invariant wasn't found
10
11
  */
11
12
  export declare function checkExternalModuleGetterReturnStatement(blockStatement: NodePath<t.BlockStatement>, statements: NodePath<t.Statement>[]): PrimingDiagnostic | undefined;
13
+ /**
14
+ * Invariant function for checking if an render function defined in an external module has only a
15
+ * statement in it, a return statement.
16
+ * @param blockStatement the babel path object for the BlockStatement representing the contents of the render function.
17
+ * @param statements the babel path object array for all of the Statements in the render function.
18
+ * @returns PrimingDiagnostic of the BlockStatement if the invariant is detected, or undefined if the invariant wasn't found
19
+ */
20
+ export declare function checkExternalModuleRenderReturnStatement(blockStatement: NodePath<t.BlockStatement>, statements: NodePath<t.Statement>[]): PrimingDiagnostic | undefined;
21
+ /**
22
+ * Function to validate the render function, returns a priming diagnost if an invariant is found.
23
+ * @param returnStmt the return satement node
24
+ * @param moduleMetadata the module metadata obj
25
+ * @returns a priming diagnostic or undefined.
26
+ */
27
+ export declare function checkRenderFunctionReturnValues(returnStmt: t.ReturnStatement, moduleMetadata: ModuleMetadata): PrimingDiagnostic | undefined;
12
28
  //# sourceMappingURL=returnStatementInvariantFunctions.d.ts.map
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.checkExternalModuleGetterReturnStatement = void 0;
3
+ exports.checkRenderFunctionReturnValues = exports.checkExternalModuleRenderReturnStatement = exports.checkExternalModuleGetterReturnStatement = void 0;
4
4
  const shared_1 = require("../shared");
5
5
  const rules_1 = require("../rules");
6
6
  /**
@@ -20,4 +20,63 @@ function checkExternalModuleGetterReturnStatement(blockStatement, statements) {
20
20
  return undefined;
21
21
  }
22
22
  exports.checkExternalModuleGetterReturnStatement = checkExternalModuleGetterReturnStatement;
23
+ /**
24
+ * Invariant function for checking if an render function defined in an external module has only a
25
+ * statement in it, a return statement.
26
+ * @param blockStatement the babel path object for the BlockStatement representing the contents of the render function.
27
+ * @param statements the babel path object array for all of the Statements in the render function.
28
+ * @returns PrimingDiagnostic of the BlockStatement if the invariant is detected, or undefined if the invariant wasn't found
29
+ */
30
+ function checkExternalModuleRenderReturnStatement(blockStatement, statements) {
31
+ // the render function doesn't only have a return method as expected. Skip traversal, then return from this method here
32
+ if (!(statements.length === 1 && statements[0].isReturnStatement())) {
33
+ if (blockStatement.node.loc) {
34
+ return (0, rules_1.getPrimingDiagnostic)(rules_1.diagnosticMessages.NO_RENDER_FUNCTION_CONTAINS_MORE_THAN_RETURN_STATEMENT, shared_1.LLSRange.fromBabelSourceLocation(blockStatement.node.loc), []);
35
+ }
36
+ }
37
+ return undefined;
38
+ }
39
+ exports.checkExternalModuleRenderReturnStatement = checkExternalModuleRenderReturnStatement;
40
+ /**
41
+ * Function to validate the render function, returns a priming diagnost if an invariant is found.
42
+ * @param returnStmt the return satement node
43
+ * @param moduleMetadata the module metadata obj
44
+ * @returns a priming diagnostic or undefined.
45
+ */
46
+ function checkRenderFunctionReturnValues(returnStmt, moduleMetadata) {
47
+ //eg. return child1;
48
+ if (returnStmt.argument && returnStmt.argument.type == 'Identifier') {
49
+ const identifierName = returnStmt.argument.name;
50
+ const importedTemplateMetadata = moduleMetadata.importsByName.get(identifierName);
51
+ //the identifier that is being returned was not found in the imports by name array.
52
+ if (importedTemplateMetadata) {
53
+ if (!importedTemplateMetadata.templateKomaciDoc) {
54
+ if (returnStmt.loc) {
55
+ return (0, rules_1.getPrimingDiagnostic)(rules_1.diagnosticMessages.NO_RENDER_FUNCTION_RETURN_STATEMENT_NOT_RETURNING_IMPORTED_TEMPLATE, shared_1.LLSRange.fromBabelSourceLocation(returnStmt.loc), []);
56
+ }
57
+ }
58
+ }
59
+ }
60
+ else if (returnStmt.argument &&
61
+ returnStmt.argument.type == 'ConditionalExpression') {
62
+ const conditionalExpr = returnStmt.argument;
63
+ const consequence = conditionalExpr.consequent;
64
+ const alternate = conditionalExpr.alternate;
65
+ const consequenceTemplateImport = moduleMetadata.importsByName.get(consequence.name);
66
+ const alternateTemplateImport = moduleMetadata.importsByName.get(alternate.name);
67
+ if (!consequenceTemplateImport.templateKomaciDoc &&
68
+ !alternateTemplateImport.templateKomaciDoc) {
69
+ if (returnStmt.loc) {
70
+ return (0, rules_1.getPrimingDiagnostic)(rules_1.diagnosticMessages.NO_RENDER_FUNCTION_RETURN_STATEMENT_NOT_RETURNING_IMPORTED_TEMPLATE, shared_1.LLSRange.fromBabelSourceLocation(returnStmt.loc), []);
71
+ }
72
+ }
73
+ }
74
+ else {
75
+ if (returnStmt.loc) {
76
+ return (0, rules_1.getPrimingDiagnostic)(rules_1.diagnosticMessages.NO_RENDER_FUNCTION_RETURN_STATEMENT_NOT_RETURNING_IMPORTED_TEMPLATE, shared_1.LLSRange.fromBabelSourceLocation(returnStmt.loc), []);
77
+ }
78
+ }
79
+ return undefined;
80
+ }
81
+ exports.checkRenderFunctionReturnValues = checkRenderFunctionReturnValues;
23
82
  //# sourceMappingURL=returnStatementInvariantFunctions.js.map
package/build/rules.js CHANGED
@@ -192,6 +192,24 @@ exports.diagnosticMessages = {
192
192
  message: 'Supported getters can only contain a return statement',
193
193
  source: SOURCE_PREFIX_OFFLINE_CODE_ANALYZER,
194
194
  },
195
+ NO_RENDER_FUNCTION_CONTAINS_MORE_THAN_RETURN_STATEMENT: {
196
+ code: `${MESSAGE_CODE_PREFIX}1025`,
197
+ severity: SEVERITY.ERROR,
198
+ message: 'Supported render functions in custom components can only contain a return statement',
199
+ source: SOURCE_PREFIX_OFFLINE_CODE_ANALYZER,
200
+ },
201
+ NO_RENDER_FUNCTION_RETURN_STATEMENT: {
202
+ code: `${MESSAGE_CODE_PREFIX}1025`,
203
+ severity: SEVERITY.ERROR,
204
+ message: 'Supported render functions need to contain a return statement',
205
+ source: SOURCE_PREFIX_OFFLINE_CODE_ANALYZER,
206
+ },
207
+ NO_RENDER_FUNCTION_RETURN_STATEMENT_NOT_RETURNING_IMPORTED_TEMPLATE: {
208
+ code: `${MESSAGE_CODE_PREFIX}1025`,
209
+ severity: SEVERITY.ERROR,
210
+ message: 'Supported render functions can only return supported imported templates',
211
+ source: SOURCE_PREFIX_OFFLINE_CODE_ANALYZER,
212
+ },
195
213
  NO_EXPRESSION_CONTAINS_MODULE_LEVEL_VARIABLE_REF: {
196
214
  code: `${MESSAGE_CODE_PREFIX}1026`,
197
215
  severity: SEVERITY.ERROR,
@@ -33,6 +33,14 @@ export declare function checkFunctionalPurity(path: NodePath<t.ClassMethod | t.C
33
33
  * least one invariant check failed. If no invariant checks failed, an empty Array<InvariantDetail> is returned.
34
34
  */
35
35
  export declare function validateGetter(getterMethodPath: NodePath<t.ClassMethod>, adgIndex: number, moduleMetadata: ModuleMetadata, moduleContext: ModuleContext, returnSourceLocation?: boolean): boolean | Array<PrimingDiagnostic>;
36
+ /**
37
+ * Given a set of results from invariant checks. we want to filter out any no-op values and put meaningful
38
+ * results into the list of allInvalidLocations
39
+ * @param allInvalidLocations PrimingDiagnostic[] containing all invariants that occurred so far
40
+ * @param results the Array<PrimingDiagnostic | undefined> containing what is return by calling invariant checker method.
41
+ * @returns array of PrimingDiagnostic filtered of no-op values/non-meaningful results.
42
+ */
43
+ export declare function processLocationInfo(allInvalidLocations: PrimingDiagnostic[], results: Array<PrimingDiagnostic | undefined>): PrimingDiagnostic[];
36
44
  /**
37
45
  * Validate template strings for purity. Variable declarations are not valid inside of a template expression so we do not have to support that use case here.
38
46
  * Template string processing is essentially a subset of what we do for getter functions. The only diff is that we don't have to do the extra "only a return statement"
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validateTemplateString = exports.validateGetter = exports.checkFunctionalPurity = void 0;
3
+ exports.validateTemplateString = exports.processLocationInfo = exports.validateGetter = exports.checkFunctionalPurity = void 0;
4
4
  const memberExpressionInvariantFunctions_1 = require("./invariantFunctions/memberExpressionInvariantFunctions");
5
5
  const callExpressionInvariantFunctions_1 = require("./invariantFunctions/callExpressionInvariantFunctions");
6
6
  const assignmentExpressionInvariantFunctions_1 = require("./invariantFunctions/assignmentExpressionInvariantFunctions");
@@ -104,8 +104,8 @@ exports.checkFunctionalPurity = checkFunctionalPurity;
104
104
  * least one invariant check failed. If no invariant checks failed, an empty Array<InvariantDetail> is returned.
105
105
  */
106
106
  function validateGetter(getterMethodPath, adgIndex, moduleMetadata, moduleContext, returnSourceLocation = false) {
107
- const getterDeclaredVars = (0, common_shared_1.getVariablesDeclaredInGetter)(getterMethodPath);
108
- const thisAliases = (0, common_shared_1.getThisAliasDeclaredInGetter)(getterMethodPath);
107
+ const getterDeclaredVars = (0, common_shared_1.getVariablesDeclaredInFunction)(getterMethodPath);
108
+ const thisAliases = (0, common_shared_1.getThisAliasDeclaredInFunction)(getterMethodPath);
109
109
  let primingDiagnostics = checkFunctionalPurity(getterMethodPath, adgIndex, moduleMetadata, moduleContext, {
110
110
  thisAliases,
111
111
  declaredVariables: getterDeclaredVars,
@@ -138,6 +138,7 @@ function processLocationInfo(allInvalidLocations, results) {
138
138
  // concat method returns a new array from the original array + the arrays to concatenate
139
139
  return allInvalidLocations.concat(results.filter((result) => result !== undefined));
140
140
  }
141
+ exports.processLocationInfo = processLocationInfo;
141
142
  /**
142
143
  * Validate template strings for purity. Variable declarations are not valid inside of a template expression so we do not have to support that use case here.
143
144
  * Template string processing is essentially a subset of what we do for getter functions. The only diff is that we don't have to do the extra "only a return statement"
@@ -0,0 +1,15 @@
1
+ import * as t from '@babel/types';
2
+ import { NodePath } from '@babel/core';
3
+ import { ModuleContext, ModuleMetadata } from '@komaci/common-shared';
4
+ import { PrimingDiagnostic } from './types';
5
+ /**
6
+ * Function to validate a components render function.
7
+ * @param renderFunction the render function to validate
8
+ * @param adgIndex the adg index
9
+ * @param moduleMetadata the moduleMeta data object
10
+ * @param moduleContext the module context
11
+ * @param returnSourceLocation a bool if we want to return the source location
12
+ * @returns true or false if the function is valid or a priming diagnostic
13
+ */
14
+ export declare function validateRenderFunction(renderFunction: NodePath<t.ClassMethod>, adgIndex: number, moduleMetadata: ModuleMetadata, moduleContext: ModuleContext, returnSourceLocation?: boolean): boolean | Array<PrimingDiagnostic>;
15
+ //# sourceMappingURL=validateRenderFunction.d.ts.map
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateRenderFunction = void 0;
4
+ const common_shared_1 = require("@komaci/common-shared");
5
+ const returnStatementInvariantFunctions_1 = require("./invariantFunctions/returnStatementInvariantFunctions");
6
+ const validateGetter_1 = require("./validateGetter");
7
+ const rules_1 = require("./rules");
8
+ const shared_1 = require("./shared");
9
+ /**
10
+ * Function to validate a components render function.
11
+ * @param renderFunction the render function to validate
12
+ * @param adgIndex the adg index
13
+ * @param moduleMetadata the moduleMeta data object
14
+ * @param moduleContext the module context
15
+ * @param returnSourceLocation a bool if we want to return the source location
16
+ * @returns true or false if the function is valid or a priming diagnostic
17
+ */
18
+ function validateRenderFunction(renderFunction, adgIndex, moduleMetadata, moduleContext, returnSourceLocation = false) {
19
+ let primingDiagnostics = [];
20
+ const declaredVars = (0, common_shared_1.getVariablesDeclaredInFunction)(renderFunction);
21
+ const thisAliases = (0, common_shared_1.getThisAliasDeclaredInFunction)(renderFunction);
22
+ //First Check the functional Purity of the render function
23
+ primingDiagnostics = (0, validateGetter_1.checkFunctionalPurity)(renderFunction, adgIndex, moduleMetadata, moduleContext, {
24
+ thisAliases,
25
+ declaredVariables: declaredVars,
26
+ });
27
+ const blockStatement = renderFunction.get('body');
28
+ const statements = blockStatement.get('body');
29
+ let hasReturnStatement = false;
30
+ //Visitor object to look at each return statement in the render function and validate it.
31
+ const Vistior = {
32
+ ReturnStatement(path) {
33
+ //Check the if the return statement is valid.
34
+ hasReturnStatement = true;
35
+ primingDiagnostics = (0, validateGetter_1.processLocationInfo)(primingDiagnostics, [
36
+ (0, returnStatementInvariantFunctions_1.checkRenderFunctionReturnValues)(path.node, moduleMetadata),
37
+ ]);
38
+ },
39
+ };
40
+ renderFunction.traverse(Vistior);
41
+ //we don't have a return statement in the render function.
42
+ if (!hasReturnStatement) {
43
+ if (renderFunction.node.loc) {
44
+ primingDiagnostics = (0, validateGetter_1.processLocationInfo)(primingDiagnostics, [
45
+ (0, rules_1.getPrimingDiagnostic)(rules_1.diagnosticMessages.NO_RENDER_FUNCTION_RETURN_STATEMENT, shared_1.LLSRange.fromBabelSourceLocation(renderFunction.node.loc), []),
46
+ ]);
47
+ }
48
+ }
49
+ // if render function was defined in an external module
50
+ if (moduleContext.isExternal) {
51
+ // the render function doesn't only have a return method as expected. Skip traversal, then return from this method here
52
+ primingDiagnostics = (0, validateGetter_1.processLocationInfo)(primingDiagnostics, [
53
+ (0, returnStatementInvariantFunctions_1.checkExternalModuleRenderReturnStatement)(blockStatement, statements),
54
+ ]);
55
+ // If checkExternalModuleGetterReturnStatement() fails we should just return. There's no use in
56
+ // validating a function that is already foundationally invalid
57
+ if (primingDiagnostics.length > 0) {
58
+ return returnSourceLocation ? primingDiagnostics : false;
59
+ }
60
+ }
61
+ return returnSourceLocation ? primingDiagnostics : primingDiagnostics.length === 0;
62
+ }
63
+ exports.validateRenderFunction = validateRenderFunction;
64
+ //# sourceMappingURL=validateRenderFunction.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@komaci/static-analyzer",
3
- "version": "242.1.5",
3
+ "version": "242.1.6",
4
4
  "description": "Komaci Diagnostics API",
5
5
  "homepage": "https://komaci.dev/",
6
6
  "repository": {
@@ -28,12 +28,12 @@
28
28
  "!**/RULES.todo.md"
29
29
  ],
30
30
  "dependencies": {
31
- "@komaci/common-shared": "242.1.5",
31
+ "@komaci/common-shared": "242.1.6",
32
32
  "@lwc/metadata": "2.22.0-0",
33
33
  "@lwc/sfdc-compiler-utils": "2.22.0-0"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@babel/types": "^7.9.0",
37
- "@komaci/types": "242.1.5"
37
+ "@komaci/types": "242.1.6"
38
38
  }
39
39
  }