-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Js Scope - Coding Logic (#216)
Adds the programming logic that detects tokens and functions and maps them to the instrumented package, ultimately generating token and function metrics. Adds unit testing for all things Js Scope. Reworks substitution logic to be able to take in arrays and objects. `createSourceFileFromText` function for unit testing ease-of-use Fixes significant bug in `getPackageData` that was preventing collection under certain circumstances. --------- Co-authored-by: Francine Lucca <francinelucca@users.noreply.github.com> Co-authored-by: Joe Harvey <jdharvey-ibm@users.noreply.github.com>
- Loading branch information
1 parent
50650ab
commit ed22e35
Showing
65 changed files
with
3,318 additions
and
478 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* Copyright IBM Corp. 2023, 2024 | ||
* | ||
* This source code is licensed under the Apache-2.0 license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
import { Substitution } from './substitution.js' | ||
|
||
/** | ||
* Substitutes values in the raw input based on the provided allowed values. | ||
* | ||
* @param raw - An array of values. | ||
* @param allowedValues - The values to leave untouched. | ||
* @returns The raw array with all non-allowed values replaced with anonymized versions of their | ||
* values. | ||
*/ | ||
export function substituteArray(raw: unknown[], allowedValues: unknown[]): unknown[] { | ||
const subs = new Substitution() | ||
|
||
return raw.map((value) => { | ||
// Value is a string that's not safe | ||
if (typeof value === 'string' && !allowedValues.includes(value)) { | ||
return subs.put(value) | ||
} | ||
|
||
// Value is an object that's not null and not safe | ||
if (typeof value === 'object' && value !== null && !allowedValues.includes(value)) { | ||
return subs.put(value) | ||
} | ||
|
||
return value | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* | ||
* Copyright IBM Corp. 2024, 2024 | ||
* | ||
* This source code is licensed under the Apache-2.0 license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
import { TypedKeyMap } from './typed-key-map.js' | ||
|
||
const subs = new TypedKeyMap() | ||
let curSub = 1 | ||
|
||
function nextSub() { | ||
return `[redacted${curSub++}]` | ||
} | ||
|
||
/** | ||
* Encapsulates logic that tracks substitution values across a telemetry run. | ||
*/ | ||
export class Substitution { | ||
/** | ||
* Puts a given value into the substitution map and returns its substituted/anonymized equivalent. | ||
* | ||
* @param key - The value to substitute. | ||
* @returns An anonymized representation of the key (using substitution). | ||
*/ | ||
public put(key: unknown): string { | ||
if (subs.has(key)) { | ||
return subs.get(key) | ||
} | ||
|
||
const next = nextSub() | ||
subs.set(key, next) | ||
|
||
return next | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* | ||
* Copyright IBM Corp. 2024, 2024 | ||
* | ||
* This source code is licensed under the Apache-2.0 license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
import * as ts from 'typescript' | ||
|
||
import type { Logger } from '../../core/log/logger.js' | ||
import { ComplexValue } from './complex-value.js' | ||
import { getNodeValueHandler } from './node-value-handler-map.js' | ||
|
||
type ExpressionContainingNode = | ||
| ts.PropertyAccessExpression | ||
| ts.ElementAccessExpression | ||
| ts.CallExpression | ||
|
||
/** | ||
* Constructs the access path to a given expression-containing node | ||
* (PropertyAccessExpression, ElementAccessExpression or CallExpression) | ||
* by reading the node's content recursively. | ||
* | ||
* @param node - TS node to retrieve access path for. | ||
* @param sourceFile - Root AST node. | ||
* @param logger - A logger instance. | ||
* @returns Access path to node represented as string array (chunks). | ||
*/ | ||
export default function getAccessPath( | ||
node: ExpressionContainingNode, | ||
sourceFile: ts.SourceFile, | ||
logger: Logger | ||
) { | ||
return computeAccessPath(node, sourceFile, [], true, logger) | ||
} | ||
|
||
/** | ||
* Constructs the access path to a given node by reading the node's content recursively. | ||
* | ||
* @param node - TS node to retrieve access path for. | ||
* @param sourceFile - Root AST node. | ||
* @param currAccessPath - For internal use only, tracks current constructed access path. | ||
* @param topLevel - For internal use only, tracks top level function call. | ||
* @param logger - A logger instance. | ||
* @returns Access path to node represented as string array (chunks). | ||
*/ | ||
function computeAccessPath( | ||
node: ts.Node, | ||
sourceFile: ts.SourceFile, | ||
currAccessPath: Array<string | ComplexValue>, | ||
topLevel: boolean, | ||
logger: Logger | ||
): Array<string | ComplexValue> { | ||
switch (node.kind) { | ||
case ts.SyntaxKind.Identifier: | ||
return [...currAccessPath, (node as ts.Identifier).escapedText.toString()] | ||
case ts.SyntaxKind.PropertyAccessExpression: | ||
currAccessPath.push((node as ts.PropertyAccessExpression).name.escapedText.toString()) | ||
break | ||
case ts.SyntaxKind.ElementAccessExpression: { | ||
const argumentExpression = (node as ts.ElementAccessExpression).argumentExpression | ||
const data = getNodeValueHandler(argumentExpression.kind, sourceFile, logger).getData( | ||
argumentExpression | ||
) | ||
if (data !== undefined && data !== null) { | ||
currAccessPath.push(data instanceof ComplexValue ? data : data.toString()) | ||
} | ||
break | ||
} | ||
} | ||
|
||
let accessPath = currAccessPath | ||
|
||
if ('expression' in node) { | ||
accessPath = computeAccessPath( | ||
node.expression as ts.Node, | ||
sourceFile, | ||
currAccessPath, | ||
false, | ||
logger | ||
) | ||
} | ||
|
||
return topLevel ? accessPath.reverse() : accessPath | ||
} |
29 changes: 0 additions & 29 deletions
29
src/main/scopes/js/import-matchers/functions/js-function-all-import-matcher.ts
This file was deleted.
Oops, something went wrong.
27 changes: 0 additions & 27 deletions
27
src/main/scopes/js/import-matchers/functions/js-function-named-import-matcher.ts
This file was deleted.
Oops, something went wrong.
28 changes: 0 additions & 28 deletions
28
src/main/scopes/js/import-matchers/functions/js-function-renamed-import-matcher.ts
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.