зеркало из https://github.com/github/codeql.git
Merge pull request #2896 from asger-semmle/typescript-3.8
TS: Support Typescript 3.8
This commit is contained in:
Коммит
160fc48803
|
@ -2,6 +2,8 @@
|
|||
|
||||
## General improvements
|
||||
|
||||
* TypeScript 3.8 is now supported.
|
||||
|
||||
* Alert suppression can now be done with single-line block comments (`/* ... */`) as well as line comments (`// ...`).
|
||||
|
||||
* Imports with the `.js` extension can now be resolved to a TypeScript file,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "typescript-parser-wrapper",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"typescript": "3.7.5"
|
||||
"typescript": "3.8.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc --project tsconfig.json",
|
||||
|
|
|
@ -225,9 +225,9 @@ tsutils@^2.12.1:
|
|||
dependencies:
|
||||
tslib "^1.8.1"
|
||||
|
||||
typescript@3.7.5:
|
||||
version "3.7.5"
|
||||
resolved "typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae"
|
||||
typescript@3.8.2:
|
||||
version "3.8.2"
|
||||
resolved typescript-3.8.2.tgz#91d6868aaead7da74f493c553aeff76c0c0b1d5a
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
|
|
|
@ -15,13 +15,21 @@ public class ExportNamedDeclaration extends ExportDeclaration {
|
|||
private final Statement declaration;
|
||||
private final List<ExportSpecifier> specifiers;
|
||||
private final Literal source;
|
||||
private final boolean hasTypeKeyword;
|
||||
|
||||
public ExportNamedDeclaration(
|
||||
SourceLocation loc, Statement declaration, List<ExportSpecifier> specifiers, Literal source) {
|
||||
this(loc, declaration, specifiers, source, false);
|
||||
}
|
||||
|
||||
public ExportNamedDeclaration(
|
||||
SourceLocation loc, Statement declaration, List<ExportSpecifier> specifiers, Literal source,
|
||||
boolean hasTypeKeyword) {
|
||||
super("ExportNamedDeclaration", loc);
|
||||
this.declaration = declaration;
|
||||
this.specifiers = specifiers;
|
||||
this.source = source;
|
||||
this.hasTypeKeyword = hasTypeKeyword;
|
||||
}
|
||||
|
||||
public Statement getDeclaration() {
|
||||
|
@ -48,4 +56,9 @@ public class ExportNamedDeclaration extends ExportDeclaration {
|
|||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
|
||||
/** Returns true if this is an <code>export type</code> declaration. */
|
||||
public boolean hasTypeKeyword() {
|
||||
return hasTypeKeyword;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package com.semmle.js.ast;
|
||||
|
||||
import com.semmle.ts.ast.INodeWithSymbol;
|
||||
import java.util.List;
|
||||
|
||||
import com.semmle.ts.ast.INodeWithSymbol;
|
||||
|
||||
/**
|
||||
* An import declaration, which can be of one of the following forms:
|
||||
*
|
||||
|
@ -24,10 +25,17 @@ public class ImportDeclaration extends Statement implements INodeWithSymbol {
|
|||
|
||||
private int symbol = -1;
|
||||
|
||||
private boolean hasTypeKeyword;
|
||||
|
||||
public ImportDeclaration(SourceLocation loc, List<ImportSpecifier> specifiers, Literal source) {
|
||||
this(loc, specifiers, source, false);
|
||||
}
|
||||
|
||||
public ImportDeclaration(SourceLocation loc, List<ImportSpecifier> specifiers, Literal source, boolean hasTypeKeyword) {
|
||||
super("ImportDeclaration", loc);
|
||||
this.specifiers = specifiers;
|
||||
this.source = source;
|
||||
this.hasTypeKeyword = hasTypeKeyword;
|
||||
}
|
||||
|
||||
public Literal getSource() {
|
||||
|
@ -52,4 +60,9 @@ public class ImportDeclaration extends Statement implements INodeWithSymbol {
|
|||
public void setSymbol(int symbol) {
|
||||
this.symbol = symbol;
|
||||
}
|
||||
|
||||
/** Returns true if this is an <code>import type</code> declaration. */
|
||||
public boolean hasTypeKeyword() {
|
||||
return hasTypeKeyword;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -250,6 +250,22 @@ public class ASTExtractor {
|
|||
/** An identifier that declares a variable and a namespace. */
|
||||
varAndNamespaceDecl,
|
||||
|
||||
/**
|
||||
* An identifier that occurs in a type-only import.
|
||||
*
|
||||
* These may declare a type and/or a namespace, but for compatibility with our AST,
|
||||
* must be emitted as a VarDecl (with no variable binding).
|
||||
*/
|
||||
typeOnlyImport,
|
||||
|
||||
/**
|
||||
* An identifier that occurs in a type-only export.
|
||||
*
|
||||
* These may refer to a type and/or a namespace, but for compatibility with our AST,
|
||||
* must be emitted as an ExportVarAccess (with no variable binding).
|
||||
*/
|
||||
typeOnlyExport,
|
||||
|
||||
/** An identifier that declares a variable, type, and namepsace. */
|
||||
varAndTypeAndNamespaceDecl,
|
||||
|
||||
|
@ -278,7 +294,8 @@ public class ASTExtractor {
|
|||
* True if this occurs as part of a type annotation, i.e. it is {@link #typeBind} or {@link
|
||||
* #typeDecl}, {@link #typeLabel}, {@link #varInTypeBind}, or {@link #namespaceBind}.
|
||||
*
|
||||
* <p>Does not hold for {@link #varAndTypeDecl}.
|
||||
* <p>Does not hold for {@link #varAndTypeDecl}, {@link #typeOnlyImport}, or @{link {@link #typeOnlyExport}
|
||||
* as these do not occur in type annotations.
|
||||
*/
|
||||
public boolean isInsideType() {
|
||||
return this == typeBind
|
||||
|
@ -488,6 +505,14 @@ public class ASTExtractor {
|
|||
addVariableBinding("decl", key, name);
|
||||
addNamespaceBinding("namespacedecl", key, name);
|
||||
break;
|
||||
case typeOnlyImport:
|
||||
addTypeBinding("typedecl", key, name);
|
||||
addNamespaceBinding("namespacedecl", key, name);
|
||||
break;
|
||||
case typeOnlyExport:
|
||||
addTypeBinding("typebind", key, name);
|
||||
addNamespaceBinding("namespacebind", key, name);
|
||||
break;
|
||||
case varAndTypeAndNamespaceDecl:
|
||||
addVariableBinding("decl", key, name);
|
||||
addTypeBinding("typedecl", key, name);
|
||||
|
@ -1538,7 +1563,14 @@ public class ASTExtractor {
|
|||
Label lbl = super.visit(nd, c);
|
||||
visit(nd.getDeclaration(), lbl, -1);
|
||||
visit(nd.getSource(), lbl, -2);
|
||||
visitAll(nd.getSpecifiers(), lbl, nd.hasSource() ? IdContext.label : IdContext.export, 0);
|
||||
IdContext childContext =
|
||||
nd.hasSource() ? IdContext.label :
|
||||
nd.hasTypeKeyword() ? IdContext.typeOnlyExport :
|
||||
IdContext.export;
|
||||
visitAll(nd.getSpecifiers(), lbl, childContext, 0);
|
||||
if (nd.hasTypeKeyword()) {
|
||||
trapwriter.addTuple("hasTypeKeyword", lbl);
|
||||
}
|
||||
return lbl;
|
||||
}
|
||||
|
||||
|
@ -1554,8 +1586,12 @@ public class ASTExtractor {
|
|||
public Label visit(ImportDeclaration nd, Context c) {
|
||||
Label lbl = super.visit(nd, c);
|
||||
visit(nd.getSource(), lbl, -1);
|
||||
visitAll(nd.getSpecifiers(), lbl);
|
||||
IdContext childContext = nd.hasTypeKeyword() ? IdContext.typeOnlyImport : IdContext.varAndTypeAndNamespaceDecl;
|
||||
visitAll(nd.getSpecifiers(), lbl, childContext, 0);
|
||||
emitNodeSymbol(nd, lbl);
|
||||
if (nd.hasTypeKeyword()) {
|
||||
trapwriter.addTuple("hasTypeKeyword", lbl);
|
||||
}
|
||||
return lbl;
|
||||
}
|
||||
|
||||
|
@ -1563,7 +1599,7 @@ public class ASTExtractor {
|
|||
public Label visit(ImportSpecifier nd, Context c) {
|
||||
Label lbl = super.visit(nd, c);
|
||||
visit(nd.getImported(), lbl, 0, IdContext.label);
|
||||
visit(nd.getLocal(), lbl, 1, IdContext.varAndTypeAndNamespaceDecl);
|
||||
visit(nd.getLocal(), lbl, 1, c.idcontext);
|
||||
return lbl;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package com.semmle.js.extractor;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.semmle.jcorn.TokenType;
|
||||
import com.semmle.jcorn.jsx.JSXParser;
|
||||
import com.semmle.js.ast.AssignmentExpression;
|
||||
|
@ -29,9 +33,6 @@ import com.semmle.ts.ast.DecoratorList;
|
|||
import com.semmle.ts.ast.ExpressionWithTypeArguments;
|
||||
import com.semmle.ts.ast.TypeAssertion;
|
||||
import com.semmle.util.exception.CatastrophicError;
|
||||
import java.util.EnumMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/** Map from SpiderMonkey expression types to the numeric kinds used in the DB scheme. */
|
||||
public class ExprKinds {
|
||||
|
@ -154,6 +155,8 @@ public class ExprKinds {
|
|||
idKinds.put(IdContext.namespaceDecl, 78);
|
||||
idKinds.put(IdContext.varAndNamespaceDecl, 78);
|
||||
idKinds.put(IdContext.varAndTypeAndNamespaceDecl, 78);
|
||||
idKinds.put(IdContext.typeOnlyImport, 78);
|
||||
idKinds.put(IdContext.typeOnlyExport, 103);
|
||||
idKinds.put(IdContext.varBind, 79);
|
||||
idKinds.put(IdContext.export, 103);
|
||||
idKinds.put(IdContext.exportBase, 103);
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
package com.semmle.js.parser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonNull;
|
||||
|
@ -34,6 +42,7 @@ import com.semmle.js.ast.ExportAllDeclaration;
|
|||
import com.semmle.js.ast.ExportDeclaration;
|
||||
import com.semmle.js.ast.ExportDefaultDeclaration;
|
||||
import com.semmle.js.ast.ExportNamedDeclaration;
|
||||
import com.semmle.js.ast.ExportNamespaceSpecifier;
|
||||
import com.semmle.js.ast.ExportSpecifier;
|
||||
import com.semmle.js.ast.Expression;
|
||||
import com.semmle.js.ast.ExpressionStatement;
|
||||
|
@ -144,13 +153,6 @@ import com.semmle.ts.ast.UnaryTypeExpr;
|
|||
import com.semmle.ts.ast.UnionTypeExpr;
|
||||
import com.semmle.util.collections.CollectionUtil;
|
||||
import com.semmle.util.data.IntList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Utility class for converting a <a
|
||||
|
@ -334,7 +336,11 @@ public class TypeScriptASTConverter {
|
|||
private Node convertNodeUntyped(JsonObject node, String defaultKind) throws ParseError {
|
||||
String kind = getKind(node);
|
||||
if (kind == null) kind = defaultKind;
|
||||
if (kind == null) kind = "Identifier";
|
||||
if (kind == null) {
|
||||
// Identifiers and PrivateIdentifiers do not have a "kind" property like other nodes.
|
||||
// Since we encode identifiers and private identifiers the same, default to Identifier.
|
||||
kind = "Identifier";
|
||||
}
|
||||
SourceLocation loc = getSourceLocation(node);
|
||||
switch (kind) {
|
||||
case "AnyKeyword":
|
||||
|
@ -441,6 +447,7 @@ public class TypeScriptASTConverter {
|
|||
case "FunctionType":
|
||||
return convertFunctionType(node, loc);
|
||||
case "Identifier":
|
||||
case "PrivateIdentifier":
|
||||
return convertIdentifier(node, loc);
|
||||
case "IfStatement":
|
||||
return convertIfStatement(node, loc);
|
||||
|
@ -507,6 +514,8 @@ public class TypeScriptASTConverter {
|
|||
return convertNamespaceDeclaration(node, loc);
|
||||
case "ModuleBlock":
|
||||
return convertModuleBlock(node, loc);
|
||||
case "NamespaceExport":
|
||||
return convertNamespaceExport(node, loc);
|
||||
case "NamespaceExportDeclaration":
|
||||
return convertNamespaceExportDeclaration(node, loc);
|
||||
case "NamespaceImport":
|
||||
|
@ -1170,11 +1179,12 @@ public class TypeScriptASTConverter {
|
|||
private Node convertExportDeclaration(JsonObject node, SourceLocation loc) throws ParseError {
|
||||
Literal source = tryConvertChild(node, "moduleSpecifier", Literal.class);
|
||||
if (hasChild(node, "exportClause")) {
|
||||
return new ExportNamedDeclaration(
|
||||
loc,
|
||||
null,
|
||||
convertChildren(node.get("exportClause").getAsJsonObject(), "elements"),
|
||||
source);
|
||||
boolean hasTypeKeyword = node.get("isTypeOnly").getAsBoolean();
|
||||
List<ExportSpecifier> specifiers =
|
||||
hasKind(node.get("exportClause"), "NamespaceExport")
|
||||
? Collections.singletonList(convertChild(node, "exportClause"))
|
||||
: convertChildren(node.get("exportClause").getAsJsonObject(), "elements");
|
||||
return new ExportNamedDeclaration(loc, null, specifiers, source, hasTypeKeyword);
|
||||
} else {
|
||||
return new ExportAllDeclaration(loc, source);
|
||||
}
|
||||
|
@ -1187,6 +1197,11 @@ public class TypeScriptASTConverter {
|
|||
convertChild(node, "name"));
|
||||
}
|
||||
|
||||
private Node convertNamespaceExport(JsonObject node, SourceLocation loc) throws ParseError {
|
||||
// Convert the "* as ns" from an export declaration.
|
||||
return new ExportNamespaceSpecifier(loc, convertChild(node, "name"));
|
||||
}
|
||||
|
||||
private Node convertExpressionStatement(JsonObject node, SourceLocation loc) throws ParseError {
|
||||
Expression expression = convertChild(node, "expression");
|
||||
return new ExpressionStatement(loc, expression);
|
||||
|
@ -1354,6 +1369,7 @@ public class TypeScriptASTConverter {
|
|||
private Node convertImportDeclaration(JsonObject node, SourceLocation loc) throws ParseError {
|
||||
Literal src = tryConvertChild(node, "moduleSpecifier", Literal.class);
|
||||
List<ImportSpecifier> specifiers = new ArrayList<>();
|
||||
boolean hasTypeKeyword = false;
|
||||
if (hasChild(node, "importClause")) {
|
||||
JsonObject importClause = node.get("importClause").getAsJsonObject();
|
||||
if (hasChild(importClause, "name")) {
|
||||
|
@ -1367,8 +1383,9 @@ public class TypeScriptASTConverter {
|
|||
specifiers.addAll(convertChildren(namedBindings, "elements"));
|
||||
}
|
||||
}
|
||||
hasTypeKeyword = importClause.get("isTypeOnly").getAsBoolean();
|
||||
}
|
||||
ImportDeclaration importDecl = new ImportDeclaration(loc, specifiers, src);
|
||||
ImportDeclaration importDecl = new ImportDeclaration(loc, specifiers, src, hasTypeKeyword);
|
||||
attachSymbolInformation(importDecl, node);
|
||||
return importDecl;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
class C {
|
||||
#foo;
|
||||
constructor() {
|
||||
this.#foo = 5;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,273 @@
|
|||
#10000=@"/privateField.ts;sourcefile"
|
||||
files(#10000,"/privateField.ts","privateField","ts",0)
|
||||
#10001=@"/;folder"
|
||||
folders(#10001,"/","")
|
||||
containerparent(#10001,#10000)
|
||||
#10002=@"loc,{#10000},0,0,0,0"
|
||||
locations_default(#10002,#10000,0,0,0,0)
|
||||
hasLocation(#10000,#10002)
|
||||
#20000=@"global_scope"
|
||||
scopes(#20000,0)
|
||||
#20001=@"script;{#10000},1,1"
|
||||
#20002=*
|
||||
lines(#20002,#20001,"class C {","
|
||||
")
|
||||
#20003=@"loc,{#10000},1,1,1,9"
|
||||
locations_default(#20003,#10000,1,1,1,9)
|
||||
hasLocation(#20002,#20003)
|
||||
#20004=*
|
||||
lines(#20004,#20001," #foo;","
|
||||
")
|
||||
#20005=@"loc,{#10000},2,1,2,6"
|
||||
locations_default(#20005,#10000,2,1,2,6)
|
||||
hasLocation(#20004,#20005)
|
||||
indentation(#10000,2," ",1)
|
||||
#20006=*
|
||||
lines(#20006,#20001," constructor() {","
|
||||
")
|
||||
#20007=@"loc,{#10000},3,1,3,16"
|
||||
locations_default(#20007,#10000,3,1,3,16)
|
||||
hasLocation(#20006,#20007)
|
||||
indentation(#10000,3," ",1)
|
||||
#20008=*
|
||||
lines(#20008,#20001," this.#foo = 5;","
|
||||
")
|
||||
#20009=@"loc,{#10000},4,1,4,17"
|
||||
locations_default(#20009,#10000,4,1,4,17)
|
||||
hasLocation(#20008,#20009)
|
||||
indentation(#10000,4," ",3)
|
||||
#20010=*
|
||||
lines(#20010,#20001," }","
|
||||
")
|
||||
#20011=@"loc,{#10000},5,1,5,2"
|
||||
locations_default(#20011,#10000,5,1,5,2)
|
||||
hasLocation(#20010,#20011)
|
||||
indentation(#10000,5," ",1)
|
||||
#20012=*
|
||||
lines(#20012,#20001,"}","
|
||||
")
|
||||
#20013=@"loc,{#10000},6,1,6,1"
|
||||
locations_default(#20013,#10000,6,1,6,1)
|
||||
hasLocation(#20012,#20013)
|
||||
numlines(#20001,6,6,0)
|
||||
#20014=*
|
||||
tokeninfo(#20014,7,#20001,0,"class")
|
||||
#20015=@"loc,{#10000},1,1,1,5"
|
||||
locations_default(#20015,#10000,1,1,1,5)
|
||||
hasLocation(#20014,#20015)
|
||||
#20016=*
|
||||
tokeninfo(#20016,6,#20001,1,"C")
|
||||
#20017=@"loc,{#10000},1,7,1,7"
|
||||
locations_default(#20017,#10000,1,7,1,7)
|
||||
hasLocation(#20016,#20017)
|
||||
#20018=*
|
||||
tokeninfo(#20018,8,#20001,2,"{")
|
||||
#20019=@"loc,{#10000},1,9,1,9"
|
||||
locations_default(#20019,#10000,1,9,1,9)
|
||||
hasLocation(#20018,#20019)
|
||||
#20020=*
|
||||
tokeninfo(#20020,8,#20001,3,";")
|
||||
#20021=@"loc,{#10000},2,6,2,6"
|
||||
locations_default(#20021,#10000,2,6,2,6)
|
||||
hasLocation(#20020,#20021)
|
||||
#20022=*
|
||||
tokeninfo(#20022,7,#20001,4,"constructor")
|
||||
#20023=@"loc,{#10000},3,2,3,12"
|
||||
locations_default(#20023,#10000,3,2,3,12)
|
||||
hasLocation(#20022,#20023)
|
||||
#20024=*
|
||||
tokeninfo(#20024,8,#20001,5,"(")
|
||||
#20025=@"loc,{#10000},3,13,3,13"
|
||||
locations_default(#20025,#10000,3,13,3,13)
|
||||
hasLocation(#20024,#20025)
|
||||
#20026=*
|
||||
tokeninfo(#20026,8,#20001,6,")")
|
||||
#20027=@"loc,{#10000},3,14,3,14"
|
||||
locations_default(#20027,#10000,3,14,3,14)
|
||||
hasLocation(#20026,#20027)
|
||||
#20028=*
|
||||
tokeninfo(#20028,8,#20001,7,"{")
|
||||
#20029=@"loc,{#10000},3,16,3,16"
|
||||
locations_default(#20029,#10000,3,16,3,16)
|
||||
hasLocation(#20028,#20029)
|
||||
#20030=*
|
||||
tokeninfo(#20030,7,#20001,8,"this")
|
||||
#20031=@"loc,{#10000},4,4,4,7"
|
||||
locations_default(#20031,#10000,4,4,4,7)
|
||||
hasLocation(#20030,#20031)
|
||||
#20032=*
|
||||
tokeninfo(#20032,8,#20001,9,".")
|
||||
#20033=@"loc,{#10000},4,8,4,8"
|
||||
locations_default(#20033,#10000,4,8,4,8)
|
||||
hasLocation(#20032,#20033)
|
||||
#20034=*
|
||||
tokeninfo(#20034,8,#20001,10,"=")
|
||||
#20035=@"loc,{#10000},4,14,4,14"
|
||||
locations_default(#20035,#10000,4,14,4,14)
|
||||
hasLocation(#20034,#20035)
|
||||
#20036=*
|
||||
tokeninfo(#20036,3,#20001,11,"5")
|
||||
#20037=@"loc,{#10000},4,16,4,16"
|
||||
locations_default(#20037,#10000,4,16,4,16)
|
||||
hasLocation(#20036,#20037)
|
||||
#20038=*
|
||||
tokeninfo(#20038,8,#20001,12,";")
|
||||
#20039=@"loc,{#10000},4,17,4,17"
|
||||
locations_default(#20039,#10000,4,17,4,17)
|
||||
hasLocation(#20038,#20039)
|
||||
#20040=*
|
||||
tokeninfo(#20040,8,#20001,13,"}")
|
||||
#20041=@"loc,{#10000},5,2,5,2"
|
||||
locations_default(#20041,#10000,5,2,5,2)
|
||||
hasLocation(#20040,#20041)
|
||||
#20042=*
|
||||
tokeninfo(#20042,8,#20001,14,"}")
|
||||
hasLocation(#20042,#20013)
|
||||
#20043=*
|
||||
tokeninfo(#20043,0,#20001,15,"")
|
||||
#20044=@"loc,{#10000},7,1,7,0"
|
||||
locations_default(#20044,#10000,7,1,7,0)
|
||||
hasLocation(#20043,#20044)
|
||||
toplevels(#20001,0)
|
||||
#20045=@"loc,{#10000},1,1,7,0"
|
||||
locations_default(#20045,#10000,1,1,7,0)
|
||||
hasLocation(#20001,#20045)
|
||||
#20046=@"var;{C};{#20000}"
|
||||
variables(#20046,"C",#20000)
|
||||
#20047=@"local_type_name;{C};{#20000}"
|
||||
local_type_names(#20047,"C",#20000)
|
||||
#20048=*
|
||||
stmts(#20048,26,#20001,0,"class C ... 5;\n }\n}")
|
||||
#20049=@"loc,{#10000},1,1,6,1"
|
||||
locations_default(#20049,#10000,1,1,6,1)
|
||||
hasLocation(#20048,#20049)
|
||||
stmtContainers(#20048,#20001)
|
||||
#20050=*
|
||||
exprs(#20050,78,#20048,0,"C")
|
||||
hasLocation(#20050,#20017)
|
||||
enclosingStmt(#20050,#20048)
|
||||
exprContainers(#20050,#20001)
|
||||
literals("C","C",#20050)
|
||||
decl(#20050,#20046)
|
||||
typedecl(#20050,#20047)
|
||||
#20051=*
|
||||
scopes(#20051,10)
|
||||
scopenodes(#20048,#20051)
|
||||
scopenesting(#20051,#20000)
|
||||
#20052=*
|
||||
properties(#20052,#20048,2,8,"#foo;")
|
||||
#20053=@"loc,{#10000},2,2,2,6"
|
||||
locations_default(#20053,#10000,2,2,2,6)
|
||||
hasLocation(#20052,#20053)
|
||||
#20054=*
|
||||
#20055=*
|
||||
exprs(#20055,0,#20052,0,"#foo")
|
||||
#20056=@"loc,{#10000},2,2,2,5"
|
||||
locations_default(#20056,#10000,2,2,2,5)
|
||||
hasLocation(#20055,#20056)
|
||||
exprContainers(#20055,#20054)
|
||||
literals("#foo","#foo",#20055)
|
||||
#20057=*
|
||||
properties(#20057,#20048,3,0,"constru ... = 5;\n }")
|
||||
#20058=@"loc,{#10000},3,2,5,2"
|
||||
locations_default(#20058,#10000,3,2,5,2)
|
||||
hasLocation(#20057,#20058)
|
||||
#20059=*
|
||||
exprs(#20059,0,#20057,0,"constru ... = 5;\n }")
|
||||
hasLocation(#20059,#20058)
|
||||
enclosingStmt(#20059,#20048)
|
||||
exprContainers(#20059,#20001)
|
||||
literals("constructor","constructor",#20059)
|
||||
exprs(#20054,9,#20057,1,"constru ... = 5;\n }")
|
||||
hasLocation(#20054,#20058)
|
||||
enclosingStmt(#20054,#20048)
|
||||
exprContainers(#20054,#20001)
|
||||
#20060=*
|
||||
scopes(#20060,1)
|
||||
scopenodes(#20054,#20060)
|
||||
scopenesting(#20060,#20051)
|
||||
#20061=@"var;{arguments};{#20060}"
|
||||
variables(#20061,"arguments",#20060)
|
||||
isArgumentsObject(#20061)
|
||||
#20062=*
|
||||
stmts(#20062,1,#20054,-2,"{\n th ... = 5;\n }")
|
||||
#20063=@"loc,{#10000},3,16,5,2"
|
||||
locations_default(#20063,#10000,3,16,5,2)
|
||||
hasLocation(#20062,#20063)
|
||||
stmtContainers(#20062,#20054)
|
||||
#20064=*
|
||||
stmts(#20064,2,#20062,0,"this.#foo = 5;")
|
||||
#20065=@"loc,{#10000},4,4,4,17"
|
||||
locations_default(#20065,#10000,4,4,4,17)
|
||||
hasLocation(#20064,#20065)
|
||||
stmtContainers(#20064,#20054)
|
||||
#20066=*
|
||||
exprs(#20066,47,#20064,0,"this.#foo = 5")
|
||||
#20067=@"loc,{#10000},4,4,4,16"
|
||||
locations_default(#20067,#10000,4,4,4,16)
|
||||
hasLocation(#20066,#20067)
|
||||
enclosingStmt(#20066,#20064)
|
||||
exprContainers(#20066,#20054)
|
||||
#20068=*
|
||||
exprs(#20068,14,#20066,0,"this.#foo")
|
||||
#20069=@"loc,{#10000},4,4,4,12"
|
||||
locations_default(#20069,#10000,4,4,4,12)
|
||||
hasLocation(#20068,#20069)
|
||||
enclosingStmt(#20068,#20064)
|
||||
exprContainers(#20068,#20054)
|
||||
#20070=*
|
||||
exprs(#20070,6,#20068,0,"this")
|
||||
hasLocation(#20070,#20031)
|
||||
enclosingStmt(#20070,#20064)
|
||||
exprContainers(#20070,#20054)
|
||||
#20071=*
|
||||
exprs(#20071,0,#20068,1,"#foo")
|
||||
#20072=@"loc,{#10000},4,9,4,12"
|
||||
locations_default(#20072,#10000,4,9,4,12)
|
||||
hasLocation(#20071,#20072)
|
||||
enclosingStmt(#20071,#20064)
|
||||
exprContainers(#20071,#20054)
|
||||
literals("#foo","#foo",#20071)
|
||||
#20073=*
|
||||
exprs(#20073,3,#20066,1,"5")
|
||||
hasLocation(#20073,#20037)
|
||||
enclosingStmt(#20073,#20064)
|
||||
exprContainers(#20073,#20054)
|
||||
literals("5","5",#20073)
|
||||
isMethod(#20057)
|
||||
#20074=*
|
||||
entry_cfg_node(#20074,#20001)
|
||||
#20075=@"loc,{#10000},1,1,1,0"
|
||||
locations_default(#20075,#10000,1,1,1,0)
|
||||
hasLocation(#20074,#20075)
|
||||
#20076=*
|
||||
exit_cfg_node(#20076,#20001)
|
||||
hasLocation(#20076,#20044)
|
||||
successor(#20055,#20052)
|
||||
successor(#20054,#20057)
|
||||
#20077=*
|
||||
entry_cfg_node(#20077,#20054)
|
||||
#20078=@"loc,{#10000},3,2,3,1"
|
||||
locations_default(#20078,#10000,3,2,3,1)
|
||||
hasLocation(#20077,#20078)
|
||||
successor(#20052,#20062)
|
||||
#20079=*
|
||||
exit_cfg_node(#20079,#20054)
|
||||
#20080=@"loc,{#10000},5,3,5,2"
|
||||
locations_default(#20080,#10000,5,3,5,2)
|
||||
hasLocation(#20079,#20080)
|
||||
successor(#20062,#20064)
|
||||
successor(#20064,#20070)
|
||||
successor(#20073,#20066)
|
||||
successor(#20071,#20068)
|
||||
successor(#20070,#20071)
|
||||
successor(#20068,#20073)
|
||||
successor(#20066,#20079)
|
||||
successor(#20077,#20055)
|
||||
successor(#20059,#20054)
|
||||
successor(#20057,#20048)
|
||||
successor(#20050,#20059)
|
||||
successor(#20048,#20076)
|
||||
successor(#20074,#20050)
|
||||
numlines(#10000,6,6,0)
|
||||
filetype(#10000,"typescript")
|
|
@ -125,7 +125,7 @@ class ASTNode extends @ast_node, Locatable {
|
|||
* Holds if this is part of an ambient declaration or type annotation in a TypeScript file.
|
||||
*
|
||||
* A declaration is ambient if it occurs under a `declare` modifier or is
|
||||
* an interface declaration, type alias, or type annotation.
|
||||
* an interface declaration, type alias, type annotation, or type-only import/export declaration.
|
||||
*
|
||||
* The TypeScript compiler emits no code for ambient declarations, but they
|
||||
* can affect name resolution and type checking at compile-time.
|
||||
|
|
|
@ -76,6 +76,16 @@ class ImportDeclaration extends Stmt, Import, @importdeclaration {
|
|||
// `import { createServer } from 'http'`
|
||||
result = DataFlow::destructuredModuleImportNode(this)
|
||||
}
|
||||
|
||||
/** Holds if this is declared with the `type` keyword, so it only imports types. */
|
||||
predicate isTypeOnly() {
|
||||
hasTypeKeyword(this)
|
||||
}
|
||||
|
||||
override predicate isAmbient() {
|
||||
Stmt.super.isAmbient() or
|
||||
isTypeOnly()
|
||||
}
|
||||
}
|
||||
|
||||
/** A literal path expression appearing in an `import` declaration. */
|
||||
|
@ -256,6 +266,16 @@ abstract class ExportDeclaration extends Stmt, @exportdeclaration {
|
|||
* to module `a` or possibly to some other module from which `a` re-exports.
|
||||
*/
|
||||
abstract DataFlow::Node getSourceNode(string name);
|
||||
|
||||
/** Holds if is declared with the `type` keyword, so only types are exported. */
|
||||
predicate isTypeOnly() {
|
||||
hasTypeKeyword(this)
|
||||
}
|
||||
|
||||
override predicate isAmbient() {
|
||||
Stmt.super.isAmbient() or
|
||||
isTypeOnly()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -413,6 +433,18 @@ class ExportNamedDeclaration extends ExportDeclaration, @exportnameddeclaration
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An export declaration with the `type` modifier.
|
||||
*/
|
||||
private class TypeOnlyExportDeclaration extends ExportNamedDeclaration {
|
||||
TypeOnlyExportDeclaration() { isTypeOnly() }
|
||||
|
||||
override predicate exportsAs(LexicalName v, string name) {
|
||||
super.exportsAs(v, name) and
|
||||
not v instanceof Variable
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An export specifier in an export declaration.
|
||||
*
|
||||
|
|
|
@ -405,10 +405,16 @@ private class AnalyzedClosureGlobalAccessPath extends AnalyzedNode, AnalyzedProp
|
|||
*/
|
||||
private class AnalyzedExportNamespaceSpecifier extends AnalyzedPropertyWrite, DataFlow::ValueNode {
|
||||
override ExportNamespaceSpecifier astNode;
|
||||
ReExportDeclaration decl;
|
||||
|
||||
AnalyzedExportNamespaceSpecifier() {
|
||||
decl = astNode.getExportDeclaration() and
|
||||
not decl.isTypeOnly()
|
||||
}
|
||||
|
||||
override predicate writesValue(AbstractValue baseVal, string propName, AbstractValue value) {
|
||||
baseVal = TAbstractExportsObject(getTopLevel()) and
|
||||
propName = astNode.getExportedName() and
|
||||
value = TAbstractExportsObject(astNode.getExportDeclaration().(ReExportDeclaration).getReExportedModule())
|
||||
value = TAbstractExportsObject(decl.getReExportedModule())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -385,6 +385,8 @@ case @expr.kind of
|
|||
|
||||
@exportspecifier = @namedexportspecifier | @exportdefaultspecifier | @exportnamespacespecifier;
|
||||
|
||||
@import_or_export_declaration = @importdeclaration | @exportdeclaration;
|
||||
|
||||
@typeassertion = @astypeassertion | @prefixtypeassertion;
|
||||
|
||||
@classdefinition = @classdeclstmt | @classexpr;
|
||||
|
@ -518,6 +520,7 @@ hasPublicKeyword (int id: @property ref);
|
|||
hasPrivateKeyword (int id: @property ref);
|
||||
hasProtectedKeyword (int id: @property ref);
|
||||
hasReadonlyKeyword (int id: @property ref);
|
||||
hasTypeKeyword (int id: @import_or_export_declaration ref);
|
||||
isOptionalMember (int id: @property ref);
|
||||
hasDefiniteAssignmentAssertion (int id: @field_or_vardeclarator ref);
|
||||
isOptionalParameterDeclaration (unique int parameter: @pattern ref);
|
||||
|
|
|
@ -7984,6 +7984,17 @@
|
|||
<dependencies/>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>hasTypeKeyword</name>
|
||||
<cardinality>1000</cardinality>
|
||||
<columnsizes>
|
||||
<e>
|
||||
<k>id</k>
|
||||
<v>1000</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies/>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>isOptionalMember</name>
|
||||
<cardinality>3668</cardinality>
|
||||
<columnsizes>
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
import { ns } from "./reexport";
|
||||
|
||||
ns.foo();
|
|
@ -0,0 +1 @@
|
|||
export function foo() {}
|
|
@ -0,0 +1 @@
|
|||
export * as ns from "./lib";
|
|
@ -0,0 +1 @@
|
|||
| reexport.ts:1:8:1:14 | * as ns |
|
|
@ -0,0 +1,3 @@
|
|||
import javascript
|
||||
|
||||
query ExportNamespaceSpecifier test_ExportNamespaceSpecifier() { any() }
|
|
@ -0,0 +1,5 @@
|
|||
propAccess
|
||||
| #privateField | tst.ts:5:9:5:26 | this.#privateField |
|
||||
| #privateField | tst.ts:6:9:6:26 | this.#privateField |
|
||||
fieldDecl
|
||||
| #privateField | tst.ts:2:5:2:23 | #privateField: any; |
|
|
@ -0,0 +1,9 @@
|
|||
import javascript
|
||||
|
||||
query PropAccess propAccess(string name) {
|
||||
result.getPropertyName() = name
|
||||
}
|
||||
|
||||
query FieldDeclaration fieldDecl(string name) {
|
||||
result.getName() = name
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
class C {
|
||||
#privateField: any;
|
||||
|
||||
constructor(x: any) {
|
||||
this.#privateField = x;
|
||||
this.#privateField(y);
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export class C {}
|
|
@ -0,0 +1 @@
|
|||
export function f() {}
|
|
@ -0,0 +1,3 @@
|
|||
import { ns } from "./importType";
|
||||
|
||||
ns.f(); // Calls local method in 'importType'
|
|
@ -0,0 +1,3 @@
|
|||
import type { C } from "./namedReexport";
|
||||
|
||||
let c: C;
|
|
@ -0,0 +1,3 @@
|
|||
export type * as ns from "./exportFunction";
|
||||
|
||||
export var ns = { f() {} };
|
|
@ -0,0 +1 @@
|
|||
export type { C } from "./exportClass";
|
|
@ -0,0 +1,26 @@
|
|||
getAVarReference
|
||||
| C | exportClass.ts:1:14:1:14 | C |
|
||||
| Foo | tst.ts:5:5:5:7 | Foo |
|
||||
| c | importRexportedClass.ts:3:5:3:5 | c |
|
||||
| f | exportFunction.ts:1:17:1:17 | f |
|
||||
| ns | importFunction.ts:1:10:1:11 | ns |
|
||||
| ns | importFunction.ts:3:1:3:2 | ns |
|
||||
| ns | importType.ts:3:12:3:13 | ns |
|
||||
getAnExportAccess
|
||||
| Foo | tst.ts:3:15:3:17 | Foo |
|
||||
getATypeDecl
|
||||
| C | exportClass.ts:1:14:1:14 | C |
|
||||
| C | importRexportedClass.ts:1:15:1:15 | C |
|
||||
| Foo | tst.ts:1:15:1:17 | Foo |
|
||||
| ns | importFunction.ts:1:10:1:11 | ns |
|
||||
| types | tst.ts:7:18:7:22 | types |
|
||||
calls
|
||||
| importFunction.ts:3:1:3:6 | ns.f() | importType.ts:3:19:3:24 | f() {} |
|
||||
exportsAs
|
||||
| exportClass.ts:1:1:1:17 | export class C {} | C | C | type |
|
||||
| exportClass.ts:1:1:1:17 | export class C {} | C | C | variable |
|
||||
| exportFunction.ts:1:1:1:22 | export ... f() {} | f | f | variable |
|
||||
| importType.ts:3:1:3:27 | export ... ) {} }; | ns | ns | variable |
|
||||
| namedReexport.ts:1:1:1:39 | export ... Class"; | C | C | type |
|
||||
| tst.ts:3:1:3:20 | export type { Foo }; | Foo | Foo | namespace |
|
||||
| tst.ts:3:1:3:20 | export type { Foo }; | Foo | Foo | type |
|
|
@ -0,0 +1,22 @@
|
|||
import javascript
|
||||
|
||||
query VarRef getAVarReference(Variable v) {
|
||||
result = v.getAReference()
|
||||
}
|
||||
|
||||
query VarRef getAnExportAccess(LocalTypeName t) {
|
||||
result = t.getAnExportAccess()
|
||||
}
|
||||
|
||||
query TypeDecl getATypeDecl(LocalTypeName t) {
|
||||
result = t.getADeclaration()
|
||||
}
|
||||
|
||||
query Function calls(DataFlow::InvokeNode invoke) {
|
||||
result = invoke.getACallee()
|
||||
}
|
||||
|
||||
query predicate exportsAs(ExportDeclaration exprt, LexicalName v, string name, string kind) {
|
||||
exprt.exportsAs(v, name) and
|
||||
kind = v.getDeclarationSpace()
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import type { Foo } from "foo";
|
||||
|
||||
export type { Foo };
|
||||
|
||||
var Foo = 45;
|
||||
|
||||
import type * as types from "types";
|
||||
|
||||
export type * as blah from "blah";
|
|
@ -3,3 +3,9 @@ class Foo {}
|
|||
|
||||
declare class Bar extends Baz {} // OK
|
||||
declare class Baz {}
|
||||
|
||||
export type { I }; // OK - does not refer to the constant 'I'
|
||||
|
||||
const I = 45;
|
||||
|
||||
interface I {}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,2 @@
|
|||
description: add support for TypeScript 3.8
|
||||
compatibility: backwards
|
Загрузка…
Ссылка в новой задаче