Skip to content

JS: Some more improvements to d.ts file analysis #9457

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,6 @@ go/main
# node_modules folders except in the JS test suite
node_modules/
!/javascript/ql/test/**/node_modules/

# Temporary folders for working with generated models
.model-temp
1 change: 1 addition & 0 deletions javascript/extractor/lib/typescript/src/type_table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1068,6 +1068,7 @@ export class TypeTable {
let superType = this.typeChecker.getTypeFromTypeNode(typeExpr);
if (superType == null) continue;
let baseTypeSymbol = superType.symbol;
baseTypeSymbol = (baseTypeSymbol as any)?.type?.symbol ?? baseTypeSymbol;
if (baseTypeSymbol == null) continue;
let baseId = this.getSymbolId(baseTypeSymbol);
// Note: take care not to perform a recursive call between the two `push` calls.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2191,6 +2191,7 @@ public Label visit(ExternalModuleDeclaration nd, Context c) {
visitAll(nd.getBody(), key);
contextManager.leaveContainer();
scopeManager.leaveScope();
emitNodeSymbol(nd, key);
return key;
}

Expand Down
6 changes: 3 additions & 3 deletions javascript/extractor/src/com/semmle/js/extractor/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public class Main {
* A version identifier that should be updated every time the extractor changes in such a way that
* it may produce different tuples for the same file under the same {@link ExtractorConfig}.
*/
public static final String EXTRACTOR_VERSION = "2022-05-24";
public static final String EXTRACTOR_VERSION = "2022-06-08";

public static final Pattern NEWLINE = Pattern.compile("\n");

Expand Down Expand Up @@ -153,7 +153,7 @@ public void run(String[] args) {
ensureFileIsExtracted(file, ap);
}
}

