@komaci/common-shared 240.1.3
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/__mocks__/@babel/parser.d.ts +2 -0
- package/build/__mocks__/@babel/parser.js +6 -0
- package/build/allowListGlobals.d.ts +4 -0
- package/build/allowListGlobals.js +7 -0
- package/build/allowlistNamespaces.d.ts +29 -0
- package/build/allowlistNamespaces.js +67 -0
- package/build/index.d.ts +7 -0
- package/build/index.js +19 -0
- package/build/internal-namespaces.json +1062 -0
- package/build/komaciDocumentIntrospection.d.ts +120 -0
- package/build/komaciDocumentIntrospection.js +366 -0
- package/build/parser.d.ts +9 -0
- package/build/parser.js +19 -0
- package/build/types.d.ts +193 -0
- package/build/types.js +16 -0
- package/build/utils.d.ts +153 -0
- package/build/utils.js +554 -0
- package/package.json +37 -0
package/build/utils.js
ADDED
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.isDeclaredInAst = exports.isExpressionThisOrAlias = exports.getThisAliasDeclaredInGetter = exports.isPropertyNodeUsed = exports.isGetterNodeUsed = exports.isPropertyUsed = exports.getClassMethodName = exports.getVariablesDeclaredInGetter = exports.isExternalModule = exports.getAstContextObject = exports.getAllClassMethods = exports.getAllModuleVaraibles = exports.getAllModuleFunctions = exports.getAllImportReferences = exports.getFromIdentifierOrStringLiteral = exports.collectImportUsage = exports.getMemberVarsFromGetter = exports.implicitConsumptionMetadata = exports.getClassPropertyInfos = exports.getClassProperties = exports.getPropertyMetadataFromAst = exports.ONE_NS = exports.FORCE_NS = exports.LIGHTNING_NS = void 0;
|
|
23
|
+
const t = __importStar(require("@babel/types"));
|
|
24
|
+
const core_1 = require("@babel/core");
|
|
25
|
+
const allowlistNamespaces_1 = require("./allowlistNamespaces");
|
|
26
|
+
exports.LIGHTNING_NS = 'lightning';
|
|
27
|
+
exports.FORCE_NS = 'force';
|
|
28
|
+
exports.ONE_NS = 'one';
|
|
29
|
+
/**
|
|
30
|
+
* collect node paths for different pieces of a given class so we can more effectively traverse them in the future
|
|
31
|
+
*
|
|
32
|
+
* we must do an init traversal to take nodes and turn them into nodepaths, which have context about their position in tree
|
|
33
|
+
* we need this info so we can do sub tree traversals later.
|
|
34
|
+
* @param ast babel abstract syntax tree
|
|
35
|
+
*/
|
|
36
|
+
function getPropertyMetadataFromAst(ast) {
|
|
37
|
+
const nodes = {
|
|
38
|
+
getters: [],
|
|
39
|
+
templateStrings: [],
|
|
40
|
+
};
|
|
41
|
+
const Visitor = {
|
|
42
|
+
Program(path) {
|
|
43
|
+
const exportDefaultDecl = path
|
|
44
|
+
.get('body')
|
|
45
|
+
.filter((child) => child.isExportDefaultDeclaration());
|
|
46
|
+
// "exportDefaultDecl[0]" here is a NodePath<t.ExportDefaultDeclaration>
|
|
47
|
+
// There can only be one ExportDefaultDeclaration class declaration per file (hence the [0] reference)
|
|
48
|
+
// ExportDefaultDeclaration can only be at the top level of the file (cannot be in an inner, nested class)
|
|
49
|
+
if (exportDefaultDecl.length > 0) {
|
|
50
|
+
const classDecl = exportDefaultDecl[0].get('declaration');
|
|
51
|
+
if (classDecl.isClassDeclaration()) {
|
|
52
|
+
const classBody = classDecl.get('body');
|
|
53
|
+
if (classBody.isClassBody()) {
|
|
54
|
+
nodes.getters = classBody
|
|
55
|
+
.get('body')
|
|
56
|
+
.filter((path) => path.node.type === 'ClassMethod' &&
|
|
57
|
+
path.node.kind === 'get');
|
|
58
|
+
nodes.templateStrings = classBody
|
|
59
|
+
.get('body')
|
|
60
|
+
.filter((path) => path.node.type === 'ClassProperty' &&
|
|
61
|
+
path.node.value &&
|
|
62
|
+
(path.node.value.type === 'TemplateLiteral' ||
|
|
63
|
+
path.node.value.type ===
|
|
64
|
+
'TaggedTemplateExpression'));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
(0, core_1.traverse)(ast, Visitor);
|
|
71
|
+
return nodes;
|
|
72
|
+
}
|
|
73
|
+
exports.getPropertyMetadataFromAst = getPropertyMetadataFromAst;
|
|
74
|
+
/**
|
|
75
|
+
* @param node
|
|
76
|
+
* @returns true if node is a ClassBody
|
|
77
|
+
*/
|
|
78
|
+
function isNodeClassBody(node) {
|
|
79
|
+
return node?.type === 'ClassBody';
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Given the AST of an entire JS source file, this method looks for class member properties.
|
|
83
|
+
* If there is no default export in the AST, no class properties will be returned (empty array is returned).
|
|
84
|
+
* @param astRoot AST representing an entire Program, as a @babel/types File object
|
|
85
|
+
* @returns Array of NodePath<ClassProperty> representing the @babel NodePaths for all class member
|
|
86
|
+
* properties, if any exist. Otherwise, returns an empty array.
|
|
87
|
+
*/
|
|
88
|
+
function getClassProperties(astRoot) {
|
|
89
|
+
let classProperties = [];
|
|
90
|
+
const prog = astRoot.program;
|
|
91
|
+
const body = prog.body;
|
|
92
|
+
const exportDefaultDecl = body.filter((child) => child.type === 'ExportDefaultDeclaration');
|
|
93
|
+
if (exportDefaultDecl.length > 0) {
|
|
94
|
+
const classDecl = exportDefaultDecl[0]
|
|
95
|
+
.declaration; // there can only be one export default declaration
|
|
96
|
+
if (isNodeClassBody(classDecl.body)) {
|
|
97
|
+
const classBody = classDecl.body;
|
|
98
|
+
classProperties = classBody.body.filter((classChild) => classChild.type === 'ClassProperty' ||
|
|
99
|
+
(classChild.type === 'ClassMethod' && classChild.kind === 'get'));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return classProperties;
|
|
103
|
+
}
|
|
104
|
+
exports.getClassProperties = getClassProperties;
|
|
105
|
+
/**
|
|
106
|
+
* Utility method that takes in an @babel/types ClassProperty array, and returns an array of ClassPropertyInfo
|
|
107
|
+
* objects containing information about each ClassProperty from the input array.
|
|
108
|
+
* @param classProperties
|
|
109
|
+
* @returns Array of ClassPropertyInfo, where each element corresponds to the input ClassProperty array.
|
|
110
|
+
*/
|
|
111
|
+
function getClassPropertyInfos(classProperties = []) {
|
|
112
|
+
const classPropInfos = [];
|
|
113
|
+
classProperties
|
|
114
|
+
.filter((classProp) => t.isIdentifier(classProp.key))
|
|
115
|
+
.forEach((classProp) => {
|
|
116
|
+
const id = classProp.key;
|
|
117
|
+
const decorators = classProp.decorators;
|
|
118
|
+
let decoratorType = undefined;
|
|
119
|
+
if (decorators) {
|
|
120
|
+
// non-annotated class properties won't have a decorator
|
|
121
|
+
const expr = decorators[0].expression;
|
|
122
|
+
if (expr.type === 'CallExpression') {
|
|
123
|
+
const callee = expr.callee;
|
|
124
|
+
decoratorType = callee.name;
|
|
125
|
+
}
|
|
126
|
+
else if (expr.type === 'Identifier') {
|
|
127
|
+
decoratorType = expr.name;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const classPropInfo = {
|
|
131
|
+
classProp: classProp,
|
|
132
|
+
classPropId: id.name,
|
|
133
|
+
isDecorated: decorators !== undefined &&
|
|
134
|
+
decorators !== null &&
|
|
135
|
+
decorators.length > 0,
|
|
136
|
+
hasInitialValue: t.isClassProperty(classProp)
|
|
137
|
+
? classProp.value !== null
|
|
138
|
+
: false,
|
|
139
|
+
};
|
|
140
|
+
if (classPropInfo.isDecorated) {
|
|
141
|
+
classPropInfo.decoratorType = decoratorType;
|
|
142
|
+
}
|
|
143
|
+
classPropInfos.push(classPropInfo);
|
|
144
|
+
});
|
|
145
|
+
return classPropInfos;
|
|
146
|
+
}
|
|
147
|
+
exports.getClassPropertyInfos = getClassPropertyInfos;
|
|
148
|
+
/**
|
|
149
|
+
* Given a valid functional node (tempalte string or getter function), collect information that we may not have been able to collect via KomaciDocument
|
|
150
|
+
* and return a list of class member variables that are properly used in the method body.
|
|
151
|
+
* "properly" = i.e. used in the right-hand side of a member expression.
|
|
152
|
+
* @param getter NodePath<ClassMethod | Class Property> path that represents class member-level getter method or template string
|
|
153
|
+
* e.g. "get myId() { return '187291110cd3a'; }"
|
|
154
|
+
* @param classPropInfos ClassPropertyInfo[] that contains all of the class-level properties.
|
|
155
|
+
* @param importDeclarations Map<string, ImporDeclarationInfo> which contains metadata for all import statements
|
|
156
|
+
* that currently exist. Does not contain state as to whether that import is being used.
|
|
157
|
+
* @param moduleLevelConsumption ModuleLevelConsumption. Contains a ConsumedImports which in turn contains a Map<string, ImportDetail>
|
|
158
|
+
* which in turn holds state as tp which imports are currently being used
|
|
159
|
+
* @returns ImplicitConsumption, which contains an array representing the properly-used member variables.
|
|
160
|
+
* Returns ImplicitConsumption with an empty array if none were found.
|
|
161
|
+
*/
|
|
162
|
+
function implicitConsumptionMetadata(node, classPropInfos, importDeclarations, // import metadata
|
|
163
|
+
moduleLevelConsumption) {
|
|
164
|
+
const identifiers = new Set();
|
|
165
|
+
const Visitors = {
|
|
166
|
+
// visitor for each type
|
|
167
|
+
MemberExpression(path) {
|
|
168
|
+
getMemberVarsFromGetter(path, identifiers);
|
|
169
|
+
},
|
|
170
|
+
Identifier(path) {
|
|
171
|
+
collectImportUsage(path, classPropInfos, importDeclarations, moduleLevelConsumption.consumedImports);
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
node.traverse(Visitors);
|
|
175
|
+
return { identifiers: Array.from(identifiers) };
|
|
176
|
+
}
|
|
177
|
+
exports.implicitConsumptionMetadata = implicitConsumptionMetadata;
|
|
178
|
+
/*
|
|
179
|
+
* Given a valid getter method (class method), return a list of class member variables that are properly
|
|
180
|
+
* used in the method body. "properly" = i.e. used in the right-hand side of a member expression.
|
|
181
|
+
* @param getterMethodPath NodePath<ClassMethod> path that represents class member-level getter method
|
|
182
|
+
* e.g. "get myId() { return '187291110cd3a'; }"
|
|
183
|
+
* @param Set<string> representing the properly-used member variables. We add names to this as they are d
|
|
184
|
+
* eemed to be member vars
|
|
185
|
+
*/
|
|
186
|
+
function getMemberVarsFromGetter(path, identifiers) {
|
|
187
|
+
if (path.get('object').type === 'ThisExpression' &&
|
|
188
|
+
path.get('property').type === 'Identifier') {
|
|
189
|
+
const identifier = path.get('property').node;
|
|
190
|
+
if (!identifiers.has(identifier.name)) {
|
|
191
|
+
identifiers.add(identifier.name);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
exports.getMemberVarsFromGetter = getMemberVarsFromGetter;
|
|
196
|
+
/**
|
|
197
|
+
* Collect metadata about all the imports consumed for an identifier in a getter
|
|
198
|
+
* @param path NodePath of the current Identifier in the getter
|
|
199
|
+
* @param classPropInfos Array of ClassPropertyInfo objects that have all of the information
|
|
200
|
+
* related to all class properties in the class.
|
|
201
|
+
* @param importDeclarations Metadata about all the imports
|
|
202
|
+
* @param consumedImports The map to add info to about this identifier, whether it is an import that is being used
|
|
203
|
+
* in the getter, or if it is assigned an import being used in the getter.
|
|
204
|
+
*/
|
|
205
|
+
function collectImportUsage(path, classPropInfos, importDeclarations, consumedImports) {
|
|
206
|
+
const name = path.node.name;
|
|
207
|
+
let nameToReference = name;
|
|
208
|
+
let importInfo = importDeclarations.get(name); // finds direct references of import specifiers in the getter
|
|
209
|
+
// i.e. find `MyID1.CONST` in the getter, where `MyID1` is an import specifier
|
|
210
|
+
if (!importInfo &&
|
|
211
|
+
path.parent.type === 'MemberExpression' &&
|
|
212
|
+
path.parent.object.type === 'Identifier' &&
|
|
213
|
+
path.parent.object === path.node) {
|
|
214
|
+
importInfo = importDeclarations.get(path.parent.object.name);
|
|
215
|
+
}
|
|
216
|
+
// find indirect import references (where import was assigned to a class member variable)
|
|
217
|
+
if (!importInfo) {
|
|
218
|
+
const importSpecifierNames = new Set(Array.from(importDeclarations.keys()));
|
|
219
|
+
classPropInfos.forEach((classPropInfo) => {
|
|
220
|
+
// check for type NodePath<t.ClassProperty> vs. t.ClassProperty. The former has a .node property
|
|
221
|
+
const isNodePath = classPropInfo.classProp.node !== undefined;
|
|
222
|
+
const classProp = isNodePath
|
|
223
|
+
? classPropInfo.classProp.node
|
|
224
|
+
: classPropInfo.classProp;
|
|
225
|
+
if (classProp.key.type === 'Identifier' &&
|
|
226
|
+
classProp.key.name === name &&
|
|
227
|
+
classProp.value?.type === 'Identifier' &&
|
|
228
|
+
importSpecifierNames.has(classProp.value.name)) {
|
|
229
|
+
importInfo = importDeclarations.get(classProp.value.name);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
if (importInfo) {
|
|
234
|
+
if (importInfo.isDefault) {
|
|
235
|
+
nameToReference = 'default';
|
|
236
|
+
}
|
|
237
|
+
else if (importInfo.isNamespaceSpecifier) {
|
|
238
|
+
// this case needs to be handled separately as it always has an alias
|
|
239
|
+
nameToReference = '*';
|
|
240
|
+
}
|
|
241
|
+
else if (importInfo.trueName) {
|
|
242
|
+
nameToReference = importInfo.trueName;
|
|
243
|
+
}
|
|
244
|
+
let fullImportContext = consumedImports.get(importInfo.namespace);
|
|
245
|
+
if (fullImportContext && !fullImportContext.names.has(name)) {
|
|
246
|
+
fullImportContext.names.add(nameToReference);
|
|
247
|
+
}
|
|
248
|
+
else if (!fullImportContext) {
|
|
249
|
+
const names = new Set();
|
|
250
|
+
names.add(nameToReference);
|
|
251
|
+
fullImportContext = {
|
|
252
|
+
names,
|
|
253
|
+
resourceName: importInfo.namespace,
|
|
254
|
+
isNamespaceSpecifier: importInfo.isNamespaceSpecifier,
|
|
255
|
+
isDefaultSpecifier: importInfo.isDefault,
|
|
256
|
+
isSupported: importInfo.isSupported,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
consumedImports.set(importInfo.namespace, fullImportContext);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
exports.collectImportUsage = collectImportUsage;
|
|
263
|
+
/**
|
|
264
|
+
* Some children of nodes can be a direct identifier or a string literal. helper helps do
|
|
265
|
+
* this consistant dance of getting the value from either
|
|
266
|
+
* @param node Node to ge value of
|
|
267
|
+
* @returns value
|
|
268
|
+
*/
|
|
269
|
+
function getFromIdentifierOrStringLiteral(node) {
|
|
270
|
+
return node.type === 'Identifier' ? node.name : node.value;
|
|
271
|
+
}
|
|
272
|
+
exports.getFromIdentifierOrStringLiteral = getFromIdentifierOrStringLiteral;
|
|
273
|
+
/**
|
|
274
|
+
* Function for getting an array of supported namesapce references.
|
|
275
|
+
* @param astRoot the root of the ast
|
|
276
|
+
* @returns an Array of supported namespace references.
|
|
277
|
+
*/
|
|
278
|
+
function getAllImportReferences(astRoot) {
|
|
279
|
+
const importReferences = new Map();
|
|
280
|
+
const program = astRoot.program;
|
|
281
|
+
const body = program.body;
|
|
282
|
+
const importDeclarations = body.filter((currentDec) => currentDec.type === 'ImportDeclaration');
|
|
283
|
+
importDeclarations.forEach((currentDec) => {
|
|
284
|
+
const isValid = isValidNamespace(currentDec.source.value) &&
|
|
285
|
+
(0, allowlistNamespaces_1.isLibraryValid)(currentDec.source.value);
|
|
286
|
+
const specifiers = currentDec.specifiers;
|
|
287
|
+
specifiers.forEach((currentSpecifier) => {
|
|
288
|
+
let importName = undefined;
|
|
289
|
+
if (currentSpecifier.type === 'ImportSpecifier') {
|
|
290
|
+
importName = currentSpecifier.local // local is alias (the most specific name)
|
|
291
|
+
? getFromIdentifierOrStringLiteral(currentSpecifier.local)
|
|
292
|
+
: getFromIdentifierOrStringLiteral(currentSpecifier.imported);
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
importName = getFromIdentifierOrStringLiteral(currentSpecifier.local);
|
|
296
|
+
}
|
|
297
|
+
importReferences.set(importName, {
|
|
298
|
+
namespace: currentDec.source.value,
|
|
299
|
+
identifierName: importName,
|
|
300
|
+
isSupported: isValid,
|
|
301
|
+
isDefault: currentSpecifier.type === 'ImportDefaultSpecifier',
|
|
302
|
+
isNamespaceSpecifier: currentSpecifier.type === 'ImportNamespaceSpecifier',
|
|
303
|
+
trueName: currentSpecifier.type === 'ImportSpecifier'
|
|
304
|
+
? getFromIdentifierOrStringLiteral(currentSpecifier.imported)
|
|
305
|
+
: undefined,
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
return importReferences;
|
|
310
|
+
}
|
|
311
|
+
exports.getAllImportReferences = getAllImportReferences;
|
|
312
|
+
/**
|
|
313
|
+
* Helper function to validate if a namespace is in our allowed namespace list.
|
|
314
|
+
* @param namespace the namespace to validate.
|
|
315
|
+
* @returns true of the namespace is supported, false if unsupported.
|
|
316
|
+
*/
|
|
317
|
+
function isValidNamespace(importPath) {
|
|
318
|
+
return (0, allowlistNamespaces_1.isNamespaceInternal)((0, allowlistNamespaces_1.getNamespaceFromImport)(importPath));
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Function to get an array of function names that are defined at the module level.
|
|
322
|
+
* @returns an array of function names that are defined at the module level.
|
|
323
|
+
*/
|
|
324
|
+
function getAllModuleFunctions(astRoot) {
|
|
325
|
+
const result = [];
|
|
326
|
+
const program = astRoot.program;
|
|
327
|
+
const body = program.body;
|
|
328
|
+
const declarations = body.filter((currentDec) => currentDec.type === 'FunctionDeclaration' ||
|
|
329
|
+
currentDec.type === 'VariableDeclaration');
|
|
330
|
+
declarations.forEach((currentDec) => {
|
|
331
|
+
if (currentDec.type === 'FunctionDeclaration') {
|
|
332
|
+
const functionDec = currentDec;
|
|
333
|
+
if (functionDec.id) {
|
|
334
|
+
result.push(functionDec.id.name);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
if (currentDec.type === 'VariableDeclaration') {
|
|
338
|
+
const varDeclarator = currentDec.declarations[0];
|
|
339
|
+
if (varDeclarator.init?.type === 'ArrowFunctionExpression' ||
|
|
340
|
+
varDeclarator.init?.type === 'FunctionExpression') {
|
|
341
|
+
if (varDeclarator.id.type === 'Identifier') {
|
|
342
|
+
result.push(varDeclarator.id.name);
|
|
343
|
+
}
|
|
344
|
+
if (varDeclarator.id.type === 'ObjectPattern') {
|
|
345
|
+
varDeclarator.id.properties.forEach((currentProp) => {
|
|
346
|
+
result.push(currentProp.value.name);
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
return result;
|
|
353
|
+
}
|
|
354
|
+
exports.getAllModuleFunctions = getAllModuleFunctions;
|
|
355
|
+
/**
|
|
356
|
+
* Function that returns an array of variable names that are defined at the module level.
|
|
357
|
+
* @param astRoot the root ast node.
|
|
358
|
+
* @returns an array of variable names that are defined at the module level.
|
|
359
|
+
*/
|
|
360
|
+
function getAllModuleVaraibles(astRoot) {
|
|
361
|
+
const result = [];
|
|
362
|
+
const program = astRoot.program;
|
|
363
|
+
const body = program.body;
|
|
364
|
+
const varDeclarations = body.filter((currentDec) => currentDec.type === 'VariableDeclaration');
|
|
365
|
+
varDeclarations.forEach((currentDec) => {
|
|
366
|
+
const declarator = currentDec.declarations[0];
|
|
367
|
+
if (declarator.init?.type != 'FunctionExpression' &&
|
|
368
|
+
declarator.init?.type != 'ArrowFunctionExpression') {
|
|
369
|
+
if (declarator.id.type === 'Identifier') {
|
|
370
|
+
result.push(declarator.id.name);
|
|
371
|
+
}
|
|
372
|
+
if (declarator.id.type === 'ObjectPattern') {
|
|
373
|
+
declarator.id.properties.forEach((currentProp) => {
|
|
374
|
+
result.push(currentProp.value.name);
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
return result;
|
|
380
|
+
}
|
|
381
|
+
exports.getAllModuleVaraibles = getAllModuleVaraibles;
|
|
382
|
+
/**
|
|
383
|
+
* Function to get an array of function names that are defined on the default exports class.
|
|
384
|
+
* @returns an array of function names that are defined on the class.
|
|
385
|
+
*/
|
|
386
|
+
function getAllClassMethods(astRoot) {
|
|
387
|
+
const result = [];
|
|
388
|
+
const program = astRoot.program;
|
|
389
|
+
const body = program.body;
|
|
390
|
+
const exportDefaultDec = body.filter((currentDec) => currentDec.type === 'ExportDefaultDeclaration');
|
|
391
|
+
const classBodyArr = exportDefaultDec[0]?.declaration.body
|
|
392
|
+
?.body;
|
|
393
|
+
if (classBodyArr) {
|
|
394
|
+
classBodyArr.forEach((dec) => {
|
|
395
|
+
if (dec.type === 'ClassMethod') {
|
|
396
|
+
const identifier = dec.key;
|
|
397
|
+
result.push(identifier.name);
|
|
398
|
+
}
|
|
399
|
+
if (dec.type === 'ClassProperty') {
|
|
400
|
+
const classProperty = dec;
|
|
401
|
+
if (classProperty.value?.type === 'FunctionExpression' ||
|
|
402
|
+
classProperty.value?.type === 'ArrowFunctionExpression') {
|
|
403
|
+
result.push(classProperty.key.name);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
return result;
|
|
409
|
+
}
|
|
410
|
+
exports.getAllClassMethods = getAllClassMethods;
|
|
411
|
+
/**
|
|
412
|
+
* Function to get an AstContext object for a given ast.
|
|
413
|
+
* @param ast the ast.
|
|
414
|
+
* @returns a context object containing meta data about the ast.
|
|
415
|
+
*/
|
|
416
|
+
function getAstContextObject(ast) {
|
|
417
|
+
const props = getClassProperties(ast);
|
|
418
|
+
const context = {
|
|
419
|
+
importDeclarations: getAllImportReferences(ast),
|
|
420
|
+
moduleFunctions: getAllModuleFunctions(ast),
|
|
421
|
+
moduleVariables: getAllModuleVaraibles(ast),
|
|
422
|
+
classProperties: getClassPropertyInfos(props),
|
|
423
|
+
classFunctions: getAllClassMethods(ast),
|
|
424
|
+
};
|
|
425
|
+
return context;
|
|
426
|
+
}
|
|
427
|
+
exports.getAstContextObject = getAstContextObject;
|
|
428
|
+
/** Determines if the module (i.e LWC Component) was written by an external user. If the namespace of the module
|
|
429
|
+
* exactly matches one of 'lightning', 'force', or 'one', it is NOT an external component.
|
|
430
|
+
* @param namespace string namespace of the ModuleInfo to check (comes from ModuleInfo.namespace)
|
|
431
|
+
* @returns true if moduleInfo is an external module, false otherwise
|
|
432
|
+
*/
|
|
433
|
+
function isExternalModule(namespace) {
|
|
434
|
+
return !(namespace === exports.LIGHTNING_NS ||
|
|
435
|
+
namespace === exports.FORCE_NS ||
|
|
436
|
+
namespace === exports.ONE_NS);
|
|
437
|
+
}
|
|
438
|
+
exports.isExternalModule = isExternalModule;
|
|
439
|
+
/**
|
|
440
|
+
* Helper function to collect all variables declared within a getter method.
|
|
441
|
+
* @param getterMethodPath the babel path object of the getter method.
|
|
442
|
+
* @returns an array of variable names that were declared in the getter method.
|
|
443
|
+
*/
|
|
444
|
+
function getVariablesDeclaredInGetter(getterMethodPath) {
|
|
445
|
+
const variables = [];
|
|
446
|
+
const getterMethodNode = getterMethodPath.node;
|
|
447
|
+
const declarations = getterMethodNode.body.body.filter((dec) => dec.type === 'VariableDeclaration');
|
|
448
|
+
declarations.forEach((dec) => {
|
|
449
|
+
dec.declarations.forEach((declarator) => {
|
|
450
|
+
variables.push(declarator.id.name);
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
return variables;
|
|
454
|
+
}
|
|
455
|
+
exports.getVariablesDeclaredInGetter = getVariablesDeclaredInGetter;
|
|
456
|
+
/**
|
|
457
|
+
* Helper to get the name of a method
|
|
458
|
+
* @param node The method node
|
|
459
|
+
* @returns the name of the node
|
|
460
|
+
*/
|
|
461
|
+
function getClassMethodName(node) {
|
|
462
|
+
return getFromIdentifierOrStringLiteral(node.node.key);
|
|
463
|
+
}
|
|
464
|
+
exports.getClassMethodName = getClassMethodName;
|
|
465
|
+
/**
|
|
466
|
+
* Check whether a property is used either directly or indirectly
|
|
467
|
+
* @param prop The prop details
|
|
468
|
+
* @returns if it is used
|
|
469
|
+
*/
|
|
470
|
+
function isPropertyUsed(prop) {
|
|
471
|
+
return prop?.usedInPriming || false;
|
|
472
|
+
}
|
|
473
|
+
exports.isPropertyUsed = isPropertyUsed;
|
|
474
|
+
/**
|
|
475
|
+
* High level wrapper to parse getter info from a babel node before checking if it is used
|
|
476
|
+
* @param getter The getter node
|
|
477
|
+
* @param properties Metadata about class properties
|
|
478
|
+
* @returns if it is used directly
|
|
479
|
+
*/
|
|
480
|
+
function isGetterNodeUsed(getter, properties) {
|
|
481
|
+
const getterName = getClassMethodName(getter);
|
|
482
|
+
const getterMeta = properties.get(getterName);
|
|
483
|
+
return isPropertyUsed(getterMeta);
|
|
484
|
+
}
|
|
485
|
+
exports.isGetterNodeUsed = isGetterNodeUsed;
|
|
486
|
+
/**
|
|
487
|
+
* High level wrapper to parse prop info from a babel node before checking if it is used
|
|
488
|
+
* @param prop The prop babel node
|
|
489
|
+
* @param properties Metadata about class properties
|
|
490
|
+
* @returns if it is used directly
|
|
491
|
+
*/
|
|
492
|
+
function isPropertyNodeUsed(prop, properties) {
|
|
493
|
+
if (prop.node.key.type === 'Identifier' || prop.node.key.type === 'StringLiteral') {
|
|
494
|
+
const propName = getFromIdentifierOrStringLiteral(prop.node.key);
|
|
495
|
+
const meta = properties.get(propName);
|
|
496
|
+
return isPropertyUsed(meta);
|
|
497
|
+
}
|
|
498
|
+
else {
|
|
499
|
+
// expression props are not things we can process
|
|
500
|
+
return false;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
exports.isPropertyNodeUsed = isPropertyNodeUsed;
|
|
504
|
+
/**
|
|
505
|
+
* @author xiaoxugu
|
|
506
|
+
* Helper function to collect all variables declared as alias of this.
|
|
507
|
+
* eg. const self = this, const that = this.
|
|
508
|
+
* @param getterMethodPath the babel path object of the getter method.
|
|
509
|
+
* @returns a {Set<string>} of variable names that were declared as alias of 'this'.
|
|
510
|
+
*/
|
|
511
|
+
function getThisAliasDeclaredInGetter(getterMethodPath) {
|
|
512
|
+
const variables = new Set();
|
|
513
|
+
const getterMethodNode = getterMethodPath.node;
|
|
514
|
+
const declarations = getterMethodNode.body.body.filter((dec) => dec.type === 'VariableDeclaration');
|
|
515
|
+
declarations.forEach((dec) => {
|
|
516
|
+
dec.declarations.forEach((declarator) => {
|
|
517
|
+
if (isExpressionThisOrAlias(variables, declarator.init)) {
|
|
518
|
+
variables.add(declarator.id.name);
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
});
|
|
522
|
+
return variables;
|
|
523
|
+
}
|
|
524
|
+
exports.getThisAliasDeclaredInGetter = getThisAliasDeclaredInGetter;
|
|
525
|
+
/**
|
|
526
|
+
* @author xiaoxugu
|
|
527
|
+
* Determines whether the passed in {Expression} is a `this` or whether it is an equivalent alias to `this`
|
|
528
|
+
* @param {Set<string>} aliases a Set<string> of variables that were assigned `this`
|
|
529
|
+
* @param {Expression | null | undefined} expr the Expression whose type is being evaluated
|
|
530
|
+
* @returns {boolean} returns true is the Expression is a `ThisExpression` or an alias to one
|
|
531
|
+
*/
|
|
532
|
+
function isExpressionThisOrAlias(aliases, expr) {
|
|
533
|
+
if (expr) {
|
|
534
|
+
return (expr.type === 'ThisExpression' ||
|
|
535
|
+
(expr.type === 'Identifier' && aliases.has(expr.name)));
|
|
536
|
+
}
|
|
537
|
+
return false;
|
|
538
|
+
}
|
|
539
|
+
exports.isExpressionThisOrAlias = isExpressionThisOrAlias;
|
|
540
|
+
/**
|
|
541
|
+
* Function to check if the id we are referecing is either declared as a class property, import reference or module variale
|
|
542
|
+
* @param astContext the ast context
|
|
543
|
+
* @param declaredGetterVars a collection of variables declared within the getter
|
|
544
|
+
* @param id the id of the member we are referencing.
|
|
545
|
+
*/
|
|
546
|
+
function isDeclaredInAst(astContext, declaredGetterVars, id) {
|
|
547
|
+
const { classProperties, importDeclarations, moduleVariables } = astContext;
|
|
548
|
+
return (classProperties.find((prop) => prop.classPropId === id) !== undefined ||
|
|
549
|
+
importDeclarations.has(id) ||
|
|
550
|
+
moduleVariables.find((varId) => varId === id) !== undefined ||
|
|
551
|
+
(declaredGetterVars || []).find((varId) => varId === id) !== undefined);
|
|
552
|
+
}
|
|
553
|
+
exports.isDeclaredInAst = isDeclaredInAst;
|
|
554
|
+
//# sourceMappingURL=utils.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@komaci/common-shared",
|
|
3
|
+
"version": "240.1.3",
|
|
4
|
+
"description": "Assets that are shared across Komaci commonjs packages",
|
|
5
|
+
"homepage": "https://komaci.dev/",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/salesforce/komaci.git",
|
|
9
|
+
"directory": "packages/@komaci/common-shared"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/salesforce/komaci/issues"
|
|
13
|
+
},
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"type": "commonjs",
|
|
19
|
+
"types": "build/index.d.ts",
|
|
20
|
+
"main": "build/index.js",
|
|
21
|
+
"module": "build/index.js",
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc -b"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"build/**/*.js",
|
|
27
|
+
"build/**/*.d.ts",
|
|
28
|
+
"build/internal-namespaces.json"
|
|
29
|
+
],
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@komaci/types": "240.1.3"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@babel/core": "^7.9.0",
|
|
35
|
+
"@babel/generator": "^7.9.0"
|
|
36
|
+
}
|
|
37
|
+
}
|