diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index 662fbefca02e..b37657b85b4f 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -42,7 +42,6 @@ import com.semmle.js.ast.Identifier; import com.semmle.js.ast.IfStatement; import com.semmle.js.ast.ImportDeclaration; -import com.semmle.js.ast.ImportNamespaceSpecifier; import com.semmle.js.ast.ImportSpecifier; import com.semmle.js.ast.InvokeExpression; import com.semmle.js.ast.JumpStatement; @@ -1449,13 +1448,7 @@ public Label visit(ImportDeclaration nd, Context c) { 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, - nd instanceof ImportNamespaceSpecifier - ? IdContext.varAndNamespaceDecl - : IdContext.varAndTypeAndNamespaceDecl); + visit(nd.getLocal(), lbl, 1, IdContext.varAndTypeAndNamespaceDecl); return lbl; } diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java index 1a5f92ca4ae5..7b0700a55cf1 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/Main.java +++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java @@ -37,7 +37,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 = "2019-03-13"; + public static final String EXTRACTOR_VERSION = "2019-03-20"; public static final Pattern NEWLINE = Pattern.compile("\n"); diff --git a/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java b/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java index 8c9902c03bf7..1270b0a94092 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java @@ -17,7 +17,6 @@ import com.semmle.js.ast.Identifier; import com.semmle.js.ast.IfStatement; import com.semmle.js.ast.ImportDeclaration; -import com.semmle.js.ast.ImportNamespaceSpecifier; import com.semmle.js.ast.ImportSpecifier; import com.semmle.js.ast.LabeledStatement; import com.semmle.js.ast.LetExpression; @@ -559,9 +558,7 @@ public Void visit(ImportDeclaration nd, Void c) { @Override public Void visit(ImportSpecifier nd, Void c) { - return visit( - nd.getLocal(), - nd instanceof ImportNamespaceSpecifier ? DeclKind.varAndNamespace : DeclKind.all); + return visit(nd.getLocal(), DeclKind.all); } @Override diff --git a/javascript/extractor/tests/es2015/output/trap/import5.js.trap b/javascript/extractor/tests/es2015/output/trap/import5.js.trap index ea5ea8a38363..c686a83cb668 100644 --- a/javascript/extractor/tests/es2015/output/trap/import5.js.trap +++ b/javascript/extractor/tests/es2015/output/trap/import5.js.trap @@ -65,45 +65,49 @@ isModule(#20001) isES2015Module(#20001) #20021=@"var;{foo};{#20020}" variables(#20021,"foo",#20020) -#20022=@"local_namespace_name;{foo};{#20020}" -local_namespace_names(#20022,"foo",#20020) +#20022=@"local_type_name;{foo};{#20020}" +local_type_names(#20022,"foo",#20020) +#20023=@"local_namespace_name;{foo};{#20020}" +local_namespace_names(#20023,"foo",#20020) variables(#20021,"foo",#20020) -local_namespace_names(#20022,"foo",#20020) -#20023=* -stmts(#20023,27,#20001,0,"import ... 'foo';") -hasLocation(#20023,#20003) -stmtContainers(#20023,#20001) +local_type_names(#20022,"foo",#20020) +local_namespace_names(#20023,"foo",#20020) #20024=* -exprs(#20024,4,#20023,-1,"'foo'") -hasLocation(#20024,#20015) -enclosingStmt(#20024,#20023) -exprContainers(#20024,#20001) -literals("foo","'foo'",#20024) +stmts(#20024,27,#20001,0,"import ... 'foo';") +hasLocation(#20024,#20003) +stmtContainers(#20024,#20001) #20025=* -exprs(#20025,85,#20023,0,"* as foo") -#20026=@"loc,{#10000},1,8,1,15" -locations_default(#20026,#10000,1,8,1,15) -hasLocation(#20025,#20026) -enclosingStmt(#20025,#20023) +exprs(#20025,4,#20024,-1,"'foo'") +hasLocation(#20025,#20015) +enclosingStmt(#20025,#20024) exprContainers(#20025,#20001) -#20027=* -exprs(#20027,78,#20025,1,"foo") -hasLocation(#20027,#20011) -enclosingStmt(#20027,#20023) -exprContainers(#20027,#20001) -literals("foo","foo",#20027) -decl(#20027,#20021) -namespacedecl(#20027,#20022) +literals("foo","'foo'",#20025) +#20026=* +exprs(#20026,85,#20024,0,"* as foo") +#20027=@"loc,{#10000},1,8,1,15" +locations_default(#20027,#10000,1,8,1,15) +hasLocation(#20026,#20027) +enclosingStmt(#20026,#20024) +exprContainers(#20026,#20001) #20028=* -entry_cfg_node(#20028,#20001) -#20029=@"loc,{#10000},1,1,1,0" -locations_default(#20029,#10000,1,1,1,0) -hasLocation(#20028,#20029) -#20030=* -exit_cfg_node(#20030,#20001) -hasLocation(#20030,#20019) -successor(#20023,#20030) -successor(#20025,#20023) -successor(#20028,#20025) +exprs(#20028,78,#20026,1,"foo") +hasLocation(#20028,#20011) +enclosingStmt(#20028,#20024) +exprContainers(#20028,#20001) +literals("foo","foo",#20028) +decl(#20028,#20021) +typedecl(#20028,#20022) +namespacedecl(#20028,#20023) +#20029=* +entry_cfg_node(#20029,#20001) +#20030=@"loc,{#10000},1,1,1,0" +locations_default(#20030,#10000,1,1,1,0) +hasLocation(#20029,#20030) +#20031=* +exit_cfg_node(#20031,#20001) +hasLocation(#20031,#20019) +successor(#20024,#20031) +successor(#20026,#20024) +successor(#20029,#20026) numlines(#10000,1,1,0) filetype(#10000,"javascript") diff --git a/javascript/extractor/tests/ts/output/trap/importExport.ts.trap b/javascript/extractor/tests/ts/output/trap/importExport.ts.trap index 4b9267996c07..3f28897f7b9f 100644 --- a/javascript/extractor/tests/ts/output/trap/importExport.ts.trap +++ b/javascript/extractor/tests/ts/output/trap/importExport.ts.trap @@ -122,98 +122,102 @@ isES2015Module(#20001) variables(#20042,"Something",#20041) #20043=@"var;{importExport};{#20041}" variables(#20043,"importExport",#20041) -#20044=@"local_type_name;{importExport};{#20041}" -local_type_names(#20044,"importExport",#20041) -#20045=@"local_namespace_name;{Something};{#20041}" -local_namespace_names(#20045,"Something",#20041) -#20046=@"local_namespace_name;{importExport};{#20041}" -local_namespace_names(#20046,"importExport",#20041) +#20044=@"local_type_name;{Something};{#20041}" +local_type_names(#20044,"Something",#20041) +#20045=@"local_type_name;{importExport};{#20041}" +local_type_names(#20045,"importExport",#20041) +#20046=@"local_namespace_name;{Something};{#20041}" +local_namespace_names(#20046,"Something",#20041) +#20047=@"local_namespace_name;{importExport};{#20041}" +local_namespace_names(#20047,"importExport",#20041) variables(#20042,"Something",#20041) variables(#20043,"importExport",#20041) -local_type_names(#20044,"importExport",#20041) -local_namespace_names(#20045,"Something",#20041) -local_namespace_names(#20046,"importExport",#20041) -#20047=* -stmts(#20047,27,#20001,0,"import ... where';") -hasLocation(#20047,#20003) -stmtContainers(#20047,#20001) +local_type_names(#20044,"Something",#20041) +local_type_names(#20045,"importExport",#20041) +local_namespace_names(#20046,"Something",#20041) +local_namespace_names(#20047,"importExport",#20041) #20048=* -exprs(#20048,4,#20047,-1,"'somewhere'") -hasLocation(#20048,#20019) -enclosingStmt(#20048,#20047) -exprContainers(#20048,#20001) -literals("somewhere","'somewhere'",#20048) +stmts(#20048,27,#20001,0,"import ... where';") +hasLocation(#20048,#20003) +stmtContainers(#20048,#20001) #20049=* -exprs(#20049,85,#20047,0,"* as Something") -#20050=@"loc,{#10000},1,8,1,21" -locations_default(#20050,#10000,1,8,1,21) -hasLocation(#20049,#20050) -enclosingStmt(#20049,#20047) +exprs(#20049,4,#20048,-1,"'somewhere'") +hasLocation(#20049,#20019) +enclosingStmt(#20049,#20048) exprContainers(#20049,#20001) -#20051=* -exprs(#20051,78,#20049,1,"Something") -hasLocation(#20051,#20015) -enclosingStmt(#20051,#20047) -exprContainers(#20051,#20001) -literals("Something","Something",#20051) -decl(#20051,#20042) -namespacedecl(#20051,#20045) +literals("somewhere","'somewhere'",#20049) +#20050=* +exprs(#20050,85,#20048,0,"* as Something") +#20051=@"loc,{#10000},1,8,1,21" +locations_default(#20051,#10000,1,8,1,21) +hasLocation(#20050,#20051) +enclosingStmt(#20050,#20048) +exprContainers(#20050,#20001) #20052=* -stmts(#20052,30,#20001,1,"export ... thingy;") -hasLocation(#20052,#20007) -stmtContainers(#20052,#20001) +exprs(#20052,78,#20050,1,"Something") +hasLocation(#20052,#20015) +enclosingStmt(#20052,#20048) +exprContainers(#20052,#20001) +literals("Something","Something",#20052) +decl(#20052,#20042) +typedecl(#20052,#20044) +namespacedecl(#20052,#20046) #20053=* -stmts(#20053,32,#20052,-1,"import ... thingy;") -#20054=@"loc,{#10000},3,8,3,46" -locations_default(#20054,#10000,3,8,3,46) -hasLocation(#20053,#20054) +stmts(#20053,30,#20001,1,"export ... thingy;") +hasLocation(#20053,#20007) stmtContainers(#20053,#20001) -#20055=* -exprs(#20055,78,#20053,0,"importExport") -hasLocation(#20055,#20027) -enclosingStmt(#20055,#20053) -exprContainers(#20055,#20001) -literals("importExport","importExport",#20055) -decl(#20055,#20043) -typedecl(#20055,#20044) -namespacedecl(#20055,#20046) +#20054=* +stmts(#20054,32,#20053,-1,"import ... thingy;") +#20055=@"loc,{#10000},3,8,3,46" +locations_default(#20055,#10000,3,8,3,46) +hasLocation(#20054,#20055) +stmtContainers(#20054,#20001) #20056=* -exprs(#20056,14,#20053,1,"Something.thingy") -#20057=@"loc,{#10000},3,30,3,45" -locations_default(#20057,#10000,3,30,3,45) -hasLocation(#20056,#20057) -enclosingStmt(#20056,#20053) +exprs(#20056,78,#20054,0,"importExport") +hasLocation(#20056,#20027) +enclosingStmt(#20056,#20054) exprContainers(#20056,#20001) -#20058=* -exprs(#20058,103,#20056,0,"Something") -hasLocation(#20058,#20031) -enclosingStmt(#20058,#20053) -exprContainers(#20058,#20001) -literals("Something","Something",#20058) -namespacebind(#20058,#20045) -bind(#20058,#20042) +literals("importExport","importExport",#20056) +decl(#20056,#20043) +typedecl(#20056,#20045) +namespacedecl(#20056,#20047) +#20057=* +exprs(#20057,14,#20054,1,"Something.thingy") +#20058=@"loc,{#10000},3,30,3,45" +locations_default(#20058,#10000,3,30,3,45) +hasLocation(#20057,#20058) +enclosingStmt(#20057,#20054) +exprContainers(#20057,#20001) #20059=* -exprs(#20059,0,#20056,1,"thingy") -hasLocation(#20059,#20035) -enclosingStmt(#20059,#20053) +exprs(#20059,103,#20057,0,"Something") +hasLocation(#20059,#20031) +enclosingStmt(#20059,#20054) exprContainers(#20059,#20001) -literals("thingy","thingy",#20059) +literals("Something","Something",#20059) +namespacebind(#20059,#20046) +bind(#20059,#20042) #20060=* -entry_cfg_node(#20060,#20001) -#20061=@"loc,{#10000},1,1,1,0" -locations_default(#20061,#10000,1,1,1,0) -hasLocation(#20060,#20061) -#20062=* -exit_cfg_node(#20062,#20001) -hasLocation(#20062,#20039) -successor(#20052,#20055) -successor(#20059,#20056) -successor(#20058,#20059) -successor(#20056,#20053) -successor(#20055,#20058) -successor(#20053,#20062) -successor(#20047,#20052) -successor(#20049,#20047) -successor(#20060,#20049) +exprs(#20060,0,#20057,1,"thingy") +hasLocation(#20060,#20035) +enclosingStmt(#20060,#20054) +exprContainers(#20060,#20001) +literals("thingy","thingy",#20060) +#20061=* +entry_cfg_node(#20061,#20001) +#20062=@"loc,{#10000},1,1,1,0" +locations_default(#20062,#10000,1,1,1,0) +hasLocation(#20061,#20062) +#20063=* +exit_cfg_node(#20063,#20001) +hasLocation(#20063,#20039) +successor(#20053,#20056) +successor(#20060,#20057) +successor(#20059,#20060) +successor(#20057,#20054) +successor(#20056,#20059) +successor(#20054,#20063) +successor(#20048,#20053) +successor(#20050,#20048) +successor(#20061,#20050) numlines(#10000,3,2,0) filetype(#10000,"typescript") diff --git a/javascript/ql/src/semmle/javascript/TypeScript.qll b/javascript/ql/src/semmle/javascript/TypeScript.qll index eae336817718..9104d4d343f8 100644 --- a/javascript/ql/src/semmle/javascript/TypeScript.qll +++ b/javascript/ql/src/semmle/javascript/TypeScript.qll @@ -359,7 +359,7 @@ class TypeDecl extends Identifier, TypeRef, LexicalDecl { TypeDecl() { this = any(ClassOrInterface ci).getIdentifier() or this = any(TypeParameter tp).getIdentifier() or - this = any(ImportSpecifier im | not im instanceof ImportNamespaceSpecifier).getLocal() or + this = any(ImportSpecifier im).getLocal() or this = any(ImportEqualsDeclaration im).getId() or this = any(TypeAliasDeclaration td).getIdentifier() or this = any(EnumDeclaration ed).getIdentifier() or diff --git a/javascript/ql/test/library-tests/TypeScript/LocalTypeResolution/ResolveTypeNames.expected b/javascript/ql/test/library-tests/TypeScript/LocalTypeResolution/ResolveTypeNames.expected index d97404e26ac7..43ba306f202c 100644 --- a/javascript/ql/test/library-tests/TypeScript/LocalTypeResolution/ResolveTypeNames.expected +++ b/javascript/ql/test/library-tests/TypeScript/LocalTypeResolution/ResolveTypeNames.expected @@ -4,6 +4,7 @@ | exports.ts:16:5:16:8 | Enum | exports.ts:7:6:7:9 | Enum | | namespaceDecls.ts:38:8:38:8 | A | namespaceDecls.ts:1:8:1:8 | A | | namespaceDecls.ts:38:8:38:8 | A | namespaceDecls.ts:6:11:6:11 | A | +| namespaceDecls.ts:39:8:39:8 | E | namespaceDecls.ts:4:13:4:13 | E | | namespaceDecls.ts:39:8:39:8 | E | namespaceDecls.ts:7:11:7:11 | E | | tst.ts:6:9:6:9 | I | tst.ts:4:11:4:11 | I | | tst.ts:8:11:8:11 | I | tst.ts:4:11:4:11 | I | diff --git a/javascript/ql/test/query-tests/Declarations/UnusedVariable/UnusedVariable.expected b/javascript/ql/test/query-tests/Declarations/UnusedVariable/UnusedVariable.expected index 30ab3133bca8..9db0d903c2d0 100644 --- a/javascript/ql/test/query-tests/Declarations/UnusedVariable/UnusedVariable.expected +++ b/javascript/ql/test/query-tests/Declarations/UnusedVariable/UnusedVariable.expected @@ -7,6 +7,7 @@ | importWithoutPragma.jsx:1:1:1:27 | import ... react'; | Unused import h. | | multi-imports.js:1:1:1:29 | import ... om 'x'; | Unused imports a, b, d. | | multi-imports.js:2:1:2:42 | import ... om 'x'; | Unused imports alphabetically, ordered. | +| namespaceImportAsType.ts:3:1:3:23 | import ... om "z"; | Unused import Z. | | require-react-in-other-scope.js:2:9:2:13 | React | Unused variable React. | | typeoftype.ts:9:7:9:7 | y | Unused variable y. | | underscore.js:6:7:6:7 | e | Unused variable e. | diff --git a/javascript/ql/test/query-tests/Declarations/UnusedVariable/namespaceImportAsType.ts b/javascript/ql/test/query-tests/Declarations/UnusedVariable/namespaceImportAsType.ts new file mode 100644 index 000000000000..8749b3b059e4 --- /dev/null +++ b/javascript/ql/test/query-tests/Declarations/UnusedVariable/namespaceImportAsType.ts @@ -0,0 +1,9 @@ +import * as X from "x"; // OK +import * as Y from "y"; // OK +import * as Z from "z"; // NOT OK + +function f(x: X) {} +function g(x: Y.T) {} + +f(null); +g(null);