From c61454b5caef46196b3bd222fb6c26ffd10370c1 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 20 Mar 2025 11:44:27 +0100 Subject: [PATCH 01/15] JS: Remove unused 'spec' field --- .../src/com/semmle/js/parser/JSDocParser.java | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java b/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java index 84027ced06c9..3db83c921768 100644 --- a/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java +++ b/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java @@ -70,30 +70,6 @@ public JSDocComment parse(Comment comment) { return new JSDocComment(comment, r.fst(), tags); } - /** Specification of Doctrine AST types for JSDoc type expressions. */ - private static final Map, List> spec = - new LinkedHashMap, List>(); - - static { - spec.put(AllLiteral.class, Arrays.asList()); - spec.put(ArrayType.class, Arrays.asList("elements")); - spec.put(FieldType.class, Arrays.asList("key", "value")); - spec.put(FunctionType.class, Arrays.asList("this", "new", "params", "result")); - spec.put(NameExpression.class, Arrays.asList("name")); - spec.put(NonNullableType.class, Arrays.asList("expression", "prefix")); - spec.put(NullableLiteral.class, Arrays.asList()); - spec.put(NullLiteral.class, Arrays.asList()); - spec.put(NullableType.class, Arrays.asList("expression", "prefix")); - spec.put(OptionalType.class, Arrays.asList("expression")); - spec.put(ParameterType.class, Arrays.asList("name", "expression")); - spec.put(RecordType.class, Arrays.asList("fields")); - spec.put(RestType.class, Arrays.asList("expression")); - spec.put(TypeApplication.class, Arrays.asList("expression", "applications")); - spec.put(UndefinedLiteral.class, Arrays.asList()); - spec.put(UnionType.class, Arrays.asList("elements")); - spec.put(VoidLiteral.class, Arrays.asList()); - } - private static String sliceSource(String source, int index, int last) { if (index >= source.length()) return ""; if (last > source.length()) last = source.length(); From 3a6089740e3607e5a1a039b02ca87d76a762d2f2 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 20 Mar 2025 13:47:59 +0100 Subject: [PATCH 02/15] JS: Separate JSDoc qualified names into individual identifiers --- .../{NameExpression.java => Identifier.java} | 8 +- .../js/ast/jsdoc/QualifiedNameExpression.java | 35 ++++++++ .../src/com/semmle/js/ast/jsdoc/Visitor.java | 4 +- .../semmle/js/extractor/JSDocExtractor.java | 15 +++- .../src/com/semmle/js/parser/JSDocParser.java | 27 +++--- javascript/ql/lib/semmle/javascript/JSDoc.qll | 84 ++++++++++++++++--- .../ql/lib/semmlecode.javascript.dbscheme | 3 +- 7 files changed, 146 insertions(+), 30 deletions(-) rename javascript/extractor/src/com/semmle/js/ast/jsdoc/{NameExpression.java => Identifier.java} (65%) create mode 100644 javascript/extractor/src/com/semmle/js/ast/jsdoc/QualifiedNameExpression.java diff --git a/javascript/extractor/src/com/semmle/js/ast/jsdoc/NameExpression.java b/javascript/extractor/src/com/semmle/js/ast/jsdoc/Identifier.java similarity index 65% rename from javascript/extractor/src/com/semmle/js/ast/jsdoc/NameExpression.java rename to javascript/extractor/src/com/semmle/js/ast/jsdoc/Identifier.java index 94db5d324451..09b393e2d4cd 100644 --- a/javascript/extractor/src/com/semmle/js/ast/jsdoc/NameExpression.java +++ b/javascript/extractor/src/com/semmle/js/ast/jsdoc/Identifier.java @@ -2,12 +2,12 @@ import com.semmle.js.ast.SourceLocation; -/** A named JSDoc type. */ -public class NameExpression extends JSDocTypeExpression { +/** An identifier in a JSDoc type. */ +public class Identifier extends JSDocTypeExpression { private final String name; - public NameExpression(SourceLocation loc, String name) { - super(loc, "NameExpression"); + public Identifier(SourceLocation loc, String name) { + super(loc, "Identifier"); this.name = name; } diff --git a/javascript/extractor/src/com/semmle/js/ast/jsdoc/QualifiedNameExpression.java b/javascript/extractor/src/com/semmle/js/ast/jsdoc/QualifiedNameExpression.java new file mode 100644 index 000000000000..93bebc6a3584 --- /dev/null +++ b/javascript/extractor/src/com/semmle/js/ast/jsdoc/QualifiedNameExpression.java @@ -0,0 +1,35 @@ +package com.semmle.js.ast.jsdoc; + +import com.semmle.js.ast.SourceLocation; + +/** A qualified name in a JSDoc type. */ +public class QualifiedNameExpression extends JSDocTypeExpression { + private final JSDocTypeExpression base; + private final Identifier name; + + public QualifiedNameExpression(SourceLocation loc, JSDocTypeExpression base, Identifier name) { + super(loc, "QualifiedNameExpression"); + this.base = base; + this.name = name; + } + + @Override + public void accept(Visitor v) { + v.visit(this); + } + + /** Returns the expression on the left side of the dot character. */ + public JSDocTypeExpression getBase() { + return base; + } + + /** Returns the identifier on the right-hand side of the dot character. */ + public Identifier getNameNode() { + return name; + } + + @Override + public String pp() { + return base.pp() + "." + name.pp(); + } +} diff --git a/javascript/extractor/src/com/semmle/js/ast/jsdoc/Visitor.java b/javascript/extractor/src/com/semmle/js/ast/jsdoc/Visitor.java index 48a2edda1e74..571a3ed9a625 100644 --- a/javascript/extractor/src/com/semmle/js/ast/jsdoc/Visitor.java +++ b/javascript/extractor/src/com/semmle/js/ast/jsdoc/Visitor.java @@ -10,7 +10,9 @@ public interface Visitor { public void visit(JSDocTag nd); - public void visit(NameExpression nd); + public void visit(Identifier nd); + + public void visit(QualifiedNameExpression nd); public void visit(NullableLiteral nd); diff --git a/javascript/extractor/src/com/semmle/js/extractor/JSDocExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/JSDocExtractor.java index 86d1e1f6f79d..2e951414733b 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/JSDocExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/JSDocExtractor.java @@ -9,13 +9,14 @@ import com.semmle.js.ast.jsdoc.JSDocElement; import com.semmle.js.ast.jsdoc.JSDocTag; import com.semmle.js.ast.jsdoc.JSDocTypeExpression; -import com.semmle.js.ast.jsdoc.NameExpression; +import com.semmle.js.ast.jsdoc.Identifier; import com.semmle.js.ast.jsdoc.NonNullableType; import com.semmle.js.ast.jsdoc.NullLiteral; import com.semmle.js.ast.jsdoc.NullableLiteral; import com.semmle.js.ast.jsdoc.NullableType; import com.semmle.js.ast.jsdoc.OptionalType; import com.semmle.js.ast.jsdoc.ParameterType; +import com.semmle.js.ast.jsdoc.QualifiedNameExpression; import com.semmle.js.ast.jsdoc.RecordType; import com.semmle.js.ast.jsdoc.RestType; import com.semmle.js.ast.jsdoc.TypeApplication; @@ -42,7 +43,7 @@ public class JSDocExtractor { jsdocTypeExprKinds.put("UndefinedLiteral", 2); jsdocTypeExprKinds.put("NullableLiteral", 3); jsdocTypeExprKinds.put("VoidLiteral", 4); - jsdocTypeExprKinds.put("NameExpression", 5); + jsdocTypeExprKinds.put("Identifier", 5); jsdocTypeExprKinds.put("TypeApplication", 6); jsdocTypeExprKinds.put("NullableType", 7); jsdocTypeExprKinds.put("NonNullableType", 8); @@ -52,6 +53,7 @@ public class JSDocExtractor { jsdocTypeExprKinds.put("FunctionType", 12); jsdocTypeExprKinds.put("OptionalType", 13); jsdocTypeExprKinds.put("RestType", 14); + jsdocTypeExprKinds.put("QualifiedNameExpression", 15); } private final TrapWriter trapwriter; @@ -122,10 +124,17 @@ public void visit(RecordType nd) { } @Override - public void visit(NameExpression nd) { + public void visit(Identifier nd) { visit((JSDocTypeExpression) nd); } + @Override + public void visit(QualifiedNameExpression nd) { + Label label = visit((JSDocTypeExpression) nd); + visit(nd.getBase(), label, 0); + visit(nd.getNameNode(), label, 1); + } + @Override public void visit(NullableLiteral nd) { visit((JSDocTypeExpression) nd); diff --git a/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java b/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java index 3db83c921768..e1b8b8b72ba8 100644 --- a/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java +++ b/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java @@ -10,13 +10,14 @@ import com.semmle.js.ast.jsdoc.JSDocComment; import com.semmle.js.ast.jsdoc.JSDocTag; import com.semmle.js.ast.jsdoc.JSDocTypeExpression; -import com.semmle.js.ast.jsdoc.NameExpression; +import com.semmle.js.ast.jsdoc.Identifier; import com.semmle.js.ast.jsdoc.NonNullableType; import com.semmle.js.ast.jsdoc.NullLiteral; import com.semmle.js.ast.jsdoc.NullableLiteral; import com.semmle.js.ast.jsdoc.NullableType; import com.semmle.js.ast.jsdoc.OptionalType; import com.semmle.js.ast.jsdoc.ParameterType; +import com.semmle.js.ast.jsdoc.QualifiedNameExpression; import com.semmle.js.ast.jsdoc.RecordType; import com.semmle.js.ast.jsdoc.RestType; import com.semmle.js.ast.jsdoc.TypeApplication; @@ -827,10 +828,16 @@ private JSDocTypeExpression parseRecordType() throws ParseError { } private JSDocTypeExpression parseNameExpression() throws ParseError { - Object name = value; SourceLocation loc = loc(); expect(Token.NAME); - return finishNode(new NameExpression(loc, name.toString())); + // Hacky initial implementation with wrong locations + String[] parts = value.toString().split("\\."); + JSDocTypeExpression node = finishNode(new Identifier(loc, parts[0])); + for (int i = 1; i < parts.length; i++) { + Identifier memberName = finishNode(new Identifier(loc, parts[i])); + node = finishNode(new QualifiedNameExpression(loc, node, memberName)); + } + return node; } // TypeExpressionList := @@ -923,14 +930,14 @@ private List parseParametersType() throws ParseError { SourceLocation loc = loc(); expr = parseTypeExpression(); - if (expr instanceof NameExpression && token == Token.COLON) { + if (expr instanceof Identifier && token == Token.COLON) { // Identifier ':' TypeExpression consume(Token.COLON); expr = finishNode( new ParameterType( new SourceLocation(loc), - ((NameExpression) expr).getName(), + ((Identifier) expr).getName(), parseTypeExpression())); } if (token == Token.EQUAL) { @@ -1106,7 +1113,7 @@ private JSDocTypeExpression parseTypeExpression() throws ParseError { consume(Token.RBRACK, "expected an array-style type declaration (' + value + '[])"); List expressions = new ArrayList<>(); expressions.add(expr); - NameExpression nameExpr = finishNode(new NameExpression(new SourceLocation(loc), "Array")); + Identifier nameExpr = finishNode(new Identifier(new SourceLocation(loc), "Array")); return finishNode(new TypeApplication(loc, nameExpr, expressions)); } @@ -1527,9 +1534,9 @@ public boolean parseName() { // fixed at the end if (isParamTitle(this._title) && this._tag.type != null - && this._tag.type instanceof NameExpression) { - this._extra_name = ((NameExpression) this._tag.type).getName(); - this._tag.name = ((NameExpression) this._tag.type).getName(); + && this._tag.type instanceof Identifier) { + this._extra_name = ((Identifier) this._tag.type).getName(); + this._tag.name = ((Identifier) this._tag.type).getName(); this._tag.type = null; } else { if (!this.addError("Missing or invalid tag name")) { @@ -1645,7 +1652,7 @@ private boolean epilogue() { Position start = new Position(_tag.startLine, _tag.startColumn, _tag.startColumn); Position end = new Position(_tag.startLine, _tag.startColumn, _tag.startColumn); SourceLocation loc = new SourceLocation(_extra_name, start, end); - this._tag.type = new NameExpression(loc, _extra_name); + this._tag.type = new Identifier(loc, _extra_name); } this._tag.name = null; diff --git a/javascript/ql/lib/semmle/javascript/JSDoc.qll b/javascript/ql/lib/semmle/javascript/JSDoc.qll index 6e1ea5caecb6..9ea517cb0757 100644 --- a/javascript/ql/lib/semmle/javascript/JSDoc.qll +++ b/javascript/ql/lib/semmle/javascript/JSDoc.qll @@ -261,17 +261,14 @@ class JSDocVoidTypeExpr extends @jsdoc_void_type_expr, JSDocTypeExpr { } /** - * A type expression referring to a named type. - * - * Example: + * An identifier in a JSDoc type expression, such as `Object` or `string`. * - * ``` - * string - * Object - * ``` + * Note that qualified names consist of multiple identifier nodes. */ -class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr { - /** Gets the name of the type the expression refers to. */ +class JSDocIdentifierTypeExpr extends @jsdoc_identifier_type_expr, JSDocTypeExpr { + /** + * Gets the name of the identifier. + */ string getName() { result = this.toString() } override predicate isString() { this.getName() = "string" } @@ -300,6 +297,71 @@ class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr { } override predicate isRawFunction() { this.getName() = "Function" } +} + +/** + * An unqualified identifier in a JSDoc type expression. + * + * Example: + * + * ``` + * string + * Object + * ``` + */ +class JSDocLocalTypeAccess extends JSDocIdentifierTypeExpr { + JSDocLocalTypeAccess() { not this = any(JSDocQualifiedTypeAccess a).getNameNode() } +} + +/** + * A qualified type name in a JSDoc type expression, such as `X.Y`. + */ +class JSDocQualifiedTypeAccess extends @jsdoc_qualified_type_expr, JSDocTypeExpr { + /** + * Gets the base of this access, such as the `X` in `X.Y`. + */ + JSDocTypeExpr getBase() { result = this.getChild(0) } + + /** + * Gets the node naming the member being accessed, such as the `Y` node in `X.Y`. + */ + JSDocIdentifierTypeExpr getNameNode() { result = this.getChild(1) } + + /** + * Gets the name being accessed, such as `Y` in `X.Y`. + */ + string getName() { result = this.getNameNode().getName() } +} + +/** + * A type expression referring to a named type. + * + * Example: + * + * ``` + * string + * Object + * Namespace.Type + * ``` + */ +class JSDocNamedTypeExpr extends JSDocTypeExpr { + JSDocNamedTypeExpr() { + this instanceof JSDocLocalTypeAccess + or + this instanceof JSDocQualifiedTypeAccess + } + + /** + * Gets the name directly as it appears in this type, including any qualifiers. + * + * For example, for `X.Y` this gets the string `"X.Y"`. + */ + string getRawName() { result = this.toString() } + + /** + * DEPRECATED. Use `getRawName()` instead. + */ + deprecated string getName() { result = this.toString() } /** * Holds if this name consists of the unqualified name `prefix` @@ -311,7 +373,7 @@ class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr { */ predicate hasNameParts(string prefix, string suffix) { exists(string regex, string name | regex = "([^.]+)(.*)" | - name = this.getName() and + name = this.getRawName() and prefix = name.regexpCapture(regex, 1) and suffix = name.regexpCapture(regex, 2) ) @@ -340,7 +402,7 @@ class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr { globalName = this.resolvedName() or not exists(this.resolvedName()) and - globalName = this.getName() + globalName = this.getRawName() } override DataFlow::ClassNode getClass() { diff --git a/javascript/ql/lib/semmlecode.javascript.dbscheme b/javascript/ql/lib/semmlecode.javascript.dbscheme index 5b5db607d20c..ccefb5e2d493 100644 --- a/javascript/ql/lib/semmlecode.javascript.dbscheme +++ b/javascript/ql/lib/semmlecode.javascript.dbscheme @@ -1001,7 +1001,7 @@ case @jsdoc_type_expr.kind of | 2 = @jsdoc_undefined_type_expr | 3 = @jsdoc_unknown_type_expr | 4 = @jsdoc_void_type_expr -| 5 = @jsdoc_named_type_expr +| 5 = @jsdoc_identifier_type_expr | 6 = @jsdoc_applied_type_expr | 7 = @jsdoc_nullable_type_expr | 8 = @jsdoc_non_nullable_type_expr @@ -1011,6 +1011,7 @@ case @jsdoc_type_expr.kind of | 12 = @jsdoc_function_type_expr | 13 = @jsdoc_optional_type_expr | 14 = @jsdoc_rest_type_expr +| 15 = @jsdoc_qualified_type_expr ; #keyset[id, idx] From fa53ff9f3ecabd5da5b3346093a48d0244a92780 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 20 Mar 2025 13:48:09 +0100 Subject: [PATCH 03/15] JS: Update extractor version string --- javascript/extractor/src/com/semmle/js/extractor/Main.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java index 56e4e42dc543..0b92711b01da 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/Main.java +++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java @@ -42,7 +42,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 = "2025-02-03"; + public static final String EXTRACTOR_VERSION = "2025-03-20"; public static final Pattern NEWLINE = Pattern.compile("\n"); From 328bf753b49753eff31267c092e8f0a619d0f3b1 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 20 Mar 2025 14:54:16 +0100 Subject: [PATCH 04/15] JS: Benign test updates --- .../JSDoc/NameResolution/test.expected | 5 +++++ .../test/library-tests/JSDoc/Nodes/tests.expected | 14 ++++++++++++++ .../JSDoc/JSDocTypeAnnotations.expected | 2 ++ 3 files changed, 21 insertions(+) diff --git a/javascript/ql/test/library-tests/JSDoc/NameResolution/test.expected b/javascript/ql/test/library-tests/JSDoc/NameResolution/test.expected index 04bbd2a2ce0b..855d1b59ff60 100644 --- a/javascript/ql/test/library-tests/JSDoc/NameResolution/test.expected +++ b/javascript/ql/test/library-tests/JSDoc/NameResolution/test.expected @@ -1,5 +1,10 @@ +| bar.js:5:14:5:18 | x | ns.very.long.namespace | | bar.js:5:14:5:18 | x.Foo | ns.very.long.namespace.Foo | +| bar.js:12:14:12:21 | iife | IIFE | | bar.js:12:14:12:21 | iife.Foo | IIFE.Foo | +| closure.js:8:12:8:28 | goog | goog | +| closure.js:8:12:8:28 | goog.net | goog.net | | closure.js:8:12:8:28 | goog.net.SomeType | goog.net.SomeType | +| closure.js:9:12:9:23 | net | goog.net | | closure.js:9:12:9:23 | net.SomeType | goog.net.SomeType | | closure.js:10:12:10:19 | SomeType | goog.net.SomeType | diff --git a/javascript/ql/test/library-tests/JSDoc/Nodes/tests.expected b/javascript/ql/test/library-tests/JSDoc/Nodes/tests.expected index 32c716421c1e..7ed69cb851f3 100644 --- a/javascript/ql/test/library-tests/JSDoc/Nodes/tests.expected +++ b/javascript/ql/test/library-tests/JSDoc/Nodes/tests.expected @@ -278,6 +278,10 @@ test_JSDocTypeExpr | tst.js:26:14:26:20 | boolean | tst.js:26:5:26:11 | @define | 0 | | tst.js:31:13:31:19 | boolean | tst.js:31:4:31:10 | @return | 0 | | tst.js:53:11:53:16 | number | tst.js:53:4:53:8 | @enum | 0 | +| tst.js:68:14:68:34 | BasicNodeList | tst.js:68:14:68:34 | goog.ds.BasicNodeList | 1 | +| tst.js:68:14:68:34 | ds | tst.js:68:14:68:34 | goog.ds | 1 | +| tst.js:68:14:68:34 | goog | tst.js:68:14:68:34 | goog.ds | 0 | +| tst.js:68:14:68:34 | goog.ds | tst.js:68:14:68:34 | goog.ds.BasicNodeList | 0 | | tst.js:68:14:68:34 | goog.ds.BasicNodeList | tst.js:68:4:68:11 | @extends | 0 | | tst.js:95:17:95:21 | Shape | tst.js:95:4:95:14 | @implements | 0 | | tst.js:110:14:110:18 | Shape | tst.js:110:4:110:11 | @extends | 0 | @@ -298,6 +302,8 @@ test_JSDocTypeExpr | tst.js:216:15:216:29 | (string\|number) | tst.js:216:5:216:12 | @typedef | 0 | | tst.js:216:16:216:21 | string | tst.js:216:15:216:29 | (string\|number) | 0 | | tst.js:216:23:216:28 | number | tst.js:216:15:216:29 | (string\|number) | 1 | +| tst.js:219:13:219:27 | NumberLike | tst.js:219:13:219:27 | goog.NumberLike | 1 | +| tst.js:219:13:219:27 | goog | tst.js:219:13:219:27 | goog.NumberLike | 0 | | tst.js:219:13:219:27 | goog.NumberLike | tst.js:219:5:219:10 | @param | 0 | | tst.js:223:12:223:36 | {myNum: number, myObject} | tst.js:223:5:223:9 | @type | 0 | | tst.js:223:20:223:25 | number | tst.js:223:12:223:36 | {myNum: number, myObject} | 0 | @@ -311,10 +317,18 @@ test_JSDocTypeExpr | tst.js:234:12:234:29 | function (): number | tst.js:234:4:234:9 | @param | 0 | | tst.js:234:24:234:29 | number | tst.js:234:12:234:29 | function (): number | -1 | | tst.js:235:12:235:46 | function (this: goog.ui.Menu, string) | tst.js:235:4:235:9 | @param | 0 | +| tst.js:235:26:235:37 | Menu | tst.js:235:26:235:37 | goog.ui.Menu | 1 | +| tst.js:235:26:235:37 | goog | tst.js:235:26:235:37 | goog.ui | 0 | +| tst.js:235:26:235:37 | goog.ui | tst.js:235:26:235:37 | goog.ui.Menu | 0 | | tst.js:235:26:235:37 | goog.ui.Menu | tst.js:235:12:235:46 | function (this: goog.ui.Menu, string) | -2 | +| tst.js:235:26:235:37 | ui | tst.js:235:26:235:37 | goog.ui | 1 | | tst.js:235:40:235:45 | string | tst.js:235:12:235:46 | function (this: goog.ui.Menu, string) | 0 | | tst.js:236:12:236:45 | function (new: goog.ui.Menu, string) | tst.js:236:4:236:9 | @param | 0 | +| tst.js:236:25:236:36 | Menu | tst.js:236:25:236:36 | goog.ui.Menu | 1 | +| tst.js:236:25:236:36 | goog | tst.js:236:25:236:36 | goog.ui | 0 | +| tst.js:236:25:236:36 | goog.ui | tst.js:236:25:236:36 | goog.ui.Menu | 0 | | tst.js:236:25:236:36 | goog.ui.Menu | tst.js:236:12:236:45 | function (new: goog.ui.Menu, string) | -2 | +| tst.js:236:25:236:36 | ui | tst.js:236:25:236:36 | goog.ui | 1 | | tst.js:236:39:236:44 | string | tst.js:236:12:236:45 | function (new: goog.ui.Menu, string) | 0 | | tst.js:237:12:237:48 | function (string, ...[number]): number | tst.js:237:4:237:9 | @param | 0 | | tst.js:237:21:237:26 | string | tst.js:237:12:237:48 | function (string, ...[number]): number | 0 | diff --git a/javascript/ql/test/library-tests/TypeAnnotations/JSDoc/JSDocTypeAnnotations.expected b/javascript/ql/test/library-tests/TypeAnnotations/JSDoc/JSDocTypeAnnotations.expected index bacfb98cdc63..983388d69a22 100644 --- a/javascript/ql/test/library-tests/TypeAnnotations/JSDoc/JSDocTypeAnnotations.expected +++ b/javascript/ql/test/library-tests/TypeAnnotations/JSDoc/JSDocTypeAnnotations.expected @@ -5,6 +5,8 @@ test_isNumber test_QualifiedName | VarType | tst.js:9:13:9:19 | VarType | | boolean | tst.js:5:14:5:20 | boolean | +| foo | tst.js:4:12:4:22 | foo | +| foo.bar | tst.js:4:12:4:22 | foo.bar | | foo.bar.baz | tst.js:4:12:4:22 | foo.bar.baz | | number | tst.js:3:12:3:17 | number | | string | tst.js:2:12:2:17 | string | From b1554443d8e3f8992d889b9fb3a0b065d434563f Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 20 Mar 2025 14:55:27 +0100 Subject: [PATCH 05/15] JS: Update TRAP output --- .../tests/comments/output/trap/jsdoc.js.trap | 236 +++++++++--------- 1 file changed, 124 insertions(+), 112 deletions(-) diff --git a/javascript/extractor/tests/comments/output/trap/jsdoc.js.trap b/javascript/extractor/tests/comments/output/trap/jsdoc.js.trap index 736a6b2d19ff..b88a66b4f486 100644 --- a/javascript/extractor/tests/comments/output/trap/jsdoc.js.trap +++ b/javascript/extractor/tests/comments/output/trap/jsdoc.js.trap @@ -517,150 +517,162 @@ jsdoc_type_exprs(#20157,4,#20145,-1,"void") locations_default(#20158,#10000,11,60,11,63) hasLocation(#20157,#20158) #20159=* -jsdoc_type_exprs(#20159,5,#20145,-2,"goog.ui.Menu") +jsdoc_type_exprs(#20159,15,#20145,-2,"goog.ui.Menu") #20160=@"loc,{#10000},11,26,11,37" locations_default(#20160,#10000,11,26,11,37) hasLocation(#20159,#20160) -jsdoc_has_new_parameter(#20145) #20161=* -jsdoc_tags(#20161,"param",#20117,4,"@param") -#20162=@"loc,{#10000},12,5,12,10" -locations_default(#20162,#10000,12,5,12,10) -hasLocation(#20161,#20162) -jsdoc_tag_names(#20161,"var_args") +jsdoc_type_exprs(#20161,15,#20159,0,"goog.ui") +hasLocation(#20161,#20160) +#20162=* +jsdoc_type_exprs(#20162,5,#20161,0,"goog") +hasLocation(#20162,#20160) #20163=* -jsdoc_type_exprs(#20163,14,#20161,0,"...number") -#20164=@"loc,{#10000},12,13,12,21" -locations_default(#20164,#10000,12,13,12,21) -hasLocation(#20163,#20164) +jsdoc_type_exprs(#20163,5,#20161,1,"ui") +hasLocation(#20163,#20160) +#20164=* +jsdoc_type_exprs(#20164,5,#20159,1,"Menu") +hasLocation(#20164,#20160) +jsdoc_has_new_parameter(#20145) #20165=* -jsdoc_type_exprs(#20165,5,#20163,0,"number") -#20166=@"loc,{#10000},12,16,12,21" -locations_default(#20166,#10000,12,16,12,21) +jsdoc_tags(#20165,"param",#20117,4,"@param") +#20166=@"loc,{#10000},12,5,12,10" +locations_default(#20166,#10000,12,5,12,10) hasLocation(#20165,#20166) +jsdoc_tag_names(#20165,"var_args") #20167=* -jsdoc(#20167,"",#20010) -hasLocation(#20167,#20011) -#20168=* -jsdoc_tags(#20168,"param",#20167,0,"@param") -#20169=@"loc,{#10000},15,4,15,9" -locations_default(#20169,#10000,15,4,15,9) -hasLocation(#20168,#20169) -#20170=* -jsdoc_errors(#20170,#20168,"Missing or invalid tag name","Missing ... ag name") +jsdoc_type_exprs(#20167,14,#20165,0,"...number") +#20168=@"loc,{#10000},12,13,12,21" +locations_default(#20168,#10000,12,13,12,21) +hasLocation(#20167,#20168) +#20169=* +jsdoc_type_exprs(#20169,5,#20167,0,"number") +#20170=@"loc,{#10000},12,16,12,21" +locations_default(#20170,#10000,12,16,12,21) +hasLocation(#20169,#20170) #20171=* -jsdoc_tags(#20171,"param",#20167,1,"@param") -#20172=@"loc,{#10000},16,4,16,9" -locations_default(#20172,#10000,16,4,16,9) -hasLocation(#20171,#20172) -jsdoc_tag_names(#20171,"x") -#20173=* -jsdoc(#20173,"",#20012) -hasLocation(#20173,#20013) +jsdoc(#20171,"",#20010) +hasLocation(#20171,#20011) +#20172=* +jsdoc_tags(#20172,"param",#20171,0,"@param") +#20173=@"loc,{#10000},15,4,15,9" +locations_default(#20173,#10000,15,4,15,9) +hasLocation(#20172,#20173) #20174=* -jsdoc_tags(#20174,"",#20173,0,"@") -#20175=@"loc,{#10000},20,4,20,4" -locations_default(#20175,#10000,20,4,20,4) -hasLocation(#20174,#20175) -jsdoc_tag_descriptions(#20174,"{link a}") -#20176=* -jsdoc_errors(#20176,#20174,"Missing or invalid title","Missing ... d title") +jsdoc_errors(#20174,#20172,"Missing or invalid tag name","Missing ... ag name") +#20175=* +jsdoc_tags(#20175,"param",#20171,1,"@param") +#20176=@"loc,{#10000},16,4,16,9" +locations_default(#20176,#10000,16,4,16,9) +hasLocation(#20175,#20176) +jsdoc_tag_names(#20175,"x") #20177=* -jsdoc(#20177,"",#20014) -hasLocation(#20177,#20015) +jsdoc(#20177,"",#20012) +hasLocation(#20177,#20013) #20178=* -jsdoc_tags(#20178,"typedef",#20177,0,"@typedef") -#20179=@"loc,{#10000},24,4,24,11" -locations_default(#20179,#10000,24,4,24,11) +jsdoc_tags(#20178,"",#20177,0,"@") +#20179=@"loc,{#10000},20,4,20,4" +locations_default(#20179,#10000,20,4,20,4) hasLocation(#20178,#20179) -jsdoc_tag_descriptions(#20178,"{a}") +jsdoc_tag_descriptions(#20178,"{link a}") #20180=* -jsdoc_errors(#20180,#20178,"Missing or invalid tag type","Missing ... ag type") +jsdoc_errors(#20180,#20178,"Missing or invalid title","Missing ... d title") #20181=* -jsdoc(#20181,"[resize description]",#20016) -hasLocation(#20181,#20017) +jsdoc(#20181,"",#20014) +hasLocation(#20181,#20015) #20182=* -jsdoc_tags(#20182,"param",#20181,0,"@param") -#20183=@"loc,{#10000},30,4,30,9" -locations_default(#20183,#10000,30,4,30,9) +jsdoc_tags(#20182,"typedef",#20181,0,"@typedef") +#20183=@"loc,{#10000},24,4,24,11" +locations_default(#20183,#10000,24,4,24,11) hasLocation(#20182,#20183) -jsdoc_tag_descriptions(#20182,"[description] -") -jsdoc_tag_names(#20182,"w") +jsdoc_tag_descriptions(#20182,"{a}") #20184=* -jsdoc_type_exprs(#20184,10,#20182,0,"[type]") -#20185=@"loc,{#10000},30,13,30,18" -locations_default(#20185,#10000,30,13,30,18) -hasLocation(#20184,#20185) +jsdoc_errors(#20184,#20182,"Missing or invalid tag type","Missing ... ag type") +#20185=* +jsdoc(#20185,"[resize description]",#20016) +hasLocation(#20185,#20017) #20186=* -jsdoc_type_exprs(#20186,5,#20184,0,"type") -#20187=@"loc,{#10000},30,14,30,17" -locations_default(#20187,#10000,30,14,30,17) +jsdoc_tags(#20186,"param",#20185,0,"@param") +#20187=@"loc,{#10000},30,4,30,9" +locations_default(#20187,#10000,30,4,30,9) hasLocation(#20186,#20187) +jsdoc_tag_descriptions(#20186,"[description] +") +jsdoc_tag_names(#20186,"w") #20188=* -jsdoc_tags(#20188,"param",#20181,1,"@param") -#20189=@"loc,{#10000},31,4,31,9" -locations_default(#20189,#10000,31,4,31,9) +jsdoc_type_exprs(#20188,10,#20186,0,"[type]") +#20189=@"loc,{#10000},30,13,30,18" +locations_default(#20189,#10000,30,13,30,18) hasLocation(#20188,#20189) -jsdoc_tag_descriptions(#20188,"[description] -") #20190=* -jsdoc_tags(#20190,"return",#20181,2,"@return") -#20191=@"loc,{#10000},32,4,32,10" -locations_default(#20191,#10000,32,4,32,10) +jsdoc_type_exprs(#20190,5,#20188,0,"type") +#20191=@"loc,{#10000},30,14,30,17" +locations_default(#20191,#10000,30,14,30,17) hasLocation(#20190,#20191) -jsdoc_tag_descriptions(#20190,"[description]") #20192=* -jsdoc_type_exprs(#20192,10,#20190,0,"[type]") -#20193=@"loc,{#10000},32,13,32,18" -locations_default(#20193,#10000,32,13,32,18) +jsdoc_tags(#20192,"param",#20185,1,"@param") +#20193=@"loc,{#10000},31,4,31,9" +locations_default(#20193,#10000,31,4,31,9) hasLocation(#20192,#20193) +jsdoc_tag_descriptions(#20192,"[description] +") #20194=* -jsdoc_type_exprs(#20194,5,#20192,0,"type") -#20195=@"loc,{#10000},32,14,32,17" -locations_default(#20195,#10000,32,14,32,17) +jsdoc_tags(#20194,"return",#20185,2,"@return") +#20195=@"loc,{#10000},32,4,32,10" +locations_default(#20195,#10000,32,4,32,10) hasLocation(#20194,#20195) +jsdoc_tag_descriptions(#20194,"[description]") #20196=* -jsdoc(#20196,"",#20018) -hasLocation(#20196,#20019) -#20197=* -jsdoc_tags(#20197,"exports",#20196,0,"@exports") -#20198=@"loc,{#10000},36,3,36,10" -locations_default(#20198,#10000,36,3,36,10) -hasLocation(#20197,#20198) -jsdoc_tag_descriptions(#20197,"R -") -#20199=* -jsdoc(#20199,"",#20020) -hasLocation(#20199,#20021) +jsdoc_type_exprs(#20196,10,#20194,0,"[type]") +#20197=@"loc,{#10000},32,13,32,18" +locations_default(#20197,#10000,32,13,32,18) +hasLocation(#20196,#20197) +#20198=* +jsdoc_type_exprs(#20198,5,#20196,0,"type") +#20199=@"loc,{#10000},32,14,32,17" +locations_default(#20199,#10000,32,14,32,17) +hasLocation(#20198,#20199) #20200=* -jsdoc_tags(#20200,"typedef",#20199,0,"@typedef") -#20201=@"loc,{#10000},41,4,41,11" -locations_default(#20201,#10000,41,4,41,11) -hasLocation(#20200,#20201) -#20202=* -jsdoc_type_exprs(#20202,9,#20200,0,"{0: number}") -#20203=@"loc,{#10000},41,14,41,24" -locations_default(#20203,#10000,41,14,41,24) -hasLocation(#20202,#20203) -jsdoc_record_field_name(#20202,0,"0") +jsdoc(#20200,"",#20018) +hasLocation(#20200,#20019) +#20201=* +jsdoc_tags(#20201,"exports",#20200,0,"@exports") +#20202=@"loc,{#10000},36,3,36,10" +locations_default(#20202,#10000,36,3,36,10) +hasLocation(#20201,#20202) +jsdoc_tag_descriptions(#20201,"R +") +#20203=* +jsdoc(#20203,"",#20020) +hasLocation(#20203,#20021) #20204=* -jsdoc_type_exprs(#20204,5,#20202,0,"number") -#20205=@"loc,{#10000},41,18,41,23" -locations_default(#20205,#10000,41,18,41,23) +jsdoc_tags(#20204,"typedef",#20203,0,"@typedef") +#20205=@"loc,{#10000},41,4,41,11" +locations_default(#20205,#10000,41,4,41,11) hasLocation(#20204,#20205) +#20206=* +jsdoc_type_exprs(#20206,9,#20204,0,"{0: number}") +#20207=@"loc,{#10000},41,14,41,24" +locations_default(#20207,#10000,41,14,41,24) +hasLocation(#20206,#20207) +jsdoc_record_field_name(#20206,0,"0") +#20208=* +jsdoc_type_exprs(#20208,5,#20206,0,"number") +#20209=@"loc,{#10000},41,18,41,23" +locations_default(#20209,#10000,41,18,41,23) +hasLocation(#20208,#20209) toplevels(#20001,0) -#20206=@"loc,{#10000},1,1,43,0" -locations_default(#20206,#10000,1,1,43,0) -hasLocation(#20001,#20206) -#20207=* -entry_cfg_node(#20207,#20001) -#20208=@"loc,{#10000},1,1,1,0" -locations_default(#20208,#10000,1,1,1,0) -hasLocation(#20207,#20208) -#20209=* -exit_cfg_node(#20209,#20001) -hasLocation(#20209,#20105) -successor(#20207,#20209) +#20210=@"loc,{#10000},1,1,43,0" +locations_default(#20210,#10000,1,1,43,0) +hasLocation(#20001,#20210) +#20211=* +entry_cfg_node(#20211,#20001) +#20212=@"loc,{#10000},1,1,1,0" +locations_default(#20212,#10000,1,1,1,0) +hasLocation(#20211,#20212) +#20213=* +exit_cfg_node(#20213,#20001) +hasLocation(#20213,#20105) +successor(#20211,#20213) numlines(#10000,42,0,37) filetype(#10000,"javascript") From 6868f661087209d5d42813f9d041364834098d55 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 20 Mar 2025 14:14:08 +0100 Subject: [PATCH 06/15] JS: Restrict size of hasNameParts Test updates look OK. Some intermediate results are omitted but the qualified name of the final type names are still present. --- javascript/ql/lib/semmle/javascript/JSDoc.qll | 1 + .../test/library-tests/JSDoc/NameResolution/test.expected | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/JSDoc.qll b/javascript/ql/lib/semmle/javascript/JSDoc.qll index 9ea517cb0757..10970a2e8b04 100644 --- a/javascript/ql/lib/semmle/javascript/JSDoc.qll +++ b/javascript/ql/lib/semmle/javascript/JSDoc.qll @@ -372,6 +372,7 @@ class JSDocNamedTypeExpr extends JSDocTypeExpr { * - `Baz` has prefix `Baz` and an empty suffix. */ predicate hasNameParts(string prefix, string suffix) { + not this = any(JSDocQualifiedTypeAccess a).getBase() and // restrict size of predicate exists(string regex, string name | regex = "([^.]+)(.*)" | name = this.getRawName() and prefix = name.regexpCapture(regex, 1) and diff --git a/javascript/ql/test/library-tests/JSDoc/NameResolution/test.expected b/javascript/ql/test/library-tests/JSDoc/NameResolution/test.expected index 855d1b59ff60..f57affb6367d 100644 --- a/javascript/ql/test/library-tests/JSDoc/NameResolution/test.expected +++ b/javascript/ql/test/library-tests/JSDoc/NameResolution/test.expected @@ -1,10 +1,10 @@ -| bar.js:5:14:5:18 | x | ns.very.long.namespace | +| bar.js:5:14:5:18 | x | x | | bar.js:5:14:5:18 | x.Foo | ns.very.long.namespace.Foo | -| bar.js:12:14:12:21 | iife | IIFE | +| bar.js:12:14:12:21 | iife | iife | | bar.js:12:14:12:21 | iife.Foo | IIFE.Foo | | closure.js:8:12:8:28 | goog | goog | | closure.js:8:12:8:28 | goog.net | goog.net | | closure.js:8:12:8:28 | goog.net.SomeType | goog.net.SomeType | -| closure.js:9:12:9:23 | net | goog.net | +| closure.js:9:12:9:23 | net | net | | closure.js:9:12:9:23 | net.SomeType | goog.net.SomeType | | closure.js:10:12:10:19 | SomeType | goog.net.SomeType | From cc2bec08084bd28cea64d51c4b02e2827c521954 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 21 Mar 2025 10:44:10 +0100 Subject: [PATCH 07/15] JS: Ensure correct value is used in parseNameExpression() The call to expect() below here updates 'token' and 'value' to that of the NEXT token (not the name). The code happened to work because the 'value' field is only updated if a token with a relevant value is found. E.g. if a name token could be followed by another name, then we would have seen the wrong name here. --- javascript/extractor/src/com/semmle/js/parser/JSDocParser.java | 1 + 1 file changed, 1 insertion(+) diff --git a/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java b/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java index e1b8b8b72ba8..21c26968adc6 100644 --- a/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java +++ b/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java @@ -829,6 +829,7 @@ private JSDocTypeExpression parseRecordType() throws ParseError { private JSDocTypeExpression parseNameExpression() throws ParseError { SourceLocation loc = loc(); + Object value = this.value; // save the value of the current token expect(Token.NAME); // Hacky initial implementation with wrong locations String[] parts = value.toString().split("\\."); From c8817d96679112c52d8fa22fbd03314f9619a108 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 21 Mar 2025 10:54:16 +0100 Subject: [PATCH 08/15] JS: Parse with proper locations --- .../src/com/semmle/js/parser/JSDocParser.java | 31 +-- .../tests/comments/output/trap/jsdoc.js.trap | 244 +++++++++--------- .../JSDoc/NameResolution/test.expected | 10 +- 3 files changed, 144 insertions(+), 141 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java b/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java index 21c26968adc6..f1b13565191e 100644 --- a/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java +++ b/javascript/extractor/src/com/semmle/js/parser/JSDocParser.java @@ -114,7 +114,7 @@ private static boolean isIdentifierPart(char ch) { } private static boolean isTypeName(char ch) { - return "><(){}[],:*|?!=".indexOf(ch) == -1 && !isWhiteSpace(ch) && !isLineTerminator(ch); + return "><(){}[],:*|?!=.".indexOf(ch) == -1 && !isWhiteSpace(ch) && !isLineTerminator(ch); } private static boolean isParamTitle(String title) { @@ -536,20 +536,9 @@ private Token scanNumber() throws ParseError { } private Token scanTypeName() { - char ch, ch2; - StringBuilder sb = new StringBuilder(); sb.append((char)advance()); while (index < endIndex && isTypeName(source.charAt(index))) { - ch = source.charAt(index); - if (ch == '.') { - if ((index + 1) < endIndex) { - ch2 = source.charAt(index + 1); - if (ch2 == '<') { - break; - } - } - } sb.append((char)advance()); } value = sb.toString(); @@ -827,15 +816,21 @@ private JSDocTypeExpression parseRecordType() throws ParseError { return finishNode(new RecordType(loc, fields)); } - private JSDocTypeExpression parseNameExpression() throws ParseError { + private Identifier parseIdentifier() throws ParseError { SourceLocation loc = loc(); Object value = this.value; // save the value of the current token expect(Token.NAME); - // Hacky initial implementation with wrong locations - String[] parts = value.toString().split("\\."); - JSDocTypeExpression node = finishNode(new Identifier(loc, parts[0])); - for (int i = 1; i < parts.length; i++) { - Identifier memberName = finishNode(new Identifier(loc, parts[i])); + return finishNode(new Identifier(loc, value.toString())); + } + + private JSDocTypeExpression parseNameExpression() throws ParseError { + JSDocTypeExpression node = parseIdentifier(); + while (token == Token.DOT) { + consume(Token.DOT); + Identifier memberName = parseIdentifier(); + // Create a SourceLocation object with the correct start location. + // The call to finishNode() will set the end location. + SourceLocation loc = new SourceLocation(node.getLoc()); node = finishNode(new QualifiedNameExpression(loc, node, memberName)); } return node; diff --git a/javascript/extractor/tests/comments/output/trap/jsdoc.js.trap b/javascript/extractor/tests/comments/output/trap/jsdoc.js.trap index b88a66b4f486..910c567993f3 100644 --- a/javascript/extractor/tests/comments/output/trap/jsdoc.js.trap +++ b/javascript/extractor/tests/comments/output/trap/jsdoc.js.trap @@ -523,156 +523,164 @@ locations_default(#20160,#10000,11,26,11,37) hasLocation(#20159,#20160) #20161=* jsdoc_type_exprs(#20161,15,#20159,0,"goog.ui") -hasLocation(#20161,#20160) -#20162=* -jsdoc_type_exprs(#20162,5,#20161,0,"goog") -hasLocation(#20162,#20160) +#20162=@"loc,{#10000},11,26,11,32" +locations_default(#20162,#10000,11,26,11,32) +hasLocation(#20161,#20162) #20163=* -jsdoc_type_exprs(#20163,5,#20161,1,"ui") -hasLocation(#20163,#20160) -#20164=* -jsdoc_type_exprs(#20164,5,#20159,1,"Menu") -hasLocation(#20164,#20160) -jsdoc_has_new_parameter(#20145) +jsdoc_type_exprs(#20163,5,#20161,0,"goog") +#20164=@"loc,{#10000},11,26,11,29" +locations_default(#20164,#10000,11,26,11,29) +hasLocation(#20163,#20164) #20165=* -jsdoc_tags(#20165,"param",#20117,4,"@param") -#20166=@"loc,{#10000},12,5,12,10" -locations_default(#20166,#10000,12,5,12,10) +jsdoc_type_exprs(#20165,5,#20161,1,"ui") +#20166=@"loc,{#10000},11,31,11,32" +locations_default(#20166,#10000,11,31,11,32) hasLocation(#20165,#20166) -jsdoc_tag_names(#20165,"var_args") #20167=* -jsdoc_type_exprs(#20167,14,#20165,0,"...number") -#20168=@"loc,{#10000},12,13,12,21" -locations_default(#20168,#10000,12,13,12,21) +jsdoc_type_exprs(#20167,5,#20159,1,"Menu") +#20168=@"loc,{#10000},11,34,11,37" +locations_default(#20168,#10000,11,34,11,37) hasLocation(#20167,#20168) +jsdoc_has_new_parameter(#20145) #20169=* -jsdoc_type_exprs(#20169,5,#20167,0,"number") -#20170=@"loc,{#10000},12,16,12,21" -locations_default(#20170,#10000,12,16,12,21) +jsdoc_tags(#20169,"param",#20117,4,"@param") +#20170=@"loc,{#10000},12,5,12,10" +locations_default(#20170,#10000,12,5,12,10) hasLocation(#20169,#20170) +jsdoc_tag_names(#20169,"var_args") #20171=* -jsdoc(#20171,"",#20010) -hasLocation(#20171,#20011) -#20172=* -jsdoc_tags(#20172,"param",#20171,0,"@param") -#20173=@"loc,{#10000},15,4,15,9" -locations_default(#20173,#10000,15,4,15,9) -hasLocation(#20172,#20173) -#20174=* -jsdoc_errors(#20174,#20172,"Missing or invalid tag name","Missing ... ag name") +jsdoc_type_exprs(#20171,14,#20169,0,"...number") +#20172=@"loc,{#10000},12,13,12,21" +locations_default(#20172,#10000,12,13,12,21) +hasLocation(#20171,#20172) +#20173=* +jsdoc_type_exprs(#20173,5,#20171,0,"number") +#20174=@"loc,{#10000},12,16,12,21" +locations_default(#20174,#10000,12,16,12,21) +hasLocation(#20173,#20174) #20175=* -jsdoc_tags(#20175,"param",#20171,1,"@param") -#20176=@"loc,{#10000},16,4,16,9" -locations_default(#20176,#10000,16,4,16,9) -hasLocation(#20175,#20176) -jsdoc_tag_names(#20175,"x") -#20177=* -jsdoc(#20177,"",#20012) -hasLocation(#20177,#20013) +jsdoc(#20175,"",#20010) +hasLocation(#20175,#20011) +#20176=* +jsdoc_tags(#20176,"param",#20175,0,"@param") +#20177=@"loc,{#10000},15,4,15,9" +locations_default(#20177,#10000,15,4,15,9) +hasLocation(#20176,#20177) #20178=* -jsdoc_tags(#20178,"",#20177,0,"@") -#20179=@"loc,{#10000},20,4,20,4" -locations_default(#20179,#10000,20,4,20,4) -hasLocation(#20178,#20179) -jsdoc_tag_descriptions(#20178,"{link a}") -#20180=* -jsdoc_errors(#20180,#20178,"Missing or invalid title","Missing ... d title") +jsdoc_errors(#20178,#20176,"Missing or invalid tag name","Missing ... ag name") +#20179=* +jsdoc_tags(#20179,"param",#20175,1,"@param") +#20180=@"loc,{#10000},16,4,16,9" +locations_default(#20180,#10000,16,4,16,9) +hasLocation(#20179,#20180) +jsdoc_tag_names(#20179,"x") #20181=* -jsdoc(#20181,"",#20014) -hasLocation(#20181,#20015) +jsdoc(#20181,"",#20012) +hasLocation(#20181,#20013) #20182=* -jsdoc_tags(#20182,"typedef",#20181,0,"@typedef") -#20183=@"loc,{#10000},24,4,24,11" -locations_default(#20183,#10000,24,4,24,11) +jsdoc_tags(#20182,"",#20181,0,"@") +#20183=@"loc,{#10000},20,4,20,4" +locations_default(#20183,#10000,20,4,20,4) hasLocation(#20182,#20183) -jsdoc_tag_descriptions(#20182,"{a}") +jsdoc_tag_descriptions(#20182,"{link a}") #20184=* -jsdoc_errors(#20184,#20182,"Missing or invalid tag type","Missing ... ag type") +jsdoc_errors(#20184,#20182,"Missing or invalid title","Missing ... d title") #20185=* -jsdoc(#20185,"[resize description]",#20016) -hasLocation(#20185,#20017) +jsdoc(#20185,"",#20014) +hasLocation(#20185,#20015) #20186=* -jsdoc_tags(#20186,"param",#20185,0,"@param") -#20187=@"loc,{#10000},30,4,30,9" -locations_default(#20187,#10000,30,4,30,9) +jsdoc_tags(#20186,"typedef",#20185,0,"@typedef") +#20187=@"loc,{#10000},24,4,24,11" +locations_default(#20187,#10000,24,4,24,11) hasLocation(#20186,#20187) -jsdoc_tag_descriptions(#20186,"[description] -") -jsdoc_tag_names(#20186,"w") +jsdoc_tag_descriptions(#20186,"{a}") #20188=* -jsdoc_type_exprs(#20188,10,#20186,0,"[type]") -#20189=@"loc,{#10000},30,13,30,18" -locations_default(#20189,#10000,30,13,30,18) -hasLocation(#20188,#20189) +jsdoc_errors(#20188,#20186,"Missing or invalid tag type","Missing ... ag type") +#20189=* +jsdoc(#20189,"[resize description]",#20016) +hasLocation(#20189,#20017) #20190=* -jsdoc_type_exprs(#20190,5,#20188,0,"type") -#20191=@"loc,{#10000},30,14,30,17" -locations_default(#20191,#10000,30,14,30,17) +jsdoc_tags(#20190,"param",#20189,0,"@param") +#20191=@"loc,{#10000},30,4,30,9" +locations_default(#20191,#10000,30,4,30,9) hasLocation(#20190,#20191) +jsdoc_tag_descriptions(#20190,"[description] +") +jsdoc_tag_names(#20190,"w") #20192=* -jsdoc_tags(#20192,"param",#20185,1,"@param") -#20193=@"loc,{#10000},31,4,31,9" -locations_default(#20193,#10000,31,4,31,9) +jsdoc_type_exprs(#20192,10,#20190,0,"[type]") +#20193=@"loc,{#10000},30,13,30,18" +locations_default(#20193,#10000,30,13,30,18) hasLocation(#20192,#20193) -jsdoc_tag_descriptions(#20192,"[description] -") #20194=* -jsdoc_tags(#20194,"return",#20185,2,"@return") -#20195=@"loc,{#10000},32,4,32,10" -locations_default(#20195,#10000,32,4,32,10) +jsdoc_type_exprs(#20194,5,#20192,0,"type") +#20195=@"loc,{#10000},30,14,30,17" +locations_default(#20195,#10000,30,14,30,17) hasLocation(#20194,#20195) -jsdoc_tag_descriptions(#20194,"[description]") #20196=* -jsdoc_type_exprs(#20196,10,#20194,0,"[type]") -#20197=@"loc,{#10000},32,13,32,18" -locations_default(#20197,#10000,32,13,32,18) +jsdoc_tags(#20196,"param",#20189,1,"@param") +#20197=@"loc,{#10000},31,4,31,9" +locations_default(#20197,#10000,31,4,31,9) hasLocation(#20196,#20197) +jsdoc_tag_descriptions(#20196,"[description] +") #20198=* -jsdoc_type_exprs(#20198,5,#20196,0,"type") -#20199=@"loc,{#10000},32,14,32,17" -locations_default(#20199,#10000,32,14,32,17) +jsdoc_tags(#20198,"return",#20189,2,"@return") +#20199=@"loc,{#10000},32,4,32,10" +locations_default(#20199,#10000,32,4,32,10) hasLocation(#20198,#20199) +jsdoc_tag_descriptions(#20198,"[description]") #20200=* -jsdoc(#20200,"",#20018) -hasLocation(#20200,#20019) -#20201=* -jsdoc_tags(#20201,"exports",#20200,0,"@exports") -#20202=@"loc,{#10000},36,3,36,10" -locations_default(#20202,#10000,36,3,36,10) -hasLocation(#20201,#20202) -jsdoc_tag_descriptions(#20201,"R -") -#20203=* -jsdoc(#20203,"",#20020) -hasLocation(#20203,#20021) +jsdoc_type_exprs(#20200,10,#20198,0,"[type]") +#20201=@"loc,{#10000},32,13,32,18" +locations_default(#20201,#10000,32,13,32,18) +hasLocation(#20200,#20201) +#20202=* +jsdoc_type_exprs(#20202,5,#20200,0,"type") +#20203=@"loc,{#10000},32,14,32,17" +locations_default(#20203,#10000,32,14,32,17) +hasLocation(#20202,#20203) #20204=* -jsdoc_tags(#20204,"typedef",#20203,0,"@typedef") -#20205=@"loc,{#10000},41,4,41,11" -locations_default(#20205,#10000,41,4,41,11) -hasLocation(#20204,#20205) -#20206=* -jsdoc_type_exprs(#20206,9,#20204,0,"{0: number}") -#20207=@"loc,{#10000},41,14,41,24" -locations_default(#20207,#10000,41,14,41,24) -hasLocation(#20206,#20207) -jsdoc_record_field_name(#20206,0,"0") +jsdoc(#20204,"",#20018) +hasLocation(#20204,#20019) +#20205=* +jsdoc_tags(#20205,"exports",#20204,0,"@exports") +#20206=@"loc,{#10000},36,3,36,10" +locations_default(#20206,#10000,36,3,36,10) +hasLocation(#20205,#20206) +jsdoc_tag_descriptions(#20205,"R +") +#20207=* +jsdoc(#20207,"",#20020) +hasLocation(#20207,#20021) #20208=* -jsdoc_type_exprs(#20208,5,#20206,0,"number") -#20209=@"loc,{#10000},41,18,41,23" -locations_default(#20209,#10000,41,18,41,23) +jsdoc_tags(#20208,"typedef",#20207,0,"@typedef") +#20209=@"loc,{#10000},41,4,41,11" +locations_default(#20209,#10000,41,4,41,11) hasLocation(#20208,#20209) +#20210=* +jsdoc_type_exprs(#20210,9,#20208,0,"{0: number}") +#20211=@"loc,{#10000},41,14,41,24" +locations_default(#20211,#10000,41,14,41,24) +hasLocation(#20210,#20211) +jsdoc_record_field_name(#20210,0,"0") +#20212=* +jsdoc_type_exprs(#20212,5,#20210,0,"number") +#20213=@"loc,{#10000},41,18,41,23" +locations_default(#20213,#10000,41,18,41,23) +hasLocation(#20212,#20213) toplevels(#20001,0) -#20210=@"loc,{#10000},1,1,43,0" -locations_default(#20210,#10000,1,1,43,0) -hasLocation(#20001,#20210) -#20211=* -entry_cfg_node(#20211,#20001) -#20212=@"loc,{#10000},1,1,1,0" -locations_default(#20212,#10000,1,1,1,0) -hasLocation(#20211,#20212) -#20213=* -exit_cfg_node(#20213,#20001) -hasLocation(#20213,#20105) -successor(#20211,#20213) +#20214=@"loc,{#10000},1,1,43,0" +locations_default(#20214,#10000,1,1,43,0) +hasLocation(#20001,#20214) +#20215=* +entry_cfg_node(#20215,#20001) +#20216=@"loc,{#10000},1,1,1,0" +locations_default(#20216,#10000,1,1,1,0) +hasLocation(#20215,#20216) +#20217=* +exit_cfg_node(#20217,#20001) +hasLocation(#20217,#20105) +successor(#20215,#20217) numlines(#10000,42,0,37) filetype(#10000,"javascript") diff --git a/javascript/ql/test/library-tests/JSDoc/NameResolution/test.expected b/javascript/ql/test/library-tests/JSDoc/NameResolution/test.expected index f57affb6367d..97730513195b 100644 --- a/javascript/ql/test/library-tests/JSDoc/NameResolution/test.expected +++ b/javascript/ql/test/library-tests/JSDoc/NameResolution/test.expected @@ -1,10 +1,10 @@ -| bar.js:5:14:5:18 | x | x | +| bar.js:5:14:5:14 | x | x | | bar.js:5:14:5:18 | x.Foo | ns.very.long.namespace.Foo | -| bar.js:12:14:12:21 | iife | iife | +| bar.js:12:14:12:17 | iife | iife | | bar.js:12:14:12:21 | iife.Foo | IIFE.Foo | -| closure.js:8:12:8:28 | goog | goog | -| closure.js:8:12:8:28 | goog.net | goog.net | +| closure.js:8:12:8:15 | goog | goog | +| closure.js:8:12:8:19 | goog.net | goog.net | | closure.js:8:12:8:28 | goog.net.SomeType | goog.net.SomeType | -| closure.js:9:12:9:23 | net | net | +| closure.js:9:12:9:14 | net | net | | closure.js:9:12:9:23 | net.SomeType | goog.net.SomeType | | closure.js:10:12:10:19 | SomeType | goog.net.SomeType | From 50202d574fa8ddb1f630bda123ddaebd798fbed3 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 21 Mar 2025 10:55:55 +0100 Subject: [PATCH 09/15] JS: Update some deprecated calls to getName() --- javascript/ql/lib/semmle/javascript/DOM.qll | 2 +- javascript/ql/lib/semmle/javascript/Externs.qll | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/DOM.qll b/javascript/ql/lib/semmle/javascript/DOM.qll index 6c6d70fede87..50a529b4a53a 100644 --- a/javascript/ql/lib/semmle/javascript/DOM.qll +++ b/javascript/ql/lib/semmle/javascript/DOM.qll @@ -296,7 +296,7 @@ module DOM { .getType() .getAnUnderlyingType() .(JSDocNamedTypeExpr) - .getName()) + .getRawName()) ) } diff --git a/javascript/ql/lib/semmle/javascript/Externs.qll b/javascript/ql/lib/semmle/javascript/Externs.qll index 9787de6f464b..a2a2533d8494 100644 --- a/javascript/ql/lib/semmle/javascript/Externs.qll +++ b/javascript/ql/lib/semmle/javascript/Externs.qll @@ -400,8 +400,8 @@ class ConstructorTag extends JSDocTag { abstract private class NamedTypeReferent extends JSDocTag { /** Gets the name of the type to which this tag refers. */ string getTarget() { - result = this.getType().(JSDocNamedTypeExpr).getName() or - result = this.getType().(JSDocAppliedTypeExpr).getHead().(JSDocNamedTypeExpr).getName() + result = this.getType().(JSDocNamedTypeExpr).getRawName() or + result = this.getType().(JSDocAppliedTypeExpr).getHead().(JSDocNamedTypeExpr).getRawName() } /** @@ -423,7 +423,7 @@ abstract private class NamedTypeReferent extends JSDocTag { * Gets the source declaration of the type to which `tp` refers, if any. */ private ExternalType sourceDecl(JSDocTypeExpr tp) { - result.getQualifiedName() = tp.(JSDocNamedTypeExpr).getName() or + result.getQualifiedName() = tp.(JSDocNamedTypeExpr).getRawName() or result = sourceDecl(tp.(JSDocAppliedTypeExpr).getHead()) or result = sourceDecl(tp.(JSDocNullableTypeExpr).getTypeExpr()) or result = sourceDecl(tp.(JSDocNonNullableTypeExpr).getTypeExpr()) or From da269c6fb1763b504124ae45132e478012dd3e7b Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 21 Mar 2025 11:12:27 +0100 Subject: [PATCH 10/15] JS: More test updates --- .../library-tests/JSDoc/Nodes/tests.expected | 28 +++++++++---------- .../JSDoc/JSDocTypeAnnotations.expected | 4 +-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/javascript/ql/test/library-tests/JSDoc/Nodes/tests.expected b/javascript/ql/test/library-tests/JSDoc/Nodes/tests.expected index 7ed69cb851f3..8c243f7a804a 100644 --- a/javascript/ql/test/library-tests/JSDoc/Nodes/tests.expected +++ b/javascript/ql/test/library-tests/JSDoc/Nodes/tests.expected @@ -278,11 +278,11 @@ test_JSDocTypeExpr | tst.js:26:14:26:20 | boolean | tst.js:26:5:26:11 | @define | 0 | | tst.js:31:13:31:19 | boolean | tst.js:31:4:31:10 | @return | 0 | | tst.js:53:11:53:16 | number | tst.js:53:4:53:8 | @enum | 0 | -| tst.js:68:14:68:34 | BasicNodeList | tst.js:68:14:68:34 | goog.ds.BasicNodeList | 1 | -| tst.js:68:14:68:34 | ds | tst.js:68:14:68:34 | goog.ds | 1 | -| tst.js:68:14:68:34 | goog | tst.js:68:14:68:34 | goog.ds | 0 | -| tst.js:68:14:68:34 | goog.ds | tst.js:68:14:68:34 | goog.ds.BasicNodeList | 0 | +| tst.js:68:14:68:17 | goog | tst.js:68:14:68:20 | goog.ds | 0 | +| tst.js:68:14:68:20 | goog.ds | tst.js:68:14:68:34 | goog.ds.BasicNodeList | 0 | | tst.js:68:14:68:34 | goog.ds.BasicNodeList | tst.js:68:4:68:11 | @extends | 0 | +| tst.js:68:19:68:20 | ds | tst.js:68:14:68:20 | goog.ds | 1 | +| tst.js:68:22:68:34 | BasicNodeList | tst.js:68:14:68:34 | goog.ds.BasicNodeList | 1 | | tst.js:95:17:95:21 | Shape | tst.js:95:4:95:14 | @implements | 0 | | tst.js:110:14:110:18 | Shape | tst.js:110:4:110:11 | @extends | 0 | | tst.js:134:13:134:18 | Object | tst.js:134:4:134:10 | @return | 0 | @@ -302,9 +302,9 @@ test_JSDocTypeExpr | tst.js:216:15:216:29 | (string\|number) | tst.js:216:5:216:12 | @typedef | 0 | | tst.js:216:16:216:21 | string | tst.js:216:15:216:29 | (string\|number) | 0 | | tst.js:216:23:216:28 | number | tst.js:216:15:216:29 | (string\|number) | 1 | -| tst.js:219:13:219:27 | NumberLike | tst.js:219:13:219:27 | goog.NumberLike | 1 | -| tst.js:219:13:219:27 | goog | tst.js:219:13:219:27 | goog.NumberLike | 0 | +| tst.js:219:13:219:16 | goog | tst.js:219:13:219:27 | goog.NumberLike | 0 | | tst.js:219:13:219:27 | goog.NumberLike | tst.js:219:5:219:10 | @param | 0 | +| tst.js:219:18:219:27 | NumberLike | tst.js:219:13:219:27 | goog.NumberLike | 1 | | tst.js:223:12:223:36 | {myNum: number, myObject} | tst.js:223:5:223:9 | @type | 0 | | tst.js:223:20:223:25 | number | tst.js:223:12:223:36 | {myNum: number, myObject} | 0 | | tst.js:226:12:226:17 | number | tst.js:226:12:226:18 | number? | 0 | @@ -317,18 +317,18 @@ test_JSDocTypeExpr | tst.js:234:12:234:29 | function (): number | tst.js:234:4:234:9 | @param | 0 | | tst.js:234:24:234:29 | number | tst.js:234:12:234:29 | function (): number | -1 | | tst.js:235:12:235:46 | function (this: goog.ui.Menu, string) | tst.js:235:4:235:9 | @param | 0 | -| tst.js:235:26:235:37 | Menu | tst.js:235:26:235:37 | goog.ui.Menu | 1 | -| tst.js:235:26:235:37 | goog | tst.js:235:26:235:37 | goog.ui | 0 | -| tst.js:235:26:235:37 | goog.ui | tst.js:235:26:235:37 | goog.ui.Menu | 0 | +| tst.js:235:26:235:29 | goog | tst.js:235:26:235:32 | goog.ui | 0 | +| tst.js:235:26:235:32 | goog.ui | tst.js:235:26:235:37 | goog.ui.Menu | 0 | | tst.js:235:26:235:37 | goog.ui.Menu | tst.js:235:12:235:46 | function (this: goog.ui.Menu, string) | -2 | -| tst.js:235:26:235:37 | ui | tst.js:235:26:235:37 | goog.ui | 1 | +| tst.js:235:31:235:32 | ui | tst.js:235:26:235:32 | goog.ui | 1 | +| tst.js:235:34:235:37 | Menu | tst.js:235:26:235:37 | goog.ui.Menu | 1 | | tst.js:235:40:235:45 | string | tst.js:235:12:235:46 | function (this: goog.ui.Menu, string) | 0 | | tst.js:236:12:236:45 | function (new: goog.ui.Menu, string) | tst.js:236:4:236:9 | @param | 0 | -| tst.js:236:25:236:36 | Menu | tst.js:236:25:236:36 | goog.ui.Menu | 1 | -| tst.js:236:25:236:36 | goog | tst.js:236:25:236:36 | goog.ui | 0 | -| tst.js:236:25:236:36 | goog.ui | tst.js:236:25:236:36 | goog.ui.Menu | 0 | +| tst.js:236:25:236:28 | goog | tst.js:236:25:236:31 | goog.ui | 0 | +| tst.js:236:25:236:31 | goog.ui | tst.js:236:25:236:36 | goog.ui.Menu | 0 | | tst.js:236:25:236:36 | goog.ui.Menu | tst.js:236:12:236:45 | function (new: goog.ui.Menu, string) | -2 | -| tst.js:236:25:236:36 | ui | tst.js:236:25:236:36 | goog.ui | 1 | +| tst.js:236:30:236:31 | ui | tst.js:236:25:236:31 | goog.ui | 1 | +| tst.js:236:33:236:36 | Menu | tst.js:236:25:236:36 | goog.ui.Menu | 1 | | tst.js:236:39:236:44 | string | tst.js:236:12:236:45 | function (new: goog.ui.Menu, string) | 0 | | tst.js:237:12:237:48 | function (string, ...[number]): number | tst.js:237:4:237:9 | @param | 0 | | tst.js:237:21:237:26 | string | tst.js:237:12:237:48 | function (string, ...[number]): number | 0 | diff --git a/javascript/ql/test/library-tests/TypeAnnotations/JSDoc/JSDocTypeAnnotations.expected b/javascript/ql/test/library-tests/TypeAnnotations/JSDoc/JSDocTypeAnnotations.expected index 983388d69a22..8ac3eea2be5f 100644 --- a/javascript/ql/test/library-tests/TypeAnnotations/JSDoc/JSDocTypeAnnotations.expected +++ b/javascript/ql/test/library-tests/TypeAnnotations/JSDoc/JSDocTypeAnnotations.expected @@ -5,8 +5,8 @@ test_isNumber test_QualifiedName | VarType | tst.js:9:13:9:19 | VarType | | boolean | tst.js:5:14:5:20 | boolean | -| foo | tst.js:4:12:4:22 | foo | -| foo.bar | tst.js:4:12:4:22 | foo.bar | +| foo | tst.js:4:12:4:14 | foo | +| foo.bar | tst.js:4:12:4:18 | foo.bar | | foo.bar.baz | tst.js:4:12:4:22 | foo.bar.baz | | number | tst.js:3:12:3:17 | number | | string | tst.js:2:12:2:17 | string | From 02ee8cfe2d510a8e1704eeefdb1338ac397db2b5 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 24 Mar 2025 09:21:54 +0100 Subject: [PATCH 11/15] JS: Add upgrade script --- .../old.dbscheme | 1193 ++++++++++++++++ .../semmlecode.javascript.dbscheme | 1194 +++++++++++++++++ .../upgrade.properties | 2 + 3 files changed, 2389 insertions(+) create mode 100644 javascript/ql/lib/upgrades/5b5db607d20c7b449cef2d1c926b24d77c69bebb/old.dbscheme create mode 100644 javascript/ql/lib/upgrades/5b5db607d20c7b449cef2d1c926b24d77c69bebb/semmlecode.javascript.dbscheme create mode 100644 javascript/ql/lib/upgrades/5b5db607d20c7b449cef2d1c926b24d77c69bebb/upgrade.properties diff --git a/javascript/ql/lib/upgrades/5b5db607d20c7b449cef2d1c926b24d77c69bebb/old.dbscheme b/javascript/ql/lib/upgrades/5b5db607d20c7b449cef2d1c926b24d77c69bebb/old.dbscheme new file mode 100644 index 000000000000..5b5db607d20c --- /dev/null +++ b/javascript/ql/lib/upgrades/5b5db607d20c7b449cef2d1c926b24d77c69bebb/old.dbscheme @@ -0,0 +1,1193 @@ +/*** Standard fragments ***/ + +/*- Files and folders -*/ + +/** + * The location of an element. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +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 +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @file | @folder + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/*- Lines of code -*/ + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +/*- External data -*/ + +/** + * External data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/*- Source location prefix -*/ + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/*- JavaScript-specific part -*/ + +@location = @location_default + +@sourceline = @locatable; + +filetype( + int file: @file ref, + string filetype: string ref +) + +// top-level code fragments +toplevels (unique int id: @toplevel, + int kind: int ref); + +is_externs (int toplevel: @toplevel ref); + +case @toplevel.kind of + 0 = @script +| 1 = @inline_script +| 2 = @event_handler +| 3 = @javascript_url +| 4 = @template_toplevel; + +is_module (int tl: @toplevel ref); +is_nodejs (int tl: @toplevel ref); +is_es2015_module (int tl: @toplevel ref); +is_closure_module (int tl: @toplevel ref); + +@xml_node_with_code = @xmlelement | @xmlattribute | @template_placeholder_tag; +toplevel_parent_xml_node( + unique int toplevel: @toplevel ref, + int xmlnode: @xml_node_with_code ref); + +xml_element_parent_expression( + unique int xmlnode: @xmlelement ref, + int expression: @expr ref, + int index: int ref); + +// statements +#keyset[parent, idx] +stmts (unique int id: @stmt, + int kind: int 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); + +@stmt_parent = @stmt | @toplevel | @function_expr | @arrow_function_expr | @static_initializer; +@stmt_container = @toplevel | @function | @namespace_declaration | @external_module_declaration | @global_augmentation_declaration; + +case @stmt.kind of + 0 = @empty_stmt +| 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @labeled_stmt +| 5 = @break_stmt +| 6 = @continue_stmt +| 7 = @with_stmt +| 8 = @switch_stmt +| 9 = @return_stmt +| 10 = @throw_stmt +| 11 = @try_stmt +| 12 = @while_stmt +| 13 = @do_while_stmt +| 14 = @for_stmt +| 15 = @for_in_stmt +| 16 = @debugger_stmt +| 17 = @function_decl_stmt +| 18 = @var_decl_stmt +| 19 = @case +| 20 = @catch_clause +| 21 = @for_of_stmt +| 22 = @const_decl_stmt +| 23 = @let_stmt +| 24 = @legacy_let_stmt +| 25 = @for_each_stmt +| 26 = @class_decl_stmt +| 27 = @import_declaration +| 28 = @export_all_declaration +| 29 = @export_default_declaration +| 30 = @export_named_declaration +| 31 = @namespace_declaration +| 32 = @import_equals_declaration +| 33 = @export_assign_declaration +| 34 = @interface_declaration +| 35 = @type_alias_declaration +| 36 = @enum_declaration +| 37 = @external_module_declaration +| 38 = @export_as_namespace_declaration +| 39 = @global_augmentation_declaration +| 40 = @using_decl_stmt +; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @let_stmt | @legacy_let_stmt | @using_decl_stmt; + +@export_declaration = @export_all_declaration | @export_default_declaration | @export_named_declaration; + +@namespace_definition = @namespace_declaration | @enum_declaration; +@type_definition = @class_definition | @interface_declaration | @enum_declaration | @type_alias_declaration | @enum_member; + +is_instantiated(unique int decl: @namespace_declaration ref); + +@declarable_node = @decl_stmt | @namespace_declaration | @class_decl_stmt | @function_decl_stmt | @enum_declaration | @external_module_declaration | @global_augmentation_declaration | @field; +has_declare_keyword(unique int stmt: @declarable_node ref); + +is_for_await_of(unique int forof: @for_of_stmt ref); + +// expressions +#keyset[parent, idx] +exprs (unique int id: @expr, + int kind: int ref, + int parent: @expr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +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); + +expr_containers (unique int expr: @expr_or_type ref, + int container: @stmt_container ref); + +array_size (unique int ae: @arraylike ref, + int sz: int ref); + +is_delegating (int yield: @yield_expr ref); + +@expr_or_stmt = @expr | @stmt; +@expr_or_type = @expr | @typeexpr; +@expr_parent = @expr_or_stmt | @property | @function_typeexpr; +@arraylike = @array_expr | @array_pattern; +@type_annotation = @typeexpr | @jsdoc_type_expr; +@node_in_stmt_container = @cfg_node | @type_annotation | @toplevel; + +case @expr.kind of + 0 = @label +| 1 = @null_literal +| 2 = @boolean_literal +| 3 = @number_literal +| 4 = @string_literal +| 5 = @regexp_literal +| 6 = @this_expr +| 7 = @array_expr +| 8 = @obj_expr +| 9 = @function_expr +| 10 = @seq_expr +| 11 = @conditional_expr +| 12 = @new_expr +| 13 = @call_expr +| 14 = @dot_expr +| 15 = @index_expr +| 16 = @neg_expr +| 17 = @plus_expr +| 18 = @log_not_expr +| 19 = @bit_not_expr +| 20 = @typeof_expr +| 21 = @void_expr +| 22 = @delete_expr +| 23 = @eq_expr +| 24 = @neq_expr +| 25 = @eqq_expr +| 26 = @neqq_expr +| 27 = @lt_expr +| 28 = @le_expr +| 29 = @gt_expr +| 30 = @ge_expr +| 31 = @lshift_expr +| 32 = @rshift_expr +| 33 = @urshift_expr +| 34 = @add_expr +| 35 = @sub_expr +| 36 = @mul_expr +| 37 = @div_expr +| 38 = @mod_expr +| 39 = @bitor_expr +| 40 = @xor_expr +| 41 = @bitand_expr +| 42 = @in_expr +| 43 = @instanceof_expr +| 44 = @logand_expr +| 45 = @logor_expr +| 47 = @assign_expr +| 48 = @assign_add_expr +| 49 = @assign_sub_expr +| 50 = @assign_mul_expr +| 51 = @assign_div_expr +| 52 = @assign_mod_expr +| 53 = @assign_lshift_expr +| 54 = @assign_rshift_expr +| 55 = @assign_urshift_expr +| 56 = @assign_or_expr +| 57 = @assign_xor_expr +| 58 = @assign_and_expr +| 59 = @preinc_expr +| 60 = @postinc_expr +| 61 = @predec_expr +| 62 = @postdec_expr +| 63 = @par_expr +| 64 = @var_declarator +| 65 = @arrow_function_expr +| 66 = @spread_element +| 67 = @array_pattern +| 68 = @object_pattern +| 69 = @yield_expr +| 70 = @tagged_template_expr +| 71 = @template_literal +| 72 = @template_element +| 73 = @array_comprehension_expr +| 74 = @generator_expr +| 75 = @for_in_comprehension_block +| 76 = @for_of_comprehension_block +| 77 = @legacy_letexpr +| 78 = @var_decl +| 79 = @proper_varaccess +| 80 = @class_expr +| 81 = @super_expr +| 82 = @newtarget_expr +| 83 = @named_import_specifier +| 84 = @import_default_specifier +| 85 = @import_namespace_specifier +| 86 = @named_export_specifier +| 87 = @exp_expr +| 88 = @assign_exp_expr +| 89 = @jsx_element +| 90 = @jsx_qualified_name +| 91 = @jsx_empty_expr +| 92 = @await_expr +| 93 = @function_sent_expr +| 94 = @decorator +| 95 = @export_default_specifier +| 96 = @export_namespace_specifier +| 97 = @bind_expr +| 98 = @external_module_reference +| 99 = @dynamic_import +| 100 = @expression_with_type_arguments +| 101 = @prefix_type_assertion +| 102 = @as_type_assertion +| 103 = @export_varaccess +| 104 = @decorator_list +| 105 = @non_null_assertion +| 106 = @bigint_literal +| 107 = @nullishcoalescing_expr +| 108 = @e4x_xml_anyname +| 109 = @e4x_xml_static_attribute_selector +| 110 = @e4x_xml_dynamic_attribute_selector +| 111 = @e4x_xml_filter_expression +| 112 = @e4x_xml_static_qualident +| 113 = @e4x_xml_dynamic_qualident +| 114 = @e4x_xml_dotdotexpr +| 115 = @import_meta_expr +| 116 = @assignlogandexpr +| 117 = @assignlogorexpr +| 118 = @assignnullishcoalescingexpr +| 119 = @template_pipe_ref +| 120 = @generated_code_expr +| 121 = @satisfies_expr +; + +@varaccess = @proper_varaccess | @export_varaccess; +@varref = @var_decl | @varaccess; + +@identifier = @label | @varref | @type_identifier; + +@literal = @null_literal | @boolean_literal | @number_literal | @string_literal | @regexp_literal | @bigint_literal; + +@propaccess = @dot_expr | @index_expr; + +@invokeexpr = @new_expr | @call_expr; + +@unaryexpr = @neg_expr | @plus_expr | @log_not_expr | @bit_not_expr | @typeof_expr | @void_expr | @delete_expr | @spread_element; + +@equality_test = @eq_expr | @neq_expr | @eqq_expr | @neqq_expr; + +@comparison = @equality_test | @lt_expr | @le_expr | @gt_expr | @ge_expr; + +@binaryexpr = @comparison | @lshift_expr | @rshift_expr | @urshift_expr | @add_expr | @sub_expr | @mul_expr | @div_expr | @mod_expr | @exp_expr | @bitor_expr | @xor_expr | @bitand_expr | @in_expr | @instanceof_expr | @logand_expr | @logor_expr | @nullishcoalescing_expr; + +@assignment = @assign_expr | @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr | @assign_mod_expr | @assign_exp_expr | @assign_lshift_expr | @assign_rshift_expr | @assign_urshift_expr | @assign_or_expr | @assign_xor_expr | @assign_and_expr | @assignlogandexpr | @assignlogorexpr | @assignnullishcoalescingexpr; + +@updateexpr = @preinc_expr | @postinc_expr | @predec_expr | @postdec_expr; + +@pattern = @varref | @array_pattern | @object_pattern; + +@comprehension_expr = @array_comprehension_expr | @generator_expr; + +@comprehension_block = @for_in_comprehension_block | @for_of_comprehension_block; + +@import_specifier = @named_import_specifier | @import_default_specifier | @import_namespace_specifier; + +@exportspecifier = @named_export_specifier | @export_default_specifier | @export_namespace_specifier; + +@type_keyword_operand = @import_declaration | @export_declaration | @import_specifier; + +@type_assertion = @as_type_assertion | @prefix_type_assertion; + +@class_definition = @class_decl_stmt | @class_expr; +@interface_definition = @interface_declaration | @interface_typeexpr; +@class_or_interface = @class_definition | @interface_definition; + +@lexical_decl = @var_decl | @type_decl; +@lexical_access = @varaccess | @local_type_access | @local_var_type_access | @local_namespace_access; +@lexical_ref = @lexical_decl | @lexical_access; + +@e4x_xml_attribute_selector = @e4x_xml_static_attribute_selector | @e4x_xml_dynamic_attribute_selector; +@e4x_xml_qualident = @e4x_xml_static_qualident | @e4x_xml_dynamic_qualident; + +expr_contains_template_tag_location( + int expr: @expr ref, + int location: @location ref +); + +@template_placeholder_tag_parent = @xmlelement | @xmlattribute | @file; + +template_placeholder_tag_info( + unique int node: @template_placeholder_tag, + int parentNode: @template_placeholder_tag_parent ref, + varchar(900) raw: string ref +); + +// scopes +scopes (unique int id: @scope, + int kind: int ref); + +case @scope.kind of + 0 = @global_scope +| 1 = @function_scope +| 2 = @catch_scope +| 3 = @module_scope +| 4 = @block_scope +| 5 = @for_scope +| 6 = @for_in_scope // for-of scopes work the same as for-in scopes +| 7 = @comprehension_block_scope +| 8 = @class_expr_scope +| 9 = @namespace_scope +| 10 = @class_decl_scope +| 11 = @interface_scope +| 12 = @type_alias_scope +| 13 = @mapped_type_scope +| 14 = @enum_scope +| 15 = @external_module_scope +| 16 = @conditional_type_scope; + +scopenodes (unique int node: @ast_node ref, + int scope: @scope ref); + +scopenesting (unique int inner: @scope ref, + int outer: @scope ref); + +// functions +@function = @function_decl_stmt | @function_expr | @arrow_function_expr; + +@parameterized = @function | @catch_clause; +@type_parameterized = @function | @class_or_interface | @type_alias_declaration | @mapped_typeexpr | @infer_typeexpr; + +is_generator (int fun: @function ref); +has_rest_parameter (int fun: @function ref); +is_async (int fun: @function ref); + +// variables and lexically scoped type names +#keyset[scope, name] +variables (unique int id: @variable, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_type_names (unique int id: @local_type_name, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_namespace_names (unique int id: @local_namespace_name, + varchar(900) name: string ref, + int scope: @scope ref); + +is_arguments_object (int id: @variable ref); + +@lexical_name = @variable | @local_type_name | @local_namespace_name; + +@bind_id = @varaccess | @local_var_type_access; +bind (unique int id: @bind_id ref, + int decl: @variable ref); + +decl (unique int id: @var_decl ref, + int decl: @variable ref); + +@typebind_id = @local_type_access | @export_varaccess; +typebind (unique int id: @typebind_id ref, + int decl: @local_type_name ref); + +@typedecl_id = @type_decl | @var_decl; +typedecl (unique int id: @typedecl_id ref, + int decl: @local_type_name ref); + +namespacedecl (unique int id: @var_decl ref, + int decl: @local_namespace_name ref); + +@namespacebind_id = @local_namespace_access | @export_varaccess; +namespacebind (unique int id: @namespacebind_id ref, + int decl: @local_namespace_name ref); + + +// properties in object literals, property patterns in object patterns, and method declarations in classes +#keyset[parent, index] +properties (unique int id: @property, + int parent: @property_parent ref, + int index: int ref, + int kind: int ref, + varchar(900) tostring: string ref); + +case @property.kind of + 0 = @value_property +| 1 = @property_getter +| 2 = @property_setter +| 3 = @jsx_attribute +| 4 = @function_call_signature +| 5 = @constructor_call_signature +| 6 = @index_signature +| 7 = @enum_member +| 8 = @proper_field +| 9 = @parameter_field +| 10 = @static_initializer +; + +@property_parent = @obj_expr | @object_pattern | @class_definition | @jsx_element | @interface_definition | @enum_declaration; +@property_accessor = @property_getter | @property_setter; +@call_signature = @function_call_signature | @constructor_call_signature; +@field = @proper_field | @parameter_field; +@field_or_vardeclarator = @field | @var_declarator; + +is_computed (int id: @property ref); +is_method (int id: @property ref); +is_static (int id: @property ref); +is_abstract_member (int id: @property ref); +is_const_enum (int id: @enum_declaration ref); +is_abstract_class (int id: @class_decl_stmt ref); + +has_public_keyword (int id: @property ref); +has_private_keyword (int id: @property ref); +has_protected_keyword (int id: @property ref); +has_readonly_keyword (int id: @property ref); +has_type_keyword (int id: @type_keyword_operand ref); +is_optional_member (int id: @property ref); +has_definite_assignment_assertion (int id: @field_or_vardeclarator ref); +is_optional_parameter_declaration (unique int parameter: @pattern ref); + +#keyset[constructor, param_index] +parameter_fields( + unique int field: @parameter_field ref, + int constructor: @function_expr ref, + int param_index: int ref +); + +// types +#keyset[parent, idx] +typeexprs ( + unique int id: @typeexpr, + int kind: int ref, + int parent: @typeexpr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref +); + +case @typeexpr.kind of + 0 = @local_type_access +| 1 = @type_decl +| 2 = @keyword_typeexpr +| 3 = @string_literal_typeexpr +| 4 = @number_literal_typeexpr +| 5 = @boolean_literal_typeexpr +| 6 = @array_typeexpr +| 7 = @union_typeexpr +| 8 = @indexed_access_typeexpr +| 9 = @intersection_typeexpr +| 10 = @parenthesized_typeexpr +| 11 = @tuple_typeexpr +| 12 = @keyof_typeexpr +| 13 = @qualified_type_access +| 14 = @generic_typeexpr +| 15 = @type_label +| 16 = @typeof_typeexpr +| 17 = @local_var_type_access +| 18 = @qualified_var_type_access +| 19 = @this_var_type_access +| 20 = @predicate_typeexpr +| 21 = @interface_typeexpr +| 22 = @type_parameter +| 23 = @plain_function_typeexpr +| 24 = @constructor_typeexpr +| 25 = @local_namespace_access +| 26 = @qualified_namespace_access +| 27 = @mapped_typeexpr +| 28 = @conditional_typeexpr +| 29 = @infer_typeexpr +| 30 = @import_type_access +| 31 = @import_namespace_access +| 32 = @import_var_type_access +| 33 = @optional_typeexpr +| 34 = @rest_typeexpr +| 35 = @bigint_literal_typeexpr +| 36 = @readonly_typeexpr +| 37 = @template_literal_typeexpr +; + +@typeref = @typeaccess | @type_decl; +@type_identifier = @type_decl | @local_type_access | @type_label | @local_var_type_access | @local_namespace_access; +@typeexpr_parent = @expr | @stmt | @property | @typeexpr; +@literal_typeexpr = @string_literal_typeexpr | @number_literal_typeexpr | @boolean_literal_typeexpr | @bigint_literal_typeexpr; +@typeaccess = @local_type_access | @qualified_type_access | @import_type_access; +@vartypeaccess = @local_var_type_access | @qualified_var_type_access | @this_var_type_access | @import_var_type_access; +@namespace_access = @local_namespace_access | @qualified_namespace_access | @import_namespace_access; +@import_typeexpr = @import_type_access | @import_namespace_access | @import_var_type_access; + +@function_typeexpr = @plain_function_typeexpr | @constructor_typeexpr; + +// types +types ( + unique int id: @type, + int kind: int ref, + varchar(900) tostring: string ref +); + +#keyset[parent, idx] +type_child ( + int child: @type ref, + int parent: @type ref, + int idx: int ref +); + +case @type.kind of + 0 = @any_type +| 1 = @string_type +| 2 = @number_type +| 3 = @union_type +| 4 = @true_type +| 5 = @false_type +| 6 = @type_reference +| 7 = @object_type +| 8 = @canonical_type_variable_type +| 9 = @typeof_type +| 10 = @void_type +| 11 = @undefined_type +| 12 = @null_type +| 13 = @never_type +| 14 = @plain_symbol_type +| 15 = @unique_symbol_type +| 16 = @objectkeyword_type +| 17 = @intersection_type +| 18 = @tuple_type +| 19 = @lexical_type_variable_type +| 20 = @this_type +| 21 = @number_literal_type +| 22 = @string_literal_type +| 23 = @unknown_type +| 24 = @bigint_type +| 25 = @bigint_literal_type +; + +@boolean_literal_type = @true_type | @false_type; +@symbol_type = @plain_symbol_type | @unique_symbol_type; +@union_or_intersection_type = @union_type | @intersection_type; +@typevariable_type = @canonical_type_variable_type | @lexical_type_variable_type; + +has_asserts_keyword(int node: @predicate_typeexpr ref); + +@typed_ast_node = @expr | @typeexpr | @function; +ast_node_type( + unique int node: @typed_ast_node ref, + int typ: @type ref); + +declared_function_signature( + unique int node: @function ref, + int sig: @signature_type ref +); + +invoke_expr_signature( + unique int node: @invokeexpr ref, + int sig: @signature_type ref +); + +invoke_expr_overload_index( + unique int node: @invokeexpr ref, + int index: int ref +); + +symbols ( + unique int id: @symbol, + int kind: int ref, + varchar(900) name: string ref +); + +symbol_parent ( + unique int symbol: @symbol ref, + int parent: @symbol ref +); + +symbol_module ( + int symbol: @symbol ref, + varchar(900) moduleName: string ref +); + +symbol_global ( + int symbol: @symbol ref, + varchar(900) globalName: string ref +); + +case @symbol.kind of + 0 = @root_symbol +| 1 = @member_symbol +| 2 = @other_symbol +; + +@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 | @external_module_declaration; + +ast_node_symbol( + unique int node: @ast_node_with_symbol ref, + int symbol: @symbol ref); + +type_symbol( + unique int typ: @type_with_symbol ref, + int symbol: @symbol ref); + +#keyset[typ, name] +type_property( + int typ: @type ref, + varchar(900) name: string ref, + int propertyType: @type ref); + +type_alias( + unique int aliasType: @type ref, + int underlyingType: @type ref); + +@literal_type = @string_literal_type | @number_literal_type | @boolean_literal_type | @bigint_literal_type; +@type_with_literal_value = @string_literal_type | @number_literal_type | @bigint_literal_type; +type_literal_value( + unique int typ: @type_with_literal_value ref, + varchar(900) value: string ref); + +signature_types ( + unique int id: @signature_type, + int kind: int ref, + varchar(900) tostring: string ref, + int type_parameters: int ref, + int required_params: int ref +); + +is_abstract_signature( + unique int sig: @signature_type ref +); + +signature_rest_parameter( + unique int sig: @signature_type ref, + int rest_param_arra_type: @type ref +); + +case @signature_type.kind of + 0 = @function_signature_type +| 1 = @constructor_signature_type +; + +#keyset[typ, kind, index] +type_contains_signature ( + int typ: @type ref, + int kind: int ref, // constructor/call/index + int index: int ref, // ordering of overloaded signatures + int sig: @signature_type ref +); + +#keyset[parent, index] +signature_contains_type ( + int child: @type ref, + int parent: @signature_type ref, + int index: int ref +); + +#keyset[sig, index] +signature_parameter_name ( + int sig: @signature_type ref, + int index: int ref, + varchar(900) name: string ref +); + +number_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +string_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +base_type_names( + int typeName: @symbol ref, + int baseTypeName: @symbol ref +); + +self_types( + int typeName: @symbol ref, + int selfType: @type_reference ref +); + +tuple_type_min_length( + unique int typ: @type ref, + int minLength: int ref +); + +tuple_type_rest_index( + unique int typ: @type ref, + int index: int ref +); + +// comments +comments (unique int id: @comment, + int kind: int ref, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(900) tostring: string ref); + +case @comment.kind of + 0 = @slashslash_comment +| 1 = @slashstar_comment +| 2 = @doc_comment +| 3 = @html_comment_start +| 4 = @htmlcommentend; + +@html_comment = @html_comment_start | @htmlcommentend; +@line_comment = @slashslash_comment | @html_comment; +@block_comment = @slashstar_comment | @doc_comment; + +// source lines +lines (unique int id: @line, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(2) terminator: string ref); +indentation (int file: @file ref, + int lineno: int ref, + varchar(1) indentChar: string ref, + int indentDepth: int ref); + +// JavaScript parse errors +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 + 0 = @regexp_alt +| 1 = @regexp_seq +| 2 = @regexp_caret +| 3 = @regexp_dollar +| 4 = @regexp_wordboundary +| 5 = @regexp_nonwordboundary +| 6 = @regexp_positive_lookahead +| 7 = @regexp_negative_lookahead +| 8 = @regexp_star +| 9 = @regexp_plus +| 10 = @regexp_opt +| 11 = @regexp_range +| 12 = @regexp_dot +| 13 = @regexp_group +| 14 = @regexp_normal_constant +| 15 = @regexp_hex_escape +| 16 = @regexp_unicode_escape +| 17 = @regexp_dec_escape +| 18 = @regexp_oct_escape +| 19 = @regexp_ctrl_escape +| 20 = @regexp_char_class_escape +| 21 = @regexp_id_escape +| 22 = @regexp_backref +| 23 = @regexp_char_class +| 24 = @regexp_char_range +| 25 = @regexp_positive_lookbehind +| 26 = @regexp_negative_lookbehind +| 27 = @regexp_unicode_property_escape +| 28 = @regexp_quoted_string +| 29 = @regexp_intersection +| 30 = @regexp_subtraction; + +regexp_parse_errors (unique int id: @regexp_parse_error, + int regexp: @regexpterm ref, + varchar(900) message: string ref); + +@regexp_quantifier = @regexp_star | @regexp_plus | @regexp_opt | @regexp_range; +@regexp_escape = @regexp_char_escape | @regexp_char_class_escape | @regexp_unicode_property_escape; +@regexp_char_escape = @regexp_hex_escape | @regexp_unicode_escape | @regexp_dec_escape | @regexp_oct_escape | @regexp_ctrl_escape | @regexp_id_escape; +@regexp_constant = @regexp_normal_constant | @regexp_char_escape; +@regexp_lookahead = @regexp_positive_lookahead | @regexp_negative_lookahead; +@regexp_lookbehind = @regexp_positive_lookbehind | @regexp_negative_lookbehind; +@regexp_subpattern = @regexp_lookahead | @regexp_lookbehind; +@regexp_anchor = @regexp_dollar | @regexp_caret; + +is_greedy (int id: @regexp_quantifier ref); +range_quantifier_lower_bound (unique int id: @regexp_range ref, int lo: int ref); +range_quantifier_upper_bound (unique int id: @regexp_range ref, int hi: int ref); +is_capture (unique int id: @regexp_group ref, int number: int ref); +is_named_capture (unique int id: @regexp_group ref, string name: string ref); +is_inverted (int id: @regexp_char_class ref); +regexp_const_value (unique int id: @regexp_constant ref, varchar(1) value: string ref); +char_class_escape (unique int id: @regexp_char_class_escape ref, varchar(1) value: string ref); +backref (unique int id: @regexp_backref ref, int value: int ref); +named_backref (unique int id: @regexp_backref ref, string name: string ref); +unicode_property_escapename (unique int id: @regexp_unicode_property_escape ref, string name: string ref); +unicode_property_escapevalue (unique int id: @regexp_unicode_property_escape ref, string value: string ref); + +// tokens +#keyset[toplevel, idx] +tokeninfo (unique int id: @token, + int kind: int ref, + int toplevel: @toplevel ref, + int idx: int ref, + varchar(900) value: string ref); + +case @token.kind of + 0 = @token_eof +| 1 = @token_null_literal +| 2 = @token_boolean_literal +| 3 = @token_numeric_literal +| 4 = @token_string_literal +| 5 = @token_regular_expression +| 6 = @token_identifier +| 7 = @token_keyword +| 8 = @token_punctuator; + +// associate comments with the token immediately following them (which may be EOF) +next_token (int comment: @comment ref, int token: @token ref); + +// JSON +#keyset[parent, idx] +json (unique int id: @json_value, + int kind: int ref, + int parent: @json_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +json_literals (varchar(900) value: string ref, + varchar(900) raw: string ref, + unique int expr: @json_value ref); + +json_properties (int obj: @json_object ref, + varchar(900) property: string ref, + int value: @json_value ref); + +json_errors (unique int id: @json_parse_error, + varchar(900) message: string ref); + +json_locations(unique int locatable: @json_locatable ref, + int location: @location_default ref); + +case @json_value.kind of + 0 = @json_null +| 1 = @json_boolean +| 2 = @json_number +| 3 = @json_string +| 4 = @json_array +| 5 = @json_object; + +@json_parent = @json_object | @json_array | @file; + +@json_locatable = @json_value | @json_parse_error; + +// locations +@ast_node = @toplevel | @stmt | @expr | @property | @typeexpr; + +@locatable = @file + | @ast_node + | @comment + | @line + | @js_parse_error | @regexp_parse_error + | @regexpterm + | @json_locatable + | @token + | @cfg_node + | @jsdoc | @jsdoc_type_expr | @jsdoc_tag + | @yaml_locatable + | @xmllocatable + | @configLocatable + | @template_placeholder_tag; + +hasLocation (unique int locatable: @locatable ref, + int location: @location ref); + +// CFG +entry_cfg_node (unique int id: @entry_node, int container: @stmt_container ref); +exit_cfg_node (unique int id: @exit_node, int container: @stmt_container ref); +guard_node (unique int id: @guard_node, int kind: int ref, int test: @expr ref); +case @guard_node.kind of + 0 = @falsy_guard +| 1 = @truthy_guard; +@condition_guard = @falsy_guard | @truthy_guard; + +@synthetic_cfg_node = @entry_node | @exit_node | @guard_node; +@cfg_node = @synthetic_cfg_node | @expr_parent; + +successor (int pred: @cfg_node ref, int succ: @cfg_node ref); + +// JSDoc comments +jsdoc (unique int id: @jsdoc, varchar(900) description: string ref, int comment: @comment ref); +#keyset[parent, idx] +jsdoc_tags (unique int id: @jsdoc_tag, varchar(900) title: string ref, + int parent: @jsdoc ref, int idx: int ref, varchar(900) tostring: string ref); +jsdoc_tag_descriptions (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); +jsdoc_tag_names (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); + +#keyset[parent, idx] +jsdoc_type_exprs (unique int id: @jsdoc_type_expr, + int kind: int ref, + int parent: @jsdoc_type_expr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); +case @jsdoc_type_expr.kind of + 0 = @jsdoc_any_type_expr +| 1 = @jsdoc_null_type_expr +| 2 = @jsdoc_undefined_type_expr +| 3 = @jsdoc_unknown_type_expr +| 4 = @jsdoc_void_type_expr +| 5 = @jsdoc_named_type_expr +| 6 = @jsdoc_applied_type_expr +| 7 = @jsdoc_nullable_type_expr +| 8 = @jsdoc_non_nullable_type_expr +| 9 = @jsdoc_record_type_expr +| 10 = @jsdoc_array_type_expr +| 11 = @jsdoc_union_type_expr +| 12 = @jsdoc_function_type_expr +| 13 = @jsdoc_optional_type_expr +| 14 = @jsdoc_rest_type_expr +; + +#keyset[id, idx] +jsdoc_record_field_name (int id: @jsdoc_record_type_expr ref, int idx: int ref, varchar(900) name: string ref); +jsdoc_prefix_qualifier (int id: @jsdoc_type_expr ref); +jsdoc_has_new_parameter (int fn: @jsdoc_function_type_expr ref); + +@jsdoc_type_expr_parent = @jsdoc_type_expr | @jsdoc_tag; + +jsdoc_errors (unique int id: @jsdoc_error, int tag: @jsdoc_tag ref, varchar(900) message: string ref, varchar(900) tostring: string ref); + +@dataflownode = @expr | @function_decl_stmt | @class_decl_stmt | @namespace_declaration | @enum_declaration | @property; + +@optionalchainable = @call_expr | @propaccess; + +isOptionalChaining(int id: @optionalchainable ref); + +/** + * The time taken for the extraction of a file. + * This table contains non-deterministic content. + * + * The sum of the `time` column for each (`file`, `timerKind`) pair + * is the total time taken for extraction of `file`. The `extractionPhase` + * column provides a granular view of the extraction time of the file. + */ +extraction_time( + int file : @file ref, + // see `com.semmle.js.extractor.ExtractionMetrics.ExtractionPhase`. + int extractionPhase: int ref, + // 0 for the elapsed CPU time in nanoseconds, 1 for the elapsed wallclock time in nanoseconds + int timerKind: int ref, + float time: float ref +) + +/** +* Non-timing related data for the extraction of a single file. +* This table contains non-deterministic content. +*/ +extraction_data( + int file : @file ref, + // the absolute path to the cache file + varchar(900) cacheFile: string ref, + boolean fromCache: boolean ref, + int length: int ref +) + +/*- YAML -*/ + +#keyset[parent, idx] +yaml (unique int id: @yaml_node, + int kind: int ref, + int parent: @yaml_node_parent ref, + int idx: int ref, + string tag: string ref, + string tostring: string ref); + +case @yaml_node.kind of + 0 = @yaml_scalar_node +| 1 = @yaml_mapping_node +| 2 = @yaml_sequence_node +| 3 = @yaml_alias_node +; + +@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node; + +@yaml_node_parent = @yaml_collection_node | @file; + +yaml_anchors (unique int node: @yaml_node ref, + string anchor: string ref); + +yaml_aliases (unique int alias: @yaml_alias_node ref, + string target: string ref); + +yaml_scalars (unique int scalar: @yaml_scalar_node ref, + int style: int ref, + string value: string ref); + +yaml_errors (unique int id: @yaml_error, + string message: string ref); + +yaml_locations(unique int locatable: @yaml_locatable ref, + int location: @location_default ref); + +@yaml_locatable = @yaml_node | @yaml_error; + +/*- XML Files -*/ + +xmlEncoding( + unique int id: @file ref, + string encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/*- Configuration files with key value pairs -*/ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; diff --git a/javascript/ql/lib/upgrades/5b5db607d20c7b449cef2d1c926b24d77c69bebb/semmlecode.javascript.dbscheme b/javascript/ql/lib/upgrades/5b5db607d20c7b449cef2d1c926b24d77c69bebb/semmlecode.javascript.dbscheme new file mode 100644 index 000000000000..ccefb5e2d493 --- /dev/null +++ b/javascript/ql/lib/upgrades/5b5db607d20c7b449cef2d1c926b24d77c69bebb/semmlecode.javascript.dbscheme @@ -0,0 +1,1194 @@ +/*** Standard fragments ***/ + +/*- Files and folders -*/ + +/** + * The location of an element. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +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 +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @file | @folder + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/*- Lines of code -*/ + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +/*- External data -*/ + +/** + * External data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/*- Source location prefix -*/ + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/*- JavaScript-specific part -*/ + +@location = @location_default + +@sourceline = @locatable; + +filetype( + int file: @file ref, + string filetype: string ref +) + +// top-level code fragments +toplevels (unique int id: @toplevel, + int kind: int ref); + +is_externs (int toplevel: @toplevel ref); + +case @toplevel.kind of + 0 = @script +| 1 = @inline_script +| 2 = @event_handler +| 3 = @javascript_url +| 4 = @template_toplevel; + +is_module (int tl: @toplevel ref); +is_nodejs (int tl: @toplevel ref); +is_es2015_module (int tl: @toplevel ref); +is_closure_module (int tl: @toplevel ref); + +@xml_node_with_code = @xmlelement | @xmlattribute | @template_placeholder_tag; +toplevel_parent_xml_node( + unique int toplevel: @toplevel ref, + int xmlnode: @xml_node_with_code ref); + +xml_element_parent_expression( + unique int xmlnode: @xmlelement ref, + int expression: @expr ref, + int index: int ref); + +// statements +#keyset[parent, idx] +stmts (unique int id: @stmt, + int kind: int 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); + +@stmt_parent = @stmt | @toplevel | @function_expr | @arrow_function_expr | @static_initializer; +@stmt_container = @toplevel | @function | @namespace_declaration | @external_module_declaration | @global_augmentation_declaration; + +case @stmt.kind of + 0 = @empty_stmt +| 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @labeled_stmt +| 5 = @break_stmt +| 6 = @continue_stmt +| 7 = @with_stmt +| 8 = @switch_stmt +| 9 = @return_stmt +| 10 = @throw_stmt +| 11 = @try_stmt +| 12 = @while_stmt +| 13 = @do_while_stmt +| 14 = @for_stmt +| 15 = @for_in_stmt +| 16 = @debugger_stmt +| 17 = @function_decl_stmt +| 18 = @var_decl_stmt +| 19 = @case +| 20 = @catch_clause +| 21 = @for_of_stmt +| 22 = @const_decl_stmt +| 23 = @let_stmt +| 24 = @legacy_let_stmt +| 25 = @for_each_stmt +| 26 = @class_decl_stmt +| 27 = @import_declaration +| 28 = @export_all_declaration +| 29 = @export_default_declaration +| 30 = @export_named_declaration +| 31 = @namespace_declaration +| 32 = @import_equals_declaration +| 33 = @export_assign_declaration +| 34 = @interface_declaration +| 35 = @type_alias_declaration +| 36 = @enum_declaration +| 37 = @external_module_declaration +| 38 = @export_as_namespace_declaration +| 39 = @global_augmentation_declaration +| 40 = @using_decl_stmt +; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @let_stmt | @legacy_let_stmt | @using_decl_stmt; + +@export_declaration = @export_all_declaration | @export_default_declaration | @export_named_declaration; + +@namespace_definition = @namespace_declaration | @enum_declaration; +@type_definition = @class_definition | @interface_declaration | @enum_declaration | @type_alias_declaration | @enum_member; + +is_instantiated(unique int decl: @namespace_declaration ref); + +@declarable_node = @decl_stmt | @namespace_declaration | @class_decl_stmt | @function_decl_stmt | @enum_declaration | @external_module_declaration | @global_augmentation_declaration | @field; +has_declare_keyword(unique int stmt: @declarable_node ref); + +is_for_await_of(unique int forof: @for_of_stmt ref); + +// expressions +#keyset[parent, idx] +exprs (unique int id: @expr, + int kind: int ref, + int parent: @expr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +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); + +expr_containers (unique int expr: @expr_or_type ref, + int container: @stmt_container ref); + +array_size (unique int ae: @arraylike ref, + int sz: int ref); + +is_delegating (int yield: @yield_expr ref); + +@expr_or_stmt = @expr | @stmt; +@expr_or_type = @expr | @typeexpr; +@expr_parent = @expr_or_stmt | @property | @function_typeexpr; +@arraylike = @array_expr | @array_pattern; +@type_annotation = @typeexpr | @jsdoc_type_expr; +@node_in_stmt_container = @cfg_node | @type_annotation | @toplevel; + +case @expr.kind of + 0 = @label +| 1 = @null_literal +| 2 = @boolean_literal +| 3 = @number_literal +| 4 = @string_literal +| 5 = @regexp_literal +| 6 = @this_expr +| 7 = @array_expr +| 8 = @obj_expr +| 9 = @function_expr +| 10 = @seq_expr +| 11 = @conditional_expr +| 12 = @new_expr +| 13 = @call_expr +| 14 = @dot_expr +| 15 = @index_expr +| 16 = @neg_expr +| 17 = @plus_expr +| 18 = @log_not_expr +| 19 = @bit_not_expr +| 20 = @typeof_expr +| 21 = @void_expr +| 22 = @delete_expr +| 23 = @eq_expr +| 24 = @neq_expr +| 25 = @eqq_expr +| 26 = @neqq_expr +| 27 = @lt_expr +| 28 = @le_expr +| 29 = @gt_expr +| 30 = @ge_expr +| 31 = @lshift_expr +| 32 = @rshift_expr +| 33 = @urshift_expr +| 34 = @add_expr +| 35 = @sub_expr +| 36 = @mul_expr +| 37 = @div_expr +| 38 = @mod_expr +| 39 = @bitor_expr +| 40 = @xor_expr +| 41 = @bitand_expr +| 42 = @in_expr +| 43 = @instanceof_expr +| 44 = @logand_expr +| 45 = @logor_expr +| 47 = @assign_expr +| 48 = @assign_add_expr +| 49 = @assign_sub_expr +| 50 = @assign_mul_expr +| 51 = @assign_div_expr +| 52 = @assign_mod_expr +| 53 = @assign_lshift_expr +| 54 = @assign_rshift_expr +| 55 = @assign_urshift_expr +| 56 = @assign_or_expr +| 57 = @assign_xor_expr +| 58 = @assign_and_expr +| 59 = @preinc_expr +| 60 = @postinc_expr +| 61 = @predec_expr +| 62 = @postdec_expr +| 63 = @par_expr +| 64 = @var_declarator +| 65 = @arrow_function_expr +| 66 = @spread_element +| 67 = @array_pattern +| 68 = @object_pattern +| 69 = @yield_expr +| 70 = @tagged_template_expr +| 71 = @template_literal +| 72 = @template_element +| 73 = @array_comprehension_expr +| 74 = @generator_expr +| 75 = @for_in_comprehension_block +| 76 = @for_of_comprehension_block +| 77 = @legacy_letexpr +| 78 = @var_decl +| 79 = @proper_varaccess +| 80 = @class_expr +| 81 = @super_expr +| 82 = @newtarget_expr +| 83 = @named_import_specifier +| 84 = @import_default_specifier +| 85 = @import_namespace_specifier +| 86 = @named_export_specifier +| 87 = @exp_expr +| 88 = @assign_exp_expr +| 89 = @jsx_element +| 90 = @jsx_qualified_name +| 91 = @jsx_empty_expr +| 92 = @await_expr +| 93 = @function_sent_expr +| 94 = @decorator +| 95 = @export_default_specifier +| 96 = @export_namespace_specifier +| 97 = @bind_expr +| 98 = @external_module_reference +| 99 = @dynamic_import +| 100 = @expression_with_type_arguments +| 101 = @prefix_type_assertion +| 102 = @as_type_assertion +| 103 = @export_varaccess +| 104 = @decorator_list +| 105 = @non_null_assertion +| 106 = @bigint_literal +| 107 = @nullishcoalescing_expr +| 108 = @e4x_xml_anyname +| 109 = @e4x_xml_static_attribute_selector +| 110 = @e4x_xml_dynamic_attribute_selector +| 111 = @e4x_xml_filter_expression +| 112 = @e4x_xml_static_qualident +| 113 = @e4x_xml_dynamic_qualident +| 114 = @e4x_xml_dotdotexpr +| 115 = @import_meta_expr +| 116 = @assignlogandexpr +| 117 = @assignlogorexpr +| 118 = @assignnullishcoalescingexpr +| 119 = @template_pipe_ref +| 120 = @generated_code_expr +| 121 = @satisfies_expr +; + +@varaccess = @proper_varaccess | @export_varaccess; +@varref = @var_decl | @varaccess; + +@identifier = @label | @varref | @type_identifier; + +@literal = @null_literal | @boolean_literal | @number_literal | @string_literal | @regexp_literal | @bigint_literal; + +@propaccess = @dot_expr | @index_expr; + +@invokeexpr = @new_expr | @call_expr; + +@unaryexpr = @neg_expr | @plus_expr | @log_not_expr | @bit_not_expr | @typeof_expr | @void_expr | @delete_expr | @spread_element; + +@equality_test = @eq_expr | @neq_expr | @eqq_expr | @neqq_expr; + +@comparison = @equality_test | @lt_expr | @le_expr | @gt_expr | @ge_expr; + +@binaryexpr = @comparison | @lshift_expr | @rshift_expr | @urshift_expr | @add_expr | @sub_expr | @mul_expr | @div_expr | @mod_expr | @exp_expr | @bitor_expr | @xor_expr | @bitand_expr | @in_expr | @instanceof_expr | @logand_expr | @logor_expr | @nullishcoalescing_expr; + +@assignment = @assign_expr | @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr | @assign_mod_expr | @assign_exp_expr | @assign_lshift_expr | @assign_rshift_expr | @assign_urshift_expr | @assign_or_expr | @assign_xor_expr | @assign_and_expr | @assignlogandexpr | @assignlogorexpr | @assignnullishcoalescingexpr; + +@updateexpr = @preinc_expr | @postinc_expr | @predec_expr | @postdec_expr; + +@pattern = @varref | @array_pattern | @object_pattern; + +@comprehension_expr = @array_comprehension_expr | @generator_expr; + +@comprehension_block = @for_in_comprehension_block | @for_of_comprehension_block; + +@import_specifier = @named_import_specifier | @import_default_specifier | @import_namespace_specifier; + +@exportspecifier = @named_export_specifier | @export_default_specifier | @export_namespace_specifier; + +@type_keyword_operand = @import_declaration | @export_declaration | @import_specifier; + +@type_assertion = @as_type_assertion | @prefix_type_assertion; + +@class_definition = @class_decl_stmt | @class_expr; +@interface_definition = @interface_declaration | @interface_typeexpr; +@class_or_interface = @class_definition | @interface_definition; + +@lexical_decl = @var_decl | @type_decl; +@lexical_access = @varaccess | @local_type_access | @local_var_type_access | @local_namespace_access; +@lexical_ref = @lexical_decl | @lexical_access; + +@e4x_xml_attribute_selector = @e4x_xml_static_attribute_selector | @e4x_xml_dynamic_attribute_selector; +@e4x_xml_qualident = @e4x_xml_static_qualident | @e4x_xml_dynamic_qualident; + +expr_contains_template_tag_location( + int expr: @expr ref, + int location: @location ref +); + +@template_placeholder_tag_parent = @xmlelement | @xmlattribute | @file; + +template_placeholder_tag_info( + unique int node: @template_placeholder_tag, + int parentNode: @template_placeholder_tag_parent ref, + varchar(900) raw: string ref +); + +// scopes +scopes (unique int id: @scope, + int kind: int ref); + +case @scope.kind of + 0 = @global_scope +| 1 = @function_scope +| 2 = @catch_scope +| 3 = @module_scope +| 4 = @block_scope +| 5 = @for_scope +| 6 = @for_in_scope // for-of scopes work the same as for-in scopes +| 7 = @comprehension_block_scope +| 8 = @class_expr_scope +| 9 = @namespace_scope +| 10 = @class_decl_scope +| 11 = @interface_scope +| 12 = @type_alias_scope +| 13 = @mapped_type_scope +| 14 = @enum_scope +| 15 = @external_module_scope +| 16 = @conditional_type_scope; + +scopenodes (unique int node: @ast_node ref, + int scope: @scope ref); + +scopenesting (unique int inner: @scope ref, + int outer: @scope ref); + +// functions +@function = @function_decl_stmt | @function_expr | @arrow_function_expr; + +@parameterized = @function | @catch_clause; +@type_parameterized = @function | @class_or_interface | @type_alias_declaration | @mapped_typeexpr | @infer_typeexpr; + +is_generator (int fun: @function ref); +has_rest_parameter (int fun: @function ref); +is_async (int fun: @function ref); + +// variables and lexically scoped type names +#keyset[scope, name] +variables (unique int id: @variable, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_type_names (unique int id: @local_type_name, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_namespace_names (unique int id: @local_namespace_name, + varchar(900) name: string ref, + int scope: @scope ref); + +is_arguments_object (int id: @variable ref); + +@lexical_name = @variable | @local_type_name | @local_namespace_name; + +@bind_id = @varaccess | @local_var_type_access; +bind (unique int id: @bind_id ref, + int decl: @variable ref); + +decl (unique int id: @var_decl ref, + int decl: @variable ref); + +@typebind_id = @local_type_access | @export_varaccess; +typebind (unique int id: @typebind_id ref, + int decl: @local_type_name ref); + +@typedecl_id = @type_decl | @var_decl; +typedecl (unique int id: @typedecl_id ref, + int decl: @local_type_name ref); + +namespacedecl (unique int id: @var_decl ref, + int decl: @local_namespace_name ref); + +@namespacebind_id = @local_namespace_access | @export_varaccess; +namespacebind (unique int id: @namespacebind_id ref, + int decl: @local_namespace_name ref); + + +// properties in object literals, property patterns in object patterns, and method declarations in classes +#keyset[parent, index] +properties (unique int id: @property, + int parent: @property_parent ref, + int index: int ref, + int kind: int ref, + varchar(900) tostring: string ref); + +case @property.kind of + 0 = @value_property +| 1 = @property_getter +| 2 = @property_setter +| 3 = @jsx_attribute +| 4 = @function_call_signature +| 5 = @constructor_call_signature +| 6 = @index_signature +| 7 = @enum_member +| 8 = @proper_field +| 9 = @parameter_field +| 10 = @static_initializer +; + +@property_parent = @obj_expr | @object_pattern | @class_definition | @jsx_element | @interface_definition | @enum_declaration; +@property_accessor = @property_getter | @property_setter; +@call_signature = @function_call_signature | @constructor_call_signature; +@field = @proper_field | @parameter_field; +@field_or_vardeclarator = @field | @var_declarator; + +is_computed (int id: @property ref); +is_method (int id: @property ref); +is_static (int id: @property ref); +is_abstract_member (int id: @property ref); +is_const_enum (int id: @enum_declaration ref); +is_abstract_class (int id: @class_decl_stmt ref); + +has_public_keyword (int id: @property ref); +has_private_keyword (int id: @property ref); +has_protected_keyword (int id: @property ref); +has_readonly_keyword (int id: @property ref); +has_type_keyword (int id: @type_keyword_operand ref); +is_optional_member (int id: @property ref); +has_definite_assignment_assertion (int id: @field_or_vardeclarator ref); +is_optional_parameter_declaration (unique int parameter: @pattern ref); + +#keyset[constructor, param_index] +parameter_fields( + unique int field: @parameter_field ref, + int constructor: @function_expr ref, + int param_index: int ref +); + +// types +#keyset[parent, idx] +typeexprs ( + unique int id: @typeexpr, + int kind: int ref, + int parent: @typeexpr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref +); + +case @typeexpr.kind of + 0 = @local_type_access +| 1 = @type_decl +| 2 = @keyword_typeexpr +| 3 = @string_literal_typeexpr +| 4 = @number_literal_typeexpr +| 5 = @boolean_literal_typeexpr +| 6 = @array_typeexpr +| 7 = @union_typeexpr +| 8 = @indexed_access_typeexpr +| 9 = @intersection_typeexpr +| 10 = @parenthesized_typeexpr +| 11 = @tuple_typeexpr +| 12 = @keyof_typeexpr +| 13 = @qualified_type_access +| 14 = @generic_typeexpr +| 15 = @type_label +| 16 = @typeof_typeexpr +| 17 = @local_var_type_access +| 18 = @qualified_var_type_access +| 19 = @this_var_type_access +| 20 = @predicate_typeexpr +| 21 = @interface_typeexpr +| 22 = @type_parameter +| 23 = @plain_function_typeexpr +| 24 = @constructor_typeexpr +| 25 = @local_namespace_access +| 26 = @qualified_namespace_access +| 27 = @mapped_typeexpr +| 28 = @conditional_typeexpr +| 29 = @infer_typeexpr +| 30 = @import_type_access +| 31 = @import_namespace_access +| 32 = @import_var_type_access +| 33 = @optional_typeexpr +| 34 = @rest_typeexpr +| 35 = @bigint_literal_typeexpr +| 36 = @readonly_typeexpr +| 37 = @template_literal_typeexpr +; + +@typeref = @typeaccess | @type_decl; +@type_identifier = @type_decl | @local_type_access | @type_label | @local_var_type_access | @local_namespace_access; +@typeexpr_parent = @expr | @stmt | @property | @typeexpr; +@literal_typeexpr = @string_literal_typeexpr | @number_literal_typeexpr | @boolean_literal_typeexpr | @bigint_literal_typeexpr; +@typeaccess = @local_type_access | @qualified_type_access | @import_type_access; +@vartypeaccess = @local_var_type_access | @qualified_var_type_access | @this_var_type_access | @import_var_type_access; +@namespace_access = @local_namespace_access | @qualified_namespace_access | @import_namespace_access; +@import_typeexpr = @import_type_access | @import_namespace_access | @import_var_type_access; + +@function_typeexpr = @plain_function_typeexpr | @constructor_typeexpr; + +// types +types ( + unique int id: @type, + int kind: int ref, + varchar(900) tostring: string ref +); + +#keyset[parent, idx] +type_child ( + int child: @type ref, + int parent: @type ref, + int idx: int ref +); + +case @type.kind of + 0 = @any_type +| 1 = @string_type +| 2 = @number_type +| 3 = @union_type +| 4 = @true_type +| 5 = @false_type +| 6 = @type_reference +| 7 = @object_type +| 8 = @canonical_type_variable_type +| 9 = @typeof_type +| 10 = @void_type +| 11 = @undefined_type +| 12 = @null_type +| 13 = @never_type +| 14 = @plain_symbol_type +| 15 = @unique_symbol_type +| 16 = @objectkeyword_type +| 17 = @intersection_type +| 18 = @tuple_type +| 19 = @lexical_type_variable_type +| 20 = @this_type +| 21 = @number_literal_type +| 22 = @string_literal_type +| 23 = @unknown_type +| 24 = @bigint_type +| 25 = @bigint_literal_type +; + +@boolean_literal_type = @true_type | @false_type; +@symbol_type = @plain_symbol_type | @unique_symbol_type; +@union_or_intersection_type = @union_type | @intersection_type; +@typevariable_type = @canonical_type_variable_type | @lexical_type_variable_type; + +has_asserts_keyword(int node: @predicate_typeexpr ref); + +@typed_ast_node = @expr | @typeexpr | @function; +ast_node_type( + unique int node: @typed_ast_node ref, + int typ: @type ref); + +declared_function_signature( + unique int node: @function ref, + int sig: @signature_type ref +); + +invoke_expr_signature( + unique int node: @invokeexpr ref, + int sig: @signature_type ref +); + +invoke_expr_overload_index( + unique int node: @invokeexpr ref, + int index: int ref +); + +symbols ( + unique int id: @symbol, + int kind: int ref, + varchar(900) name: string ref +); + +symbol_parent ( + unique int symbol: @symbol ref, + int parent: @symbol ref +); + +symbol_module ( + int symbol: @symbol ref, + varchar(900) moduleName: string ref +); + +symbol_global ( + int symbol: @symbol ref, + varchar(900) globalName: string ref +); + +case @symbol.kind of + 0 = @root_symbol +| 1 = @member_symbol +| 2 = @other_symbol +; + +@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 | @external_module_declaration; + +ast_node_symbol( + unique int node: @ast_node_with_symbol ref, + int symbol: @symbol ref); + +type_symbol( + unique int typ: @type_with_symbol ref, + int symbol: @symbol ref); + +#keyset[typ, name] +type_property( + int typ: @type ref, + varchar(900) name: string ref, + int propertyType: @type ref); + +type_alias( + unique int aliasType: @type ref, + int underlyingType: @type ref); + +@literal_type = @string_literal_type | @number_literal_type | @boolean_literal_type | @bigint_literal_type; +@type_with_literal_value = @string_literal_type | @number_literal_type | @bigint_literal_type; +type_literal_value( + unique int typ: @type_with_literal_value ref, + varchar(900) value: string ref); + +signature_types ( + unique int id: @signature_type, + int kind: int ref, + varchar(900) tostring: string ref, + int type_parameters: int ref, + int required_params: int ref +); + +is_abstract_signature( + unique int sig: @signature_type ref +); + +signature_rest_parameter( + unique int sig: @signature_type ref, + int rest_param_arra_type: @type ref +); + +case @signature_type.kind of + 0 = @function_signature_type +| 1 = @constructor_signature_type +; + +#keyset[typ, kind, index] +type_contains_signature ( + int typ: @type ref, + int kind: int ref, // constructor/call/index + int index: int ref, // ordering of overloaded signatures + int sig: @signature_type ref +); + +#keyset[parent, index] +signature_contains_type ( + int child: @type ref, + int parent: @signature_type ref, + int index: int ref +); + +#keyset[sig, index] +signature_parameter_name ( + int sig: @signature_type ref, + int index: int ref, + varchar(900) name: string ref +); + +number_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +string_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +base_type_names( + int typeName: @symbol ref, + int baseTypeName: @symbol ref +); + +self_types( + int typeName: @symbol ref, + int selfType: @type_reference ref +); + +tuple_type_min_length( + unique int typ: @type ref, + int minLength: int ref +); + +tuple_type_rest_index( + unique int typ: @type ref, + int index: int ref +); + +// comments +comments (unique int id: @comment, + int kind: int ref, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(900) tostring: string ref); + +case @comment.kind of + 0 = @slashslash_comment +| 1 = @slashstar_comment +| 2 = @doc_comment +| 3 = @html_comment_start +| 4 = @htmlcommentend; + +@html_comment = @html_comment_start | @htmlcommentend; +@line_comment = @slashslash_comment | @html_comment; +@block_comment = @slashstar_comment | @doc_comment; + +// source lines +lines (unique int id: @line, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(2) terminator: string ref); +indentation (int file: @file ref, + int lineno: int ref, + varchar(1) indentChar: string ref, + int indentDepth: int ref); + +// JavaScript parse errors +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 + 0 = @regexp_alt +| 1 = @regexp_seq +| 2 = @regexp_caret +| 3 = @regexp_dollar +| 4 = @regexp_wordboundary +| 5 = @regexp_nonwordboundary +| 6 = @regexp_positive_lookahead +| 7 = @regexp_negative_lookahead +| 8 = @regexp_star +| 9 = @regexp_plus +| 10 = @regexp_opt +| 11 = @regexp_range +| 12 = @regexp_dot +| 13 = @regexp_group +| 14 = @regexp_normal_constant +| 15 = @regexp_hex_escape +| 16 = @regexp_unicode_escape +| 17 = @regexp_dec_escape +| 18 = @regexp_oct_escape +| 19 = @regexp_ctrl_escape +| 20 = @regexp_char_class_escape +| 21 = @regexp_id_escape +| 22 = @regexp_backref +| 23 = @regexp_char_class +| 24 = @regexp_char_range +| 25 = @regexp_positive_lookbehind +| 26 = @regexp_negative_lookbehind +| 27 = @regexp_unicode_property_escape +| 28 = @regexp_quoted_string +| 29 = @regexp_intersection +| 30 = @regexp_subtraction; + +regexp_parse_errors (unique int id: @regexp_parse_error, + int regexp: @regexpterm ref, + varchar(900) message: string ref); + +@regexp_quantifier = @regexp_star | @regexp_plus | @regexp_opt | @regexp_range; +@regexp_escape = @regexp_char_escape | @regexp_char_class_escape | @regexp_unicode_property_escape; +@regexp_char_escape = @regexp_hex_escape | @regexp_unicode_escape | @regexp_dec_escape | @regexp_oct_escape | @regexp_ctrl_escape | @regexp_id_escape; +@regexp_constant = @regexp_normal_constant | @regexp_char_escape; +@regexp_lookahead = @regexp_positive_lookahead | @regexp_negative_lookahead; +@regexp_lookbehind = @regexp_positive_lookbehind | @regexp_negative_lookbehind; +@regexp_subpattern = @regexp_lookahead | @regexp_lookbehind; +@regexp_anchor = @regexp_dollar | @regexp_caret; + +is_greedy (int id: @regexp_quantifier ref); +range_quantifier_lower_bound (unique int id: @regexp_range ref, int lo: int ref); +range_quantifier_upper_bound (unique int id: @regexp_range ref, int hi: int ref); +is_capture (unique int id: @regexp_group ref, int number: int ref); +is_named_capture (unique int id: @regexp_group ref, string name: string ref); +is_inverted (int id: @regexp_char_class ref); +regexp_const_value (unique int id: @regexp_constant ref, varchar(1) value: string ref); +char_class_escape (unique int id: @regexp_char_class_escape ref, varchar(1) value: string ref); +backref (unique int id: @regexp_backref ref, int value: int ref); +named_backref (unique int id: @regexp_backref ref, string name: string ref); +unicode_property_escapename (unique int id: @regexp_unicode_property_escape ref, string name: string ref); +unicode_property_escapevalue (unique int id: @regexp_unicode_property_escape ref, string value: string ref); + +// tokens +#keyset[toplevel, idx] +tokeninfo (unique int id: @token, + int kind: int ref, + int toplevel: @toplevel ref, + int idx: int ref, + varchar(900) value: string ref); + +case @token.kind of + 0 = @token_eof +| 1 = @token_null_literal +| 2 = @token_boolean_literal +| 3 = @token_numeric_literal +| 4 = @token_string_literal +| 5 = @token_regular_expression +| 6 = @token_identifier +| 7 = @token_keyword +| 8 = @token_punctuator; + +// associate comments with the token immediately following them (which may be EOF) +next_token (int comment: @comment ref, int token: @token ref); + +// JSON +#keyset[parent, idx] +json (unique int id: @json_value, + int kind: int ref, + int parent: @json_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +json_literals (varchar(900) value: string ref, + varchar(900) raw: string ref, + unique int expr: @json_value ref); + +json_properties (int obj: @json_object ref, + varchar(900) property: string ref, + int value: @json_value ref); + +json_errors (unique int id: @json_parse_error, + varchar(900) message: string ref); + +json_locations(unique int locatable: @json_locatable ref, + int location: @location_default ref); + +case @json_value.kind of + 0 = @json_null +| 1 = @json_boolean +| 2 = @json_number +| 3 = @json_string +| 4 = @json_array +| 5 = @json_object; + +@json_parent = @json_object | @json_array | @file; + +@json_locatable = @json_value | @json_parse_error; + +// locations +@ast_node = @toplevel | @stmt | @expr | @property | @typeexpr; + +@locatable = @file + | @ast_node + | @comment + | @line + | @js_parse_error | @regexp_parse_error + | @regexpterm + | @json_locatable + | @token + | @cfg_node + | @jsdoc | @jsdoc_type_expr | @jsdoc_tag + | @yaml_locatable + | @xmllocatable + | @configLocatable + | @template_placeholder_tag; + +hasLocation (unique int locatable: @locatable ref, + int location: @location ref); + +// CFG +entry_cfg_node (unique int id: @entry_node, int container: @stmt_container ref); +exit_cfg_node (unique int id: @exit_node, int container: @stmt_container ref); +guard_node (unique int id: @guard_node, int kind: int ref, int test: @expr ref); +case @guard_node.kind of + 0 = @falsy_guard +| 1 = @truthy_guard; +@condition_guard = @falsy_guard | @truthy_guard; + +@synthetic_cfg_node = @entry_node | @exit_node | @guard_node; +@cfg_node = @synthetic_cfg_node | @expr_parent; + +successor (int pred: @cfg_node ref, int succ: @cfg_node ref); + +// JSDoc comments +jsdoc (unique int id: @jsdoc, varchar(900) description: string ref, int comment: @comment ref); +#keyset[parent, idx] +jsdoc_tags (unique int id: @jsdoc_tag, varchar(900) title: string ref, + int parent: @jsdoc ref, int idx: int ref, varchar(900) tostring: string ref); +jsdoc_tag_descriptions (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); +jsdoc_tag_names (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); + +#keyset[parent, idx] +jsdoc_type_exprs (unique int id: @jsdoc_type_expr, + int kind: int ref, + int parent: @jsdoc_type_expr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); +case @jsdoc_type_expr.kind of + 0 = @jsdoc_any_type_expr +| 1 = @jsdoc_null_type_expr +| 2 = @jsdoc_undefined_type_expr +| 3 = @jsdoc_unknown_type_expr +| 4 = @jsdoc_void_type_expr +| 5 = @jsdoc_identifier_type_expr +| 6 = @jsdoc_applied_type_expr +| 7 = @jsdoc_nullable_type_expr +| 8 = @jsdoc_non_nullable_type_expr +| 9 = @jsdoc_record_type_expr +| 10 = @jsdoc_array_type_expr +| 11 = @jsdoc_union_type_expr +| 12 = @jsdoc_function_type_expr +| 13 = @jsdoc_optional_type_expr +| 14 = @jsdoc_rest_type_expr +| 15 = @jsdoc_qualified_type_expr +; + +#keyset[id, idx] +jsdoc_record_field_name (int id: @jsdoc_record_type_expr ref, int idx: int ref, varchar(900) name: string ref); +jsdoc_prefix_qualifier (int id: @jsdoc_type_expr ref); +jsdoc_has_new_parameter (int fn: @jsdoc_function_type_expr ref); + +@jsdoc_type_expr_parent = @jsdoc_type_expr | @jsdoc_tag; + +jsdoc_errors (unique int id: @jsdoc_error, int tag: @jsdoc_tag ref, varchar(900) message: string ref, varchar(900) tostring: string ref); + +@dataflownode = @expr | @function_decl_stmt | @class_decl_stmt | @namespace_declaration | @enum_declaration | @property; + +@optionalchainable = @call_expr | @propaccess; + +isOptionalChaining(int id: @optionalchainable ref); + +/** + * The time taken for the extraction of a file. + * This table contains non-deterministic content. + * + * The sum of the `time` column for each (`file`, `timerKind`) pair + * is the total time taken for extraction of `file`. The `extractionPhase` + * column provides a granular view of the extraction time of the file. + */ +extraction_time( + int file : @file ref, + // see `com.semmle.js.extractor.ExtractionMetrics.ExtractionPhase`. + int extractionPhase: int ref, + // 0 for the elapsed CPU time in nanoseconds, 1 for the elapsed wallclock time in nanoseconds + int timerKind: int ref, + float time: float ref +) + +/** +* Non-timing related data for the extraction of a single file. +* This table contains non-deterministic content. +*/ +extraction_data( + int file : @file ref, + // the absolute path to the cache file + varchar(900) cacheFile: string ref, + boolean fromCache: boolean ref, + int length: int ref +) + +/*- YAML -*/ + +#keyset[parent, idx] +yaml (unique int id: @yaml_node, + int kind: int ref, + int parent: @yaml_node_parent ref, + int idx: int ref, + string tag: string ref, + string tostring: string ref); + +case @yaml_node.kind of + 0 = @yaml_scalar_node +| 1 = @yaml_mapping_node +| 2 = @yaml_sequence_node +| 3 = @yaml_alias_node +; + +@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node; + +@yaml_node_parent = @yaml_collection_node | @file; + +yaml_anchors (unique int node: @yaml_node ref, + string anchor: string ref); + +yaml_aliases (unique int alias: @yaml_alias_node ref, + string target: string ref); + +yaml_scalars (unique int scalar: @yaml_scalar_node ref, + int style: int ref, + string value: string ref); + +yaml_errors (unique int id: @yaml_error, + string message: string ref); + +yaml_locations(unique int locatable: @yaml_locatable ref, + int location: @location_default ref); + +@yaml_locatable = @yaml_node | @yaml_error; + +/*- XML Files -*/ + +xmlEncoding( + unique int id: @file ref, + string encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/*- Configuration files with key value pairs -*/ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; diff --git a/javascript/ql/lib/upgrades/5b5db607d20c7b449cef2d1c926b24d77c69bebb/upgrade.properties b/javascript/ql/lib/upgrades/5b5db607d20c7b449cef2d1c926b24d77c69bebb/upgrade.properties new file mode 100644 index 000000000000..9812f386f8c3 --- /dev/null +++ b/javascript/ql/lib/upgrades/5b5db607d20c7b449cef2d1c926b24d77c69bebb/upgrade.properties @@ -0,0 +1,2 @@ +description: split up qualified names in jsdoc type exprs +compatibility: backwards From ab1f9292284a49233ab7e59de7b6d0bcbc66ecee Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 24 Mar 2025 12:10:12 +0100 Subject: [PATCH 12/15] JS: Add downgrade script --- .../old.dbscheme | 1194 +++++++++++++++++ .../semmlecode.javascript.dbscheme | 1193 ++++++++++++++++ .../upgrade.properties | 2 + 3 files changed, 2389 insertions(+) create mode 100644 javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/old.dbscheme create mode 100644 javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/semmlecode.javascript.dbscheme create mode 100644 javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/upgrade.properties diff --git a/javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/old.dbscheme b/javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/old.dbscheme new file mode 100644 index 000000000000..ccefb5e2d493 --- /dev/null +++ b/javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/old.dbscheme @@ -0,0 +1,1194 @@ +/*** Standard fragments ***/ + +/*- Files and folders -*/ + +/** + * The location of an element. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +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 +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @file | @folder + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/*- Lines of code -*/ + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +/*- External data -*/ + +/** + * External data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/*- Source location prefix -*/ + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/*- JavaScript-specific part -*/ + +@location = @location_default + +@sourceline = @locatable; + +filetype( + int file: @file ref, + string filetype: string ref +) + +// top-level code fragments +toplevels (unique int id: @toplevel, + int kind: int ref); + +is_externs (int toplevel: @toplevel ref); + +case @toplevel.kind of + 0 = @script +| 1 = @inline_script +| 2 = @event_handler +| 3 = @javascript_url +| 4 = @template_toplevel; + +is_module (int tl: @toplevel ref); +is_nodejs (int tl: @toplevel ref); +is_es2015_module (int tl: @toplevel ref); +is_closure_module (int tl: @toplevel ref); + +@xml_node_with_code = @xmlelement | @xmlattribute | @template_placeholder_tag; +toplevel_parent_xml_node( + unique int toplevel: @toplevel ref, + int xmlnode: @xml_node_with_code ref); + +xml_element_parent_expression( + unique int xmlnode: @xmlelement ref, + int expression: @expr ref, + int index: int ref); + +// statements +#keyset[parent, idx] +stmts (unique int id: @stmt, + int kind: int 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); + +@stmt_parent = @stmt | @toplevel | @function_expr | @arrow_function_expr | @static_initializer; +@stmt_container = @toplevel | @function | @namespace_declaration | @external_module_declaration | @global_augmentation_declaration; + +case @stmt.kind of + 0 = @empty_stmt +| 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @labeled_stmt +| 5 = @break_stmt +| 6 = @continue_stmt +| 7 = @with_stmt +| 8 = @switch_stmt +| 9 = @return_stmt +| 10 = @throw_stmt +| 11 = @try_stmt +| 12 = @while_stmt +| 13 = @do_while_stmt +| 14 = @for_stmt +| 15 = @for_in_stmt +| 16 = @debugger_stmt +| 17 = @function_decl_stmt +| 18 = @var_decl_stmt +| 19 = @case +| 20 = @catch_clause +| 21 = @for_of_stmt +| 22 = @const_decl_stmt +| 23 = @let_stmt +| 24 = @legacy_let_stmt +| 25 = @for_each_stmt +| 26 = @class_decl_stmt +| 27 = @import_declaration +| 28 = @export_all_declaration +| 29 = @export_default_declaration +| 30 = @export_named_declaration +| 31 = @namespace_declaration +| 32 = @import_equals_declaration +| 33 = @export_assign_declaration +| 34 = @interface_declaration +| 35 = @type_alias_declaration +| 36 = @enum_declaration +| 37 = @external_module_declaration +| 38 = @export_as_namespace_declaration +| 39 = @global_augmentation_declaration +| 40 = @using_decl_stmt +; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @let_stmt | @legacy_let_stmt | @using_decl_stmt; + +@export_declaration = @export_all_declaration | @export_default_declaration | @export_named_declaration; + +@namespace_definition = @namespace_declaration | @enum_declaration; +@type_definition = @class_definition | @interface_declaration | @enum_declaration | @type_alias_declaration | @enum_member; + +is_instantiated(unique int decl: @namespace_declaration ref); + +@declarable_node = @decl_stmt | @namespace_declaration | @class_decl_stmt | @function_decl_stmt | @enum_declaration | @external_module_declaration | @global_augmentation_declaration | @field; +has_declare_keyword(unique int stmt: @declarable_node ref); + +is_for_await_of(unique int forof: @for_of_stmt ref); + +// expressions +#keyset[parent, idx] +exprs (unique int id: @expr, + int kind: int ref, + int parent: @expr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +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); + +expr_containers (unique int expr: @expr_or_type ref, + int container: @stmt_container ref); + +array_size (unique int ae: @arraylike ref, + int sz: int ref); + +is_delegating (int yield: @yield_expr ref); + +@expr_or_stmt = @expr | @stmt; +@expr_or_type = @expr | @typeexpr; +@expr_parent = @expr_or_stmt | @property | @function_typeexpr; +@arraylike = @array_expr | @array_pattern; +@type_annotation = @typeexpr | @jsdoc_type_expr; +@node_in_stmt_container = @cfg_node | @type_annotation | @toplevel; + +case @expr.kind of + 0 = @label +| 1 = @null_literal +| 2 = @boolean_literal +| 3 = @number_literal +| 4 = @string_literal +| 5 = @regexp_literal +| 6 = @this_expr +| 7 = @array_expr +| 8 = @obj_expr +| 9 = @function_expr +| 10 = @seq_expr +| 11 = @conditional_expr +| 12 = @new_expr +| 13 = @call_expr +| 14 = @dot_expr +| 15 = @index_expr +| 16 = @neg_expr +| 17 = @plus_expr +| 18 = @log_not_expr +| 19 = @bit_not_expr +| 20 = @typeof_expr +| 21 = @void_expr +| 22 = @delete_expr +| 23 = @eq_expr +| 24 = @neq_expr +| 25 = @eqq_expr +| 26 = @neqq_expr +| 27 = @lt_expr +| 28 = @le_expr +| 29 = @gt_expr +| 30 = @ge_expr +| 31 = @lshift_expr +| 32 = @rshift_expr +| 33 = @urshift_expr +| 34 = @add_expr +| 35 = @sub_expr +| 36 = @mul_expr +| 37 = @div_expr +| 38 = @mod_expr +| 39 = @bitor_expr +| 40 = @xor_expr +| 41 = @bitand_expr +| 42 = @in_expr +| 43 = @instanceof_expr +| 44 = @logand_expr +| 45 = @logor_expr +| 47 = @assign_expr +| 48 = @assign_add_expr +| 49 = @assign_sub_expr +| 50 = @assign_mul_expr +| 51 = @assign_div_expr +| 52 = @assign_mod_expr +| 53 = @assign_lshift_expr +| 54 = @assign_rshift_expr +| 55 = @assign_urshift_expr +| 56 = @assign_or_expr +| 57 = @assign_xor_expr +| 58 = @assign_and_expr +| 59 = @preinc_expr +| 60 = @postinc_expr +| 61 = @predec_expr +| 62 = @postdec_expr +| 63 = @par_expr +| 64 = @var_declarator +| 65 = @arrow_function_expr +| 66 = @spread_element +| 67 = @array_pattern +| 68 = @object_pattern +| 69 = @yield_expr +| 70 = @tagged_template_expr +| 71 = @template_literal +| 72 = @template_element +| 73 = @array_comprehension_expr +| 74 = @generator_expr +| 75 = @for_in_comprehension_block +| 76 = @for_of_comprehension_block +| 77 = @legacy_letexpr +| 78 = @var_decl +| 79 = @proper_varaccess +| 80 = @class_expr +| 81 = @super_expr +| 82 = @newtarget_expr +| 83 = @named_import_specifier +| 84 = @import_default_specifier +| 85 = @import_namespace_specifier +| 86 = @named_export_specifier +| 87 = @exp_expr +| 88 = @assign_exp_expr +| 89 = @jsx_element +| 90 = @jsx_qualified_name +| 91 = @jsx_empty_expr +| 92 = @await_expr +| 93 = @function_sent_expr +| 94 = @decorator +| 95 = @export_default_specifier +| 96 = @export_namespace_specifier +| 97 = @bind_expr +| 98 = @external_module_reference +| 99 = @dynamic_import +| 100 = @expression_with_type_arguments +| 101 = @prefix_type_assertion +| 102 = @as_type_assertion +| 103 = @export_varaccess +| 104 = @decorator_list +| 105 = @non_null_assertion +| 106 = @bigint_literal +| 107 = @nullishcoalescing_expr +| 108 = @e4x_xml_anyname +| 109 = @e4x_xml_static_attribute_selector +| 110 = @e4x_xml_dynamic_attribute_selector +| 111 = @e4x_xml_filter_expression +| 112 = @e4x_xml_static_qualident +| 113 = @e4x_xml_dynamic_qualident +| 114 = @e4x_xml_dotdotexpr +| 115 = @import_meta_expr +| 116 = @assignlogandexpr +| 117 = @assignlogorexpr +| 118 = @assignnullishcoalescingexpr +| 119 = @template_pipe_ref +| 120 = @generated_code_expr +| 121 = @satisfies_expr +; + +@varaccess = @proper_varaccess | @export_varaccess; +@varref = @var_decl | @varaccess; + +@identifier = @label | @varref | @type_identifier; + +@literal = @null_literal | @boolean_literal | @number_literal | @string_literal | @regexp_literal | @bigint_literal; + +@propaccess = @dot_expr | @index_expr; + +@invokeexpr = @new_expr | @call_expr; + +@unaryexpr = @neg_expr | @plus_expr | @log_not_expr | @bit_not_expr | @typeof_expr | @void_expr | @delete_expr | @spread_element; + +@equality_test = @eq_expr | @neq_expr | @eqq_expr | @neqq_expr; + +@comparison = @equality_test | @lt_expr | @le_expr | @gt_expr | @ge_expr; + +@binaryexpr = @comparison | @lshift_expr | @rshift_expr | @urshift_expr | @add_expr | @sub_expr | @mul_expr | @div_expr | @mod_expr | @exp_expr | @bitor_expr | @xor_expr | @bitand_expr | @in_expr | @instanceof_expr | @logand_expr | @logor_expr | @nullishcoalescing_expr; + +@assignment = @assign_expr | @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr | @assign_mod_expr | @assign_exp_expr | @assign_lshift_expr | @assign_rshift_expr | @assign_urshift_expr | @assign_or_expr | @assign_xor_expr | @assign_and_expr | @assignlogandexpr | @assignlogorexpr | @assignnullishcoalescingexpr; + +@updateexpr = @preinc_expr | @postinc_expr | @predec_expr | @postdec_expr; + +@pattern = @varref | @array_pattern | @object_pattern; + +@comprehension_expr = @array_comprehension_expr | @generator_expr; + +@comprehension_block = @for_in_comprehension_block | @for_of_comprehension_block; + +@import_specifier = @named_import_specifier | @import_default_specifier | @import_namespace_specifier; + +@exportspecifier = @named_export_specifier | @export_default_specifier | @export_namespace_specifier; + +@type_keyword_operand = @import_declaration | @export_declaration | @import_specifier; + +@type_assertion = @as_type_assertion | @prefix_type_assertion; + +@class_definition = @class_decl_stmt | @class_expr; +@interface_definition = @interface_declaration | @interface_typeexpr; +@class_or_interface = @class_definition | @interface_definition; + +@lexical_decl = @var_decl | @type_decl; +@lexical_access = @varaccess | @local_type_access | @local_var_type_access | @local_namespace_access; +@lexical_ref = @lexical_decl | @lexical_access; + +@e4x_xml_attribute_selector = @e4x_xml_static_attribute_selector | @e4x_xml_dynamic_attribute_selector; +@e4x_xml_qualident = @e4x_xml_static_qualident | @e4x_xml_dynamic_qualident; + +expr_contains_template_tag_location( + int expr: @expr ref, + int location: @location ref +); + +@template_placeholder_tag_parent = @xmlelement | @xmlattribute | @file; + +template_placeholder_tag_info( + unique int node: @template_placeholder_tag, + int parentNode: @template_placeholder_tag_parent ref, + varchar(900) raw: string ref +); + +// scopes +scopes (unique int id: @scope, + int kind: int ref); + +case @scope.kind of + 0 = @global_scope +| 1 = @function_scope +| 2 = @catch_scope +| 3 = @module_scope +| 4 = @block_scope +| 5 = @for_scope +| 6 = @for_in_scope // for-of scopes work the same as for-in scopes +| 7 = @comprehension_block_scope +| 8 = @class_expr_scope +| 9 = @namespace_scope +| 10 = @class_decl_scope +| 11 = @interface_scope +| 12 = @type_alias_scope +| 13 = @mapped_type_scope +| 14 = @enum_scope +| 15 = @external_module_scope +| 16 = @conditional_type_scope; + +scopenodes (unique int node: @ast_node ref, + int scope: @scope ref); + +scopenesting (unique int inner: @scope ref, + int outer: @scope ref); + +// functions +@function = @function_decl_stmt | @function_expr | @arrow_function_expr; + +@parameterized = @function | @catch_clause; +@type_parameterized = @function | @class_or_interface | @type_alias_declaration | @mapped_typeexpr | @infer_typeexpr; + +is_generator (int fun: @function ref); +has_rest_parameter (int fun: @function ref); +is_async (int fun: @function ref); + +// variables and lexically scoped type names +#keyset[scope, name] +variables (unique int id: @variable, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_type_names (unique int id: @local_type_name, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_namespace_names (unique int id: @local_namespace_name, + varchar(900) name: string ref, + int scope: @scope ref); + +is_arguments_object (int id: @variable ref); + +@lexical_name = @variable | @local_type_name | @local_namespace_name; + +@bind_id = @varaccess | @local_var_type_access; +bind (unique int id: @bind_id ref, + int decl: @variable ref); + +decl (unique int id: @var_decl ref, + int decl: @variable ref); + +@typebind_id = @local_type_access | @export_varaccess; +typebind (unique int id: @typebind_id ref, + int decl: @local_type_name ref); + +@typedecl_id = @type_decl | @var_decl; +typedecl (unique int id: @typedecl_id ref, + int decl: @local_type_name ref); + +namespacedecl (unique int id: @var_decl ref, + int decl: @local_namespace_name ref); + +@namespacebind_id = @local_namespace_access | @export_varaccess; +namespacebind (unique int id: @namespacebind_id ref, + int decl: @local_namespace_name ref); + + +// properties in object literals, property patterns in object patterns, and method declarations in classes +#keyset[parent, index] +properties (unique int id: @property, + int parent: @property_parent ref, + int index: int ref, + int kind: int ref, + varchar(900) tostring: string ref); + +case @property.kind of + 0 = @value_property +| 1 = @property_getter +| 2 = @property_setter +| 3 = @jsx_attribute +| 4 = @function_call_signature +| 5 = @constructor_call_signature +| 6 = @index_signature +| 7 = @enum_member +| 8 = @proper_field +| 9 = @parameter_field +| 10 = @static_initializer +; + +@property_parent = @obj_expr | @object_pattern | @class_definition | @jsx_element | @interface_definition | @enum_declaration; +@property_accessor = @property_getter | @property_setter; +@call_signature = @function_call_signature | @constructor_call_signature; +@field = @proper_field | @parameter_field; +@field_or_vardeclarator = @field | @var_declarator; + +is_computed (int id: @property ref); +is_method (int id: @property ref); +is_static (int id: @property ref); +is_abstract_member (int id: @property ref); +is_const_enum (int id: @enum_declaration ref); +is_abstract_class (int id: @class_decl_stmt ref); + +has_public_keyword (int id: @property ref); +has_private_keyword (int id: @property ref); +has_protected_keyword (int id: @property ref); +has_readonly_keyword (int id: @property ref); +has_type_keyword (int id: @type_keyword_operand ref); +is_optional_member (int id: @property ref); +has_definite_assignment_assertion (int id: @field_or_vardeclarator ref); +is_optional_parameter_declaration (unique int parameter: @pattern ref); + +#keyset[constructor, param_index] +parameter_fields( + unique int field: @parameter_field ref, + int constructor: @function_expr ref, + int param_index: int ref +); + +// types +#keyset[parent, idx] +typeexprs ( + unique int id: @typeexpr, + int kind: int ref, + int parent: @typeexpr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref +); + +case @typeexpr.kind of + 0 = @local_type_access +| 1 = @type_decl +| 2 = @keyword_typeexpr +| 3 = @string_literal_typeexpr +| 4 = @number_literal_typeexpr +| 5 = @boolean_literal_typeexpr +| 6 = @array_typeexpr +| 7 = @union_typeexpr +| 8 = @indexed_access_typeexpr +| 9 = @intersection_typeexpr +| 10 = @parenthesized_typeexpr +| 11 = @tuple_typeexpr +| 12 = @keyof_typeexpr +| 13 = @qualified_type_access +| 14 = @generic_typeexpr +| 15 = @type_label +| 16 = @typeof_typeexpr +| 17 = @local_var_type_access +| 18 = @qualified_var_type_access +| 19 = @this_var_type_access +| 20 = @predicate_typeexpr +| 21 = @interface_typeexpr +| 22 = @type_parameter +| 23 = @plain_function_typeexpr +| 24 = @constructor_typeexpr +| 25 = @local_namespace_access +| 26 = @qualified_namespace_access +| 27 = @mapped_typeexpr +| 28 = @conditional_typeexpr +| 29 = @infer_typeexpr +| 30 = @import_type_access +| 31 = @import_namespace_access +| 32 = @import_var_type_access +| 33 = @optional_typeexpr +| 34 = @rest_typeexpr +| 35 = @bigint_literal_typeexpr +| 36 = @readonly_typeexpr +| 37 = @template_literal_typeexpr +; + +@typeref = @typeaccess | @type_decl; +@type_identifier = @type_decl | @local_type_access | @type_label | @local_var_type_access | @local_namespace_access; +@typeexpr_parent = @expr | @stmt | @property | @typeexpr; +@literal_typeexpr = @string_literal_typeexpr | @number_literal_typeexpr | @boolean_literal_typeexpr | @bigint_literal_typeexpr; +@typeaccess = @local_type_access | @qualified_type_access | @import_type_access; +@vartypeaccess = @local_var_type_access | @qualified_var_type_access | @this_var_type_access | @import_var_type_access; +@namespace_access = @local_namespace_access | @qualified_namespace_access | @import_namespace_access; +@import_typeexpr = @import_type_access | @import_namespace_access | @import_var_type_access; + +@function_typeexpr = @plain_function_typeexpr | @constructor_typeexpr; + +// types +types ( + unique int id: @type, + int kind: int ref, + varchar(900) tostring: string ref +); + +#keyset[parent, idx] +type_child ( + int child: @type ref, + int parent: @type ref, + int idx: int ref +); + +case @type.kind of + 0 = @any_type +| 1 = @string_type +| 2 = @number_type +| 3 = @union_type +| 4 = @true_type +| 5 = @false_type +| 6 = @type_reference +| 7 = @object_type +| 8 = @canonical_type_variable_type +| 9 = @typeof_type +| 10 = @void_type +| 11 = @undefined_type +| 12 = @null_type +| 13 = @never_type +| 14 = @plain_symbol_type +| 15 = @unique_symbol_type +| 16 = @objectkeyword_type +| 17 = @intersection_type +| 18 = @tuple_type +| 19 = @lexical_type_variable_type +| 20 = @this_type +| 21 = @number_literal_type +| 22 = @string_literal_type +| 23 = @unknown_type +| 24 = @bigint_type +| 25 = @bigint_literal_type +; + +@boolean_literal_type = @true_type | @false_type; +@symbol_type = @plain_symbol_type | @unique_symbol_type; +@union_or_intersection_type = @union_type | @intersection_type; +@typevariable_type = @canonical_type_variable_type | @lexical_type_variable_type; + +has_asserts_keyword(int node: @predicate_typeexpr ref); + +@typed_ast_node = @expr | @typeexpr | @function; +ast_node_type( + unique int node: @typed_ast_node ref, + int typ: @type ref); + +declared_function_signature( + unique int node: @function ref, + int sig: @signature_type ref +); + +invoke_expr_signature( + unique int node: @invokeexpr ref, + int sig: @signature_type ref +); + +invoke_expr_overload_index( + unique int node: @invokeexpr ref, + int index: int ref +); + +symbols ( + unique int id: @symbol, + int kind: int ref, + varchar(900) name: string ref +); + +symbol_parent ( + unique int symbol: @symbol ref, + int parent: @symbol ref +); + +symbol_module ( + int symbol: @symbol ref, + varchar(900) moduleName: string ref +); + +symbol_global ( + int symbol: @symbol ref, + varchar(900) globalName: string ref +); + +case @symbol.kind of + 0 = @root_symbol +| 1 = @member_symbol +| 2 = @other_symbol +; + +@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 | @external_module_declaration; + +ast_node_symbol( + unique int node: @ast_node_with_symbol ref, + int symbol: @symbol ref); + +type_symbol( + unique int typ: @type_with_symbol ref, + int symbol: @symbol ref); + +#keyset[typ, name] +type_property( + int typ: @type ref, + varchar(900) name: string ref, + int propertyType: @type ref); + +type_alias( + unique int aliasType: @type ref, + int underlyingType: @type ref); + +@literal_type = @string_literal_type | @number_literal_type | @boolean_literal_type | @bigint_literal_type; +@type_with_literal_value = @string_literal_type | @number_literal_type | @bigint_literal_type; +type_literal_value( + unique int typ: @type_with_literal_value ref, + varchar(900) value: string ref); + +signature_types ( + unique int id: @signature_type, + int kind: int ref, + varchar(900) tostring: string ref, + int type_parameters: int ref, + int required_params: int ref +); + +is_abstract_signature( + unique int sig: @signature_type ref +); + +signature_rest_parameter( + unique int sig: @signature_type ref, + int rest_param_arra_type: @type ref +); + +case @signature_type.kind of + 0 = @function_signature_type +| 1 = @constructor_signature_type +; + +#keyset[typ, kind, index] +type_contains_signature ( + int typ: @type ref, + int kind: int ref, // constructor/call/index + int index: int ref, // ordering of overloaded signatures + int sig: @signature_type ref +); + +#keyset[parent, index] +signature_contains_type ( + int child: @type ref, + int parent: @signature_type ref, + int index: int ref +); + +#keyset[sig, index] +signature_parameter_name ( + int sig: @signature_type ref, + int index: int ref, + varchar(900) name: string ref +); + +number_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +string_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +base_type_names( + int typeName: @symbol ref, + int baseTypeName: @symbol ref +); + +self_types( + int typeName: @symbol ref, + int selfType: @type_reference ref +); + +tuple_type_min_length( + unique int typ: @type ref, + int minLength: int ref +); + +tuple_type_rest_index( + unique int typ: @type ref, + int index: int ref +); + +// comments +comments (unique int id: @comment, + int kind: int ref, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(900) tostring: string ref); + +case @comment.kind of + 0 = @slashslash_comment +| 1 = @slashstar_comment +| 2 = @doc_comment +| 3 = @html_comment_start +| 4 = @htmlcommentend; + +@html_comment = @html_comment_start | @htmlcommentend; +@line_comment = @slashslash_comment | @html_comment; +@block_comment = @slashstar_comment | @doc_comment; + +// source lines +lines (unique int id: @line, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(2) terminator: string ref); +indentation (int file: @file ref, + int lineno: int ref, + varchar(1) indentChar: string ref, + int indentDepth: int ref); + +// JavaScript parse errors +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 + 0 = @regexp_alt +| 1 = @regexp_seq +| 2 = @regexp_caret +| 3 = @regexp_dollar +| 4 = @regexp_wordboundary +| 5 = @regexp_nonwordboundary +| 6 = @regexp_positive_lookahead +| 7 = @regexp_negative_lookahead +| 8 = @regexp_star +| 9 = @regexp_plus +| 10 = @regexp_opt +| 11 = @regexp_range +| 12 = @regexp_dot +| 13 = @regexp_group +| 14 = @regexp_normal_constant +| 15 = @regexp_hex_escape +| 16 = @regexp_unicode_escape +| 17 = @regexp_dec_escape +| 18 = @regexp_oct_escape +| 19 = @regexp_ctrl_escape +| 20 = @regexp_char_class_escape +| 21 = @regexp_id_escape +| 22 = @regexp_backref +| 23 = @regexp_char_class +| 24 = @regexp_char_range +| 25 = @regexp_positive_lookbehind +| 26 = @regexp_negative_lookbehind +| 27 = @regexp_unicode_property_escape +| 28 = @regexp_quoted_string +| 29 = @regexp_intersection +| 30 = @regexp_subtraction; + +regexp_parse_errors (unique int id: @regexp_parse_error, + int regexp: @regexpterm ref, + varchar(900) message: string ref); + +@regexp_quantifier = @regexp_star | @regexp_plus | @regexp_opt | @regexp_range; +@regexp_escape = @regexp_char_escape | @regexp_char_class_escape | @regexp_unicode_property_escape; +@regexp_char_escape = @regexp_hex_escape | @regexp_unicode_escape | @regexp_dec_escape | @regexp_oct_escape | @regexp_ctrl_escape | @regexp_id_escape; +@regexp_constant = @regexp_normal_constant | @regexp_char_escape; +@regexp_lookahead = @regexp_positive_lookahead | @regexp_negative_lookahead; +@regexp_lookbehind = @regexp_positive_lookbehind | @regexp_negative_lookbehind; +@regexp_subpattern = @regexp_lookahead | @regexp_lookbehind; +@regexp_anchor = @regexp_dollar | @regexp_caret; + +is_greedy (int id: @regexp_quantifier ref); +range_quantifier_lower_bound (unique int id: @regexp_range ref, int lo: int ref); +range_quantifier_upper_bound (unique int id: @regexp_range ref, int hi: int ref); +is_capture (unique int id: @regexp_group ref, int number: int ref); +is_named_capture (unique int id: @regexp_group ref, string name: string ref); +is_inverted (int id: @regexp_char_class ref); +regexp_const_value (unique int id: @regexp_constant ref, varchar(1) value: string ref); +char_class_escape (unique int id: @regexp_char_class_escape ref, varchar(1) value: string ref); +backref (unique int id: @regexp_backref ref, int value: int ref); +named_backref (unique int id: @regexp_backref ref, string name: string ref); +unicode_property_escapename (unique int id: @regexp_unicode_property_escape ref, string name: string ref); +unicode_property_escapevalue (unique int id: @regexp_unicode_property_escape ref, string value: string ref); + +// tokens +#keyset[toplevel, idx] +tokeninfo (unique int id: @token, + int kind: int ref, + int toplevel: @toplevel ref, + int idx: int ref, + varchar(900) value: string ref); + +case @token.kind of + 0 = @token_eof +| 1 = @token_null_literal +| 2 = @token_boolean_literal +| 3 = @token_numeric_literal +| 4 = @token_string_literal +| 5 = @token_regular_expression +| 6 = @token_identifier +| 7 = @token_keyword +| 8 = @token_punctuator; + +// associate comments with the token immediately following them (which may be EOF) +next_token (int comment: @comment ref, int token: @token ref); + +// JSON +#keyset[parent, idx] +json (unique int id: @json_value, + int kind: int ref, + int parent: @json_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +json_literals (varchar(900) value: string ref, + varchar(900) raw: string ref, + unique int expr: @json_value ref); + +json_properties (int obj: @json_object ref, + varchar(900) property: string ref, + int value: @json_value ref); + +json_errors (unique int id: @json_parse_error, + varchar(900) message: string ref); + +json_locations(unique int locatable: @json_locatable ref, + int location: @location_default ref); + +case @json_value.kind of + 0 = @json_null +| 1 = @json_boolean +| 2 = @json_number +| 3 = @json_string +| 4 = @json_array +| 5 = @json_object; + +@json_parent = @json_object | @json_array | @file; + +@json_locatable = @json_value | @json_parse_error; + +// locations +@ast_node = @toplevel | @stmt | @expr | @property | @typeexpr; + +@locatable = @file + | @ast_node + | @comment + | @line + | @js_parse_error | @regexp_parse_error + | @regexpterm + | @json_locatable + | @token + | @cfg_node + | @jsdoc | @jsdoc_type_expr | @jsdoc_tag + | @yaml_locatable + | @xmllocatable + | @configLocatable + | @template_placeholder_tag; + +hasLocation (unique int locatable: @locatable ref, + int location: @location ref); + +// CFG +entry_cfg_node (unique int id: @entry_node, int container: @stmt_container ref); +exit_cfg_node (unique int id: @exit_node, int container: @stmt_container ref); +guard_node (unique int id: @guard_node, int kind: int ref, int test: @expr ref); +case @guard_node.kind of + 0 = @falsy_guard +| 1 = @truthy_guard; +@condition_guard = @falsy_guard | @truthy_guard; + +@synthetic_cfg_node = @entry_node | @exit_node | @guard_node; +@cfg_node = @synthetic_cfg_node | @expr_parent; + +successor (int pred: @cfg_node ref, int succ: @cfg_node ref); + +// JSDoc comments +jsdoc (unique int id: @jsdoc, varchar(900) description: string ref, int comment: @comment ref); +#keyset[parent, idx] +jsdoc_tags (unique int id: @jsdoc_tag, varchar(900) title: string ref, + int parent: @jsdoc ref, int idx: int ref, varchar(900) tostring: string ref); +jsdoc_tag_descriptions (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); +jsdoc_tag_names (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); + +#keyset[parent, idx] +jsdoc_type_exprs (unique int id: @jsdoc_type_expr, + int kind: int ref, + int parent: @jsdoc_type_expr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); +case @jsdoc_type_expr.kind of + 0 = @jsdoc_any_type_expr +| 1 = @jsdoc_null_type_expr +| 2 = @jsdoc_undefined_type_expr +| 3 = @jsdoc_unknown_type_expr +| 4 = @jsdoc_void_type_expr +| 5 = @jsdoc_identifier_type_expr +| 6 = @jsdoc_applied_type_expr +| 7 = @jsdoc_nullable_type_expr +| 8 = @jsdoc_non_nullable_type_expr +| 9 = @jsdoc_record_type_expr +| 10 = @jsdoc_array_type_expr +| 11 = @jsdoc_union_type_expr +| 12 = @jsdoc_function_type_expr +| 13 = @jsdoc_optional_type_expr +| 14 = @jsdoc_rest_type_expr +| 15 = @jsdoc_qualified_type_expr +; + +#keyset[id, idx] +jsdoc_record_field_name (int id: @jsdoc_record_type_expr ref, int idx: int ref, varchar(900) name: string ref); +jsdoc_prefix_qualifier (int id: @jsdoc_type_expr ref); +jsdoc_has_new_parameter (int fn: @jsdoc_function_type_expr ref); + +@jsdoc_type_expr_parent = @jsdoc_type_expr | @jsdoc_tag; + +jsdoc_errors (unique int id: @jsdoc_error, int tag: @jsdoc_tag ref, varchar(900) message: string ref, varchar(900) tostring: string ref); + +@dataflownode = @expr | @function_decl_stmt | @class_decl_stmt | @namespace_declaration | @enum_declaration | @property; + +@optionalchainable = @call_expr | @propaccess; + +isOptionalChaining(int id: @optionalchainable ref); + +/** + * The time taken for the extraction of a file. + * This table contains non-deterministic content. + * + * The sum of the `time` column for each (`file`, `timerKind`) pair + * is the total time taken for extraction of `file`. The `extractionPhase` + * column provides a granular view of the extraction time of the file. + */ +extraction_time( + int file : @file ref, + // see `com.semmle.js.extractor.ExtractionMetrics.ExtractionPhase`. + int extractionPhase: int ref, + // 0 for the elapsed CPU time in nanoseconds, 1 for the elapsed wallclock time in nanoseconds + int timerKind: int ref, + float time: float ref +) + +/** +* Non-timing related data for the extraction of a single file. +* This table contains non-deterministic content. +*/ +extraction_data( + int file : @file ref, + // the absolute path to the cache file + varchar(900) cacheFile: string ref, + boolean fromCache: boolean ref, + int length: int ref +) + +/*- YAML -*/ + +#keyset[parent, idx] +yaml (unique int id: @yaml_node, + int kind: int ref, + int parent: @yaml_node_parent ref, + int idx: int ref, + string tag: string ref, + string tostring: string ref); + +case @yaml_node.kind of + 0 = @yaml_scalar_node +| 1 = @yaml_mapping_node +| 2 = @yaml_sequence_node +| 3 = @yaml_alias_node +; + +@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node; + +@yaml_node_parent = @yaml_collection_node | @file; + +yaml_anchors (unique int node: @yaml_node ref, + string anchor: string ref); + +yaml_aliases (unique int alias: @yaml_alias_node ref, + string target: string ref); + +yaml_scalars (unique int scalar: @yaml_scalar_node ref, + int style: int ref, + string value: string ref); + +yaml_errors (unique int id: @yaml_error, + string message: string ref); + +yaml_locations(unique int locatable: @yaml_locatable ref, + int location: @location_default ref); + +@yaml_locatable = @yaml_node | @yaml_error; + +/*- XML Files -*/ + +xmlEncoding( + unique int id: @file ref, + string encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/*- Configuration files with key value pairs -*/ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; diff --git a/javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/semmlecode.javascript.dbscheme b/javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/semmlecode.javascript.dbscheme new file mode 100644 index 000000000000..5b5db607d20c --- /dev/null +++ b/javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/semmlecode.javascript.dbscheme @@ -0,0 +1,1193 @@ +/*** Standard fragments ***/ + +/*- Files and folders -*/ + +/** + * The location of an element. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +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 +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @file | @folder + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/*- Lines of code -*/ + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +/*- External data -*/ + +/** + * External data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/*- Source location prefix -*/ + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/*- JavaScript-specific part -*/ + +@location = @location_default + +@sourceline = @locatable; + +filetype( + int file: @file ref, + string filetype: string ref +) + +// top-level code fragments +toplevels (unique int id: @toplevel, + int kind: int ref); + +is_externs (int toplevel: @toplevel ref); + +case @toplevel.kind of + 0 = @script +| 1 = @inline_script +| 2 = @event_handler +| 3 = @javascript_url +| 4 = @template_toplevel; + +is_module (int tl: @toplevel ref); +is_nodejs (int tl: @toplevel ref); +is_es2015_module (int tl: @toplevel ref); +is_closure_module (int tl: @toplevel ref); + +@xml_node_with_code = @xmlelement | @xmlattribute | @template_placeholder_tag; +toplevel_parent_xml_node( + unique int toplevel: @toplevel ref, + int xmlnode: @xml_node_with_code ref); + +xml_element_parent_expression( + unique int xmlnode: @xmlelement ref, + int expression: @expr ref, + int index: int ref); + +// statements +#keyset[parent, idx] +stmts (unique int id: @stmt, + int kind: int 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); + +@stmt_parent = @stmt | @toplevel | @function_expr | @arrow_function_expr | @static_initializer; +@stmt_container = @toplevel | @function | @namespace_declaration | @external_module_declaration | @global_augmentation_declaration; + +case @stmt.kind of + 0 = @empty_stmt +| 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @labeled_stmt +| 5 = @break_stmt +| 6 = @continue_stmt +| 7 = @with_stmt +| 8 = @switch_stmt +| 9 = @return_stmt +| 10 = @throw_stmt +| 11 = @try_stmt +| 12 = @while_stmt +| 13 = @do_while_stmt +| 14 = @for_stmt +| 15 = @for_in_stmt +| 16 = @debugger_stmt +| 17 = @function_decl_stmt +| 18 = @var_decl_stmt +| 19 = @case +| 20 = @catch_clause +| 21 = @for_of_stmt +| 22 = @const_decl_stmt +| 23 = @let_stmt +| 24 = @legacy_let_stmt +| 25 = @for_each_stmt +| 26 = @class_decl_stmt +| 27 = @import_declaration +| 28 = @export_all_declaration +| 29 = @export_default_declaration +| 30 = @export_named_declaration +| 31 = @namespace_declaration +| 32 = @import_equals_declaration +| 33 = @export_assign_declaration +| 34 = @interface_declaration +| 35 = @type_alias_declaration +| 36 = @enum_declaration +| 37 = @external_module_declaration +| 38 = @export_as_namespace_declaration +| 39 = @global_augmentation_declaration +| 40 = @using_decl_stmt +; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @let_stmt | @legacy_let_stmt | @using_decl_stmt; + +@export_declaration = @export_all_declaration | @export_default_declaration | @export_named_declaration; + +@namespace_definition = @namespace_declaration | @enum_declaration; +@type_definition = @class_definition | @interface_declaration | @enum_declaration | @type_alias_declaration | @enum_member; + +is_instantiated(unique int decl: @namespace_declaration ref); + +@declarable_node = @decl_stmt | @namespace_declaration | @class_decl_stmt | @function_decl_stmt | @enum_declaration | @external_module_declaration | @global_augmentation_declaration | @field; +has_declare_keyword(unique int stmt: @declarable_node ref); + +is_for_await_of(unique int forof: @for_of_stmt ref); + +// expressions +#keyset[parent, idx] +exprs (unique int id: @expr, + int kind: int ref, + int parent: @expr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +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); + +expr_containers (unique int expr: @expr_or_type ref, + int container: @stmt_container ref); + +array_size (unique int ae: @arraylike ref, + int sz: int ref); + +is_delegating (int yield: @yield_expr ref); + +@expr_or_stmt = @expr | @stmt; +@expr_or_type = @expr | @typeexpr; +@expr_parent = @expr_or_stmt | @property | @function_typeexpr; +@arraylike = @array_expr | @array_pattern; +@type_annotation = @typeexpr | @jsdoc_type_expr; +@node_in_stmt_container = @cfg_node | @type_annotation | @toplevel; + +case @expr.kind of + 0 = @label +| 1 = @null_literal +| 2 = @boolean_literal +| 3 = @number_literal +| 4 = @string_literal +| 5 = @regexp_literal +| 6 = @this_expr +| 7 = @array_expr +| 8 = @obj_expr +| 9 = @function_expr +| 10 = @seq_expr +| 11 = @conditional_expr +| 12 = @new_expr +| 13 = @call_expr +| 14 = @dot_expr +| 15 = @index_expr +| 16 = @neg_expr +| 17 = @plus_expr +| 18 = @log_not_expr +| 19 = @bit_not_expr +| 20 = @typeof_expr +| 21 = @void_expr +| 22 = @delete_expr +| 23 = @eq_expr +| 24 = @neq_expr +| 25 = @eqq_expr +| 26 = @neqq_expr +| 27 = @lt_expr +| 28 = @le_expr +| 29 = @gt_expr +| 30 = @ge_expr +| 31 = @lshift_expr +| 32 = @rshift_expr +| 33 = @urshift_expr +| 34 = @add_expr +| 35 = @sub_expr +| 36 = @mul_expr +| 37 = @div_expr +| 38 = @mod_expr +| 39 = @bitor_expr +| 40 = @xor_expr +| 41 = @bitand_expr +| 42 = @in_expr +| 43 = @instanceof_expr +| 44 = @logand_expr +| 45 = @logor_expr +| 47 = @assign_expr +| 48 = @assign_add_expr +| 49 = @assign_sub_expr +| 50 = @assign_mul_expr +| 51 = @assign_div_expr +| 52 = @assign_mod_expr +| 53 = @assign_lshift_expr +| 54 = @assign_rshift_expr +| 55 = @assign_urshift_expr +| 56 = @assign_or_expr +| 57 = @assign_xor_expr +| 58 = @assign_and_expr +| 59 = @preinc_expr +| 60 = @postinc_expr +| 61 = @predec_expr +| 62 = @postdec_expr +| 63 = @par_expr +| 64 = @var_declarator +| 65 = @arrow_function_expr +| 66 = @spread_element +| 67 = @array_pattern +| 68 = @object_pattern +| 69 = @yield_expr +| 70 = @tagged_template_expr +| 71 = @template_literal +| 72 = @template_element +| 73 = @array_comprehension_expr +| 74 = @generator_expr +| 75 = @for_in_comprehension_block +| 76 = @for_of_comprehension_block +| 77 = @legacy_letexpr +| 78 = @var_decl +| 79 = @proper_varaccess +| 80 = @class_expr +| 81 = @super_expr +| 82 = @newtarget_expr +| 83 = @named_import_specifier +| 84 = @import_default_specifier +| 85 = @import_namespace_specifier +| 86 = @named_export_specifier +| 87 = @exp_expr +| 88 = @assign_exp_expr +| 89 = @jsx_element +| 90 = @jsx_qualified_name +| 91 = @jsx_empty_expr +| 92 = @await_expr +| 93 = @function_sent_expr +| 94 = @decorator +| 95 = @export_default_specifier +| 96 = @export_namespace_specifier +| 97 = @bind_expr +| 98 = @external_module_reference +| 99 = @dynamic_import +| 100 = @expression_with_type_arguments +| 101 = @prefix_type_assertion +| 102 = @as_type_assertion +| 103 = @export_varaccess +| 104 = @decorator_list +| 105 = @non_null_assertion +| 106 = @bigint_literal +| 107 = @nullishcoalescing_expr +| 108 = @e4x_xml_anyname +| 109 = @e4x_xml_static_attribute_selector +| 110 = @e4x_xml_dynamic_attribute_selector +| 111 = @e4x_xml_filter_expression +| 112 = @e4x_xml_static_qualident +| 113 = @e4x_xml_dynamic_qualident +| 114 = @e4x_xml_dotdotexpr +| 115 = @import_meta_expr +| 116 = @assignlogandexpr +| 117 = @assignlogorexpr +| 118 = @assignnullishcoalescingexpr +| 119 = @template_pipe_ref +| 120 = @generated_code_expr +| 121 = @satisfies_expr +; + +@varaccess = @proper_varaccess | @export_varaccess; +@varref = @var_decl | @varaccess; + +@identifier = @label | @varref | @type_identifier; + +@literal = @null_literal | @boolean_literal | @number_literal | @string_literal | @regexp_literal | @bigint_literal; + +@propaccess = @dot_expr | @index_expr; + +@invokeexpr = @new_expr | @call_expr; + +@unaryexpr = @neg_expr | @plus_expr | @log_not_expr | @bit_not_expr | @typeof_expr | @void_expr | @delete_expr | @spread_element; + +@equality_test = @eq_expr | @neq_expr | @eqq_expr | @neqq_expr; + +@comparison = @equality_test | @lt_expr | @le_expr | @gt_expr | @ge_expr; + +@binaryexpr = @comparison | @lshift_expr | @rshift_expr | @urshift_expr | @add_expr | @sub_expr | @mul_expr | @div_expr | @mod_expr | @exp_expr | @bitor_expr | @xor_expr | @bitand_expr | @in_expr | @instanceof_expr | @logand_expr | @logor_expr | @nullishcoalescing_expr; + +@assignment = @assign_expr | @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr | @assign_mod_expr | @assign_exp_expr | @assign_lshift_expr | @assign_rshift_expr | @assign_urshift_expr | @assign_or_expr | @assign_xor_expr | @assign_and_expr | @assignlogandexpr | @assignlogorexpr | @assignnullishcoalescingexpr; + +@updateexpr = @preinc_expr | @postinc_expr | @predec_expr | @postdec_expr; + +@pattern = @varref | @array_pattern | @object_pattern; + +@comprehension_expr = @array_comprehension_expr | @generator_expr; + +@comprehension_block = @for_in_comprehension_block | @for_of_comprehension_block; + +@import_specifier = @named_import_specifier | @import_default_specifier | @import_namespace_specifier; + +@exportspecifier = @named_export_specifier | @export_default_specifier | @export_namespace_specifier; + +@type_keyword_operand = @import_declaration | @export_declaration | @import_specifier; + +@type_assertion = @as_type_assertion | @prefix_type_assertion; + +@class_definition = @class_decl_stmt | @class_expr; +@interface_definition = @interface_declaration | @interface_typeexpr; +@class_or_interface = @class_definition | @interface_definition; + +@lexical_decl = @var_decl | @type_decl; +@lexical_access = @varaccess | @local_type_access | @local_var_type_access | @local_namespace_access; +@lexical_ref = @lexical_decl | @lexical_access; + +@e4x_xml_attribute_selector = @e4x_xml_static_attribute_selector | @e4x_xml_dynamic_attribute_selector; +@e4x_xml_qualident = @e4x_xml_static_qualident | @e4x_xml_dynamic_qualident; + +expr_contains_template_tag_location( + int expr: @expr ref, + int location: @location ref +); + +@template_placeholder_tag_parent = @xmlelement | @xmlattribute | @file; + +template_placeholder_tag_info( + unique int node: @template_placeholder_tag, + int parentNode: @template_placeholder_tag_parent ref, + varchar(900) raw: string ref +); + +// scopes +scopes (unique int id: @scope, + int kind: int ref); + +case @scope.kind of + 0 = @global_scope +| 1 = @function_scope +| 2 = @catch_scope +| 3 = @module_scope +| 4 = @block_scope +| 5 = @for_scope +| 6 = @for_in_scope // for-of scopes work the same as for-in scopes +| 7 = @comprehension_block_scope +| 8 = @class_expr_scope +| 9 = @namespace_scope +| 10 = @class_decl_scope +| 11 = @interface_scope +| 12 = @type_alias_scope +| 13 = @mapped_type_scope +| 14 = @enum_scope +| 15 = @external_module_scope +| 16 = @conditional_type_scope; + +scopenodes (unique int node: @ast_node ref, + int scope: @scope ref); + +scopenesting (unique int inner: @scope ref, + int outer: @scope ref); + +// functions +@function = @function_decl_stmt | @function_expr | @arrow_function_expr; + +@parameterized = @function | @catch_clause; +@type_parameterized = @function | @class_or_interface | @type_alias_declaration | @mapped_typeexpr | @infer_typeexpr; + +is_generator (int fun: @function ref); +has_rest_parameter (int fun: @function ref); +is_async (int fun: @function ref); + +// variables and lexically scoped type names +#keyset[scope, name] +variables (unique int id: @variable, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_type_names (unique int id: @local_type_name, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_namespace_names (unique int id: @local_namespace_name, + varchar(900) name: string ref, + int scope: @scope ref); + +is_arguments_object (int id: @variable ref); + +@lexical_name = @variable | @local_type_name | @local_namespace_name; + +@bind_id = @varaccess | @local_var_type_access; +bind (unique int id: @bind_id ref, + int decl: @variable ref); + +decl (unique int id: @var_decl ref, + int decl: @variable ref); + +@typebind_id = @local_type_access | @export_varaccess; +typebind (unique int id: @typebind_id ref, + int decl: @local_type_name ref); + +@typedecl_id = @type_decl | @var_decl; +typedecl (unique int id: @typedecl_id ref, + int decl: @local_type_name ref); + +namespacedecl (unique int id: @var_decl ref, + int decl: @local_namespace_name ref); + +@namespacebind_id = @local_namespace_access | @export_varaccess; +namespacebind (unique int id: @namespacebind_id ref, + int decl: @local_namespace_name ref); + + +// properties in object literals, property patterns in object patterns, and method declarations in classes +#keyset[parent, index] +properties (unique int id: @property, + int parent: @property_parent ref, + int index: int ref, + int kind: int ref, + varchar(900) tostring: string ref); + +case @property.kind of + 0 = @value_property +| 1 = @property_getter +| 2 = @property_setter +| 3 = @jsx_attribute +| 4 = @function_call_signature +| 5 = @constructor_call_signature +| 6 = @index_signature +| 7 = @enum_member +| 8 = @proper_field +| 9 = @parameter_field +| 10 = @static_initializer +; + +@property_parent = @obj_expr | @object_pattern | @class_definition | @jsx_element | @interface_definition | @enum_declaration; +@property_accessor = @property_getter | @property_setter; +@call_signature = @function_call_signature | @constructor_call_signature; +@field = @proper_field | @parameter_field; +@field_or_vardeclarator = @field | @var_declarator; + +is_computed (int id: @property ref); +is_method (int id: @property ref); +is_static (int id: @property ref); +is_abstract_member (int id: @property ref); +is_const_enum (int id: @enum_declaration ref); +is_abstract_class (int id: @class_decl_stmt ref); + +has_public_keyword (int id: @property ref); +has_private_keyword (int id: @property ref); +has_protected_keyword (int id: @property ref); +has_readonly_keyword (int id: @property ref); +has_type_keyword (int id: @type_keyword_operand ref); +is_optional_member (int id: @property ref); +has_definite_assignment_assertion (int id: @field_or_vardeclarator ref); +is_optional_parameter_declaration (unique int parameter: @pattern ref); + +#keyset[constructor, param_index] +parameter_fields( + unique int field: @parameter_field ref, + int constructor: @function_expr ref, + int param_index: int ref +); + +// types +#keyset[parent, idx] +typeexprs ( + unique int id: @typeexpr, + int kind: int ref, + int parent: @typeexpr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref +); + +case @typeexpr.kind of + 0 = @local_type_access +| 1 = @type_decl +| 2 = @keyword_typeexpr +| 3 = @string_literal_typeexpr +| 4 = @number_literal_typeexpr +| 5 = @boolean_literal_typeexpr +| 6 = @array_typeexpr +| 7 = @union_typeexpr +| 8 = @indexed_access_typeexpr +| 9 = @intersection_typeexpr +| 10 = @parenthesized_typeexpr +| 11 = @tuple_typeexpr +| 12 = @keyof_typeexpr +| 13 = @qualified_type_access +| 14 = @generic_typeexpr +| 15 = @type_label +| 16 = @typeof_typeexpr +| 17 = @local_var_type_access +| 18 = @qualified_var_type_access +| 19 = @this_var_type_access +| 20 = @predicate_typeexpr +| 21 = @interface_typeexpr +| 22 = @type_parameter +| 23 = @plain_function_typeexpr +| 24 = @constructor_typeexpr +| 25 = @local_namespace_access +| 26 = @qualified_namespace_access +| 27 = @mapped_typeexpr +| 28 = @conditional_typeexpr +| 29 = @infer_typeexpr +| 30 = @import_type_access +| 31 = @import_namespace_access +| 32 = @import_var_type_access +| 33 = @optional_typeexpr +| 34 = @rest_typeexpr +| 35 = @bigint_literal_typeexpr +| 36 = @readonly_typeexpr +| 37 = @template_literal_typeexpr +; + +@typeref = @typeaccess | @type_decl; +@type_identifier = @type_decl | @local_type_access | @type_label | @local_var_type_access | @local_namespace_access; +@typeexpr_parent = @expr | @stmt | @property | @typeexpr; +@literal_typeexpr = @string_literal_typeexpr | @number_literal_typeexpr | @boolean_literal_typeexpr | @bigint_literal_typeexpr; +@typeaccess = @local_type_access | @qualified_type_access | @import_type_access; +@vartypeaccess = @local_var_type_access | @qualified_var_type_access | @this_var_type_access | @import_var_type_access; +@namespace_access = @local_namespace_access | @qualified_namespace_access | @import_namespace_access; +@import_typeexpr = @import_type_access | @import_namespace_access | @import_var_type_access; + +@function_typeexpr = @plain_function_typeexpr | @constructor_typeexpr; + +// types +types ( + unique int id: @type, + int kind: int ref, + varchar(900) tostring: string ref +); + +#keyset[parent, idx] +type_child ( + int child: @type ref, + int parent: @type ref, + int idx: int ref +); + +case @type.kind of + 0 = @any_type +| 1 = @string_type +| 2 = @number_type +| 3 = @union_type +| 4 = @true_type +| 5 = @false_type +| 6 = @type_reference +| 7 = @object_type +| 8 = @canonical_type_variable_type +| 9 = @typeof_type +| 10 = @void_type +| 11 = @undefined_type +| 12 = @null_type +| 13 = @never_type +| 14 = @plain_symbol_type +| 15 = @unique_symbol_type +| 16 = @objectkeyword_type +| 17 = @intersection_type +| 18 = @tuple_type +| 19 = @lexical_type_variable_type +| 20 = @this_type +| 21 = @number_literal_type +| 22 = @string_literal_type +| 23 = @unknown_type +| 24 = @bigint_type +| 25 = @bigint_literal_type +; + +@boolean_literal_type = @true_type | @false_type; +@symbol_type = @plain_symbol_type | @unique_symbol_type; +@union_or_intersection_type = @union_type | @intersection_type; +@typevariable_type = @canonical_type_variable_type | @lexical_type_variable_type; + +has_asserts_keyword(int node: @predicate_typeexpr ref); + +@typed_ast_node = @expr | @typeexpr | @function; +ast_node_type( + unique int node: @typed_ast_node ref, + int typ: @type ref); + +declared_function_signature( + unique int node: @function ref, + int sig: @signature_type ref +); + +invoke_expr_signature( + unique int node: @invokeexpr ref, + int sig: @signature_type ref +); + +invoke_expr_overload_index( + unique int node: @invokeexpr ref, + int index: int ref +); + +symbols ( + unique int id: @symbol, + int kind: int ref, + varchar(900) name: string ref +); + +symbol_parent ( + unique int symbol: @symbol ref, + int parent: @symbol ref +); + +symbol_module ( + int symbol: @symbol ref, + varchar(900) moduleName: string ref +); + +symbol_global ( + int symbol: @symbol ref, + varchar(900) globalName: string ref +); + +case @symbol.kind of + 0 = @root_symbol +| 1 = @member_symbol +| 2 = @other_symbol +; + +@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 | @external_module_declaration; + +ast_node_symbol( + unique int node: @ast_node_with_symbol ref, + int symbol: @symbol ref); + +type_symbol( + unique int typ: @type_with_symbol ref, + int symbol: @symbol ref); + +#keyset[typ, name] +type_property( + int typ: @type ref, + varchar(900) name: string ref, + int propertyType: @type ref); + +type_alias( + unique int aliasType: @type ref, + int underlyingType: @type ref); + +@literal_type = @string_literal_type | @number_literal_type | @boolean_literal_type | @bigint_literal_type; +@type_with_literal_value = @string_literal_type | @number_literal_type | @bigint_literal_type; +type_literal_value( + unique int typ: @type_with_literal_value ref, + varchar(900) value: string ref); + +signature_types ( + unique int id: @signature_type, + int kind: int ref, + varchar(900) tostring: string ref, + int type_parameters: int ref, + int required_params: int ref +); + +is_abstract_signature( + unique int sig: @signature_type ref +); + +signature_rest_parameter( + unique int sig: @signature_type ref, + int rest_param_arra_type: @type ref +); + +case @signature_type.kind of + 0 = @function_signature_type +| 1 = @constructor_signature_type +; + +#keyset[typ, kind, index] +type_contains_signature ( + int typ: @type ref, + int kind: int ref, // constructor/call/index + int index: int ref, // ordering of overloaded signatures + int sig: @signature_type ref +); + +#keyset[parent, index] +signature_contains_type ( + int child: @type ref, + int parent: @signature_type ref, + int index: int ref +); + +#keyset[sig, index] +signature_parameter_name ( + int sig: @signature_type ref, + int index: int ref, + varchar(900) name: string ref +); + +number_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +string_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +base_type_names( + int typeName: @symbol ref, + int baseTypeName: @symbol ref +); + +self_types( + int typeName: @symbol ref, + int selfType: @type_reference ref +); + +tuple_type_min_length( + unique int typ: @type ref, + int minLength: int ref +); + +tuple_type_rest_index( + unique int typ: @type ref, + int index: int ref +); + +// comments +comments (unique int id: @comment, + int kind: int ref, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(900) tostring: string ref); + +case @comment.kind of + 0 = @slashslash_comment +| 1 = @slashstar_comment +| 2 = @doc_comment +| 3 = @html_comment_start +| 4 = @htmlcommentend; + +@html_comment = @html_comment_start | @htmlcommentend; +@line_comment = @slashslash_comment | @html_comment; +@block_comment = @slashstar_comment | @doc_comment; + +// source lines +lines (unique int id: @line, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(2) terminator: string ref); +indentation (int file: @file ref, + int lineno: int ref, + varchar(1) indentChar: string ref, + int indentDepth: int ref); + +// JavaScript parse errors +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 + 0 = @regexp_alt +| 1 = @regexp_seq +| 2 = @regexp_caret +| 3 = @regexp_dollar +| 4 = @regexp_wordboundary +| 5 = @regexp_nonwordboundary +| 6 = @regexp_positive_lookahead +| 7 = @regexp_negative_lookahead +| 8 = @regexp_star +| 9 = @regexp_plus +| 10 = @regexp_opt +| 11 = @regexp_range +| 12 = @regexp_dot +| 13 = @regexp_group +| 14 = @regexp_normal_constant +| 15 = @regexp_hex_escape +| 16 = @regexp_unicode_escape +| 17 = @regexp_dec_escape +| 18 = @regexp_oct_escape +| 19 = @regexp_ctrl_escape +| 20 = @regexp_char_class_escape +| 21 = @regexp_id_escape +| 22 = @regexp_backref +| 23 = @regexp_char_class +| 24 = @regexp_char_range +| 25 = @regexp_positive_lookbehind +| 26 = @regexp_negative_lookbehind +| 27 = @regexp_unicode_property_escape +| 28 = @regexp_quoted_string +| 29 = @regexp_intersection +| 30 = @regexp_subtraction; + +regexp_parse_errors (unique int id: @regexp_parse_error, + int regexp: @regexpterm ref, + varchar(900) message: string ref); + +@regexp_quantifier = @regexp_star | @regexp_plus | @regexp_opt | @regexp_range; +@regexp_escape = @regexp_char_escape | @regexp_char_class_escape | @regexp_unicode_property_escape; +@regexp_char_escape = @regexp_hex_escape | @regexp_unicode_escape | @regexp_dec_escape | @regexp_oct_escape | @regexp_ctrl_escape | @regexp_id_escape; +@regexp_constant = @regexp_normal_constant | @regexp_char_escape; +@regexp_lookahead = @regexp_positive_lookahead | @regexp_negative_lookahead; +@regexp_lookbehind = @regexp_positive_lookbehind | @regexp_negative_lookbehind; +@regexp_subpattern = @regexp_lookahead | @regexp_lookbehind; +@regexp_anchor = @regexp_dollar | @regexp_caret; + +is_greedy (int id: @regexp_quantifier ref); +range_quantifier_lower_bound (unique int id: @regexp_range ref, int lo: int ref); +range_quantifier_upper_bound (unique int id: @regexp_range ref, int hi: int ref); +is_capture (unique int id: @regexp_group ref, int number: int ref); +is_named_capture (unique int id: @regexp_group ref, string name: string ref); +is_inverted (int id: @regexp_char_class ref); +regexp_const_value (unique int id: @regexp_constant ref, varchar(1) value: string ref); +char_class_escape (unique int id: @regexp_char_class_escape ref, varchar(1) value: string ref); +backref (unique int id: @regexp_backref ref, int value: int ref); +named_backref (unique int id: @regexp_backref ref, string name: string ref); +unicode_property_escapename (unique int id: @regexp_unicode_property_escape ref, string name: string ref); +unicode_property_escapevalue (unique int id: @regexp_unicode_property_escape ref, string value: string ref); + +// tokens +#keyset[toplevel, idx] +tokeninfo (unique int id: @token, + int kind: int ref, + int toplevel: @toplevel ref, + int idx: int ref, + varchar(900) value: string ref); + +case @token.kind of + 0 = @token_eof +| 1 = @token_null_literal +| 2 = @token_boolean_literal +| 3 = @token_numeric_literal +| 4 = @token_string_literal +| 5 = @token_regular_expression +| 6 = @token_identifier +| 7 = @token_keyword +| 8 = @token_punctuator; + +// associate comments with the token immediately following them (which may be EOF) +next_token (int comment: @comment ref, int token: @token ref); + +// JSON +#keyset[parent, idx] +json (unique int id: @json_value, + int kind: int ref, + int parent: @json_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +json_literals (varchar(900) value: string ref, + varchar(900) raw: string ref, + unique int expr: @json_value ref); + +json_properties (int obj: @json_object ref, + varchar(900) property: string ref, + int value: @json_value ref); + +json_errors (unique int id: @json_parse_error, + varchar(900) message: string ref); + +json_locations(unique int locatable: @json_locatable ref, + int location: @location_default ref); + +case @json_value.kind of + 0 = @json_null +| 1 = @json_boolean +| 2 = @json_number +| 3 = @json_string +| 4 = @json_array +| 5 = @json_object; + +@json_parent = @json_object | @json_array | @file; + +@json_locatable = @json_value | @json_parse_error; + +// locations +@ast_node = @toplevel | @stmt | @expr | @property | @typeexpr; + +@locatable = @file + | @ast_node + | @comment + | @line + | @js_parse_error | @regexp_parse_error + | @regexpterm + | @json_locatable + | @token + | @cfg_node + | @jsdoc | @jsdoc_type_expr | @jsdoc_tag + | @yaml_locatable + | @xmllocatable + | @configLocatable + | @template_placeholder_tag; + +hasLocation (unique int locatable: @locatable ref, + int location: @location ref); + +// CFG +entry_cfg_node (unique int id: @entry_node, int container: @stmt_container ref); +exit_cfg_node (unique int id: @exit_node, int container: @stmt_container ref); +guard_node (unique int id: @guard_node, int kind: int ref, int test: @expr ref); +case @guard_node.kind of + 0 = @falsy_guard +| 1 = @truthy_guard; +@condition_guard = @falsy_guard | @truthy_guard; + +@synthetic_cfg_node = @entry_node | @exit_node | @guard_node; +@cfg_node = @synthetic_cfg_node | @expr_parent; + +successor (int pred: @cfg_node ref, int succ: @cfg_node ref); + +// JSDoc comments +jsdoc (unique int id: @jsdoc, varchar(900) description: string ref, int comment: @comment ref); +#keyset[parent, idx] +jsdoc_tags (unique int id: @jsdoc_tag, varchar(900) title: string ref, + int parent: @jsdoc ref, int idx: int ref, varchar(900) tostring: string ref); +jsdoc_tag_descriptions (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); +jsdoc_tag_names (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); + +#keyset[parent, idx] +jsdoc_type_exprs (unique int id: @jsdoc_type_expr, + int kind: int ref, + int parent: @jsdoc_type_expr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); +case @jsdoc_type_expr.kind of + 0 = @jsdoc_any_type_expr +| 1 = @jsdoc_null_type_expr +| 2 = @jsdoc_undefined_type_expr +| 3 = @jsdoc_unknown_type_expr +| 4 = @jsdoc_void_type_expr +| 5 = @jsdoc_named_type_expr +| 6 = @jsdoc_applied_type_expr +| 7 = @jsdoc_nullable_type_expr +| 8 = @jsdoc_non_nullable_type_expr +| 9 = @jsdoc_record_type_expr +| 10 = @jsdoc_array_type_expr +| 11 = @jsdoc_union_type_expr +| 12 = @jsdoc_function_type_expr +| 13 = @jsdoc_optional_type_expr +| 14 = @jsdoc_rest_type_expr +; + +#keyset[id, idx] +jsdoc_record_field_name (int id: @jsdoc_record_type_expr ref, int idx: int ref, varchar(900) name: string ref); +jsdoc_prefix_qualifier (int id: @jsdoc_type_expr ref); +jsdoc_has_new_parameter (int fn: @jsdoc_function_type_expr ref); + +@jsdoc_type_expr_parent = @jsdoc_type_expr | @jsdoc_tag; + +jsdoc_errors (unique int id: @jsdoc_error, int tag: @jsdoc_tag ref, varchar(900) message: string ref, varchar(900) tostring: string ref); + +@dataflownode = @expr | @function_decl_stmt | @class_decl_stmt | @namespace_declaration | @enum_declaration | @property; + +@optionalchainable = @call_expr | @propaccess; + +isOptionalChaining(int id: @optionalchainable ref); + +/** + * The time taken for the extraction of a file. + * This table contains non-deterministic content. + * + * The sum of the `time` column for each (`file`, `timerKind`) pair + * is the total time taken for extraction of `file`. The `extractionPhase` + * column provides a granular view of the extraction time of the file. + */ +extraction_time( + int file : @file ref, + // see `com.semmle.js.extractor.ExtractionMetrics.ExtractionPhase`. + int extractionPhase: int ref, + // 0 for the elapsed CPU time in nanoseconds, 1 for the elapsed wallclock time in nanoseconds + int timerKind: int ref, + float time: float ref +) + +/** +* Non-timing related data for the extraction of a single file. +* This table contains non-deterministic content. +*/ +extraction_data( + int file : @file ref, + // the absolute path to the cache file + varchar(900) cacheFile: string ref, + boolean fromCache: boolean ref, + int length: int ref +) + +/*- YAML -*/ + +#keyset[parent, idx] +yaml (unique int id: @yaml_node, + int kind: int ref, + int parent: @yaml_node_parent ref, + int idx: int ref, + string tag: string ref, + string tostring: string ref); + +case @yaml_node.kind of + 0 = @yaml_scalar_node +| 1 = @yaml_mapping_node +| 2 = @yaml_sequence_node +| 3 = @yaml_alias_node +; + +@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node; + +@yaml_node_parent = @yaml_collection_node | @file; + +yaml_anchors (unique int node: @yaml_node ref, + string anchor: string ref); + +yaml_aliases (unique int alias: @yaml_alias_node ref, + string target: string ref); + +yaml_scalars (unique int scalar: @yaml_scalar_node ref, + int style: int ref, + string value: string ref); + +yaml_errors (unique int id: @yaml_error, + string message: string ref); + +yaml_locations(unique int locatable: @yaml_locatable ref, + int location: @location_default ref); + +@yaml_locatable = @yaml_node | @yaml_error; + +/*- XML Files -*/ + +xmlEncoding( + unique int id: @file ref, + string encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/*- Configuration files with key value pairs -*/ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; diff --git a/javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/upgrade.properties b/javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/upgrade.properties new file mode 100644 index 000000000000..9812f386f8c3 --- /dev/null +++ b/javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/upgrade.properties @@ -0,0 +1,2 @@ +description: split up qualified names in jsdoc type exprs +compatibility: backwards From cccea919b465048d9b7f6040ce24a67353bb8a21 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 24 Mar 2025 15:11:11 +0100 Subject: [PATCH 13/15] JS: Update stats file --- javascript/ql/lib/semmlecode.javascript.dbscheme.stats | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmlecode.javascript.dbscheme.stats b/javascript/ql/lib/semmlecode.javascript.dbscheme.stats index 0b8848ff1d6f..51889bd9286f 100644 --- a/javascript/ql/lib/semmlecode.javascript.dbscheme.stats +++ b/javascript/ql/lib/semmlecode.javascript.dbscheme.stats @@ -1334,10 +1334,14 @@ 8 -@jsdoc_named_type_expr +@jsdoc_identifier_type_expr 18639 +@jsdoc_qualified_type_expr +1000 + + @jsdoc_applied_type_expr 303 From 86ae8012beaa51b8016109215be8832bbd863bc7 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 27 Mar 2025 11:31:36 +0100 Subject: [PATCH 14/15] Expand downgrade script --- .../jsdoc_type_exprs.ql | 37 +++++++++++++++++++ .../upgrade.properties | 2 + 2 files changed, 39 insertions(+) create mode 100644 javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/jsdoc_type_exprs.ql diff --git a/javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/jsdoc_type_exprs.ql b/javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/jsdoc_type_exprs.ql new file mode 100644 index 000000000000..4f12eb443f93 --- /dev/null +++ b/javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/jsdoc_type_exprs.ql @@ -0,0 +1,37 @@ +// Removes all nodes nested inside a qualified type access, +// and changes qualified type access nodes to "named type" nodes. +// +/* + * jsdoc_type_exprs (unique int id: @jsdoc_type_expr, + * int kind: int ref, + * int parent: @jsdoc_type_expr_parent ref, + * int idx: int ref, + * varchar(900) tostring: string ref); + */ + +class JSDocTypeExprParent extends @jsdoc_type_expr_parent { + string toString() { none() } +} + +class JSDocTypeExpr extends @jsdoc_type_expr { + string toString() { none() } + + JSDocTypeExpr getChild(int n) { jsdoc_type_exprs(result, _, this, n, _) } + + int getNewKind() { jsdoc_type_exprs(this, result, _, _, _) } + + predicate shouldRemove() { this = any(JSDocQualifiedTypeAccess a).getChild(_) } +} + +class JSDocQualifiedTypeAccess extends @jsdoc_qualified_type_expr, JSDocTypeExpr { + override int getNewKind() { + result = 5 + /* 5 = @jsdoc_named_type_expr */ + } +} + +from JSDocTypeExpr node, JSDocTypeExprParent parent, int idx, string tostring +where + jsdoc_type_exprs(node, _, parent, idx, tostring) and + not node.shouldRemove() +select node, node.getNewKind(), parent, idx, tostring diff --git a/javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/upgrade.properties b/javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/upgrade.properties index 9812f386f8c3..d67984c6ef9e 100644 --- a/javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/upgrade.properties +++ b/javascript/downgrades/ccefb5e2d49318eea4aeafd4c6ae2af9f94ac72a/upgrade.properties @@ -1,2 +1,4 @@ description: split up qualified names in jsdoc type exprs compatibility: backwards + +jsdoc_type_exprs.rel: run jsdoc_type_exprs.ql From 441ca1c862f884e7ac9f412ce1c9e47e50e00e84 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 27 Mar 2025 11:54:01 +0100 Subject: [PATCH 15/15] JS: Change compatibility of upgrade script to partial --- .../5b5db607d20c7b449cef2d1c926b24d77c69bebb/upgrade.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/lib/upgrades/5b5db607d20c7b449cef2d1c926b24d77c69bebb/upgrade.properties b/javascript/ql/lib/upgrades/5b5db607d20c7b449cef2d1c926b24d77c69bebb/upgrade.properties index 9812f386f8c3..c26b1e1de099 100644 --- a/javascript/ql/lib/upgrades/5b5db607d20c7b449cef2d1c926b24d77c69bebb/upgrade.properties +++ b/javascript/ql/lib/upgrades/5b5db607d20c7b449cef2d1c926b24d77c69bebb/upgrade.properties @@ -1,2 +1,2 @@ description: split up qualified names in jsdoc type exprs -compatibility: backwards +compatibility: partial