TypeScriptParser tsParser = extractorState.getTypeScriptParser();
tsParser.setTypescriptRam(extractorConfig.getTypeScriptRam());
if (containsTypeScriptFiles()) {
Expand Down Expand Up @@ -460,7 +460,7 @@ private static TypeScriptMode getTypeScriptMode(ArgsParser ap) {
if (ap.has(P_TYPESCRIPT)) return TypeScriptMode.BASIC;
return TypeScriptMode.NONE;
}

private Path inferSourceRoot(ArgsParser ap) {
List<File> files = getFilesArg(ap);
Path sourceRoot = files.iterator().next().toPath().toAbsolutePath().getParent();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
import java.util.List;

/** A statement of form <code>declare module "X" {...}</code>. */
public class ExternalModuleDeclaration extends Statement {
public class ExternalModuleDeclaration extends Statement implements INodeWithSymbol {
private final Literal name;
private final List<Statement> body;
private int symbol = -1;

public ExternalModuleDeclaration(SourceLocation loc, Literal name, List<Statement> body) {
super("ExternalModuleDeclaration", loc);
Expand All @@ -29,4 +30,14 @@ public Literal getName() {
public List<Statement> getBody() {
return body;
}

@Override
public int getSymbol() {
return this.symbol;
}

@Override
public void setSymbol(int symbol) {
this.symbol = symbol;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ private Node convertNodeUntyped(JsonObject node, String defaultKind) throws Pars
return convertTryStatement(node, loc);
case "TupleType":
return convertTupleType(node, loc);
case "NamedTupleMember":
case "NamedTupleMember":
return convertNamedTupleMember(node, loc);
case "TypeAliasDeclaration":
return convertTypeAliasDeclaration(node, loc);
Expand Down Expand Up @@ -1710,7 +1710,9 @@ private Node convertNamespaceDeclaration(JsonObject node, SourceLocation loc) th
}
if (nameNode instanceof Literal) {
// Declaration of form: declare module "X" {...}
return new ExternalModuleDeclaration(loc, (Literal) nameNode, body);
ExternalModuleDeclaration decl = new ExternalModuleDeclaration(loc, (Literal) nameNode, body);
attachSymbolInformation(decl, node);
return decl;
}
if (hasFlag(node, "GlobalAugmentation")) {
// Declaration of form: declare global {...}
Expand Down
29 changes: 29 additions & 0 deletions javascript/ql/lib/semmle/javascript/NPM.qll
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,35 @@ class PackageJson extends JsonObject {
Module getMainModule() {
result = min(Module m, int prio | m.getFile() = resolveMainModule(this, prio) | m order by prio)
}

/**
* Gets the `types` or `typings` field of this package.
*/
string getTypings() { result = this.getPropStringValue(["types", "typings"]) }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is also the "types" field under "exports": https://devblogs.microsoft.com/typescript/announcing-typescript-4-7-rc/#package-json-exports-imports-and-self-referencing

(Might not be that relevant, so you can probably skip it).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new exports/imports fields are too complex to handle in this PR


/**
* Gets the file containing the typings of this package, which can either be from the `types` or
* `typings` field, or derived from the `main` or `module` fields.
*/
File getTypingsFile() {
result =
TypingsModulePathString::of(this).resolve(this.getFile().getParentContainer()).getContainer()
or
not exists(TypingsModulePathString::of(this)) and
exists(File mainFile |
mainFile = this.getMainModule().getFile() and
result =
mainFile
.getParentContainer()
.getFile(mainFile.getStem().regexpReplaceAll("\\.d$", "") + ".d.ts")
)
}

/**
* Gets the module containing the typings of this package, which can either be from the `types` or
* `typings` field, or derived from the `main` or `module` fields.
*/
Module getTypingsModule() { result.getFile() = this.getTypingsFile() }
}

/** DEPRECATED: Alias for PackageJson */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,29 @@ private class FilesPath extends PathExpr, @json_string {
private module FilesPath {
FilesPath of(PackageJson pkg) { result.getPackageJson() = pkg }
}

/**
* A JSON string in a `package.json` file specifying the path of the
* TypeScript typings entry point.
*/
class TypingsModulePathString extends PathString {
PackageJson pkg;

TypingsModulePathString() {
this = pkg.getTypings()
or
not exists(pkg.getTypings()) and
this = pkg.getMain().regexpReplaceAll("\\.[mc]?js$", ".d.ts")
}

/** Gets the `package.json` file containing this path. */
PackageJson getPackageJson() { result = pkg }

override Folder getARootFolder() { result = pkg.getFile().getParentContainer() }
}

/** Companion module to the `TypingsModulePathString` class. */
module TypingsModulePathString {
/** Get the typings path for the given `package.json` file. */
TypingsModulePathString of(PackageJson pkg) { result.getPackageJson() = pkg }
}
54 changes: 27 additions & 27 deletions javascript/ql/lib/semmlecode.javascript.dbscheme
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,33 @@
/** Files and folders **/

@location = @location_default;

locations_default(unique int id: @location_default,
int file: @file ref,
int beginLine: int ref,
int beginColumn: int ref,
int endLine: int ref,
int endColumn: int ref
);

@sourceline = @locatable;

numlines(int element_id: @sourceline ref,
int num_lines: int ref,
int num_code: int ref,
int num_comment: int ref
);

files(unique int id: @file,
varchar(900) name: string ref);

folders(unique int id: @folder,
varchar(900) name: string ref);


@container = @folder | @file ;


containerparent(int parent: @container ref,
unique int child: @container ref);

Expand All @@ -39,14 +39,14 @@ duplicateCode(
unique int id : @duplication,
varchar(900) relativePath : string ref,
int equivClass : int ref);

similarCode(
unique int id : @similarity,
varchar(900) relativePath : string ref,
int equivClass : int ref);

@duplication_or_similarity = @duplication | @similarity;

tokens(
int id : @duplication_or_similarity ref,
int offset : int ref,
Expand All @@ -63,9 +63,9 @@ externalData(
int column: int ref,
varchar(900) value : string ref
);

snapshotDate(unique date snapshotDate : date ref);

sourceLocationPrefix(varchar(900) prefix : string ref);

/** Version control data **/
Expand All @@ -77,18 +77,18 @@ svnentries(
date revisionDate : date ref,
int changeSize : int ref
);

svnaffectedfiles(
int id : @svnentry ref,
int file : @file ref,
varchar(500) action : string ref
);

svnentrymsg(
int id : @svnentry ref,
varchar(500) message : string ref
);

svnchurn(
int commit : @svnentry ref,
int file : @file ref,
Expand Down Expand Up @@ -134,15 +134,15 @@ xml_element_parent_expression(

// statements
#keyset[parent, idx]
stmts (unique int id: @stmt,
stmts (unique int id: @stmt,
int kind: int ref,
int parent: @stmt_parent ref,
int parent: @stmt_parent ref,
int idx: int ref,
varchar(900) tostring: string ref);

stmt_containers (unique int stmt: @stmt ref,
int container: @stmt_container ref);

jump_targets (unique int jump: @stmt ref,
int target: @stmt ref);

Expand Down Expand Up @@ -217,7 +217,7 @@ exprs (unique int id: @expr,
literals (varchar(900) value: string ref,
varchar(900) raw: string ref,
unique int expr: @expr_or_type ref);

enclosing_stmt (unique int expr: @expr_or_type ref,
int stmt: @stmt ref);

Expand Down Expand Up @@ -445,7 +445,7 @@ case @scope.kind of

scopenodes (unique int node: @ast_node ref,
int scope: @scope ref);

scopenesting (unique int inner: @scope ref,
int outer: @scope ref);

Expand Down Expand Up @@ -667,7 +667,7 @@ has_asserts_keyword(int node: @predicate_typeexpr ref);

@typed_ast_node = @expr | @typeexpr | @function;
ast_node_type(
unique int node: @typed_ast_node ref,
unique int node: @typed_ast_node ref,
int typ: @type ref);

declared_function_signature(
Expand Down Expand Up @@ -713,7 +713,7 @@ case @symbol.kind of
;

@type_with_symbol = @type_reference | @typevariable_type | @typeof_type | @unique_symbol_type;
@ast_node_with_symbol = @type_definition | @namespace_definition | @toplevel | @typeaccess | @namespace_access | @var_decl | @function | @invokeexpr | @import_declaration | @external_module_reference;
@ast_node_with_symbol = @type_definition | @namespace_definition | @toplevel | @typeaccess | @namespace_access | @var_decl | @function | @invokeexpr | @import_declaration | @external_module_reference | @external_module_declaration;

ast_node_symbol(
unique int node: @ast_node_with_symbol ref,
Expand Down Expand Up @@ -846,15 +846,15 @@ js_parse_errors (unique int id: @js_parse_error,
int toplevel: @toplevel ref,
varchar(900) message: string ref,
varchar(900) line: string ref);

// regular expressions
#keyset[parent, idx]
regexpterm (unique int id: @regexpterm,
int kind: int ref,
int parent: @regexpparent ref,
int idx: int ref,
varchar(900) tostring: string ref);

@regexpparent = @regexpterm | @regexp_literal | @string_literal | @add_expr;

case @regexpterm.kind of
Expand Down Expand Up @@ -972,7 +972,7 @@ case @json_value.kind of
// locations
@ast_node = @toplevel | @stmt | @expr | @property | @typeexpr;

@locatable = @file
@locatable = @file
| @ast_node
| @comment
| @line
Expand Down
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy