From 7816c9ef9b1b89429f674084f3fa8907bf3fe533 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 25 Apr 2023 12:28:30 -0700 Subject: [PATCH 001/500] Adds .DS_Store to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index c76d54cb8..9b72fd034 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ Cargo.lock /.crates.toml /.crates2.json /bin/ + +# MacOS stuff +.DS_Store \ No newline at end of file From 0c8cc6b38e7149b83167b8defa1a99fde4bf5eb7 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 25 Apr 2023 12:28:53 -0700 Subject: [PATCH 002/500] Adds JS stuff to be added; plus some integrations --- .../.gitignore | 4 + .../Cargo.toml | 19 + .../README.md | 38 + .../base_syntax.html | 1411 ++++++ .../bindings/rust/lib.rs | 7 + .../package.json | 20 + .../simple.html | 1411 ++++++ .../src/builtins.cfg | 1 + .../src/builtins.js | 0 .../src/stack-graphs.tsg | 3764 +++++++++++++++++ .../test.html | 1411 ++++++ .../test/base_syntax.js | 66 + .../default_arguments_from_enclosing_scope.js | 8 + .../default_arguments_from_other_arguments.js | 10 + .../test/binding/destructuring_assignments.js | 19 + ...ents_with_defaults_from_enclosing_scope.js | 5 + ...ents_with_defaults_from_other_variables.js | 6 + .../test/binding/destructuring_parameters.js | 7 + .../binding/object_assignment_patterns.js | 4 + .../test/binding/simple.js | 30 + .../test/bug_regressions/2141.js | 14 + .../test/bug_regressions/2227.js | 17 + .../test/bug_regressions/2291.js | 28 + .../class_declaration.js | 6 + .../classes_and_instances/class_expression.js | 10 + .../class_expression_superclasses.js | 15 + .../class_expression_this_field_access.js | 19 + .../field_declaration.js | 10 + .../function_class_this_field_access.js | 15 + .../method_call_this_argument.js | 22 + .../method_definition.js | 12 + .../classes_and_instances/superclasses.js | 15 + .../this_field_access.js | 19 + .../test/compound_literals/arrays.js | 5 + .../compound_literals/object_extend_method.js | 15 + .../test/compound_literals/objects.js | 15 + .../test/control_flow_statements/dowhile.js | 10 + .../test/control_flow_statements/for.js | 17 + .../test/control_flow_statements/forin.js | 11 + .../test/control_flow_statements/if.js | 14 + .../test/control_flow_statements/try.js | 22 + .../test/control_flow_statements/while.js | 10 + .../test/control_flow_statements/with.js | 13 + .../functions_and_calls/arguments_variable.js | 22 + ...alues_with_param_lists_and_block_bodies.js | 13 + ...values_with_param_lists_and_expr_bodies.js | 11 + ...lues_with_single_param_and_block_bodies.js | 13 + ...alues_with_single_param_and_expr_bodies.js | 11 + .../functions_and_calls/call_arguments.js | 7 + .../function_declarations.js | 13 + .../functions_and_calls/function_values.js | 15 + .../generator_function_declarations.js | 13 + .../generator_function_values.js | 15 + .../commonjs_imports_and_exports.js | 16 + .../es6_imports_and_exports.js | 193 + .../test/simple_expressions/comma.js | 7 + .../simple_expressions/template_strings.js | 4 + .../test/simple_expressions/ternary.js | 4 + .../test/simple_expressions/variables.js | 9 + 59 files changed, 8941 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-javascript/.gitignore create mode 100644 languages/tree-sitter-stack-graphs-javascript/Cargo.toml create mode 100644 languages/tree-sitter-stack-graphs-javascript/README.md create mode 100644 languages/tree-sitter-stack-graphs-javascript/base_syntax.html create mode 100644 languages/tree-sitter-stack-graphs-javascript/bindings/rust/lib.rs create mode 100644 languages/tree-sitter-stack-graphs-javascript/package.json create mode 100644 languages/tree-sitter-stack-graphs-javascript/simple.html create mode 100644 languages/tree-sitter-stack-graphs-javascript/src/builtins.cfg create mode 100644 languages/tree-sitter-stack-graphs-javascript/src/builtins.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg create mode 100644 languages/tree-sitter-stack-graphs-javascript/test.html create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/binding/default_arguments_from_enclosing_scope.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/binding/default_arguments_from_other_arguments.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_assignments.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_assignments_with_defaults_from_enclosing_scope.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_assignments_with_defaults_from_other_variables.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_parameters.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/binding/object_assignment_patterns.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/binding/simple.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/bug_regressions/2141.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/bug_regressions/2227.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/bug_regressions/2291.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_declaration.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_expression.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_expression_superclasses.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_expression_this_field_access.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/field_declaration.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/function_class_this_field_access.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/method_call_this_argument.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/method_definition.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/superclasses.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/this_field_access.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/compound_literals/arrays.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/compound_literals/object_extend_method.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/compound_literals/objects.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/dowhile.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/for.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/forin.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/if.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/try.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/while.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/with.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arguments_variable.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_param_lists_and_block_bodies.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_param_lists_and_expr_bodies.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_single_param_and_block_bodies.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_single_param_and_expr_bodies.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/call_arguments.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/function_declarations.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/function_values.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/generator_function_declarations.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/generator_function_values.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/imports_and_exports/commonjs_imports_and_exports.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/imports_and_exports/es6_imports_and_exports.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/comma.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/template_strings.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/ternary.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variables.js diff --git a/languages/tree-sitter-stack-graphs-javascript/.gitignore b/languages/tree-sitter-stack-graphs-javascript/.gitignore new file mode 100644 index 000000000..186883d53 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/.gitignore @@ -0,0 +1,4 @@ +/Cargo.lock +/node_modules +/package-lock.json +/target diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml new file mode 100644 index 000000000..f7d6607e4 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "tree-sitter-stack-graphs-javascript" +version = "0.1.0" +description = "Stack graphs definition for JavaScript using tree-sitter-javascript" +readme = "README.md" +keywords = ["tree-sitter", "stack-graphs", "javascript"] +authors = ["Beka Valentine "] +edition = "2018" + +include = [ + "bindings/rust", + "src" +] + +[lib] +path = "bindings/rust/lib.rs" + +[dev-dependencies] +tree-sitter-stack-graphs = "~0.6.0" diff --git a/languages/tree-sitter-stack-graphs-javascript/README.md b/languages/tree-sitter-stack-graphs-javascript/README.md new file mode 100644 index 000000000..8e5adec15 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/README.md @@ -0,0 +1,38 @@ +# tree-sitter-stack-graphs definition for JavaScript + +This project defines tree-sitter-stack-graphs rules for JavaScript using the [tree-sitter-javascript](https://www.npmjs.com/package/tree-sitter-javascript) grammar. + +## Development + +The project is organized as follows: + +- The stack graph rules are defined in `src/stack-graphs.tsg`. +- Builtins sources and configuration are defined in `src/builtins.js` and `builtins.cfg` respectively. +- Tests are put into the `test` directory. + +Make sure all development dependencies are installed by running: + + npm install + +Run all tests in the project by executing the following: + + npm test + +Parse and test a single file by executing the following commands: + + npm run parse-file test/test.js + npm run test-file test/test.js + +Additional flags can be passed to these commands as well. For example, to generate a visualization for the test, execute: + + npm run test-file -- -V test/test.js + +To generate the visualization regardless of test outcome, execute: + + npm run test-file -- -V --output-mode=always test/test.js + +These commands should be enough for regular development. If necessary, the `tree-sitter-stack-graphs` command can be invoked directly as well, by executing: + + npx tree-sitter-stack-graphs + +Go to https://crates.io/crates/tree-sitter-stack-graphs for links to examples and documentation. diff --git a/languages/tree-sitter-stack-graphs-javascript/base_syntax.html b/languages/tree-sitter-stack-graphs-javascript/base_syntax.html new file mode 100644 index 000000000..30842a7cc --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/base_syntax.html @@ -0,0 +1,1411 @@ + + + + + + + +test/base_syntax.js + + + + + + + + + + + + + + + + + + + + +
+
+ + + + diff --git a/languages/tree-sitter-stack-graphs-javascript/bindings/rust/lib.rs b/languages/tree-sitter-stack-graphs-javascript/bindings/rust/lib.rs new file mode 100644 index 000000000..84d0bbe7e --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/bindings/rust/lib.rs @@ -0,0 +1,7 @@ +/// The stack graphs query for this language +pub const STACK_GRAPHS_QUERY: &str = include_str!("../../src/stack-graphs.tsg"); + +/// The stack graphs builtins configuration for this language +pub const STACK_GRAPHS_BUILTINS_CONFIG: &str = include_str!("../../src/builtins.cfg"); +/// The stack graphs builtins source for this language +pub const STACK_GRAPHS_BUILTINS_SOURCE: &str = include_str!("../../src/builtins.js"); diff --git a/languages/tree-sitter-stack-graphs-javascript/package.json b/languages/tree-sitter-stack-graphs-javascript/package.json new file mode 100644 index 000000000..861ceeb58 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/package.json @@ -0,0 +1,20 @@ +{ + "name": "tree-sitter-stack-graphs-javascript", + "version": "0.1.0", + "description": "Stack graphs definition for JavaScript using tree-sitter-javascript", + "author": "Beka Valentine ", + "keywords": [ + "tree-sitter", + "stack-graphs", + "javascript" + ], + "devDependencies": { + "tree-sitter-stack-graphs": "~0.6.0", + "tree-sitter-javascript": "github:tree-sitter/tree-sitter-javascript#fdeb68ac8d2bd5a78b943528bb68ceda3aade2eb" + }, + "scripts": { + "test": "npx tree-sitter-stack-graphs test --grammar node_modules/tree-sitter-javascript --tsg src/stack-graphs --builtins src/builtins test", + "parse-file": "npx tree-sitter-stack-graphs parse --grammar node_modules/tree-sitter-javascript", + "test-file": "npx tree-sitter-stack-graphs test --grammar node_modules/tree-sitter-javascript --tsg src/stack-graphs --builtins src/builtins" + } +} \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/simple.html b/languages/tree-sitter-stack-graphs-javascript/simple.html new file mode 100644 index 000000000..9ef7c5c6c --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/simple.html @@ -0,0 +1,1411 @@ + + + + + + + +test/binding/simple.js + + + + + + + + + + + + + + + + + + + + +
+
+ + + + diff --git a/languages/tree-sitter-stack-graphs-javascript/src/builtins.cfg b/languages/tree-sitter-stack-graphs-javascript/src/builtins.cfg new file mode 100644 index 000000000..d685061be --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/src/builtins.cfg @@ -0,0 +1 @@ +[globals] diff --git a/languages/tree-sitter-stack-graphs-javascript/src/builtins.js b/languages/tree-sitter-stack-graphs-javascript/src/builtins.js new file mode 100644 index 000000000..e69de29bb diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg new file mode 100644 index 000000000..c8056e069 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -0,0 +1,3764 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Stack graphs definition for JavaScript +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Global Variables +;; ^^^^^^^^^^^^^^^^ + +global FILE_PATH +global ROOT_NODE +global JUMP_TO_SCOPE_NODE + +;; Attribute Shorthands +;; ^^^^^^^^^^^^^^^^^^^^ + +attribute node_definition = node => type = "pop_symbol", node_symbol = node, is_definition +attribute node_reference = node => type = "push_symbol", node_symbol = node, is_reference +attribute pop_node = node => type = "pop_symbol", node_symbol = node +attribute pop_scoped_node = node => type = "pop_scoped_symbol", node_symbol = node +attribute pop_scoped_symbol = symbol => type = "pop_scoped_symbol", symbol = symbol +attribute pop_symbol = symbol => type = "pop_symbol", symbol = symbol +attribute push_node = node => type = "push_symbol", node_symbol = node +attribute push_scoped_node = node => type = "push_scoped_symbol", node_symbol = node +attribute push_scoped_symbol = symbol => type = "push_scoped_symbol", symbol = symbol +attribute push_symbol = symbol => type = "push_symbol", symbol = symbol +attribute scoped_node_definition = node => type = "pop_scoped_symbol", node_symbol = node, is_definition +attribute scoped_node_reference = node => type = "push_scoped_symbol", node_symbol = node, is_reference +attribute symbol_definition = symbol => type = "pop_symbol", symbol = symbol, is_definition +attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, is_reference + +attribute node_symbol = node => symbol = (source-text node), source_node = node + +;; Stack Graph Rules +;; ^^^^^^^^^^^^^^^^^ + + + + + + + + + + + + + + + + + + + +;; # JavaScript + +;; This file defines StackGraph queries for JavaScript. It is written as a +;; semi-literate file, which is to say, comments starting with `;;` can be +;; treated as Markdown. This file can therefore be converted into a +;; corresponding pure Markdown document by removing the StackGraph comments, and +;; wrapping the uncommented code in Markdown code blocks. + +;; This file has a number of sections that it's divided into, and it's useful to +;; provide an overview here. Aside from conventions, the queries are broken up +;; into groups by what kind of syntactic objects the group covers. There are +;; Programs, Statements, Expressions, Patterns, and Special Cases. + +;; Within each major section, we break things down by the particular syntactic +;; form under consideration. Some particular syntactic forms are not one of the +;; main forms listed, but are tightly associated with other forms -- for +;; example, the branches of an `if` statement are not statements nor +;; expressions, they're simply components of an `if` statement. In that +;; situation, we group them with the primary statement that they're associated +;; with, where possible, and nearby when not. + +;; Additionally, some syntactic constructs have arbitrary numbers of child +;; nodes, which requires us to explain how to relate them as sequences of +;; nodes. In such cases, we have associated queries with the node type in +;; question. + +;; ## Design Conventions + +;; The general convention for how JavaScript is translated into a Stack Graph is +;; to treat the graph as a reverse Control Flow Graph. There are some corner +;; cases for which that analogy doesn't quite work, but it's sufficient for +;; conveying the overall approach. Many things matter for name resolution in a +;; Control Flow Graph, but one of the only ones we can really encode into a +;; Stack Graph, and arguably the most important one, is the flow of the variable +;; environment, and so we create scope nodes for those. + +;; In particular, for each node, during an execution traversal, there is an +;; incoming variable environment that the node will be executed in, and an +;; outgoing variable environment that resulted from executing the node and all +;; the various variable assignments and updates inside it. + +;; An example helps, so let's consider a simplified case: `if` statement with a +;; mandatory `else` branch. If we were to implement an execution function for +;; this fictionalized language, there would be some environment that goes into +;; the execution at the whole `if-then-else` statement, an environment that goes +;; into the evaluation of the test, an environment that comes out of the test +;; (because the test could be something like `x++` which changes the +;; environment), an environment which goes into each branch (which happens to be +;; the same one that came out of the test), and an environment that comes out of +;; each of the branches. So each major AST node has a pair of environments +;; associated with it: the incoming one to execute it in, and the outcoming node +;; that resulted from executing. + +;; We therefore would implement `if-then-else` statements like so: + +;; ``````stgdoc +;; (if_then_else +;; (_)@test +;; (_)@consequent +;; (_)alternative)@if_stmt { +;; +;; edge @test.before_scope -> @if_stmt.before_scope +;; edge @consequent.before_scope -> @test.after_scope +;; edge @alternative.before_scope -> @test.after_scope +;; edge @if_stmt.after_scope -> @consequent.after_scope +;; edge @if_stmt.after_scope -> @alternative.after_scope +;; +;; } +;; `````` +;; +;; Another important way that things build scopes is through values. When an +;; expression is executed and returns a value, that value in many ways acts like +;; a sub-environment, at least in that the value has different parts that can be +;; accessed in various ways. For a simple value, as constructed by a number +;; literal expression, the number itself has no parts. So it has an associated +;; value scope node in the graph, but no edges coming off that: + +;; ``````stgdoc +;; (number)@num { +;; attr @num.value "pop" = "NUM_VAL" +;; } +;; `````` + +;; Why we use a `pop` attribute here isn't deeply important so we'll gloss over +;; it. + +;; All kinds of expressions have values, what precisely goes into them depends +;; on what the expression is. Objects, for instance, would have corresponding +;; values that point to the values of each of the keys in the object. Arrays +;; would have values that point to the values of each of the indexes. + +;; The primary purpose of values is to act as the targets of assignments, so +;; that names can resolve to something in code. Normally we care only about the +;; location of the assignment, of course, but we also need to be able to do +;; further lookup on the values. For instance, in an expression like `x.y.z`, +;; we need to look up `x` of course, but also then further look up `y` on that, +;; and then `z`. So whatever `x` is assigned to has to also be present in the +;; graph as something which can itself have stuff hanging off it that can be +;; used for lookup. + +;; If you were to run some JavaScript to test whether or not number literals +;; have parts (really, members/fields), you'd discover that actually they do, +;; but not because of which number they are. Rather, their parts are for builtin +;; functionality like `toString`. To handle this, we can point the value to some +;; shared global variable that represents the prototype for the number, like so: + +;; ``````stgdoc +;; (number)@num { +;; attr @num.value "pop" = "NUM_VAL" +;; edge @num.value -> @num::number_prototype +;; } +;; `````` + +;; In the preamble definition for the `program` node type, we could then also +;; want to define number prototype, something like this: + +;; ``````stgdoc +;; (program)@prog { +;; +;; ... +;; +;; let @prog::number_prototype = @prog.number_prototype +;; edge @prog.number_prototype -> @prog.number_prototype_toString_method_value +;; edge @prog.number_prototype -> @prog.number_prototype_valueOf_method_value +;; ...etc +;; +;; ... +;; +;; } +;; `````` + +;; We would then also want to have a bunch of hand-encoded graphs for the values +;; of those fields. That would then allow the number values to point to their +;; prototypes where the fields could be found and used for further lookup on +;; methods. + +;; One caveat of this is that we don't want to get too deep into explaining how +;; some method might be implemented. Indeed, sometimes we *can't*, because it's +;; not implementable in JavaScript at all and is instead some primitive function +;; implemented in the host language. What we want to do, instead, is to provide +;; just enough implementation that other data can flow through as much as +;; possible, to prevent calls to primitive methods from blocking downstream name +;; resolution. For instance, it would be unfortunate if calling `toString` on a +;; number did not let you look up string fields on the resultant value of the +;; call, i.e. if `length` in `(5).toString().length` just simply could not be +;; resolved at all. In such cases, the ideal approach is to implement a bare +;; minimum of `toString` so that we can recover the fact that its returned +;; value is a string. E.g.: + +;; ``````stgdoc +;; (program)@prog { +;; +;; ... +;; +;; edge @prog.number_prototype -> @prog.number_prototype_toString_method_value +;; edge @prog.number_prototype_toString_method_value -> @prog.number_prototype_toString_method_value_return +;; attr @prog.number_prototype_toString_method_value_return "pop" = "GUARD:RETURN" +;; edge @prog.number_prototype_toString_method_value_return -> @prog.string_prototype +;; +;; ... +;; +;; } +;; `````` + +;; As currently implemented, this document does not contain any rules for +;; builtins because of the scope of that task, but they are currently in the +;; pipeline, using the above approach. + +;; Something you may notice in the above code snippet is this pop node labelled +;; `GUARD:RETURN`. This is another part of the design conventions for this +;; library. We often want to use nodes in the graph to constrain name lookup. +;; In this case, we want to be able to pinpoint some of the graph nodes +;; associated with the body of a function as being the values returned by the +;; function. We do this by creating a so-called guard node, which will only be +;; traversed if there is a corresponding push somewhere else. We would generate +;; such a push node precisely when we call a function. This lets us treat the +;; function *ASTs* as if they have parts that we can inspect *in the graph*. + +;; By convention, this library of queries prefixes all guard nodes with "GUARD:" +;; to distinguish them from nodes that more directly correspond to aspects of +;; execution such as member lookup (labelled with ".") or variable lookup +;; (labelled with the variable name itself). The current names used for guard +;; nodes are + +;; - `GUARD:RETURN` - used for the AST nodes for values returned by a function +;; in the function body +;; - `GUARD:THIS` - used for the implicit `this` argument of a function inside +;; its body +;; - `GUARD:CONSTRUCTOR` - used for the constructor method inside a `Class` +;; - `GUARD:MODULE` - used for the final scope of the module +;; - `GUARD:EXPORTS` - used for the names exported by the module +;; - `GUARD:DEFAULT` - used for the default export value + + + + + + + + + + +;; ██████ ██████ ██████ ██████ ██████ █████ ███ ███ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ████ ██ +;; ██████ ██████ ██ ██ ██ ███ ██████ ███████ ██ ████ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ██ ██ ██ ██████ ██████ ██ ██ ██ ██ ██ ██ ███████ + +;; ## Programs + +;; ### Attributes Defined on Programs +;; TODO + +;; ### Program Queries + +(program)@prog { + + node @prog.before_scope + node @prog.after_scope + node @prog.module_scope + node @prog.module_pop + node @prog.exports + node @prog.exports_pop + + scan FILE_PATH { + "([^/]+)\.js$" { + attr (@prog.module_pop) pop_symbol = $1 + ;; attr (@prog.module_pop) no_span + } + } + + edge @prog.before_scope -> ROOT_NODE + + attr (@prog.module_scope) symbol_definition = "GUARD:MODULE" + edge ROOT_NODE -> @prog.module_pop + edge @prog.module_pop -> @prog.module_scope + edge @prog.module_scope -> @prog.after_scope + + ;; attr (@prog) no_span + ;; attr (@prog.module_pop) no_span + ;; attr (@prog.module_scope) no_span + ;; attr (@prog.exports) no_span + ;; attr (@prog.exports_pop) no_span + ;; attr (@prog.before_scope) no_span + ;; attr (@prog.after_scope) no_span + + let @prog.prog = @prog + ;; let @prog.exports = @prog.exports + attr (@prog.exports_pop) pop_symbol = "GUARD:EXPORTS" + edge @prog.module_pop -> @prog.exports_pop + edge @prog.exports_pop -> @prog.exports + + ;; builtin types + node @prog.builtins_number + +} + +;; propagate variables to children +(_ (_)@child)@parent { + + let @child.builtins_number = @parent.builtins_number + +} + +; programs, first statement +(program + . + (_)@first_stmt)@prog { + + ; scopes flow from the program into the first statement + edge @first_stmt.before_scope -> @prog.before_scope + +} + +; program, between statements +(program + (_)@left_stmt + . + (_)@right_stmt) { + + ; scopes flow from the left statement to the right one + edge @right_stmt.before_scope -> @left_stmt.after_scope + +} + +; program, last statement +(program + (_)@last_stmt + .)@prog { + + ; scopes flow from the last statement to the program + edge @prog.after_scope -> @last_stmt.after_scope + +} + +(hash_bang_line)@hashbang { + + node @hashbang.before_scope + node @hashbang.after_scope + + edge @hashbang.after_scope -> @hashbang.before_scope + +} + +(comment)@comment { + + node @comment.before_scope + node @comment.after_scope + + edge @comment.after_scope -> @comment.before_scope + +} + + + + + + + + + + +;; ███████ ████████ █████ ████████ ███████ ███ ███ ███████ ███ ██ ████████ ███████ +;; ██ ██ ██ ██ ██ ██ ████ ████ ██ ████ ██ ██ ██ +;; ███████ ██ ███████ ██ █████ ██ ████ ██ █████ ██ ██ ██ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ███████ ██ ██ ██ ██ ███████ ██ ██ ███████ ██ ████ ██ ███████ + +;; ## Statements + +;; ### Attributes Defined on Statements +;; TODO +;; node @stmt.before_scope +;; node @stmt.after_scope + +;; ### Statement Queries + +;; #### Export + +(export_statement)@export_stmt { + + node @export_stmt.before_scope + node @export_stmt.after_scope + +} + +; exports of just names +; eg +; export { foo, bar as baz }; +;; (export_statement +;; (export_clause)@export_clause +;; !source)@export_stmt { + +;; edge @export_clause.source -> @export_clause.before_scope + +;; ; scope flows through the export clause +;; edge @export_clause.before_scope -> @export_stmt.before_scope +;; edge @export_stmt.after_scope -> @export_clause.after_scope +;; } + +;; (export_statement +;; (export_clause)@export_clause +;; source:(_)@source)@export_stmt { + +;; edge @export_clause.source -> @source.push_exports_guard + +;; attr @source.push_exports_guard "push" = "GUARD:EXPORTS" +;; scan @source { +;; "\"([^/\"]+)\.js\"$" { +;; attr @source.push "push" = $1 +;; } +;; } +;; edge @source.push_exports_guard -> @source.push +;; edge @source.push -> root + +;; edge @export_clause.before_scope -> @export_stmt.before_scope +;; edge @export_stmt.after_scope -> @export_clause.after_scope + + +;; } + +;; (export_statement +;; (declaration)@decl)@export_stmt { +;; edge @decl.before_scope -> @export_stmt.before_scope +;; edge @export_stmt.after_scope -> @decl.after_scope +;; } + +;; (export_statement +;; declaration: [ +;; (function_declaration name:(identifier)@name) +;; (generator_function_declaration name:(identifier)@name) +;; (class_declaration name:(identifier)@name) +;; (lexical_declaration (variable_declarator name:(identifier)@name)) +;; (variable_declaration (variable_declarator name:(identifier)@name)) +;; ]@decl)@export_stmt { + +;; ; TODO this doesn't support destructuring exports + +;; attr @name.pop "pop" = @name, "definition" +;; attr @name.push "push" = @name +;; edge @export_stmt::exports -> @name.pop +;; edge @name.pop -> @decl.value +;; } + +; TODO +; export let [x,y] = [1,2]; +;; (export_statement +;; declaration: [ +;; (lexical_declaration +;; (variable_declarator +;; name: [ +;; (object_pattern) +;; (array_pattern) +;; ]@pattern)) +;; (variable_declaration +;; (variable_declarator +;; name: [ +;; (object_pattern) +;; (array_pattern) +;; ]@pattern)) +;; ])@export_stmt { + +;; edge @export_stmt::exports -> @pattern.new_bindings + +;; } + +; LATER-TODO tree sitter doesn't yet support empty switch bodies +; THIS IS A HUGE HACK AND MUST BE FIXED +;; (export_clause)@export_clause { +;; edge @export_clause.after_scope -> @export_clause.before_scope +;; } + +;; (export_clause +;; (_)@export)@export_clause { + +;; edge @export.source -> @export_clause.source +;; } + +;; (export_clause +;; . +;; (_)@first_export)@export_clause { + +;; edge @first_export.before_scope -> @export_clause.before_scope +;; } + +;; (export_clause +;; (_)@left_export +;; . +;; (_)@right_export) { + +;; edge @right_export.before_scope -> @left_export.after_scope +;; } + +;; (export_clause +;; (_)@last_export +;; .)@export_clause { + +;; edge @export_clause.after_scope -> @last_export.after_scope +;; } + +;; (export_specifier)@export_specifier { +;; edge @export_specifier.after_scope -> @export_specifier.before_scope +;; } + +;; ( +;; (export_specifier +;; name:(_)@name +;; !alias)@export_specifier + +;; (#not-eq? @name "default") +;; ) { + +;; attr @name.pop "pop" = @name, "definition" +;; attr @name.push "push" = @name, "reference" +;; edge @name.pop -> @name.push +;; edge @name.push -> @export_specifier.source + +;; edge @export_specifier::exports -> @name.pop +;; } + +;; ( +;; (export_specifier +;; name:(_)@name +;; alias:(_)@alias)@export_specifier + +;; (#not-eq? @alias "default") + +;; ) { + +;; attr @alias.pop "pop" = @alias, "definition" +;; attr @name.push "push" = @name, "reference" +;; edge @alias.pop -> @name.push +;; edge @name.push -> @export_specifier.source + +;; edge @export_specifier::exports -> @alias.pop +;; } + +;; ( +;; (export_specifier +;; name:(_)@name +;; !alias)@export_specifier + +;; (#eq? @name "default") + +;; ) { + +;; attr @export_specifier.pop_guard_default "pop" = "GUARD:DEFAULT" +;; attr @export_specifier.push_guard_default "push" = "GUARD:DEFAULT" +;; edge @export_specifier::exports -> @export_specifier.pop_guard_default +;; edge @export_specifier.pop_guard_default -> @export_specifier.push_guard_default +;; edge @export_specifier.push_guard_default -> @export_specifier.source + +;; } + +;; ( +;; (export_specifier +;; name:(_)@name +;; alias:(_)@alias)@export_specifier + +;; (#eq? @alias "default") + +;; ) { + +;; attr @name.push "push" = @name +;; attr @export_specifier.guard_default "pop" = "GUARD:DEFAULT" +;; edge @name.push -> @export_specifier.source +;; edge @export_specifier.guard_default -> @name.push +;; edge @export_specifier::exports -> @export_specifier.guard_default +;; } + +; simple default exports +; export default ...; + +;; (export_statement +;; value:(_)@default_expr)@export_stmt { + +;; attr @export_stmt.default_guard "pop" = "GUARD:DEFAULT", "definition" +;; edge @default_expr.before_scope -> @export_stmt.before_scope +;; edge @export_stmt.after_scope -> @default_expr.after_scope +;; edge @export_stmt::exports -> @export_stmt.default_guard +;; edge @export_stmt.default_guard -> @default_expr.value +;; } + +; aggregated exports +; export * from "foo.js"; +;; (export_statement +;; . +;; source:(_)@source)@export_statement { + +;; edge @export_statement.after_scope -> @export_statement.before_scope + +;; attr @source.push_exports_guard "push" = "GUARD:EXPORTS" +;; scan @source { +;; "\"([^/\"]+)\.js\"$" { +;; attr @source.push "push" = $1 +;; } +;; } + +;; edge @export_statement::exports -> @source.push_exports_guard +;; edge @source.push_exports_guard -> @source.push +;; edge @source.push -> root + +;; } + +; namespace exports +; export * as foo from "bar.js"; +;; (export_statement +;; (namespace_export (_)@alias) +;; source:(_)@source)@export_statement { + +;; edge @export_statement.after_scope -> @export_statement.before_scope + +;; attr @source.push_exports_guard "push" = "GUARD:EXPORTS" +;; scan @source { +;; "\"([^/\"]+)\.js\"$" { +;; attr @source.push "push" = $1 +;; } +;; } +;; attr @alias.pop "pop" = @alias, "definition" +;; attr @alias.pop_dot "pop" = "." +;; edge @export_statement::exports -> @alias.pop +;; edge @alias.pop -> @alias.pop_dot +;; edge @alias.pop_dot -> @source.push_exports_guard +;; edge @source.push_exports_guard -> @source.push +;; edge @source.push -> root + +;; } + + + +;; #### Import + +; https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import + +(import_statement)@import_stmt { + + node @import_stmt.before_scope + node @import_stmt.after_scope + +} + +; import "foo.js"; +; only used for side effects not imports. +; HACK this is not a good solution, but we can't do better with the +; current tree sitter grammar +;; (import_statement)@import_stmt { +;; edge @import_stmt.after_scope -> @import_stmt.before_scope +;; } + +; import * as name from "module-name"; +;; (import_clause +;; (namespace_import)@namespace_import)@import_clause { + +;; edge @namespace_import.before_scope -> @import_clause.before_scope +;; edge @import_clause.after_scope -> @namespace_import.after_scope +;; edge @namespace_import.source -> @import_clause.source +;; } + +;; (namespace_import (identifier)@imported_as)@namespace_import { + +;; edge @namespace_import.after_scope -> @namespace_import.before_scope + +;; attr @imported_as.pop "pop" = @imported_as, "definition" +;; attr @imported_as.pop_dot "pop" = "." +;; edge @imported_as.pop -> @imported_as.pop_dot +;; edge @imported_as.pop_dot -> @namespace_import.source + +;; edge @namespace_import.after_scope -> @imported_as.pop + +;; } + +; import { export1 } from "module-name"; +; import { export1 as alias1 } from "module-name"; +; import { export1 , export2 } from "module-name"; +; import { export1 , export2 as alias2 , [...] } from "module-name"; + +;; (import_statement +;; (import_clause)@import_clause +;; source:(_)@source)@import_stmt { + +;; edge @import_clause.before_scope -> @import_stmt.before_scope +;; edge @import_stmt.after_scope -> @import_clause.after_scope + +;; scan @source { +;; "\"([^/\"]+)\.js\"$" { +;; attr @source.push "push" = $1 +;; } +;; } +;; attr @source.push_guard_exports "push" = "GUARD:EXPORTS" +;; edge @source.push_guard_exports -> @source.push +;; edge @source.push -> root +;; edge @import_clause.source -> @source.push_guard_exports + +;; } + +;; (import_clause +;; (named_imports)@named_imports)@import_clause { + +;; edge @named_imports.before_scope -> @import_clause.before_scope +;; edge @import_clause.after_scope -> @named_imports.after_scope +;; edge @named_imports.source -> @import_clause.source + +;; } + +; LATER-TODO tree sitter doesn't yet support empty named imports +; THIS IS A HUGE HACK AND MUST BE FIXED +;; (named_imports)@named_imports { +;; edge @named_imports.after_scope -> @named_imports.before_scope +;; } + +;; (named_imports +;; (import_specifier)@import_specifier)@named_imports { + +;; edge @import_specifier.source -> @named_imports.source +;; } + +;; (named_imports +;; . +;; (import_specifier)@first_import)@named_imports { + +;; edge @first_import.before_scope -> @named_imports.before_scope +;; } + +;; (named_imports +;; (import_specifier)@left_import +;; . +;; (import_specifier)@right_import) { + +;; edge @right_import.before_scope -> @left_import.after_scope +;; } + +;; (named_imports +;; (import_specifier)@last_import +;; .)@named_imports { + +;; edge @named_imports.after_scope -> @last_import.after_scope +;; } + +;; ( + +;; (import_specifier +;; name:(_)@name +;; !alias)@import_specifier + +;; (#not-eq? @name "default") + +;; ) { + +;; edge @import_specifier.after_scope -> @import_specifier.before_scope + +;; attr @name.pop "pop" = @name, "definition" +;; attr @name.push "push" = @name, "reference" +;; edge @name.pop -> @name.push +;; edge @name.push -> @import_specifier.source +;; edge @import_specifier.after_scope -> @name.pop + +;; } + +;; ( + +;; (import_specifier +;; name:(_)@name +;; alias:(_)@alias)@import_specifier + +;; (#not-eq? @name "default") + +;; ) { + +;; edge @import_specifier.after_scope -> @import_specifier.before_scope + +;; attr @alias.pop "pop" = @alias, "definition" +;; attr @name.push "push" = @name, "reference" +;; edge @alias.pop -> @name.push +;; edge @name.push -> @import_specifier.source +;; edge @import_specifier.after_scope -> @alias.pop + +;; } + +; (import_statement +; (import_clause +; (named_imports +; (import_specifier +; name:(_)@name +; alias:(_)@alias))) +; source: (_)@mod_name)@import_stmt { +; +; ; scope passes through, augmented by the identifier +; scan @mod_name { +; "\"([^/\"]+)\.js\"$" { +; attr @mod_name.push "push" = $1, "reference" +; } +; } +; edge @mod_name.push -> root +; +; attr @name "push", "reference" +; attr @name.push_dot "push" = "." +; edge @name.push_dot -> @mod_name.push +; edge @name -> @name.push_dot +; +; attr @alias "pop", "definition" +; edge @alias -> @name +; +; edge @import_stmt.after_scope -> @alias +; } + + +; TODO import defaultExport, { export1 [ , [...] ] } from "module-name"; +; TODO import defaultExport, * as name from "module-name"; +; TODO var promise = import("module-name"); + +; import defaultExport from "module-name"; +;; (import_clause +;; (identifier)@default_name)@import_clause { + +;; edge @import_clause.after_scope -> @import_clause.before_scope + +;; attr @default_name.pop "pop" = @default_name, "definition" +;; attr @default_name.push_guard_default "push" = "GUARD:DEFAULT" +;; edge @default_name.pop -> @default_name.push_guard_default +;; edge @default_name.push_guard_default -> @import_clause.source + +;; edge @import_clause.after_scope -> @default_name.pop + +;; } + + + +;; #### Debugger + +(debugger_statement)@debugger_stmt { + + node @debugger_stmt.before_scope + node @debugger_stmt.after_scope + + ; scopes flow through unchanged + edge @debugger_stmt.after_scope -> @debugger_stmt.before_scope + +} + + + +;; #### Expression + +(expression_statement (_)@inner)@expr_stmt { + + node @expr_stmt.before_scope + node @expr_stmt.after_scope + + ; scopes flow in then back out + edge @inner.before_scope -> @expr_stmt.before_scope + edge @expr_stmt.after_scope -> @inner.after_scope + +} + + + +;; #### Declarations + +;; ##### Variable Declarations + +(variable_declaration)@variable_decl { + + node @variable_decl.before_scope + node @variable_decl.after_scope + +} + +(lexical_declaration)@lexical_decl { + + node @lexical_decl.before_scope + node @lexical_decl.after_scope + +} + +(variable_declaration + (variable_declarator + name:(identifier)@name))@variable_decl +{ + + node @variable_decl.name_pop + + attr (@variable_decl.name_pop) node_definition = @name + edge @variable_decl.after_scope -> @variable_decl.name_pop + attr (@variable_decl.after_scope -> @variable_decl.name_pop) precedence = 1 + +} + +(lexical_declaration + (variable_declarator + name:(identifier)@name))@lexical_decl +{ + + node @lexical_decl.name_pop + + attr (@lexical_decl.name_pop) node_definition = @name + edge @lexical_decl.after_scope -> @lexical_decl.name_pop + attr (@lexical_decl.after_scope -> @lexical_decl.name_pop) precedence = 1 + +} + +;; (variable_declaration +;; (variable_declarator +;; !value))@decl { + +;; edge @decl.after_scope -> @decl.before_scope +;; } + +;; (lexical_declaration +;; (variable_declarator +;; !value))@decl { + +;; edge @decl.after_scope -> @decl.before_scope +;; } + +(variable_declaration + (variable_declarator + name:(identifier)@name + value:(_)@initializer))@variable_decl +{ + + edge @variable_decl.name_pop -> @initializer.value + edge @initializer.before_scope -> @variable_decl.before_scope + edge @variable_decl.after_scope -> @initializer.after_scope + +} + +(lexical_declaration + (variable_declarator + name:(identifier)@name + value:(_)@initializer))@lexical_decl +{ + + edge @lexical_decl.name_pop -> @initializer.value + edge @initializer.before_scope -> @lexical_decl.before_scope + edge @lexical_decl.after_scope -> @initializer.after_scope + attr (@lexical_decl.after_scope -> @initializer.after_scope) precedence = 0 + +} + +;; (variable_declaration +;; (variable_declarator +;; name:[(object_pattern) (array_pattern)]@pat +;; value:(_)@initializer))@decl { + +;; edge @initializer.before_scope -> @decl.before_scope +;; edge @pat.before_scope -> @initializer.after_scope +;; edge @decl.after_scope -> @pat.after_scope + +;; edge @pat.covalue -> @initializer.value +;; } + +;; (lexical_declaration +;; (variable_declarator +;; name:[(object_pattern) (array_pattern)]@pat +;; value:(_)@initializer))@decl { + +;; edge @initializer.before_scope -> @decl.before_scope +;; edge @pat.before_scope -> @initializer.after_scope +;; edge @decl.after_scope -> @pat.after_scope + +;; edge @pat.covalue -> @initializer.value +;; } + + + +;; ##### Function Declarations + +(function_declaration + name:(_)@name + parameters:(_)@call_sig + body:(_)@body)@fun_decl +{ + + node @fun_decl.before_scope + node @fun_decl.after_scope + +;; attr @name.pop "syntax_type" = "function" + +;; ; scope flows across the decl +;; edge @fun_decl.after_scope -> @fun_decl.before_scope + +;; ; with an augmentation for the function +;; attr @name.pop "pop" = @name, "definition" +;; edge @fun_decl.after_scope -> @name.pop +;; edge @name.pop -> @fun_decl.value + +;; ; function values have drop nodes that handle closures, that points to the +;; ; before scope for the function +;; attr @fun_decl.value_drop "drop" +;; edge @fun_decl.value_drop -> @fun_decl.before_scope + +;; ; the call sig's before scope comes from the drop node then flows into the body +;; edge @call_sig.before_scope -> @fun_decl.value_drop +;; attr @call_sig.this_pop "pop" = "this", "definition" +;; attr @call_sig.this_push "push" = "this" +;; edge @call_sig.this_pop -> @call_sig.this_push +;; edge @call_sig.this_push -> @fun_decl.value_arg_scope +;; edge @call_sig.before_scope -> @call_sig.this_pop +;; attr @call_sig.arguments_pop "pop" = "arguments", "definition" +;; attr @call_sig.arguments_push "push" = "arguments" +;; edge @call_sig.arguments_pop -> @call_sig.arguments_push +;; edge @call_sig.arguments_push -> @fun_decl.value_arg_scope +;; edge @call_sig.before_scope -> @call_sig.arguments_pop +;; edge @body.before_scope -> @call_sig.after_scope + + +;; ; function values have call nodes +;; attr @fun_decl.value_call "pop" = "()", "pop-scope" +;; edge @fun_decl.value -> @fun_decl.value_call + +;; ; function values have return nodes which need to be visible for returns +;; attr @fun_decl.value_return "endpoint" +;; attr @fun_decl.value_return "pop" = "GUARD:RETURN" +;; edge @fun_decl.value_call -> @fun_decl.value_return +;; let @body::return_or_yield = @fun_decl.value_return + +;; ; method values have this nodes which need to be visible for constructor calls +;; attr @fun_decl.value_this "push" = "this" +;; attr @fun_decl.value_this_guard "endpoint" +;; attr @fun_decl.value_this_guard "pop" = "GUARD:THIS" +;; edge @fun_decl.value_call -> @fun_decl.value_this_guard +;; edge @fun_decl.value_this_guard -> @fun_decl.value_this +;; edge @fun_decl.value_this -> @body.after_scope + +;; ; function values have a jump node that lets params connect up to actual arguments +;; attr @fun_decl.value_arg_scope "jump-to" +} + +;; (function_declaration +;; parameters: +;; (formal_parameters (_)@param))@fun_decl { + +;; ; parameters jump to the pushed argument scope +;; attr @param.arg_index "push" = (child-index @param) +;; edge @param.covalue -> @param.arg_index +;; edge @param.arg_index -> @fun_decl.value_arg_scope +;; } + + + +;; ##### Generator Function Declarations + +(generator_function_declaration + name:(_)@name + parameters:(_)@call_sig + body:(_)@body)@gen_fun_decl +{ + + node @gen_fun_decl.before_scope + node @gen_fun_decl.after_scope + +;; attr @name.pop "syntax_type" = "function" + +;; ; scope flows across the decl +;; edge @fun_decl.after_scope -> @fun_decl.before_scope + +;; ; with an augmentation for the function +;; attr @name.pop "pop" = @name, "definition" +;; edge @fun_decl.after_scope -> @name.pop +;; edge @name.pop -> @fun_decl.value + +;; ; function values have drop nodes that handle closures, that points to the +;; ; before scope of the declaration +;; attr @fun_decl.value_drop "drop" +;; edge @fun_decl.value_drop -> @fun_decl.before_scope + + +;; ; the call sig's before scope comes from the drop node then flows into the body +;; edge @call_sig.before_scope -> @fun_decl.value_drop +;; attr @call_sig.this_pop "pop" = "this", "definition" +;; attr @call_sig.this_push "push" = "this" +;; edge @call_sig.this_pop -> @call_sig.this_push +;; edge @call_sig.this_push -> @fun_decl.value_arg_scope +;; edge @call_sig.before_scope -> @call_sig.this_pop +;; attr @call_sig.arguments_pop "pop" = "arguments", "definition" +;; attr @call_sig.arguments_push "push" = "arguments" +;; edge @call_sig.arguments_pop -> @call_sig.arguments_push +;; edge @call_sig.arguments_push -> @fun_decl.value_arg_scope +;; edge @call_sig.before_scope -> @call_sig.arguments_pop +;; edge @body.before_scope -> @call_sig.after_scope + +;; ; function values have call nodes +;; attr @fun_decl.value_call "pop" = "()", "pop-scope" +;; edge @fun_decl.value -> @fun_decl.value_call + +;; ; function values have return nodes which need to be visible for returns +;; attr @fun_decl.value_return "endpoint" +;; attr @fun_decl.value_return "pop" = "GUARD:RETURN" +;; edge @fun_decl.value_call -> @fun_decl.value_return +;; let @body::return_or_yield = @fun_decl.value_return + +;; ; method values have this nodes which need to be visible for constructor calls +;; attr @fun_decl.value_this "push" = "this" +;; attr @fun_decl.value_this_guard "endpoint" +;; attr @fun_decl.value_this_guard "pop" = "GUARD:THIS" +;; edge @fun_decl.value_call -> @fun_decl.value_this_guard +;; edge @fun_decl.value_this_guard -> @fun_decl.value_this +;; edge @fun_decl.value_this -> @body.after_scope + +;; ; function values have a jump node that lets params connect up to actual arguments +;; attr @fun_decl.value_arg_scope "jump-to" +} + +;; (generator_function_declaration +;; parameters: +;; (formal_parameters (_)@param))@fun_decl { + +;; ; parameters jump to the pushed argument scope +;; attr @param.arg_index "push" = (child-index @param) +;; edge @param.covalue -> @param.arg_index +;; edge @param.arg_index -> @fun_decl.value_arg_scope +;; } + + + +;; #### Classes + +(class_declaration + name:(_)@name + body:(_)@body)@class_decl +{ + + node @class_decl.before_scope + node @class_decl.after_scope + +;; attr @name.pop "syntax_type" = "class" + +;; attr @name.pop "pop" = @name, "definition" +;; edge @class_decl.after_scope -> @name.pop +;; edge @name.pop -> @class_decl.value + +;; edge @body.before_scope -> @class_decl.before_scope +;; edge @class_decl.value -> @body.after_scope +;; edge @class_decl.after_scope -> @class_decl.before_scope +;; } + +;; (class_declaration +;; (class_heritage (_)@name))@class_decl { + +;; edge @name.before_scope -> @class_decl.before_scope +;; edge @class_decl.value -> @name.value +} + + +; LATER-TODO tree sitter doesn't yet support empty switch bodies +; THIS IS A HUGE HACK AND MUST BE FIXED +;; (class_body)@class_body { +;; edge @class_body.after_scope -> @class_body.before_scope +;; } + +;; (class_body +;; . +;; (_)@first_decl)@class_body { + +;; edge @first_decl.before_scope -> @class_body.before_scope +;; } + +;; (class_body +;; (_)@left_decl +;; . +;; (_)@right_decl) { + +;; edge @right_decl.before_scope -> @left_decl.after_scope +;; } + +;; (class_body +;; (_)@last_decl +;; .)@class_body { + +;; edge @class_body.after_scope -> @last_decl.after_scope +;; } + + +;; ( +;; (method_definition +;; name:(_)@name)@method_def +;; (#eq? @name "constructor") +;; ) { +;; ; augmentation for the constructor +;; attr @name.constructor_guard "pop" = "GUARD:CONSTRUCTOR", "definition" +;; edge @method_def.after_scope -> @name.constructor_guard +;; edge @name.constructor_guard -> @method_def.method_value +;; } + +;; ( +;; (method_definition +;; name:(_)@name)@method_def +;; (#not-eq? @name "constructor") +;; ) { +;; ; augmentation for the method +;; attr @name.pop "pop" = @name, "definition" +;; attr @name.pop_dot "pop" = "." +;; edge @method_def.after_scope -> @name.pop_dot +;; edge @name.pop_dot -> @name.pop +;; edge @name.pop -> @method_def.method_value +;; } + +;; (method_definition +;; name:(_)@name +;; parameters:(_)@call_sig +;; body:(_)@body)@method_def { + +;; attr @name.pop "syntax_type" = "method" + +;; ; scope flows across the decl +;; edge @method_def.after_scope -> @method_def.before_scope + +;; ; method values have drop nodes that handle closures, that points to the +;; ; before scope from method def +;; attr @method_def.method_value_drop "drop" +;; edge @method_def.method_value_drop -> @method_def.before_scope + +;; ; the call sig's before scope comes from the drop node then flows into the body +;; edge @call_sig.before_scope -> @method_def.method_value_drop +;; edge @body.before_scope -> @call_sig.after_scope + +;; ; method values have call nodes +;; attr @method_def.method_value_call "pop" = "()", "pop-scope" +;; edge @method_def.method_value -> @method_def.method_value_call + +;; ; method values have return nodes which need to be visible for returns +;; attr @method_def.method_value_return "endpoint" +;; attr @method_def.method_value_return "pop" = "GUARD:RETURN" +;; edge @method_def.method_value_call -> @method_def.method_value_return +;; let @body::return_or_yield = @method_def.method_value_return + +;; ; method values have this nodes which need to be visible for constructor calls +;; attr @method_def.method_value_this "push" = "this" +;; attr @method_def.method_value_this_guard "endpoint" +;; attr @method_def.method_value_this_guard "pop" = "GUARD:THIS" +;; edge @method_def.method_value_call -> @method_def.method_value_this_guard +;; edge @method_def.method_value_this_guard -> @method_def.method_value_this +;; edge @method_def.method_value_this -> @body.after_scope + +;; ; method values have a jump node that lets params connect up to actual arguments +;; attr @method_def.method_value_arg_scope "jump-to" +;; } + +;; (method_definition +;; parameters: +;; (formal_parameters (_)@param))@method_def { + +;; ; parameters jump to the pushed argument scope +;; attr @param.arg_index "push" = (child-index @param) +;; edge @param.covalue -> @param.arg_index +;; edge @param.arg_index -> @method_def.method_value_arg_scope +;; } + + + +;; (field_definition +;; property:(property_identifier)@property)@field_def { + +;; attr @property.pop "pop" = @property, "definition" +;; attr @property.pop_dot "pop" = "." +;; edge @field_def.after_scope -> @property.pop_dot +;; edge @property.pop_dot -> @property.pop +;; } + +;; (field_definition +;; !value)@field_def { + +;; edge @field_def.after_scope -> @field_def.before_scope +;; } + +;; (field_definition +;; property:(_)@property +;; value:(_)@value)@field_def { + +;; edge @value.before_scope -> @field_def.before_scope +;; edge @field_def.after_scope -> @value.after_scope +;; edge @property.pop -> @value.value +;; } + + + +;; #### Statement Block + +(statement_block)@stmt_block { + + node @stmt_block.before_scope + node @stmt_block.after_scope + +} + +; statement block, first statement +;; (statement_block +;; . +;; (_)@first_stmt)@block { + +;; ; scope flows from block to first statement +;; edge @first_stmt.before_scope -> @block.before_scope +;; } + +; statement block, between statements +;; (statement_block +;; (_)@left_stmt +;; . +;; (_)@right_stmt) { +;; ; scope flows from left to right +;; edge @right_stmt.before_scope -> @left_stmt.after_scope +;; } + +; statement block, last statement +;; (statement_block +;; (_)@last_stmt +;; .)@block { +;; ; scope flows from last statement to block +;; edge @block.after_scope -> @last_stmt.after_scope +;; } + + + + + +;; #### If + +(if_statement condition:(_)@condition)@if_stmt { + + node @if_stmt.before_scope + node @if_stmt.after_scope + + ; scopes flow from the if statement to the condition + edge @condition.before_scope -> @if_stmt.before_scope + +} + +;; (if_statement +;; condition:(_)@condition +;; consequence:(_)@consequence)@if_stmt { + +;; ; scopes flow from the condition to the consequence, then to the if statement +;; edge @consequence.before_scope -> @condition.after_scope +;; edge @if_stmt.after_scope -> @consequence.after_scope +;; } + +;; (if_statement +;; condition:(_)@condition +;; alternative:(_)@alternative)@if_stmt { + +;; ; scopes flow from the condition to the alternative, then to the if statement +;; edge @alternative.before_scope -> @condition.after_scope +;; edge @if_stmt.after_scope -> @alternative.after_scope +;; } + +;; (else_clause (_)@inner)@else_clause { + +;; ; scopes flow in and right back out +;; edge @inner.before_scope -> @else_clause.before_scope +;; edge @else_clause.after_scope -> @inner.after_scope +;; } + + + + +;; #### Switch + +(switch_statement + value:(_)@value + body:(switch_body)@body)@switch_stmt +{ + + node @switch_stmt.before_scope + node @switch_stmt.after_scope + +;; ; scopes flow into the value then into the body then back out to the switch +;; edge @value.before_scope -> @switch_stmt.before_scope +;; edge @body.before_scope -> @value.after_scope +;; edge @switch_stmt.after_scope -> @body.after_scope +} + +; LATER-TODO tree sitter doesn't yet support empty switch bodies +; THIS IS A HUGE HACK AND MUST BE FIXED +;; (switch_body)@switch_body { +;; edge @switch_body.after_scope -> @switch_body.before_scope +;; } + +; switch body, first choice +;; (switch_body +;; . +;; (_)@first_choice)@switch_body { + +;; ; scopes flow from the body into the first choice +;; edge @first_choice.before_scope -> @switch_body.before_scope +;; } + +; switch body, between choices +;; (switch_body +;; (_)@left_choice +;; . +;; (_)@right_choice) { + +;; ; scopes flow left to right +;; edge @right_choice.before_scope -> @left_choice.after_scope +;; } + +; switch body, last choice +;; (switch_body +;; (_)@last_choice +;; .)@switch_body { + +;; ; scope flows out to the switch body +;; edge @switch_body.after_scope -> @last_choice.after_scope +;; } + +; LATER-TODO tree sitter doesnt yet support switch case's with no statements +; THIS IS A HUGE HACK AND MUST BE FIXED +;; (switch_case)@switch_case { +;; edge @switch_case.after_scope -> @switch_case.before_scope +;; } + +; switch case, non-empty statements, first statement +;; (switch_case +;; value:(_)@value +;; . +;; (_)@first_stmt)@switch_case { + +;; ; scopes flow into the value then into the first statement +;; edge @value.before_scope -> @switch_case.before_scope +;; edge @first_stmt.before_scope -> @value.after_scope +;; } + +; switch case, non-empty statements, between statement +;; (switch_case +;; value:(_) +;; (_)@left_stmt +;; . +;; (_)@right_stmt) { + +;; ; scopes flow left to right +;; edge @right_stmt.before_scope -> @left_stmt.after_scope +;; } + +; switch case, non-empty statements, last statement +;; (switch_case +;; value:(_) +;; (_)@last_stmt +;; .)@switch_case { + +;; ; scopes flow out from the last statement to the case +;; edge @switch_case.after_scope -> @last_stmt.after_scope +;; } + +; LATER-TODO tree sitter doesnt yet support empty defaults +; THIS IS A HUGE HACK AND MUST BE FIXED +;; (switch_default)@switch_default { +;; edge @switch_default.after_scope -> @switch_default.before_scope +;; } + +; switch default, non-empty statements, first statement +;; (switch_default +;; . +;; (_)@first_stmt)@switch_default { + +;; ; scopes flow into the first statement +;; edge @first_stmt.before_scope -> @switch_default.before_scope +;; } + +; switch default, non-empty statements, between statements +;; (switch_default +;; (_)@left_stmt +;; . +;; (_)@right_stmt) { + +;; ; scopes flow left to right +;; edge @right_stmt.before_scope -> @left_stmt.after_scope +;; } + +; switch default, non-empty statements, last statement +;; (switch_default +;; (_)@last_stmt +;; .)@switch_default { + +;; ; scopes flow out to the default +;; edge @switch_default.after_scope -> @last_stmt.after_scope +;; } + + + +;; #### For + +(for_statement + initializer:(_)@initializer + condition:(_)@condition + increment:(_)@increment + body:(_)@body)@for_stmt +{ + + node @for_stmt.before_scope + node @for_stmt.after_scope + +;; ; scopes flow from statement to initializer then test then body then increment +;; edge @initializer.before_scope -> @for_stmt.before_scope +;; edge @condition.before_scope -> @initializer.after_scope +;; edge @body.before_scope -> @condition.after_scope +;; edge @increment.before_scope -> @body.after_scope + +;; ; scopes also from from the body back into the condition +;; edge @condition.before_scope -> @body.after_scope + +;; ; scopes also flow from condition out to statement +;; edge @for_stmt.after_scope -> @condition.after_scope +} + + + +;; #### For In + +(for_in_statement + left:(_)@left + right:(_)@right + body:(_)@body)@for_in_stmt +{ + + node @for_in_stmt.before_scope + node @for_in_stmt.after_scope + +;; ; scopes flow from statement to right then to body then back out +;; edge @right.before_scope -> @for_in_stmt.before_scope +;; edge @body.before_scope -> @right.after_scope +;; edge @for_in_stmt.after_scope -> @body.after_scope +} + +;; (for_in_statement +;; left:(identifier)@left +;; right:(_)@right +;; body:(_)@body) { + +;; attr @left.pop "pop", "definition" +;; edge @left.pop -> @right.value +;; edge @body.before_scope -> @left.pop +;; } + + + +;; #### While + +(while_statement + condition:(_)@condition + body:(_)@body)@while_stmt +{ + + node @while_stmt.before_scope + node @while_stmt.after_scope + +;; ; scopes flow from while to condition then to body then back out +;; edge @condition.before_scope -> @while_stmt.before_scope +;; edge @body.before_scope -> @condition.after_scope +;; edge @while_stmt.after_scope -> @body.after_scope + +;; ; scopes also flow back into the condition +;; edge @condition.before_scope -> @body.after_scope +} + + + +;; #### Do + +(do_statement + body:(_)@body + condition:(_)@condition)@do_stmt +{ + + node @do_stmt.before_scope + node @do_stmt.after_scope + +;; ; scopes flow from statement to body then condition then back to statement +;; edge @body.before_scope -> @do_stmt.before_scope +;; edge @condition.before_scope -> @body.after_scope +;; edge @do_stmt.after_scope -> @condition.after_scope + +;; ; scopes also flow back to the body from the condition +;; edge @body.before_scope -> @condition.after_scope + +} + + + +;; #### Try + +(try_statement body:(_)@body)@try_stmt { + + node @try_stmt.before_scope + node @try_stmt.after_scope + +;; ; scopes flow into the body then back out +;; edge @body.before_scope -> @try_stmt.before_scope +;; edge @try_stmt.after_scope -> @body.after_scope + +} + +;; (try_statement +;; body:(_)@body +;; handler:(_)@handler)@try_stmt { + +;; ; scopes flow from body to handler then back out +;; edge @handler.before_scope -> @body.after_scope +;; edge @try_stmt.after_scope -> @handler.after_scope +;; } + +;; (try_statement +;; body:(_)@body +;; finalizer:(_)@finalizer)@try_stmt { + +;; ; scopes flow from body to finalizer then back out +;; edge @finalizer.before_scope -> @body.after_scope +;; edge @try_stmt.after_scope -> @finalizer.after_scope +;; } + +;; (try_statement +;; handler:(_)@handler +;; finalizer:(_)@finalizer)@try_stmt { + +;; ; scopes flow from handler to finalizer then back out +;; edge @finalizer.before_scope -> @handler.after_scope +;; edge @try_stmt.after_scope -> @finalizer.after_scope +;; } + +;; (catch_clause body:(_)@body)@catch_clause { +;; ; scopes flow in then back out +;; edge @body.before_scope -> @catch_clause.before_scope +;; edge @catch_clause.after_scope -> @body.after_scope +;; } + +;; (catch_clause +;; parameter:(identifier)@name +;; body:(_)@body) { + +;; attr @name.pop "pop", "definition" +;; edge @body.before_scope -> @name.pop +;; } + +;; (finally_clause body:(_)@body)@finally_clause { +;; ; scopes flow in thenback out +;; edge @body.before_scope -> @finally_clause.before_scope +;; edge @finally_clause.after_scope -> @body.after_scope +;; } + + + +;; #### With + +(with_statement + object:(_)@object + body:(_)@body)@with_stmt +{ + + node @with_stmt.before_scope + node @with_stmt.after_scope + +;; ; scopes flow from the statement into the object then into the body then back out +;; edge @object.before_scope -> @with_stmt.before_scope +;; edge @body.before_scope -> @object.after_scope +;; edge @with_stmt.after_scope -> @body.after_scope + +;; attr @object.push_dot "push" = "." +;; edge @object.push_dot -> @object.value +;; edge @body.before_scope -> @object.push_dot +} + + + +;; #### Break + +(break_statement)@break_stmt { + + node @break_stmt.before_scope + node @break_stmt.after_scope + + ;; ; scopes flow through unchanged + ;; edge @break_stmt.after_scope -> @break_stmt.before_scope +} + + + +;; #### Continue + +(continue_statement)@continue_stmt { + + node @continue_stmt.before_scope + node @continue_stmt.after_scope + +;; ; scopes flow through unchanged +;; edge @continue_stmt.after_scope -> @continue_stmt.before_scope +} + + + +;; #### Return + +(return_statement)@return_stmt { + + node @return_stmt.before_scope + node @return_stmt.after_scope + +} + +; LATER-TODO tree sitter doesn't let us express empty returns currently +;; (return_statement)@return_stmt { +;; ; scopes flow through unchanged +;; edge @return_stmt.after_scope -> @return_stmt.before_scope +;; } + +;; (return_statement +;; (_)@returned_expr)@return_stmt { +;; ; scopes flow through the returned expresssion +;; edge @returned_expr.before_scope -> @return_stmt.before_scope +;; edge @return_stmt.after_scope -> @returned_expr.after_scope + +;; ; return statements hook up to the call node of the function value +;; edge @return_stmt::return_or_yield -> @returned_expr.value +;; } + + + +;; #### Throw + +(throw_statement (_)@thrown_expr)@throw_stmt { + + node @throw_stmt.before_scope + node @throw_stmt.after_scope + +;; ; scopes flow through the returned expresssion +;; edge @thrown_expr.before_scope -> @throw_stmt.before_scope +;; edge @throw_stmt.after_scope -> @thrown_expr.after_scope +} + + + +;; #### Empty + +(empty_statement)@empty_stmt { + + node @empty_stmt.before_scope + node @empty_stmt.after_scope + +;; ; scopes flow through unchaged +;; edge @empty_stmt.after_scope -> @empty_stmt.before_scope +} + + + +;; #### Labeled + +;; TODO DEBUG!!! this doesnt work, causes a weird error + +;; (labeled_statement (_)@inner)@labeled_stmt { + +;; node @labeled_stmt.before_scope +;; node @labeled_stmt.after_scope + +;; ;; ; scopes flow through the inner statement then back out +;; ;; edge @inner.before_scope -> @labeled_stmt.before_scope +;; ;; edge @labeled_stmt.after_scope -> @inner.after_scope +;; } + + + + + + + + + + +;; ███████ ██ ██ ██████ ██████ ███████ ███████ ███████ ██ ██████ ███ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ +;; █████ ███ ██████ ██████ █████ ███████ ███████ ██ ██ ██ ██ ██ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ███████ ██ ██ ██ ██ ██ ███████ ███████ ███████ ██ ██████ ██ ████ ███████ + +;; ## Expressions + +;; ### Attributes Defined on Expressions +;; TODO +;; node @expr.before_scope +;; node @expr.after_scope +;; node @expr.value + +;; ### Expression Queries + + +;; #### Parenthesized + +(parenthesized_expression (_)@inner)@parens { + + node @parens.before_scope + node @parens.after_scope + node @parens.value + + ; scopes flow right through + edge @inner.before_scope -> @parens.before_scope + edge @parens.after_scope -> @inner.after_scope + + ; as do values + edge @parens.value -> @inner.value + +} + + +;; #### Strings + +(string)@string { + + node @string.before_scope + node @string.after_scope + node @string.value + +;; ; scopes don't change +;; edge @string.after_scope -> @string.before_scope + +;; ; the value of a string is the string primitive +;; edge @string.value -> @string::string +} + + +;; #### Template Strings + +(template_string)@template_string { + + node @template_string.before_scope + node @template_string.after_scope + node @template_string.value + +} + +; template_strings w/ no substitutions +; LATER-TODO tree sitter queries don't let us find the absence of substitutions +; THIS IS A HUGE HACK AND MUST BE FIXED +;; (template_string)@template_string { +;; edge @template_string.after_scope -> @template_string.before_scope +;; } + +; nonempty template string, value +; LATER-TODO this isn't really right, but it gets flows through the template string +; which may be useful +;; (template_string (template_substitution (_)@inner_expr))@template_string { +;; ; the value of a template string is a template string value built from the values of its substitutions +;; ; attr @template_string.value "template_string_value" +;; edge @template_string.value -> @inner_expr.value +;; } + +; nonempty template string, first substitution +;; (template_string . (template_substitution (_)@first_inner_expr))@template_string { +;; ; scopes propagate into the first subtitution of the template string +;; edge @first_inner_expr.before_scope -> @template_string.before_scope +;; } + +; nonempty template string, between substitutions +;; (template_string +;; (template_substitution (_)@left_inner_expr) +;; . +;; (template_substitution (_)@right_inner_expr))@template_string { +;; ; scopes propagate from left substitutions to right substitutions +;; edge @right_inner_expr.before_scope -> @left_inner_expr.after_scope +;; } + +; nonempty template string, last substitution +;; (template_string . (template_substitution (_)@last_inner_expr))@template_string { +;; ; scopes propagate out of the last substitution to the template string +;; edge @template_string.after_scope -> @last_inner_expr.after_scope +;; } + + + +;; #### Numbers + +(number)@number { + + node @number.before_scope + node @number.after_scope + node @number.value + + ; scopes don't change + edge @number.after_scope -> @number.before_scope + + ; the value of a number is the number primitive + edge @number.value -> @number.builtins_number + +} + + +;; #### Variables + +(primary_expression/identifier)@variable { + + node @variable.before_scope + node @variable.after_scope + node @variable.value + + ; scopes don't change + edge @variable.after_scope -> @variable.before_scope + + ; value is a lookup, ie a push + attr (@variable.value) node_reference = @variable + edge @variable.value -> @variable.before_scope + +} + + +;; #### Booleans + +(true)@true { + + node @true.before_scope + node @true.after_scope + node @true.value + + ; scopes don't change + edge @true.after_scope -> @true.before_scope + +;; ; the value of true is a boolean primitive +;; edge @true.value -> @true::boolean + +} + +(false)@false { + + node @false.before_scope + node @false.after_scope + node @false.value + + ; scopes don't change + edge @false.after_scope -> @false.before_scope + +;; ; the value of false is a boolean primitive +;; edge @false.value -> @false::boolean +} + + +;; #### This + +(this)@this { + + node @this.before_scope + node @this.after_scope + node @this.value + + ; scopes don't change + edge @this.after_scope -> @this.before_scope + + ;; ; this is a lookup, ie a push + ;; attr @this.value "push" = "this", "reference" + ;; edge @this.value -> @this.before_scope +} + + +;; #### Super + +(super)@super { + + node @super.before_scope + node @super.after_scope + node @super.value + + ; scopes don't change + edge @super.after_scope -> @super.before_scope + +} + + +;; #### Null + +(null)@null { + + node @null.before_scope + node @null.after_scope + node @null.value + + ; scopes don't change + edge @null.after_scope -> @null.before_scope + + ;; ; the value of null is the null primitive + ;; edge @null.value -> @null::null +} + + +;; #### Undefined + +(undefined)@undefined { + + node @undefined.before_scope + node @undefined.after_scope + node @undefined.value + + ; scopes don't change + edge @undefined.after_scope -> @undefined.before_scope + + ;; ; the value of undefined is the undefined primitive + ;; edge @undefined.value -> @undefined::undefined +} + + +;; #### Regular Expressions + +(regex)@regex { + + node @regex.before_scope + node @regex.after_scope + node @regex.value + + ; scopes don't change + edge @regex.after_scope -> @regex.before_scope + +;; ; the value of a regex is the Regex prototype +;; edge @regex.value -> @regex::Regex_prototype +} + + +;; #### Spread Elements + +;; (spread_element (_)@expr)@spread_elem { +;; ; scopes flow in then right back out +;; edge @expr.before_scope -> @spread_elem.before_scope +;; edge @spread_elem.after_scope -> @expr.after_scope +;; } + + +;; #### Objects + +(object)@object { + + node @object.before_scope + node @object.after_scope + node @object.value + +} + +; empty objects +; LATER-TODO currently unsupported by tree sitter queries +; THIS IS A HUGE HACK AND MUST BE FIXED +;; (object)@object_expr { +;; edge @object_expr.after_scope -> @object_expr.before_scope +;; } + +; non-empty objects, scopes, first entry +;; (object +;; . +;; (_)@first_entry)@object_expr { +;; ; scopes propagate from the object to the first entry +;; edge @first_entry.before_scope -> @object_expr.before_scope +;; } + +; non-empty objects, scopes, between entries +;; (object +;; (_)@left_entry +;; . +;; (_)@right_entry +;; )@object_expr { +;; ; scopes propagate from left entries to right entries +;; edge @right_entry.before_scope -> @left_entry.after_scope +;; } + +; non-empty objects, scopes, last entry +;; (object +;; (_)@last_entry +;; .)@object_expr { +;; ; scopes propagate from the last entry back to the object +;; edge @object_expr.after_scope -> @last_entry.after_scope +;; } + +; shorthand property identifier +;; (object +;; (shorthand_property_identifier)@keyval)@object { + +;; ; scopes flow into rhsvar, and also straight across b/c they can't be modified +;; edge @keyval.rhsvar_before_scope -> @keyval.before_scope +;; edge @keyval.after_scope -> @keyval.before_scope + +;; ; shorthand property identifiers have secret variable exprs +;; attr @keyval.rhsvar_value "push" = @keyval, "reference" +;; edge @keyval.rhsvar_value -> @keyval.rhsvar_before_scope + +;; ; shorthand property identifiers augment the object value with a member binding +;; attr @keyval.boundvar_pop "pop" = @keyval, "definition" + +;; attr @object.field_pop_dot "pop" = "." +;; edge @keyval.boundvar_pop -> @keyval.rhsvar_value +;; edge @object.field_pop_dot -> @keyval.boundvar_pop +;; edge @object.value -> @object.field_pop_dot + +;; } + +; pairs +;; (object +;; (pair +;; key:(_)@key +;; value: (_)@value)@pair)@object { + +;; ; scopes flow into values then back to the pair +;; edge @value.before_scope -> @pair.before_scope +;; edge @pair.after_scope -> @value.after_scope + +;; ; pairs augment the object value with a member binding + +;; ; This is done differently depending on what the key is. See next rules. +;; ; attr @key.pop "pop" = @key, "definition" +;; attr @key.pop "definition" + +;; attr @object.field_pop_dot "pop" = "." +;; edge @key.pop -> @value.value +;; edge @object.field_pop_dot -> @key.pop +;; edge @object.value -> @object.field_pop_dot +;; } + +;; (pair key:(property_identifier)@key) { +;; attr @key.pop "pop" = @key +;; } + +;; (pair key:(string)@key) { +;; attr @key.pop "pop" = (replace @key "\"" "") +;; } + +;; (pair key:(number)@key) { +;; attr @key.pop "pop" = @key +;; } + + + +;; #### Arrays + +(array)@array_expr { + + node @array_expr.before_scope + node @array_expr.after_scope + node @array_expr.value + +} + +; empty arrays +; LATER-TODO currently unsupported by tree sitter queries +; THIS IS A HUGE HACK AND MUST BE FIXED +;; (array)@array_expr { +;; edge @array_expr.after_scope -> @array_expr.before_scope +;; } + +; nonempty arrays, first element +;; (array +;; . +;; (_)@first_element)@array_expr { +;; ; scopes propagate into the first element of the array +;; edge @first_element.before_scope -> @array_expr.before_scope +;; } + +; nonempty arrays, between elements +;; (array +;; (_)@left_element +;; . +;; (_)@right_element) { +;; ; scopes propagate from left elements to right elements +;; edge @right_element.before_scope -> @left_element.after_scope +;; } + +; nonempty arrays, last element +;; (array +;; (_)@last_element +;; .)@array_expr { +;; ; scopes propagate out of the last element to the array +;; edge @array_expr.after_scope -> @last_element.after_scope +;; } + +; elements at indices +;; (array (_)@element)@array_expr { +;; attr @array_expr.element_pop_dot "pop" = "." +;; attr @element.index_pop "pop" = (child-index @element), "definition" +;; edge @array_expr.element_pop_dot -> @element.index_pop +;; edge @array_expr.value -> @array_expr.element_pop_dot +;; edge @element.index_pop -> @element.value +;; } + + + +;; #### Formal Parameters + +; LATER-TODO scope propagation through empty formal parameters +; currently unsupported by tree sitter queries +; THIS IS A HUGE HACK AND MUST BE FIXED + +;; (formal_parameters)@formal_params { +;; edge @formal_params.after_scope -> @formal_params.before_scope +;; } + +; first parameter +;; (formal_parameters +;; . +;; (_)@first_param)@formal_params { + +;; edge @first_param.before_scope -> @formal_params.before_scope +;; } + +; between parameters +;; (formal_parameters +;; (_)@left_param +;; . +;; (_)@right_param) { + +;; ; scope flows left to right +;; edge @right_param.before_scope -> @left_param.after_scope +;; } + +; last parameter +;; (formal_parameters +;; (_)@last_param +;; .)@formal_params { + +;; ; scope flows from the param to the call sig +;; edge @formal_params.after_scope -> @last_param.after_scope +;; } + + + +;; #### Function Literals + +; functions with names +;; (function +;; name:(_)@name +;; parameters:(_)@call_sig)@fun { + +;; attr @name.pop "syntax_type" = "function" + +;; ; if the function has a name, this is bound the callsig's before scope +;; attr @name.pop "pop" = @name, "definition" +;; edge @call_sig.before_scope -> @name.pop +;; edge @name.pop -> @fun.value +;; } + + +; function +(function + parameters:(_)@call_sig + body:(_)@body)@fun +{ + + node @fun.before_scope + node @fun.after_scope + node @fun.value + +;; ; scope flows across the decl +;; edge @fun.after_scope -> @fun.before_scope + +;; ; function values have drop nodes that handle closures, that points to the +;; ; before scope from the function +;; attr @fun.value_drop "drop" +;; edge @fun.value_drop -> @fun.before_scope + +;; ; the call sig's before scope comes from the drop node, +;; ; then flows into the body, and includes a variable binding for "this" +;; edge @call_sig.before_scope -> @fun.value_drop +;; attr @call_sig.this_pop "pop" = "this", "definition" +;; attr @call_sig.this_push "push" = "this" +;; edge @call_sig.this_pop -> @call_sig.this_push +;; edge @call_sig.this_push -> @fun.value_arg_scope +;; edge @call_sig.before_scope -> @call_sig.this_pop +;; attr @call_sig.arguments_pop "pop" = "arguments", "definition" +;; attr @call_sig.arguments_push "push" = "arguments" +;; edge @call_sig.arguments_pop -> @call_sig.arguments_push +;; edge @call_sig.arguments_push -> @fun.value_arg_scope +;; edge @call_sig.before_scope -> @call_sig.arguments_pop +;; edge @body.before_scope -> @call_sig.after_scope + +;; ; function values have call nodes +;; attr @fun.value_call "pop" = "()", "pop-scope" +;; edge @fun.value -> @fun.value_call + +;; ; function values have return nodes which need to be visible for returns +;; attr @fun.value_return "endpoint" +;; attr @fun.value_return "pop" = "GUARD:RETURN" +;; edge @fun.value_call -> @fun.value_return +;; let @body::return_or_yield = @fun.value_return + +;; ; function values have this nodes which need to be visible for method calls +;; attr @fun.value_this "push" = "this" +;; attr @fun.value_this_guard "endpoint" +;; attr @fun.value_this_guard "pop" = "GUARD:THIS" +;; edge @fun.value_call -> @fun.value_this_guard +;; edge @fun.value_this_guard -> @fun.value_this +;; edge @fun.value_this -> @body.after_scope + +;; ; function values have a jump node that lets params connect up to actual arguments +;; attr @fun.value_arg_scope "jump-to" +} + +;; (function +;; parameters: +;; (formal_parameters (_)@param))@fun { + +;; ; parameters jump to the pushed argument scope +;; attr @param.arg_index "push" = (child-index @param) +;; edge @param.covalue -> @param.arg_index +;; edge @param.arg_index -> @fun.value_arg_scope +;; } + + + +;; #### Arrow Function Literals + +; function +[ + (arrow_function + parameters:(_)@call_sig + body:(_)@body)@fun + + (arrow_function + parameter:(_)@call_sig + body:(_)@body)@fun +] { + + node @fun.before_scope + node @fun.after_scope + node @fun.value + +;; ; scope flows across the decl +;; edge @fun.after_scope -> @fun.before_scope + +;; ; function values have drop nodes that handle closures, that points to the +;; ; before scope from the function +;; attr @fun.value_drop "drop" +;; edge @fun.value_drop -> @fun.before_scope + +;; ; the call sig's before scope comes from the drop node then flows into the body +;; edge @call_sig.before_scope -> @fun.value_drop +;; edge @body.before_scope -> @call_sig.after_scope + +;; ; function values have call nodes +;; attr @fun.value_call "pop" = "()", "pop-scope" +;; edge @fun.value -> @fun.value_call + +;; ; function values have return nodes which need to be visible for returns +;; attr @fun.value_return "endpoint" +;; attr @fun.value_return "pop" = "GUARD:RETURN" +;; edge @fun.value_call -> @fun.value_return +;; let @body::return_or_yield = @fun.value_return + +;; ; function values have this nodes which need to be visible for method calls +;; attr @fun.value_this "push" = "this" +;; attr @fun.value_this_guard "endpoint" +;; attr @fun.value_this_guard "pop" = "GUARD:THIS" +;; edge @fun.value_call -> @fun.value_this_guard +;; edge @fun.value_this_guard -> @fun.value_this +;; edge @fun.value_this -> @body.after_scope + +;; ; function values have a jump node that lets params connect up to actual arguments +;; attr @fun.value_arg_scope "jump-to" +} + +; arrow functions returning exprs need special rules for getting the return value hooked up +;; (arrow_function +;; body:(expression)@return_expr) { +;; edge @return_expr::return_or_yield -> @return_expr.value +;; } + +;; (arrow_function +;; parameter:(_)@param)@fun { + +;; ; scope flows from the param right back out +;; edge @param.after_scope -> @param.before_scope + +;; ; but augmented with a pop, b/c it's not a pattern +;; attr @param.pop "pop" = @param, "definition" +;; edge @param.pop -> @param.covalue +;; edge @param.after_scope -> @param.pop + +;; ; parameters jump to the pushed argument scope +;; attr @param.arg_index "push" = "0" +;; edge @param.covalue -> @param.arg_index +;; edge @param.arg_index -> @fun.value_arg_scope +;; } + +;; (arrow_function +;; parameters: +;; (formal_parameters (_)@param))@fun { + +;; ; parameters jump to the pushed argument scope +;; attr @param.arg_index "push" = (child-index @param) +;; edge @param.covalue -> @param.arg_index +;; edge @param.arg_index -> @fun.value_arg_scope +;; } + + + +;; #### Generator Function Literals + +; generator functions with names +;; (generator_function +;; name:(_)@name +;; parameters:(_)@call_sig)@gen_fun +;; { + +;; attr @name.pop "syntax_type" = "function" + +;; ; if the function has a name, this is bound the callsig's before scope +;; attr @name.pop "pop" = @name, "definition" +;; edge @call_sig.before_scope -> @name.pop +;; edge @name.pop -> @fun.value +;; } + + +; generator function +(generator_function + parameters:(_)@call_sig + body:(_)@body)@gen_fun +{ + + node @gen_fun.before_scope + node @gen_fun.after_scope + node @gen_fun.value + +;; ; scope flows across the decl +;; edge @fun.after_scope -> @fun.before_scope + +;; ; function values have drop nodes that handle closures, that points to the +;; ; before scope from the function +;; attr @fun.value_drop "drop" +;; edge @fun.value_drop -> @fun.before_scope + +;; ; the call sig's before scope comes from the drop node then flows into the body +;; edge @call_sig.before_scope -> @fun.value_drop +;; edge @body.before_scope -> @call_sig.after_scope + +;; ; function values have call nodes +;; attr @fun.value_call "pop" = "()", "pop-scope" +;; edge @fun.value -> @fun.value_call + +;; ; function values have return nodes which need to be visible for returns +;; attr @fun.value_return "endpoint" +;; attr @fun.value_return "pop" = "GUARD:RETURN" +;; edge @fun.value_call -> @fun.value_return +;; let @body::return_or_yield = @fun.value_return + +;; ; function values have this nodes which need to be visible for method calls +;; attr @fun.value_this "push" = "this" +;; attr @fun.value_this_guard "endpoint" +;; attr @fun.value_this_guard "pop" = "GUARD:THIS" +;; edge @fun.value_call -> @fun.value_this_guard +;; edge @fun.value_this_guard -> @fun.value_this +;; edge @fun.value_this -> @body.after_scope + +;; ; function values have a jump node that lets params connect up to actual arguments +;; attr @fun.value_arg_scope "jump-to" +} + +;; (generator_function +;; parameters: +;; (formal_parameters (_)@param))@fun { + +;; ; parameters jump to the pushed argument scope +;; attr @param.arg_index "push" = (child-index @param) +;; edge @param.covalue -> @param.arg_index +;; edge @param.arg_index -> @fun.value_arg_scope +;; } + + +;; #### Function Calls + +; calls, functions +(call_expression + function:(_)@function + arguments:(_)@arguments)@call_expr +{ + + node @call_expr.before_scope + node @call_expr.after_scope + node @call_expr.value + +;; ; scopes flow from call expressions into the function +;; edge @function.before_scope -> @call_expr.before_scope +;; edge @arguments.before_scope -> @function.after_scope +;; edge @call_expr.after_scope -> @arguments.after_scope +} + +; calls, values +;; (call_expression +;; function:(_)@function +;; arguments:(_)@arguments)@call_expr { + +;; ; value is a call, ie a push "()" node w/ "push-scope" @arguments +;; attr @call_expr.return_guard "push" = "GUARD:RETURN" +;; attr @call_expr.call "push" = "()", "push-scope" = @arguments.arg_scope +;; edge @call_expr.value -> @call_expr.return_guard +;; edge @call_expr.return_guard -> @call_expr.call +;; edge @call_expr.call -> @function.value + +;; attr @arguments.arg_this "pop" = "this", "definition" +;; edge @arguments.arg_scope -> @arguments.arg_this + +;; edge @arguments.arg_scope -> @arguments.arg_scope_no_this + +;; attr @arguments.arg_arguments "pop" = "arguments", "definition" +;; attr @arguments.arg_arguments_dot "pop" = "." +;; edge @arguments.arg_scope -> @arguments.arg_arguments +;; edge @arguments.arg_arguments -> @arguments.arg_arguments_dot +;; edge @arguments.arg_arguments_dot -> @arguments.arg_scope_no_this +;; edge @arguments.arg_arguments -> @call_expr::arguments_prototype +;; } + +; special case to make `this` bind correctly in calls of the forms `x.f(...)` +; and `x[f](...)` +;; (call_expression +;; function:[ +;; (member_expression object:(_)@object) +;; (subscript_expression object:(_)@object) +;; ] +;; arguments:(_)@arguments) { + +;; edge @arguments.arg_this -> @object.value +;; } + + +; TODO this should eventually be removed and replaced with a version that only +; applies to the negation of (member_expression), but that's not supported by +; tree-sitter currently +;; (call_expression +;; function: (_)@function +;; arguments:(_)@arguments)@call_expr { + +;; edge @arguments.arg_this -> @call_expr::null +;; } +;; (call_expression +;; arguments:(arguments (_)@arg)@arguments) { + +;; attr @arg.arg_index "pop" = (child-index @arg) +;; edge @arguments.arg_scope_no_this -> @arg.arg_index +;; edge @arg.arg_index -> @arg.value +;; } + + + +;; #### Arguments + +; LATER-TODO currently unsupported by tree sitter queries +; THIS IS A HUGE HACK AND MUST BE FIXED +;; (arguments)@arguments { +;; edge @arguments.after_scope -> @arguments.before_scope +;; } + +;; (arguments +;; . +;; (_)@first_arg)@arguments { + +;; edge @first_arg.before_scope -> @arguments.before_scope +;; } + +;; (arguments +;; (_)@left_arg +;; . +;; (_)@right_arg) { + +;; edge @right_arg.before_scope -> @left_arg.after_scope +;; } + +;; (arguments +;; (_)@last_arg +;; .)@arguments { + +;; edge @arguments.after_scope -> @last_arg.after_scope +;; } + + + +;; #### Property Access + +;; ##### Member Expressions + +(member_expression + object: (_)@object + property: (_)@property)@member_expr +{ + + node @member_expr.before_scope + node @member_expr.after_scope + node @member_expr.value + +;; ; scopes flow into object then back out +;; edge @object.before_scope -> @member_expr.before_scope +;; edge @member_expr.after_scope -> @object.after_scope + +;; ; value is a member projection on the value of the object ie. a push then push dot +;; attr @property.push "push", "reference" +;; ;attr @member_expr.value "push" = @property.pop +;; attr @member_expr.push_dot "push" = "." +;; edge @property.push -> @member_expr.push_dot +;; ;edge @member_expr.value -> @member_expr.push_dot +;; edge @member_expr.value -> @property.push +;; edge @member_expr.push_dot -> @object.value +} + +;; ##### Subscript Expressions + +(subscript_expression + object: (_)@object + index: (_)@index)@subscript_expr +{ + + node @subscript_expr.before_scope + node @subscript_expr.after_scope + node @subscript_expr.value + +;; ; scopes flow left to right +;; edge @object.before_scope -> @subscript_expression.before_scope +;; edge @index.before_scope -> @object.after_scope +;; edge @subscript_expression.after_scope -> @index.after_scope + +;; ; value is a subscript lookup, ie a push then push dot + +;; ; this is done differently depending on what the index is +;; ; attr @index.push "push" = @index, "reference" + +} + +;; (subscript_expression +;; object: (_)@object +;; index: (string)@index)@subscript_expression { + +;; attr @index.push "reference" + +;; attr @index.push_dot "push" = "." +;; edge @subscript_expression.value -> @index.push +;; edge @index.push -> @index.push_dot +;; edge @index.push_dot -> @object.value +;; attr @index.push "push" = (replace @index "\"" "") +;; } + +;; (subscript_expression +;; object: (_)@object +;; index: (number)@index)@subscript_expression { + +;; attr @index.push "reference" + +;; attr @index.push_dot "push" = "." +;; edge @subscript_expression.value -> @index.push +;; edge @index.push -> @index.push_dot +;; edge @index.push_dot -> @object.value +;; attr @index.push "push" = @index +;; } + + + +;; #### Constructor Calls + +(new_expression + constructor:(_)@constructor + arguments:(_)@arguments)@new_expr +{ + + node @new_expr.before_scope + node @new_expr.after_scope + node @new_expr.value + +;; edge @constructor.before_scope -> @new_expr.before_scope +;; edge @arguments.before_scope -> @constructor.after_scope +;; edge @new_expr.after_scope -> @arguments.after_scope + +;; attr @new_expr.call "push" = "()", "push-scope" = @arguments.arg_scope + +;; ; we guard for constructors for the case where we have a "true" class +;; attr @constructor.constructor "push" = "GUARD:CONSTRUCTOR" +;; edge @new_expr.call -> @constructor.constructor +;; edge @constructor.constructor -> @constructor.value + +;; ; and also just go right to the value incase we have a function-as-constructor +;; edge @new_expr.call -> @constructor.value + + + +;; ; value coming from the constructor call +;; attr @new_expr.guard_this "push" = "GUARD:THIS" +;; edge @new_expr.value -> @new_expr.guard_this +;; edge @new_expr.guard_this -> @new_expr.call + +;; ; value coming from the field decls in the class +;; edge @new_expr.value -> @constructor.value + +;; attr @arguments.arg_this "pop" = "this", "definition" +;; edge @arguments.arg_scope -> @arguments.arg_this +;; edge @arguments.arg_this -> @new_expr::empty_object +} + +;; (new_expression +;; arguments:(arguments (_)@arg)@arguments) { + +;; attr @arg.arg_index "pop" = (child-index @arg) +;; edge @arguments.arg_scope -> @arg.arg_index +;; edge @arg.arg_index -> @arg.value +;; } + + + +;; #### Await + +(await_expression (_)@awaited)@await_expr { + + node @await_expr.before_scope + node @await_expr.after_scope + node @await_expr.value + +;; ; scopes flow into the inner expression then back out +;; edge @awaited.before_scope -> @await_expr.before_scope +;; edge @await_expr.after_scope -> @awaited.after_scope + +;; ; value is just propagated up +;; edge @await_expr.value -> @awaited.value +} + + + +;; #### Update Expressions + +(update_expression argument: (_)@argument)@update_expr { + + node @update_expr.before_scope + node @update_expr.after_scope + node @update_expr.value + +;; ; scope propagates through the operand then is updated by the expr +;; edge @argument.before_scope -> @update_expr.before_scope +;; edge @update_expr.after_scope -> @argument.after_scope +;; ; LATER-TODO this isn't quite right because the update argument can't be an arbitrary expr +;; ; eg f(x)++ doesn't make any sense, you have to have something more like +;; ; (update_expression argument: (lvar)@argument) +;; attr @argument.pop "pop", "definition" +;; edge @update_expr.value -> @argument.value +;; edge @update_expr.after_scope -> @argument.pop +;; edge @argument.pop -> @argument.value +} + + +;; #### Binary Expressions + +(binary_expression left: (_)@left right: (_)@right)@binary_expr { + + node @binary_expr.before_scope + node @binary_expr.after_scope + node @binary_expr.value + + ; scopes propagate left to right through the operands unchanged by the binop itself + edge @left.before_scope -> @binary_expr.before_scope + edge @right.before_scope -> @left.after_scope + edge @binary_expr.after_scope -> @right.after_scope + + ; value is a binary op value built from the operands + ; LATER-TODO this isn't quite correct but it permits flow through the expression + ; which can be useful + ; attr @binary_expr.value "binary_operation_value" + edge @binary_expr.value -> @left.value + edge @binary_expr.value -> @right.value +} + + +;; #### Unary Expressions + +(unary_expression argument: (_)@argument)@unary_expr { + + node @unary_expr.before_scope + node @unary_expr.after_scope + node @unary_expr.value + +;; ; scope propagates through the operand +;; edge @argument.before_scope -> @unary_expr.before_scope +;; edge @unary_expr.after_scope -> @argument.after_scope + +;; ; value is a unaryop value built from the operand +;; ; LATER-TODO this isn't quite correct but it permits flow through the expression +;; ; which can be useful +;; ; attr @unary_expr.value "unary_operation_value" +;; edge @unary_expr.value -> @argument.value +} + + + +;; #### Assignment Expressions; + +; scopes on RHS, values +(assignment_expression + left: (_)@left + right: (_)@right)@assignment_expr +{ + + node @assignment_expr.before_scope + node @assignment_expr.after_scope + node @assignment_expr.value + + ; scopes flow into the RHS then back out to the whole expr, + ; augmented (in subsequent rules) by the LHS + edge @right.before_scope -> @assignment_expr.before_scope + edge @left.before_scope -> @right.after_scope + edge @assignment_expr.after_scope -> @left.after_scope + + ; value of the whole thing is value of the RHS + edge @assignment_expr.value -> @right.value + +} + +; augmentation of scope via identifiers +(assignment_expression + left: (identifier)@left + right: (_)@right)@assignment_expr +{ + + node @left.before_scope + node @left.after_scope + node @assignment_expr.pop + + ; augments the scope by adding a lookup edge, ie. a pop + attr (@assignment_expr.pop) node_definition = @left + edge @assignment_expr.after_scope -> @assignment_expr.pop + edge @assignment_expr.pop -> @right.value + + ; ensure the scope flows through the identifier + edge @left.after_scope -> @left.before_scope +} + +; assignment to direct fields on `this` +;; (assignment_expression +;; left: (member_expression +;; object:(this)@this +;; property:(_)@property) +;; right: (_)@right)@assignment_expr { + +;; ; HACK +;; attr @this.drop "drop" +;; edge @this.drop -> @this.pop +;; attr @this.pop "pop" = "this" +;; attr @this.pop_dot "pop" = "." +;; attr @property.pop "pop" = @property, "definition" +;; edge @assignment_expr.after_scope -> @this.drop +;; edge @assignment_expr.after_scope -> @this.pop +;; edge @this.pop -> @this.pop_dot +;; edge @this.pop_dot -> @property.pop +;; edge @property.pop -> @right.value +;; } + +; augmentation of scope via _destructuring_patterns +;; (assignment_expression +;; left: [(object_pattern) (array_pattern)]@left +;; right: (_)@right)@assignment_expr { + +;; ; scope flows from LHS into pattern then back to assignment +;; edge @left.before_scope -> @right.after_scope +;; edge @assignment_expr.after_scope -> @left.after_scope +;; } + + + +;; #### Augmented Assignment Expressions + +(augmented_assignment_expression + left: (_)@left + right: (_)@right)@augmented_assignment_expr +{ + + node @augmented_assignment_expr.before_scope + node @augmented_assignment_expr.after_scope + node @augmented_assignment_expr.value + + ; scopes flow into the RHS then back out to the whole expr, augmented by the LHS + edge @right.before_scope -> @augmented_assignment_expr.before_scope + edge @augmented_assignment_expr.after_scope -> @right.after_scope + +} + +(augmented_assignment_expression + left:(identifier)@left + right:(_)@right)@augmented_assignment_expr +{ + + node @left.before_scope + node @left.after_scope + node @augmented_assignment_expr.pop + node @augmented_assignment_expr.push + + ; augment the scope + attr (@augmented_assignment_expr.pop) node_definition = @left + attr (@augmented_assignment_expr.push) node_reference = @left + edge @augmented_assignment_expr.push -> @augmented_assignment_expr.before_scope + edge @augmented_assignment_expr.pop -> @augmented_assignment_expr.push + edge @augmented_assignment_expr.pop -> @right.value + edge @augmented_assignment_expr.after_scope -> @augmented_assignment_expr.pop + +} + + + +;; #### Comma Operator / Sequence Expressions + +(sequence_expression + left: (_)@left + right: (_)@right)@sequence_expr +{ + + node @sequence_expr.before_scope + node @sequence_expr.after_scope + node @sequence_expr.value + +;; ; scopes propagate left to right +;; edge @left.before_scope -> @sequence_expr.before_scope +;; edge @right.before_scope -> @left.after_scope +;; edge @sequence_expr.after_scope -> @right.after_scope + +;; ; the value is just the value of the right +;; edge @sequence_expr.value -> @right.value +} + + + +;; #### Ternary Expression + +(ternary_expression + condition: (_)@condition + consequence: (_)@consequence + alternative: (_)@alternative)@ternary_expr +{ + + node @ternary_expr.before_scope + node @ternary_expr.after_scope + node @ternary_expr.value + +;; ; scopes propagate into condition, then into each branch +;; edge @condition.before_scope -> @ternary_expr.before_scope +;; edge @consequence.before_scope -> @condition.after_scope +;; edge @alternative.before_scope -> @condition.after_scope +;; edge @ternary_expr.after_scope -> @consequence.after_scope +;; edge @ternary_expr.after_scope -> @alternative.after_scope + +;; ; value of the whole thing is a conditional value from the operands +;; edge @ternary_expr.value -> @consequence.value +;; edge @ternary_expr.value -> @alternative.value +} + + + +;; #### Yield + +(yield_expression (_)@yielded_expr)@yield_expr { + + node @yield_expr.before_scope + node @yield_expr.after_scope + node @yield_expr.value + +;; ; scopes flow in to the yielded expression then back out +;; edge @yielded_expr.before_scope -> @yield_expr.before_scope +;; edge @yield_expr.after_scope -> @yielded_expr.after_scope + +;; ; yield expressions hook up to the call node of the function value +;; edge @yield_expr::return_or_yield -> @yielded_expr.value +} + + + +;; #### Class Expressions + +(class body:(_)@body)@class { + + node @class.before_scope + node @class.after_scope + node @class.value + +;; edge @body.before_scope -> @class.before_scope +;; edge @class.value -> @body.after_scope +;; edge @class.after_scope -> @class.before_scope +} + +;; (class +;; name:(_)@name +;; body:(_)@body)@class { + +;; attr @name.pop "syntax_type" = "class" + +;; attr @name.pop "pop" = @name, "definition" +;; edge @body.before_scope -> @name.pop +;; edge @name.pop -> @class.value +;; } + +;; (class +;; (class_heritage (_)@name))@class { + +;; edge @name.before_scope -> @class.before_scope +;; edge @class.value -> @name.value +;; } + + + + + + + + + + +;; ██████ █████ ████████ ████████ ███████ ██████ ███ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ +;; ██████ ███████ ██ ██ █████ ██████ ██ ██ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ██ ██ ██ ██ ██ ███████ ██ ██ ██ ████ ███████ + +;; ## Patterns + +;; Patterns introduce at least two interesting problems to the task of name +;; resolution. On the one hand, patterns by themselves are rich in structure +;; and binding possibilities. On the other, they function to pull apart +;; structure in ways that we would like to make use of in resolving names. Let's +;; look at these in order. + +;; ### Binding Possibilities + +;; If names could only be bound directly either on the LHS of an assignment, or +;; as the formal parameters to a function, or in related places like as +;; arguments to increment or decrement operators, then there would be little +;; trouble saying where a name is bound. But consider a destructuring assignment +;; such as this: + +;; ``````javascript +;; let [x,y,z] = arr; +;; `````` + +;; This assignment has variable names on the LHS of an assignment, sure, but not +;; directly as the LHS. Rather they're buried down inside a pattern. Here they +;; aren't very deep, just one node below the root of the LHS, but they can be +;; arbitrarily far down: + +;; ``````javascript +;; let [x, [y, [z, w], q], r] = arr; +;; `````` + +;; On top of this, patterns in JavaScript permit default assignments, such as + +;; ``````javascript +;; let [x, y = 1] = arr; +;; `````` + +;; These default values can be the result of a computation itself containing +;; variables, such as + +;; ``````javascript +;; let [x, y = 2*z] = arr; +;; `````` + +;; Additionally, those variables referenced in the default value are evaluated +;; *after* the RHS of the assignment. In the following code, `z` is incremented +;; and becomes `2`, and then `x` is assigned to that value. The array on the RHS +;; is only one element long, so the `y` variable gets assigned the default value +;; of `2*z`, which is computed *after* the increment, and so is `2*2` or `4`. + +;; ``````javascript +;; let z = 1; +;; let [x, y = 2*z] = [z++]; +;; `````` + +;; To complicated matters further, the default value can reference the *bound +;; variables to its left*. For instance: + +;; ``````javascript +;; let [x, y = x+1] = arr; +;; `````` + +;; All of this leads to some very interesting and tricky problems for name +;; resolution. The flow of the environment is as follows: First, the environment +;; flows into the RHS of the assignment and is updated by whatever evaluations +;; happen there, then it flows out of the RHS and into the LHS, where it goes +;; through each pattern in the LHS parse tree, in a left-to-right, depth-first +;; traversal. Patterns with no default assignments do nothing to the environment +;; but patterns with a default will pass the environment to the default value, +;; where it may be updated by the evaluation, and then passed further along. +;; Each variable, whether bare or on the left of an assignment, also has to +;; extend the environment because those variables come into scope further along. + +;; ### Structure Decomposition + +;; Let's now look at how patterns decompose structure. Let's consider the effect +;; of an assignment such as this: + +;; ``````javascript +;; let [x,y] = [1,2]; +;; `````` + +;; This assignment binds `x` to `1` and `y` to `2`. It's equivalent to doing + +;; ``````javascript +;; let x = 1, y = 2; +;; `````` + +;; Except, unlike the latter, the array destructuring does not have any obvious +;; pairing up of the names with the expressions that give them their values. +;; Now, perhaps there's some clever hack we can perform for this special case +;; where the RHS is a structure like `[1,2]` where it's manifestly clear out to +;; pair things up, but of course the RHS can come from anywhere. It can come +;; from a local variable assignment: + +;; ``````javascript +;; let arr = [1,2]; +;; let [x,y] = arr; +;; `````` + +;; Or a function call: + +;; ``````javascript +;; function foo(arr) { +;; let [x,y] = arr; +;; ... +;; } +;; foo([1,2]); +;; `````` + +;; Or any other number of places. We would like *all* of these to permit at +;; least *some* amount of name resolution so that we can find that `x` is `1` +;; and `y` is `2`. This should extend also to objects, not just arrays. + +;; The approach we take is to recognize a general pattern of equivalence, which +;; the above double-let assignment is related special case. For arrays, all +;; destructuring assignments of the form + +;; ``````javascript +;; let [..., pat_i, ...] = arr; +;; `````` + +;; are equivalent to + +;; ``````javascript +;; let pat_i = arr[i]; +;; `````` + +;; For any pattern `pat` and expression `arr`. So for instance the simple case +;; of a pattern expression and an array literal + +;; ``````javascript +;; let [x,y] = [1,2]; +;; `````` + +;; is equivalent to a pair of lets + +;; ``````javascript +;; let x = [1,2][0]; +;; let y = [1,2][1]; +;; `````` + +;; Modulo any change in side effects from duplicating the array syntactically, +;; these two are equivalent and this would be a valid code transformation. Or if +;; the pattern were an embedded array destructuring like so: + +;; ``````javascript +;; let [x, [y,z]] = [1, [2,3]]; +;; `````` + +;; then this would be equivalent to + +;; ``````javascript +;; let x = [1, [2,3]][0]; +;; let [y,z] = [1, [2,3]][1]; +;; `````` + +;; And of course the second let here would similarly unfold to be equivalent to +;; a pair of assignments, giving us + +;; ``````javascript +;; let x = [1, [2,3]][0]; +;; let y = [1, [2,3]][1][0]; +;; let z = [1, [2,3]][1][1]; +;; `````` + +;; Similarly for objects, we have the following destructuring equivalence that +;; says an assignment like this: + +;; ``````javascript +;; let {..., k: pat, ...} = obj; +;; `````` + +;; is equivalent to + +;; ``````javascript +;; let pat = obj[k]; +;; `````` + +;; for all patterns `pat` and expressions `obj`. + +;; This lets us then conclude that whatever the graphs are that we generate for +;; patterns ought to be equivalent to the graphs we would general for using +;; array indexing and object indexing. Since array and object indexing are fully +;; capable of participating in name resolution, if we can achieve this +;; equivalence, patterns can also fully participate as well, and we'll be able +;; to say that the assignment `let [x,y] = [1,2]` yields the name `x` resolving +;; to `1` and `y` to `2`, as well as many many more complicated cases. + +;; As mentioned in the intro to this doc, assignments point to values. The +;; simplest way to do this, in the absence of patterns, is just to have an edge +;; from the after scope of the assignment to a pop node for the variable, +;; and then to the value node of the RHS, so for `let x = 1;` it'd be like so: + +;; `````` +;; after_scope ---> POP "x" ---> value_node_for_1 +;; `````` + +;; But the above discussion of destructuring complicates this. What we do to +;; address this is introduce the notion of a "covalue". Just as we can say that +;; an expression *has* a value, or produces a value, etc., we'll say that a +;; pattern *consumes* a value. Expressions have values going "out", while +;; patterns have values coming "in". And so like expressions have an associated +;; `value` node in the graph, patterns have an associated `covalue` node. The +;; covalue corresponds to an incoming value. + +;; We build covalues similar to how we build values. Consider the value for an +;; array such as `["foo", "bar"]`, which will be a scope node with pop nodes +;; going out to the values of the strings, like so: + +;; `````` +;; ,---> POP 0 ---> value_node_of_foo +;; value_node_of_the_array ---| +;; `---> POP 1 ---> value_node_of_bar +;; `````` + +;; Similarly, a covalue for an array pattern will also have nodes for the +;; sub-patterns and nodes for the first and second indexes. But rather than pop +;; nodes, which show you where the 0th and 1st elements are, they'll be push +;; nodes to establish the lookup of those elements. The edges will therefore +;; go the other way around. So for a pattern like `[x,y]`, we have the graph + +;; `````` +;; ,--- PUSH 0 <--- covalue_node_of_x +;; covalue_node_of_the_pattern <---| +;; `--- PUSH 1 <--- covalue_node_of_y +;; `````` + +;; For readers familiar with category theory's notion of duality, this explains +;; why these are called "covalues". The general schema here is that where values +;; have pops, covalues have pushes, and all the arrows get flipped. + +;; ### Attributes Defined on Patterns +;; TODO +;; node @pat.before_scope +;; node @pat.after_scope +;; node @pat.new_bindings + +;; ### Pattern Queries + +;; #### Variable Patterns + +; scope propagation through identifier patterns +(pattern/identifier)@ident_pat { + + node @ident_pat.before_scope + node @ident_pat.after_scope + node @ident_pat.new_bindings + node @ident_pat.pop + + ; scope flows through, binding via a pop edge that goes to an unknown value + attr (@ident_pat.pop) node_definition = @ident_pat + edge @ident_pat.pop -> @ident_pat.covalue + edge @ident_pat.after_scope -> @ident_pat.before_scope + edge @ident_pat.after_scope -> @ident_pat.pop + + edge @ident_pat.new_bindings -> @ident_pat.pop + +} + + +;; #### Object Patterns + +; LATER-TODO scope propagation through empty object patterns +; currently unsupported by tree sitter queries +; THIS IS A HUGE HACK AND MUST BE FIXED +;; (object_pattern)@object_pat { +;; edge @object_pat.after_scope -> @object_pat.before_scope +;; } + +; scope propagation through object patterns, first entry +;; (object_pattern +;; . +;; (_)@first_entry)@object_pat { + +;; ; scope propagates from object pattern to entry +;; edge @first_entry.before_scope -> @object_pat.before_scope +;; } + +; scope propagation through object patterns, between entries +;; (object_pattern +;; (_)@left_entry +;; . +;; (_)@right_entry) { + +;; ; scope propagates from left entry to right entry +;; edge @right_entry.before_scope -> @left_entry.after_scope +;; } + +; scope propagation through object patterns, last entry +;; (object_pattern +;; (_)@last_entry +;; .)@object_pat { + +;; ; scope propagates out from last entry to object pattern +;; edge @object_pat.after_scope -> @last_entry.after_scope +;; } + +; covalue propagation through object patterns +;; (object_pattern +;; (_)@entry)@object_pat { + +;; ; covalues flow into entries unchanged +;; edge @entry.covalue -> @object_pat.covalue + +;; edge @object_pat.new_bindings -> @entry.new_bindings +;; } + +; object entry pair patterns +;; (pair_pattern +;; key:(_)@key +;; value:(_)@value_pat)@pair_pat { + +;; ; covalues flow in dotted +;; attr @key.push_dot "push" = "." +;; edge @value_pat.covalue -> @key.push +;; edge @key.push -> @key.push_dot +;; edge @key.push_dot -> @pair_pat.covalue +;; ; scope flows into value pattern then back out +;; edge @value_pat.before_scope -> @pair_pat.before_scope +;; edge @pair_pat.after_scope -> @value_pat.after_scope + +;; edge @pair_pat.new_bindings -> @value_pat.new_bindings +;; } + +;; (pair_pattern +;; key:(property_identifier)@key)@pair_pattern { + +;; attr @key.push "push" = @key, "reference" +;; } + +;; (pair_pattern +;; key:(string)@key)@pair_pattern { + +;; attr @key.push "push" = (replace @key "\"" ""), "reference" +;; } + +; LATER-TODO the left pattern has to be a name, it cant be another pattern +; object entry assignment patterns +;; (object_assignment_pattern +;; left:(_)@left_pat +;; right:(_)@right_expr)@object_assignment_pat { + +;; ; scope flows both THROUGH and AROUND the RHS, because it's a +;; ; by-passable default not a guaranteed value + +;; ; here we go around +;; edge @left_pat.before_scope -> @object_assignment_pat.before_scope + +;; ; and here we go through +;; edge @right_expr.before_scope -> @object_assignment_pat.before_scope +;; edge @left_pat.before_scope -> @right_expr.after_scope + +;; ; and in either case we come out the LHS +;; edge @object_assignment_pat.after_scope -> @left_pat.after_scope + +;; ; covalues flow both in from the outside and also from the right expression +;; edge @left_pat.covalue -> @object_assignment_pat.covalue +;; edge @left_pat.covalue -> @right_expr.value + +;; edge @object_assignment_pat.new_bindings -> @left_pat.new_bindings + +;; } + +; if the object assignment pattern happens to have an identifier on the LHS it also binds +;; (object_assignment_pattern +;; left:(shorthand_property_identifier_pattern)@left_pat +;; right:(_)@right_expr)@object_assignment_pat { + +;; edge @left_pat.after_scope -> @left_pat.before_scope + +;; attr @left_pat.push "push" = @left_pat, "reference" +;; attr @left_pat.push_dot "push" = "." +;; attr @left_pat.pop "pop" = @left_pat, "definition" +;; edge @left_pat.pop -> @left_pat.push +;; edge @left_pat.push -> @left_pat.push_dot +;; edge @left_pat.push_dot -> @left_pat.covalue +;; edge @object_assignment_pat.after_scope -> @left_pat.pop + +;; edge @object_assignment_pat.new_bindings -> @left_pat.pop +;; } + + +;; #### Array Patterns + +; LATER-TODO scope propagation through empty array patterns +; currently unsupported by tree sitter queries +; THIS IS A HUGE HACK AND MUST BE FIXED +;; (array_pattern)@array_pat { +;; edge @array_pat.after_scope -> @array_pat.before_scope +;; } + +; scope propagation through array patterns, first element +;; (array_pattern +;; . +;; (_)@first_el_pat)@array_pat { + +;; ; scope flows into the first element +;; edge @first_el_pat.before_scope -> @array_pat.before_scope +;; } + +; scope propagation through array patterns, between element +;; (array_pattern +;; (_)@left_el_pat +;; . +;; (_)@right_el_pat) { + +;; ; scope flows from left to right +;; edge @right_el_pat.before_scope -> @left_el_pat.after_scope +;; } + +; scope propagation through array patterns, last element +;; (array_pattern +;; (_)@last_el_pat +;; .)@array_pat { + +;; ; scope flow out from the last element +;; edge @array_pat.after_scope -> @last_el_pat.after_scope +;; } + +; array pattern elements +;; (array_pattern (_)@element_pat)@array_pat { +;; attr @element_pat.element_index_push "push" = (child-index @element_pat), "reference" +;; attr @array_pat.element_index_push_dot "push" = "." +;; edge @element_pat.covalue -> @element_pat.element_index_push +;; edge @element_pat.element_index_push -> @array_pat.element_index_push_dot +;; edge @array_pat.element_index_push_dot -> @array_pat.covalue + +;; edge @array_pat.new_bindings -> @element_pat.new_bindings +;; } + + +;; #### Assignment Patterns + +; scope propagation through assignment patterns +;; (assignment_pattern +;; left:(_)@left_pat +;; right:(_)@right_expr)@assignment_pat { + +;; ; scope flows both THROUGH and AROUND the RHS, because it's a +;; ; by-passable default not a guaranteed value + +;; ; here we go around +;; edge @left_pat.before_scope -> @assignment_pat.before_scope + +;; ; and here we go through +;; edge @right_expr.before_scope -> @assignment_pat.before_scope +;; edge @left_pat.before_scope -> @right_expr.after_scope + +;; ; the pattern's covalue is the whole thing's, and also the RHS +;; edge @left_pat.covalue -> @assignment_pat.covalue +;; edge @left_pat.covalue -> @right_expr.value + +;; ; and in either case we come out the LHS +;; edge @assignment_pat.after_scope -> @left_pat.after_scope + +;; edge @assignment_pat.new_bindings -> @left_pat.new_bindings +;; } + + +;; #### Rest Patterns + +;; (rest_pattern (_)@name)@rest_pat { +;; ; scope flows through, binding via a pop edge that goes to an unknown value + +;; attr @rest_pat.pop "pop" = @name, "definition" +;; edge @rest_pat.after_scope -> @rest_pat.before_scope +;; edge @rest_pat.after_scope -> @rest_pat.pop +;; } + + + + + + + + + + +;; ███████ ██████ ███████ ██████ ██ █████ ██ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ███████ ██████ █████ ██ ██ ███████ ██ +;; ██ ██ ██ ██ ██ ██ ██ ██ +;; ███████ ██ ███████ ██████ ██ ██ ██ ███████ + +;; ## Special Cases +;; +;; There are a number of annoying features that libraries make use of to +;; effectively add features to JavaScript. While they don't technically change +;; the language in any way, they're broad design patterns that are meant to be +;; used *as if* these things were more language level than not. These often make +;; it hard to do analysis without actually running code, and so instead, we +;; define some special case queries that treat these techniques as if they were +;; indeed core features of the language. +;; +;; ### Extend +;; +;; The extend method is a mass assignment of values to keys on objects and gets +;; used a bunch for building module export objects. We special case it here so +;; that we can do lookup on it because the extend method itself is dependent on +;; state and mutability, and has no good analytical explanation within the +;; Stack Graph formalism. +;; +;; Since we can't extend the actual value, but only the syntactic references to +;; it in the SG formalism, we treat extend as a kind of shadowing binder, +;; similar to how we treat `+=` or `*=`. + +;; ( +;; (call_expression +;; function: (member_expression +;; object: (identifier)@object +;; property: (_)@extend) +;; arguments: (arguments (object)@new_fields))@call_expr +;; (#eq? @extend "extend") +;; ) { + +;; attr @object.pop "pop" = @object, "definition" +;; edge @call_expr.after_scope -> @object.pop +;; edge @object.pop -> @new_fields.value + +;; } + +;; ### CommonJS-style Exports + +;; CommonJS introduced an export style for pre-ES6 JavaScript that permitted +;; modules to export functions using an exports object bound to a top-level +;; variable `exports`. For instance, to export something as `foo`, we would do: + +;; ``````javascript +;; exports.foo = 1; +;; `````` + +;; If we then imported with `require`, the exports object would have `foo` as +;; a field. Alternatively, we can also specify the entire export object, using + +;; ``````javascript +;; module.exports = my_exported_object; +;; `````` + +;; ( +;; (assignment_expression +;; left: (member_expression +;; object:(identifier)@exports +;; property:(_)@property) +;; right: (_)@right)@assignment_expr +;; (#eq? @exports "exports") +;; ) { + +;; attr @property.pop "pop" = @property, "definition" +;; attr @property.pop_dot "pop" = "." +;; edge @assignment_expr::exports -> @property.pop_dot +;; edge @property.pop_dot -> @property.pop +;; edge @property.pop -> @right.value +;; } + +;; ( +;; (assignment_expression +;; left: (member_expression +;; object:(identifier)@module +;; property:(_)@exports) +;; right: (_)@right)@assignment_expr +;; (#eq? @module "module") +;; (#eq? @exports "exports") +;; ) { + +;; edge @assignment_expr::exports -> @right.value +;; } + +;; ## CommonJS-style Imports + +;; Similar to exports, CommonJS also defines a way to do imports. In general, +;; these look like `require(expr)`, but in practice the expression is a string +;; constant, which is the only case we hand. + +;; ( +;; (call_expression +;; function:(_)@require +;; arguments:(arguments (string)@mod_name))@call_expr +;; (#eq? @require "require") +;; ) { + +;; scan @mod_name { +;; "\"([^/\"]+)\.js\"$" { +;; attr @mod_name.push "push" = $1 +;; } +;; } + +;; attr @mod_name.module_guard "push" = "GUARD:EXPORTS" +;; edge @call_expr.value -> @mod_name.module_guard +;; edge @mod_name.module_guard -> @mod_name.push +;; edge @mod_name.push -> root + +;; } + + + + + + + + + + +;; ██████ ███████ ███████ ██ ███ ██ ██ ███████ ███ ██ ███████ +;; ██ ██ ██ ██ ██ ████ ██ ██ ██ ████ ██ ██ +;; ██ ██ █████ █████ ██ ██ ██ ██ ██ █████ ██ ██ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ██████ ███████ ██ ██ ██ ████ ██ ███████ ██ ████ ███████ + +;; ## Definiens Rules + +;; These rules explain how defined names relate to syntactic definitions +;; of various forms. Sometimes that's declared function names mapping to +;; the entire function declaration, and sometimes that's variables in an +;; assignment being mapped to the thing it's assigned to. The purpose of +;; these is not to augment stack graphs, per se, but to permit syntax +;; oriented tools that need to know about approximate call graphs, etc. + +;; ### Basic Definiens Rules + +;; These rules are all about declarations and terms that have the names +;; directly in them. + +;; (class_declaration +;; name:(_)@name +;; body:(_)@body)@class_decl { + +;; attr @name.pop "definiens" = @class_decl + +;; } + +;; (function_declaration +;; name:(_)@name +;; parameters:(_)@call_sig +;; body:(_)@body)@fun_decl { + +;; attr @name.pop "definiens" = @fun_decl + +;; } + +;; (generator_function_declaration +;; name:(_)@name +;; parameters:(_)@call_sig +;; body:(_)@body)@fun_decl { + +;; attr @name.pop "definiens" = @fun_decl + +;; } + +;; (method_definition +;; name:(_)@name +;; parameters:(_)@call_sig +;; body:(_)@body)@method_def { + +;; attr @name.pop "definiens" = @method_def + +;; } + +;; (function +;; name:(_)@name +;; parameters:(_)@call_sig)@fun { + +;; attr @name.pop "definiens" = @fun + +;; } + +;; (generator_function +;; name:(_)@name +;; parameters:(_)@call_sig)@fun { + +;; attr @name.pop "definiens" = @fun + +;; } + +;; (class +;; name:(_)@name +;; body:(_)@body)@class { + +;; attr @name.pop "definiens" = @class + +;; } + +;; ### Assignment-like Rules + +;; These rules make up for the fact that JavaScript permits way more +;; kinds of definitions/declarations than just those that show up in +;; syntactic declarations of the thing in question. + +;; These rules are currently way less precise than we would like but +;; do provide at least some information about definiens for these +;; kinds of definitions. + +;; (assignment_expression +;; left: (identifier)@left +;; right: [ +;; (function) +;; (generator_function) +;; (arrow_function) +;; ]@right) { + +;; attr @left.pop "definiens" = @right + +;; } + +;; (assignment_expression +;; left: (member_expression property:(_)@left) +;; right: [ +;; (function) +;; (generator_function) +;; (arrow_function) +;; ]@right) { + +;; attr @left.ignore_guard "pop" = "GUARD:GANDALF" +;; attr @left.definiens_hook "pop" = @left, "definition" +;; attr @left.definiens_hook "definiens" = @right +;; edge root -> @left.ignore_guard +;; edge @left.ignore_guard -> @left.definiens_hook +;; } + +;; (variable_declaration +;; (variable_declarator +;; name:(identifier)@name +;; value: [ +;; (function) +;; (generator_function) +;; (arrow_function) +;; ]@initializer)) { + +;; attr @name.pop "definiens" = @initializer + +;; } + +;; (lexical_declaration +;; (variable_declarator +;; name:(identifier)@name +;; value: [ +;; (function) +;; (generator_function) +;; (arrow_function) +;; ]@initializer)) { + +;; attr @name.pop "definiens" = @initializer + +;; } + +;; (pair +;; key: (_)@name +;; value: [ +;; (function) +;; (generator_function) +;; (arrow_function) +;; ]@value) { + +;; attr @name.ignore_guard "pop" = "GUARD:GANDALF" +;; attr @name.definiens_hook "pop" = @name, "definition" +;; attr @name.definiens_hook "definiens" = @value +;; edge root -> @name.ignore_guard +;; edge @name.ignore_guard -> @name.definiens_hook + +;; } \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test.html b/languages/tree-sitter-stack-graphs-javascript/test.html new file mode 100644 index 000000000..3292a1b77 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test.html @@ -0,0 +1,1411 @@ + + + + + + + +test/test.js + + + + + + + + + + + + + + + + + + + + +
+
+ + + + diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js new file mode 100644 index 000000000..cb73bfdb5 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -0,0 +1,66 @@ +#!/usr/bin/node + +// foo + +export let x = 1; +import "foo"; +debugger; +var x; +let x; +function foo() { } +function* foo() { } +class Foo { } +{ } +if (true) { } +switch (x) { } +for (x; y; z) { } +for (x in xs) { } +while (x) { } +do { } while (x); +try { throw x; } catch (e) { } +with (x) { } +break; +continue; +return; +; +// foo: x; + +(5); +"foo"; +`foo`; +`f${"o"}o` +5; +x; +true; +false; +this; +super; +null; +undefined; +/foo/; +({}); +{ + foo: "bar" +}; +[]; +[1, 2, 3]; +function () { }; +() => { }; +function* () { }; +foo(); +foo(bar); +foo.bar; +foo[bar]; +new Foo(); +new Foo(bar); +await foo; +x++; +--x; +1 + 1; +-2; +(x = 1); +x += 1; +(1, 2); +1 ? 2 : 3; +yield 1; +class { }; \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/binding/default_arguments_from_enclosing_scope.js b/languages/tree-sitter-stack-graphs-javascript/test/binding/default_arguments_from_enclosing_scope.js new file mode 100644 index 000000000..eaf4ee768 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/binding/default_arguments_from_enclosing_scope.js @@ -0,0 +1,8 @@ +let x = { bar: 0 }; + +function foo(y = x) { + return y; +} + +foo({ bar: 1 }).bar; +// ^ defined: 1, 7 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/binding/default_arguments_from_other_arguments.js b/languages/tree-sitter-stack-graphs-javascript/test/binding/default_arguments_from_other_arguments.js new file mode 100644 index 000000000..149ce62fb --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/binding/default_arguments_from_other_arguments.js @@ -0,0 +1,10 @@ +function foo(x, y = x) { + return y; +} + +foo({ bar: 1 }).bar; +// ^ defined: 5 + +foo({}, + { bar: 2 }).bar; +// ^ defined: 9 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_assignments.js b/languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_assignments.js new file mode 100644 index 000000000..9daed0d96 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_assignments.js @@ -0,0 +1,19 @@ +let obj = { x: 1, y: { z: 2 } }; +let { x: xval, y: yval } = obj; +let x = xval; +// ^ defined: 1, 2 + +let y = yval; +// ^ defined: 1, 2 + + y.z; +// ^ defined: 1 + +let [w, + q] = [1,2]; + + w; +// ^ defined: 12, 13 + + q; +// ^ defined: 13, 13 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_assignments_with_defaults_from_enclosing_scope.js b/languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_assignments_with_defaults_from_enclosing_scope.js new file mode 100644 index 000000000..f578947bd --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_assignments_with_defaults_from_enclosing_scope.js @@ -0,0 +1,5 @@ +let x = { foo: 0 }; +let [y, z = x] = [1]; + + z.foo; +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_assignments_with_defaults_from_other_variables.js b/languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_assignments_with_defaults_from_other_variables.js new file mode 100644 index 000000000..a7925a9f4 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_assignments_with_defaults_from_other_variables.js @@ -0,0 +1,6 @@ +let [x, y = x] = [ // newline here distinguishes the object value from the vars + { foo: 2 } +]; + + y.foo; +// ^ defined: 2 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_parameters.js b/languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_parameters.js new file mode 100644 index 000000000..6034f1f0e --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_parameters.js @@ -0,0 +1,7 @@ +function foo({ x: xval }) { + return xval; +// ^ defined: 1 +} + +foo({ x: { y: 1 } }).y; +// ^ defined: 6 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/binding/object_assignment_patterns.js b/languages/tree-sitter-stack-graphs-javascript/test/binding/object_assignment_patterns.js new file mode 100644 index 000000000..3529733c9 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/binding/object_assignment_patterns.js @@ -0,0 +1,4 @@ +let { x = 1 } = { "x": 5 }; + + x; +// ^ defined: 1, 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/binding/simple.js b/languages/tree-sitter-stack-graphs-javascript/test/binding/simple.js new file mode 100644 index 000000000..b8ab43597 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/binding/simple.js @@ -0,0 +1,30 @@ +var x = 1; +let y = 2; +const z = 3; + +/**/ x + y + z; +// ^ defined: 1 +// ^ defined: 2 +// ^ defined: 3 + +x = (y = 2); + +/**/ x + y; +// ^ defined: 1, 10 +// ^ defined: 2, 10 + +/**/ x *= (z += 2); +// ^ defined: 1, 10 +// ^ defined: 3 + +/**/ z - x; +// ^ defined: 3, 16 +// ^ defined: 1, 10, 16 + +let a = 1; +let b = a; + +/**/ b; +// ^ defined: 24, 25 +// this seems weird but it makes sense in terms of what kinds of results we want +// to find: both the assignment to b, and also what it ultimately resolves to diff --git a/languages/tree-sitter-stack-graphs-javascript/test/bug_regressions/2141.js b/languages/tree-sitter-stack-graphs-javascript/test/bug_regressions/2141.js new file mode 100644 index 000000000..c37b95267 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/bug_regressions/2141.js @@ -0,0 +1,14 @@ +function bark() { + console.log("Bark!"); +} + +function meow() { + console.log("Meow!"); +} + +function speak() { + bark(); +// ^ defined: 1 + meow(); +// ^ defined: 5 +} \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/bug_regressions/2227.js b/languages/tree-sitter-stack-graphs-javascript/test/bug_regressions/2227.js new file mode 100644 index 000000000..c6dd885cd --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/bug_regressions/2227.js @@ -0,0 +1,17 @@ +class Cat { + constructor(name, age) { + this.name = name; + this.age = age; + } + + name() { + return this.name; + } + + age() { + return this.age + } +} + +Cat; +//^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/bug_regressions/2291.js b/languages/tree-sitter-stack-graphs-javascript/test/bug_regressions/2291.js new file mode 100644 index 000000000..e8da2831c --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/bug_regressions/2291.js @@ -0,0 +1,28 @@ +// need this to make the tests stop complaining about non-existing test cases +x = 1; +_ = x; +// ^ defined: 2 + +f = function () { }; +f = function* () { }; +f = () => 1; + +var f = function () { }; +var f = function* () { }; +var f = () => 1; + +let f = function () { }; +let f = function* () { }; +let f = () => 1; + +f.p = function () { }; +f.p = function* () { }; +f.p = () => 1; + +// related assignment-like things: + +{ + f: function () { }, + f: function* () { }, + f: () => 1 +}; \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_declaration.js b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_declaration.js new file mode 100644 index 000000000..beb37cf1d --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_declaration.js @@ -0,0 +1,6 @@ + class Foo { + + } + + Foo; +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_expression.js new file mode 100644 index 000000000..4abc8b566 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_expression.js @@ -0,0 +1,10 @@ +let Bar = + class Foo { + constructor() { + Foo; +// ^ defined: 2 + } + }; + + Bar; +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_expression_superclasses.js b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_expression_superclasses.js new file mode 100644 index 000000000..c27cf9be2 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_expression_superclasses.js @@ -0,0 +1,15 @@ +let Foo = class { + constructor() { + this.x = 5; + } +} + +let Bar = class extends Foo { + constructor() { + + } +} + +let bar = new Bar(); +bar.x +// ^ defined: 3 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_expression_this_field_access.js b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_expression_this_field_access.js new file mode 100644 index 000000000..b68554283 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_expression_this_field_access.js @@ -0,0 +1,19 @@ + let Foo = class { + constructor() { + this.bar = 5; + } + }; + + let x = new Foo(); + x.bar; +// ^ defined: 3 + +let Bar = class { + constructor(x) { + this.field = x; + } +} + +let bar = new Bar({ baz: 5 }); +bar.field.baz +// ^ defined: 17 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/field_declaration.js b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/field_declaration.js new file mode 100644 index 000000000..28c0cf434 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/field_declaration.js @@ -0,0 +1,10 @@ +class Foo { + bar; + baz = 5; +} + +let x = new Foo(); + x.bar; +// ^ defined: 2 + x.baz; +// ^ defined: 3 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/function_class_this_field_access.js b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/function_class_this_field_access.js new file mode 100644 index 000000000..f48af3a96 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/function_class_this_field_access.js @@ -0,0 +1,15 @@ + function Foo() { + this.bar = 5; + } + + let x = new Foo(); + x.bar; +// ^ defined: 2 + +function Bar(x) { + this.field = x; +} + +let bar = new Bar({ baz: 5 }); +bar.field.baz +// ^ defined: 13 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/method_call_this_argument.js b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/method_call_this_argument.js new file mode 100644 index 000000000..1a4d93962 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/method_call_this_argument.js @@ -0,0 +1,22 @@ +let x = { + foo: { baz: 5 }, + bar: function () { + return this.foo; + } +}; + +x.bar().baz; +// ^ defined: 2 + +x["bar"]().baz; +// ^ defined: 2 + +let y = [ + { baz: 5 }, + function () { + return this[0]; + } +]; + +y[1]().baz; +// ^ defined: 15 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/method_definition.js b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/method_definition.js new file mode 100644 index 000000000..5166f5b78 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/method_definition.js @@ -0,0 +1,12 @@ +class Foo { + bar(x) { + return x; + } +} + +let obj = { field: 5 }; +let y = new Foo(); + y.bar; +// ^ defined: 2 +y.bar(obj).field +// ^ defined: 7 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/superclasses.js b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/superclasses.js new file mode 100644 index 000000000..82ac7b32d --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/superclasses.js @@ -0,0 +1,15 @@ +class Foo { + constructor() { + this.x = 5; + } +} + +class Bar extends Foo { + constructor() { + + } +} + +let bar = new Bar(); +bar.x +// ^ defined: 3 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/this_field_access.js b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/this_field_access.js new file mode 100644 index 000000000..a43d41473 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/this_field_access.js @@ -0,0 +1,19 @@ + class Foo { + constructor() { + this.bar = 5; + } + } + + let x = new Foo(); + x.bar; +// ^ defined: 3 + +class Bar { + constructor(x) { + this.field = x; + } +} + +let bar = new Bar({ baz: 5 }); +bar.field.baz +// ^ defined: 17 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_literals/arrays.js b/languages/tree-sitter-stack-graphs-javascript/test/compound_literals/arrays.js new file mode 100644 index 000000000..52c6dc6fb --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/compound_literals/arrays.js @@ -0,0 +1,5 @@ +let arr = [{ x: 1 }, + { x: 2 }]; +let one = arr[1].x; +// ^ defined: 1 +// ^ defined: 2 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_literals/object_extend_method.js b/languages/tree-sitter-stack-graphs-javascript/test/compound_literals/object_extend_method.js new file mode 100644 index 000000000..f062c125d --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/compound_literals/object_extend_method.js @@ -0,0 +1,15 @@ +var obj = { + x: 1, + y: 2 +}; + +obj.extend({ + z: 3 +}); + +let x = obj.x; +// ^ defined: 2 +let y = obj.y; +// ^ defined: 3 +let z = obj.z; +// ^ defined: 7 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_literals/objects.js b/languages/tree-sitter-stack-graphs-javascript/test/compound_literals/objects.js new file mode 100644 index 000000000..d9a093743 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/compound_literals/objects.js @@ -0,0 +1,15 @@ +let obj = { x: 1, y: 2, 0: "z" }; +let obj_x = obj.x; +let x = obj_x; +// ^ defined: 1, 2 +let obj_y = obj["y"]; +let y = obj_y; +// ^ defined: 1, 5 + +let obj_z = obj[0]; +let z = obj_z; +// ^ defined: 1, 9 + +let obj2 = { x, y }; +// ^ defined: 1, 2, 3, 13 +// ^ defined: 1, 5, 6, 13 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/dowhile.js b/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/dowhile.js new file mode 100644 index 000000000..869361d0a --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/dowhile.js @@ -0,0 +1,10 @@ +let x = 1; + +do { + x = x * 2; + // ^ defined: 1, 4, 6 +} while (x--); +// ^ defined: 1, 4, 6 + +const y = x; +// ^ defined: 1, 4, 6 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/for.js b/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/for.js new file mode 100644 index 000000000..fa0fa36fd --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/for.js @@ -0,0 +1,17 @@ +var x = 1; + +for (let y = 2; x + y < 2; y++, x--) { + // ^ defined: 1, 11 + // ^ defined: 3, 12 + // ^ defined: 3, 12 + // ^ defined: 1, 11 + alert(x + y); + // ^ defined: 1, 11 + // ^ defined: 3, 12 + x = 2; + y = 3; +} + +const z = x - y; +// ^ defined: 1, 11 +// ^ defined: 3, 12 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/forin.js b/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/forin.js new file mode 100644 index 000000000..2dddccdbf --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/forin.js @@ -0,0 +1,11 @@ +var xs = [0,1,2]; + +for (x in xs) { + // ^ defined: 1 + alert(x); + // ^ defined: 1, 3 + var y = 0; +} + +let z = y; +// ^ defined: 7 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/if.js b/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/if.js new file mode 100644 index 000000000..e14c5ba40 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/if.js @@ -0,0 +1,14 @@ +let x = 0; + +if (true) { + var y = x; + // ^ defined: 1 +} else if (true) { + var y = x+1; + // ^ defined: 1 +} else { + var y = x-2; +} + +const z = y; +// ^ defined: 1, 4, 7, 10 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/try.js b/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/try.js new file mode 100644 index 000000000..7d3fb8b2f --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/try.js @@ -0,0 +1,22 @@ +var x = 1; + +try { + var y = 2; + alert(x); + // ^ defined: 1 +} catch (e) { + const z = 3; + alert(x, y, e); + // ^ defined: 1 + // ^ defined: 4 + // ^ defined: 7 +} finally { + let w = 4; + alert(x, y, z); + // ^ defined: 1 + // ^ defined: 4 + // ^ defined: 8 +} + +alert(w); +// ^ defined: 14 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/while.js b/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/while.js new file mode 100644 index 000000000..e843e680f --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/while.js @@ -0,0 +1,10 @@ +let x = 1; + +while (x--) { + // ^ defined: 1, 3, 5 + x = x * 2; + // ^ defined: 1, 3, 5 +} + +const y = x; +// ^ defined: 1, 3, 5 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/with.js b/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/with.js new file mode 100644 index 000000000..d356bfcdf --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/with.js @@ -0,0 +1,13 @@ +with ({ x: 1, y: 2 }) { + x + y; +// ^ defined: 1 +// ^ defined: 1 +} + +let obj = { z: 3, + w: 4 }; +with (obj) { + z + w; +// ^ defined: 7 +// ^ defined: 8 +} diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arguments_variable.js b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arguments_variable.js new file mode 100644 index 000000000..daf8ed4f3 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arguments_variable.js @@ -0,0 +1,22 @@ +let x = { foo: 1 }; + +function f() { + return arguments; +} + +f(x)[0].foo; +// ^ defined: 1 + +function* g() { + return arguments; +} + +g(x)[0].foo; +// ^ defined: 1 + +let h = function () { + return arguments; +}; + +h(x)[0].foo; +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_param_lists_and_block_bodies.js b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_param_lists_and_block_bodies.js new file mode 100644 index 000000000..282007779 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_param_lists_and_block_bodies.js @@ -0,0 +1,13 @@ +let a = { bar: 1 }; +let b = { quux: 2 }; + +let foo = (x) => { + b.quux; +// ^ defined: 2 +// ^ defined: 2 + return x; +// ^ defined: 4 +}; + +foo(a).bar; +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_param_lists_and_expr_bodies.js b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_param_lists_and_expr_bodies.js new file mode 100644 index 000000000..01b68607d --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_param_lists_and_expr_bodies.js @@ -0,0 +1,11 @@ +let a = { bar: 1 }; +let b = { quux: 2 }; + +let foo = (x) => + (b.quux, x); +// ^ defined: 2 +// ^ defined: 2 +// ^ defined: 4 + +foo(a).bar; +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_single_param_and_block_bodies.js b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_single_param_and_block_bodies.js new file mode 100644 index 000000000..cb12d62df --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_single_param_and_block_bodies.js @@ -0,0 +1,13 @@ +let a = { bar: 1 }; +let b = { quux: 2 }; + +let foo = x => { + b.quux; +// ^ defined: 2 +// ^ defined: 2 + return x; +// ^ defined: 4 +}; + +foo(a).bar; +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_single_param_and_expr_bodies.js b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_single_param_and_expr_bodies.js new file mode 100644 index 000000000..85af929dc --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_single_param_and_expr_bodies.js @@ -0,0 +1,11 @@ +let a = { bar: 1 }; +let b = { quux: 2 }; + +let foo = x => + (b.quux, x); +// ^ defined: 2 +// ^ defined: 2 +// ^ defined: 4 + +foo(a).bar; +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/call_arguments.js b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/call_arguments.js new file mode 100644 index 000000000..864a78766 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/call_arguments.js @@ -0,0 +1,7 @@ +let x = 1; +let y = 2; + +let z = foo(x, y++, y); +// ^ defined: 1, 4 +// ^ defined: 2, 4, 4 +// ^ defined: 2, 4, 4 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/function_declarations.js b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/function_declarations.js new file mode 100644 index 000000000..8f1078539 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/function_declarations.js @@ -0,0 +1,13 @@ +let a = { bar: 1 }; +let b = { quux: 2 }; + +function foo(x) { + b.quux; +// ^ defined: 2 +// ^ defined: 2 + return x; +// ^ defined: 4 +} + +foo(a).bar; +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/function_values.js b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/function_values.js new file mode 100644 index 000000000..dc42375f3 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/function_values.js @@ -0,0 +1,15 @@ +let a = { bar: 1 }; +let b = { quux: 2 }; + +let foo = function bar(x) { + b.quux; +// ^ defined: 2 +// ^ defined: 2 + bar; +// ^ defined: 4 + return x; +// ^ defined: 4 +}; + +foo(a).bar; +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/generator_function_declarations.js b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/generator_function_declarations.js new file mode 100644 index 000000000..781867bf6 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/generator_function_declarations.js @@ -0,0 +1,13 @@ +let a = { bar: 1 }; +let b = { quux: 2 }; + +function* foo(x) { + b.quux; +// ^ defined: 2 +// ^ defined: 2 + yield x; +// ^ defined: 4 +} + +foo(a).bar; +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/generator_function_values.js b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/generator_function_values.js new file mode 100644 index 000000000..10894dcb3 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/generator_function_values.js @@ -0,0 +1,15 @@ +let a = { bar: 1 }; +let b = { quux: 2 }; + +let foo = function* bar(x) { + b.quux; +// ^ defined: 2 +// ^ defined: 2 + bar; +// ^ defined: 4 + yield x; +// ^ defined: 4 +}; + +foo(a).bar; +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/imports_and_exports/commonjs_imports_and_exports.js b/languages/tree-sitter-stack-graphs-javascript/test/imports_and_exports/commonjs_imports_and_exports.js new file mode 100644 index 000000000..70cda6893 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/imports_and_exports/commonjs_imports_and_exports.js @@ -0,0 +1,16 @@ +/*--- path: a.js ---*/ + +exports.foo = 1; +module.exports = { + bar: 2 +}; + +/*--- path b.js ---*/ + +const mod1 = require("a.js"); + +mod1.foo; +// ^ defined: 3 + +mod1.bar; +// ^ defined: 5 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/imports_and_exports/es6_imports_and_exports.js b/languages/tree-sitter-stack-graphs-javascript/test/imports_and_exports/es6_imports_and_exports.js new file mode 100644 index 000000000..ae771b453 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/imports_and_exports/es6_imports_and_exports.js @@ -0,0 +1,193 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Basic Exports and Imports +// +//////////////////////////////////////////////////////////////////////////////// + +/*--- path: a_basic.js ---*/ + +// Direct exports of declarations +export let a; +export let b = 1; +export function c() { } +export class D { } + +// Export list +let e = 2; +export { e }; + +// Renaming exports +let f = 3; +export { f as g }; + +// Exporting destructured assignments with renaming +export const { "k0": h, "k1": i } = { "k0": 4, "k1": 5 }; +export const [j, + k] = [1,2]; +export const { "a": [l] } = { "a": [1] }; +export const { m = 1 } = { "m": 2 }; + +/*--- path: b_basic_0.js ---*/ + +import { a, b as b2 } from "a_basic.js"; + + a; +// ^ defined: 10, 32 + + b2; +// ^ defined: 11, 32 + +/*--- path: b_basic_1.js ---*/ + +import * as mod from "a_basic.js"; + + mod; +// ^ defined: 42 + + mod.a; +// ^ defined: 10 + + mod.b; +// ^ defined: 11 + + mod.c; +// ^ defined: 12 + + mod.D; +// ^ defined: 13 + + mod.e; +// ^ defined: 16, 17 + + mod.f; +// ^ defined: + + mod.g; +// ^ defined: 20, 21 + + mod.h; +// ^ defined: 24, 24 + + mod.i; +// ^ defined: 24, 24 + + mod.j; +// ^ defined: 25, 26 + + mod.k; +// ^ defined: 26, 26 + + mod.l; +// ^ defined: 27, 27 + + mod.m; +// ^ defined: 28, 28 + + +//////////////////////////////////////////////////////////////////////////////// +// +// Default exports +// +//////////////////////////////////////////////////////////////////////////////// + +/*--- path: a_default_0.js ---*/ + +let n = 6; +export default n; + + +/*--- path: a_default_1.js ---*/ + +export default function () { } + + +/*--- path: a_default_2.js ---*/ + +export default function* () { } + + +/*--- path: a_default_3.js ---*/ +export default class { } + + +/*--- path: a_default_4.js ---*/ + +let o = 7; + +export { o as default }; + + +/*--- path: b_default.js ---*/ + +import p from "a_default_0.js" +import q from "a_default_1.js" +import r from "a_default_2.js" +import s from "a_default_3.js" + + p; +// ^ defined: 95, 96, 122 + + q; +// ^ defined: 101, 123 + + r; +// ^ defined: 106, 124 + + s; +// ^ defined: 110, 125 + + +//////////////////////////////////////////////////////////////////////////////// +// +// Aggregating Modules +// +//////////////////////////////////////////////////////////////////////////////// + +/*--- path: b_aggregating_0.js ---*/ + +export * from "a_basic.js"; + + +/*--- path: b_aggregating_1.js ---*/ + +export * as t from "a_basic.js"; + + +/*--- path: b_aggregating_2.js ---*/ + +export { c, D as D1 } from "a_basic.js"; + + +/*--- path: b_aggregating_3.js ---*/ + +export { e as default } from "a_basic.js"; + + +/*--- path: c_aggregating.js ---*/ + +import { a } from "b_aggregating_0.js"; + + a; +// ^ defined: 10, 168 + + b; +// ^ defined: + +import { t } from "b_aggregating_1.js"; + + t.a; +// ^ defined: 153, 176 +// ^ defined: 10 + +import { c, D1 } from "b_aggregating_2.js"; + + c; +// ^ defined: 12, 158, 182 + + D1; +// ^ defined: 13, 158, 182 + +import e2 from "b_aggregating_3.js"; + + e2; +// ^ defined: 16, 17, 190 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/comma.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/comma.js new file mode 100644 index 000000000..58a51610e --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/comma.js @@ -0,0 +1,7 @@ +let x = 1; +let y = (1, x); +// ^ defined: 1 + +let y = (1, x = 5); +let z = x; +// ^ defined: 1, 5 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/template_strings.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/template_strings.js new file mode 100644 index 000000000..099cd1d37 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/template_strings.js @@ -0,0 +1,4 @@ +let x = 1; + +let y = `template ${ x } string`; +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/ternary.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/ternary.js new file mode 100644 index 000000000..4c7947e5a --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/ternary.js @@ -0,0 +1,4 @@ +let x = 1; +let y = true ? x++ : 2; +let z = x; +// ^ defined: 1, 2 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variables.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variables.js new file mode 100644 index 000000000..92b9f9c8e --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variables.js @@ -0,0 +1,9 @@ +let x = 1; +const y = 2; + +var z = x + y; +// ^ defined: 1 +// ^ defined 2 + +let w = z; +// ^ defined: 1, 2, 4 From 59fcce651b7c6669bd8f52e23dfa5efba579fcbe Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Fri, 28 Apr 2023 13:17:18 -0700 Subject: [PATCH 003/500] Adds more updated rules and improves tests --- .../src/stack-graphs.tsg | 177 ++++++++++-------- .../test/binding/simple.js | 30 +-- .../assignment_expression.js | 18 ++ .../augmented_assignment_expression.js | 15 ++ .../test/simple_expressions/await.js | 11 ++ .../simple_expressions/binary_expression.js | 12 ++ .../test/simple_expressions/booleans.js | 9 + .../test/simple_expressions/null.js | 8 + .../test/simple_expressions/number.js | 8 + .../parenthesized_expression.js | 11 ++ .../test/simple_expressions/regex.js | 8 + .../test/simple_expressions/string.js | 8 + .../test/simple_expressions/super.js | 8 + .../{ternary.js => ternary_expression.js} | 2 +- .../test/simple_expressions/this.js | 8 + .../simple_expressions/unary_expression.js | 11 ++ .../test/simple_expressions/undefined.js | 8 + .../simple_expressions/update_expression.js | 11 ++ .../test/simple_expressions/variable.js | 11 ++ .../test/simple_expressions/variables.js | 9 - .../simple_expressions/yield_expression.js | 11 ++ 21 files changed, 280 insertions(+), 114 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/assignment_expression.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/augmented_assignment_expression.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/await.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/binary_expression.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/booleans.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/null.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/number.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/parenthesized_expression.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/regex.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/string.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/super.js rename languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/{ternary.js => ternary_expression.js} (63%) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/this.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/unary_expression.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/undefined.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/update_expression.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variable.js delete mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variables.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index c8056e069..9f3f2a978 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -304,6 +304,11 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; builtin types node @prog.builtins_number + node @prog.builtins_string + node @prog.builtins_boolean + node @prog.builtins_null + node @prog.builtins_undefined + node @prog.builtins_Regex_prototype } @@ -311,6 +316,11 @@ attribute node_symbol = node => symbol = (source-text node), source_n (_ (_)@child)@parent { let @child.builtins_number = @parent.builtins_number + let @child.builtins_string = @parent.builtins_string + let @child.builtins_boolean = @parent.builtins_boolean + let @child.builtins_null = @parent.builtins_null + let @child.builtins_undefined = @parent.builtins_undefined + let @child.builtins_Regex_prototype = @parent.builtins_Regex_prototype } @@ -1818,11 +1828,11 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @string.after_scope node @string.value -;; ; scopes don't change -;; edge @string.after_scope -> @string.before_scope + ; scopes don't change + edge @string.after_scope -> @string.before_scope -;; ; the value of a string is the string primitive -;; edge @string.value -> @string::string + ; the value of a string is the string primitive + edge @string.value -> @string.builtins_string } @@ -1839,39 +1849,39 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; template_strings w/ no substitutions ; LATER-TODO tree sitter queries don't let us find the absence of substitutions ; THIS IS A HUGE HACK AND MUST BE FIXED -;; (template_string)@template_string { -;; edge @template_string.after_scope -> @template_string.before_scope -;; } +(template_string)@template_string { + edge @template_string.after_scope -> @template_string.before_scope +} ; nonempty template string, value ; LATER-TODO this isn't really right, but it gets flows through the template string ; which may be useful -;; (template_string (template_substitution (_)@inner_expr))@template_string { -;; ; the value of a template string is a template string value built from the values of its substitutions -;; ; attr @template_string.value "template_string_value" -;; edge @template_string.value -> @inner_expr.value -;; } +(template_string (template_substitution (_)@inner_expr))@template_string { + ; the value of a template string is a template string value built from the values of its substitutions + ; attr @template_string.value "template_string_value" + edge @template_string.value -> @inner_expr.value +} ; nonempty template string, first substitution -;; (template_string . (template_substitution (_)@first_inner_expr))@template_string { -;; ; scopes propagate into the first subtitution of the template string -;; edge @first_inner_expr.before_scope -> @template_string.before_scope -;; } +(template_string . (template_substitution (_)@first_inner_expr))@template_string { + ; scopes propagate into the first subtitution of the template string + edge @first_inner_expr.before_scope -> @template_string.before_scope +} ; nonempty template string, between substitutions -;; (template_string -;; (template_substitution (_)@left_inner_expr) -;; . -;; (template_substitution (_)@right_inner_expr))@template_string { -;; ; scopes propagate from left substitutions to right substitutions -;; edge @right_inner_expr.before_scope -> @left_inner_expr.after_scope -;; } +(template_string + (template_substitution (_)@left_inner_expr) + . + (template_substitution (_)@right_inner_expr))@template_string { + ; scopes propagate from left substitutions to right substitutions + edge @right_inner_expr.before_scope -> @left_inner_expr.after_scope +} ; nonempty template string, last substitution -;; (template_string . (template_substitution (_)@last_inner_expr))@template_string { -;; ; scopes propagate out of the last substitution to the template string -;; edge @template_string.after_scope -> @last_inner_expr.after_scope -;; } +(template_string . (template_substitution (_)@last_inner_expr))@template_string { + ; scopes propagate out of the last substitution to the template string + edge @template_string.after_scope -> @last_inner_expr.after_scope +} @@ -1921,8 +1931,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; scopes don't change edge @true.after_scope -> @true.before_scope -;; ; the value of true is a boolean primitive -;; edge @true.value -> @true::boolean + ; the value of true is a boolean primitive + edge @true.value -> @true.builtins_boolean } @@ -1935,8 +1945,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; scopes don't change edge @false.after_scope -> @false.before_scope -;; ; the value of false is a boolean primitive -;; edge @false.value -> @false::boolean + ; the value of false is a boolean primitive + edge @false.value -> @false.builtins_boolean } @@ -1951,6 +1961,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; scopes don't change edge @this.after_scope -> @this.before_scope + ;; TODO ;; ; this is a lookup, ie a push ;; attr @this.value "push" = "this", "reference" ;; edge @this.value -> @this.before_scope @@ -1982,8 +1993,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; scopes don't change edge @null.after_scope -> @null.before_scope - ;; ; the value of null is the null primitive - ;; edge @null.value -> @null::null + ; the value of null is the null primitive + edge @null.value -> @null.builtins_null } @@ -1998,8 +2009,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; scopes don't change edge @undefined.after_scope -> @undefined.before_scope - ;; ; the value of undefined is the undefined primitive - ;; edge @undefined.value -> @undefined::undefined + ; the value of undefined is the undefined primitive + edge @undefined.value -> @undefined.builtins_undefined } @@ -2014,13 +2025,15 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; scopes don't change edge @regex.after_scope -> @regex.before_scope -;; ; the value of a regex is the Regex prototype -;; edge @regex.value -> @regex::Regex_prototype + ; the value of a regex is the Regex prototype + edge @regex.value -> @regex.builtins_Regex_prototype } ;; #### Spread Elements +;; TODO NOW + ;; (spread_element (_)@expr)@spread_elem { ;; ; scopes flow in then right back out ;; edge @expr.before_scope -> @spread_elem.before_scope @@ -2705,12 +2718,12 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @await_expr.after_scope node @await_expr.value -;; ; scopes flow into the inner expression then back out -;; edge @awaited.before_scope -> @await_expr.before_scope -;; edge @await_expr.after_scope -> @awaited.after_scope + ; scopes flow into the inner expression then back out + edge @awaited.before_scope -> @await_expr.before_scope + edge @await_expr.after_scope -> @awaited.after_scope -;; ; value is just propagated up -;; edge @await_expr.value -> @awaited.value + ; value is just propagated up + edge @await_expr.value -> @awaited.value } @@ -2722,17 +2735,18 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @update_expr.before_scope node @update_expr.after_scope node @update_expr.value + node @update_expr.pop -;; ; scope propagates through the operand then is updated by the expr -;; edge @argument.before_scope -> @update_expr.before_scope -;; edge @update_expr.after_scope -> @argument.after_scope -;; ; LATER-TODO this isn't quite right because the update argument can't be an arbitrary expr -;; ; eg f(x)++ doesn't make any sense, you have to have something more like -;; ; (update_expression argument: (lvar)@argument) -;; attr @argument.pop "pop", "definition" -;; edge @update_expr.value -> @argument.value -;; edge @update_expr.after_scope -> @argument.pop -;; edge @argument.pop -> @argument.value + ; scope propagates through the operand then is updated by the expr + edge @argument.before_scope -> @update_expr.before_scope + edge @update_expr.after_scope -> @argument.after_scope + ; LATER-TODO this isn't quite right because the update argument can't be an arbitrary expr + ; eg f(x)++ doesn't make any sense, you have to have something more like + ; (update_expression argument: (lvar)@argument) + attr (@update_expr.pop) node_definition = @argument + edge @update_expr.value -> @argument.value + edge @update_expr.after_scope -> @update_expr.pop + edge @update_expr.pop -> @argument.value } @@ -2749,12 +2763,12 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @right.before_scope -> @left.after_scope edge @binary_expr.after_scope -> @right.after_scope - ; value is a binary op value built from the operands - ; LATER-TODO this isn't quite correct but it permits flow through the expression - ; which can be useful - ; attr @binary_expr.value "binary_operation_value" - edge @binary_expr.value -> @left.value - edge @binary_expr.value -> @right.value + ;; ; value is a binary op value built from the operands + ;; ; LATER-TODO this isn't quite correct but it permits flow through the expression + ;; ; which can be useful + ;; ; attr @binary_expr.value "binary_operation_value" + ;; edge @binary_expr.value -> @left.value + ;; edge @binary_expr.value -> @right.value } @@ -2766,9 +2780,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @unary_expr.after_scope node @unary_expr.value -;; ; scope propagates through the operand -;; edge @argument.before_scope -> @unary_expr.before_scope -;; edge @unary_expr.after_scope -> @argument.after_scope + ; scope propagates through the operand + edge @argument.before_scope -> @unary_expr.before_scope + edge @unary_expr.after_scope -> @argument.after_scope ;; ; value is a unaryop value built from the operand ;; ; LATER-TODO this isn't quite correct but it permits flow through the expression @@ -2781,6 +2795,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Assignment Expressions; +; TODO NOW ; scopes on RHS, values (assignment_expression left: (_)@left @@ -2822,6 +2837,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n } ; assignment to direct fields on `this` +; TODO NOW ;; (assignment_expression ;; left: (member_expression ;; object:(this)@this @@ -2855,6 +2871,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Augmented Assignment Expressions +; TODO NOW (augmented_assignment_expression left: (_)@left right: (_)@right)@augmented_assignment_expr @@ -2903,13 +2920,13 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @sequence_expr.after_scope node @sequence_expr.value -;; ; scopes propagate left to right -;; edge @left.before_scope -> @sequence_expr.before_scope -;; edge @right.before_scope -> @left.after_scope -;; edge @sequence_expr.after_scope -> @right.after_scope + ; scopes propagate left to right + edge @left.before_scope -> @sequence_expr.before_scope + edge @right.before_scope -> @left.after_scope + edge @sequence_expr.after_scope -> @right.after_scope -;; ; the value is just the value of the right -;; edge @sequence_expr.value -> @right.value + ; the value is just the value of the right + edge @sequence_expr.value -> @right.value } @@ -2926,16 +2943,16 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @ternary_expr.after_scope node @ternary_expr.value -;; ; scopes propagate into condition, then into each branch -;; edge @condition.before_scope -> @ternary_expr.before_scope -;; edge @consequence.before_scope -> @condition.after_scope -;; edge @alternative.before_scope -> @condition.after_scope -;; edge @ternary_expr.after_scope -> @consequence.after_scope -;; edge @ternary_expr.after_scope -> @alternative.after_scope + ; scopes propagate into condition, then into each branch + edge @condition.before_scope -> @ternary_expr.before_scope + edge @consequence.before_scope -> @condition.after_scope + edge @alternative.before_scope -> @condition.after_scope + edge @ternary_expr.after_scope -> @consequence.after_scope + edge @ternary_expr.after_scope -> @alternative.after_scope -;; ; value of the whole thing is a conditional value from the operands -;; edge @ternary_expr.value -> @consequence.value -;; edge @ternary_expr.value -> @alternative.value + ; value of the whole thing is a conditional value from the operands + edge @ternary_expr.value -> @consequence.value + edge @ternary_expr.value -> @alternative.value } @@ -2948,10 +2965,11 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @yield_expr.after_scope node @yield_expr.value -;; ; scopes flow in to the yielded expression then back out -;; edge @yielded_expr.before_scope -> @yield_expr.before_scope -;; edge @yield_expr.after_scope -> @yielded_expr.after_scope + ; scopes flow in to the yielded expression then back out + edge @yielded_expr.before_scope -> @yield_expr.before_scope + edge @yield_expr.after_scope -> @yielded_expr.after_scope +; TODO NOW ;; ; yield expressions hook up to the call node of the function value ;; edge @yield_expr::return_or_yield -> @yielded_expr.value } @@ -2960,6 +2978,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Class Expressions +; TODO NOW (class body:(_)@body)@class { node @class.before_scope diff --git a/languages/tree-sitter-stack-graphs-javascript/test/binding/simple.js b/languages/tree-sitter-stack-graphs-javascript/test/binding/simple.js index b8ab43597..c0197e565 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/binding/simple.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/binding/simple.js @@ -2,29 +2,9 @@ var x = 1; let y = 2; const z = 3; -/**/ x + y + z; +/**/ x; // ^ defined: 1 -// ^ defined: 2 -// ^ defined: 3 - -x = (y = 2); - -/**/ x + y; -// ^ defined: 1, 10 -// ^ defined: 2, 10 - -/**/ x *= (z += 2); -// ^ defined: 1, 10 -// ^ defined: 3 - -/**/ z - x; -// ^ defined: 3, 16 -// ^ defined: 1, 10, 16 - -let a = 1; -let b = a; - -/**/ b; -// ^ defined: 24, 25 -// this seems weird but it makes sense in terms of what kinds of results we want -// to find: both the assignment to b, and also what it ultimately resolves to +/**/ y; +// ^ defined: 2 +/**/ z; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/assignment_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/assignment_expression.js new file mode 100644 index 000000000..cb6dc00ec --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/assignment_expression.js @@ -0,0 +1,18 @@ +let x = 1; +let y = 2; +let z = 3; + +// Flow into subexpressions + +z = x; +// ^ defined: 1 + +// Flow around and update + +x = (y = 3); + +/**/ x; +// ^ defined: 1, 12 + +/****/ y; +// ^ defined: 2, 12 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/augmented_assignment_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/augmented_assignment_expression.js new file mode 100644 index 000000000..2abe79cbc --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/augmented_assignment_expression.js @@ -0,0 +1,15 @@ +let x = 1; +let y = 2; +let z = 3; + +// Flow into subexpressions + +z += x; +// ^ defined: 1 + +// Flow around and update + +y += 1; + +/**/ y; +// ^ defined: 2, 12 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/await.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/await.js new file mode 100644 index 000000000..16cb81a93 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/await.js @@ -0,0 +1,11 @@ +let x = 1; + +// Flow into subexpressions + +await x; +// ^ defined: 1 + +// Flow around + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/binary_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/binary_expression.js new file mode 100644 index 000000000..58538b3d1 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/binary_expression.js @@ -0,0 +1,12 @@ +let x = 1; + +// Flow into subexpressions + +/**/ x + x; +// ^ defined: 1 +// ^ defined: 1 + +// Flow around + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/booleans.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/booleans.js new file mode 100644 index 000000000..bf227b43c --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/booleans.js @@ -0,0 +1,9 @@ +let x = 1; + +// Flow around + +true; +false; + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/null.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/null.js new file mode 100644 index 000000000..f13eb4a5f --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/null.js @@ -0,0 +1,8 @@ +let x = 1; + +// Flow around + +null; + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/number.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/number.js new file mode 100644 index 000000000..955646910 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/number.js @@ -0,0 +1,8 @@ +let x = 1; + +// Flow around + +5; + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/parenthesized_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/parenthesized_expression.js new file mode 100644 index 000000000..7b173c788 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/parenthesized_expression.js @@ -0,0 +1,11 @@ +let x = 1; + +// Flow into subexpressions + +/**/ (x); +// ^ defined: 1 + +// Flow around + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/regex.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/regex.js new file mode 100644 index 000000000..09fd564f1 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/regex.js @@ -0,0 +1,8 @@ +let x = 1; + +// Flow around + +/foo/; + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/string.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/string.js new file mode 100644 index 000000000..db207e4c4 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/string.js @@ -0,0 +1,8 @@ +let x = 1; + +// Flow around + +"foo"; + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/super.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/super.js new file mode 100644 index 000000000..e3317db0d --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/super.js @@ -0,0 +1,8 @@ +let x = 1; + +// Flow around + +super; + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/ternary.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/ternary_expression.js similarity index 63% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/ternary.js rename to languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/ternary_expression.js index 4c7947e5a..6f0131464 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/ternary.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/ternary_expression.js @@ -1,4 +1,4 @@ let x = 1; -let y = true ? x++ : 2; +let y = true ? x = 5 : 2; let z = x; // ^ defined: 1, 2 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/this.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/this.js new file mode 100644 index 000000000..bf8cc6420 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/this.js @@ -0,0 +1,8 @@ +let x = 1; + +// Flow around + +this; + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/unary_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/unary_expression.js new file mode 100644 index 000000000..7d97da2f1 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/unary_expression.js @@ -0,0 +1,11 @@ +let x = 1; + +// Flow into subexpressions + +/**/ -x; +// ^ defined: 1 + +// Flow around + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/undefined.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/undefined.js new file mode 100644 index 000000000..219678bce --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/undefined.js @@ -0,0 +1,8 @@ +let x = 1; + +// Flow around + +undefined; + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/update_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/update_expression.js new file mode 100644 index 000000000..1981ec322 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/update_expression.js @@ -0,0 +1,11 @@ +let x = 1; + +// Flow into subexpressions + +/**/ x++; +// ^ defined: 1 + +// Flow around and update + +/**/ x; +// ^ defined: 1, 5 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variable.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variable.js new file mode 100644 index 000000000..4e9475cbc --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variable.js @@ -0,0 +1,11 @@ +let x = 1; + +// Flow into subexpressions + +/**/ x; +// ^ defined: 1 + +// Flow around + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variables.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variables.js deleted file mode 100644 index 92b9f9c8e..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variables.js +++ /dev/null @@ -1,9 +0,0 @@ -let x = 1; -const y = 2; - -var z = x + y; -// ^ defined: 1 -// ^ defined 2 - -let w = z; -// ^ defined: 1, 2, 4 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js new file mode 100644 index 000000000..2dbbc612f --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js @@ -0,0 +1,11 @@ +let x = 1; + +// Flow into subexpressions + +yield x; +// ^ defined: 1 + +// Flow around + +/**/ x; +// ^ defined: 1 \ No newline at end of file From 96d354646e516c6ff8b7fe1ff6d27327b2d07617 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Fri, 28 Apr 2023 13:18:07 -0700 Subject: [PATCH 004/500] Removes test html files --- .../base_syntax.html | 1411 ----------------- .../simple.html | 1411 ----------------- .../test.html | 1411 ----------------- 3 files changed, 4233 deletions(-) delete mode 100644 languages/tree-sitter-stack-graphs-javascript/base_syntax.html delete mode 100644 languages/tree-sitter-stack-graphs-javascript/simple.html delete mode 100644 languages/tree-sitter-stack-graphs-javascript/test.html diff --git a/languages/tree-sitter-stack-graphs-javascript/base_syntax.html b/languages/tree-sitter-stack-graphs-javascript/base_syntax.html deleted file mode 100644 index 30842a7cc..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/base_syntax.html +++ /dev/null @@ -1,1411 +0,0 @@ - - - - - - - -test/base_syntax.js - - - - - - - - - - - - - - - - - - - - -
-
- - - - diff --git a/languages/tree-sitter-stack-graphs-javascript/simple.html b/languages/tree-sitter-stack-graphs-javascript/simple.html deleted file mode 100644 index 9ef7c5c6c..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/simple.html +++ /dev/null @@ -1,1411 +0,0 @@ - - - - - - - -test/binding/simple.js - - - - - - - - - - - - - - - - - - - - -
-
- - - - diff --git a/languages/tree-sitter-stack-graphs-javascript/test.html b/languages/tree-sitter-stack-graphs-javascript/test.html deleted file mode 100644 index 3292a1b77..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/test.html +++ /dev/null @@ -1,1411 +0,0 @@ - - - - - - - -test/test.js - - - - - - - - - - - - - - - - - - - - -
-
- - - - From 3a59a564c26edd7dd79e416fd611a03589d96dfe Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Mon, 8 May 2023 09:54:15 -0700 Subject: [PATCH 005/500] Adds more JS --- .../src/stack-graphs.tsg | 58 +++++++++---------- .../assignment_expression.js | 3 +- .../augmented_assignment_expression.js | 3 +- .../test/simple_expressions/await.js | 3 +- .../simple_expressions/binary_expression.js | 3 +- .../parenthesized_expression.js | 3 +- .../simple_expressions/unary_expression.js | 3 +- .../simple_expressions/update_expression.js | 3 +- .../test/simple_expressions/variable.js | 3 +- .../simple_expressions/yield_expression.js | 3 +- .../test/statements/if_statement.js | 9 +++ ...ical_declaration_basic_no_destructuring.js | 18 ++++++ .../test/statements/statement_block.js | 21 +++++++ ...able_declaration_basic_no_destructuring.js | 18 ++++++ 14 files changed, 104 insertions(+), 47 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/if_statement.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/lexical_declaration_basic_no_destructuring.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/statement_block.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/variable_declaration_basic_no_destructuring.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 9f3f2a978..7e3b388d5 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -920,19 +920,19 @@ attribute node_symbol = node => symbol = (source-text node), source_n } -;; (variable_declaration -;; (variable_declarator -;; !value))@decl { +(variable_declaration + (variable_declarator + !value))@decl { -;; edge @decl.after_scope -> @decl.before_scope -;; } + edge @decl.after_scope -> @decl.before_scope +} -;; (lexical_declaration -;; (variable_declarator -;; !value))@decl { +(lexical_declaration + (variable_declarator + !value))@decl { -;; edge @decl.after_scope -> @decl.before_scope -;; } + edge @decl.after_scope -> @decl.before_scope +} (variable_declaration (variable_declarator @@ -1306,30 +1306,30 @@ attribute node_symbol = node => symbol = (source-text node), source_n } ; statement block, first statement -;; (statement_block -;; . -;; (_)@first_stmt)@block { +(statement_block + . + (_)@first_stmt)@block { -;; ; scope flows from block to first statement -;; edge @first_stmt.before_scope -> @block.before_scope -;; } + ; scope flows from block to first statement + edge @first_stmt.before_scope -> @block.before_scope +} ; statement block, between statements -;; (statement_block -;; (_)@left_stmt -;; . -;; (_)@right_stmt) { -;; ; scope flows from left to right -;; edge @right_stmt.before_scope -> @left_stmt.after_scope -;; } +(statement_block + (_)@left_stmt + . + (_)@right_stmt) { + ; scope flows from left to right + edge @right_stmt.before_scope -> @left_stmt.after_scope +} ; statement block, last statement -;; (statement_block -;; (_)@last_stmt -;; .)@block { -;; ; scope flows from last statement to block -;; edge @block.after_scope -> @last_stmt.after_scope -;; } +(statement_block + (_)@last_stmt + .)@block { + ; scope flows from last statement to block + edge @block.after_scope -> @last_stmt.after_scope +} diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/assignment_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/assignment_expression.js index cb6dc00ec..54ed3c5ff 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/assignment_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/assignment_expression.js @@ -2,8 +2,7 @@ let x = 1; let y = 2; let z = 3; -// Flow into subexpressions - +// Flow in z = x; // ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/augmented_assignment_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/augmented_assignment_expression.js index 2abe79cbc..a676fe155 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/augmented_assignment_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/augmented_assignment_expression.js @@ -2,8 +2,7 @@ let x = 1; let y = 2; let z = 3; -// Flow into subexpressions - +// Flow in z += x; // ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/await.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/await.js index 16cb81a93..ba47cd64d 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/await.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/await.js @@ -1,7 +1,6 @@ let x = 1; -// Flow into subexpressions - +// Flow in await x; // ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/binary_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/binary_expression.js index 58538b3d1..e056da627 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/binary_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/binary_expression.js @@ -1,7 +1,6 @@ let x = 1; -// Flow into subexpressions - +// Flow in /**/ x + x; // ^ defined: 1 // ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/parenthesized_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/parenthesized_expression.js index 7b173c788..257737fce 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/parenthesized_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/parenthesized_expression.js @@ -1,7 +1,6 @@ let x = 1; -// Flow into subexpressions - +// Flow in /**/ (x); // ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/unary_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/unary_expression.js index 7d97da2f1..649ffb31e 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/unary_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/unary_expression.js @@ -1,7 +1,6 @@ let x = 1; -// Flow into subexpressions - +// Flow in /**/ -x; // ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/update_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/update_expression.js index 1981ec322..0c1b30f52 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/update_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/update_expression.js @@ -1,7 +1,6 @@ let x = 1; -// Flow into subexpressions - +// Flow in /**/ x++; // ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variable.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variable.js index 4e9475cbc..10b835b75 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variable.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variable.js @@ -1,7 +1,6 @@ let x = 1; -// Flow into subexpressions - +// Flow in /**/ x; // ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js index 2dbbc612f..14fa90440 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js @@ -1,7 +1,6 @@ let x = 1; -// Flow into subexpressions - +// Flow in yield x; // ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/if_statement.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/if_statement.js new file mode 100644 index 000000000..51d819194 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/if_statement.js @@ -0,0 +1,9 @@ +let x = 1; + +// Flow in + +if (x) { + // ^ defined: 1 + /**/ x; + // ^ defined: 1 +} \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/lexical_declaration_basic_no_destructuring.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/lexical_declaration_basic_no_destructuring.js new file mode 100644 index 000000000..0a5b6fd3a --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/lexical_declaration_basic_no_destructuring.js @@ -0,0 +1,18 @@ +let x = 1; +/**/ x; +// ^ defined: 1 + +// Flow in +let y = x; +// ^ defined: 1 + +// Flow around + +/**/ x; +// ^ defined: 1 + +// Shadowing + +let x = 2; +/**/ x; +// ^ defined: 17 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/statement_block.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/statement_block.js new file mode 100644 index 000000000..19f70a1b2 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/statement_block.js @@ -0,0 +1,21 @@ +let x = 1; + +// Flow in +{ + /**/ x; + // ^ defined: 1 +} + +// Flow around + +/**/ x; +// ^ defined: 1 + +// Flow out + +{ + let y = 1; +} + +/**/ y; +// ^ defined: 17 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/variable_declaration_basic_no_destructuring.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/variable_declaration_basic_no_destructuring.js new file mode 100644 index 000000000..d1aacbc58 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/variable_declaration_basic_no_destructuring.js @@ -0,0 +1,18 @@ +var x = 1; +/**/ x; +// ^ defined: 1 + +// Flow in +var y = x; +// ^ defined: 1 + +// Flow around + +/**/ x; +// ^ defined: 1 + +// Shadowing + +var x = 2; +/**/ x; +// ^ defined: 17 \ No newline at end of file From a1478633bb54c053f21f927d9966f7ae64394f8e Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 9 May 2023 16:21:02 -0700 Subject: [PATCH 006/500] Adds more statements --- .../src/stack-graphs.tsg | 302 +++++++++++------- .../test/base_syntax.js | 2 +- .../assignment_expression.js | 4 +- .../augmented_assignment_expression.js | 2 +- .../simple_expressions/update_expression.js | 2 +- .../test/statements/for_in_statement.js | 25 ++ .../test/statements/for_statement.js | 31 ++ .../test/statements/if_statement.js | 25 +- .../test/statements/switch_statement.js | 25 ++ 9 files changed, 287 insertions(+), 131 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/for_in_statement.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/for_statement.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/switch_statement.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 7e3b388d5..a03cf2913 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -368,6 +368,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @comment.before_scope node @comment.after_scope + node @comment.value edge @comment.after_scope -> @comment.before_scope @@ -1347,30 +1348,38 @@ attribute node_symbol = node => symbol = (source-text node), source_n } -;; (if_statement -;; condition:(_)@condition -;; consequence:(_)@consequence)@if_stmt { +(if_statement + condition:(_)@condition + consequence:(_)@consequence)@if_stmt +{ -;; ; scopes flow from the condition to the consequence, then to the if statement -;; edge @consequence.before_scope -> @condition.after_scope -;; edge @if_stmt.after_scope -> @consequence.after_scope -;; } + ; scopes flow from the condition to the consequence, then to the if statement + edge @consequence.before_scope -> @condition.after_scope + edge @if_stmt.after_scope -> @consequence.after_scope -;; (if_statement -;; condition:(_)@condition -;; alternative:(_)@alternative)@if_stmt { +} -;; ; scopes flow from the condition to the alternative, then to the if statement -;; edge @alternative.before_scope -> @condition.after_scope -;; edge @if_stmt.after_scope -> @alternative.after_scope -;; } +(if_statement + condition:(_)@condition + alternative:(_)@alternative)@if_stmt +{ -;; (else_clause (_)@inner)@else_clause { + ; scopes flow from the condition to the alternative, then to the if statement + edge @alternative.before_scope -> @condition.after_scope + edge @if_stmt.after_scope -> @alternative.after_scope -;; ; scopes flow in and right back out -;; edge @inner.before_scope -> @else_clause.before_scope -;; edge @else_clause.after_scope -> @inner.after_scope -;; } +} + +(else_clause (_)@inner)@else_clause { + + node @else_clause.before_scope + node @else_clause.after_scope + + ; scopes flow in and right back out + edge @inner.before_scope -> @else_clause.before_scope + edge @else_clause.after_scope -> @inner.after_scope + +} @@ -1385,117 +1394,156 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @switch_stmt.before_scope node @switch_stmt.after_scope -;; ; scopes flow into the value then into the body then back out to the switch -;; edge @value.before_scope -> @switch_stmt.before_scope -;; edge @body.before_scope -> @value.after_scope -;; edge @switch_stmt.after_scope -> @body.after_scope + ; scopes flow into the value then into the body then back out to the switch + edge @value.before_scope -> @switch_stmt.before_scope + edge @body.before_scope -> @value.after_scope + edge @switch_stmt.after_scope -> @body.after_scope +} + +(switch_body)@switch_body { + + node @switch_body.before_scope + node @switch_body.after_scope + } ; LATER-TODO tree sitter doesn't yet support empty switch bodies ; THIS IS A HUGE HACK AND MUST BE FIXED -;; (switch_body)@switch_body { -;; edge @switch_body.after_scope -> @switch_body.before_scope -;; } +(switch_body)@switch_body { + edge @switch_body.after_scope -> @switch_body.before_scope +} ; switch body, first choice -;; (switch_body -;; . -;; (_)@first_choice)@switch_body { +(switch_body + . + (_)@first_choice)@switch_body +{ -;; ; scopes flow from the body into the first choice -;; edge @first_choice.before_scope -> @switch_body.before_scope -;; } + ; scopes flow from the body into the first choice + edge @first_choice.before_scope -> @switch_body.before_scope + +} ; switch body, between choices -;; (switch_body -;; (_)@left_choice -;; . -;; (_)@right_choice) { +(switch_body + (_)@left_choice + . + (_)@right_choice) +{ -;; ; scopes flow left to right -;; edge @right_choice.before_scope -> @left_choice.after_scope -;; } + ; scopes flow left to right + edge @right_choice.before_scope -> @left_choice.after_scope + +} ; switch body, last choice -;; (switch_body -;; (_)@last_choice -;; .)@switch_body { +(switch_body + (_)@last_choice + .)@switch_body +{ -;; ; scope flows out to the switch body -;; edge @switch_body.after_scope -> @last_choice.after_scope -;; } + ; scope flows out to the switch body + edge @switch_body.after_scope -> @last_choice.after_scope + +} + +(switch_case)@switch_case { + + node @switch_case.before_scope + node @switch_case.after_scope + +} ; LATER-TODO tree sitter doesnt yet support switch case's with no statements ; THIS IS A HUGE HACK AND MUST BE FIXED -;; (switch_case)@switch_case { -;; edge @switch_case.after_scope -> @switch_case.before_scope -;; } +(switch_case)@switch_case { + edge @switch_case.after_scope -> @switch_case.before_scope +} ; switch case, non-empty statements, first statement -;; (switch_case -;; value:(_)@value -;; . -;; (_)@first_stmt)@switch_case { +(switch_case + value:(_)@value + . + (_)@first_stmt)@switch_case +{ -;; ; scopes flow into the value then into the first statement -;; edge @value.before_scope -> @switch_case.before_scope -;; edge @first_stmt.before_scope -> @value.after_scope -;; } + ; scopes flow into the value then into the first statement + edge @value.before_scope -> @switch_case.before_scope + edge @first_stmt.before_scope -> @value.after_scope + +} ; switch case, non-empty statements, between statement -;; (switch_case -;; value:(_) -;; (_)@left_stmt -;; . -;; (_)@right_stmt) { +(switch_case + value:(_) + (_)@left_stmt + . + (_)@right_stmt) +{ -;; ; scopes flow left to right -;; edge @right_stmt.before_scope -> @left_stmt.after_scope -;; } + ; scopes flow left to right + edge @right_stmt.before_scope -> @left_stmt.after_scope + +} ; switch case, non-empty statements, last statement -;; (switch_case -;; value:(_) -;; (_)@last_stmt -;; .)@switch_case { +(switch_case + value:(_) + (_)@last_stmt + .)@switch_case +{ -;; ; scopes flow out from the last statement to the case -;; edge @switch_case.after_scope -> @last_stmt.after_scope -;; } + ; scopes flow out from the last statement to the case + edge @switch_case.after_scope -> @last_stmt.after_scope + +} + +(switch_default)@switch_default { + + node @switch_default.before_scope + node @switch_default.after_scope + +} ; LATER-TODO tree sitter doesnt yet support empty defaults ; THIS IS A HUGE HACK AND MUST BE FIXED -;; (switch_default)@switch_default { -;; edge @switch_default.after_scope -> @switch_default.before_scope -;; } +(switch_default)@switch_default { + edge @switch_default.after_scope -> @switch_default.before_scope +} ; switch default, non-empty statements, first statement -;; (switch_default -;; . -;; (_)@first_stmt)@switch_default { +(switch_default + . + (_)@first_stmt)@switch_default +{ -;; ; scopes flow into the first statement -;; edge @first_stmt.before_scope -> @switch_default.before_scope -;; } + ; scopes flow into the first statement + edge @first_stmt.before_scope -> @switch_default.before_scope + +} ; switch default, non-empty statements, between statements -;; (switch_default -;; (_)@left_stmt -;; . -;; (_)@right_stmt) { +(switch_default + (_)@left_stmt + . + (_)@right_stmt) +{ -;; ; scopes flow left to right -;; edge @right_stmt.before_scope -> @left_stmt.after_scope -;; } + ; scopes flow left to right + edge @right_stmt.before_scope -> @left_stmt.after_scope + +} ; switch default, non-empty statements, last statement -;; (switch_default -;; (_)@last_stmt -;; .)@switch_default { +(switch_default + (_)@last_stmt + .)@switch_default +{ -;; ; scopes flow out to the default -;; edge @switch_default.after_scope -> @last_stmt.after_scope -;; } + ; scopes flow out to the default + edge @switch_default.after_scope -> @last_stmt.after_scope + +} @@ -1511,17 +1559,17 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @for_stmt.before_scope node @for_stmt.after_scope -;; ; scopes flow from statement to initializer then test then body then increment -;; edge @initializer.before_scope -> @for_stmt.before_scope -;; edge @condition.before_scope -> @initializer.after_scope -;; edge @body.before_scope -> @condition.after_scope -;; edge @increment.before_scope -> @body.after_scope + ; scopes flow from statement to initializer then test then body then increment + edge @initializer.before_scope -> @for_stmt.before_scope + edge @condition.before_scope -> @initializer.after_scope + edge @body.before_scope -> @condition.after_scope + edge @increment.before_scope -> @body.after_scope -;; ; scopes also from from the body back into the condition -;; edge @condition.before_scope -> @body.after_scope + ; scopes also from from the body back into the condition + edge @condition.before_scope -> @increment.after_scope -;; ; scopes also flow from condition out to statement -;; edge @for_stmt.after_scope -> @condition.after_scope + ; scopes also flow from condition out to statement + edge @for_stmt.after_scope -> @condition.after_scope } @@ -1537,21 +1585,25 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @for_in_stmt.before_scope node @for_in_stmt.after_scope -;; ; scopes flow from statement to right then to body then back out -;; edge @right.before_scope -> @for_in_stmt.before_scope -;; edge @body.before_scope -> @right.after_scope -;; edge @for_in_stmt.after_scope -> @body.after_scope + ; scopes flow from statement to right then to body then back out + edge @right.before_scope -> @for_in_stmt.before_scope + edge @body.before_scope -> @right.after_scope + edge @for_in_stmt.after_scope -> @body.after_scope + } -;; (for_in_statement -;; left:(identifier)@left -;; right:(_)@right -;; body:(_)@body) { +(for_in_statement + left:(identifier)@left + right:(_)@right + body:(_)@body)@for_in_stmt +{ -;; attr @left.pop "pop", "definition" -;; edge @left.pop -> @right.value -;; edge @body.before_scope -> @left.pop -;; } + node @for_in_stmt.pop + attr (@for_in_stmt.pop) node_definition = @left + edge @for_in_stmt.pop -> @right.value + edge @body.before_scope -> @for_in_stmt.pop + +} @@ -1764,17 +1816,15 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Labeled -;; TODO DEBUG!!! this doesnt work, causes a weird error - -;; (labeled_statement (_)@inner)@labeled_stmt { +(labeled_statement body:(_)@inner)@labeled_stmt { -;; node @labeled_stmt.before_scope -;; node @labeled_stmt.after_scope + node @labeled_stmt.before_scope + node @labeled_stmt.after_scope -;; ;; ; scopes flow through the inner statement then back out -;; ;; edge @inner.before_scope -> @labeled_stmt.before_scope -;; ;; edge @labeled_stmt.after_scope -> @inner.after_scope -;; } +;; ; scopes flow through the inner statement then back out +;; edge @inner.before_scope -> @labeled_stmt.before_scope +;; edge @labeled_stmt.after_scope -> @inner.after_scope +} @@ -1804,12 +1854,16 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Parenthesized -(parenthesized_expression (_)@inner)@parens { +(parenthesized_expression)@parens { node @parens.before_scope node @parens.after_scope node @parens.value +} + +(parenthesized_expression (_)@inner)@parens { + ; scopes flow right through edge @inner.before_scope -> @parens.before_scope edge @parens.after_scope -> @inner.after_scope diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index cb73bfdb5..92b611208 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -23,7 +23,7 @@ break; continue; return; ; -// foo: x; +foo: x; (5); "foo"; diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/assignment_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/assignment_expression.js index 54ed3c5ff..1293c178c 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/assignment_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/assignment_expression.js @@ -11,7 +11,7 @@ z = x; x = (y = 3); /**/ x; -// ^ defined: 1, 12 +// ^ defined: 1, 11 /****/ y; -// ^ defined: 2, 12 \ No newline at end of file +// ^ defined: 2, 11 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/augmented_assignment_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/augmented_assignment_expression.js index a676fe155..9ff2d6261 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/augmented_assignment_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/augmented_assignment_expression.js @@ -11,4 +11,4 @@ z += x; y += 1; /**/ y; -// ^ defined: 2, 12 \ No newline at end of file +// ^ defined: 2, 11 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/update_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/update_expression.js index 0c1b30f52..02d3318c7 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/update_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/update_expression.js @@ -7,4 +7,4 @@ let x = 1; // Flow around and update /**/ x; -// ^ defined: 1, 5 \ No newline at end of file +// ^ defined: 1, 4 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/for_in_statement.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/for_in_statement.js new file mode 100644 index 000000000..eac6898a8 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/for_in_statement.js @@ -0,0 +1,25 @@ +let x = 1; + +// Flow in + +for (let y in (x, 1)) { + // ^ defined: 1 + /**/ x; + // ^ defined: 1 + /**/ y; + // ^ defined: 5 + z = 1; +} + +// Flow out + +/**/ y; +// ^ defined: 5 + +/**/ z; +// ^ defined: 11 + +// Flow around + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/for_statement.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/for_statement.js new file mode 100644 index 000000000..7a1f8b29f --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/for_statement.js @@ -0,0 +1,31 @@ +let x = 1; + +// Flow in + +for (let y = (x, 1); + // ^ defined: 1 + /**************/ x < y; + // ^ defined: 1 + // ^ defined: 5, 10 + /*********************/ y = (x, y)) { + // ^ defined: 1 + // ^ defined: 5, 10 + /**/ x; + // ^ defined: 1 + /**/ y; + // ^ defined: 5, 10 + z = 1; +} + +// Flow out + +/**/ y; +// ^ defined: 5, 10 + +/**/ z; +// ^ defined: 17 + +// Flow around + +/**/ x; +// ^ defined 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/if_statement.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/if_statement.js index 51d819194..c278bba7b 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/statements/if_statement.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/if_statement.js @@ -2,8 +2,29 @@ let x = 1; // Flow in -if (x) { +// TODO NOW add flow into the condition too +if (/**/ x) { // ^ defined: 1 /**/ x; // ^ defined: 1 -} \ No newline at end of file + y = 2; +} else if (x) { + // ^ defined: 1 + /**/ x; + // ^ defined: 1 + y = 2; +} else { + /**/ x; + // ^ defined: 1 + y = 2; +} + +// Flow out + +/**/ y; +// ^ defined: 10, 15, 19 + +// Flow around + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/switch_statement.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/switch_statement.js new file mode 100644 index 000000000..38287a7cf --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/switch_statement.js @@ -0,0 +1,25 @@ +let x = 1; + +// Flow in + +switch (x) { + // ^ defined: 1 + case value: + /**/ x; + // ^ defined: 1 + y = 2; + default: + /**/ x; + // ^ defined: 1 + y = 2; +} + +// Flow out + +/**/ y; +// ^ defined: 10, 16 + +// Flow around + +/**/ x; +// ^ defined: 1 \ No newline at end of file From 1b65b0fd13a6b10a90c3e87baeeadef0af583603 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 9 May 2023 17:17:59 -0700 Subject: [PATCH 007/500] Adds more statements --- .../src/stack-graphs.tsg | 142 ++++++++++-------- .../test/statements/do_statement.js | 25 +++ .../test/statements/try_statement.js | 31 ++++ .../test/statements/while_statement.js | 25 +++ .../test/statements/with_statement.js | 25 +++ 5 files changed, 189 insertions(+), 59 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/do_statement.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/try_statement.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/while_statement.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/with_statement.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index a03cf2913..55f1fafac 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -1617,13 +1617,13 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @while_stmt.before_scope node @while_stmt.after_scope -;; ; scopes flow from while to condition then to body then back out -;; edge @condition.before_scope -> @while_stmt.before_scope -;; edge @body.before_scope -> @condition.after_scope -;; edge @while_stmt.after_scope -> @body.after_scope + ; scopes flow from while to condition then to body then back out + edge @condition.before_scope -> @while_stmt.before_scope + edge @body.before_scope -> @condition.after_scope + edge @while_stmt.after_scope -> @body.after_scope -;; ; scopes also flow back into the condition -;; edge @condition.before_scope -> @body.after_scope + ; scopes also flow back into the condition + edge @condition.before_scope -> @body.after_scope } @@ -1638,13 +1638,13 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @do_stmt.before_scope node @do_stmt.after_scope -;; ; scopes flow from statement to body then condition then back to statement -;; edge @body.before_scope -> @do_stmt.before_scope -;; edge @condition.before_scope -> @body.after_scope -;; edge @do_stmt.after_scope -> @condition.after_scope + ; scopes flow from statement to body then condition then back to statement + edge @body.before_scope -> @do_stmt.before_scope + edge @condition.before_scope -> @body.after_scope + edge @do_stmt.after_scope -> @condition.after_scope -;; ; scopes also flow back to the body from the condition -;; edge @body.before_scope -> @condition.after_scope + ; scopes also flow back to the body from the condition + edge @body.before_scope -> @condition.after_scope } @@ -1657,58 +1657,81 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @try_stmt.before_scope node @try_stmt.after_scope -;; ; scopes flow into the body then back out -;; edge @body.before_scope -> @try_stmt.before_scope -;; edge @try_stmt.after_scope -> @body.after_scope + ; scopes flow into the body then back out + edge @body.before_scope -> @try_stmt.before_scope + edge @try_stmt.after_scope -> @body.after_scope } -;; (try_statement -;; body:(_)@body -;; handler:(_)@handler)@try_stmt { +(try_statement + body:(_)@body + handler:(_)@handler)@try_stmt +{ -;; ; scopes flow from body to handler then back out -;; edge @handler.before_scope -> @body.after_scope -;; edge @try_stmt.after_scope -> @handler.after_scope -;; } + ; scopes flow from body to handler then back out + edge @handler.before_scope -> @body.after_scope + edge @try_stmt.after_scope -> @handler.after_scope -;; (try_statement -;; body:(_)@body -;; finalizer:(_)@finalizer)@try_stmt { +} -;; ; scopes flow from body to finalizer then back out -;; edge @finalizer.before_scope -> @body.after_scope -;; edge @try_stmt.after_scope -> @finalizer.after_scope -;; } +(try_statement + body:(_)@body + finalizer:(_)@finalizer)@try_stmt +{ -;; (try_statement -;; handler:(_)@handler -;; finalizer:(_)@finalizer)@try_stmt { + ; scopes flow from body to finalizer then back out + edge @finalizer.before_scope -> @body.after_scope -;; ; scopes flow from handler to finalizer then back out -;; edge @finalizer.before_scope -> @handler.after_scope -;; edge @try_stmt.after_scope -> @finalizer.after_scope -;; } +} -;; (catch_clause body:(_)@body)@catch_clause { -;; ; scopes flow in then back out -;; edge @body.before_scope -> @catch_clause.before_scope -;; edge @catch_clause.after_scope -> @body.after_scope -;; } +(try_statement + handler:(_)@handler + finalizer:(_)@finalizer)@try_stmt +{ -;; (catch_clause -;; parameter:(identifier)@name -;; body:(_)@body) { + ; scopes flow from handler to finalizer then back out + edge @finalizer.before_scope -> @handler.after_scope -;; attr @name.pop "pop", "definition" -;; edge @body.before_scope -> @name.pop -;; } +} -;; (finally_clause body:(_)@body)@finally_clause { -;; ; scopes flow in thenback out -;; edge @body.before_scope -> @finally_clause.before_scope -;; edge @finally_clause.after_scope -> @body.after_scope -;; } +(try_statement finalizer:(_)@finalizer)@try_stmt { + + edge @try_stmt.after_scope -> @finalizer.after_scope + +} + +(catch_clause body:(_)@body)@catch_clause { + + node @catch_clause.before_scope + node @catch_clause.after_scope + + ; scopes flow in then back out + edge @body.before_scope -> @catch_clause.before_scope + edge @catch_clause.after_scope -> @body.after_scope + +} + +(catch_clause + parameter:(identifier)@name + body:(_)@body)@catch_clause +{ + + node @catch_clause.pop + attr (@catch_clause.pop) node_definition = @name + edge @body.before_scope -> @catch_clause.pop + +} + +(finally_clause body:(_)@body)@finally_clause { + + node @finally_clause.before_scope + node @finally_clause.after_scope + + ; scopes flow in thenback out + edge @body.before_scope -> @finally_clause.before_scope + edge @finally_clause.after_scope -> @body.after_scope + +} @@ -1721,15 +1744,16 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @with_stmt.before_scope node @with_stmt.after_scope + node @with_stmt.push_dot -;; ; scopes flow from the statement into the object then into the body then back out -;; edge @object.before_scope -> @with_stmt.before_scope -;; edge @body.before_scope -> @object.after_scope -;; edge @with_stmt.after_scope -> @body.after_scope + ; scopes flow from the statement into the object then into the body then back out + edge @object.before_scope -> @with_stmt.before_scope + edge @body.before_scope -> @object.after_scope + edge @with_stmt.after_scope -> @body.after_scope -;; attr @object.push_dot "push" = "." -;; edge @object.push_dot -> @object.value -;; edge @body.before_scope -> @object.push_dot + attr (@with_stmt.push_dot) push_symbol = "." + edge @with_stmt.push_dot -> @object.value + edge @body.before_scope -> @with_stmt.push_dot } diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/do_statement.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/do_statement.js new file mode 100644 index 000000000..be81e9e2a --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/do_statement.js @@ -0,0 +1,25 @@ +let x = 1; + +// Flow in + +do { + /**/ x; + // ^ defined: 1 + /**/ y; + // ^ defined: 11 + z = 1; +} while ((x, y = 5)); +// ^ defined: 1 + +// Flow out + +/**/ y; +// ^ defined: 11 + +/**/ z; +// ^ defined: 10 + +// Flow around + +/**/ x; +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/try_statement.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/try_statement.js new file mode 100644 index 000000000..0b6613243 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/try_statement.js @@ -0,0 +1,31 @@ +let x = 1; + +// Flow in + +try { + /**/ x; + // ^ defined: 1 + y = 1; +} catch (e) { + /**/ e + // ^ defined: 9 + /**/ y; + // ^ defined: 8 + y = 1; +} finally { + /**/ x; + // ^ defined: 1 + /**/ y; + // ^ defined: 8, 14 + y = 1; +} + +// Flow out + +/**/ y; +// ^ defined: 8, 14, 20 + +// Flow around + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/while_statement.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/while_statement.js new file mode 100644 index 000000000..6df4acafe --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/while_statement.js @@ -0,0 +1,25 @@ +let x = 1; + +// Flow in + +while ((x, y = 5)) { + // ^ defined: 1 + /**/ x; + // ^ defined: 1 + /**/ y; + // ^ defined: 5 + z = 1; +} + +// Flow out + +/**/ y; +// ^ defined: 5 + +/**/ z; +// ^ defined: 11 + +// Flow around + +/**/ x; +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/with_statement.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/with_statement.js new file mode 100644 index 000000000..8b11e2de9 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/with_statement.js @@ -0,0 +1,25 @@ +let x = 1; + +// Flow in + +with ((y = 1, x)) { + // ^ defined: 1 + /**/ x; + // ^ defined: 1 + /**/ y; + // ^ defined: 5 + z = 1; +} + +// Flow out + +/**/ y; +// ^ defined: 5 + +/**/ z; +// ^ defined: 11 + +// Flow around + +/**/ x; +// ^ defined: 1 \ No newline at end of file From 2d8535f8391817bc7ec1e9e7f99274404d57e946 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 9 May 2023 17:18:20 -0700 Subject: [PATCH 008/500] Moves old tests into a dir --- .../{ => old}/binding/default_arguments_from_enclosing_scope.js | 0 .../{ => old}/binding/default_arguments_from_other_arguments.js | 0 .../test/{ => old}/binding/destructuring_assignments.js | 0 ...estructuring_assignments_with_defaults_from_enclosing_scope.js | 0 ...estructuring_assignments_with_defaults_from_other_variables.js | 0 .../test/{ => old}/binding/destructuring_parameters.js | 0 .../test/{ => old}/binding/object_assignment_patterns.js | 0 .../test/{ => old}/binding/simple.js | 0 .../test/{ => old}/bug_regressions/2141.js | 0 .../test/{ => old}/bug_regressions/2227.js | 0 .../test/{ => old}/bug_regressions/2291.js | 0 .../test/{ => old}/classes_and_instances/class_declaration.js | 0 .../test/{ => old}/classes_and_instances/class_expression.js | 0 .../classes_and_instances/class_expression_superclasses.js | 0 .../classes_and_instances/class_expression_this_field_access.js | 0 .../test/{ => old}/classes_and_instances/field_declaration.js | 0 .../classes_and_instances/function_class_this_field_access.js | 0 .../{ => old}/classes_and_instances/method_call_this_argument.js | 0 .../test/{ => old}/classes_and_instances/method_definition.js | 0 .../test/{ => old}/classes_and_instances/superclasses.js | 0 .../test/{ => old}/classes_and_instances/this_field_access.js | 0 .../test/{ => old}/compound_literals/arrays.js | 0 .../test/{ => old}/compound_literals/object_extend_method.js | 0 .../test/{ => old}/compound_literals/objects.js | 0 .../test/{ => old}/control_flow_statements/dowhile.js | 0 .../test/{ => old}/control_flow_statements/for.js | 0 .../test/{ => old}/control_flow_statements/forin.js | 0 .../test/{ => old}/control_flow_statements/if.js | 0 .../test/{ => old}/control_flow_statements/try.js | 0 .../test/{ => old}/control_flow_statements/while.js | 0 .../test/{ => old}/control_flow_statements/with.js | 0 .../test/{ => old}/functions_and_calls/arguments_variable.js | 0 .../arrow_function_values_with_param_lists_and_block_bodies.js | 0 .../arrow_function_values_with_param_lists_and_expr_bodies.js | 0 .../arrow_function_values_with_single_param_and_block_bodies.js | 0 .../arrow_function_values_with_single_param_and_expr_bodies.js | 0 .../test/{ => old}/functions_and_calls/call_arguments.js | 0 .../test/{ => old}/functions_and_calls/function_declarations.js | 0 .../test/{ => old}/functions_and_calls/function_values.js | 0 .../functions_and_calls/generator_function_declarations.js | 0 .../{ => old}/functions_and_calls/generator_function_values.js | 0 .../{ => old}/imports_and_exports/commonjs_imports_and_exports.js | 0 .../test/{ => old}/imports_and_exports/es6_imports_and_exports.js | 0 43 files changed, 0 insertions(+), 0 deletions(-) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/binding/default_arguments_from_enclosing_scope.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/binding/default_arguments_from_other_arguments.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/binding/destructuring_assignments.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/binding/destructuring_assignments_with_defaults_from_enclosing_scope.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/binding/destructuring_assignments_with_defaults_from_other_variables.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/binding/destructuring_parameters.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/binding/object_assignment_patterns.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/binding/simple.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/bug_regressions/2141.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/bug_regressions/2227.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/bug_regressions/2291.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/classes_and_instances/class_declaration.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/classes_and_instances/class_expression.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/classes_and_instances/class_expression_superclasses.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/classes_and_instances/class_expression_this_field_access.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/classes_and_instances/field_declaration.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/classes_and_instances/function_class_this_field_access.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/classes_and_instances/method_call_this_argument.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/classes_and_instances/method_definition.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/classes_and_instances/superclasses.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/classes_and_instances/this_field_access.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/compound_literals/arrays.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/compound_literals/object_extend_method.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/compound_literals/objects.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/control_flow_statements/dowhile.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/control_flow_statements/for.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/control_flow_statements/forin.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/control_flow_statements/if.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/control_flow_statements/try.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/control_flow_statements/while.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/control_flow_statements/with.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/functions_and_calls/arguments_variable.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/functions_and_calls/arrow_function_values_with_param_lists_and_block_bodies.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/functions_and_calls/arrow_function_values_with_param_lists_and_expr_bodies.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/functions_and_calls/arrow_function_values_with_single_param_and_block_bodies.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/functions_and_calls/arrow_function_values_with_single_param_and_expr_bodies.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/functions_and_calls/call_arguments.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/functions_and_calls/function_declarations.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/functions_and_calls/function_values.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/functions_and_calls/generator_function_declarations.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/functions_and_calls/generator_function_values.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/imports_and_exports/commonjs_imports_and_exports.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{ => old}/imports_and_exports/es6_imports_and_exports.js (100%) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/binding/default_arguments_from_enclosing_scope.js b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/default_arguments_from_enclosing_scope.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/binding/default_arguments_from_enclosing_scope.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/binding/default_arguments_from_enclosing_scope.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/binding/default_arguments_from_other_arguments.js b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/default_arguments_from_other_arguments.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/binding/default_arguments_from_other_arguments.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/binding/default_arguments_from_other_arguments.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_assignments.js b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_assignments.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_assignments_with_defaults_from_enclosing_scope.js b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments_with_defaults_from_enclosing_scope.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_assignments_with_defaults_from_enclosing_scope.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments_with_defaults_from_enclosing_scope.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_assignments_with_defaults_from_other_variables.js b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments_with_defaults_from_other_variables.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_assignments_with_defaults_from_other_variables.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments_with_defaults_from_other_variables.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_parameters.js b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_parameters.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/binding/destructuring_parameters.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_parameters.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/binding/object_assignment_patterns.js b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/object_assignment_patterns.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/binding/object_assignment_patterns.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/binding/object_assignment_patterns.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/binding/simple.js b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/simple.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/binding/simple.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/binding/simple.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/bug_regressions/2141.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/2141.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/bug_regressions/2141.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/2141.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/bug_regressions/2227.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/2227.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/bug_regressions/2227.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/2227.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/bug_regressions/2291.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/2291.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/bug_regressions/2291.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/2291.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_declaration.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_declaration.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_declaration.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_declaration.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_expression.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_expression.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_expression.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_expression_superclasses.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_expression_superclasses.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_expression_superclasses.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_expression_superclasses.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_expression_this_field_access.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_expression_this_field_access.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/class_expression_this_field_access.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_expression_this_field_access.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/field_declaration.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/field_declaration.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/field_declaration.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/field_declaration.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/function_class_this_field_access.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/function_class_this_field_access.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/function_class_this_field_access.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/function_class_this_field_access.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/method_call_this_argument.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/method_call_this_argument.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/method_call_this_argument.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/method_call_this_argument.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/method_definition.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/method_definition.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/method_definition.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/method_definition.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/superclasses.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/superclasses.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/superclasses.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/superclasses.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/this_field_access.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/this_field_access.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/classes_and_instances/this_field_access.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/this_field_access.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_literals/arrays.js b/languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/arrays.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/compound_literals/arrays.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/arrays.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_literals/object_extend_method.js b/languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/object_extend_method.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/compound_literals/object_extend_method.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/object_extend_method.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_literals/objects.js b/languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/objects.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/compound_literals/objects.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/objects.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/dowhile.js b/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/dowhile.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/dowhile.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/dowhile.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/for.js b/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/for.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/for.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/for.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/forin.js b/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/forin.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/forin.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/forin.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/if.js b/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/if.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/if.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/if.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/try.js b/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/try.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/try.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/try.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/while.js b/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/while.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/while.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/while.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/with.js b/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/with.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/control_flow_statements/with.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/with.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arguments_variable.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arguments_variable.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arguments_variable.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arguments_variable.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_param_lists_and_block_bodies.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_param_lists_and_block_bodies.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_param_lists_and_block_bodies.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_param_lists_and_block_bodies.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_param_lists_and_expr_bodies.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_param_lists_and_expr_bodies.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_param_lists_and_expr_bodies.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_param_lists_and_expr_bodies.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_single_param_and_block_bodies.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_single_param_and_block_bodies.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_single_param_and_block_bodies.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_single_param_and_block_bodies.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_single_param_and_expr_bodies.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_single_param_and_expr_bodies.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/arrow_function_values_with_single_param_and_expr_bodies.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_single_param_and_expr_bodies.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/call_arguments.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/call_arguments.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/call_arguments.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/call_arguments.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/function_declarations.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/function_declarations.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/function_declarations.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/function_declarations.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/function_values.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/function_values.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/function_values.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/function_values.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/generator_function_declarations.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/generator_function_declarations.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/generator_function_declarations.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/generator_function_declarations.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/generator_function_values.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/generator_function_values.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/functions_and_calls/generator_function_values.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/generator_function_values.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/imports_and_exports/commonjs_imports_and_exports.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/commonjs_imports_and_exports.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/imports_and_exports/commonjs_imports_and_exports.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/commonjs_imports_and_exports.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/imports_and_exports/es6_imports_and_exports.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/es6_imports_and_exports.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/imports_and_exports/es6_imports_and_exports.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/es6_imports_and_exports.js From 21caf96e2dcee57de7d64bd3a129658a1efbbd8d Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 9 May 2023 18:01:05 -0700 Subject: [PATCH 009/500] Adds more expression tests and more statements --- .../src/stack-graphs.tsg | 52 +++++++++++++++---- .../assignment_expression.js | 2 +- .../augmented_assignment_expression.js | 2 +- .../test/simple_expressions/await.js | 9 +++- .../simple_expressions/binary_expression.js | 9 +++- .../test/simple_expressions/comma.js | 26 ++++++++-- .../parenthesized_expression.js | 7 +++ .../simple_expressions/template_strings.js | 20 ++++++- .../simple_expressions/ternary_expression.js | 33 ++++++++++-- .../simple_expressions/unary_expression.js | 8 +++ .../simple_expressions/update_expression.js | 10 +++- .../test/simple_expressions/variable.js | 1 + .../simple_expressions/yield_expression.js | 8 +++ .../label_continue_break_statements.js | 15 ++++++ .../test/statements/label_statement.js | 16 ++++++ ...ical_declaration_basic_no_destructuring.js | 2 +- .../test/statements/switch_statement.js | 4 +- ...able_declaration_basic_no_destructuring.js | 2 +- 18 files changed, 198 insertions(+), 28 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/label_continue_break_statements.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/label_statement.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 55f1fafac..86df155a1 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -1751,7 +1751,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @body.before_scope -> @object.after_scope edge @with_stmt.after_scope -> @body.after_scope - attr (@with_stmt.push_dot) push_symbol = "." + attr (@with_stmt.push_dot) push_symbol = "GUARD:MEMBER" edge @with_stmt.push_dot -> @object.value edge @body.before_scope -> @with_stmt.push_dot } @@ -1765,8 +1765,20 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @break_stmt.before_scope node @break_stmt.after_scope - ;; ; scopes flow through unchanged - ;; edge @break_stmt.after_scope -> @break_stmt.before_scope + ; scopes flow through unchanged + edge @break_stmt.after_scope -> @break_stmt.before_scope +} + +(break_statement (_)@label)@break_stmt { + + node @break_stmt.label_push + node @break_stmt.label_guard + + attr (@break_stmt.label_guard) push_symbol = "GUARD:LABEL" + attr (@break_stmt.label_push) node_reference = @label + + edge @break_stmt.label_push -> @break_stmt.label_guard + edge @break_stmt.label_guard -> @break_stmt.before_scope } @@ -1778,8 +1790,20 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @continue_stmt.before_scope node @continue_stmt.after_scope -;; ; scopes flow through unchanged -;; edge @continue_stmt.after_scope -> @continue_stmt.before_scope + ; scopes flow through unchanged + edge @continue_stmt.after_scope -> @continue_stmt.before_scope +} + +(continue_statement (_)@label)@continue_stmt { + + node @continue_stmt.label_push + node @continue_stmt.label_guard + + attr (@continue_stmt.label_guard) push_symbol = "GUARD:LABEL" + attr (@continue_stmt.label_push) node_reference = @label + + edge @continue_stmt.label_push -> @continue_stmt.label_guard + edge @continue_stmt.label_guard -> @continue_stmt.before_scope } @@ -1840,14 +1864,24 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Labeled -(labeled_statement body:(_)@inner)@labeled_stmt { +(labeled_statement + label:(_)@label + body:(_)@inner)@labeled_stmt +{ node @labeled_stmt.before_scope node @labeled_stmt.after_scope + node @labeled_stmt.label_pop + node @labeled_stmt.label_guard + + attr (@labeled_stmt.label_guard) pop_symbol = "GUARD:LABEL" + attr (@labeled_stmt.label_pop) node_definition = @label -;; ; scopes flow through the inner statement then back out -;; edge @inner.before_scope -> @labeled_stmt.before_scope -;; edge @labeled_stmt.after_scope -> @inner.after_scope + ; scopes flow through the inner statement then back out + edge @inner.before_scope -> @labeled_stmt.before_scope + edge @inner.before_scope -> @labeled_stmt.label_guard + edge @labeled_stmt.label_guard -> @labeled_stmt.label_pop + edge @labeled_stmt.after_scope -> @inner.after_scope } diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/assignment_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/assignment_expression.js index 1293c178c..d03c690cc 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/assignment_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/assignment_expression.js @@ -6,7 +6,7 @@ let z = 3; z = x; // ^ defined: 1 -// Flow around and update +// Flow around, update, and out x = (y = 3); diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/augmented_assignment_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/augmented_assignment_expression.js index 9ff2d6261..b8c31a7f8 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/augmented_assignment_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/augmented_assignment_expression.js @@ -6,7 +6,7 @@ let z = 3; z += x; // ^ defined: 1 -// Flow around and update +// Flow around and out y += 1; diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/await.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/await.js index ba47cd64d..0a0d43e06 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/await.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/await.js @@ -7,4 +7,11 @@ await x; // Flow around /**/ x; -// ^ defined: 1 \ No newline at end of file +// ^ defined: 1 + +// Flow out + +await y = 1; + +/**/ y; +// ^ defined: 14 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/binary_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/binary_expression.js index e056da627..88da3d14a 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/binary_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/binary_expression.js @@ -8,4 +8,11 @@ let x = 1; // Flow around /**/ x; -// ^ defined: 1 \ No newline at end of file +// ^ defined: 1 + +// Flow out + +x + (y = 1); + +/**/ y; +// ^ defined: 15 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/comma.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/comma.js index 58a51610e..940482749 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/comma.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/comma.js @@ -1,7 +1,23 @@ let x = 1; -let y = (1, x); -// ^ defined: 1 -let y = (1, x = 5); -let z = x; -// ^ defined: 1, 5 +// Flow in + +(1, x); +// ^ defined: 1 + +(y = 1, y); +// ^ defined: 8 + +// Flow out + +(1, z = 5); + +/**/ y; +// ^ defined: 8 +/**/ z; +// ^ defined: 13 + +// Flow around + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/parenthesized_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/parenthesized_expression.js index 257737fce..07a787792 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/parenthesized_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/parenthesized_expression.js @@ -4,6 +4,13 @@ let x = 1; /**/ (x); // ^ defined: 1 +// Flow out + +(y = 1); + +/**/ y; +// ^ defined: 9 + // Flow around /**/ x; diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/template_strings.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/template_strings.js index 099cd1d37..f8bfa0837 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/template_strings.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/template_strings.js @@ -1,4 +1,20 @@ let x = 1; -let y = `template ${ x } string`; -// ^ defined: 1 +// Flow in + +`template ${x} string`; +// ^ defined: 1 + +`template ${y = 1} ${y} string`; +// ^ defined: 8 + + +// Flow out + +/**/ y; +// ^ defined: 8 + +// Flow around + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/ternary_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/ternary_expression.js index 6f0131464..5e22add80 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/ternary_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/ternary_expression.js @@ -1,4 +1,31 @@ let x = 1; -let y = true ? x = 5 : 2; -let z = x; -// ^ defined: 1, 2 + +// Flow in + +/**/ x ? x : x; +// ^ defined: 1 +// ^ defined: 1 +// ^ defined: 1 + +// Flow out + +(y = 1) ? + /**/ (y, z = 1) : + // ^ defined: 12 + /**/ (y, w = 1); + // ^ defined: 12 + + +/**/ y; +// ^ defined: 12 + +/**/ z; +// ^ defined: 13 + +/**/ w; +// ^ defined: 15 + +// Flow around + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/unary_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/unary_expression.js index 649ffb31e..0dbb71814 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/unary_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/unary_expression.js @@ -1,9 +1,17 @@ let x = 1; // Flow in + /**/ -x; // ^ defined: 1 +// Flow out + +-(y = 1); + +/**/ y; +// ^ defined: 10 + // Flow around /**/ x; diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/update_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/update_expression.js index 02d3318c7..2197e5571 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/update_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/update_expression.js @@ -1,10 +1,18 @@ let x = 1; // Flow in + /**/ x++; // ^ defined: 1 +// Flow out + +--(y = 1); + +/**/ y; +// ^ defined: 10 + // Flow around and update /**/ x; -// ^ defined: 1, 4 \ No newline at end of file +// ^ defined: 1, 5 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variable.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variable.js index 10b835b75..05ba7b308 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variable.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variable.js @@ -1,6 +1,7 @@ let x = 1; // Flow in + /**/ x; // ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js index 14fa90440..ff2bab226 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js @@ -1,9 +1,17 @@ let x = 1; // Flow in + yield x; // ^ defined: 1 +// Flow out + +yield y = 1; + +/**/ y; +// ^ defined: 10 + // Flow around /**/ x; diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/label_continue_break_statements.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/label_continue_break_statements.js new file mode 100644 index 000000000..f205dcefe --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/label_continue_break_statements.js @@ -0,0 +1,15 @@ +let x = 1; + +outer: while (t) { + while (t) { + break outer; + // ^ defined: 3 + } + continue outer; + // ^ defined: 3 +} + +// Flow around + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/label_statement.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/label_statement.js new file mode 100644 index 000000000..5ebc6df3c --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/label_statement.js @@ -0,0 +1,16 @@ +let x = 1; + +// Flow in + +label: x, y = 1; +// ^ defined: 1 + +// Flow out + +/**/ y; +// ^ defined: 5 + +// Flow around + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/lexical_declaration_basic_no_destructuring.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/lexical_declaration_basic_no_destructuring.js index 0a5b6fd3a..de4720de3 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/statements/lexical_declaration_basic_no_destructuring.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/lexical_declaration_basic_no_destructuring.js @@ -15,4 +15,4 @@ let y = x; let x = 2; /**/ x; -// ^ defined: 17 \ No newline at end of file +// ^ defined: 16 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/switch_statement.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/switch_statement.js index 38287a7cf..a40f7f2e9 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/statements/switch_statement.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/switch_statement.js @@ -4,7 +4,7 @@ let x = 1; switch (x) { // ^ defined: 1 - case value: + case 0: /**/ x; // ^ defined: 1 y = 2; @@ -17,7 +17,7 @@ switch (x) { // Flow out /**/ y; -// ^ defined: 10, 16 +// ^ defined: 10, 14 // Flow around diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/variable_declaration_basic_no_destructuring.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/variable_declaration_basic_no_destructuring.js index d1aacbc58..7cc45c1c7 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/statements/variable_declaration_basic_no_destructuring.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/variable_declaration_basic_no_destructuring.js @@ -15,4 +15,4 @@ var y = x; var x = 2; /**/ x; -// ^ defined: 17 \ No newline at end of file +// ^ defined: 16 \ No newline at end of file From fa9c77e6b8ce06ffc989766af3712df6a52887e4 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 9 May 2023 18:09:11 -0700 Subject: [PATCH 010/500] Adds more section headers --- .../src/stack-graphs.tsg | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 86df155a1..691592cf3 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -398,6 +398,14 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ### Statement Queries + + +;; ███████ ██ ██ ██████ ██████ ██████ ████████ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; █████ ███ ██████ ██ ██ ██████ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ███████ ██ ██ ██ ██████ ██ ██ ██ ███████ + ;; #### Export (export_statement)@export_stmt { @@ -651,6 +659,12 @@ attribute node_symbol = node => symbol = (source-text node), source_n +;; ██ ███ ███ ██████ ██████ ██████ ████████ ███████ +;; ██ ████ ████ ██ ██ ██ ██ ██ ██ ██ ██ +;; ██ ██ ████ ██ ██████ ██ ██ ██████ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ██ ██ ██ ██ ██████ ██ ██ ██ ███████ + ;; #### Import ; https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import @@ -848,6 +862,18 @@ attribute node_symbol = node => symbol = (source-text node), source_n +;; ███ ██ ██████ ██████ ███ ███ █████ ██ +;; ████ ██ ██ ██ ██ ██ ████ ████ ██ ██ ██ +;; ██ ██ ██ ██ ██ ██████ ██ ████ ██ ███████ ██ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ██ ████ ██████ ██ ██ ██ ██ ██ ██ ███████ + +;; ███████ ████████ █████ ████████ ███████ ███ ███ ███████ ███ ██ ████████ ███████ +;; ██ ██ ██ ██ ██ ██ ████ ████ ██ ████ ██ ██ ██ +;; ███████ ██ ███████ ██ █████ ██ ████ ██ █████ ██ ██ ██ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ███████ ██ ██ ██ ██ ███████ ██ ██ ███████ ██ ████ ██ ███████ + ;; #### Debugger (debugger_statement)@debugger_stmt { From a77344d2655137867f862183de68edfeb6c0d3ef Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 10 May 2023 13:43:58 +0200 Subject: [PATCH 011/500] Update project structure --- ...sh-tree-sitter-stack-graphs-javascript.yml | 45 ++++++++++ .../.gitignore | 1 + .../CHANGELOG.md | 6 ++ .../Cargo.toml | 30 +++++-- .../README.md | 88 ++++++++++++++++--- .../bindings/rust/lib.rs | 7 -- .../package.json | 20 ----- .../rust/bin.rs | 33 +++++++ .../rust/lib.rs | 50 +++++++++++ .../rust/test.rs | 24 +++++ 10 files changed, 257 insertions(+), 47 deletions(-) create mode 100644 .github/workflows/publish-tree-sitter-stack-graphs-javascript.yml create mode 100644 languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md delete mode 100644 languages/tree-sitter-stack-graphs-javascript/bindings/rust/lib.rs delete mode 100644 languages/tree-sitter-stack-graphs-javascript/package.json create mode 100644 languages/tree-sitter-stack-graphs-javascript/rust/bin.rs create mode 100644 languages/tree-sitter-stack-graphs-javascript/rust/lib.rs create mode 100644 languages/tree-sitter-stack-graphs-javascript/rust/test.rs diff --git a/.github/workflows/publish-tree-sitter-stack-graphs-javascript.yml b/.github/workflows/publish-tree-sitter-stack-graphs-javascript.yml new file mode 100644 index 000000000..ff6826770 --- /dev/null +++ b/.github/workflows/publish-tree-sitter-stack-graphs-javascript.yml @@ -0,0 +1,45 @@ +name: Publish tree-sitter-stack-graphs-javascript release + +on: + push: + tags: + - tree-sitter-stack-graphs-javascript-v* + +jobs: + publish-crate: + runs-on: ubuntu-latest + env: + CARGO_TERM_COLOR: always + CARGO_INCREMENTAL: 0 + CRATE_DIR: './languages/tree-sitter-stack-graphs-javascript' + steps: + - name: Install Rust environment + uses: hecrj/setup-rust-action@v1 + - name: Checkout repository + uses: actions/checkout@v3 + # TODO Verify the crate version matches the tag + - name: Test crate + run: cargo test --all-features + working-directory: ${{ env.CRATE_DIR }} + - name: Verify publish crate + run: cargo publish --dry-run + working-directory: ${{ env.CRATE_DIR }} + - name: Publish crate + run: cargo publish + working-directory: ${{ env.CRATE_DIR }} + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + create-release: + needs: publish-crate + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Create GitHub release + uses: ncipollo/release-action@v1 + with: + body: | + Find more info on all releases at https://crates.io/crates/tree-sitter-stack-graphs-javascript. + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/languages/tree-sitter-stack-graphs-javascript/.gitignore b/languages/tree-sitter-stack-graphs-javascript/.gitignore index 186883d53..7392bff36 100644 --- a/languages/tree-sitter-stack-graphs-javascript/.gitignore +++ b/languages/tree-sitter-stack-graphs-javascript/.gitignore @@ -1,3 +1,4 @@ +*.html /Cargo.lock /node_modules /package-lock.json diff --git a/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md b/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md new file mode 100644 index 000000000..3b21ea383 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md @@ -0,0 +1,6 @@ +# Changelog for tree-sitter-stack-graphs-javascript + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml index f7d6607e4..1cc716577 100644 --- a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -5,15 +5,33 @@ description = "Stack graphs definition for JavaScript using tree-sitter-javascri readme = "README.md" keywords = ["tree-sitter", "stack-graphs", "javascript"] authors = ["Beka Valentine "] +license = "MIT OR Apache-2.0" edition = "2018" -include = [ - "bindings/rust", - "src" -] +[[bin]] +name = "tree-sitter-stack-graphs-javascript" +path = "rust/bin.rs" +required-features = ["cli"] [lib] -path = "bindings/rust/lib.rs" +path = "rust/lib.rs" +test = false + +[[test]] +name = "test" +path = "rust/test.rs" +harness = false + +[features] +cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"] + +[dependencies] +anyhow = { version = "1.0", optional = true } +clap = { version = "3", optional = true } +stack-graphs = { version = "0.10", path = "../../stack-graphs" } +tree-sitter-stack-graphs = { version = "0.6", path = "../../tree-sitter-stack-graphs" } +tree-sitter-javascript = "0.20" [dev-dependencies] -tree-sitter-stack-graphs = "~0.6.0" +anyhow = "1.0" +tree-sitter-stack-graphs = { version = "0.6", path = "../../tree-sitter-stack-graphs", features = ["cli"] } diff --git a/languages/tree-sitter-stack-graphs-javascript/README.md b/languages/tree-sitter-stack-graphs-javascript/README.md index 8e5adec15..3b53f03de 100644 --- a/languages/tree-sitter-stack-graphs-javascript/README.md +++ b/languages/tree-sitter-stack-graphs-javascript/README.md @@ -1,38 +1,98 @@ # tree-sitter-stack-graphs definition for JavaScript -This project defines tree-sitter-stack-graphs rules for JavaScript using the [tree-sitter-javascript](https://www.npmjs.com/package/tree-sitter-javascript) grammar. +This project defines tree-sitter-stack-graphs rules for JavaScript using the [tree-sitter-javascript][] grammar. + +[tree-sitter-javascript]: https://crates.io/crates/tree-sitter-javascript + +## Usage + +To use this library, add the following to your `Cargo.toml`: + +``` toml +[dependencies] +tree-sitter-stack-graphs-javascript = "0.0.1" +``` + +Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-javascript/*/) for more details on how to use this library. + +## Command-line Program + +The command-line program for `tree-sitter-stack-graphs-javascript` lets you do stack graph based analysis and lookup from the command line. + +Install the program using `cargo install` as follows: + +``` sh +$ cargo install --features cli tree-sitter-stack-graphs-javascript +$ tree-sitter-stack-graphs-javascript --help +``` ## Development +The project is written in Rust, and requires a recent version installed. Rust can be installed and updated using [rustup][]. + +[rustup]: https://rustup.rs/ + The project is organized as follows: - The stack graph rules are defined in `src/stack-graphs.tsg`. - Builtins sources and configuration are defined in `src/builtins.js` and `builtins.cfg` respectively. - Tests are put into the `test` directory. -Make sure all development dependencies are installed by running: +### Building and Running Tests - npm install +Build the project by running: -Run all tests in the project by executing the following: +``` sh +$ cargo build +``` - npm test +Run the tests as follows: -Parse and test a single file by executing the following commands: +``` sh +$ cargo test +``` - npm run parse-file test/test.js - npm run test-file test/test.js +The project consists of a library and a CLI. By default, running `cargo` only applies to the library. To run `cargo` commands on the CLI as well, add `--features cli` or `--all-features`. -Additional flags can be passed to these commands as well. For example, to generate a visualization for the test, execute: +Run the CLI from source as follows: - npm run test-file -- -V test/test.js +``` sh +$ cargo run --features cli -- ARGS +``` -To generate the visualization regardless of test outcome, execute: +Sources are formatted using the standard Rust formatted, which is applied by running: + +``` sh +$ cargo fmt +``` - npm run test-file -- -V --output-mode=always test/test.js +### Writing TSG -These commands should be enough for regular development. If necessary, the `tree-sitter-stack-graphs` command can be invoked directly as well, by executing: +The stack graph rules are written in [tree-sitter-graph][]. Checkout the [examples][], +which contain self-contained TSG rules for specific language features. A VSCode +[extension][] is available that provides syntax highlighting for TSG files. + +[tree-sitter-graph]: https://github.com/tree-sitter/tree-sitter-graph +[examples]: https://github.com/github/stack-graphs/blob/main/tree-sitter-stack-graphs/examples/ +[extension]: https://marketplace.visualstudio.com/items?itemName=tree-sitter.tree-sitter-graph + +Parse and test a single file by executing the following commands: + +``` sh +$ cargo run --features cli -- parse FILES... +$ cargo run --features cli -- test TESTFILES... +``` + +Generate a visualization to debug failing tests by passing the `-V` flag: + +``` sh +$ cargo run --features cli -- test -V TESTFILES... +``` + +To generate the visualization regardless of test outcome, execute: - npx tree-sitter-stack-graphs +``` sh +$ cargo run --features cli -- test -V --output-mode=always TESTFILES... +``` Go to https://crates.io/crates/tree-sitter-stack-graphs for links to examples and documentation. diff --git a/languages/tree-sitter-stack-graphs-javascript/bindings/rust/lib.rs b/languages/tree-sitter-stack-graphs-javascript/bindings/rust/lib.rs deleted file mode 100644 index 84d0bbe7e..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/bindings/rust/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -/// The stack graphs query for this language -pub const STACK_GRAPHS_QUERY: &str = include_str!("../../src/stack-graphs.tsg"); - -/// The stack graphs builtins configuration for this language -pub const STACK_GRAPHS_BUILTINS_CONFIG: &str = include_str!("../../src/builtins.cfg"); -/// The stack graphs builtins source for this language -pub const STACK_GRAPHS_BUILTINS_SOURCE: &str = include_str!("../../src/builtins.js"); diff --git a/languages/tree-sitter-stack-graphs-javascript/package.json b/languages/tree-sitter-stack-graphs-javascript/package.json deleted file mode 100644 index 861ceeb58..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "tree-sitter-stack-graphs-javascript", - "version": "0.1.0", - "description": "Stack graphs definition for JavaScript using tree-sitter-javascript", - "author": "Beka Valentine ", - "keywords": [ - "tree-sitter", - "stack-graphs", - "javascript" - ], - "devDependencies": { - "tree-sitter-stack-graphs": "~0.6.0", - "tree-sitter-javascript": "github:tree-sitter/tree-sitter-javascript#fdeb68ac8d2bd5a78b943528bb68ceda3aade2eb" - }, - "scripts": { - "test": "npx tree-sitter-stack-graphs test --grammar node_modules/tree-sitter-javascript --tsg src/stack-graphs --builtins src/builtins test", - "parse-file": "npx tree-sitter-stack-graphs parse --grammar node_modules/tree-sitter-javascript", - "test-file": "npx tree-sitter-stack-graphs test --grammar node_modules/tree-sitter-javascript --tsg src/stack-graphs --builtins src/builtins" - } -} \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/bin.rs b/languages/tree-sitter-stack-graphs-javascript/rust/bin.rs new file mode 100644 index 000000000..5d5e998ad --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/rust/bin.rs @@ -0,0 +1,33 @@ +// -*- coding: utf-8 -*- +// ------------------------------------------------------------------------------------------------ +// Copyright © 2023, stack-graphs authors. +// Licensed under either of Apache License, Version 2.0, or MIT license, at your option. +// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. +// ------------------------------------------------------------------------------------------------ + +use anyhow::anyhow; +use clap::Parser; +use tree_sitter_stack_graphs::cli::database::default_user_database_path_for_crate; +use tree_sitter_stack_graphs::cli::provided_languages::Subcommands; +use tree_sitter_stack_graphs::NoCancellation; + +fn main() -> anyhow::Result<()> { + let lc = match tree_sitter_stack_graphs_javascript::try_language_configuration(&NoCancellation) + { + Ok(lc) => lc, + Err(err) => { + eprintln!("{}", err.display_pretty()); + return Err(anyhow!("Language configuration error")); + } + }; + let cli = Cli::parse(); + let default_db_path = default_user_database_path_for_crate(env!("CARGO_PKG_NAME"))?; + cli.subcommand.run(default_db_path, vec![lc]) +} + +#[derive(Parser)] +#[clap(about, version)] +pub struct Cli { + #[clap(subcommand)] + subcommand: Subcommands, +} diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/lib.rs b/languages/tree-sitter-stack-graphs-javascript/rust/lib.rs new file mode 100644 index 000000000..d9b6a0886 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/rust/lib.rs @@ -0,0 +1,50 @@ +// -*- coding: utf-8 -*- +// ------------------------------------------------------------------------------------------------ +// Copyright © 2023, stack-graphs authors. +// Licensed under either of Apache License, Version 2.0, or MIT license, at your option. +// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. +// ------------------------------------------------------------------------------------------------ + +use tree_sitter_stack_graphs::loader::FileAnalyzers; +use tree_sitter_stack_graphs::loader::LanguageConfiguration; +use tree_sitter_stack_graphs::loader::LoadError; +use tree_sitter_stack_graphs::CancellationFlag; + +/// The stack graphs tsg source for this language. +pub const STACK_GRAPHS_TSG_PATH: &str = "src/stack-graphs.tsg"; +/// The stack graphs tsg source for this language. +pub const STACK_GRAPHS_TSG_SOURCE: &str = include_str!("../src/stack-graphs.tsg"); + +/// The stack graphs builtins configuration for this language. +pub const STACK_GRAPHS_BUILTINS_CONFIG: &str = include_str!("../src/builtins.cfg"); +/// The stack graphs builtins path for this language +pub const STACK_GRAPHS_BUILTINS_PATH: &str = "src/builtins.js"; +/// The stack graphs builtins source for this language. +pub const STACK_GRAPHS_BUILTINS_SOURCE: &str = include_str!("../src/builtins.js"); + +/// The name of the file path global variable. +pub const FILE_PATH_VAR: &str = "FILE_PATH"; + +pub fn language_configuration(cancellation_flag: &dyn CancellationFlag) -> LanguageConfiguration { + try_language_configuration(cancellation_flag).unwrap_or_else(|err| panic!("{}", err)) +} + +pub fn try_language_configuration( + cancellation_flag: &dyn CancellationFlag, +) -> Result { + LanguageConfiguration::from_sources( + tree_sitter_javascript::language(), + Some(String::from("source.js")), + None, + vec![String::from("js")], + STACK_GRAPHS_TSG_PATH.into(), + STACK_GRAPHS_TSG_SOURCE, + Some(( + STACK_GRAPHS_BUILTINS_PATH.into(), + STACK_GRAPHS_BUILTINS_SOURCE, + )), + Some(STACK_GRAPHS_BUILTINS_CONFIG), + FileAnalyzers::new(), + cancellation_flag, + ) +} diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/test.rs b/languages/tree-sitter-stack-graphs-javascript/rust/test.rs new file mode 100644 index 000000000..ea396ec07 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/rust/test.rs @@ -0,0 +1,24 @@ +// -*- coding: utf-8 -*- +// ------------------------------------------------------------------------------------------------ +// Copyright © 2023, stack-graphs authors. +// Licensed under either of Apache License, Version 2.0, or MIT license, at your option. +// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. +// ------------------------------------------------------------------------------------------------ + +use anyhow::anyhow; +use std::path::PathBuf; +use tree_sitter_stack_graphs::ci::Tester; +use tree_sitter_stack_graphs::NoCancellation; + +fn main() -> anyhow::Result<()> { + let lc = match tree_sitter_stack_graphs_javascript::try_language_configuration(&NoCancellation) + { + Ok(lc) => lc, + Err(err) => { + eprintln!("{}", err.display_pretty()); + return Err(anyhow!("Language configuration error")); + } + }; + let test_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test"); + Tester::new(vec![lc], vec![test_path]).run() +} From b58fdfda09f39856b084e3745d12e50ab1f2020f Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 10 May 2023 14:00:09 +0200 Subject: [PATCH 012/500] Depend on latest grammar commit --- languages/tree-sitter-stack-graphs-javascript/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml index 1cc716577..bd8f94244 100644 --- a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -30,7 +30,7 @@ anyhow = { version = "1.0", optional = true } clap = { version = "3", optional = true } stack-graphs = { version = "0.10", path = "../../stack-graphs" } tree-sitter-stack-graphs = { version = "0.6", path = "../../tree-sitter-stack-graphs" } -tree-sitter-javascript = "0.20" +tree-sitter-javascript = { git = "https://github.com/tree-sitter/tree-sitter-javascript", rev = "5720b249490b3c17245ba772f6be4a43edb4e3b7" } [dev-dependencies] anyhow = "1.0" From 6cba08286aa5279f662f97b7d93436fd1c86b714 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Wed, 10 May 2023 16:54:24 -0700 Subject: [PATCH 013/500] Adds array and object support --- .../src/stack-graphs.tsg | 343 +++++++++++------- .../test/compound_expressions/array.js | 29 ++ .../compound_expressions/member_expression.js | 18 + .../member_object_flow.js | 7 + .../test/compound_expressions/object.js | 23 ++ .../object_computed_proprety_name_flow.js | 8 + ...ject_shorthand_property_identifier_flow.js | 8 + .../subscript_array_flow.js | 6 + .../subscript_expression.js | 24 ++ .../subscript_object_flow.js | 8 + 10 files changed, 345 insertions(+), 129 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/array.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/member_expression.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/member_object_flow.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object_computed_proprety_name_flow.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object_shorthand_property_identifier_flow.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/subscript_array_flow.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/subscript_expression.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/subscript_object_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 691592cf3..c9e80ad48 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -2186,97 +2186,168 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @object.before_scope node @object.after_scope node @object.value + node @object.member_pop + + attr (@object.member_pop) pop_symbol = "GUARD:MEMBER" + edge @object.value -> @object.member_pop } ; empty objects ; LATER-TODO currently unsupported by tree sitter queries ; THIS IS A HUGE HACK AND MUST BE FIXED -;; (object)@object_expr { -;; edge @object_expr.after_scope -> @object_expr.before_scope -;; } +(object)@object_expr { + + edge @object_expr.after_scope -> @object_expr.before_scope + +} ; non-empty objects, scopes, first entry -;; (object -;; . -;; (_)@first_entry)@object_expr { -;; ; scopes propagate from the object to the first entry -;; edge @first_entry.before_scope -> @object_expr.before_scope -;; } +(object + . + (_)@first_entry)@object_expr +{ + + ; scopes propagate from the object to the first entry + edge @first_entry.before_scope -> @object_expr.before_scope + +} ; non-empty objects, scopes, between entries -;; (object -;; (_)@left_entry -;; . -;; (_)@right_entry -;; )@object_expr { -;; ; scopes propagate from left entries to right entries -;; edge @right_entry.before_scope -> @left_entry.after_scope -;; } +(object + (_)@left_entry + . + (_)@right_entry) +{ + + ; scopes propagate from left entries to right entries + edge @right_entry.before_scope -> @left_entry.after_scope + +} ; non-empty objects, scopes, last entry -;; (object -;; (_)@last_entry -;; .)@object_expr { -;; ; scopes propagate from the last entry back to the object -;; edge @object_expr.after_scope -> @last_entry.after_scope -;; } +(object + (_)@last_entry + .)@object_expr +{ + + ; scopes propagate from the last entry back to the object + edge @object_expr.after_scope -> @last_entry.after_scope + +} ; shorthand property identifier -;; (object -;; (shorthand_property_identifier)@keyval)@object { +(shorthand_property_identifier)@keyval { -;; ; scopes flow into rhsvar, and also straight across b/c they can't be modified -;; edge @keyval.rhsvar_before_scope -> @keyval.before_scope -;; edge @keyval.after_scope -> @keyval.before_scope + node @keyval.before_scope + node @keyval.after_scope -;; ; shorthand property identifiers have secret variable exprs -;; attr @keyval.rhsvar_value "push" = @keyval, "reference" -;; edge @keyval.rhsvar_value -> @keyval.rhsvar_before_scope +} -;; ; shorthand property identifiers augment the object value with a member binding -;; attr @keyval.boundvar_pop "pop" = @keyval, "definition" +(object (shorthand_property_identifier)@keyval)@object { -;; attr @object.field_pop_dot "pop" = "." -;; edge @keyval.boundvar_pop -> @keyval.rhsvar_value -;; edge @object.field_pop_dot -> @keyval.boundvar_pop -;; edge @object.value -> @object.field_pop_dot + node rhsvar_before_scope + node rhsvar_after_scope + node rhsvar_value + node key_pop -;; } + attr (rhsvar_value) node_reference = @keyval + attr (key_pop) node_definition = @keyval + + + ; scopes flow into rhsvar, and also straight across b/c they can't be modified + edge rhsvar_before_scope -> @keyval.before_scope + edge rhsvar_after_scope -> rhsvar_before_scope + edge @keyval.after_scope -> rhsvar_after_scope + + edge rhsvar_value -> rhsvar_before_scope + + ; shorthand property identifiers augment the object value with a member binding + edge key_pop -> rhsvar_value + edge @object.member_pop -> key_pop + +} ; pairs -;; (object -;; (pair -;; key:(_)@key -;; value: (_)@value)@pair)@object { -;; ; scopes flow into values then back to the pair -;; edge @value.before_scope -> @pair.before_scope -;; edge @pair.after_scope -> @value.after_scope +(computed_property_name (_)@expr)@computed_property_name { -;; ; pairs augment the object value with a member binding + node @computed_property_name.before_scope + node @computed_property_name.after_scope -;; ; This is done differently depending on what the key is. See next rules. -;; ; attr @key.pop "pop" = @key, "definition" -;; attr @key.pop "definition" + edge @expr.before_scope -> @computed_property_name.before_scope + edge @computed_property_name.after_scope -> @expr.after_scope -;; attr @object.field_pop_dot "pop" = "." -;; edge @key.pop -> @value.value -;; edge @object.field_pop_dot -> @key.pop -;; edge @object.value -> @object.field_pop_dot -;; } +} -;; (pair key:(property_identifier)@key) { -;; attr @key.pop "pop" = @key -;; } +(pair + key:(_)@key + value: (_)@value)@pair +{ + + node @pair.before_scope + node @pair.after_scope + +} + +(object + (pair + key:(_)@key + value:(_)@value)@pair)@object +{ + + ; pairs augment the object value with a member binding + node @pair.key_pop + + ; This is done differently depending on what the key is. See next rules. + ; attr @key.pop "pop" = @key, "definition" + + edge @pair.key_pop -> @value.value + edge @object.member_pop -> @pair.key_pop + +} + +(pair + key:(property_identifier)@key + value:(_)@value)@pair +{ + + attr (@pair.key_pop) node_definition = @key + + ; scopes flow into the value, then back to the pair + edge @value.before_scope -> @pair.before_scope + edge @pair.after_scope -> @value.after_scope + +} ;; (pair key:(string)@key) { ;; attr @key.pop "pop" = (replace @key "\"" "") ;; } -;; (pair key:(number)@key) { -;; attr @key.pop "pop" = @key -;; } +(pair + key:(number)@key + value:(_)@value)@pair +{ + + attr (@pair.key_pop) node_definition = @key + + ; scopes flow into the value, then back to the pair + edge @value.before_scope -> @pair.before_scope + edge @pair.after_scope -> @value.after_scope + +} + +(pair + key:(computed_property_name)@key + value:(_)@value)@pair +{ + + ; scopes flow into the key, then out to the value, then back to the pair + edge @key.before_scope -> @pair.before_scope + edge @value.before_scope -> @key.after_scope + edge @pair.after_scope -> @value.after_scope + +} @@ -2287,49 +2358,65 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @array_expr.before_scope node @array_expr.after_scope node @array_expr.value + node @array_expr.element_pop_dot + + attr (@array_expr.element_pop_dot) pop_symbol = "GUARD:MEMBER" + edge @array_expr.value -> @array_expr.element_pop_dot } ; empty arrays ; LATER-TODO currently unsupported by tree sitter queries ; THIS IS A HUGE HACK AND MUST BE FIXED -;; (array)@array_expr { -;; edge @array_expr.after_scope -> @array_expr.before_scope -;; } +(array)@array_expr { + + edge @array_expr.after_scope -> @array_expr.before_scope + +} ; nonempty arrays, first element -;; (array -;; . -;; (_)@first_element)@array_expr { -;; ; scopes propagate into the first element of the array -;; edge @first_element.before_scope -> @array_expr.before_scope -;; } +(array + . + (_)@first_element)@array_expr { + + ; scopes propagate into the first element of the array + edge @first_element.before_scope -> @array_expr.before_scope + +} ; nonempty arrays, between elements -;; (array -;; (_)@left_element -;; . -;; (_)@right_element) { -;; ; scopes propagate from left elements to right elements -;; edge @right_element.before_scope -> @left_element.after_scope -;; } +(array + (_)@left_element + . + (_)@right_element) +{ + + ; scopes propagate from left elements to right elements + edge @right_element.before_scope -> @left_element.after_scope + +} ; nonempty arrays, last element -;; (array -;; (_)@last_element -;; .)@array_expr { -;; ; scopes propagate out of the last element to the array -;; edge @array_expr.after_scope -> @last_element.after_scope -;; } +(array + (_)@last_element + .)@array_expr +{ + + ; scopes propagate out of the last element to the array + edge @array_expr.after_scope -> @last_element.after_scope + +} ; elements at indices -;; (array (_)@element)@array_expr { -;; attr @array_expr.element_pop_dot "pop" = "." -;; attr @element.index_pop "pop" = (child-index @element), "definition" -;; edge @array_expr.element_pop_dot -> @element.index_pop -;; edge @array_expr.value -> @array_expr.element_pop_dot -;; edge @element.index_pop -> @element.value -;; } +(array (_)@element)@array_expr { + + node element_index_pop + + attr (element_index_pop) symbol_definition = (named-child-index @element) + edge @array_expr.element_pop_dot -> element_index_pop + edge element_index_pop -> @element.value + +} @@ -2732,19 +2819,20 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @member_expr.before_scope node @member_expr.after_scope node @member_expr.value + node member_push + node property_push + + ; scopes flow into object then back out + edge @object.before_scope -> @member_expr.before_scope + edge @member_expr.after_scope -> @object.after_scope -;; ; scopes flow into object then back out -;; edge @object.before_scope -> @member_expr.before_scope -;; edge @member_expr.after_scope -> @object.after_scope + ; value is a member projection on the value of the object ie. a push then push dot + attr (member_push) push_symbol = "GUARD:MEMBER" + attr (property_push) node_reference = @property + edge property_push -> member_push + edge @member_expr.value -> property_push + edge member_push -> @object.value -;; ; value is a member projection on the value of the object ie. a push then push dot -;; attr @property.push "push", "reference" -;; ;attr @member_expr.value "push" = @property.pop -;; attr @member_expr.push_dot "push" = "." -;; edge @property.push -> @member_expr.push_dot -;; ;edge @member_expr.value -> @member_expr.push_dot -;; edge @member_expr.value -> @property.push -;; edge @member_expr.push_dot -> @object.value } ;; ##### Subscript Expressions @@ -2757,44 +2845,41 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @subscript_expr.before_scope node @subscript_expr.after_scope node @subscript_expr.value + node @subscript_expr.push_dot + node @subscript_expr.index_push -;; ; scopes flow left to right -;; edge @object.before_scope -> @subscript_expression.before_scope -;; edge @index.before_scope -> @object.after_scope -;; edge @subscript_expression.after_scope -> @index.after_scope + ; scopes flow left to right + edge @object.before_scope -> @subscript_expr.before_scope + edge @index.before_scope -> @object.after_scope + edge @subscript_expr.after_scope -> @index.after_scope -;; ; value is a subscript lookup, ie a push then push dot + ; value is a subscript lookup, ie a push then push dot + attr (@subscript_expr.push_dot) push_symbol = "GUARD:MEMBER" + edge @subscript_expr.push_dot -> @object.value -;; ; this is done differently depending on what the index is -;; ; attr @index.push "push" = @index, "reference" + ; this is done differently depending on what the index is + ; attr @index.push "push" = @index, "reference" + edge @subscript_expr.value -> @subscript_expr.index_push + edge @subscript_expr.index_push -> @subscript_expr.push_dot } -;; (subscript_expression -;; object: (_)@object -;; index: (string)@index)@subscript_expression { - -;; attr @index.push "reference" - -;; attr @index.push_dot "push" = "." -;; edge @subscript_expression.value -> @index.push -;; edge @index.push -> @index.push_dot -;; edge @index.push_dot -> @object.value -;; attr @index.push "push" = (replace @index "\"" "") -;; } +(subscript_expression + object: (_)@object + index: (string)@index)@subscript_expr +{ -;; (subscript_expression -;; object: (_)@object -;; index: (number)@index)@subscript_expression { + attr (@subscript_expr.index_push) push_symbol = (replace (source-text @index) "[\"\']" "") +} -;; attr @index.push "reference" +(subscript_expression + object: (_)@object + index: (number)@index)@subscript_expr +{ -;; attr @index.push_dot "push" = "." -;; edge @subscript_expression.value -> @index.push -;; edge @index.push -> @index.push_dot -;; edge @index.push_dot -> @object.value -;; attr @index.push "push" = @index -;; } + attr (@subscript_expr.index_push) node_reference = @index + +} diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/array.js b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/array.js new file mode 100644 index 000000000..0ebe4d990 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/array.js @@ -0,0 +1,29 @@ +let x = 1; + +// Flow in + +[0, x]; +// ^ defined: 1 + +// Flow out + +[y = 1, + 0, y]; +// ^ defind: 10 + +/**/ y; +// ^ defined: 10 + +// Flow around + +/**/ x; +// ^ defineed: 1 + +let arr = [0, x]; +let x2 = arg[0]; + +/**/ x2; +// ^ defined: 23 +// let one = arr[1].x; +// // defined: 1 +// // defined: 2 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/member_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/member_expression.js new file mode 100644 index 000000000..b397d747a --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/member_expression.js @@ -0,0 +1,18 @@ +let x = 1; + +// Flow in + +/**/ x.foo; +// ^ defined: 1 + +// Flow out + +(y = 1).foo; + +/**/ y; +// ^ defined: 10 + +// Flow around + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/member_object_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/member_object_flow.js new file mode 100644 index 000000000..b8ec9ce73 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/member_object_flow.js @@ -0,0 +1,7 @@ +let x = 0; +let obj = { + foo: x +}; + +obj.foo; +// ^ defined: 1, 3 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object.js b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object.js new file mode 100644 index 000000000..feb199395 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object.js @@ -0,0 +1,23 @@ +let x = 1; + +// Flow in + +{ + /**/[x]: x + // ^ defined: 1 + // ^ defined: 1 +}; + +// Flow out + +{ + [y = 0]: + /**/ (y, z = 0) + // ^ defined: 14 +}; + +/**/ y; +// ^ defined: 14 + +/**/ z; +// ^ defined: 15 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object_computed_proprety_name_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object_computed_proprety_name_flow.js new file mode 100644 index 000000000..c9ee50c43 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object_computed_proprety_name_flow.js @@ -0,0 +1,8 @@ +let x = 0; +let obj = { + ["foo"]: x +}; +let y = obj["foo"]; + +/**/ y; +// TODO defined: 1, 3, 5 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object_shorthand_property_identifier_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object_shorthand_property_identifier_flow.js new file mode 100644 index 000000000..77c85e823 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object_shorthand_property_identifier_flow.js @@ -0,0 +1,8 @@ +let x = 1; + +let obj = { + x +}; + +obj.x; +// ^ defined: 1, 4 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/subscript_array_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/subscript_array_flow.js new file mode 100644 index 000000000..21071da2f --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/subscript_array_flow.js @@ -0,0 +1,6 @@ +let x = 0; +let arr = [0, x]; +let x2 = arr[1]; + +/**/ x2; +// ^ defined: 1, 3 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/subscript_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/subscript_expression.js new file mode 100644 index 000000000..e63083d83 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/subscript_expression.js @@ -0,0 +1,24 @@ +let x = 1; + +// Flow in + +/**/ x[x]; +// ^ defined: 1 +// ^ defined: 1 + +// Flow out + +(y = 1)[ + z = 1 +]; + +/**/ y; +// ^ defined: 11 + +/**/ z; +// ^ defined: 12 + +// Flow around + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/subscript_object_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/subscript_object_flow.js new file mode 100644 index 000000000..c3d5fc209 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/subscript_object_flow.js @@ -0,0 +1,8 @@ +let x = 0; +let obj = { + foo: x +}; +let y = obj["foo"]; + +/**/ y; +// ^ defined: 1, 3, 5 \ No newline at end of file From d71b3c529a179f1543c05e488b2f451e466a76ed Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 11 May 2023 20:05:35 +0200 Subject: [PATCH 014/500] Rename unused captures --- .../src/stack-graphs.tsg | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 691592cf3..566a31e75 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -963,7 +963,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (variable_declaration (variable_declarator - name:(identifier)@name + name:(identifier)@_name value:(_)@initializer))@variable_decl { @@ -975,7 +975,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (lexical_declaration (variable_declarator - name:(identifier)@name + name:(identifier)@_name value:(_)@initializer))@lexical_decl { @@ -1015,9 +1015,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ##### Function Declarations (function_declaration - name:(_)@name - parameters:(_)@call_sig - body:(_)@body)@fun_decl + name:(_)@_name + parameters:(_)@_call_sig + body:(_)@_body)@fun_decl { node @fun_decl.before_scope @@ -1090,9 +1090,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ##### Generator Function Declarations (generator_function_declaration - name:(_)@name - parameters:(_)@call_sig - body:(_)@body)@gen_fun_decl + name:(_)@_name + parameters:(_)@_call_sig + body:(_)@_body)@gen_fun_decl { node @gen_fun_decl.before_scope @@ -1165,8 +1165,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Classes (class_declaration - name:(_)@name - body:(_)@body)@class_decl + name:(_)@_name + body:(_)@_body)@class_decl { node @class_decl.before_scope @@ -1603,7 +1603,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### For In (for_in_statement - left:(_)@left + left:(_)@_left right:(_)@right body:(_)@body)@for_in_stmt { @@ -1702,7 +1702,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (try_statement body:(_)@body - finalizer:(_)@finalizer)@try_stmt + finalizer:(_)@finalizer)@_try_stmt { ; scopes flow from body to finalizer then back out @@ -1712,7 +1712,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (try_statement handler:(_)@handler - finalizer:(_)@finalizer)@try_stmt + finalizer:(_)@finalizer)@_try_stmt { ; scopes flow from handler to finalizer then back out @@ -1863,7 +1863,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Throw -(throw_statement (_)@thrown_expr)@throw_stmt { +(throw_statement (_)@_thrown_expr)@throw_stmt { node @throw_stmt.before_scope node @throw_stmt.after_scope @@ -2010,7 +2010,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (template_string (template_substitution (_)@left_inner_expr) . - (template_substitution (_)@right_inner_expr))@template_string { + (template_substitution (_)@right_inner_expr))@_template_string { ; scopes propagate from left substitutions to right substitutions edge @right_inner_expr.before_scope -> @left_inner_expr.after_scope } @@ -2390,8 +2390,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; function (function - parameters:(_)@call_sig - body:(_)@body)@fun + parameters:(_)@_call_sig + body:(_)@_body)@fun { node @fun.before_scope @@ -2460,12 +2460,12 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; function [ (arrow_function - parameters:(_)@call_sig - body:(_)@body)@fun + parameters:(_)@_call_sig + body:(_)@_body)@fun (arrow_function - parameter:(_)@call_sig - body:(_)@body)@fun + parameter:(_)@_call_sig + body:(_)@_body)@fun ] { node @fun.before_scope @@ -2560,8 +2560,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; generator function (generator_function - parameters:(_)@call_sig - body:(_)@body)@gen_fun + parameters:(_)@_call_sig + body:(_)@_body)@gen_fun { node @gen_fun.before_scope @@ -2617,8 +2617,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; calls, functions (call_expression - function:(_)@function - arguments:(_)@arguments)@call_expr + function:(_)@_function + arguments:(_)@_arguments)@call_expr { node @call_expr.before_scope @@ -2725,8 +2725,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ##### Member Expressions (member_expression - object: (_)@object - property: (_)@property)@member_expr + object: (_)@_object + property: (_)@_property)@member_expr { node @member_expr.before_scope @@ -2750,8 +2750,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ##### Subscript Expressions (subscript_expression - object: (_)@object - index: (_)@index)@subscript_expr + object: (_)@_object + index: (_)@_index)@subscript_expr { node @subscript_expr.before_scope @@ -2801,8 +2801,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Constructor Calls (new_expression - constructor:(_)@constructor - arguments:(_)@arguments)@new_expr + constructor:(_)@_constructor + arguments:(_)@_arguments)@new_expr { node @new_expr.before_scope @@ -3011,7 +3011,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; TODO NOW (augmented_assignment_expression - left: (_)@left + left: (_)@_left right: (_)@right)@augmented_assignment_expr { @@ -3117,7 +3117,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Class Expressions ; TODO NOW -(class body:(_)@body)@class { +(class body:(_)@_body)@class { node @class.before_scope node @class.after_scope From 1aee0116ceed4c66faa6c330963b07403c8ac0c3 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 16 May 2023 19:03:58 +0200 Subject: [PATCH 015/500] Bump clap to v4 --- languages/tree-sitter-stack-graphs-javascript/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml index bd8f94244..ca28f83f8 100644 --- a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -27,7 +27,7 @@ cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"] [dependencies] anyhow = { version = "1.0", optional = true } -clap = { version = "3", optional = true } +clap = { version = "4", optional = true } stack-graphs = { version = "0.10", path = "../../stack-graphs" } tree-sitter-stack-graphs = { version = "0.6", path = "../../tree-sitter-stack-graphs" } tree-sitter-javascript = { git = "https://github.com/tree-sitter/tree-sitter-javascript", rev = "5720b249490b3c17245ba772f6be4a43edb4e3b7" } From d19181145ce0c8756dc8a3bf0ba674c2e0f56646 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 16 May 2023 19:14:20 +0200 Subject: [PATCH 016/500] Pin tree-sitter to v0.20.9 to prevent matching bug in v0.20.10 --- languages/tree-sitter-stack-graphs-javascript/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml index ca28f83f8..7adda795d 100644 --- a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -29,6 +29,7 @@ cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"] anyhow = { version = "1.0", optional = true } clap = { version = "4", optional = true } stack-graphs = { version = "0.10", path = "../../stack-graphs" } +tree-sitter = "=0.20.9" tree-sitter-stack-graphs = { version = "0.6", path = "../../tree-sitter-stack-graphs" } tree-sitter-javascript = { git = "https://github.com/tree-sitter/tree-sitter-javascript", rev = "5720b249490b3c17245ba772f6be4a43edb4e3b7" } From d858b8cab985cb13414116464656238f8b43a86f Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 16 May 2023 19:14:55 +0200 Subject: [PATCH 017/500] Skip old tests --- .../binding/default_arguments_from_enclosing_scope.js | 0 .../binding/default_arguments_from_other_arguments.js | 0 .../test/{old => old.skip}/binding/destructuring_assignments.js | 0 ...tructuring_assignments_with_defaults_from_enclosing_scope.js | 0 ...tructuring_assignments_with_defaults_from_other_variables.js | 0 .../test/{old => old.skip}/binding/destructuring_parameters.js | 0 .../{old => old.skip}/binding/object_assignment_patterns.js | 0 .../test/{old => old.skip}/binding/simple.js | 0 .../test/{old => old.skip}/bug_regressions/2141.js | 0 .../test/{old => old.skip}/bug_regressions/2227.js | 0 .../test/{old => old.skip}/bug_regressions/2291.js | 0 .../classes_and_instances/class_declaration.js | 2 +- .../{old => old.skip}/classes_and_instances/class_expression.js | 0 .../classes_and_instances/class_expression_superclasses.js | 0 .../classes_and_instances/class_expression_this_field_access.js | 0 .../classes_and_instances/field_declaration.js | 0 .../classes_and_instances/function_class_this_field_access.js | 0 .../classes_and_instances/method_call_this_argument.js | 0 .../classes_and_instances/method_definition.js | 0 .../{old => old.skip}/classes_and_instances/superclasses.js | 0 .../classes_and_instances/this_field_access.js | 0 .../test/{old => old.skip}/compound_literals/arrays.js | 0 .../{old => old.skip}/compound_literals/object_extend_method.js | 0 .../test/{old => old.skip}/compound_literals/objects.js | 0 .../test/{old => old.skip}/control_flow_statements/dowhile.js | 0 .../test/{old => old.skip}/control_flow_statements/for.js | 0 .../test/{old => old.skip}/control_flow_statements/forin.js | 0 .../test/{old => old.skip}/control_flow_statements/if.js | 0 .../test/{old => old.skip}/control_flow_statements/try.js | 0 .../test/{old => old.skip}/control_flow_statements/while.js | 0 .../test/{old => old.skip}/control_flow_statements/with.js | 0 .../{old => old.skip}/functions_and_calls/arguments_variable.js | 0 .../arrow_function_values_with_param_lists_and_block_bodies.js | 0 .../arrow_function_values_with_param_lists_and_expr_bodies.js | 0 .../arrow_function_values_with_single_param_and_block_bodies.js | 0 .../arrow_function_values_with_single_param_and_expr_bodies.js | 0 .../{old => old.skip}/functions_and_calls/call_arguments.js | 0 .../functions_and_calls/function_declarations.js | 0 .../{old => old.skip}/functions_and_calls/function_values.js | 0 .../functions_and_calls/generator_function_declarations.js | 0 .../functions_and_calls/generator_function_values.js | 0 .../imports_and_exports/commonjs_imports_and_exports.js | 0 .../imports_and_exports/es6_imports_and_exports.js | 0 43 files changed, 1 insertion(+), 1 deletion(-) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/binding/default_arguments_from_enclosing_scope.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/binding/default_arguments_from_other_arguments.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/binding/destructuring_assignments.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/binding/destructuring_assignments_with_defaults_from_enclosing_scope.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/binding/destructuring_assignments_with_defaults_from_other_variables.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/binding/destructuring_parameters.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/binding/object_assignment_patterns.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/binding/simple.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/bug_regressions/2141.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/bug_regressions/2227.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/bug_regressions/2291.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/classes_and_instances/class_declaration.js (90%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/classes_and_instances/class_expression.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/classes_and_instances/class_expression_superclasses.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/classes_and_instances/class_expression_this_field_access.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/classes_and_instances/field_declaration.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/classes_and_instances/function_class_this_field_access.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/classes_and_instances/method_call_this_argument.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/classes_and_instances/method_definition.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/classes_and_instances/superclasses.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/classes_and_instances/this_field_access.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/compound_literals/arrays.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/compound_literals/object_extend_method.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/compound_literals/objects.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/control_flow_statements/dowhile.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/control_flow_statements/for.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/control_flow_statements/forin.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/control_flow_statements/if.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/control_flow_statements/try.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/control_flow_statements/while.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/control_flow_statements/with.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/functions_and_calls/arguments_variable.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/functions_and_calls/arrow_function_values_with_param_lists_and_block_bodies.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/functions_and_calls/arrow_function_values_with_param_lists_and_expr_bodies.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/functions_and_calls/arrow_function_values_with_single_param_and_block_bodies.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/functions_and_calls/arrow_function_values_with_single_param_and_expr_bodies.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/functions_and_calls/call_arguments.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/functions_and_calls/function_declarations.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/functions_and_calls/function_values.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/functions_and_calls/generator_function_declarations.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/functions_and_calls/generator_function_values.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/imports_and_exports/commonjs_imports_and_exports.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old => old.skip}/imports_and_exports/es6_imports_and_exports.js (100%) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/binding/default_arguments_from_enclosing_scope.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/default_arguments_from_enclosing_scope.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/binding/default_arguments_from_enclosing_scope.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/default_arguments_from_enclosing_scope.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/binding/default_arguments_from_other_arguments.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/default_arguments_from_other_arguments.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/binding/default_arguments_from_other_arguments.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/default_arguments_from_other_arguments.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/destructuring_assignments.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/destructuring_assignments.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments_with_defaults_from_enclosing_scope.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/destructuring_assignments_with_defaults_from_enclosing_scope.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments_with_defaults_from_enclosing_scope.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/destructuring_assignments_with_defaults_from_enclosing_scope.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments_with_defaults_from_other_variables.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/destructuring_assignments_with_defaults_from_other_variables.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments_with_defaults_from_other_variables.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/destructuring_assignments_with_defaults_from_other_variables.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_parameters.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/destructuring_parameters.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_parameters.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/destructuring_parameters.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/binding/object_assignment_patterns.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/object_assignment_patterns.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/binding/object_assignment_patterns.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/object_assignment_patterns.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/binding/simple.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/simple.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/binding/simple.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/simple.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/2141.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/bug_regressions/2141.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/2141.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/bug_regressions/2141.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/2227.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/bug_regressions/2227.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/2227.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/bug_regressions/2227.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/2291.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/bug_regressions/2291.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/2291.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/bug_regressions/2291.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_declaration.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/class_declaration.js similarity index 90% rename from languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_declaration.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/class_declaration.js index beb37cf1d..3504188bf 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_declaration.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/class_declaration.js @@ -1,5 +1,5 @@ class Foo { - + } Foo; diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/class_expression.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_expression.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/class_expression.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_expression_superclasses.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/class_expression_superclasses.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_expression_superclasses.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/class_expression_superclasses.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_expression_this_field_access.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/class_expression_this_field_access.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_expression_this_field_access.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/class_expression_this_field_access.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/field_declaration.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/field_declaration.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/field_declaration.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/field_declaration.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/function_class_this_field_access.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/function_class_this_field_access.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/function_class_this_field_access.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/function_class_this_field_access.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/method_call_this_argument.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/method_call_this_argument.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/method_call_this_argument.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/method_call_this_argument.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/method_definition.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/method_definition.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/method_definition.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/method_definition.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/superclasses.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/superclasses.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/superclasses.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/superclasses.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/this_field_access.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/this_field_access.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/this_field_access.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/this_field_access.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/arrays.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/compound_literals/arrays.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/arrays.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/compound_literals/arrays.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/object_extend_method.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/compound_literals/object_extend_method.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/object_extend_method.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/compound_literals/object_extend_method.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/objects.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/compound_literals/objects.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/objects.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/compound_literals/objects.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/dowhile.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/dowhile.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/dowhile.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/dowhile.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/for.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/for.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/for.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/for.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/forin.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/forin.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/forin.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/forin.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/if.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/if.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/if.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/if.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/try.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/try.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/try.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/try.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/while.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/while.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/while.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/while.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/with.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/with.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/with.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/with.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arguments_variable.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arguments_variable.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arguments_variable.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arguments_variable.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_param_lists_and_block_bodies.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arrow_function_values_with_param_lists_and_block_bodies.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_param_lists_and_block_bodies.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arrow_function_values_with_param_lists_and_block_bodies.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_param_lists_and_expr_bodies.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arrow_function_values_with_param_lists_and_expr_bodies.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_param_lists_and_expr_bodies.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arrow_function_values_with_param_lists_and_expr_bodies.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_single_param_and_block_bodies.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arrow_function_values_with_single_param_and_block_bodies.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_single_param_and_block_bodies.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arrow_function_values_with_single_param_and_block_bodies.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_single_param_and_expr_bodies.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arrow_function_values_with_single_param_and_expr_bodies.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_single_param_and_expr_bodies.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arrow_function_values_with_single_param_and_expr_bodies.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/call_arguments.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/call_arguments.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/call_arguments.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/call_arguments.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/function_declarations.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/function_declarations.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/function_declarations.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/function_declarations.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/function_values.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/function_values.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/function_values.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/function_values.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/generator_function_declarations.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/generator_function_declarations.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/generator_function_declarations.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/generator_function_declarations.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/generator_function_values.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/generator_function_values.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/generator_function_values.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/generator_function_values.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/commonjs_imports_and_exports.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/imports_and_exports/commonjs_imports_and_exports.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/commonjs_imports_and_exports.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/imports_and_exports/commonjs_imports_and_exports.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/es6_imports_and_exports.js b/languages/tree-sitter-stack-graphs-javascript/test/old.skip/imports_and_exports/es6_imports_and_exports.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/es6_imports_and_exports.js rename to languages/tree-sitter-stack-graphs-javascript/test/old.skip/imports_and_exports/es6_imports_and_exports.js From 828c72588bea928dbed0be127dfed1c7509ac4eb Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 16 May 2023 19:39:05 +0200 Subject: [PATCH 018/500] Fix captures and tests --- .../src/stack-graphs.tsg | 18 +++++++++--------- .../test/compound_expressions/array.js | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 9d35d14b8..0a20bddac 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -2281,8 +2281,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n } (pair - key:(_)@key - value: (_)@value)@pair + key:(_)@_key + value: (_)@_value)@pair { node @pair.before_scope @@ -2292,7 +2292,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (object (pair - key:(_)@key + key:(_)@_key value:(_)@value)@pair)@object { @@ -2812,8 +2812,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ##### Member Expressions (member_expression - object: (_)@_object - property: (_)@_property)@member_expr + object: (_)@object + property: (_)@property)@member_expr { node @member_expr.before_scope @@ -2838,8 +2838,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ##### Subscript Expressions (subscript_expression - object: (_)@_object - index: (_)@_index)@subscript_expr + object: (_)@object + index: (_)@index)@subscript_expr { node @subscript_expr.before_scope @@ -2865,7 +2865,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n } (subscript_expression - object: (_)@object + object: (_)@_object index: (string)@index)@subscript_expr { @@ -2873,7 +2873,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n } (subscript_expression - object: (_)@object + object: (_)@_object index: (number)@index)@subscript_expr { diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/array.js b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/array.js index 0ebe4d990..77e7269d4 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/array.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/array.js @@ -9,7 +9,7 @@ let x = 1; [y = 1, 0, y]; -// ^ defind: 10 +// ^ defined: 10 /**/ y; // ^ defined: 10 @@ -17,7 +17,7 @@ let x = 1; // Flow around /**/ x; -// ^ defineed: 1 +// ^ defined: 1 let arr = [0, x]; let x2 = arg[0]; From 1bfeffc630122880143b41af882d4bbc8d78f591 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 12:57:23 +0200 Subject: [PATCH 019/500] [conv] initial --- .../src/stack-graphs-conv.tsg | 3283 +++++++++++++++++ 1 file changed, 3283 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg new file mode 100644 index 000000000..f56040561 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -0,0 +1,3283 @@ +;; # JavaScript + +;; This file defines StackGraph queries for JavaScript. It is written as a +;; semi-literate file, which is to say, comments starting with `;;` can be +;; treated as Markdown. This file can therefore be converted into a +;; corresponding pure Markdown document by removing the StackGraph comments, and +;; wrapping the uncommented code in Markdown code blocks. + +;; This file has a number of sections that it's divided into, and it's useful to +;; provide an overview here. Aside from conventions, the queries are broken up +;; into groups by what kind of syntactic objects the group covers. There are +;; Programs, Statements, Expressions, Patterns, and Special Cases. + +;; Within each major section, we break things down by the particular syntactic +;; form under consideration. Some particular syntactic forms are not one of the +;; main forms listed, but are tightly associated with other forms -- for +;; example, the branches of an `if` statement are not statements nor +;; expressions, they're simply components of an `if` statement. In that +;; situation, we group them with the primary statement that they're associated +;; with, where possible, and nearby when not. + +;; Additionally, some syntactic constructs have arbitrary numbers of child +;; nodes, which requires us to explain how to relate them as sequences of +;; nodes. In such cases, we have associated queries with the node type in +;; question. + +;; ## Design Conventions + +;; The general convention for how JavaScript is translated into a Stack Graph is +;; to treat the graph as a reverse Control Flow Graph. There are some corner +;; cases for which that analogy doesn't quite work, but it's sufficient for +;; conveying the overall approach. Many things matter for name resolution in a +;; Control Flow Graph, but one of the only ones we can really encode into a +;; Stack Graph, and arguably the most important one, is the flow of the variable +;; environment, and so we create scope nodes for those. + +;; In particular, for each node, during an execution traversal, there is an +;; incoming variable environment that the node will be executed in, and an +;; outgoing variable environment that resulted from executing the node and all +;; the various variable assignments and updates inside it. + +;; An example helps, so let's consider a simplified case: `if` statement with a +;; mandatory `else` branch. If we were to implement an execution function for +;; this fictionalized language, there would be some environment that goes into +;; the execution at the whole `if-then-else` statement, an environment that goes +;; into the evaluation of the test, an environment that comes out of the test +;; (because the test could be something like `x++` which changes the +;; environment), an environment which goes into each branch (which happens to be +;; the same one that came out of the test), and an environment that comes out of +;; each of the branches. So each major AST node has a pair of environments +;; associated with it: the incoming one to execute it in, and the outcoming node +;; that resulted from executing. + +;; We therefore would implement `if-then-else` statements like so: + +;; ``````stgdoc +;; (if_then_else +;; (_)@test +;; (_)@consequent +;; (_)alternative)@if_stmt { +;; +;; edge @test.before_scope -> @if_stmt.before_scope +;; edge @consequent.before_scope -> @test.after_scope +;; edge @alternative.before_scope -> @test.after_scope +;; edge @if_stmt.after_scope -> @consequent.after_scope +;; edge @if_stmt.after_scope -> @alternative.after_scope +;; +;; } +;; `````` +;; +;; Another important way that things build scopes is through values. When an +;; expression is executed and returns a value, that value in many ways acts like +;; a sub-environment, at least in that the value has different parts that can be +;; accessed in various ways. For a simple value, as constructed by a number +;; literal expression, the number itself has no parts. So it has an associated +;; value scope node in the graph, but no edges coming off that: + +;; ``````stgdoc +;; (number)@num { +;; attr @num.value "pop" = "NUM_VAL" +;; } +;; `````` + +;; Why we use a `pop` attribute here isn't deeply important so we'll gloss over +;; it. + +;; All kinds of expressions have values, what precisely goes into them depends +;; on what the expression is. Objects, for instance, would have corresponding +;; values that point to the values of each of the keys in the object. Arrays +;; would have values that point to the values of each of the indexes. + +;; The primary purpose of values is to act as the targets of assignments, so +;; that names can resolve to something in code. Normally we care only about the +;; location of the assignment, of course, but we also need to be able to do +;; further lookup on the values. For instance, in an expression like `x.y.z`, +;; we need to look up `x` of course, but also then further look up `y` on that, +;; and then `z`. So whatever `x` is assigned to has to also be present in the +;; graph as something which can itself have stuff hanging off it that can be +;; used for lookup. + +;; If you were to run some JavaScript to test whether or not number literals +;; have parts (really, members/fields), you'd discover that actually they do, +;; but not because of which number they are. Rather, their parts are for builtin +;; functionality like `toString`. To handle this, we can point the value to some +;; shared global variable that represents the prototype for the number, like so: + +;; ``````stgdoc +;; (number)@num { +;; attr @num.value "pop" = "NUM_VAL" +;; edge @num.value -> @num::number_prototype +;; } +;; `````` + +;; In the preamble definition for the `program` node type, we could then also +;; want to define number prototype, something like this: + +;; ``````stgdoc +;; (program)@prog { +;; +;; ... +;; +;; let @prog::number_prototype = @prog.number_prototype +;; edge @prog.number_prototype -> @prog.number_prototype_toString_method_value +;; edge @prog.number_prototype -> @prog.number_prototype_valueOf_method_value +;; ...etc +;; +;; ... +;; +;; } +;; `````` + +;; We would then also want to have a bunch of hand-encoded graphs for the values +;; of those fields. That would then allow the number values to point to their +;; prototypes where the fields could be found and used for further lookup on +;; methods. + +;; One caveat of this is that we don't want to get too deep into explaining how +;; some method might be implemented. Indeed, sometimes we *can't*, because it's +;; not implementable in JavaScript at all and is instead some primitive function +;; implemented in the host language. What we want to do, instead, is to provide +;; just enough implementation that other data can flow through as much as +;; possible, to prevent calls to primitive methods from blocking downstream name +;; resolution. For instance, it would be unfortunate if calling `toString` on a +;; number did not let you look up string fields on the resultant value of the +;; call, i.e. if `length` in `(5).toString().length` just simply could not be +;; resolved at all. In such cases, the ideal approach is to implement a bare +;; minimum of `toString` so that we can recover the fact that its returned +;; value is a string. E.g.: + +;; ``````stgdoc +;; (program)@prog { +;; +;; ... +;; +;; edge @prog.number_prototype -> @prog.number_prototype_toString_method_value +;; edge @prog.number_prototype_toString_method_value -> @prog.number_prototype_toString_method_value_return +;; attr @prog.number_prototype_toString_method_value_return "pop" = "GUARD:RETURN" +;; edge @prog.number_prototype_toString_method_value_return -> @prog.string_prototype +;; +;; ... +;; +;; } +;; `````` + +;; As currently implemented, this document does not contain any rules for +;; builtins because of the scope of that task, but they are currently in the +;; pipeline, using the above approach. + +;; Something you may notice in the above code snippet is this pop node labelled +;; `GUARD:RETURN`. This is another part of the design conventions for this +;; library. We often want to use nodes in the graph to constrain name lookup. +;; In this case, we want to be able to pinpoint some of the graph nodes +;; associated with the body of a function as being the values returned by the +;; function. We do this by creating a so-called guard node, which will only be +;; traversed if there is a corresponding push somewhere else. We would generate +;; such a push node precisely when we call a function. This lets us treat the +;; function *ASTs* as if they have parts that we can inspect *in the graph*. + +;; By convention, this library of queries prefixes all guard nodes with "GUARD:" +;; to distinguish them from nodes that more directly correspond to aspects of +;; execution such as member lookup (labelled with ".") or variable lookup +;; (labelled with the variable name itself). The current names used for guard +;; nodes are + +;; - `GUARD:RETURN` - used for the AST nodes for values returned by a function +;; in the function body +;; - `GUARD:THIS` - used for the implicit `this` argument of a function inside +;; its body +;; - `GUARD:CONSTRUCTOR` - used for the constructor method inside a `Class` +;; - `GUARD:MODULE` - used for the final scope of the module +;; - `GUARD:EXPORTS` - used for the names exported by the module +;; - `GUARD:DEFAULT` - used for the default export value + + +;; ## Nodes + +(_)@node { + +} + + +;; ## Programs + +;; ### Attributes Defined on Programs +;; TODO + +;; ### Program Queries + +(program)@prog { + scan filepath { + "([^/]+)\.js$" { + attr @prog.module_pop "definition", "pop" = $1 + attr @prog.module_pop "no_span" + } + } + + edge @prog.before_scope -> root + + attr @prog.module_scope "pop" = "GUARD:MODULE" + edge root -> @prog.module_pop + edge @prog.module_pop -> @prog.module_scope + edge @prog.module_scope -> @prog.after_scope + + attr @prog "no_span" + attr @prog.module_pop "no_span" + attr @prog.module_scope "no_span" + attr @prog.exports "no_span" + attr @prog.exports_pop "no_span" + attr @prog.before_scope "no_span" + attr @prog.after_scope "no_span" + + let @prog::prog = @prog + let @prog::exports = @prog.exports + attr @prog.exports_pop "pop" = "GUARD:EXPORTS" + edge @prog.module_pop -> @prog.exports_pop + edge @prog.exports_pop -> @prog.exports +} + +; programs, first statement +(program + . + (_)@first_stmt)@prog { + + ; scopes flow from the program into the first statement + edge @first_stmt.before_scope -> @prog.before_scope +} + +; program, between statements +(program + (_)@left_stmt + . + (_)@right_stmt) { + + ; scopes flow from the left statement to the right one + edge @right_stmt.before_scope -> @left_stmt.after_scope +} + +; program, last statement +(program + (_)@last_stmt + .)@prog { + + ; scopes flow from the last statement to the program + edge @prog.after_scope -> @last_stmt.after_scope +} + +(hash_bang_line)@hashbang { + edge @hashbang.after_scope -> @hashbang.before_scope +} + +(comment)@comment { + edge @comment.after_scope -> @comment.before_scope +} + + + +;; ## Statements + +;; ### Attributes Defined on Statements +;; TODO + +;; ### Statement Queries + +;; #### Export + +; exports of just names +; eg +; export { foo, bar as baz }; +(export_statement + (export_clause)@export_clause + !source)@export_stmt { + + edge @export_clause.source -> @export_clause.before_scope + + ; scope flows through the export clause + edge @export_clause.before_scope -> @export_stmt.before_scope + edge @export_stmt.after_scope -> @export_clause.after_scope +} + +(export_statement + (export_clause)@export_clause + source:(_)@source)@export_stmt { + + edge @export_clause.source -> @source.push_exports_guard + + attr @source.push_exports_guard "push" = "GUARD:EXPORTS" + scan @source { + "\"([^/\"]+)\.js\"$" { + attr @source.push "push" = $1 + } + } + edge @source.push_exports_guard -> @source.push + edge @source.push -> root + + edge @export_clause.before_scope -> @export_stmt.before_scope + edge @export_stmt.after_scope -> @export_clause.after_scope + + +} + +(export_statement + (declaration)@decl)@export_stmt { + edge @decl.before_scope -> @export_stmt.before_scope + edge @export_stmt.after_scope -> @decl.after_scope +} + +(export_statement + declaration: [ + (function_declaration name:(identifier)@name) + (generator_function_declaration name:(identifier)@name) + (class_declaration name:(identifier)@name) + (lexical_declaration (variable_declarator name:(identifier)@name)) + (variable_declaration (variable_declarator name:(identifier)@name)) + ]@decl)@export_stmt { + + ; TODO this doesn't support destructuring exports + + attr @name.pop "pop" = @name, "definition" + attr @name.push "push" = @name + edge @export_stmt::exports -> @name.pop + edge @name.pop -> @decl.value +} + +; TODO +; export let [x,y] = [1,2]; +(export_statement + declaration: [ + (lexical_declaration + (variable_declarator + name: [ + (object_pattern) + (array_pattern) + ]@pattern)) + (variable_declaration + (variable_declarator + name: [ + (object_pattern) + (array_pattern) + ]@pattern)) + ])@export_stmt { + + edge @export_stmt::exports -> @pattern.new_bindings + +} + +; LATER-TODO tree sitter doesn't yet support empty switch bodies +; THIS IS A HUGE HACK AND MUST BE FIXED +(export_clause)@export_clause { + edge @export_clause.after_scope -> @export_clause.before_scope +} + +(export_clause + (_)@export)@export_clause { + + edge @export.source -> @export_clause.source +} + +(export_clause + . + (_)@first_export)@export_clause { + + edge @first_export.before_scope -> @export_clause.before_scope +} + +(export_clause + (_)@left_export + . + (_)@right_export) { + + edge @right_export.before_scope -> @left_export.after_scope +} + +(export_clause + (_)@last_export + .)@export_clause { + + edge @export_clause.after_scope -> @last_export.after_scope +} + +(export_specifier)@export_specifier { + edge @export_specifier.after_scope -> @export_specifier.before_scope +} + +( + (export_specifier + name:(_)@name + !alias)@export_specifier + + (#not-eq? @name "default") +) { + + attr @name.pop "pop" = @name, "definition" + attr @name.push "push" = @name, "reference" + edge @name.pop -> @name.push + edge @name.push -> @export_specifier.source + + edge @export_specifier::exports -> @name.pop +} + +( + (export_specifier + name:(_)@name + alias:(_)@alias)@export_specifier + + (#not-eq? @alias "default") + +) { + + attr @alias.pop "pop" = @alias, "definition" + attr @name.push "push" = @name, "reference" + edge @alias.pop -> @name.push + edge @name.push -> @export_specifier.source + + edge @export_specifier::exports -> @alias.pop +} + +( + (export_specifier + name:(_)@name + !alias)@export_specifier + + (#eq? @name "default") + +) { + + attr @export_specifier.pop_guard_default "pop" = "GUARD:DEFAULT" + attr @export_specifier.push_guard_default "push" = "GUARD:DEFAULT" + edge @export_specifier::exports -> @export_specifier.pop_guard_default + edge @export_specifier.pop_guard_default -> @export_specifier.push_guard_default + edge @export_specifier.push_guard_default -> @export_specifier.source + +} + +( + (export_specifier + name:(_)@name + alias:(_)@alias)@export_specifier + + (#eq? @alias "default") + +) { + + attr @name.push "push" = @name + attr @export_specifier.guard_default "pop" = "GUARD:DEFAULT" + edge @name.push -> @export_specifier.source + edge @export_specifier.guard_default -> @name.push + edge @export_specifier::exports -> @export_specifier.guard_default +} + +; simple default exports +; export default ...; + +(export_statement + value:(_)@default_expr)@export_stmt { + + attr @export_stmt.default_guard "pop" = "GUARD:DEFAULT", "definition" + edge @default_expr.before_scope -> @export_stmt.before_scope + edge @export_stmt.after_scope -> @default_expr.after_scope + edge @export_stmt::exports -> @export_stmt.default_guard + edge @export_stmt.default_guard -> @default_expr.value +} + +; aggregated exports +; export * from "foo.js"; +(export_statement + . + source:(_)@source)@export_statement { + + edge @export_statement.after_scope -> @export_statement.before_scope + + attr @source.push_exports_guard "push" = "GUARD:EXPORTS" + scan @source { + "\"([^/\"]+)\.js\"$" { + attr @source.push "push" = $1 + } + } + + edge @export_statement::exports -> @source.push_exports_guard + edge @source.push_exports_guard -> @source.push + edge @source.push -> root + +} + +; namespace exports +; export * as foo from "bar.js"; +(export_statement + (namespace_export (_)@alias) + source:(_)@source)@export_statement { + + edge @export_statement.after_scope -> @export_statement.before_scope + + attr @source.push_exports_guard "push" = "GUARD:EXPORTS" + scan @source { + "\"([^/\"]+)\.js\"$" { + attr @source.push "push" = $1 + } + } + attr @alias.pop "pop" = @alias, "definition" + attr @alias.pop_dot "pop" = "." + edge @export_statement::exports -> @alias.pop + edge @alias.pop -> @alias.pop_dot + edge @alias.pop_dot -> @source.push_exports_guard + edge @source.push_exports_guard -> @source.push + edge @source.push -> root + +} + + + +;; #### Import + +; https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import + + +; import "foo.js"; +; only used for side effects not imports. +; HACK this is not a good solution, but we can't do better with the +; current tree sitter grammar +(import_statement)@import_stmt { + edge @import_stmt.after_scope -> @import_stmt.before_scope +} + +; import * as name from "module-name"; +(import_clause + (namespace_import)@namespace_import)@import_clause { + + edge @namespace_import.before_scope -> @import_clause.before_scope + edge @import_clause.after_scope -> @namespace_import.after_scope + edge @namespace_import.source -> @import_clause.source +} + +(namespace_import (identifier)@imported_as)@namespace_import { + + edge @namespace_import.after_scope -> @namespace_import.before_scope + + attr @imported_as.pop "pop" = @imported_as, "definition" + attr @imported_as.pop_dot "pop" = "." + edge @imported_as.pop -> @imported_as.pop_dot + edge @imported_as.pop_dot -> @namespace_import.source + + edge @namespace_import.after_scope -> @imported_as.pop + +} + +; import { export1 } from "module-name"; +; import { export1 as alias1 } from "module-name"; +; import { export1 , export2 } from "module-name"; +; import { export1 , export2 as alias2 , [...] } from "module-name"; + +(import_statement + (import_clause)@import_clause + source:(_)@source)@import_stmt { + + edge @import_clause.before_scope -> @import_stmt.before_scope + edge @import_stmt.after_scope -> @import_clause.after_scope + + scan @source { + "\"([^/\"]+)\.js\"$" { + attr @source.push "push" = $1 + } + } + attr @source.push_guard_exports "push" = "GUARD:EXPORTS" + edge @source.push_guard_exports -> @source.push + edge @source.push -> root + edge @import_clause.source -> @source.push_guard_exports + +} + +(import_clause + (named_imports)@named_imports)@import_clause { + + edge @named_imports.before_scope -> @import_clause.before_scope + edge @import_clause.after_scope -> @named_imports.after_scope + edge @named_imports.source -> @import_clause.source + +} + +; LATER-TODO tree sitter doesn't yet support empty named imports +; THIS IS A HUGE HACK AND MUST BE FIXED +(named_imports)@named_imports { + edge @named_imports.after_scope -> @named_imports.before_scope +} + +(named_imports + (import_specifier)@import_specifier)@named_imports { + + edge @import_specifier.source -> @named_imports.source +} + +(named_imports + . + (import_specifier)@first_import)@named_imports { + + edge @first_import.before_scope -> @named_imports.before_scope +} + +(named_imports + (import_specifier)@left_import + . + (import_specifier)@right_import) { + + edge @right_import.before_scope -> @left_import.after_scope +} + +(named_imports + (import_specifier)@last_import + .)@named_imports { + + edge @named_imports.after_scope -> @last_import.after_scope +} + +( + + (import_specifier + name:(_)@name + !alias)@import_specifier + + (#not-eq? @name "default") + +) { + + edge @import_specifier.after_scope -> @import_specifier.before_scope + + attr @name.pop "pop" = @name, "definition" + attr @name.push "push" = @name, "reference" + edge @name.pop -> @name.push + edge @name.push -> @import_specifier.source + edge @import_specifier.after_scope -> @name.pop + +} + +( + + (import_specifier + name:(_)@name + alias:(_)@alias)@import_specifier + + (#not-eq? @name "default") + +) { + + edge @import_specifier.after_scope -> @import_specifier.before_scope + + attr @alias.pop "pop" = @alias, "definition" + attr @name.push "push" = @name, "reference" + edge @alias.pop -> @name.push + edge @name.push -> @import_specifier.source + edge @import_specifier.after_scope -> @alias.pop + +} + +; (import_statement +; (import_clause +; (named_imports +; (import_specifier +; name:(_)@name +; alias:(_)@alias))) +; source: (_)@mod_name)@import_stmt { +; +; ; scope passes through, augmented by the identifier +; scan @mod_name { +; "\"([^/\"]+)\.js\"$" { +; attr @mod_name.push "push" = $1, "reference" +; } +; } +; edge @mod_name.push -> root +; +; attr @name "push", "reference" +; attr @name.push_dot "push" = "." +; edge @name.push_dot -> @mod_name.push +; edge @name -> @name.push_dot +; +; attr @alias "pop", "definition" +; edge @alias -> @name +; +; edge @import_stmt.after_scope -> @alias +; } + + +; TODO import defaultExport, { export1 [ , [...] ] } from "module-name"; +; TODO import defaultExport, * as name from "module-name"; +; TODO var promise = import("module-name"); + +; import defaultExport from "module-name"; +(import_clause + (identifier)@default_name)@import_clause { + + edge @import_clause.after_scope -> @import_clause.before_scope + + attr @default_name.pop "pop" = @default_name, "definition" + attr @default_name.push_guard_default "push" = "GUARD:DEFAULT" + edge @default_name.pop -> @default_name.push_guard_default + edge @default_name.push_guard_default -> @import_clause.source + + edge @import_clause.after_scope -> @default_name.pop + +} + + + +;; #### Debugger + +(debugger_statement)@debugger_stmt { + ; scopes flow through unchanged + edge @debugger_stmt.after_scope -> @debugger_stmt.before_scope +} + + + +;; #### Expression + +(expression_statement (_)@inner)@expr_stmt { + + ; scopes flow in then back out + edge @inner.before_scope -> @expr_stmt.before_scope + edge @expr_stmt.after_scope -> @inner.after_scope +} + + + +;; #### Declarations + +;; ##### Variable Declarations + +(variable_declaration + (variable_declarator + name:(identifier)@name))@decl { + + attr @name.pop "pop", "definition" + edge @decl.after_scope -> @name.pop +} + +(lexical_declaration + (variable_declarator + name:(identifier)@name))@decl { + + attr @name.pop "pop", "definition" + edge @decl.after_scope -> @name.pop +} + +(variable_declaration + (variable_declarator + !value))@decl { + + edge @decl.after_scope -> @decl.before_scope +} + +(lexical_declaration + (variable_declarator + !value))@decl { + + edge @decl.after_scope -> @decl.before_scope +} + +(variable_declaration + (variable_declarator + name:(identifier)@name + value:(_)@initializer))@decl { + + edge @name.pop -> @initializer.value + edge @decl.value -> @initializer.value + edge @initializer.before_scope -> @decl.before_scope + edge @decl.after_scope -> @initializer.after_scope +} + +(lexical_declaration + (variable_declarator + name:(identifier)@name + value:(_)@initializer))@decl { + + edge @name.pop -> @initializer.value + edge @decl.value -> @initializer.value + edge @initializer.before_scope -> @decl.before_scope + edge @decl.after_scope -> @initializer.after_scope +} + +(variable_declaration + (variable_declarator + name:[(object_pattern) (array_pattern)]@pat + value:(_)@initializer))@decl { + + edge @initializer.before_scope -> @decl.before_scope + edge @pat.before_scope -> @initializer.after_scope + edge @decl.after_scope -> @pat.after_scope + + edge @pat.covalue -> @initializer.value +} + +(lexical_declaration + (variable_declarator + name:[(object_pattern) (array_pattern)]@pat + value:(_)@initializer))@decl { + + edge @initializer.before_scope -> @decl.before_scope + edge @pat.before_scope -> @initializer.after_scope + edge @decl.after_scope -> @pat.after_scope + + edge @pat.covalue -> @initializer.value +} + + + +;; ##### Function Declarations + +(function_declaration + name:(_)@name + parameters:(_)@call_sig + body:(_)@body)@fun_decl { + + attr @name.pop "syntax_type" = "function" + + ; scope flows across the decl + edge @fun_decl.after_scope -> @fun_decl.before_scope + + ; with an augmentation for the function + attr @name.pop "pop" = @name, "definition" + edge @fun_decl.after_scope -> @name.pop + edge @name.pop -> @fun_decl.value + + ; function values have drop nodes that handle closures, that points to the + ; before scope for the function + attr @fun_decl.value_drop "drop" + edge @fun_decl.value_drop -> @fun_decl.before_scope + + ; the call sig's before scope comes from the drop node then flows into the body + edge @call_sig.before_scope -> @fun_decl.value_drop + attr @call_sig.this_pop "pop" = "this", "definition" + attr @call_sig.this_push "push" = "this" + edge @call_sig.this_pop -> @call_sig.this_push + edge @call_sig.this_push -> @fun_decl.value_arg_scope + edge @call_sig.before_scope -> @call_sig.this_pop + attr @call_sig.arguments_pop "pop" = "arguments", "definition" + attr @call_sig.arguments_push "push" = "arguments" + edge @call_sig.arguments_pop -> @call_sig.arguments_push + edge @call_sig.arguments_push -> @fun_decl.value_arg_scope + edge @call_sig.before_scope -> @call_sig.arguments_pop + edge @body.before_scope -> @call_sig.after_scope + + + ; function values have call nodes + attr @fun_decl.value_call "pop" = "()", "pop-scope" + edge @fun_decl.value -> @fun_decl.value_call + + ; function values have return nodes which need to be visible for returns + attr @fun_decl.value_return "endpoint" + attr @fun_decl.value_return "pop" = "GUARD:RETURN" + edge @fun_decl.value_call -> @fun_decl.value_return + let @body::return_or_yield = @fun_decl.value_return + + ; method values have this nodes which need to be visible for constructor calls + attr @fun_decl.value_this "push" = "this" + attr @fun_decl.value_this_guard "endpoint" + attr @fun_decl.value_this_guard "pop" = "GUARD:THIS" + edge @fun_decl.value_call -> @fun_decl.value_this_guard + edge @fun_decl.value_this_guard -> @fun_decl.value_this + edge @fun_decl.value_this -> @body.after_scope + + ; function values have a jump node that lets params connect up to actual arguments + attr @fun_decl.value_arg_scope "jump-to" +} + +(function_declaration + parameters: + (formal_parameters (_)@param))@fun_decl { + + ; parameters jump to the pushed argument scope + attr @param.arg_index "push" = (child-index @param) + edge @param.covalue -> @param.arg_index + edge @param.arg_index -> @fun_decl.value_arg_scope +} + + +;; ##### Generator Function Declarations + +(generator_function_declaration + name:(_)@name + parameters:(_)@call_sig + body:(_)@body)@fun_decl { + + attr @name.pop "syntax_type" = "function" + + ; scope flows across the decl + edge @fun_decl.after_scope -> @fun_decl.before_scope + + ; with an augmentation for the function + attr @name.pop "pop" = @name, "definition" + edge @fun_decl.after_scope -> @name.pop + edge @name.pop -> @fun_decl.value + + ; function values have drop nodes that handle closures, that points to the + ; before scope of the declaration + attr @fun_decl.value_drop "drop" + edge @fun_decl.value_drop -> @fun_decl.before_scope + + + ; the call sig's before scope comes from the drop node then flows into the body + edge @call_sig.before_scope -> @fun_decl.value_drop + attr @call_sig.this_pop "pop" = "this", "definition" + attr @call_sig.this_push "push" = "this" + edge @call_sig.this_pop -> @call_sig.this_push + edge @call_sig.this_push -> @fun_decl.value_arg_scope + edge @call_sig.before_scope -> @call_sig.this_pop + attr @call_sig.arguments_pop "pop" = "arguments", "definition" + attr @call_sig.arguments_push "push" = "arguments" + edge @call_sig.arguments_pop -> @call_sig.arguments_push + edge @call_sig.arguments_push -> @fun_decl.value_arg_scope + edge @call_sig.before_scope -> @call_sig.arguments_pop + edge @body.before_scope -> @call_sig.after_scope + + ; function values have call nodes + attr @fun_decl.value_call "pop" = "()", "pop-scope" + edge @fun_decl.value -> @fun_decl.value_call + + ; function values have return nodes which need to be visible for returns + attr @fun_decl.value_return "endpoint" + attr @fun_decl.value_return "pop" = "GUARD:RETURN" + edge @fun_decl.value_call -> @fun_decl.value_return + let @body::return_or_yield = @fun_decl.value_return + + ; method values have this nodes which need to be visible for constructor calls + attr @fun_decl.value_this "push" = "this" + attr @fun_decl.value_this_guard "endpoint" + attr @fun_decl.value_this_guard "pop" = "GUARD:THIS" + edge @fun_decl.value_call -> @fun_decl.value_this_guard + edge @fun_decl.value_this_guard -> @fun_decl.value_this + edge @fun_decl.value_this -> @body.after_scope + + ; function values have a jump node that lets params connect up to actual arguments + attr @fun_decl.value_arg_scope "jump-to" +} + +(generator_function_declaration + parameters: + (formal_parameters (_)@param))@fun_decl { + + ; parameters jump to the pushed argument scope + attr @param.arg_index "push" = (child-index @param) + edge @param.covalue -> @param.arg_index + edge @param.arg_index -> @fun_decl.value_arg_scope +} + + + +;; #### Classes + +(class_declaration + name:(_)@name + body:(_)@body)@class_decl { + + attr @name.pop "syntax_type" = "class" + + attr @name.pop "pop" = @name, "definition" + edge @class_decl.after_scope -> @name.pop + edge @name.pop -> @class_decl.value + + edge @body.before_scope -> @class_decl.before_scope + edge @class_decl.value -> @body.after_scope + edge @class_decl.after_scope -> @class_decl.before_scope +} + +(class_declaration + (class_heritage (_)@name))@class_decl { + + edge @name.before_scope -> @class_decl.before_scope + edge @class_decl.value -> @name.value +} + + +; LATER-TODO tree sitter doesn't yet support empty switch bodies +; THIS IS A HUGE HACK AND MUST BE FIXED +(class_body)@class_body { + edge @class_body.after_scope -> @class_body.before_scope +} + +(class_body + . + (_)@first_decl)@class_body { + + edge @first_decl.before_scope -> @class_body.before_scope +} + +(class_body + (_)@left_decl + . + (_)@right_decl) { + + edge @right_decl.before_scope -> @left_decl.after_scope +} + +(class_body + (_)@last_decl + .)@class_body { + + edge @class_body.after_scope -> @last_decl.after_scope +} + + +( + (method_definition + name:(_)@name)@method_def + (#eq? @name "constructor") +) { + ; augmentation for the constructor + attr @name.constructor_guard "pop" = "GUARD:CONSTRUCTOR", "definition" + edge @method_def.after_scope -> @name.constructor_guard + edge @name.constructor_guard -> @method_def.method_value +} + +( + (method_definition + name:(_)@name)@method_def + (#not-eq? @name "constructor") +) { + ; augmentation for the method + attr @name.pop "pop" = @name, "definition" + attr @name.pop_dot "pop" = "." + edge @method_def.after_scope -> @name.pop_dot + edge @name.pop_dot -> @name.pop + edge @name.pop -> @method_def.method_value +} + +(method_definition + name:(_)@name + parameters:(_)@call_sig + body:(_)@body)@method_def { + + attr @name.pop "syntax_type" = "method" + + ; scope flows across the decl + edge @method_def.after_scope -> @method_def.before_scope + + ; method values have drop nodes that handle closures, that points to the + ; before scope from method def + attr @method_def.method_value_drop "drop" + edge @method_def.method_value_drop -> @method_def.before_scope + + ; the call sig's before scope comes from the drop node then flows into the body + edge @call_sig.before_scope -> @method_def.method_value_drop + edge @body.before_scope -> @call_sig.after_scope + + ; method values have call nodes + attr @method_def.method_value_call "pop" = "()", "pop-scope" + edge @method_def.method_value -> @method_def.method_value_call + + ; method values have return nodes which need to be visible for returns + attr @method_def.method_value_return "endpoint" + attr @method_def.method_value_return "pop" = "GUARD:RETURN" + edge @method_def.method_value_call -> @method_def.method_value_return + let @body::return_or_yield = @method_def.method_value_return + + ; method values have this nodes which need to be visible for constructor calls + attr @method_def.method_value_this "push" = "this" + attr @method_def.method_value_this_guard "endpoint" + attr @method_def.method_value_this_guard "pop" = "GUARD:THIS" + edge @method_def.method_value_call -> @method_def.method_value_this_guard + edge @method_def.method_value_this_guard -> @method_def.method_value_this + edge @method_def.method_value_this -> @body.after_scope + + ; method values have a jump node that lets params connect up to actual arguments + attr @method_def.method_value_arg_scope "jump-to" +} + +(method_definition + parameters: + (formal_parameters (_)@param))@method_def { + + ; parameters jump to the pushed argument scope + attr @param.arg_index "push" = (child-index @param) + edge @param.covalue -> @param.arg_index + edge @param.arg_index -> @method_def.method_value_arg_scope +} + + + +(field_definition + property:(property_identifier)@property)@field_def { + + attr @property.pop "pop" = @property, "definition" + attr @property.pop_dot "pop" = "." + edge @field_def.after_scope -> @property.pop_dot + edge @property.pop_dot -> @property.pop +} + +(field_definition + !value)@field_def { + + edge @field_def.after_scope -> @field_def.before_scope +} + +(field_definition + property:(_)@property + value:(_)@value)@field_def { + + edge @value.before_scope -> @field_def.before_scope + edge @field_def.after_scope -> @value.after_scope + edge @property.pop -> @value.value +} + + + +;; #### Statement Block + +; statement block, first statement +(statement_block + . + (_)@first_stmt)@block { + + ; scope flows from block to first statement + edge @first_stmt.before_scope -> @block.before_scope +} + +; statement block, between statements +(statement_block + (_)@left_stmt + . + (_)@right_stmt) { + ; scope flows from left to right + edge @right_stmt.before_scope -> @left_stmt.after_scope +} + +; statement block, last statement +(statement_block + (_)@last_stmt + .)@block { + ; scope flows from last statement to block + edge @block.after_scope -> @last_stmt.after_scope +} + + + + + +;; #### If + +(if_statement + condition:(_)@condition)@if_stmt { + + ; scopes flow from the if statement to the condition + edge @condition.before_scope -> @if_stmt.before_scope +} + +(if_statement + condition:(_)@condition + consequence:(_)@consequence)@if_stmt { + + ; scopes flow from the condition to the consequence, then to the if statement + edge @consequence.before_scope -> @condition.after_scope + edge @if_stmt.after_scope -> @consequence.after_scope +} + +(if_statement + condition:(_)@condition + alternative:(_)@alternative)@if_stmt { + + ; scopes flow from the condition to the alternative, then to the if statement + edge @alternative.before_scope -> @condition.after_scope + edge @if_stmt.after_scope -> @alternative.after_scope +} + +(else_clause (_)@inner)@else_clause { + + ; scopes flow in and right back out + edge @inner.before_scope -> @else_clause.before_scope + edge @else_clause.after_scope -> @inner.after_scope +} + + + + +;; #### Switch + +(switch_statement + value:(_)@value + body:(switch_body)@body)@switch_stmt { + + ; scopes flow into the value then into the body then back out to the switch + edge @value.before_scope -> @switch_stmt.before_scope + edge @body.before_scope -> @value.after_scope + edge @switch_stmt.after_scope -> @body.after_scope +} + +; LATER-TODO tree sitter doesn't yet support empty switch bodies +; THIS IS A HUGE HACK AND MUST BE FIXED +(switch_body)@switch_body { + edge @switch_body.after_scope -> @switch_body.before_scope +} + +; switch body, first choice +(switch_body + . + (_)@first_choice)@switch_body { + + ; scopes flow from the body into the first choice + edge @first_choice.before_scope -> @switch_body.before_scope +} + +; switch body, between choices +(switch_body + (_)@left_choice + . + (_)@right_choice) { + + ; scopes flow left to right + edge @right_choice.before_scope -> @left_choice.after_scope +} + +; switch body, last choice +(switch_body + (_)@last_choice + .)@switch_body { + + ; scope flows out to the switch body + edge @switch_body.after_scope -> @last_choice.after_scope +} + +; LATER-TODO tree sitter doesnt yet support switch case's with no statements +; THIS IS A HUGE HACK AND MUST BE FIXED +(switch_case)@switch_case { + edge @switch_case.after_scope -> @switch_case.before_scope +} + +; switch case, non-empty statements, first statement +(switch_case + value:(_)@value + . + (_)@first_stmt)@switch_case { + + ; scopes flow into the value then into the first statement + edge @value.before_scope -> @switch_case.before_scope + edge @first_stmt.before_scope -> @value.after_scope +} + +; switch case, non-empty statements, between statement +(switch_case + value:(_) + (_)@left_stmt + . + (_)@right_stmt) { + + ; scopes flow left to right + edge @right_stmt.before_scope -> @left_stmt.after_scope +} + +; switch case, non-empty statements, last statement +(switch_case + value:(_) + (_)@last_stmt + .)@switch_case { + + ; scopes flow out from the last statement to the case + edge @switch_case.after_scope -> @last_stmt.after_scope +} + +; LATER-TODO tree sitter doesnt yet support empty defaults +; THIS IS A HUGE HACK AND MUST BE FIXED +(switch_default)@switch_default { + edge @switch_default.after_scope -> @switch_default.before_scope +} + +; switch default, non-empty statements, first statement +(switch_default + . + (_)@first_stmt)@switch_default { + + ; scopes flow into the first statement + edge @first_stmt.before_scope -> @switch_default.before_scope +} + +; switch default, non-empty statements, between statements +(switch_default + (_)@left_stmt + . + (_)@right_stmt) { + + ; scopes flow left to right + edge @right_stmt.before_scope -> @left_stmt.after_scope +} + +; switch default, non-empty statements, last statement +(switch_default + (_)@last_stmt + .)@switch_default { + + ; scopes flow out to the default + edge @switch_default.after_scope -> @last_stmt.after_scope +} + + + +;; #### For + +(for_statement + initializer:(_)@initializer + condition:(_)@condition + increment:(_)@increment + body:(_)@body)@for_stmt { + + ; scopes flow from statement to initializer then test then body then increment + edge @initializer.before_scope -> @for_stmt.before_scope + edge @condition.before_scope -> @initializer.after_scope + edge @body.before_scope -> @condition.after_scope + edge @increment.before_scope -> @body.after_scope + + ; scopes also from from the body back into the condition + edge @condition.before_scope -> @body.after_scope + + ; scopes also flow from condition out to statement + edge @for_stmt.after_scope -> @condition.after_scope +} + + + +;; #### For In + +(for_in_statement + left:(_)@left + right:(_)@right + body:(_)@body)@for_in_stmt { + + ; scopes flow from statement to right then to body then back out + edge @right.before_scope -> @for_in_stmt.before_scope + edge @body.before_scope -> @right.after_scope + edge @for_in_stmt.after_scope -> @body.after_scope +} + +(for_in_statement + left:(identifier)@left + right:(_)@right + body:(_)@body) { + + attr @left.pop "pop", "definition" + edge @left.pop -> @right.value + edge @body.before_scope -> @left.pop +} + + + +;; #### While + +(while_statement + condition:(_)@condition + body:(_)@body)@while_stmt { + + ; scopes flow from while to condition then to body then back out + edge @condition.before_scope -> @while_stmt.before_scope + edge @body.before_scope -> @condition.after_scope + edge @while_stmt.after_scope -> @body.after_scope + + ; scopes also flow back into the condition + edge @condition.before_scope -> @body.after_scope +} + + + +;; #### Do + +(do_statement + body:(_)@body + condition:(_)@condition)@do_stmt { + + ; scopes flow from statement to body then condition then back to statement + edge @body.before_scope -> @do_stmt.before_scope + edge @condition.before_scope -> @body.after_scope + edge @do_stmt.after_scope -> @condition.after_scope + + ; scopes also flow back to the body from the condition + edge @body.before_scope -> @condition.after_scope + +} + + + +;; #### Try + +(try_statement + body:(_)@body)@try_stmt { + + ; scopes flow into the body then back out + edge @body.before_scope -> @try_stmt.before_scope + edge @try_stmt.after_scope -> @body.after_scope + +} + +(try_statement + body:(_)@body + handler:(_)@handler)@try_stmt { + + ; scopes flow from body to handler then back out + edge @handler.before_scope -> @body.after_scope + edge @try_stmt.after_scope -> @handler.after_scope +} + +(try_statement + body:(_)@body + finalizer:(_)@finalizer)@try_stmt { + + ; scopes flow from body to finalizer then back out + edge @finalizer.before_scope -> @body.after_scope + edge @try_stmt.after_scope -> @finalizer.after_scope +} + +(try_statement + handler:(_)@handler + finalizer:(_)@finalizer)@try_stmt { + + ; scopes flow from handler to finalizer then back out + edge @finalizer.before_scope -> @handler.after_scope + edge @try_stmt.after_scope -> @finalizer.after_scope +} + +(catch_clause body:(_)@body)@catch_clause { + ; scopes flow in then back out + edge @body.before_scope -> @catch_clause.before_scope + edge @catch_clause.after_scope -> @body.after_scope +} + +(catch_clause + parameter:(identifier)@name + body:(_)@body) { + + attr @name.pop "pop", "definition" + edge @body.before_scope -> @name.pop +} + +(finally_clause body:(_)@body)@finally_clause { + ; scopes flow in thenback out + edge @body.before_scope -> @finally_clause.before_scope + edge @finally_clause.after_scope -> @body.after_scope +} + + + +;; #### With + +(with_statement + object:(_)@object + body:(_)@body)@with_stmt { + + ; scopes flow from the statement into the object then into the body then back out + edge @object.before_scope -> @with_stmt.before_scope + edge @body.before_scope -> @object.after_scope + edge @with_stmt.after_scope -> @body.after_scope + + attr @object.push_dot "push" = "." + edge @object.push_dot -> @object.value + edge @body.before_scope -> @object.push_dot +} + + + +;; #### Break + +(break_statement)@break_stmt { + ; scopes flow through unchanged + edge @break_stmt.after_scope -> @break_stmt.before_scope +} + + + +;; #### Continue + +(continue_statement)@continue_stmt { + ; scopes flow through unchanged + edge @continue_stmt.after_scope -> @continue_stmt.before_scope +} + + + +;; #### Return + +; LATER-TODO tree sitter doesn't let us express empty returns currently +(return_statement)@return_stmt { + ; scopes flow through unchanged + edge @return_stmt.after_scope -> @return_stmt.before_scope +} + +(return_statement + (_)@returned_expr)@return_stmt { + ; scopes flow through the returned expresssion + edge @returned_expr.before_scope -> @return_stmt.before_scope + edge @return_stmt.after_scope -> @returned_expr.after_scope + + ; return statements hook up to the call node of the function value + edge @return_stmt::return_or_yield -> @returned_expr.value +} + + + +;; #### Throw + +(throw_statement (_)@thrown_expr)@throw_stmt { + ; scopes flow through the returned expresssion + edge @thrown_expr.before_scope -> @throw_stmt.before_scope + edge @throw_stmt.after_scope -> @thrown_expr.after_scope +} + + + +;; #### Empty + +(empty_statement)@empty_stmt { + ; scopes flow through unchaged + edge @empty_stmt.after_scope -> @empty_stmt.before_scope +} + + + +;; #### Labeled + +(labeled_statement (_)@inner)@labeled_stmt { + ; scopes flow through the inner statement then back out + edge @inner.before_scope -> @labeled_stmt.before_scope + edge @labeled_stmt.after_scope -> @inner.after_scope +} + + + +;; ## Expressions + +;; ### Attributes Defined on Expressions +;; TODO + +;; ### Expression Queries + + +;; #### Parenthesized + +(parenthesized_expression (_)@inner)@parens { + ; scopes flow right through + edge @inner.before_scope -> @parens.before_scope + edge @parens.after_scope -> @inner.after_scope + + ; as do values + edge @parens.value -> @inner.value +} + + +;; #### Strings + +(string)@string { + ; scopes don't change + edge @string.after_scope -> @string.before_scope + + ; the value of a string is the string primitive + edge @string.value -> @string::string +} + + +;; #### Template Strings + +; template_strings w/ no substitutions +; LATER-TODO tree sitter queries don't let us find the absence of substitutions +; THIS IS A HUGE HACK AND MUST BE FIXED +(template_string)@template_string { + edge @template_string.after_scope -> @template_string.before_scope +} + +; nonempty template string, value +; LATER-TODO this isn't really right, but it gets flows through the template string +; which may be useful +(template_string (template_substitution (_)@inner_expr))@template_string { + ; the value of a template string is a template string value built from the values of its substitutions + ; attr @template_string.value "template_string_value" + edge @template_string.value -> @inner_expr.value +} + +; nonempty template string, first substitution +(template_string . (template_substitution (_)@first_inner_expr))@template_string { + ; scopes propagate into the first subtitution of the template string + edge @first_inner_expr.before_scope -> @template_string.before_scope +} + +; nonempty template string, between substitutions +(template_string + (template_substitution (_)@left_inner_expr) + . + (template_substitution (_)@right_inner_expr))@template_string { + ; scopes propagate from left substitutions to right substitutions + edge @right_inner_expr.before_scope -> @left_inner_expr.after_scope +} + +; nonempty template string, last substitution +(template_string . (template_substitution (_)@last_inner_expr))@template_string { + ; scopes propagate out of the last substitution to the template string + edge @template_string.after_scope -> @last_inner_expr.after_scope +} + + + +;; #### Numbers + +(number)@number { + ; scopes don't change + edge @number.after_scope -> @number.before_scope + + ; the value of a number is the number primitive + edge @number.value -> @number::number +} + + +;; #### Variables + +(primary_expression/identifier)@variable { + ; scopes don't change + edge @variable.after_scope -> @variable.before_scope + + ; value is a lookup, ie a push + attr @variable.value "push", "reference" + edge @variable.value -> @variable.before_scope +} + + +;; #### Booleans + +(true)@true { + ; scopes don't change + edge @true.after_scope -> @true.before_scope + + ; the value of true is a boolean primitive + edge @true.value -> @true::boolean +} + +(false)@false { + ; scopes don't change + edge @false.after_scope -> @false.before_scope + + ; the value of false is a boolean primitive + edge @false.value -> @false::boolean +} + + +;; #### This + +(this)@this { + ; scopes don't change + edge @this.after_scope -> @this.before_scope + + ; this is a lookup, ie a push + attr @this.value "push" = "this", "reference" + edge @this.value -> @this.before_scope +} + + +;; #### Super + +(super)@super { + ; scopes don't change + edge @super.after_scope -> @super.before_scope +} + + +;; #### Null + +(null)@null { + ; scopes don't change + edge @null.after_scope -> @null.before_scope + + ; the value of null is the null primitive + edge @null.value -> @null::null +} + + +;; #### Undefined + +(undefined)@undefined { + ; scopes don't change + edge @undefined.after_scope -> @undefined.before_scope + + ; the value of undefined is the undefined primitive + edge @undefined.value -> @undefined::undefined +} + + +;; #### Regular Expressions + +(regex)@regex { + ; scopes don't change + edge @regex.after_scope -> @regex.before_scope + + ; the value of a regex is the Regex prototype + edge @regex.value -> @regex::Regex_prototype +} + + +;; #### Spread Elements + +(spread_element (_)@expr)@spread_elem { + ; scopes flow in then right back out + edge @expr.before_scope -> @spread_elem.before_scope + edge @spread_elem.after_scope -> @expr.after_scope +} + + +;; #### Objects + +; empty objects +; LATER-TODO currently unsupported by tree sitter queries +; THIS IS A HUGE HACK AND MUST BE FIXED +(object)@object_expr { + edge @object_expr.after_scope -> @object_expr.before_scope +} + +; non-empty objects, scopes, first entry +(object + . + (_)@first_entry)@object_expr { + ; scopes propagate from the object to the first entry + edge @first_entry.before_scope -> @object_expr.before_scope +} + +; non-empty objects, scopes, between entries +(object + (_)@left_entry + . + (_)@right_entry +)@object_expr { + ; scopes propagate from left entries to right entries + edge @right_entry.before_scope -> @left_entry.after_scope +} + +; non-empty objects, scopes, last entry +(object + (_)@last_entry + .)@object_expr { + ; scopes propagate from the last entry back to the object + edge @object_expr.after_scope -> @last_entry.after_scope +} + +; shorthand property identifier +(object + (shorthand_property_identifier)@keyval)@object { + + ; scopes flow into rhsvar, and also straight across b/c they can't be modified + edge @keyval.rhsvar_before_scope -> @keyval.before_scope + edge @keyval.after_scope -> @keyval.before_scope + + ; shorthand property identifiers have secret variable exprs + attr @keyval.rhsvar_value "push" = @keyval, "reference" + edge @keyval.rhsvar_value -> @keyval.rhsvar_before_scope + + ; shorthand property identifiers augment the object value with a member binding + attr @keyval.boundvar_pop "pop" = @keyval, "definition" + + attr @object.field_pop_dot "pop" = "." + edge @keyval.boundvar_pop -> @keyval.rhsvar_value + edge @object.field_pop_dot -> @keyval.boundvar_pop + edge @object.value -> @object.field_pop_dot + +} + +; pairs +(object + (pair + key:(_)@key + value: (_)@value)@pair)@object { + + ; scopes flow into values then back to the pair + edge @value.before_scope -> @pair.before_scope + edge @pair.after_scope -> @value.after_scope + + ; pairs augment the object value with a member binding + + ; This is done differently depending on what the key is. See next rules. + ; attr @key.pop "pop" = @key, "definition" + attr @key.pop "definition" + + attr @object.field_pop_dot "pop" = "." + edge @key.pop -> @value.value + edge @object.field_pop_dot -> @key.pop + edge @object.value -> @object.field_pop_dot +} + +(pair key:(property_identifier)@key) { + attr @key.pop "pop" = @key +} + +(pair key:(string)@key) { + attr @key.pop "pop" = (replace @key "\"" "") +} + +(pair key:(number)@key) { + attr @key.pop "pop" = @key +} + + + +;; #### Arrays + +; empty arrays +; LATER-TODO currently unsupported by tree sitter queries +; THIS IS A HUGE HACK AND MUST BE FIXED +(array)@array_expr { + edge @array_expr.after_scope -> @array_expr.before_scope +} + +; nonempty arrays, first element +(array + . + (_)@first_element)@array_expr { + ; scopes propagate into the first element of the array + edge @first_element.before_scope -> @array_expr.before_scope +} + +; nonempty arrays, between elements +(array + (_)@left_element + . + (_)@right_element) { + ; scopes propagate from left elements to right elements + edge @right_element.before_scope -> @left_element.after_scope +} + +; nonempty arrays, last element +(array + (_)@last_element + .)@array_expr { + ; scopes propagate out of the last element to the array + edge @array_expr.after_scope -> @last_element.after_scope +} + +; elements at indices +(array (_)@element)@array_expr { + attr @array_expr.element_pop_dot "pop" = "." + attr @element.index_pop "pop" = (child-index @element), "definition" + edge @array_expr.element_pop_dot -> @element.index_pop + edge @array_expr.value -> @array_expr.element_pop_dot + edge @element.index_pop -> @element.value +} + + + +;; #### Formal Parameters + +; LATER-TODO scope propagation through empty formal parameters +; currently unsupported by tree sitter queries +; THIS IS A HUGE HACK AND MUST BE FIXED + +(formal_parameters)@formal_params { + edge @formal_params.after_scope -> @formal_params.before_scope +} + +; first parameter +(formal_parameters + . + (_)@first_param)@formal_params { + + edge @first_param.before_scope -> @formal_params.before_scope +} + +; between parameters +(formal_parameters + (_)@left_param + . + (_)@right_param) { + + ; scope flows left to right + edge @right_param.before_scope -> @left_param.after_scope +} + +; last parameter +(formal_parameters + (_)@last_param + .)@formal_params { + + ; scope flows from the param to the call sig + edge @formal_params.after_scope -> @last_param.after_scope +} + + + +;; #### Function Literals + +; functions with names +(function + name:(_)@name + parameters:(_)@call_sig)@fun { + + attr @name.pop "syntax_type" = "function" + + ; if the function has a name, this is bound the callsig's before scope + attr @name.pop "pop" = @name, "definition" + edge @call_sig.before_scope -> @name.pop + edge @name.pop -> @fun.value +} + + +; function +(function + parameters:(_)@call_sig + body:(_)@body)@fun { + + ; scope flows across the decl + edge @fun.after_scope -> @fun.before_scope + + ; function values have drop nodes that handle closures, that points to the + ; before scope from the function + attr @fun.value_drop "drop" + edge @fun.value_drop -> @fun.before_scope + + ; the call sig's before scope comes from the drop node, + ; then flows into the body, and includes a variable binding for "this" + edge @call_sig.before_scope -> @fun.value_drop + attr @call_sig.this_pop "pop" = "this", "definition" + attr @call_sig.this_push "push" = "this" + edge @call_sig.this_pop -> @call_sig.this_push + edge @call_sig.this_push -> @fun.value_arg_scope + edge @call_sig.before_scope -> @call_sig.this_pop + attr @call_sig.arguments_pop "pop" = "arguments", "definition" + attr @call_sig.arguments_push "push" = "arguments" + edge @call_sig.arguments_pop -> @call_sig.arguments_push + edge @call_sig.arguments_push -> @fun.value_arg_scope + edge @call_sig.before_scope -> @call_sig.arguments_pop + edge @body.before_scope -> @call_sig.after_scope + + ; function values have call nodes + attr @fun.value_call "pop" = "()", "pop-scope" + edge @fun.value -> @fun.value_call + + ; function values have return nodes which need to be visible for returns + attr @fun.value_return "endpoint" + attr @fun.value_return "pop" = "GUARD:RETURN" + edge @fun.value_call -> @fun.value_return + let @body::return_or_yield = @fun.value_return + + ; function values have this nodes which need to be visible for method calls + attr @fun.value_this "push" = "this" + attr @fun.value_this_guard "endpoint" + attr @fun.value_this_guard "pop" = "GUARD:THIS" + edge @fun.value_call -> @fun.value_this_guard + edge @fun.value_this_guard -> @fun.value_this + edge @fun.value_this -> @body.after_scope + + ; function values have a jump node that lets params connect up to actual arguments + attr @fun.value_arg_scope "jump-to" +} + +(function + parameters: + (formal_parameters (_)@param))@fun { + + ; parameters jump to the pushed argument scope + attr @param.arg_index "push" = (child-index @param) + edge @param.covalue -> @param.arg_index + edge @param.arg_index -> @fun.value_arg_scope +} + + + +;; #### Arrow Function Literals + +; function +[ + (arrow_function + parameters:(_)@call_sig + body:(_)@body)@fun + + (arrow_function + parameter:(_)@call_sig + body:(_)@body)@fun +] { + + ; scope flows across the decl + edge @fun.after_scope -> @fun.before_scope + + ; function values have drop nodes that handle closures, that points to the + ; before scope from the function + attr @fun.value_drop "drop" + edge @fun.value_drop -> @fun.before_scope + + ; the call sig's before scope comes from the drop node then flows into the body + edge @call_sig.before_scope -> @fun.value_drop + edge @body.before_scope -> @call_sig.after_scope + + ; function values have call nodes + attr @fun.value_call "pop" = "()", "pop-scope" + edge @fun.value -> @fun.value_call + + ; function values have return nodes which need to be visible for returns + attr @fun.value_return "endpoint" + attr @fun.value_return "pop" = "GUARD:RETURN" + edge @fun.value_call -> @fun.value_return + let @body::return_or_yield = @fun.value_return + + ; function values have this nodes which need to be visible for method calls + attr @fun.value_this "push" = "this" + attr @fun.value_this_guard "endpoint" + attr @fun.value_this_guard "pop" = "GUARD:THIS" + edge @fun.value_call -> @fun.value_this_guard + edge @fun.value_this_guard -> @fun.value_this + edge @fun.value_this -> @body.after_scope + + ; function values have a jump node that lets params connect up to actual arguments + attr @fun.value_arg_scope "jump-to" +} + +; arrow functions returning exprs need special rules for getting the return value hooked up +(arrow_function + body:(expression)@return_expr) { + edge @return_expr::return_or_yield -> @return_expr.value +} + +(arrow_function + parameter:(_)@param)@fun { + + ; scope flows from the param right back out + edge @param.after_scope -> @param.before_scope + + ; but augmented with a pop, b/c it's not a pattern + attr @param.pop "pop" = @param, "definition" + edge @param.pop -> @param.covalue + edge @param.after_scope -> @param.pop + + ; parameters jump to the pushed argument scope + attr @param.arg_index "push" = "0" + edge @param.covalue -> @param.arg_index + edge @param.arg_index -> @fun.value_arg_scope +} + +(arrow_function + parameters: + (formal_parameters (_)@param))@fun { + + ; parameters jump to the pushed argument scope + attr @param.arg_index "push" = (child-index @param) + edge @param.covalue -> @param.arg_index + edge @param.arg_index -> @fun.value_arg_scope +} + + + +;; #### Generator Function Literals + +; generator functions with names +(generator_function + name:(_)@name + parameters:(_)@call_sig)@fun { + + attr @name.pop "syntax_type" = "function" + + ; if the function has a name, this is bound the callsig's before scope + attr @name.pop "pop" = @name, "definition" + edge @call_sig.before_scope -> @name.pop + edge @name.pop -> @fun.value +} + + +; generator function +(generator_function + parameters:(_)@call_sig + body:(_)@body)@fun { + + ; scope flows across the decl + edge @fun.after_scope -> @fun.before_scope + + ; function values have drop nodes that handle closures, that points to the + ; before scope from the function + attr @fun.value_drop "drop" + edge @fun.value_drop -> @fun.before_scope + + ; the call sig's before scope comes from the drop node then flows into the body + edge @call_sig.before_scope -> @fun.value_drop + edge @body.before_scope -> @call_sig.after_scope + + ; function values have call nodes + attr @fun.value_call "pop" = "()", "pop-scope" + edge @fun.value -> @fun.value_call + + ; function values have return nodes which need to be visible for returns + attr @fun.value_return "endpoint" + attr @fun.value_return "pop" = "GUARD:RETURN" + edge @fun.value_call -> @fun.value_return + let @body::return_or_yield = @fun.value_return + + ; function values have this nodes which need to be visible for method calls + attr @fun.value_this "push" = "this" + attr @fun.value_this_guard "endpoint" + attr @fun.value_this_guard "pop" = "GUARD:THIS" + edge @fun.value_call -> @fun.value_this_guard + edge @fun.value_this_guard -> @fun.value_this + edge @fun.value_this -> @body.after_scope + + ; function values have a jump node that lets params connect up to actual arguments + attr @fun.value_arg_scope "jump-to" +} + +(generator_function + parameters: + (formal_parameters (_)@param))@fun { + + ; parameters jump to the pushed argument scope + attr @param.arg_index "push" = (child-index @param) + edge @param.covalue -> @param.arg_index + edge @param.arg_index -> @fun.value_arg_scope +} + + +;; #### Function Calls + +; calls, functions +(call_expression + function:(_)@function + arguments:(_)@arguments)@call_expr { + + ; scopes flow from call expressions into the function + edge @function.before_scope -> @call_expr.before_scope + edge @arguments.before_scope -> @function.after_scope + edge @call_expr.after_scope -> @arguments.after_scope +} + +; calls, values +(call_expression + function:(_)@function + arguments:(_)@arguments)@call_expr { + + ; value is a call, ie a push "()" node w/ "push-scope" @arguments + attr @call_expr.return_guard "push" = "GUARD:RETURN" + attr @call_expr.call "push" = "()", "push-scope" = @arguments.arg_scope + edge @call_expr.value -> @call_expr.return_guard + edge @call_expr.return_guard -> @call_expr.call + edge @call_expr.call -> @function.value + + attr @arguments.arg_this "pop" = "this", "definition" + edge @arguments.arg_scope -> @arguments.arg_this + + edge @arguments.arg_scope -> @arguments.arg_scope_no_this + + attr @arguments.arg_arguments "pop" = "arguments", "definition" + attr @arguments.arg_arguments_dot "pop" = "." + edge @arguments.arg_scope -> @arguments.arg_arguments + edge @arguments.arg_arguments -> @arguments.arg_arguments_dot + edge @arguments.arg_arguments_dot -> @arguments.arg_scope_no_this + edge @arguments.arg_arguments -> @call_expr::arguments_prototype +} + +; special case to make `this` bind correctly in calls of the forms `x.f(...)` +; and `x[f](...)` +(call_expression + function:[ + (member_expression object:(_)@object) + (subscript_expression object:(_)@object) + ] + arguments:(_)@arguments) { + + edge @arguments.arg_this -> @object.value +} + + +; TODO this should eventually be removed and replaced with a version that only +; applies to the negation of (member_expression), but that's not supported by +; tree-sitter currently +(call_expression + function: (_)@function + arguments:(_)@arguments)@call_expr { + + edge @arguments.arg_this -> @call_expr::null +} +(call_expression + arguments:(arguments (_)@arg)@arguments) { + + attr @arg.arg_index "pop" = (child-index @arg) + edge @arguments.arg_scope_no_this -> @arg.arg_index + edge @arg.arg_index -> @arg.value +} + + + +;; #### Arguments + +; LATER-TODO currently unsupported by tree sitter queries +; THIS IS A HUGE HACK AND MUST BE FIXED +(arguments)@arguments { + edge @arguments.after_scope -> @arguments.before_scope +} + +(arguments + . + (_)@first_arg)@arguments { + + edge @first_arg.before_scope -> @arguments.before_scope +} + +(arguments + (_)@left_arg + . + (_)@right_arg) { + + edge @right_arg.before_scope -> @left_arg.after_scope +} + +(arguments + (_)@last_arg + .)@arguments { + + edge @arguments.after_scope -> @last_arg.after_scope +} + + + +;; #### Property Access + +;; ##### Member Expressions + +(member_expression + object: (_)@object + property: (_)@property)@member_expr { + + ; scopes flow into object then back out + edge @object.before_scope -> @member_expr.before_scope + edge @member_expr.after_scope -> @object.after_scope + + ; value is a member projection on the value of the object ie. a push then push dot + attr @property.push "push", "reference" + ;attr @member_expr.value "push" = @property.pop + attr @member_expr.push_dot "push" = "." + edge @property.push -> @member_expr.push_dot + ;edge @member_expr.value -> @member_expr.push_dot + edge @member_expr.value -> @property.push + edge @member_expr.push_dot -> @object.value +} + +;; ##### Subscript Expressions + +(subscript_expression + object: (_)@object + index: (_)@index)@subscript_expression { + + ; scopes flow left to right + edge @object.before_scope -> @subscript_expression.before_scope + edge @index.before_scope -> @object.after_scope + edge @subscript_expression.after_scope -> @index.after_scope + + ; value is a subscript lookup, ie a push then push dot + + ; this is done differently depending on what the index is + ; attr @index.push "push" = @index, "reference" + +} + +(subscript_expression + object: (_)@object + index: (string)@index)@subscript_expression { + + attr @index.push "reference" + + attr @index.push_dot "push" = "." + edge @subscript_expression.value -> @index.push + edge @index.push -> @index.push_dot + edge @index.push_dot -> @object.value + attr @index.push "push" = (replace @index "\"" "") +} + +(subscript_expression + object: (_)@object + index: (number)@index)@subscript_expression { + + attr @index.push "reference" + + attr @index.push_dot "push" = "." + edge @subscript_expression.value -> @index.push + edge @index.push -> @index.push_dot + edge @index.push_dot -> @object.value + attr @index.push "push" = @index +} + + + +;; #### Constructor Calls + +(new_expression + constructor:(_)@constructor + arguments:(_)@arguments)@new_expr { + + edge @constructor.before_scope -> @new_expr.before_scope + edge @arguments.before_scope -> @constructor.after_scope + edge @new_expr.after_scope -> @arguments.after_scope + + attr @new_expr.call "push" = "()", "push-scope" = @arguments.arg_scope + + ; we guard for constructors for the case where we have a "true" class + attr @constructor.constructor "push" = "GUARD:CONSTRUCTOR" + edge @new_expr.call -> @constructor.constructor + edge @constructor.constructor -> @constructor.value + + ; and also just go right to the value incase we have a function-as-constructor + edge @new_expr.call -> @constructor.value + + + + ; value coming from the constructor call + attr @new_expr.guard_this "push" = "GUARD:THIS" + edge @new_expr.value -> @new_expr.guard_this + edge @new_expr.guard_this -> @new_expr.call + + ; value coming from the field decls in the class + edge @new_expr.value -> @constructor.value + + attr @arguments.arg_this "pop" = "this", "definition" + edge @arguments.arg_scope -> @arguments.arg_this + edge @arguments.arg_this -> @new_expr::empty_object +} + +(new_expression + arguments:(arguments (_)@arg)@arguments) { + + attr @arg.arg_index "pop" = (child-index @arg) + edge @arguments.arg_scope -> @arg.arg_index + edge @arg.arg_index -> @arg.value +} + + + +;; #### Await + +(await_expression (_)@awaited)@await_expr { + ; scopes flow into the inner expression then back out + edge @awaited.before_scope -> @await_expr.before_scope + edge @await_expr.after_scope -> @awaited.after_scope + + ; value is just propagated up + edge @await_expr.value -> @awaited.value +} + + + +;; #### Update Expressions + +(update_expression argument: (_)@argument)@update_expr { + ; scope propagates through the operand then is updated by the expr + edge @argument.before_scope -> @update_expr.before_scope + edge @update_expr.after_scope -> @argument.after_scope + ; LATER-TODO this isn't quite right because the update argument can't be an arbitrary expr + ; eg f(x)++ doesn't make any sense, you have to have something more like + ; (update_expression argument: (lvar)@argument) + attr @argument.pop "pop", "definition" + edge @update_expr.value -> @argument.value + edge @update_expr.after_scope -> @argument.pop + edge @argument.pop -> @argument.value +} + + +;; #### Binary Expressions + +(binary_expression left: (_)@left right: (_)@right)@binary_expr { + ; scopes propagate left to right through the operands unchanged by the binop itself + edge @left.before_scope -> @binary_expr.before_scope + edge @right.before_scope -> @left.after_scope + edge @binary_expr.after_scope -> @right.after_scope + + ; value is a binary op value built from the operands + ; LATER-TODO this isn't quite correct but it permits flow through the expression + ; which can be useful + ; attr @binary_expr.value "binary_operation_value" + edge @binary_expr.value -> @left.value + edge @binary_expr.value -> @right.value +} + + +;; #### Unary Expressions + +(unary_expression argument: (_)@argument)@unary_expr { + ; scope propagates through the operand + edge @argument.before_scope -> @unary_expr.before_scope + edge @unary_expr.after_scope -> @argument.after_scope + + ; value is a unaryop value built from the operand + ; LATER-TODO this isn't quite correct but it permits flow through the expression + ; which can be useful + ; attr @unary_expr.value "unary_operation_value" + edge @unary_expr.value -> @argument.value +} + + + +;; #### Assignment Expressions; + +; scopes on RHS, values +(assignment_expression + left: (_)@left + right: (_)@right)@assignment_expr { + + ; scopes flow into the RHS then back out to the whole expr, + ; augmented (in subsequent rules) by the LHS + edge @right.before_scope -> @assignment_expr.before_scope + edge @left.before_scope -> @right.after_scope + edge @assignment_expr.after_scope -> @left.after_scope + + ; value of the whole thing is value of the RHS + edge @assignment_expr.value -> @right.value +} + +; augmentation of scope via identifiers +(assignment_expression + left: (identifier)@left + right: (_)@right)@assignment_expr { + + ; augments the scope by adding a lookup edge, ie. a pop + attr @left.pop "pop" = @left, "definition" + edge @assignment_expr.after_scope -> @left.pop + edge @left.pop -> @right.value + + ; ensure the scope flows through the identifier + edge @left.after_scope -> @left.before_scope +} + +; assignment to direct fields on `this` +(assignment_expression + left: (member_expression + object:(this)@this + property:(_)@property) + right: (_)@right)@assignment_expr { + + ; HACK + attr @this.drop "drop" + edge @this.drop -> @this.pop + attr @this.pop "pop" = "this" + attr @this.pop_dot "pop" = "." + attr @property.pop "pop" = @property, "definition" + edge @assignment_expr.after_scope -> @this.drop + edge @assignment_expr.after_scope -> @this.pop + edge @this.pop -> @this.pop_dot + edge @this.pop_dot -> @property.pop + edge @property.pop -> @right.value +} + +; augmentation of scope via _destructuring_patterns +(assignment_expression + left: [(object_pattern) (array_pattern)]@left + right: (_)@right)@assignment_expr { + + ; scope flows from LHS into pattern then back to assignment + edge @left.before_scope -> @right.after_scope + edge @assignment_expr.after_scope -> @left.after_scope +} + + + +;; #### Augmented Assignment Expressions + +(augmented_assignment_expression + left: (_)@left + right: (_)@right)@augmented_assignment_expr { + + ; scopes flow into the RHS then back out to the whole expr, augmented by the LHS + edge @right.before_scope -> @augmented_assignment_expr.before_scope + edge @augmented_assignment_expr.after_scope -> @right.after_scope +} + +(augmented_assignment_expression + left:(identifier)@left + right:(_)@right)@augmented_assignment_expr { + + ; augment the scope + attr @left.pop "pop" = @left, "definition" + attr @left.push "push" = @left, "reference" + edge @left.push -> @augmented_assignment_expr.before_scope + edge @left.pop -> @left.push + edge @left.pop -> @right.value + edge @augmented_assignment_expr.after_scope -> @left.pop +} + + +;; #### Comma Operator / Sequence Expressions + +(sequence_expression + left: (_)@left + right: (_)@right)@sequence_expr { + + ; scopes propagate left to right + edge @left.before_scope -> @sequence_expr.before_scope + edge @right.before_scope -> @left.after_scope + edge @sequence_expr.after_scope -> @right.after_scope + + ; the value is just the value of the right + edge @sequence_expr.value -> @right.value +} + + +;; #### Ternary Expression + +(ternary_expression + condition: (_)@condition + consequence: (_)@consequence + alternative: (_)@alternative)@ternary_expr { + + ; scopes propagate into condition, then into each branch + edge @condition.before_scope -> @ternary_expr.before_scope + edge @consequence.before_scope -> @condition.after_scope + edge @alternative.before_scope -> @condition.after_scope + edge @ternary_expr.after_scope -> @consequence.after_scope + edge @ternary_expr.after_scope -> @alternative.after_scope + + ; value of the whole thing is a conditional value from the operands + edge @ternary_expr.value -> @consequence.value + edge @ternary_expr.value -> @alternative.value +} + + + +;; #### Yield + +(yield_expression (_)@yielded_expr)@yield_expr { + ; scopes flow in to the yielded expression then back out + edge @yielded_expr.before_scope -> @yield_expr.before_scope + edge @yield_expr.after_scope -> @yielded_expr.after_scope + + ; yield expressions hook up to the call node of the function value + edge @yield_expr::return_or_yield -> @yielded_expr.value +} + + + +;; #### Class Expressions + +(class + body:(_)@body)@class { + + edge @body.before_scope -> @class.before_scope + edge @class.value -> @body.after_scope + edge @class.after_scope -> @class.before_scope +} + +(class + name:(_)@name + body:(_)@body)@class { + + attr @name.pop "syntax_type" = "class" + + attr @name.pop "pop" = @name, "definition" + edge @body.before_scope -> @name.pop + edge @name.pop -> @class.value +} + +(class + (class_heritage (_)@name))@class { + + edge @name.before_scope -> @class.before_scope + edge @class.value -> @name.value +} + + + +;; ## Patterns + +;; Patterns introduce at least two interesting problems to the task of name +;; resolution. On the one hand, patterns by themselves are rich in structure +;; and binding possibilities. On the other, they function to pull apart +;; structure in ways that we would like to make use of in resolving names. Let's +;; look at these in order. + +;; ### Binding Possibilities + +;; If names could only be bound directly either on the LHS of an assignment, or +;; as the formal parameters to a function, or in related places like as +;; arguments to increment or decrement operators, then there would be little +;; trouble saying where a name is bound. But consider a destructuring assignment +;; such as this: + +;; ``````javascript +;; let [x,y,z] = arr; +;; `````` + +;; This assignment has variable names on the LHS of an assignment, sure, but not +;; directly as the LHS. Rather they're buried down inside a pattern. Here they +;; aren't very deep, just one node below the root of the LHS, but they can be +;; arbitrarily far down: + +;; ``````javascript +;; let [x, [y, [z, w], q], r] = arr; +;; `````` + +;; On top of this, patterns in JavaScript permit default assignments, such as + +;; ``````javascript +;; let [x, y = 1] = arr; +;; `````` + +;; These default values can be the result of a computation itself containing +;; variables, such as + +;; ``````javascript +;; let [x, y = 2*z] = arr; +;; `````` + +;; Additionally, those variables referenced in the default value are evaluated +;; *after* the RHS of the assignment. In the following code, `z` is incremented +;; and becomes `2`, and then `x` is assigned to that value. The array on the RHS +;; is only one element long, so the `y` variable gets assigned the default value +;; of `2*z`, which is computed *after* the increment, and so is `2*2` or `4`. + +;; ``````javascript +;; let z = 1; +;; let [x, y = 2*z] = [z++]; +;; `````` + +;; To complicated matters further, the default value can reference the *bound +;; variables to its left*. For instance: + +;; ``````javascript +;; let [x, y = x+1] = arr; +;; `````` + +;; All of this leads to some very interesting and tricky problems for name +;; resolution. The flow of the environment is as follows: First, the environment +;; flows into the RHS of the assignment and is updated by whatever evaluations +;; happen there, then it flows out of the RHS and into the LHS, where it goes +;; through each pattern in the LHS parse tree, in a left-to-right, depth-first +;; traversal. Patterns with no default assignments do nothing to the environment +;; but patterns with a default will pass the environment to the default value, +;; where it may be updated by the evaluation, and then passed further along. +;; Each variable, whether bare or on the left of an assignment, also has to +;; extend the environment because those variables come into scope further along. + +;; ### Structure Decomposition + +;; Let's now look at how patterns decompose structure. Let's consider the effect +;; of an assignment such as this: + +;; ``````javascript +;; let [x,y] = [1,2]; +;; `````` + +;; This assignment binds `x` to `1` and `y` to `2`. It's equivalent to doing + +;; ``````javascript +;; let x = 1, y = 2; +;; `````` + +;; Except, unlike the latter, the array destructuring does not have any obvious +;; pairing up of the names with the expressions that give them their values. +;; Now, perhaps there's some clever hack we can perform for this special case +;; where the RHS is a structure like `[1,2]` where it's manifestly clear out to +;; pair things up, but of course the RHS can come from anywhere. It can come +;; from a local variable assignment: + +;; ``````javascript +;; let arr = [1,2]; +;; let [x,y] = arr; +;; `````` + +;; Or a function call: + +;; ``````javascript +;; function foo(arr) { +;; let [x,y] = arr; +;; ... +;; } +;; foo([1,2]); +;; `````` + +;; Or any other number of places. We would like *all* of these to permit at +;; least *some* amount of name resolution so that we can find that `x` is `1` +;; and `y` is `2`. This should extend also to objects, not just arrays. + +;; The approach we take is to recognize a general pattern of equivalence, which +;; the above double-let assignment is related special case. For arrays, all +;; destructuring assignments of the form + +;; ``````javascript +;; let [..., pat_i, ...] = arr; +;; `````` + +;; are equivalent to + +;; ``````javascript +;; let pat_i = arr[i]; +;; `````` + +;; For any pattern `pat` and expression `arr`. So for instance the simple case +;; of a pattern expression and an array literal + +;; ``````javascript +;; let [x,y] = [1,2]; +;; `````` + +;; is equivalent to a pair of lets + +;; ``````javascript +;; let x = [1,2][0]; +;; let y = [1,2][1]; +;; `````` + +;; Modulo any change in side effects from duplicating the array syntactically, +;; these two are equivalent and this would be a valid code transformation. Or if +;; the pattern were an embedded array destructuring like so: + +;; ``````javascript +;; let [x, [y,z]] = [1, [2,3]]; +;; `````` + +;; then this would be equivalent to + +;; ``````javascript +;; let x = [1, [2,3]][0]; +;; let [y,z] = [1, [2,3]][1]; +;; `````` + +;; And of course the second let here would similarly unfold to be equivalent to +;; a pair of assignments, giving us + +;; ``````javascript +;; let x = [1, [2,3]][0]; +;; let y = [1, [2,3]][1][0]; +;; let z = [1, [2,3]][1][1]; +;; `````` + +;; Similarly for objects, we have the following destructuring equivalence that +;; says an assignment like this: + +;; ``````javascript +;; let {..., k: pat, ...} = obj; +;; `````` + +;; is equivalent to + +;; ``````javascript +;; let pat = obj[k]; +;; `````` + +;; for all patterns `pat` and expressions `obj`. + +;; This lets us then conclude that whatever the graphs are that we generate for +;; patterns ought to be equivalent to the graphs we would general for using +;; array indexing and object indexing. Since array and object indexing are fully +;; capable of participating in name resolution, if we can achieve this +;; equivalence, patterns can also fully participate as well, and we'll be able +;; to say that the assignment `let [x,y] = [1,2]` yields the name `x` resolving +;; to `1` and `y` to `2`, as well as many many more complicated cases. + +;; As mentioned in the intro to this doc, assignments point to values. The +;; simplest way to do this, in the absence of patterns, is just to have an edge +;; from the after scope of the assignment to a pop node for the variable, +;; and then to the value node of the RHS, so for `let x = 1;` it'd be like so: + +;; `````` +;; after_scope ---> POP "x" ---> value_node_for_1 +;; `````` + +;; But the above discussion of destructuring complicates this. What we do to +;; address this is introduce the notion of a "covalue". Just as we can say that +;; an expression *has* a value, or produces a value, etc., we'll say that a +;; pattern *consumes* a value. Expressions have values going "out", while +;; patterns have values coming "in". And so like expressions have an associated +;; `value` node in the graph, patterns have an associated `covalue` node. The +;; covalue corresponds to an incoming value. + +;; We build covalues similar to how we build values. Consider the value for an +;; array such as `["foo", "bar"]`, which will be a scope node with pop nodes +;; going out to the values of the strings, like so: + +;; `````` +;; ,---> POP 0 ---> value_node_of_foo +;; value_node_of_the_array ---| +;; `---> POP 1 ---> value_node_of_bar +;; `````` + +;; Similarly, a covalue for an array pattern will also have nodes for the +;; sub-patterns and nodes for the first and second indexes. But rather than pop +;; nodes, which show you where the 0th and 1st elements are, they'll be push +;; nodes to establish the lookup of those elements. The edges will therefore +;; go the other way around. So for a pattern like `[x,y]`, we have the graph + +;; `````` +;; ,--- PUSH 0 <--- covalue_node_of_x +;; covalue_node_of_the_pattern <---| +;; `--- PUSH 1 <--- covalue_node_of_y +;; `````` + +;; For readers familiar with category theory's notion of duality, this explains +;; why these are called "covalues". The general schema here is that where values +;; have pops, covalues have pushes, and all the arrows get flipped. + +;; ### Attributes Defined on Patterns +;; TODO + +;; ### Pattern Queries + +;; #### Variable Patterns + +; scope propagation through identifier patterns +(pattern/identifier)@ident_pat { + + ; scope flows through, binding via a pop edge that goes to an unknown value + attr @ident_pat.pop "pop" = @ident_pat, "definition" + edge @ident_pat.pop -> @ident_pat.covalue + edge @ident_pat.after_scope -> @ident_pat.before_scope + edge @ident_pat.after_scope -> @ident_pat.pop + + edge @ident_pat.new_bindings -> @ident_pat.pop +} + + +;; #### Object Patterns + +; LATER-TODO scope propagation through empty object patterns +; currently unsupported by tree sitter queries +; THIS IS A HUGE HACK AND MUST BE FIXED +(object_pattern)@object_pat { + edge @object_pat.after_scope -> @object_pat.before_scope +} + +; scope propagation through object patterns, first entry +(object_pattern + . + (_)@first_entry)@object_pat { + + ; scope propagates from object pattern to entry + edge @first_entry.before_scope -> @object_pat.before_scope +} + +; scope propagation through object patterns, between entries +(object_pattern + (_)@left_entry + . + (_)@right_entry) { + + ; scope propagates from left entry to right entry + edge @right_entry.before_scope -> @left_entry.after_scope +} + +; scope propagation through object patterns, last entry +(object_pattern + (_)@last_entry + .)@object_pat { + + ; scope propagates out from last entry to object pattern + edge @object_pat.after_scope -> @last_entry.after_scope +} + +; covalue propagation through object patterns +(object_pattern + (_)@entry)@object_pat { + + ; covalues flow into entries unchanged + edge @entry.covalue -> @object_pat.covalue + + edge @object_pat.new_bindings -> @entry.new_bindings +} + +; object entry pair patterns +(pair_pattern + key:(_)@key + value:(_)@value_pat)@pair_pat { + + ; covalues flow in dotted + attr @key.push_dot "push" = "." + edge @value_pat.covalue -> @key.push + edge @key.push -> @key.push_dot + edge @key.push_dot -> @pair_pat.covalue + ; scope flows into value pattern then back out + edge @value_pat.before_scope -> @pair_pat.before_scope + edge @pair_pat.after_scope -> @value_pat.after_scope + + edge @pair_pat.new_bindings -> @value_pat.new_bindings +} + +(pair_pattern + key:(property_identifier)@key)@pair_pattern { + + attr @key.push "push" = @key, "reference" +} + +(pair_pattern + key:(string)@key)@pair_pattern { + + attr @key.push "push" = (replace @key "\"" ""), "reference" +} + +; LATER-TODO the left pattern has to be a name, it cant be another pattern +; object entry assignment patterns +(object_assignment_pattern + left:(_)@left_pat + right:(_)@right_expr)@object_assignment_pat { + + ; scope flows both THROUGH and AROUND the RHS, because it's a + ; by-passable default not a guaranteed value + + ; here we go around + edge @left_pat.before_scope -> @object_assignment_pat.before_scope + + ; and here we go through + edge @right_expr.before_scope -> @object_assignment_pat.before_scope + edge @left_pat.before_scope -> @right_expr.after_scope + + ; and in either case we come out the LHS + edge @object_assignment_pat.after_scope -> @left_pat.after_scope + + ; covalues flow both in from the outside and also from the right expression + edge @left_pat.covalue -> @object_assignment_pat.covalue + edge @left_pat.covalue -> @right_expr.value + + edge @object_assignment_pat.new_bindings -> @left_pat.new_bindings + +} + +; if the object assignment pattern happens to have an identifier on the LHS it also binds +(object_assignment_pattern + left:(shorthand_property_identifier_pattern)@left_pat + right:(_)@right_expr)@object_assignment_pat { + + edge @left_pat.after_scope -> @left_pat.before_scope + + attr @left_pat.push "push" = @left_pat, "reference" + attr @left_pat.push_dot "push" = "." + attr @left_pat.pop "pop" = @left_pat, "definition" + edge @left_pat.pop -> @left_pat.push + edge @left_pat.push -> @left_pat.push_dot + edge @left_pat.push_dot -> @left_pat.covalue + edge @object_assignment_pat.after_scope -> @left_pat.pop + + edge @object_assignment_pat.new_bindings -> @left_pat.pop +} + + +;; #### Array Patterns + +; LATER-TODO scope propagation through empty array patterns +; currently unsupported by tree sitter queries +; THIS IS A HUGE HACK AND MUST BE FIXED +(array_pattern)@array_pat { + edge @array_pat.after_scope -> @array_pat.before_scope +} + +; scope propagation through array patterns, first element +(array_pattern + . + (_)@first_el_pat)@array_pat { + + ; scope flows into the first element + edge @first_el_pat.before_scope -> @array_pat.before_scope +} + +; scope propagation through array patterns, between element +(array_pattern + (_)@left_el_pat + . + (_)@right_el_pat) { + + ; scope flows from left to right + edge @right_el_pat.before_scope -> @left_el_pat.after_scope +} + +; scope propagation through array patterns, last element +(array_pattern + (_)@last_el_pat + .)@array_pat { + + ; scope flow out from the last element + edge @array_pat.after_scope -> @last_el_pat.after_scope +} + +; array pattern elements +(array_pattern (_)@element_pat)@array_pat { + attr @element_pat.element_index_push "push" = (child-index @element_pat), "reference" + attr @array_pat.element_index_push_dot "push" = "." + edge @element_pat.covalue -> @element_pat.element_index_push + edge @element_pat.element_index_push -> @array_pat.element_index_push_dot + edge @array_pat.element_index_push_dot -> @array_pat.covalue + + edge @array_pat.new_bindings -> @element_pat.new_bindings +} + + +;; #### Assignment Patterns + +; scope propagation through assignment patterns +(assignment_pattern + left:(_)@left_pat + right:(_)@right_expr)@assignment_pat { + + ; scope flows both THROUGH and AROUND the RHS, because it's a + ; by-passable default not a guaranteed value + + ; here we go around + edge @left_pat.before_scope -> @assignment_pat.before_scope + + ; and here we go through + edge @right_expr.before_scope -> @assignment_pat.before_scope + edge @left_pat.before_scope -> @right_expr.after_scope + + ; the pattern's covalue is the whole thing's, and also the RHS + edge @left_pat.covalue -> @assignment_pat.covalue + edge @left_pat.covalue -> @right_expr.value + + ; and in either case we come out the LHS + edge @assignment_pat.after_scope -> @left_pat.after_scope + + edge @assignment_pat.new_bindings -> @left_pat.new_bindings +} + + +;; #### Rest Patterns + +(rest_pattern (_)@name)@rest_pat { + ; scope flows through, binding via a pop edge that goes to an unknown value + + attr @rest_pat.pop "pop" = @name, "definition" + edge @rest_pat.after_scope -> @rest_pat.before_scope + edge @rest_pat.after_scope -> @rest_pat.pop +} + + + +;; ## Special Cases +;; +;; There are a number of annoying features that libraries make use of to +;; effectively add features to JavaScript. While they don't technically change +;; the language in any way, they're broad design patterns that are meant to be +;; used *as if* these things were more language level than not. These often make +;; it hard to do analysis without actually running code, and so instead, we +;; define some special case queries that treat these techniques as if they were +;; indeed core features of the language. +;; +;; ### Extend +;; +;; The extend method is a mass assignment of values to keys on objects and gets +;; used a bunch for building module export objects. We special case it here so +;; that we can do lookup on it because the extend method itself is dependent on +;; state and mutability, and has no good analytical explanation within the +;; Stack Graph formalism. +;; +;; Since we can't extend the actual value, but only the syntactic references to +;; it in the SG formalism, we treat extend as a kind of shadowing binder, +;; similar to how we treat `+=` or `*=`. + +( + (call_expression + function: (member_expression + object: (identifier)@object + property: (_)@extend) + arguments: (arguments (object)@new_fields))@call_expr + (#eq? @extend "extend") +) { + + attr @object.pop "pop" = @object, "definition" + edge @call_expr.after_scope -> @object.pop + edge @object.pop -> @new_fields.value + +} + +;; ### CommonJS-style Exports + +;; CommonJS introduced an export style for pre-ES6 JavaScript that permitted +;; modules to export functions using an exports object bound to a top-level +;; variable `exports`. For instance, to export something as `foo`, we would do: + +;; ``````javascript +;; exports.foo = 1; +;; `````` + +;; If we then imported with `require`, the exports object would have `foo` as +;; a field. Alternatively, we can also specify the entire export object, using + +;; ``````javascript +;; module.exports = my_exported_object; +;; `````` + +( + (assignment_expression + left: (member_expression + object:(identifier)@exports + property:(_)@property) + right: (_)@right)@assignment_expr + (#eq? @exports "exports") +) { + + attr @property.pop "pop" = @property, "definition" + attr @property.pop_dot "pop" = "." + edge @assignment_expr::exports -> @property.pop_dot + edge @property.pop_dot -> @property.pop + edge @property.pop -> @right.value +} + +( + (assignment_expression + left: (member_expression + object:(identifier)@module + property:(_)@exports) + right: (_)@right)@assignment_expr + (#eq? @module "module") + (#eq? @exports "exports") +) { + + edge @assignment_expr::exports -> @right.value +} + +;; ## CommonJS-style Imports + +;; Similar to exports, CommonJS also defines a way to do imports. In general, +;; these look like `require(expr)`, but in practice the expression is a string +;; constant, which is the only case we hand. + +( + (call_expression + function:(_)@require + arguments:(arguments (string)@mod_name))@call_expr + (#eq? @require "require") +) { + + scan @mod_name { + "\"([^/\"]+)\.js\"$" { + attr @mod_name.push "push" = $1 + } + } + + attr @mod_name.module_guard "push" = "GUARD:EXPORTS" + edge @call_expr.value -> @mod_name.module_guard + edge @mod_name.module_guard -> @mod_name.push + edge @mod_name.push -> root + +} + + +;; ## Definiens Rules + +;; These rules explain how defined names relate to syntactic definitions +;; of various forms. Sometimes that's declared function names mapping to +;; the entire function declaration, and sometimes that's variables in an +;; assignment being mapped to the thing it's assigned to. The purpose of +;; these is not to augment stack graphs, per se, but to permit syntax +;; oriented tools that need to know about approximate call graphs, etc. + +;; ### Basic Definiens Rules + +;; These rules are all about declarations and terms that have the names +;; directly in them. + +(class_declaration + name:(_)@name + body:(_)@body)@class_decl { + + attr @name.pop "definiens" = @class_decl + +} + +(function_declaration + name:(_)@name + parameters:(_)@call_sig + body:(_)@body)@fun_decl { + + attr @name.pop "definiens" = @fun_decl + +} + +(generator_function_declaration + name:(_)@name + parameters:(_)@call_sig + body:(_)@body)@fun_decl { + + attr @name.pop "definiens" = @fun_decl + +} + +(method_definition + name:(_)@name + parameters:(_)@call_sig + body:(_)@body)@method_def { + + attr @name.pop "definiens" = @method_def + +} + +(function + name:(_)@name + parameters:(_)@call_sig)@fun { + + attr @name.pop "definiens" = @fun + +} + +(generator_function + name:(_)@name + parameters:(_)@call_sig)@fun { + + attr @name.pop "definiens" = @fun + +} + +(class + name:(_)@name + body:(_)@body)@class { + + attr @name.pop "definiens" = @class + +} + +;; ### Assignment-like Rules + +;; These rules make up for the fact that JavaScript permits way more +;; kinds of definitions/declarations than just those that show up in +;; syntactic declarations of the thing in question. + +;; These rules are currently way less precise than we would like but +;; do provide at least some information about definiens for these +;; kinds of definitions. + +(assignment_expression + left: (identifier)@left + right: [ + (function) + (generator_function) + (arrow_function) + ]@right) { + + attr @left.pop "definiens" = @right + +} + +(assignment_expression + left: (member_expression property:(_)@left) + right: [ + (function) + (generator_function) + (arrow_function) + ]@right) { + + attr @left.ignore_guard "pop" = "GUARD:GANDALF" + attr @left.definiens_hook "pop" = @left, "definition" + attr @left.definiens_hook "definiens" = @right + edge root -> @left.ignore_guard + edge @left.ignore_guard -> @left.definiens_hook +} + +(variable_declaration + (variable_declarator + name:(identifier)@name + value: [ + (function) + (generator_function) + (arrow_function) + ]@initializer)) { + + attr @name.pop "definiens" = @initializer + +} + +(lexical_declaration + (variable_declarator + name:(identifier)@name + value: [ + (function) + (generator_function) + (arrow_function) + ]@initializer)) { + + attr @name.pop "definiens" = @initializer + +} + +(pair + key: (_)@name + value: [ + (function) + (generator_function) + (arrow_function) + ]@value) { + +attr @name.ignore_guard "pop" = "GUARD:GANDALF" +attr @name.definiens_hook "pop" = @name, "definition" +attr @name.definiens_hook "definiens" = @value +edge root -> @name.ignore_guard +edge @name.ignore_guard -> @name.definiens_hook + +} \ No newline at end of file From 2280a1d9d9db97eadca9eba3d65d8dfcb9627b56 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 13:02:48 +0200 Subject: [PATCH 020/500] [conv] shorthands --- .../src/stack-graphs-conv.tsg | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index f56040561..2ce2034bf 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -191,6 +191,25 @@ ;; - `GUARD:EXPORTS` - used for the names exported by the module ;; - `GUARD:DEFAULT` - used for the default export value +;; ## Attribute Shorthands + +attribute node_definition = node => type = "pop_symbol", node_symbol = node, is_definition +attribute node_reference = node => type = "push_symbol", node_symbol = node, is_reference +attribute pop_node = node => type = "pop_symbol", node_symbol = node +attribute pop_scoped_node = node => type = "pop_scoped_symbol", node_symbol = node +attribute pop_scoped_symbol = symbol => type = "pop_scoped_symbol", symbol = symbol +attribute pop_symbol = symbol => type = "pop_symbol", symbol = symbol +attribute push_node = node => type = "push_symbol", node_symbol = node +attribute push_scoped_node = node => type = "push_scoped_symbol", node_symbol = node +attribute push_scoped_symbol = symbol => type = "push_scoped_symbol", symbol = symbol +attribute push_symbol = symbol => type = "push_symbol", symbol = symbol +attribute scoped_node_definition = node => type = "pop_scoped_symbol", node_symbol = node, is_definition +attribute scoped_node_reference = node => type = "push_scoped_symbol", node_symbol = node, is_reference +attribute symbol_definition = symbol => type = "pop_symbol", symbol = symbol, is_definition +attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, is_reference + +attribute node_symbol = node => symbol = (source-text node), source_node = node + ;; ## Nodes @@ -3280,4 +3299,4 @@ attr @name.definiens_hook "definiens" = @value edge root -> @name.ignore_guard edge @name.ignore_guard -> @name.definiens_hook -} \ No newline at end of file +} From 37f4665e0fb9db6b8425f3242f33bb0ea0e3943e Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 13:03:03 +0200 Subject: [PATCH 021/500] [conv] nodes --- .../src/stack-graphs-conv.tsg | 66 ++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 2ce2034bf..b078e0ccb 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -214,7 +214,71 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ## Nodes (_)@node { - + @node.after_scope + @node.arg_arguments + @node.arg_arguments_dot + @node.arg_index + @node.arg_scope + @node.arg_scope_no_this + @node.arg_this + @node.arguments_pop + @node.arguments_push + @node.before_scope + @node.boundvar_pop + @node.call + @node.constructor + @node.constructor_guard + @node.covalue + @node.default_guard + @node.definiens_hook + @node.drop + @node.element_index_push + @node.element_index_push_dot + @node.element_pop_dot + @node.exports + @node.exports_pop + @node.field_pop_dot + @node.guard_default + @node.guard_this + @node.ignore_guard + @node.index_pop + @node.method_value + @node.method_value_arg_scope + @node.method_value_call + @node.method_value_drop + @node.method_value_return + @node.method_value_this + @node.method_value_this_guard + @node.module_guard + @node.module_pop + @node.module_scope + @node.new_bindings + @node.number_prototype + @node.number_prototype_toString_method_value + @node.number_prototype_toString_method_value_return + @node.number_prototype_valueOf_method_value + @node.pop + @node.pop_dot + @node.pop_guard_default + @node.push + @node.push_dot + @node.push_exports_guard + @node.push_guard_default + @node.push_guard_exports + @node.return_guard + @node.rhsvar_before_scope + @node.rhsvar_value + @node.source + @node.string_prototype + @node.this_pop + @node.this_push + @node.value + @node.value_arg_scope + @node.value_call + @node.value_drop + @node.value_return + @node.value_this + @node.value_this_guard } From c2357ed7ebc2ff6657ea680897d7386ec9bb1946 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 13:04:36 +0200 Subject: [PATCH 022/500] [conv] global vars --- .../src/stack-graphs-conv.tsg | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index b078e0ccb..eef4b1aad 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -191,6 +191,13 @@ ;; - `GUARD:EXPORTS` - used for the names exported by the module ;; - `GUARD:DEFAULT` - used for the default export value +;; ## Global Variables + +global FILE_PATH +global ROOT_NODE +global JUMP_TO_SCOPE_NODE + + ;; ## Attribute Shorthands attribute node_definition = node => type = "pop_symbol", node_symbol = node, is_definition @@ -290,17 +297,17 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ### Program Queries (program)@prog { - scan filepath { + scan FILE_PATH { "([^/]+)\.js$" { attr @prog.module_pop "definition", "pop" = $1 attr @prog.module_pop "no_span" } } - edge @prog.before_scope -> root + edge @prog.before_scope -> ROOT_NODE attr @prog.module_scope "pop" = "GUARD:MODULE" - edge root -> @prog.module_pop + edge ROOT_NODE -> @prog.module_pop edge @prog.module_pop -> @prog.module_scope edge @prog.module_scope -> @prog.after_scope @@ -393,7 +400,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n } } edge @source.push_exports_guard -> @source.push - edge @source.push -> root + edge @source.push -> ROOT_NODE edge @export_clause.before_scope -> @export_stmt.before_scope edge @export_stmt.after_scope -> @export_clause.after_scope @@ -580,7 +587,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @export_statement::exports -> @source.push_exports_guard edge @source.push_exports_guard -> @source.push - edge @source.push -> root + edge @source.push -> ROOT_NODE } @@ -604,7 +611,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @alias.pop -> @alias.pop_dot edge @alias.pop_dot -> @source.push_exports_guard edge @source.push_exports_guard -> @source.push - edge @source.push -> root + edge @source.push -> ROOT_NODE } @@ -664,7 +671,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n } attr @source.push_guard_exports "push" = "GUARD:EXPORTS" edge @source.push_guard_exports -> @source.push - edge @source.push -> root + edge @source.push -> ROOT_NODE edge @import_clause.source -> @source.push_guard_exports } @@ -766,7 +773,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; attr @mod_name.push "push" = $1, "reference" ; } ; } -; edge @mod_name.push -> root +; edge @mod_name.push -> ROOT_NODE ; ; attr @name "push", "reference" ; attr @name.push_dot "push" = "." @@ -3208,7 +3215,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr @mod_name.module_guard "push" = "GUARD:EXPORTS" edge @call_expr.value -> @mod_name.module_guard edge @mod_name.module_guard -> @mod_name.push - edge @mod_name.push -> root + edge @mod_name.push -> ROOT_NODE } @@ -3319,7 +3326,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr @left.ignore_guard "pop" = "GUARD:GANDALF" attr @left.definiens_hook "pop" = @left, "definition" attr @left.definiens_hook "definiens" = @right - edge root -> @left.ignore_guard + edge ROOT_NODE -> @left.ignore_guard edge @left.ignore_guard -> @left.definiens_hook } @@ -3360,7 +3367,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr @name.ignore_guard "pop" = "GUARD:GANDALF" attr @name.definiens_hook "pop" = @name, "definition" attr @name.definiens_hook "definiens" = @value -edge root -> @name.ignore_guard +edge ROOT_NODE -> @name.ignore_guard edge @name.ignore_guard -> @name.definiens_hook } From b6d70dd3246b1c3e48b4875feda13870430df1d4 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 13:08:31 +0200 Subject: [PATCH 023/500] [conv] nodes --- .../src/stack-graphs-conv.tsg | 130 +++++++++--------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index eef4b1aad..ab343a907 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -221,71 +221,71 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ## Nodes (_)@node { - @node.after_scope - @node.arg_arguments - @node.arg_arguments_dot - @node.arg_index - @node.arg_scope - @node.arg_scope_no_this - @node.arg_this - @node.arguments_pop - @node.arguments_push - @node.before_scope - @node.boundvar_pop - @node.call - @node.constructor - @node.constructor_guard - @node.covalue - @node.default_guard - @node.definiens_hook - @node.drop - @node.element_index_push - @node.element_index_push_dot - @node.element_pop_dot - @node.exports - @node.exports_pop - @node.field_pop_dot - @node.guard_default - @node.guard_this - @node.ignore_guard - @node.index_pop - @node.method_value - @node.method_value_arg_scope - @node.method_value_call - @node.method_value_drop - @node.method_value_return - @node.method_value_this - @node.method_value_this_guard - @node.module_guard - @node.module_pop - @node.module_scope - @node.new_bindings - @node.number_prototype - @node.number_prototype_toString_method_value - @node.number_prototype_toString_method_value_return - @node.number_prototype_valueOf_method_value - @node.pop - @node.pop_dot - @node.pop_guard_default - @node.push - @node.push_dot - @node.push_exports_guard - @node.push_guard_default - @node.push_guard_exports - @node.return_guard - @node.rhsvar_before_scope - @node.rhsvar_value - @node.source - @node.string_prototype - @node.this_pop - @node.this_push - @node.value - @node.value_arg_scope - @node.value_call - @node.value_drop - @node.value_return - @node.value_this - @node.value_this_guard + node @node.after_scope + node @node.arg_arguments + node @node.arg_arguments_dot + node @node.arg_index + node @node.arg_scope + node @node.arg_scope_no_this + node @node.arg_this + node @node.arguments_pop + node @node.arguments_push + node @node.before_scope + node @node.boundvar_pop + node @node.call + node @node.constructor + node @node.constructor_guard + node @node.covalue + node @node.default_guard + node @node.definiens_hook + node @node.drop + node @node.element_index_push + node @node.element_index_push_dot + node @node.element_pop_dot + node @node.exports + node @node.exports_pop + node @node.field_pop_dot + node @node.guard_default + node @node.guard_this + node @node.ignore_guard + node @node.index_pop + node @node.method_value + node @node.method_value_arg_scope + node @node.method_value_call + node @node.method_value_drop + node @node.method_value_return + node @node.method_value_this + node @node.method_value_this_guard + node @node.module_guard + node @node.module_pop + node @node.module_scope + node @node.new_bindings + node @node.number_prototype + node @node.number_prototype_toString_method_value + node @node.number_prototype_toString_method_value_return + node @node.number_prototype_valueOf_method_value + node @node.pop + node @node.pop_dot + node @node.pop_guard_default + node @node.push + node @node.push_dot + node @node.push_exports_guard + node @node.push_guard_default + node @node.push_guard_exports + node @node.return_guard + node @node.rhsvar_before_scope + node @node.rhsvar_value + node @node.source + node @node.string_prototype + node @node.this_pop + node @node.this_push + node @node.value + node @node.value_arg_scope + node @node.value_call + node @node.value_drop + node @node.value_return + node @node.value_this + node @node.value_this_guard } From 3dcfc56a491c969ae9082d2c1486bcb9bc68d807 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 13:10:07 +0200 Subject: [PATCH 024/500] [conv] attr --- .../src/stack-graphs-conv.tsg | 428 +++++++++--------- 1 file changed, 214 insertions(+), 214 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index ab343a907..fa2a87b11 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -77,7 +77,7 @@ ;; ``````stgdoc ;; (number)@num { -;; attr @num.value "pop" = "NUM_VAL" +;; attr (@num.value) "pop" = "NUM_VAL" ;; } ;; `````` @@ -106,7 +106,7 @@ ;; ``````stgdoc ;; (number)@num { -;; attr @num.value "pop" = "NUM_VAL" +;; attr (@num.value) "pop" = "NUM_VAL" ;; edge @num.value -> @num::number_prototype ;; } ;; `````` @@ -154,7 +154,7 @@ ;; ;; edge @prog.number_prototype -> @prog.number_prototype_toString_method_value ;; edge @prog.number_prototype_toString_method_value -> @prog.number_prototype_toString_method_value_return -;; attr @prog.number_prototype_toString_method_value_return "pop" = "GUARD:RETURN" +;; attr (@prog.number_prototype_toString_method_value_return) "pop" = "GUARD:RETURN" ;; edge @prog.number_prototype_toString_method_value_return -> @prog.string_prototype ;; ;; ... @@ -299,29 +299,29 @@ attribute node_symbol = node => symbol = (source-text node), source_n (program)@prog { scan FILE_PATH { "([^/]+)\.js$" { - attr @prog.module_pop "definition", "pop" = $1 - attr @prog.module_pop "no_span" + attr (@prog.module_pop) "definition", "pop" = $1 + attr (@prog.module_pop) "no_span" } } edge @prog.before_scope -> ROOT_NODE - attr @prog.module_scope "pop" = "GUARD:MODULE" + attr (@prog.module_scope) "pop" = "GUARD:MODULE" edge ROOT_NODE -> @prog.module_pop edge @prog.module_pop -> @prog.module_scope edge @prog.module_scope -> @prog.after_scope - attr @prog "no_span" - attr @prog.module_pop "no_span" - attr @prog.module_scope "no_span" - attr @prog.exports "no_span" - attr @prog.exports_pop "no_span" - attr @prog.before_scope "no_span" - attr @prog.after_scope "no_span" + attr (@prog) "no_span" + attr (@prog.module_pop) "no_span" + attr (@prog.module_scope) "no_span" + attr (@prog.exports) "no_span" + attr (@prog.exports_pop) "no_span" + attr (@prog.before_scope) "no_span" + attr (@prog.after_scope) "no_span" let @prog::prog = @prog let @prog::exports = @prog.exports - attr @prog.exports_pop "pop" = "GUARD:EXPORTS" + attr (@prog.exports_pop) "pop" = "GUARD:EXPORTS" edge @prog.module_pop -> @prog.exports_pop edge @prog.exports_pop -> @prog.exports } @@ -393,10 +393,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @export_clause.source -> @source.push_exports_guard - attr @source.push_exports_guard "push" = "GUARD:EXPORTS" + attr (@source.push_exports_guard) "push" = "GUARD:EXPORTS" scan @source { "\"([^/\"]+)\.js\"$" { - attr @source.push "push" = $1 + attr (@source.push) "push" = $1 } } edge @source.push_exports_guard -> @source.push @@ -425,8 +425,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; TODO this doesn't support destructuring exports - attr @name.pop "pop" = @name, "definition" - attr @name.push "push" = @name + attr (@name.pop) "pop" = @name, "definition" + attr (@name.push) "push" = @name edge @export_stmt::exports -> @name.pop edge @name.pop -> @decl.value } @@ -499,8 +499,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n (#not-eq? @name "default") ) { - attr @name.pop "pop" = @name, "definition" - attr @name.push "push" = @name, "reference" + attr (@name.pop) "pop" = @name, "definition" + attr (@name.push) "push" = @name, "reference" edge @name.pop -> @name.push edge @name.push -> @export_specifier.source @@ -516,8 +516,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ) { - attr @alias.pop "pop" = @alias, "definition" - attr @name.push "push" = @name, "reference" + attr (@alias.pop) "pop" = @alias, "definition" + attr (@name.push) "push" = @name, "reference" edge @alias.pop -> @name.push edge @name.push -> @export_specifier.source @@ -533,8 +533,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ) { - attr @export_specifier.pop_guard_default "pop" = "GUARD:DEFAULT" - attr @export_specifier.push_guard_default "push" = "GUARD:DEFAULT" + attr (@export_specifier.pop_guard_default) "pop" = "GUARD:DEFAULT" + attr (@export_specifier.push_guard_default) "push" = "GUARD:DEFAULT" edge @export_specifier::exports -> @export_specifier.pop_guard_default edge @export_specifier.pop_guard_default -> @export_specifier.push_guard_default edge @export_specifier.push_guard_default -> @export_specifier.source @@ -550,8 +550,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ) { - attr @name.push "push" = @name - attr @export_specifier.guard_default "pop" = "GUARD:DEFAULT" + attr (@name.push) "push" = @name + attr (@export_specifier.guard_default) "pop" = "GUARD:DEFAULT" edge @name.push -> @export_specifier.source edge @export_specifier.guard_default -> @name.push edge @export_specifier::exports -> @export_specifier.guard_default @@ -563,7 +563,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (export_statement value:(_)@default_expr)@export_stmt { - attr @export_stmt.default_guard "pop" = "GUARD:DEFAULT", "definition" + attr (@export_stmt.default_guard) "pop" = "GUARD:DEFAULT", "definition" edge @default_expr.before_scope -> @export_stmt.before_scope edge @export_stmt.after_scope -> @default_expr.after_scope edge @export_stmt::exports -> @export_stmt.default_guard @@ -578,10 +578,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @export_statement.after_scope -> @export_statement.before_scope - attr @source.push_exports_guard "push" = "GUARD:EXPORTS" + attr (@source.push_exports_guard) "push" = "GUARD:EXPORTS" scan @source { "\"([^/\"]+)\.js\"$" { - attr @source.push "push" = $1 + attr (@source.push) "push" = $1 } } @@ -599,14 +599,14 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @export_statement.after_scope -> @export_statement.before_scope - attr @source.push_exports_guard "push" = "GUARD:EXPORTS" + attr (@source.push_exports_guard) "push" = "GUARD:EXPORTS" scan @source { "\"([^/\"]+)\.js\"$" { - attr @source.push "push" = $1 + attr (@source.push) "push" = $1 } } - attr @alias.pop "pop" = @alias, "definition" - attr @alias.pop_dot "pop" = "." + attr (@alias.pop) "pop" = @alias, "definition" + attr (@alias.pop_dot) "pop" = "." edge @export_statement::exports -> @alias.pop edge @alias.pop -> @alias.pop_dot edge @alias.pop_dot -> @source.push_exports_guard @@ -643,8 +643,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @namespace_import.after_scope -> @namespace_import.before_scope - attr @imported_as.pop "pop" = @imported_as, "definition" - attr @imported_as.pop_dot "pop" = "." + attr (@imported_as.pop) "pop" = @imported_as, "definition" + attr (@imported_as.pop_dot) "pop" = "." edge @imported_as.pop -> @imported_as.pop_dot edge @imported_as.pop_dot -> @namespace_import.source @@ -666,10 +666,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n scan @source { "\"([^/\"]+)\.js\"$" { - attr @source.push "push" = $1 + attr (@source.push) "push" = $1 } } - attr @source.push_guard_exports "push" = "GUARD:EXPORTS" + attr (@source.push_guard_exports) "push" = "GUARD:EXPORTS" edge @source.push_guard_exports -> @source.push edge @source.push -> ROOT_NODE edge @import_clause.source -> @source.push_guard_exports @@ -731,8 +731,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @import_specifier.after_scope -> @import_specifier.before_scope - attr @name.pop "pop" = @name, "definition" - attr @name.push "push" = @name, "reference" + attr (@name.pop) "pop" = @name, "definition" + attr (@name.push) "push" = @name, "reference" edge @name.pop -> @name.push edge @name.push -> @import_specifier.source edge @import_specifier.after_scope -> @name.pop @@ -751,8 +751,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @import_specifier.after_scope -> @import_specifier.before_scope - attr @alias.pop "pop" = @alias, "definition" - attr @name.push "push" = @name, "reference" + attr (@alias.pop) "pop" = @alias, "definition" + attr (@name.push) "push" = @name, "reference" edge @alias.pop -> @name.push edge @name.push -> @import_specifier.source edge @import_specifier.after_scope -> @alias.pop @@ -770,17 +770,17 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; ; scope passes through, augmented by the identifier ; scan @mod_name { ; "\"([^/\"]+)\.js\"$" { -; attr @mod_name.push "push" = $1, "reference" +; attr (@mod_name.push) "push" = $1, "reference" ; } ; } ; edge @mod_name.push -> ROOT_NODE ; -; attr @name "push", "reference" -; attr @name.push_dot "push" = "." +; attr (@name) "push", "reference" +; attr (@name.push_dot) "push" = "." ; edge @name.push_dot -> @mod_name.push ; edge @name -> @name.push_dot ; -; attr @alias "pop", "definition" +; attr (@alias) "pop", "definition" ; edge @alias -> @name ; ; edge @import_stmt.after_scope -> @alias @@ -797,8 +797,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @import_clause.after_scope -> @import_clause.before_scope - attr @default_name.pop "pop" = @default_name, "definition" - attr @default_name.push_guard_default "push" = "GUARD:DEFAULT" + attr (@default_name.pop) "pop" = @default_name, "definition" + attr (@default_name.push_guard_default) "push" = "GUARD:DEFAULT" edge @default_name.pop -> @default_name.push_guard_default edge @default_name.push_guard_default -> @import_clause.source @@ -836,7 +836,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (variable_declarator name:(identifier)@name))@decl { - attr @name.pop "pop", "definition" + attr (@name.pop) "pop", "definition" edge @decl.after_scope -> @name.pop } @@ -844,7 +844,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (variable_declarator name:(identifier)@name))@decl { - attr @name.pop "pop", "definition" + attr (@name.pop) "pop", "definition" edge @decl.after_scope -> @name.pop } @@ -917,30 +917,30 @@ attribute node_symbol = node => symbol = (source-text node), source_n parameters:(_)@call_sig body:(_)@body)@fun_decl { - attr @name.pop "syntax_type" = "function" + attr (@name.pop) "syntax_type" = "function" ; scope flows across the decl edge @fun_decl.after_scope -> @fun_decl.before_scope ; with an augmentation for the function - attr @name.pop "pop" = @name, "definition" + attr (@name.pop) "pop" = @name, "definition" edge @fun_decl.after_scope -> @name.pop edge @name.pop -> @fun_decl.value ; function values have drop nodes that handle closures, that points to the ; before scope for the function - attr @fun_decl.value_drop "drop" + attr (@fun_decl.value_drop) "drop" edge @fun_decl.value_drop -> @fun_decl.before_scope ; the call sig's before scope comes from the drop node then flows into the body edge @call_sig.before_scope -> @fun_decl.value_drop - attr @call_sig.this_pop "pop" = "this", "definition" - attr @call_sig.this_push "push" = "this" + attr (@call_sig.this_pop) "pop" = "this", "definition" + attr (@call_sig.this_push) "push" = "this" edge @call_sig.this_pop -> @call_sig.this_push edge @call_sig.this_push -> @fun_decl.value_arg_scope edge @call_sig.before_scope -> @call_sig.this_pop - attr @call_sig.arguments_pop "pop" = "arguments", "definition" - attr @call_sig.arguments_push "push" = "arguments" + attr (@call_sig.arguments_pop) "pop" = "arguments", "definition" + attr (@call_sig.arguments_push) "push" = "arguments" edge @call_sig.arguments_pop -> @call_sig.arguments_push edge @call_sig.arguments_push -> @fun_decl.value_arg_scope edge @call_sig.before_scope -> @call_sig.arguments_pop @@ -948,25 +948,25 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; function values have call nodes - attr @fun_decl.value_call "pop" = "()", "pop-scope" + attr (@fun_decl.value_call) "pop" = "()", "pop-scope" edge @fun_decl.value -> @fun_decl.value_call ; function values have return nodes which need to be visible for returns - attr @fun_decl.value_return "endpoint" - attr @fun_decl.value_return "pop" = "GUARD:RETURN" + attr (@fun_decl.value_return) "endpoint" + attr (@fun_decl.value_return) "pop" = "GUARD:RETURN" edge @fun_decl.value_call -> @fun_decl.value_return let @body::return_or_yield = @fun_decl.value_return ; method values have this nodes which need to be visible for constructor calls - attr @fun_decl.value_this "push" = "this" - attr @fun_decl.value_this_guard "endpoint" - attr @fun_decl.value_this_guard "pop" = "GUARD:THIS" + attr (@fun_decl.value_this) "push" = "this" + attr (@fun_decl.value_this_guard) "endpoint" + attr (@fun_decl.value_this_guard) "pop" = "GUARD:THIS" edge @fun_decl.value_call -> @fun_decl.value_this_guard edge @fun_decl.value_this_guard -> @fun_decl.value_this edge @fun_decl.value_this -> @body.after_scope ; function values have a jump node that lets params connect up to actual arguments - attr @fun_decl.value_arg_scope "jump-to" + attr (@fun_decl.value_arg_scope) "jump-to" } (function_declaration @@ -974,7 +974,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (formal_parameters (_)@param))@fun_decl { ; parameters jump to the pushed argument scope - attr @param.arg_index "push" = (child-index @param) + attr (@param.arg_index) "push" = (child-index @param) edge @param.covalue -> @param.arg_index edge @param.arg_index -> @fun_decl.value_arg_scope } @@ -987,56 +987,56 @@ attribute node_symbol = node => symbol = (source-text node), source_n parameters:(_)@call_sig body:(_)@body)@fun_decl { - attr @name.pop "syntax_type" = "function" + attr (@name.pop) "syntax_type" = "function" ; scope flows across the decl edge @fun_decl.after_scope -> @fun_decl.before_scope ; with an augmentation for the function - attr @name.pop "pop" = @name, "definition" + attr (@name.pop) "pop" = @name, "definition" edge @fun_decl.after_scope -> @name.pop edge @name.pop -> @fun_decl.value ; function values have drop nodes that handle closures, that points to the ; before scope of the declaration - attr @fun_decl.value_drop "drop" + attr (@fun_decl.value_drop) "drop" edge @fun_decl.value_drop -> @fun_decl.before_scope ; the call sig's before scope comes from the drop node then flows into the body edge @call_sig.before_scope -> @fun_decl.value_drop - attr @call_sig.this_pop "pop" = "this", "definition" - attr @call_sig.this_push "push" = "this" + attr (@call_sig.this_pop) "pop" = "this", "definition" + attr (@call_sig.this_push) "push" = "this" edge @call_sig.this_pop -> @call_sig.this_push edge @call_sig.this_push -> @fun_decl.value_arg_scope edge @call_sig.before_scope -> @call_sig.this_pop - attr @call_sig.arguments_pop "pop" = "arguments", "definition" - attr @call_sig.arguments_push "push" = "arguments" + attr (@call_sig.arguments_pop) "pop" = "arguments", "definition" + attr (@call_sig.arguments_push) "push" = "arguments" edge @call_sig.arguments_pop -> @call_sig.arguments_push edge @call_sig.arguments_push -> @fun_decl.value_arg_scope edge @call_sig.before_scope -> @call_sig.arguments_pop edge @body.before_scope -> @call_sig.after_scope ; function values have call nodes - attr @fun_decl.value_call "pop" = "()", "pop-scope" + attr (@fun_decl.value_call) "pop" = "()", "pop-scope" edge @fun_decl.value -> @fun_decl.value_call ; function values have return nodes which need to be visible for returns - attr @fun_decl.value_return "endpoint" - attr @fun_decl.value_return "pop" = "GUARD:RETURN" + attr (@fun_decl.value_return) "endpoint" + attr (@fun_decl.value_return) "pop" = "GUARD:RETURN" edge @fun_decl.value_call -> @fun_decl.value_return let @body::return_or_yield = @fun_decl.value_return ; method values have this nodes which need to be visible for constructor calls - attr @fun_decl.value_this "push" = "this" - attr @fun_decl.value_this_guard "endpoint" - attr @fun_decl.value_this_guard "pop" = "GUARD:THIS" + attr (@fun_decl.value_this) "push" = "this" + attr (@fun_decl.value_this_guard) "endpoint" + attr (@fun_decl.value_this_guard) "pop" = "GUARD:THIS" edge @fun_decl.value_call -> @fun_decl.value_this_guard edge @fun_decl.value_this_guard -> @fun_decl.value_this edge @fun_decl.value_this -> @body.after_scope ; function values have a jump node that lets params connect up to actual arguments - attr @fun_decl.value_arg_scope "jump-to" + attr (@fun_decl.value_arg_scope) "jump-to" } (generator_function_declaration @@ -1044,7 +1044,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (formal_parameters (_)@param))@fun_decl { ; parameters jump to the pushed argument scope - attr @param.arg_index "push" = (child-index @param) + attr (@param.arg_index) "push" = (child-index @param) edge @param.covalue -> @param.arg_index edge @param.arg_index -> @fun_decl.value_arg_scope } @@ -1057,9 +1057,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n name:(_)@name body:(_)@body)@class_decl { - attr @name.pop "syntax_type" = "class" + attr (@name.pop) "syntax_type" = "class" - attr @name.pop "pop" = @name, "definition" + attr (@name.pop) "pop" = @name, "definition" edge @class_decl.after_scope -> @name.pop edge @name.pop -> @class_decl.value @@ -1111,7 +1111,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (#eq? @name "constructor") ) { ; augmentation for the constructor - attr @name.constructor_guard "pop" = "GUARD:CONSTRUCTOR", "definition" + attr (@name.constructor_guard) "pop" = "GUARD:CONSTRUCTOR", "definition" edge @method_def.after_scope -> @name.constructor_guard edge @name.constructor_guard -> @method_def.method_value } @@ -1122,8 +1122,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n (#not-eq? @name "constructor") ) { ; augmentation for the method - attr @name.pop "pop" = @name, "definition" - attr @name.pop_dot "pop" = "." + attr (@name.pop) "pop" = @name, "definition" + attr (@name.pop_dot) "pop" = "." edge @method_def.after_scope -> @name.pop_dot edge @name.pop_dot -> @name.pop edge @name.pop -> @method_def.method_value @@ -1134,14 +1134,14 @@ attribute node_symbol = node => symbol = (source-text node), source_n parameters:(_)@call_sig body:(_)@body)@method_def { - attr @name.pop "syntax_type" = "method" + attr (@name.pop) "syntax_type" = "method" ; scope flows across the decl edge @method_def.after_scope -> @method_def.before_scope ; method values have drop nodes that handle closures, that points to the ; before scope from method def - attr @method_def.method_value_drop "drop" + attr (@method_def.method_value_drop) "drop" edge @method_def.method_value_drop -> @method_def.before_scope ; the call sig's before scope comes from the drop node then flows into the body @@ -1149,25 +1149,25 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @body.before_scope -> @call_sig.after_scope ; method values have call nodes - attr @method_def.method_value_call "pop" = "()", "pop-scope" + attr (@method_def.method_value_call) "pop" = "()", "pop-scope" edge @method_def.method_value -> @method_def.method_value_call ; method values have return nodes which need to be visible for returns - attr @method_def.method_value_return "endpoint" - attr @method_def.method_value_return "pop" = "GUARD:RETURN" + attr (@method_def.method_value_return) "endpoint" + attr (@method_def.method_value_return) "pop" = "GUARD:RETURN" edge @method_def.method_value_call -> @method_def.method_value_return let @body::return_or_yield = @method_def.method_value_return ; method values have this nodes which need to be visible for constructor calls - attr @method_def.method_value_this "push" = "this" - attr @method_def.method_value_this_guard "endpoint" - attr @method_def.method_value_this_guard "pop" = "GUARD:THIS" + attr (@method_def.method_value_this) "push" = "this" + attr (@method_def.method_value_this_guard) "endpoint" + attr (@method_def.method_value_this_guard) "pop" = "GUARD:THIS" edge @method_def.method_value_call -> @method_def.method_value_this_guard edge @method_def.method_value_this_guard -> @method_def.method_value_this edge @method_def.method_value_this -> @body.after_scope ; method values have a jump node that lets params connect up to actual arguments - attr @method_def.method_value_arg_scope "jump-to" + attr (@method_def.method_value_arg_scope) "jump-to" } (method_definition @@ -1175,7 +1175,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (formal_parameters (_)@param))@method_def { ; parameters jump to the pushed argument scope - attr @param.arg_index "push" = (child-index @param) + attr (@param.arg_index) "push" = (child-index @param) edge @param.covalue -> @param.arg_index edge @param.arg_index -> @method_def.method_value_arg_scope } @@ -1185,8 +1185,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n (field_definition property:(property_identifier)@property)@field_def { - attr @property.pop "pop" = @property, "definition" - attr @property.pop_dot "pop" = "." + attr (@property.pop) "pop" = @property, "definition" + attr (@property.pop_dot) "pop" = "." edge @field_def.after_scope -> @property.pop_dot edge @property.pop_dot -> @property.pop } @@ -1438,7 +1438,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n right:(_)@right body:(_)@body) { - attr @left.pop "pop", "definition" + attr (@left.pop) "pop", "definition" edge @left.pop -> @right.value edge @body.before_scope -> @left.pop } @@ -1528,7 +1528,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n parameter:(identifier)@name body:(_)@body) { - attr @name.pop "pop", "definition" + attr (@name.pop) "pop", "definition" edge @body.before_scope -> @name.pop } @@ -1551,7 +1551,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @body.before_scope -> @object.after_scope edge @with_stmt.after_scope -> @body.after_scope - attr @object.push_dot "push" = "." + attr (@object.push_dot) "push" = "." edge @object.push_dot -> @object.value edge @body.before_scope -> @object.push_dot } @@ -1670,7 +1670,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; which may be useful (template_string (template_substitution (_)@inner_expr))@template_string { ; the value of a template string is a template string value built from the values of its substitutions - ; attr @template_string.value "template_string_value" + ; attr (@template_string.value) "template_string_value" edge @template_string.value -> @inner_expr.value } @@ -1715,7 +1715,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @variable.after_scope -> @variable.before_scope ; value is a lookup, ie a push - attr @variable.value "push", "reference" + attr (@variable.value) "push", "reference" edge @variable.value -> @variable.before_scope } @@ -1746,7 +1746,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @this.after_scope -> @this.before_scope ; this is a lookup, ie a push - attr @this.value "push" = "this", "reference" + attr (@this.value) "push" = "this", "reference" edge @this.value -> @this.before_scope } @@ -1845,13 +1845,13 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @keyval.after_scope -> @keyval.before_scope ; shorthand property identifiers have secret variable exprs - attr @keyval.rhsvar_value "push" = @keyval, "reference" + attr (@keyval.rhsvar_value) "push" = @keyval, "reference" edge @keyval.rhsvar_value -> @keyval.rhsvar_before_scope ; shorthand property identifiers augment the object value with a member binding - attr @keyval.boundvar_pop "pop" = @keyval, "definition" + attr (@keyval.boundvar_pop) "pop" = @keyval, "definition" - attr @object.field_pop_dot "pop" = "." + attr (@object.field_pop_dot) "pop" = "." edge @keyval.boundvar_pop -> @keyval.rhsvar_value edge @object.field_pop_dot -> @keyval.boundvar_pop edge @object.value -> @object.field_pop_dot @@ -1871,25 +1871,25 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; pairs augment the object value with a member binding ; This is done differently depending on what the key is. See next rules. - ; attr @key.pop "pop" = @key, "definition" - attr @key.pop "definition" + ; attr (@key.pop) "pop" = @key, "definition" + attr (@key.pop) "definition" - attr @object.field_pop_dot "pop" = "." + attr (@object.field_pop_dot) "pop" = "." edge @key.pop -> @value.value edge @object.field_pop_dot -> @key.pop edge @object.value -> @object.field_pop_dot } (pair key:(property_identifier)@key) { - attr @key.pop "pop" = @key + attr (@key.pop) "pop" = @key } (pair key:(string)@key) { - attr @key.pop "pop" = (replace @key "\"" "") + attr (@key.pop) "pop" = (replace @key "\"" "") } (pair key:(number)@key) { - attr @key.pop "pop" = @key + attr (@key.pop) "pop" = @key } @@ -1930,8 +1930,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; elements at indices (array (_)@element)@array_expr { - attr @array_expr.element_pop_dot "pop" = "." - attr @element.index_pop "pop" = (child-index @element), "definition" + attr (@array_expr.element_pop_dot) "pop" = "." + attr (@element.index_pop) "pop" = (child-index @element), "definition" edge @array_expr.element_pop_dot -> @element.index_pop edge @array_expr.value -> @array_expr.element_pop_dot edge @element.index_pop -> @element.value @@ -1985,10 +1985,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n name:(_)@name parameters:(_)@call_sig)@fun { - attr @name.pop "syntax_type" = "function" + attr (@name.pop) "syntax_type" = "function" ; if the function has a name, this is bound the callsig's before scope - attr @name.pop "pop" = @name, "definition" + attr (@name.pop) "pop" = @name, "definition" edge @call_sig.before_scope -> @name.pop edge @name.pop -> @fun.value } @@ -2004,44 +2004,44 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; function values have drop nodes that handle closures, that points to the ; before scope from the function - attr @fun.value_drop "drop" + attr (@fun.value_drop) "drop" edge @fun.value_drop -> @fun.before_scope ; the call sig's before scope comes from the drop node, ; then flows into the body, and includes a variable binding for "this" edge @call_sig.before_scope -> @fun.value_drop - attr @call_sig.this_pop "pop" = "this", "definition" - attr @call_sig.this_push "push" = "this" + attr (@call_sig.this_pop) "pop" = "this", "definition" + attr (@call_sig.this_push) "push" = "this" edge @call_sig.this_pop -> @call_sig.this_push edge @call_sig.this_push -> @fun.value_arg_scope edge @call_sig.before_scope -> @call_sig.this_pop - attr @call_sig.arguments_pop "pop" = "arguments", "definition" - attr @call_sig.arguments_push "push" = "arguments" + attr (@call_sig.arguments_pop) "pop" = "arguments", "definition" + attr (@call_sig.arguments_push) "push" = "arguments" edge @call_sig.arguments_pop -> @call_sig.arguments_push edge @call_sig.arguments_push -> @fun.value_arg_scope edge @call_sig.before_scope -> @call_sig.arguments_pop edge @body.before_scope -> @call_sig.after_scope ; function values have call nodes - attr @fun.value_call "pop" = "()", "pop-scope" + attr (@fun.value_call) "pop" = "()", "pop-scope" edge @fun.value -> @fun.value_call ; function values have return nodes which need to be visible for returns - attr @fun.value_return "endpoint" - attr @fun.value_return "pop" = "GUARD:RETURN" + attr (@fun.value_return) "endpoint" + attr (@fun.value_return) "pop" = "GUARD:RETURN" edge @fun.value_call -> @fun.value_return let @body::return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls - attr @fun.value_this "push" = "this" - attr @fun.value_this_guard "endpoint" - attr @fun.value_this_guard "pop" = "GUARD:THIS" + attr (@fun.value_this) "push" = "this" + attr (@fun.value_this_guard) "endpoint" + attr (@fun.value_this_guard) "pop" = "GUARD:THIS" edge @fun.value_call -> @fun.value_this_guard edge @fun.value_this_guard -> @fun.value_this edge @fun.value_this -> @body.after_scope ; function values have a jump node that lets params connect up to actual arguments - attr @fun.value_arg_scope "jump-to" + attr (@fun.value_arg_scope) "jump-to" } (function @@ -2049,7 +2049,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (formal_parameters (_)@param))@fun { ; parameters jump to the pushed argument scope - attr @param.arg_index "push" = (child-index @param) + attr (@param.arg_index) "push" = (child-index @param) edge @param.covalue -> @param.arg_index edge @param.arg_index -> @fun.value_arg_scope } @@ -2074,7 +2074,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; function values have drop nodes that handle closures, that points to the ; before scope from the function - attr @fun.value_drop "drop" + attr (@fun.value_drop) "drop" edge @fun.value_drop -> @fun.before_scope ; the call sig's before scope comes from the drop node then flows into the body @@ -2082,25 +2082,25 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @body.before_scope -> @call_sig.after_scope ; function values have call nodes - attr @fun.value_call "pop" = "()", "pop-scope" + attr (@fun.value_call) "pop" = "()", "pop-scope" edge @fun.value -> @fun.value_call ; function values have return nodes which need to be visible for returns - attr @fun.value_return "endpoint" - attr @fun.value_return "pop" = "GUARD:RETURN" + attr (@fun.value_return) "endpoint" + attr (@fun.value_return) "pop" = "GUARD:RETURN" edge @fun.value_call -> @fun.value_return let @body::return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls - attr @fun.value_this "push" = "this" - attr @fun.value_this_guard "endpoint" - attr @fun.value_this_guard "pop" = "GUARD:THIS" + attr (@fun.value_this) "push" = "this" + attr (@fun.value_this_guard) "endpoint" + attr (@fun.value_this_guard) "pop" = "GUARD:THIS" edge @fun.value_call -> @fun.value_this_guard edge @fun.value_this_guard -> @fun.value_this edge @fun.value_this -> @body.after_scope ; function values have a jump node that lets params connect up to actual arguments - attr @fun.value_arg_scope "jump-to" + attr (@fun.value_arg_scope) "jump-to" } ; arrow functions returning exprs need special rules for getting the return value hooked up @@ -2116,12 +2116,12 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @param.after_scope -> @param.before_scope ; but augmented with a pop, b/c it's not a pattern - attr @param.pop "pop" = @param, "definition" + attr (@param.pop) "pop" = @param, "definition" edge @param.pop -> @param.covalue edge @param.after_scope -> @param.pop ; parameters jump to the pushed argument scope - attr @param.arg_index "push" = "0" + attr (@param.arg_index) "push" = "0" edge @param.covalue -> @param.arg_index edge @param.arg_index -> @fun.value_arg_scope } @@ -2131,7 +2131,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (formal_parameters (_)@param))@fun { ; parameters jump to the pushed argument scope - attr @param.arg_index "push" = (child-index @param) + attr (@param.arg_index) "push" = (child-index @param) edge @param.covalue -> @param.arg_index edge @param.arg_index -> @fun.value_arg_scope } @@ -2145,10 +2145,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n name:(_)@name parameters:(_)@call_sig)@fun { - attr @name.pop "syntax_type" = "function" + attr (@name.pop) "syntax_type" = "function" ; if the function has a name, this is bound the callsig's before scope - attr @name.pop "pop" = @name, "definition" + attr (@name.pop) "pop" = @name, "definition" edge @call_sig.before_scope -> @name.pop edge @name.pop -> @fun.value } @@ -2164,7 +2164,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; function values have drop nodes that handle closures, that points to the ; before scope from the function - attr @fun.value_drop "drop" + attr (@fun.value_drop) "drop" edge @fun.value_drop -> @fun.before_scope ; the call sig's before scope comes from the drop node then flows into the body @@ -2172,25 +2172,25 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @body.before_scope -> @call_sig.after_scope ; function values have call nodes - attr @fun.value_call "pop" = "()", "pop-scope" + attr (@fun.value_call) "pop" = "()", "pop-scope" edge @fun.value -> @fun.value_call ; function values have return nodes which need to be visible for returns - attr @fun.value_return "endpoint" - attr @fun.value_return "pop" = "GUARD:RETURN" + attr (@fun.value_return) "endpoint" + attr (@fun.value_return) "pop" = "GUARD:RETURN" edge @fun.value_call -> @fun.value_return let @body::return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls - attr @fun.value_this "push" = "this" - attr @fun.value_this_guard "endpoint" - attr @fun.value_this_guard "pop" = "GUARD:THIS" + attr (@fun.value_this) "push" = "this" + attr (@fun.value_this_guard) "endpoint" + attr (@fun.value_this_guard) "pop" = "GUARD:THIS" edge @fun.value_call -> @fun.value_this_guard edge @fun.value_this_guard -> @fun.value_this edge @fun.value_this -> @body.after_scope ; function values have a jump node that lets params connect up to actual arguments - attr @fun.value_arg_scope "jump-to" + attr (@fun.value_arg_scope) "jump-to" } (generator_function @@ -2198,7 +2198,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (formal_parameters (_)@param))@fun { ; parameters jump to the pushed argument scope - attr @param.arg_index "push" = (child-index @param) + attr (@param.arg_index) "push" = (child-index @param) edge @param.covalue -> @param.arg_index edge @param.arg_index -> @fun.value_arg_scope } @@ -2223,19 +2223,19 @@ attribute node_symbol = node => symbol = (source-text node), source_n arguments:(_)@arguments)@call_expr { ; value is a call, ie a push "()" node w/ "push-scope" @arguments - attr @call_expr.return_guard "push" = "GUARD:RETURN" - attr @call_expr.call "push" = "()", "push-scope" = @arguments.arg_scope + attr (@call_expr.return_guard) "push" = "GUARD:RETURN" + attr (@call_expr.call) "push" = "()", "push-scope" = @arguments.arg_scope edge @call_expr.value -> @call_expr.return_guard edge @call_expr.return_guard -> @call_expr.call edge @call_expr.call -> @function.value - attr @arguments.arg_this "pop" = "this", "definition" + attr (@arguments.arg_this) "pop" = "this", "definition" edge @arguments.arg_scope -> @arguments.arg_this edge @arguments.arg_scope -> @arguments.arg_scope_no_this - attr @arguments.arg_arguments "pop" = "arguments", "definition" - attr @arguments.arg_arguments_dot "pop" = "." + attr (@arguments.arg_arguments) "pop" = "arguments", "definition" + attr (@arguments.arg_arguments_dot) "pop" = "." edge @arguments.arg_scope -> @arguments.arg_arguments edge @arguments.arg_arguments -> @arguments.arg_arguments_dot edge @arguments.arg_arguments_dot -> @arguments.arg_scope_no_this @@ -2267,7 +2267,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (call_expression arguments:(arguments (_)@arg)@arguments) { - attr @arg.arg_index "pop" = (child-index @arg) + attr (@arg.arg_index) "pop" = (child-index @arg) edge @arguments.arg_scope_no_this -> @arg.arg_index edge @arg.arg_index -> @arg.value } @@ -2319,9 +2319,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @member_expr.after_scope -> @object.after_scope ; value is a member projection on the value of the object ie. a push then push dot - attr @property.push "push", "reference" - ;attr @member_expr.value "push" = @property.pop - attr @member_expr.push_dot "push" = "." + attr (@property.push) "push", "reference" + ;attr (@member_expr.value) "push" = @property.pop + attr (@member_expr.push_dot) "push" = "." edge @property.push -> @member_expr.push_dot ;edge @member_expr.value -> @member_expr.push_dot edge @member_expr.value -> @property.push @@ -2342,7 +2342,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; value is a subscript lookup, ie a push then push dot ; this is done differently depending on what the index is - ; attr @index.push "push" = @index, "reference" + ; attr (@index.push) "push" = @index, "reference" } @@ -2350,26 +2350,26 @@ attribute node_symbol = node => symbol = (source-text node), source_n object: (_)@object index: (string)@index)@subscript_expression { - attr @index.push "reference" + attr (@index.push) "reference" - attr @index.push_dot "push" = "." + attr (@index.push_dot) "push" = "." edge @subscript_expression.value -> @index.push edge @index.push -> @index.push_dot edge @index.push_dot -> @object.value - attr @index.push "push" = (replace @index "\"" "") + attr (@index.push) "push" = (replace @index "\"" "") } (subscript_expression object: (_)@object index: (number)@index)@subscript_expression { - attr @index.push "reference" + attr (@index.push) "reference" - attr @index.push_dot "push" = "." + attr (@index.push_dot) "push" = "." edge @subscript_expression.value -> @index.push edge @index.push -> @index.push_dot edge @index.push_dot -> @object.value - attr @index.push "push" = @index + attr (@index.push) "push" = @index } @@ -2384,10 +2384,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @arguments.before_scope -> @constructor.after_scope edge @new_expr.after_scope -> @arguments.after_scope - attr @new_expr.call "push" = "()", "push-scope" = @arguments.arg_scope + attr (@new_expr.call) "push" = "()", "push-scope" = @arguments.arg_scope ; we guard for constructors for the case where we have a "true" class - attr @constructor.constructor "push" = "GUARD:CONSTRUCTOR" + attr (@constructor.constructor) "push" = "GUARD:CONSTRUCTOR" edge @new_expr.call -> @constructor.constructor edge @constructor.constructor -> @constructor.value @@ -2397,14 +2397,14 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; value coming from the constructor call - attr @new_expr.guard_this "push" = "GUARD:THIS" + attr (@new_expr.guard_this) "push" = "GUARD:THIS" edge @new_expr.value -> @new_expr.guard_this edge @new_expr.guard_this -> @new_expr.call ; value coming from the field decls in the class edge @new_expr.value -> @constructor.value - attr @arguments.arg_this "pop" = "this", "definition" + attr (@arguments.arg_this) "pop" = "this", "definition" edge @arguments.arg_scope -> @arguments.arg_this edge @arguments.arg_this -> @new_expr::empty_object } @@ -2412,7 +2412,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (new_expression arguments:(arguments (_)@arg)@arguments) { - attr @arg.arg_index "pop" = (child-index @arg) + attr (@arg.arg_index) "pop" = (child-index @arg) edge @arguments.arg_scope -> @arg.arg_index edge @arg.arg_index -> @arg.value } @@ -2441,7 +2441,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; LATER-TODO this isn't quite right because the update argument can't be an arbitrary expr ; eg f(x)++ doesn't make any sense, you have to have something more like ; (update_expression argument: (lvar)@argument) - attr @argument.pop "pop", "definition" + attr (@argument.pop) "pop", "definition" edge @update_expr.value -> @argument.value edge @update_expr.after_scope -> @argument.pop edge @argument.pop -> @argument.value @@ -2459,7 +2459,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; value is a binary op value built from the operands ; LATER-TODO this isn't quite correct but it permits flow through the expression ; which can be useful - ; attr @binary_expr.value "binary_operation_value" + ; attr (@binary_expr.value) "binary_operation_value" edge @binary_expr.value -> @left.value edge @binary_expr.value -> @right.value } @@ -2475,7 +2475,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; value is a unaryop value built from the operand ; LATER-TODO this isn't quite correct but it permits flow through the expression ; which can be useful - ; attr @unary_expr.value "unary_operation_value" + ; attr (@unary_expr.value) "unary_operation_value" edge @unary_expr.value -> @argument.value } @@ -2504,7 +2504,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n right: (_)@right)@assignment_expr { ; augments the scope by adding a lookup edge, ie. a pop - attr @left.pop "pop" = @left, "definition" + attr (@left.pop) "pop" = @left, "definition" edge @assignment_expr.after_scope -> @left.pop edge @left.pop -> @right.value @@ -2520,11 +2520,11 @@ attribute node_symbol = node => symbol = (source-text node), source_n right: (_)@right)@assignment_expr { ; HACK - attr @this.drop "drop" + attr (@this.drop) "drop" edge @this.drop -> @this.pop - attr @this.pop "pop" = "this" - attr @this.pop_dot "pop" = "." - attr @property.pop "pop" = @property, "definition" + attr (@this.pop) "pop" = "this" + attr (@this.pop_dot) "pop" = "." + attr (@property.pop) "pop" = @property, "definition" edge @assignment_expr.after_scope -> @this.drop edge @assignment_expr.after_scope -> @this.pop edge @this.pop -> @this.pop_dot @@ -2560,8 +2560,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n right:(_)@right)@augmented_assignment_expr { ; augment the scope - attr @left.pop "pop" = @left, "definition" - attr @left.push "push" = @left, "reference" + attr (@left.pop) "pop" = @left, "definition" + attr (@left.push) "push" = @left, "reference" edge @left.push -> @augmented_assignment_expr.before_scope edge @left.pop -> @left.push edge @left.pop -> @right.value @@ -2633,9 +2633,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n name:(_)@name body:(_)@body)@class { - attr @name.pop "syntax_type" = "class" + attr (@name.pop) "syntax_type" = "class" - attr @name.pop "pop" = @name, "definition" + attr (@name.pop) "pop" = @name, "definition" edge @body.before_scope -> @name.pop edge @name.pop -> @class.value } @@ -2890,7 +2890,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (pattern/identifier)@ident_pat { ; scope flows through, binding via a pop edge that goes to an unknown value - attr @ident_pat.pop "pop" = @ident_pat, "definition" + attr (@ident_pat.pop) "pop" = @ident_pat, "definition" edge @ident_pat.pop -> @ident_pat.covalue edge @ident_pat.after_scope -> @ident_pat.before_scope edge @ident_pat.after_scope -> @ident_pat.pop @@ -2952,7 +2952,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n value:(_)@value_pat)@pair_pat { ; covalues flow in dotted - attr @key.push_dot "push" = "." + attr (@key.push_dot) "push" = "." edge @value_pat.covalue -> @key.push edge @key.push -> @key.push_dot edge @key.push_dot -> @pair_pat.covalue @@ -2966,13 +2966,13 @@ attribute node_symbol = node => symbol = (source-text node), source_n (pair_pattern key:(property_identifier)@key)@pair_pattern { - attr @key.push "push" = @key, "reference" + attr (@key.push) "push" = @key, "reference" } (pair_pattern key:(string)@key)@pair_pattern { - attr @key.push "push" = (replace @key "\"" ""), "reference" + attr (@key.push) "push" = (replace @key "\"" ""), "reference" } ; LATER-TODO the left pattern has to be a name, it cant be another pattern @@ -3009,9 +3009,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @left_pat.after_scope -> @left_pat.before_scope - attr @left_pat.push "push" = @left_pat, "reference" - attr @left_pat.push_dot "push" = "." - attr @left_pat.pop "pop" = @left_pat, "definition" + attr (@left_pat.push) "push" = @left_pat, "reference" + attr (@left_pat.push_dot) "push" = "." + attr (@left_pat.pop) "pop" = @left_pat, "definition" edge @left_pat.pop -> @left_pat.push edge @left_pat.push -> @left_pat.push_dot edge @left_pat.push_dot -> @left_pat.covalue @@ -3060,8 +3060,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; array pattern elements (array_pattern (_)@element_pat)@array_pat { - attr @element_pat.element_index_push "push" = (child-index @element_pat), "reference" - attr @array_pat.element_index_push_dot "push" = "." + attr (@element_pat.element_index_push) "push" = (child-index @element_pat), "reference" + attr (@array_pat.element_index_push_dot) "push" = "." edge @element_pat.covalue -> @element_pat.element_index_push edge @element_pat.element_index_push -> @array_pat.element_index_push_dot edge @array_pat.element_index_push_dot -> @array_pat.covalue @@ -3103,7 +3103,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (rest_pattern (_)@name)@rest_pat { ; scope flows through, binding via a pop edge that goes to an unknown value - attr @rest_pat.pop "pop" = @name, "definition" + attr (@rest_pat.pop) "pop" = @name, "definition" edge @rest_pat.after_scope -> @rest_pat.before_scope edge @rest_pat.after_scope -> @rest_pat.pop } @@ -3141,7 +3141,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (#eq? @extend "extend") ) { - attr @object.pop "pop" = @object, "definition" + attr (@object.pop) "pop" = @object, "definition" edge @call_expr.after_scope -> @object.pop edge @object.pop -> @new_fields.value @@ -3173,8 +3173,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n (#eq? @exports "exports") ) { - attr @property.pop "pop" = @property, "definition" - attr @property.pop_dot "pop" = "." + attr (@property.pop) "pop" = @property, "definition" + attr (@property.pop_dot) "pop" = "." edge @assignment_expr::exports -> @property.pop_dot edge @property.pop_dot -> @property.pop edge @property.pop -> @right.value @@ -3208,11 +3208,11 @@ attribute node_symbol = node => symbol = (source-text node), source_n scan @mod_name { "\"([^/\"]+)\.js\"$" { - attr @mod_name.push "push" = $1 + attr (@mod_name.push) "push" = $1 } } - attr @mod_name.module_guard "push" = "GUARD:EXPORTS" + attr (@mod_name.module_guard) "push" = "GUARD:EXPORTS" edge @call_expr.value -> @mod_name.module_guard edge @mod_name.module_guard -> @mod_name.push edge @mod_name.push -> ROOT_NODE @@ -3238,7 +3238,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n name:(_)@name body:(_)@body)@class_decl { - attr @name.pop "definiens" = @class_decl + attr (@name.pop) "definiens" = @class_decl } @@ -3247,7 +3247,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n parameters:(_)@call_sig body:(_)@body)@fun_decl { - attr @name.pop "definiens" = @fun_decl + attr (@name.pop) "definiens" = @fun_decl } @@ -3256,7 +3256,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n parameters:(_)@call_sig body:(_)@body)@fun_decl { - attr @name.pop "definiens" = @fun_decl + attr (@name.pop) "definiens" = @fun_decl } @@ -3265,7 +3265,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n parameters:(_)@call_sig body:(_)@body)@method_def { - attr @name.pop "definiens" = @method_def + attr (@name.pop) "definiens" = @method_def } @@ -3273,7 +3273,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n name:(_)@name parameters:(_)@call_sig)@fun { - attr @name.pop "definiens" = @fun + attr (@name.pop) "definiens" = @fun } @@ -3281,7 +3281,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n name:(_)@name parameters:(_)@call_sig)@fun { - attr @name.pop "definiens" = @fun + attr (@name.pop) "definiens" = @fun } @@ -3289,7 +3289,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n name:(_)@name body:(_)@body)@class { - attr @name.pop "definiens" = @class + attr (@name.pop) "definiens" = @class } @@ -3311,7 +3311,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (arrow_function) ]@right) { - attr @left.pop "definiens" = @right + attr (@left.pop) "definiens" = @right } @@ -3323,9 +3323,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n (arrow_function) ]@right) { - attr @left.ignore_guard "pop" = "GUARD:GANDALF" - attr @left.definiens_hook "pop" = @left, "definition" - attr @left.definiens_hook "definiens" = @right + attr (@left.ignore_guard) "pop" = "GUARD:GANDALF" + attr (@left.definiens_hook) "pop" = @left, "definition" + attr (@left.definiens_hook) "definiens" = @right edge ROOT_NODE -> @left.ignore_guard edge @left.ignore_guard -> @left.definiens_hook } @@ -3339,7 +3339,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (arrow_function) ]@initializer)) { - attr @name.pop "definiens" = @initializer + attr (@name.pop) "definiens" = @initializer } @@ -3352,7 +3352,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (arrow_function) ]@initializer)) { - attr @name.pop "definiens" = @initializer + attr (@name.pop) "definiens" = @initializer } @@ -3364,9 +3364,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n (arrow_function) ]@value) { -attr @name.ignore_guard "pop" = "GUARD:GANDALF" -attr @name.definiens_hook "pop" = @name, "definition" -attr @name.definiens_hook "definiens" = @value +attr (@name.ignore_guard) "pop" = "GUARD:GANDALF" +attr (@name.definiens_hook) "pop" = @name, "definition" +attr (@name.definiens_hook) "definiens" = @value edge ROOT_NODE -> @name.ignore_guard edge @name.ignore_guard -> @name.definiens_hook From efc1a8cf2d5afb3dbc3ffe983ad4ddcf590d9ce9 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 13:11:15 +0200 Subject: [PATCH 025/500] [conv] pop_symbol --- .../src/stack-graphs-conv.tsg | 98 +++++++++---------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index fa2a87b11..0589e5098 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -77,7 +77,7 @@ ;; ``````stgdoc ;; (number)@num { -;; attr (@num.value) "pop" = "NUM_VAL" +;; attr (@num.value) pop_symbol = "NUM_VAL" ;; } ;; `````` @@ -106,7 +106,7 @@ ;; ``````stgdoc ;; (number)@num { -;; attr (@num.value) "pop" = "NUM_VAL" +;; attr (@num.value) pop_symbol = "NUM_VAL" ;; edge @num.value -> @num::number_prototype ;; } ;; `````` @@ -154,7 +154,7 @@ ;; ;; edge @prog.number_prototype -> @prog.number_prototype_toString_method_value ;; edge @prog.number_prototype_toString_method_value -> @prog.number_prototype_toString_method_value_return -;; attr (@prog.number_prototype_toString_method_value_return) "pop" = "GUARD:RETURN" +;; attr (@prog.number_prototype_toString_method_value_return) pop_symbol = "GUARD:RETURN" ;; edge @prog.number_prototype_toString_method_value_return -> @prog.string_prototype ;; ;; ... @@ -306,7 +306,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @prog.before_scope -> ROOT_NODE - attr (@prog.module_scope) "pop" = "GUARD:MODULE" + attr (@prog.module_scope) pop_symbol = "GUARD:MODULE" edge ROOT_NODE -> @prog.module_pop edge @prog.module_pop -> @prog.module_scope edge @prog.module_scope -> @prog.after_scope @@ -321,7 +321,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n let @prog::prog = @prog let @prog::exports = @prog.exports - attr (@prog.exports_pop) "pop" = "GUARD:EXPORTS" + attr (@prog.exports_pop) pop_symbol = "GUARD:EXPORTS" edge @prog.module_pop -> @prog.exports_pop edge @prog.exports_pop -> @prog.exports } @@ -533,7 +533,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ) { - attr (@export_specifier.pop_guard_default) "pop" = "GUARD:DEFAULT" + attr (@export_specifier.pop_guard_default) pop_symbol = "GUARD:DEFAULT" attr (@export_specifier.push_guard_default) "push" = "GUARD:DEFAULT" edge @export_specifier::exports -> @export_specifier.pop_guard_default edge @export_specifier.pop_guard_default -> @export_specifier.push_guard_default @@ -551,7 +551,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ) { attr (@name.push) "push" = @name - attr (@export_specifier.guard_default) "pop" = "GUARD:DEFAULT" + attr (@export_specifier.guard_default) pop_symbol = "GUARD:DEFAULT" edge @name.push -> @export_specifier.source edge @export_specifier.guard_default -> @name.push edge @export_specifier::exports -> @export_specifier.guard_default @@ -563,7 +563,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (export_statement value:(_)@default_expr)@export_stmt { - attr (@export_stmt.default_guard) "pop" = "GUARD:DEFAULT", "definition" + attr (@export_stmt.default_guard) pop_symbol = "GUARD:DEFAULT", "definition" edge @default_expr.before_scope -> @export_stmt.before_scope edge @export_stmt.after_scope -> @default_expr.after_scope edge @export_stmt::exports -> @export_stmt.default_guard @@ -606,7 +606,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n } } attr (@alias.pop) "pop" = @alias, "definition" - attr (@alias.pop_dot) "pop" = "." + attr (@alias.pop_dot) pop_symbol = "." edge @export_statement::exports -> @alias.pop edge @alias.pop -> @alias.pop_dot edge @alias.pop_dot -> @source.push_exports_guard @@ -644,7 +644,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @namespace_import.after_scope -> @namespace_import.before_scope attr (@imported_as.pop) "pop" = @imported_as, "definition" - attr (@imported_as.pop_dot) "pop" = "." + attr (@imported_as.pop_dot) pop_symbol = "." edge @imported_as.pop -> @imported_as.pop_dot edge @imported_as.pop_dot -> @namespace_import.source @@ -934,12 +934,12 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; the call sig's before scope comes from the drop node then flows into the body edge @call_sig.before_scope -> @fun_decl.value_drop - attr (@call_sig.this_pop) "pop" = "this", "definition" + attr (@call_sig.this_pop) pop_symbol = "this", "definition" attr (@call_sig.this_push) "push" = "this" edge @call_sig.this_pop -> @call_sig.this_push edge @call_sig.this_push -> @fun_decl.value_arg_scope edge @call_sig.before_scope -> @call_sig.this_pop - attr (@call_sig.arguments_pop) "pop" = "arguments", "definition" + attr (@call_sig.arguments_pop) pop_symbol = "arguments", "definition" attr (@call_sig.arguments_push) "push" = "arguments" edge @call_sig.arguments_pop -> @call_sig.arguments_push edge @call_sig.arguments_push -> @fun_decl.value_arg_scope @@ -948,19 +948,19 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; function values have call nodes - attr (@fun_decl.value_call) "pop" = "()", "pop-scope" + attr (@fun_decl.value_call) pop_symbol = "()", "pop-scope" edge @fun_decl.value -> @fun_decl.value_call ; function values have return nodes which need to be visible for returns attr (@fun_decl.value_return) "endpoint" - attr (@fun_decl.value_return) "pop" = "GUARD:RETURN" + attr (@fun_decl.value_return) pop_symbol = "GUARD:RETURN" edge @fun_decl.value_call -> @fun_decl.value_return let @body::return_or_yield = @fun_decl.value_return ; method values have this nodes which need to be visible for constructor calls attr (@fun_decl.value_this) "push" = "this" attr (@fun_decl.value_this_guard) "endpoint" - attr (@fun_decl.value_this_guard) "pop" = "GUARD:THIS" + attr (@fun_decl.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun_decl.value_call -> @fun_decl.value_this_guard edge @fun_decl.value_this_guard -> @fun_decl.value_this edge @fun_decl.value_this -> @body.after_scope @@ -1005,12 +1005,12 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; the call sig's before scope comes from the drop node then flows into the body edge @call_sig.before_scope -> @fun_decl.value_drop - attr (@call_sig.this_pop) "pop" = "this", "definition" + attr (@call_sig.this_pop) pop_symbol = "this", "definition" attr (@call_sig.this_push) "push" = "this" edge @call_sig.this_pop -> @call_sig.this_push edge @call_sig.this_push -> @fun_decl.value_arg_scope edge @call_sig.before_scope -> @call_sig.this_pop - attr (@call_sig.arguments_pop) "pop" = "arguments", "definition" + attr (@call_sig.arguments_pop) pop_symbol = "arguments", "definition" attr (@call_sig.arguments_push) "push" = "arguments" edge @call_sig.arguments_pop -> @call_sig.arguments_push edge @call_sig.arguments_push -> @fun_decl.value_arg_scope @@ -1018,19 +1018,19 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @body.before_scope -> @call_sig.after_scope ; function values have call nodes - attr (@fun_decl.value_call) "pop" = "()", "pop-scope" + attr (@fun_decl.value_call) pop_symbol = "()", "pop-scope" edge @fun_decl.value -> @fun_decl.value_call ; function values have return nodes which need to be visible for returns attr (@fun_decl.value_return) "endpoint" - attr (@fun_decl.value_return) "pop" = "GUARD:RETURN" + attr (@fun_decl.value_return) pop_symbol = "GUARD:RETURN" edge @fun_decl.value_call -> @fun_decl.value_return let @body::return_or_yield = @fun_decl.value_return ; method values have this nodes which need to be visible for constructor calls attr (@fun_decl.value_this) "push" = "this" attr (@fun_decl.value_this_guard) "endpoint" - attr (@fun_decl.value_this_guard) "pop" = "GUARD:THIS" + attr (@fun_decl.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun_decl.value_call -> @fun_decl.value_this_guard edge @fun_decl.value_this_guard -> @fun_decl.value_this edge @fun_decl.value_this -> @body.after_scope @@ -1111,7 +1111,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (#eq? @name "constructor") ) { ; augmentation for the constructor - attr (@name.constructor_guard) "pop" = "GUARD:CONSTRUCTOR", "definition" + attr (@name.constructor_guard) pop_symbol = "GUARD:CONSTRUCTOR", "definition" edge @method_def.after_scope -> @name.constructor_guard edge @name.constructor_guard -> @method_def.method_value } @@ -1123,7 +1123,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ) { ; augmentation for the method attr (@name.pop) "pop" = @name, "definition" - attr (@name.pop_dot) "pop" = "." + attr (@name.pop_dot) pop_symbol = "." edge @method_def.after_scope -> @name.pop_dot edge @name.pop_dot -> @name.pop edge @name.pop -> @method_def.method_value @@ -1149,19 +1149,19 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @body.before_scope -> @call_sig.after_scope ; method values have call nodes - attr (@method_def.method_value_call) "pop" = "()", "pop-scope" + attr (@method_def.method_value_call) pop_symbol = "()", "pop-scope" edge @method_def.method_value -> @method_def.method_value_call ; method values have return nodes which need to be visible for returns attr (@method_def.method_value_return) "endpoint" - attr (@method_def.method_value_return) "pop" = "GUARD:RETURN" + attr (@method_def.method_value_return) pop_symbol = "GUARD:RETURN" edge @method_def.method_value_call -> @method_def.method_value_return let @body::return_or_yield = @method_def.method_value_return ; method values have this nodes which need to be visible for constructor calls attr (@method_def.method_value_this) "push" = "this" attr (@method_def.method_value_this_guard) "endpoint" - attr (@method_def.method_value_this_guard) "pop" = "GUARD:THIS" + attr (@method_def.method_value_this_guard) pop_symbol = "GUARD:THIS" edge @method_def.method_value_call -> @method_def.method_value_this_guard edge @method_def.method_value_this_guard -> @method_def.method_value_this edge @method_def.method_value_this -> @body.after_scope @@ -1186,7 +1186,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n property:(property_identifier)@property)@field_def { attr (@property.pop) "pop" = @property, "definition" - attr (@property.pop_dot) "pop" = "." + attr (@property.pop_dot) pop_symbol = "." edge @field_def.after_scope -> @property.pop_dot edge @property.pop_dot -> @property.pop } @@ -1851,7 +1851,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; shorthand property identifiers augment the object value with a member binding attr (@keyval.boundvar_pop) "pop" = @keyval, "definition" - attr (@object.field_pop_dot) "pop" = "." + attr (@object.field_pop_dot) pop_symbol = "." edge @keyval.boundvar_pop -> @keyval.rhsvar_value edge @object.field_pop_dot -> @keyval.boundvar_pop edge @object.value -> @object.field_pop_dot @@ -1874,7 +1874,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; attr (@key.pop) "pop" = @key, "definition" attr (@key.pop) "definition" - attr (@object.field_pop_dot) "pop" = "." + attr (@object.field_pop_dot) pop_symbol = "." edge @key.pop -> @value.value edge @object.field_pop_dot -> @key.pop edge @object.value -> @object.field_pop_dot @@ -1930,7 +1930,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; elements at indices (array (_)@element)@array_expr { - attr (@array_expr.element_pop_dot) "pop" = "." + attr (@array_expr.element_pop_dot) pop_symbol = "." attr (@element.index_pop) "pop" = (child-index @element), "definition" edge @array_expr.element_pop_dot -> @element.index_pop edge @array_expr.value -> @array_expr.element_pop_dot @@ -2010,12 +2010,12 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; the call sig's before scope comes from the drop node, ; then flows into the body, and includes a variable binding for "this" edge @call_sig.before_scope -> @fun.value_drop - attr (@call_sig.this_pop) "pop" = "this", "definition" + attr (@call_sig.this_pop) pop_symbol = "this", "definition" attr (@call_sig.this_push) "push" = "this" edge @call_sig.this_pop -> @call_sig.this_push edge @call_sig.this_push -> @fun.value_arg_scope edge @call_sig.before_scope -> @call_sig.this_pop - attr (@call_sig.arguments_pop) "pop" = "arguments", "definition" + attr (@call_sig.arguments_pop) pop_symbol = "arguments", "definition" attr (@call_sig.arguments_push) "push" = "arguments" edge @call_sig.arguments_pop -> @call_sig.arguments_push edge @call_sig.arguments_push -> @fun.value_arg_scope @@ -2023,19 +2023,19 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @body.before_scope -> @call_sig.after_scope ; function values have call nodes - attr (@fun.value_call) "pop" = "()", "pop-scope" + attr (@fun.value_call) pop_symbol = "()", "pop-scope" edge @fun.value -> @fun.value_call ; function values have return nodes which need to be visible for returns attr (@fun.value_return) "endpoint" - attr (@fun.value_return) "pop" = "GUARD:RETURN" + attr (@fun.value_return) pop_symbol = "GUARD:RETURN" edge @fun.value_call -> @fun.value_return let @body::return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls attr (@fun.value_this) "push" = "this" attr (@fun.value_this_guard) "endpoint" - attr (@fun.value_this_guard) "pop" = "GUARD:THIS" + attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun.value_call -> @fun.value_this_guard edge @fun.value_this_guard -> @fun.value_this edge @fun.value_this -> @body.after_scope @@ -2082,19 +2082,19 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @body.before_scope -> @call_sig.after_scope ; function values have call nodes - attr (@fun.value_call) "pop" = "()", "pop-scope" + attr (@fun.value_call) pop_symbol = "()", "pop-scope" edge @fun.value -> @fun.value_call ; function values have return nodes which need to be visible for returns attr (@fun.value_return) "endpoint" - attr (@fun.value_return) "pop" = "GUARD:RETURN" + attr (@fun.value_return) pop_symbol = "GUARD:RETURN" edge @fun.value_call -> @fun.value_return let @body::return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls attr (@fun.value_this) "push" = "this" attr (@fun.value_this_guard) "endpoint" - attr (@fun.value_this_guard) "pop" = "GUARD:THIS" + attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun.value_call -> @fun.value_this_guard edge @fun.value_this_guard -> @fun.value_this edge @fun.value_this -> @body.after_scope @@ -2172,19 +2172,19 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @body.before_scope -> @call_sig.after_scope ; function values have call nodes - attr (@fun.value_call) "pop" = "()", "pop-scope" + attr (@fun.value_call) pop_symbol = "()", "pop-scope" edge @fun.value -> @fun.value_call ; function values have return nodes which need to be visible for returns attr (@fun.value_return) "endpoint" - attr (@fun.value_return) "pop" = "GUARD:RETURN" + attr (@fun.value_return) pop_symbol = "GUARD:RETURN" edge @fun.value_call -> @fun.value_return let @body::return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls attr (@fun.value_this) "push" = "this" attr (@fun.value_this_guard) "endpoint" - attr (@fun.value_this_guard) "pop" = "GUARD:THIS" + attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun.value_call -> @fun.value_this_guard edge @fun.value_this_guard -> @fun.value_this edge @fun.value_this -> @body.after_scope @@ -2229,13 +2229,13 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @call_expr.return_guard -> @call_expr.call edge @call_expr.call -> @function.value - attr (@arguments.arg_this) "pop" = "this", "definition" + attr (@arguments.arg_this) pop_symbol = "this", "definition" edge @arguments.arg_scope -> @arguments.arg_this edge @arguments.arg_scope -> @arguments.arg_scope_no_this - attr (@arguments.arg_arguments) "pop" = "arguments", "definition" - attr (@arguments.arg_arguments_dot) "pop" = "." + attr (@arguments.arg_arguments) pop_symbol = "arguments", "definition" + attr (@arguments.arg_arguments_dot) pop_symbol = "." edge @arguments.arg_scope -> @arguments.arg_arguments edge @arguments.arg_arguments -> @arguments.arg_arguments_dot edge @arguments.arg_arguments_dot -> @arguments.arg_scope_no_this @@ -2404,7 +2404,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; value coming from the field decls in the class edge @new_expr.value -> @constructor.value - attr (@arguments.arg_this) "pop" = "this", "definition" + attr (@arguments.arg_this) pop_symbol = "this", "definition" edge @arguments.arg_scope -> @arguments.arg_this edge @arguments.arg_this -> @new_expr::empty_object } @@ -2522,8 +2522,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; HACK attr (@this.drop) "drop" edge @this.drop -> @this.pop - attr (@this.pop) "pop" = "this" - attr (@this.pop_dot) "pop" = "." + attr (@this.pop) pop_symbol = "this" + attr (@this.pop_dot) pop_symbol = "." attr (@property.pop) "pop" = @property, "definition" edge @assignment_expr.after_scope -> @this.drop edge @assignment_expr.after_scope -> @this.pop @@ -3174,7 +3174,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ) { attr (@property.pop) "pop" = @property, "definition" - attr (@property.pop_dot) "pop" = "." + attr (@property.pop_dot) pop_symbol = "." edge @assignment_expr::exports -> @property.pop_dot edge @property.pop_dot -> @property.pop edge @property.pop -> @right.value @@ -3323,7 +3323,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (arrow_function) ]@right) { - attr (@left.ignore_guard) "pop" = "GUARD:GANDALF" + attr (@left.ignore_guard) pop_symbol = "GUARD:GANDALF" attr (@left.definiens_hook) "pop" = @left, "definition" attr (@left.definiens_hook) "definiens" = @right edge ROOT_NODE -> @left.ignore_guard @@ -3364,7 +3364,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (arrow_function) ]@value) { -attr (@name.ignore_guard) "pop" = "GUARD:GANDALF" +attr (@name.ignore_guard) pop_symbol = "GUARD:GANDALF" attr (@name.definiens_hook) "pop" = @name, "definition" attr (@name.definiens_hook) "definiens" = @value edge ROOT_NODE -> @name.ignore_guard From fa2a09b5a1f196285ef390b4edfe0f0299a126f7 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 13:11:31 +0200 Subject: [PATCH 026/500] [conv] push_symbol --- .../src/stack-graphs-conv.tsg | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 0589e5098..4599ba506 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -393,7 +393,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @export_clause.source -> @source.push_exports_guard - attr (@source.push_exports_guard) "push" = "GUARD:EXPORTS" + attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" scan @source { "\"([^/\"]+)\.js\"$" { attr (@source.push) "push" = $1 @@ -534,7 +534,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ) { attr (@export_specifier.pop_guard_default) pop_symbol = "GUARD:DEFAULT" - attr (@export_specifier.push_guard_default) "push" = "GUARD:DEFAULT" + attr (@export_specifier.push_guard_default) push_symbol = "GUARD:DEFAULT" edge @export_specifier::exports -> @export_specifier.pop_guard_default edge @export_specifier.pop_guard_default -> @export_specifier.push_guard_default edge @export_specifier.push_guard_default -> @export_specifier.source @@ -578,7 +578,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @export_statement.after_scope -> @export_statement.before_scope - attr (@source.push_exports_guard) "push" = "GUARD:EXPORTS" + attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" scan @source { "\"([^/\"]+)\.js\"$" { attr (@source.push) "push" = $1 @@ -599,7 +599,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @export_statement.after_scope -> @export_statement.before_scope - attr (@source.push_exports_guard) "push" = "GUARD:EXPORTS" + attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" scan @source { "\"([^/\"]+)\.js\"$" { attr (@source.push) "push" = $1 @@ -669,7 +669,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (@source.push) "push" = $1 } } - attr (@source.push_guard_exports) "push" = "GUARD:EXPORTS" + attr (@source.push_guard_exports) push_symbol = "GUARD:EXPORTS" edge @source.push_guard_exports -> @source.push edge @source.push -> ROOT_NODE edge @import_clause.source -> @source.push_guard_exports @@ -776,7 +776,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; edge @mod_name.push -> ROOT_NODE ; ; attr (@name) "push", "reference" -; attr (@name.push_dot) "push" = "." +; attr (@name.push_dot) push_symbol = "." ; edge @name.push_dot -> @mod_name.push ; edge @name -> @name.push_dot ; @@ -798,7 +798,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @import_clause.after_scope -> @import_clause.before_scope attr (@default_name.pop) "pop" = @default_name, "definition" - attr (@default_name.push_guard_default) "push" = "GUARD:DEFAULT" + attr (@default_name.push_guard_default) push_symbol = "GUARD:DEFAULT" edge @default_name.pop -> @default_name.push_guard_default edge @default_name.push_guard_default -> @import_clause.source @@ -935,12 +935,12 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; the call sig's before scope comes from the drop node then flows into the body edge @call_sig.before_scope -> @fun_decl.value_drop attr (@call_sig.this_pop) pop_symbol = "this", "definition" - attr (@call_sig.this_push) "push" = "this" + attr (@call_sig.this_push) push_symbol = "this" edge @call_sig.this_pop -> @call_sig.this_push edge @call_sig.this_push -> @fun_decl.value_arg_scope edge @call_sig.before_scope -> @call_sig.this_pop attr (@call_sig.arguments_pop) pop_symbol = "arguments", "definition" - attr (@call_sig.arguments_push) "push" = "arguments" + attr (@call_sig.arguments_push) push_symbol = "arguments" edge @call_sig.arguments_pop -> @call_sig.arguments_push edge @call_sig.arguments_push -> @fun_decl.value_arg_scope edge @call_sig.before_scope -> @call_sig.arguments_pop @@ -958,7 +958,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n let @body::return_or_yield = @fun_decl.value_return ; method values have this nodes which need to be visible for constructor calls - attr (@fun_decl.value_this) "push" = "this" + attr (@fun_decl.value_this) push_symbol = "this" attr (@fun_decl.value_this_guard) "endpoint" attr (@fun_decl.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun_decl.value_call -> @fun_decl.value_this_guard @@ -1006,12 +1006,12 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; the call sig's before scope comes from the drop node then flows into the body edge @call_sig.before_scope -> @fun_decl.value_drop attr (@call_sig.this_pop) pop_symbol = "this", "definition" - attr (@call_sig.this_push) "push" = "this" + attr (@call_sig.this_push) push_symbol = "this" edge @call_sig.this_pop -> @call_sig.this_push edge @call_sig.this_push -> @fun_decl.value_arg_scope edge @call_sig.before_scope -> @call_sig.this_pop attr (@call_sig.arguments_pop) pop_symbol = "arguments", "definition" - attr (@call_sig.arguments_push) "push" = "arguments" + attr (@call_sig.arguments_push) push_symbol = "arguments" edge @call_sig.arguments_pop -> @call_sig.arguments_push edge @call_sig.arguments_push -> @fun_decl.value_arg_scope edge @call_sig.before_scope -> @call_sig.arguments_pop @@ -1028,7 +1028,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n let @body::return_or_yield = @fun_decl.value_return ; method values have this nodes which need to be visible for constructor calls - attr (@fun_decl.value_this) "push" = "this" + attr (@fun_decl.value_this) push_symbol = "this" attr (@fun_decl.value_this_guard) "endpoint" attr (@fun_decl.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun_decl.value_call -> @fun_decl.value_this_guard @@ -1159,7 +1159,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n let @body::return_or_yield = @method_def.method_value_return ; method values have this nodes which need to be visible for constructor calls - attr (@method_def.method_value_this) "push" = "this" + attr (@method_def.method_value_this) push_symbol = "this" attr (@method_def.method_value_this_guard) "endpoint" attr (@method_def.method_value_this_guard) pop_symbol = "GUARD:THIS" edge @method_def.method_value_call -> @method_def.method_value_this_guard @@ -1551,7 +1551,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @body.before_scope -> @object.after_scope edge @with_stmt.after_scope -> @body.after_scope - attr (@object.push_dot) "push" = "." + attr (@object.push_dot) push_symbol = "." edge @object.push_dot -> @object.value edge @body.before_scope -> @object.push_dot } @@ -1746,7 +1746,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @this.after_scope -> @this.before_scope ; this is a lookup, ie a push - attr (@this.value) "push" = "this", "reference" + attr (@this.value) push_symbol = "this", "reference" edge @this.value -> @this.before_scope } @@ -2011,12 +2011,12 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; then flows into the body, and includes a variable binding for "this" edge @call_sig.before_scope -> @fun.value_drop attr (@call_sig.this_pop) pop_symbol = "this", "definition" - attr (@call_sig.this_push) "push" = "this" + attr (@call_sig.this_push) push_symbol = "this" edge @call_sig.this_pop -> @call_sig.this_push edge @call_sig.this_push -> @fun.value_arg_scope edge @call_sig.before_scope -> @call_sig.this_pop attr (@call_sig.arguments_pop) pop_symbol = "arguments", "definition" - attr (@call_sig.arguments_push) "push" = "arguments" + attr (@call_sig.arguments_push) push_symbol = "arguments" edge @call_sig.arguments_pop -> @call_sig.arguments_push edge @call_sig.arguments_push -> @fun.value_arg_scope edge @call_sig.before_scope -> @call_sig.arguments_pop @@ -2033,7 +2033,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n let @body::return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls - attr (@fun.value_this) "push" = "this" + attr (@fun.value_this) push_symbol = "this" attr (@fun.value_this_guard) "endpoint" attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun.value_call -> @fun.value_this_guard @@ -2092,7 +2092,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n let @body::return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls - attr (@fun.value_this) "push" = "this" + attr (@fun.value_this) push_symbol = "this" attr (@fun.value_this_guard) "endpoint" attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun.value_call -> @fun.value_this_guard @@ -2121,7 +2121,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @param.after_scope -> @param.pop ; parameters jump to the pushed argument scope - attr (@param.arg_index) "push" = "0" + attr (@param.arg_index) push_symbol = "0" edge @param.covalue -> @param.arg_index edge @param.arg_index -> @fun.value_arg_scope } @@ -2182,7 +2182,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n let @body::return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls - attr (@fun.value_this) "push" = "this" + attr (@fun.value_this) push_symbol = "this" attr (@fun.value_this_guard) "endpoint" attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun.value_call -> @fun.value_this_guard @@ -2223,8 +2223,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n arguments:(_)@arguments)@call_expr { ; value is a call, ie a push "()" node w/ "push-scope" @arguments - attr (@call_expr.return_guard) "push" = "GUARD:RETURN" - attr (@call_expr.call) "push" = "()", "push-scope" = @arguments.arg_scope + attr (@call_expr.return_guard) push_symbol = "GUARD:RETURN" + attr (@call_expr.call) push_symbol = "()", "push-scope" = @arguments.arg_scope edge @call_expr.value -> @call_expr.return_guard edge @call_expr.return_guard -> @call_expr.call edge @call_expr.call -> @function.value @@ -2321,7 +2321,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; value is a member projection on the value of the object ie. a push then push dot attr (@property.push) "push", "reference" ;attr (@member_expr.value) "push" = @property.pop - attr (@member_expr.push_dot) "push" = "." + attr (@member_expr.push_dot) push_symbol = "." edge @property.push -> @member_expr.push_dot ;edge @member_expr.value -> @member_expr.push_dot edge @member_expr.value -> @property.push @@ -2352,7 +2352,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (@index.push) "reference" - attr (@index.push_dot) "push" = "." + attr (@index.push_dot) push_symbol = "." edge @subscript_expression.value -> @index.push edge @index.push -> @index.push_dot edge @index.push_dot -> @object.value @@ -2365,7 +2365,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (@index.push) "reference" - attr (@index.push_dot) "push" = "." + attr (@index.push_dot) push_symbol = "." edge @subscript_expression.value -> @index.push edge @index.push -> @index.push_dot edge @index.push_dot -> @object.value @@ -2384,10 +2384,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @arguments.before_scope -> @constructor.after_scope edge @new_expr.after_scope -> @arguments.after_scope - attr (@new_expr.call) "push" = "()", "push-scope" = @arguments.arg_scope + attr (@new_expr.call) push_symbol = "()", "push-scope" = @arguments.arg_scope ; we guard for constructors for the case where we have a "true" class - attr (@constructor.constructor) "push" = "GUARD:CONSTRUCTOR" + attr (@constructor.constructor) push_symbol = "GUARD:CONSTRUCTOR" edge @new_expr.call -> @constructor.constructor edge @constructor.constructor -> @constructor.value @@ -2397,7 +2397,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; value coming from the constructor call - attr (@new_expr.guard_this) "push" = "GUARD:THIS" + attr (@new_expr.guard_this) push_symbol = "GUARD:THIS" edge @new_expr.value -> @new_expr.guard_this edge @new_expr.guard_this -> @new_expr.call @@ -2952,7 +2952,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n value:(_)@value_pat)@pair_pat { ; covalues flow in dotted - attr (@key.push_dot) "push" = "." + attr (@key.push_dot) push_symbol = "." edge @value_pat.covalue -> @key.push edge @key.push -> @key.push_dot edge @key.push_dot -> @pair_pat.covalue @@ -3010,7 +3010,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @left_pat.after_scope -> @left_pat.before_scope attr (@left_pat.push) "push" = @left_pat, "reference" - attr (@left_pat.push_dot) "push" = "." + attr (@left_pat.push_dot) push_symbol = "." attr (@left_pat.pop) "pop" = @left_pat, "definition" edge @left_pat.pop -> @left_pat.push edge @left_pat.push -> @left_pat.push_dot @@ -3061,7 +3061,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; array pattern elements (array_pattern (_)@element_pat)@array_pat { attr (@element_pat.element_index_push) "push" = (child-index @element_pat), "reference" - attr (@array_pat.element_index_push_dot) "push" = "." + attr (@array_pat.element_index_push_dot) push_symbol = "." edge @element_pat.covalue -> @element_pat.element_index_push edge @element_pat.element_index_push -> @array_pat.element_index_push_dot edge @array_pat.element_index_push_dot -> @array_pat.covalue @@ -3212,7 +3212,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n } } - attr (@mod_name.module_guard) "push" = "GUARD:EXPORTS" + attr (@mod_name.module_guard) push_symbol = "GUARD:EXPORTS" edge @call_expr.value -> @mod_name.module_guard edge @mod_name.module_guard -> @mod_name.push edge @mod_name.push -> ROOT_NODE From d467ea30801749ddc87d718ef6970cecf3ac0a69 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 13:12:06 +0200 Subject: [PATCH 027/500] [conv] prog --- .../src/stack-graphs-conv.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 4599ba506..5073647f8 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -299,7 +299,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (program)@prog { scan FILE_PATH { "([^/]+)\.js$" { - attr (@prog.module_pop) "definition", "pop" = $1 + attr (@prog.module_pop) symbol_definition = $1, source_node = prog attr (@prog.module_pop) "no_span" } } From d10473c3f96d95701643bfadce24b06092608818 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 13:13:01 +0200 Subject: [PATCH 028/500] [conv] empty_source_span --- .../src/stack-graphs-conv.tsg | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 5073647f8..3e04bf45a 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -300,7 +300,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n scan FILE_PATH { "([^/]+)\.js$" { attr (@prog.module_pop) symbol_definition = $1, source_node = prog - attr (@prog.module_pop) "no_span" + attr (@prog.module_pop) empty_source_span } } @@ -311,13 +311,13 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @prog.module_pop -> @prog.module_scope edge @prog.module_scope -> @prog.after_scope - attr (@prog) "no_span" - attr (@prog.module_pop) "no_span" - attr (@prog.module_scope) "no_span" - attr (@prog.exports) "no_span" - attr (@prog.exports_pop) "no_span" - attr (@prog.before_scope) "no_span" - attr (@prog.after_scope) "no_span" + attr (@prog) empty_source_span + attr (@prog.module_pop) empty_source_span + attr (@prog.module_scope) empty_source_span + attr (@prog.exports) empty_source_span + attr (@prog.exports_pop) empty_source_span + attr (@prog.before_scope) empty_source_span + attr (@prog.after_scope) empty_source_span let @prog::prog = @prog let @prog::exports = @prog.exports From dd575970798759aa31d3ee937dbbad2966e06417 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 13:15:14 +0200 Subject: [PATCH 029/500] [conv] node_definition --- .../src/stack-graphs-conv.tsg | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 3e04bf45a..167883c5e 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -425,7 +425,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; TODO this doesn't support destructuring exports - attr (@name.pop) "pop" = @name, "definition" + attr (@name.pop) node_definition = @name attr (@name.push) "push" = @name edge @export_stmt::exports -> @name.pop edge @name.pop -> @decl.value @@ -499,7 +499,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (#not-eq? @name "default") ) { - attr (@name.pop) "pop" = @name, "definition" + attr (@name.pop) node_definition = @name attr (@name.push) "push" = @name, "reference" edge @name.pop -> @name.push edge @name.push -> @export_specifier.source @@ -516,7 +516,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ) { - attr (@alias.pop) "pop" = @alias, "definition" + attr (@alias.pop) node_definition = @alias attr (@name.push) "push" = @name, "reference" edge @alias.pop -> @name.push edge @name.push -> @export_specifier.source @@ -605,7 +605,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (@source.push) "push" = $1 } } - attr (@alias.pop) "pop" = @alias, "definition" + attr (@alias.pop) node_definition = @alias attr (@alias.pop_dot) pop_symbol = "." edge @export_statement::exports -> @alias.pop edge @alias.pop -> @alias.pop_dot @@ -643,7 +643,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @namespace_import.after_scope -> @namespace_import.before_scope - attr (@imported_as.pop) "pop" = @imported_as, "definition" + attr (@imported_as.pop) node_definition = @imported_as attr (@imported_as.pop_dot) pop_symbol = "." edge @imported_as.pop -> @imported_as.pop_dot edge @imported_as.pop_dot -> @namespace_import.source @@ -731,7 +731,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @import_specifier.after_scope -> @import_specifier.before_scope - attr (@name.pop) "pop" = @name, "definition" + attr (@name.pop) node_definition = @name attr (@name.push) "push" = @name, "reference" edge @name.pop -> @name.push edge @name.push -> @import_specifier.source @@ -751,7 +751,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @import_specifier.after_scope -> @import_specifier.before_scope - attr (@alias.pop) "pop" = @alias, "definition" + attr (@alias.pop) node_definition = @alias attr (@name.push) "push" = @name, "reference" edge @alias.pop -> @name.push edge @name.push -> @import_specifier.source @@ -797,7 +797,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @import_clause.after_scope -> @import_clause.before_scope - attr (@default_name.pop) "pop" = @default_name, "definition" + attr (@default_name.pop) node_definition = @default_name attr (@default_name.push_guard_default) push_symbol = "GUARD:DEFAULT" edge @default_name.pop -> @default_name.push_guard_default edge @default_name.push_guard_default -> @import_clause.source @@ -923,7 +923,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @fun_decl.after_scope -> @fun_decl.before_scope ; with an augmentation for the function - attr (@name.pop) "pop" = @name, "definition" + attr (@name.pop) node_definition = @name edge @fun_decl.after_scope -> @name.pop edge @name.pop -> @fun_decl.value @@ -993,7 +993,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @fun_decl.after_scope -> @fun_decl.before_scope ; with an augmentation for the function - attr (@name.pop) "pop" = @name, "definition" + attr (@name.pop) node_definition = @name edge @fun_decl.after_scope -> @name.pop edge @name.pop -> @fun_decl.value @@ -1059,7 +1059,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (@name.pop) "syntax_type" = "class" - attr (@name.pop) "pop" = @name, "definition" + attr (@name.pop) node_definition = @name edge @class_decl.after_scope -> @name.pop edge @name.pop -> @class_decl.value @@ -1122,7 +1122,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (#not-eq? @name "constructor") ) { ; augmentation for the method - attr (@name.pop) "pop" = @name, "definition" + attr (@name.pop) node_definition = @name attr (@name.pop_dot) pop_symbol = "." edge @method_def.after_scope -> @name.pop_dot edge @name.pop_dot -> @name.pop @@ -1185,7 +1185,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (field_definition property:(property_identifier)@property)@field_def { - attr (@property.pop) "pop" = @property, "definition" + attr (@property.pop) node_definition = @property attr (@property.pop_dot) pop_symbol = "." edge @field_def.after_scope -> @property.pop_dot edge @property.pop_dot -> @property.pop @@ -1849,7 +1849,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @keyval.rhsvar_value -> @keyval.rhsvar_before_scope ; shorthand property identifiers augment the object value with a member binding - attr (@keyval.boundvar_pop) "pop" = @keyval, "definition" + attr (@keyval.boundvar_pop) node_definition = @keyval attr (@object.field_pop_dot) pop_symbol = "." edge @keyval.boundvar_pop -> @keyval.rhsvar_value @@ -1871,7 +1871,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; pairs augment the object value with a member binding ; This is done differently depending on what the key is. See next rules. - ; attr (@key.pop) "pop" = @key, "definition" + ; attr (@key.pop) node_definition = @key attr (@key.pop) "definition" attr (@object.field_pop_dot) pop_symbol = "." @@ -1988,7 +1988,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (@name.pop) "syntax_type" = "function" ; if the function has a name, this is bound the callsig's before scope - attr (@name.pop) "pop" = @name, "definition" + attr (@name.pop) node_definition = @name edge @call_sig.before_scope -> @name.pop edge @name.pop -> @fun.value } @@ -2116,7 +2116,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @param.after_scope -> @param.before_scope ; but augmented with a pop, b/c it's not a pattern - attr (@param.pop) "pop" = @param, "definition" + attr (@param.pop) node_definition = @param edge @param.pop -> @param.covalue edge @param.after_scope -> @param.pop @@ -2148,7 +2148,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (@name.pop) "syntax_type" = "function" ; if the function has a name, this is bound the callsig's before scope - attr (@name.pop) "pop" = @name, "definition" + attr (@name.pop) node_definition = @name edge @call_sig.before_scope -> @name.pop edge @name.pop -> @fun.value } @@ -2504,7 +2504,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n right: (_)@right)@assignment_expr { ; augments the scope by adding a lookup edge, ie. a pop - attr (@left.pop) "pop" = @left, "definition" + attr (@left.pop) node_definition = @left edge @assignment_expr.after_scope -> @left.pop edge @left.pop -> @right.value @@ -2524,7 +2524,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @this.drop -> @this.pop attr (@this.pop) pop_symbol = "this" attr (@this.pop_dot) pop_symbol = "." - attr (@property.pop) "pop" = @property, "definition" + attr (@property.pop) node_definition = @property edge @assignment_expr.after_scope -> @this.drop edge @assignment_expr.after_scope -> @this.pop edge @this.pop -> @this.pop_dot @@ -2560,7 +2560,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n right:(_)@right)@augmented_assignment_expr { ; augment the scope - attr (@left.pop) "pop" = @left, "definition" + attr (@left.pop) node_definition = @left attr (@left.push) "push" = @left, "reference" edge @left.push -> @augmented_assignment_expr.before_scope edge @left.pop -> @left.push @@ -2635,7 +2635,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (@name.pop) "syntax_type" = "class" - attr (@name.pop) "pop" = @name, "definition" + attr (@name.pop) node_definition = @name edge @body.before_scope -> @name.pop edge @name.pop -> @class.value } @@ -2890,7 +2890,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (pattern/identifier)@ident_pat { ; scope flows through, binding via a pop edge that goes to an unknown value - attr (@ident_pat.pop) "pop" = @ident_pat, "definition" + attr (@ident_pat.pop) node_definition = @ident_pat edge @ident_pat.pop -> @ident_pat.covalue edge @ident_pat.after_scope -> @ident_pat.before_scope edge @ident_pat.after_scope -> @ident_pat.pop @@ -3011,7 +3011,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (@left_pat.push) "push" = @left_pat, "reference" attr (@left_pat.push_dot) push_symbol = "." - attr (@left_pat.pop) "pop" = @left_pat, "definition" + attr (@left_pat.pop) node_definition = @left_pat edge @left_pat.pop -> @left_pat.push edge @left_pat.push -> @left_pat.push_dot edge @left_pat.push_dot -> @left_pat.covalue @@ -3103,7 +3103,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (rest_pattern (_)@name)@rest_pat { ; scope flows through, binding via a pop edge that goes to an unknown value - attr (@rest_pat.pop) "pop" = @name, "definition" + attr (@rest_pat.pop) node_definition = @name edge @rest_pat.after_scope -> @rest_pat.before_scope edge @rest_pat.after_scope -> @rest_pat.pop } @@ -3141,7 +3141,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (#eq? @extend "extend") ) { - attr (@object.pop) "pop" = @object, "definition" + attr (@object.pop) node_definition = @object edge @call_expr.after_scope -> @object.pop edge @object.pop -> @new_fields.value @@ -3173,7 +3173,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (#eq? @exports "exports") ) { - attr (@property.pop) "pop" = @property, "definition" + attr (@property.pop) node_definition = @property attr (@property.pop_dot) pop_symbol = "." edge @assignment_expr::exports -> @property.pop_dot edge @property.pop_dot -> @property.pop @@ -3324,7 +3324,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ]@right) { attr (@left.ignore_guard) pop_symbol = "GUARD:GANDALF" - attr (@left.definiens_hook) "pop" = @left, "definition" + attr (@left.definiens_hook) node_definition = @left attr (@left.definiens_hook) "definiens" = @right edge ROOT_NODE -> @left.ignore_guard edge @left.ignore_guard -> @left.definiens_hook @@ -3365,7 +3365,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ]@value) { attr (@name.ignore_guard) pop_symbol = "GUARD:GANDALF" -attr (@name.definiens_hook) "pop" = @name, "definition" +attr (@name.definiens_hook) node_definition = @name attr (@name.definiens_hook) "definiens" = @value edge ROOT_NODE -> @name.ignore_guard edge @name.ignore_guard -> @name.definiens_hook From 336885bf2ec6e1a984e9cafbcdd37223580beb72 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 13:15:40 +0200 Subject: [PATCH 030/500] [conv] node_reference --- .../src/stack-graphs-conv.tsg | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 167883c5e..9e832722c 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -500,7 +500,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ) { attr (@name.pop) node_definition = @name - attr (@name.push) "push" = @name, "reference" + attr (@name.push) node_reference = @name edge @name.pop -> @name.push edge @name.push -> @export_specifier.source @@ -517,7 +517,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ) { attr (@alias.pop) node_definition = @alias - attr (@name.push) "push" = @name, "reference" + attr (@name.push) node_reference = @name edge @alias.pop -> @name.push edge @name.push -> @export_specifier.source @@ -732,7 +732,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @import_specifier.after_scope -> @import_specifier.before_scope attr (@name.pop) node_definition = @name - attr (@name.push) "push" = @name, "reference" + attr (@name.push) node_reference = @name edge @name.pop -> @name.push edge @name.push -> @import_specifier.source edge @import_specifier.after_scope -> @name.pop @@ -752,7 +752,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @import_specifier.after_scope -> @import_specifier.before_scope attr (@alias.pop) node_definition = @alias - attr (@name.push) "push" = @name, "reference" + attr (@name.push) node_reference = @name edge @alias.pop -> @name.push edge @name.push -> @import_specifier.source edge @import_specifier.after_scope -> @alias.pop @@ -1845,7 +1845,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @keyval.after_scope -> @keyval.before_scope ; shorthand property identifiers have secret variable exprs - attr (@keyval.rhsvar_value) "push" = @keyval, "reference" + attr (@keyval.rhsvar_value) node_reference = @keyval edge @keyval.rhsvar_value -> @keyval.rhsvar_before_scope ; shorthand property identifiers augment the object value with a member binding @@ -2342,7 +2342,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; value is a subscript lookup, ie a push then push dot ; this is done differently depending on what the index is - ; attr (@index.push) "push" = @index, "reference" + ; attr (@index.push) node_reference = @index } @@ -2561,7 +2561,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; augment the scope attr (@left.pop) node_definition = @left - attr (@left.push) "push" = @left, "reference" + attr (@left.push) node_reference = @left edge @left.push -> @augmented_assignment_expr.before_scope edge @left.pop -> @left.push edge @left.pop -> @right.value @@ -2966,7 +2966,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (pair_pattern key:(property_identifier)@key)@pair_pattern { - attr (@key.push) "push" = @key, "reference" + attr (@key.push) node_reference = @key } (pair_pattern @@ -3009,7 +3009,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @left_pat.after_scope -> @left_pat.before_scope - attr (@left_pat.push) "push" = @left_pat, "reference" + attr (@left_pat.push) node_reference = @left_pat attr (@left_pat.push_dot) push_symbol = "." attr (@left_pat.pop) node_definition = @left_pat edge @left_pat.pop -> @left_pat.push From b1fcd4567ccfa1a0791f88ce46373f301abc9062 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 13:16:57 +0200 Subject: [PATCH 031/500] [conv] ::prog --- .../src/stack-graphs-conv.tsg | 1 - 1 file changed, 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 9e832722c..d4c0ca386 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -319,7 +319,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (@prog.before_scope) empty_source_span attr (@prog.after_scope) empty_source_span - let @prog::prog = @prog let @prog::exports = @prog.exports attr (@prog.exports_pop) pop_symbol = "GUARD:EXPORTS" edge @prog.module_pop -> @prog.exports_pop From 6618f870ef42b596a6a381b2e164394955fca58e Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 13:19:15 +0200 Subject: [PATCH 032/500] [conv] ::null --- .../src/stack-graphs-conv.tsg | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index d4c0ca386..7e8bf5351 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -289,6 +289,14 @@ attribute node_symbol = node => symbol = (source-text node), source_n } +; ## Inherited + +inherit .null + +(program)@prog { + node @prog.null +} + ;; ## Programs ;; ### Attributes Defined on Programs @@ -1765,7 +1773,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @null.after_scope -> @null.before_scope ; the value of null is the null primitive - edge @null.value -> @null::null + edge @null.value -> @null.null } @@ -2261,7 +2269,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n function: (_)@function arguments:(_)@arguments)@call_expr { - edge @arguments.arg_this -> @call_expr::null + edge @arguments.arg_this -> @call_expr.null } (call_expression arguments:(arguments (_)@arg)@arguments) { From 6cea20be33c5d518a15bbb6e0304318a32ceb335 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 13:20:19 +0200 Subject: [PATCH 033/500] [conv] ::string --- .../src/stack-graphs-conv.tsg | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 7e8bf5351..089f071ea 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -292,9 +292,11 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; ## Inherited inherit .null +inherit .string (program)@prog { node @prog.null + node @prog.string } ;; ## Programs @@ -1659,7 +1661,7 @@ inherit .null edge @string.after_scope -> @string.before_scope ; the value of a string is the string primitive - edge @string.value -> @string::string + edge @string.value -> @string.string } From 11d9ebc04b460a8863860f74c993fe5affa9b439 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 13:24:07 +0200 Subject: [PATCH 034/500] [conv] ::exports --- .../src/stack-graphs-conv.tsg | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 089f071ea..91a96f85a 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -291,6 +291,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; ## Inherited +inherit .exports inherit .null inherit .string @@ -329,7 +330,6 @@ inherit .string attr (@prog.before_scope) empty_source_span attr (@prog.after_scope) empty_source_span - let @prog::exports = @prog.exports attr (@prog.exports_pop) pop_symbol = "GUARD:EXPORTS" edge @prog.module_pop -> @prog.exports_pop edge @prog.exports_pop -> @prog.exports @@ -436,7 +436,7 @@ inherit .string attr (@name.pop) node_definition = @name attr (@name.push) "push" = @name - edge @export_stmt::exports -> @name.pop + edge @export_stmt.exports -> @name.pop edge @name.pop -> @decl.value } @@ -458,7 +458,7 @@ inherit .string ]@pattern)) ])@export_stmt { - edge @export_stmt::exports -> @pattern.new_bindings + edge @export_stmt.exports -> @pattern.new_bindings } @@ -513,7 +513,7 @@ inherit .string edge @name.pop -> @name.push edge @name.push -> @export_specifier.source - edge @export_specifier::exports -> @name.pop + edge @export_specifier.exports -> @name.pop } ( @@ -530,7 +530,7 @@ inherit .string edge @alias.pop -> @name.push edge @name.push -> @export_specifier.source - edge @export_specifier::exports -> @alias.pop + edge @export_specifier.exports -> @alias.pop } ( @@ -544,7 +544,7 @@ inherit .string attr (@export_specifier.pop_guard_default) pop_symbol = "GUARD:DEFAULT" attr (@export_specifier.push_guard_default) push_symbol = "GUARD:DEFAULT" - edge @export_specifier::exports -> @export_specifier.pop_guard_default + edge @export_specifier.exports -> @export_specifier.pop_guard_default edge @export_specifier.pop_guard_default -> @export_specifier.push_guard_default edge @export_specifier.push_guard_default -> @export_specifier.source @@ -563,7 +563,7 @@ inherit .string attr (@export_specifier.guard_default) pop_symbol = "GUARD:DEFAULT" edge @name.push -> @export_specifier.source edge @export_specifier.guard_default -> @name.push - edge @export_specifier::exports -> @export_specifier.guard_default + edge @export_specifier.exports -> @export_specifier.guard_default } ; simple default exports @@ -575,7 +575,7 @@ inherit .string attr (@export_stmt.default_guard) pop_symbol = "GUARD:DEFAULT", "definition" edge @default_expr.before_scope -> @export_stmt.before_scope edge @export_stmt.after_scope -> @default_expr.after_scope - edge @export_stmt::exports -> @export_stmt.default_guard + edge @export_stmt.exports -> @export_stmt.default_guard edge @export_stmt.default_guard -> @default_expr.value } @@ -594,7 +594,7 @@ inherit .string } } - edge @export_statement::exports -> @source.push_exports_guard + edge @export_statement.exports -> @source.push_exports_guard edge @source.push_exports_guard -> @source.push edge @source.push -> ROOT_NODE @@ -616,7 +616,7 @@ inherit .string } attr (@alias.pop) node_definition = @alias attr (@alias.pop_dot) pop_symbol = "." - edge @export_statement::exports -> @alias.pop + edge @export_statement.exports -> @alias.pop edge @alias.pop -> @alias.pop_dot edge @alias.pop_dot -> @source.push_exports_guard edge @source.push_exports_guard -> @source.push @@ -3184,7 +3184,7 @@ inherit .string attr (@property.pop) node_definition = @property attr (@property.pop_dot) pop_symbol = "." - edge @assignment_expr::exports -> @property.pop_dot + edge @assignment_expr.exports -> @property.pop_dot edge @property.pop_dot -> @property.pop edge @property.pop -> @right.value } @@ -3199,7 +3199,7 @@ inherit .string (#eq? @exports "exports") ) { - edge @assignment_expr::exports -> @right.value + edge @assignment_expr.exports -> @right.value } ;; ## CommonJS-style Imports From 99aeabba938113b341f9ddba973577a9fc35030e Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 13:25:20 +0200 Subject: [PATCH 035/500] [conv] ::number --- .../src/stack-graphs-conv.tsg | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 91a96f85a..fc481c71a 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -293,10 +293,12 @@ attribute node_symbol = node => symbol = (source-text node), source_n inherit .exports inherit .null +inherit .number inherit .string (program)@prog { node @prog.null + node @prog.number node @prog.string } @@ -1713,7 +1715,7 @@ inherit .string edge @number.after_scope -> @number.before_scope ; the value of a number is the number primitive - edge @number.value -> @number::number + edge @number.value -> @number.number } From f75b0f986507e3839a96a998623e3aa5e3f462fb Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 13:27:26 +0200 Subject: [PATCH 036/500] [conv] ::number_prototype --- .../src/stack-graphs-conv.tsg | 4 ---- 1 file changed, 4 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index fc481c71a..7d9dd1821 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -260,10 +260,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.module_pop node @node.module_scope node @node.new_bindings - node @node.number_prototype - node @node.number_prototype_toString_method_value - node @node.number_prototype_toString_method_value_return - node @node.number_prototype_valueOf_method_value node @node.pop node @node.pop_dot node @node.pop_guard_default From f111d75c9ed035974f387c30edc7536a05c565ae Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 13:28:39 +0200 Subject: [PATCH 037/500] [conv] ::return_or_yield --- .../src/stack-graphs-conv.tsg | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 7d9dd1821..f1e8003b9 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -290,6 +290,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n inherit .exports inherit .null inherit .number +inherit .return_or_yield inherit .string (program)@prog { @@ -962,7 +963,7 @@ inherit .string attr (@fun_decl.value_return) "endpoint" attr (@fun_decl.value_return) pop_symbol = "GUARD:RETURN" edge @fun_decl.value_call -> @fun_decl.value_return - let @body::return_or_yield = @fun_decl.value_return + let @body.return_or_yield = @fun_decl.value_return ; method values have this nodes which need to be visible for constructor calls attr (@fun_decl.value_this) push_symbol = "this" @@ -1032,7 +1033,7 @@ inherit .string attr (@fun_decl.value_return) "endpoint" attr (@fun_decl.value_return) pop_symbol = "GUARD:RETURN" edge @fun_decl.value_call -> @fun_decl.value_return - let @body::return_or_yield = @fun_decl.value_return + let @body.return_or_yield = @fun_decl.value_return ; method values have this nodes which need to be visible for constructor calls attr (@fun_decl.value_this) push_symbol = "this" @@ -1163,7 +1164,7 @@ inherit .string attr (@method_def.method_value_return) "endpoint" attr (@method_def.method_value_return) pop_symbol = "GUARD:RETURN" edge @method_def.method_value_call -> @method_def.method_value_return - let @body::return_or_yield = @method_def.method_value_return + let @body.return_or_yield = @method_def.method_value_return ; method values have this nodes which need to be visible for constructor calls attr (@method_def.method_value_this) push_symbol = "this" @@ -1598,7 +1599,7 @@ inherit .string edge @return_stmt.after_scope -> @returned_expr.after_scope ; return statements hook up to the call node of the function value - edge @return_stmt::return_or_yield -> @returned_expr.value + edge @return_stmt.return_or_yield -> @returned_expr.value } @@ -2037,7 +2038,7 @@ inherit .string attr (@fun.value_return) "endpoint" attr (@fun.value_return) pop_symbol = "GUARD:RETURN" edge @fun.value_call -> @fun.value_return - let @body::return_or_yield = @fun.value_return + let @body.return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls attr (@fun.value_this) push_symbol = "this" @@ -2096,7 +2097,7 @@ inherit .string attr (@fun.value_return) "endpoint" attr (@fun.value_return) pop_symbol = "GUARD:RETURN" edge @fun.value_call -> @fun.value_return - let @body::return_or_yield = @fun.value_return + let @body.return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls attr (@fun.value_this) push_symbol = "this" @@ -2113,7 +2114,7 @@ inherit .string ; arrow functions returning exprs need special rules for getting the return value hooked up (arrow_function body:(expression)@return_expr) { - edge @return_expr::return_or_yield -> @return_expr.value + edge @return_expr.return_or_yield -> @return_expr.value } (arrow_function @@ -2186,7 +2187,7 @@ inherit .string attr (@fun.value_return) "endpoint" attr (@fun.value_return) pop_symbol = "GUARD:RETURN" edge @fun.value_call -> @fun.value_return - let @body::return_or_yield = @fun.value_return + let @body.return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls attr (@fun.value_this) push_symbol = "this" @@ -2621,7 +2622,7 @@ inherit .string edge @yield_expr.after_scope -> @yielded_expr.after_scope ; yield expressions hook up to the call node of the function value - edge @yield_expr::return_or_yield -> @yielded_expr.value + edge @yield_expr.return_or_yield -> @yielded_expr.value } From d7ec123c8d053a15232a8f5dd7d05b3f6251c4ee Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 14:34:14 +0200 Subject: [PATCH 038/500] [conv] remaining :: --- .../src/stack-graphs-conv.tsg | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index f1e8003b9..06509749d 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -287,16 +287,26 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; ## Inherited +inherit .Regex_prototype +inherit .arguments_prototype +inherit .boolean +inherit .empty_object inherit .exports inherit .null inherit .number inherit .return_or_yield inherit .string +inherit .undefined (program)@prog { + node @node.Regex_prototype + node @node.arguments_prototype + node @node.empty_object + node @prog.boolean node @prog.null node @prog.number node @prog.string + node @prog.undefined } ;; ## Programs @@ -1735,7 +1745,7 @@ inherit .string edge @true.after_scope -> @true.before_scope ; the value of true is a boolean primitive - edge @true.value -> @true::boolean + edge @true.value -> @true.boolean } (false)@false { @@ -1743,7 +1753,7 @@ inherit .string edge @false.after_scope -> @false.before_scope ; the value of false is a boolean primitive - edge @false.value -> @false::boolean + edge @false.value -> @false.boolean } @@ -1785,7 +1795,7 @@ inherit .string edge @undefined.after_scope -> @undefined.before_scope ; the value of undefined is the undefined primitive - edge @undefined.value -> @undefined::undefined + edge @undefined.value -> @undefined.undefined } @@ -1796,7 +1806,7 @@ inherit .string edge @regex.after_scope -> @regex.before_scope ; the value of a regex is the Regex prototype - edge @regex.value -> @regex::Regex_prototype + edge @regex.value -> @regex.Regex_prototype } @@ -2247,7 +2257,7 @@ inherit .string edge @arguments.arg_scope -> @arguments.arg_arguments edge @arguments.arg_arguments -> @arguments.arg_arguments_dot edge @arguments.arg_arguments_dot -> @arguments.arg_scope_no_this - edge @arguments.arg_arguments -> @call_expr::arguments_prototype + edge @arguments.arg_arguments -> @call_expr.arguments_prototype } ; special case to make `this` bind correctly in calls of the forms `x.f(...)` @@ -2414,7 +2424,7 @@ inherit .string attr (@arguments.arg_this) pop_symbol = "this", "definition" edge @arguments.arg_scope -> @arguments.arg_this - edge @arguments.arg_this -> @new_expr::empty_object + edge @arguments.arg_this -> @new_expr.empty_object } (new_expression From c268a0b025618ec890540abdb84d38de4e2f52a2 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 14:35:23 +0200 Subject: [PATCH 039/500] [conv] ::number_prototype --- .../src/stack-graphs-conv.tsg | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 06509749d..bbc1a6ca6 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -107,7 +107,7 @@ ;; ``````stgdoc ;; (number)@num { ;; attr (@num.value) pop_symbol = "NUM_VAL" -;; edge @num.value -> @num::number_prototype +;; edge @num.value -> @num.number_prototype ;; } ;; `````` @@ -115,11 +115,13 @@ ;; want to define number prototype, something like this: ;; ``````stgdoc +;; inherit .number_prototype +;; ;; (program)@prog { ;; ;; ... ;; -;; let @prog::number_prototype = @prog.number_prototype +;; node @prog.number_prototype ;; edge @prog.number_prototype -> @prog.number_prototype_toString_method_value ;; edge @prog.number_prototype -> @prog.number_prototype_valueOf_method_value ;; ...etc From 0dfcea7b5cde4f9268f9faab0205974ca18e3b8a Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 14:36:35 +0200 Subject: [PATCH 040/500] [conv] push_symbol --- .../src/stack-graphs-conv.tsg | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index bbc1a6ca6..046a4a001 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -416,7 +416,7 @@ inherit .undefined attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" scan @source { "\"([^/\"]+)\.js\"$" { - attr (@source.push) "push" = $1 + attr (@source.push) push_symbol = $1 } } edge @source.push_exports_guard -> @source.push @@ -601,7 +601,7 @@ inherit .undefined attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" scan @source { "\"([^/\"]+)\.js\"$" { - attr (@source.push) "push" = $1 + attr (@source.push) push_symbol = $1 } } @@ -622,7 +622,7 @@ inherit .undefined attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" scan @source { "\"([^/\"]+)\.js\"$" { - attr (@source.push) "push" = $1 + attr (@source.push) push_symbol = $1 } } attr (@alias.pop) node_definition = @alias @@ -686,7 +686,7 @@ inherit .undefined scan @source { "\"([^/\"]+)\.js\"$" { - attr (@source.push) "push" = $1 + attr (@source.push) push_symbol = $1 } } attr (@source.push_guard_exports) push_symbol = "GUARD:EXPORTS" @@ -790,7 +790,7 @@ inherit .undefined ; ; scope passes through, augmented by the identifier ; scan @mod_name { ; "\"([^/\"]+)\.js\"$" { -; attr (@mod_name.push) "push" = $1, "reference" +; attr (@mod_name.push) symbol_reference = $1, source_node = @mod_name ; } ; } ; edge @mod_name.push -> ROOT_NODE @@ -3228,7 +3228,7 @@ inherit .undefined scan @mod_name { "\"([^/\"]+)\.js\"$" { - attr (@mod_name.push) "push" = $1 + attr (@mod_name.push) push_symbol = $1 } } From f056230dc7d81ed41cd69665c28fe1c3199d9506 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 14:37:56 +0200 Subject: [PATCH 041/500] [conv] push_node --- .../src/stack-graphs-conv.tsg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 046a4a001..73c0bca8b 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -446,7 +446,7 @@ inherit .undefined ; TODO this doesn't support destructuring exports attr (@name.pop) node_definition = @name - attr (@name.push) "push" = @name + attr (@name.push) push_node = @name edge @export_stmt.exports -> @name.pop edge @name.pop -> @decl.value } @@ -570,7 +570,7 @@ inherit .undefined ) { - attr (@name.push) "push" = @name + attr (@name.push) push_node = @name attr (@export_specifier.guard_default) pop_symbol = "GUARD:DEFAULT" edge @name.push -> @export_specifier.source edge @export_specifier.guard_default -> @name.push @@ -2340,7 +2340,7 @@ inherit .undefined ; value is a member projection on the value of the object ie. a push then push dot attr (@property.push) "push", "reference" - ;attr (@member_expr.value) "push" = @property.pop + ;attr (@member_expr.value) push_node = @property.pop attr (@member_expr.push_dot) push_symbol = "." edge @property.push -> @member_expr.push_dot ;edge @member_expr.value -> @member_expr.push_dot @@ -2389,7 +2389,7 @@ inherit .undefined edge @subscript_expression.value -> @index.push edge @index.push -> @index.push_dot edge @index.push_dot -> @object.value - attr (@index.push) "push" = @index + attr (@index.push) push_node = @index } From a5306f9b4467f5aa540b1650e18ce10858be7636 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 14:40:43 +0200 Subject: [PATCH 042/500] [conv] push_node --- .../src/stack-graphs-conv.tsg | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 73c0bca8b..dd9fded9f 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -795,7 +795,7 @@ inherit .undefined ; } ; edge @mod_name.push -> ROOT_NODE ; -; attr (@name) "push", "reference" +; attr (@name) node_reference = @name ; attr (@name.push_dot) push_symbol = "." ; edge @name.push_dot -> @mod_name.push ; edge @name -> @name.push_dot @@ -994,7 +994,7 @@ inherit .undefined (formal_parameters (_)@param))@fun_decl { ; parameters jump to the pushed argument scope - attr (@param.arg_index) "push" = (child-index @param) + attr (@param.arg_index) push_symbol = (child-index @param) edge @param.covalue -> @param.arg_index edge @param.arg_index -> @fun_decl.value_arg_scope } @@ -1064,7 +1064,7 @@ inherit .undefined (formal_parameters (_)@param))@fun_decl { ; parameters jump to the pushed argument scope - attr (@param.arg_index) "push" = (child-index @param) + attr (@param.arg_index) push_symbol = (child-index @param) edge @param.covalue -> @param.arg_index edge @param.arg_index -> @fun_decl.value_arg_scope } @@ -1195,7 +1195,7 @@ inherit .undefined (formal_parameters (_)@param))@method_def { ; parameters jump to the pushed argument scope - attr (@param.arg_index) "push" = (child-index @param) + attr (@param.arg_index) push_symbol = (child-index @param) edge @param.covalue -> @param.arg_index edge @param.arg_index -> @method_def.method_value_arg_scope } @@ -1735,7 +1735,7 @@ inherit .undefined edge @variable.after_scope -> @variable.before_scope ; value is a lookup, ie a push - attr (@variable.value) "push", "reference" + attr (@variable.value) node_reference = @variable edge @variable.value -> @variable.before_scope } @@ -2069,7 +2069,7 @@ inherit .undefined (formal_parameters (_)@param))@fun { ; parameters jump to the pushed argument scope - attr (@param.arg_index) "push" = (child-index @param) + attr (@param.arg_index) push_symbol = (child-index @param) edge @param.covalue -> @param.arg_index edge @param.arg_index -> @fun.value_arg_scope } @@ -2151,7 +2151,7 @@ inherit .undefined (formal_parameters (_)@param))@fun { ; parameters jump to the pushed argument scope - attr (@param.arg_index) "push" = (child-index @param) + attr (@param.arg_index) push_symbol = (child-index @param) edge @param.covalue -> @param.arg_index edge @param.arg_index -> @fun.value_arg_scope } @@ -2218,7 +2218,7 @@ inherit .undefined (formal_parameters (_)@param))@fun { ; parameters jump to the pushed argument scope - attr (@param.arg_index) "push" = (child-index @param) + attr (@param.arg_index) push_symbol = (child-index @param) edge @param.covalue -> @param.arg_index edge @param.arg_index -> @fun.value_arg_scope } @@ -2339,7 +2339,7 @@ inherit .undefined edge @member_expr.after_scope -> @object.after_scope ; value is a member projection on the value of the object ie. a push then push dot - attr (@property.push) "push", "reference" + attr (@property.push) node_reference @property ;attr (@member_expr.value) push_node = @property.pop attr (@member_expr.push_dot) push_symbol = "." edge @property.push -> @member_expr.push_dot @@ -2376,7 +2376,7 @@ inherit .undefined edge @subscript_expression.value -> @index.push edge @index.push -> @index.push_dot edge @index.push_dot -> @object.value - attr (@index.push) "push" = (replace @index "\"" "") + attr (@index.push) push_symbol = (replace @index "\"" "") } (subscript_expression @@ -2992,7 +2992,7 @@ inherit .undefined (pair_pattern key:(string)@key)@pair_pattern { - attr (@key.push) "push" = (replace @key "\"" ""), "reference" + attr (@key.push) symbol_reference = (replace @key "\"" ""), source_node = @key } ; LATER-TODO the left pattern has to be a name, it cant be another pattern @@ -3080,7 +3080,7 @@ inherit .undefined ; array pattern elements (array_pattern (_)@element_pat)@array_pat { - attr (@element_pat.element_index_push) "push" = (child-index @element_pat), "reference" + attr (@element_pat.element_index_push) push_symbol = (child-index @element_pat) attr (@array_pat.element_index_push_dot) push_symbol = "." edge @element_pat.covalue -> @element_pat.element_index_push edge @element_pat.element_index_push -> @array_pat.element_index_push_dot From 80cbf2ae7c5138c9b8e4562b47aa1c44bdde4b89 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 14:44:52 +0200 Subject: [PATCH 043/500] [conv] mor epops --- .../src/stack-graphs-conv.tsg | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index dd9fded9f..76cfebe6f 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -800,7 +800,7 @@ inherit .undefined ; edge @name.push_dot -> @mod_name.push ; edge @name -> @name.push_dot ; -; attr (@alias) "pop", "definition" +; attr (@alias) node_definition = @alias ; edge @alias -> @name ; ; edge @import_stmt.after_scope -> @alias @@ -856,7 +856,7 @@ inherit .undefined (variable_declarator name:(identifier)@name))@decl { - attr (@name.pop) "pop", "definition" + attr (@name.pop) node_definition = @name, "definition" edge @decl.after_scope -> @name.pop } @@ -864,7 +864,7 @@ inherit .undefined (variable_declarator name:(identifier)@name))@decl { - attr (@name.pop) "pop", "definition" + attr (@name.pop) node_definition = @name, "definition" edge @decl.after_scope -> @name.pop } @@ -1458,7 +1458,7 @@ inherit .undefined right:(_)@right body:(_)@body) { - attr (@left.pop) "pop", "definition" + attr (@left.pop) node_definition = @left edge @left.pop -> @right.value edge @body.before_scope -> @left.pop } @@ -1548,7 +1548,7 @@ inherit .undefined parameter:(identifier)@name body:(_)@body) { - attr (@name.pop) "pop", "definition" + attr (@name.pop) node_definition = @name, "definition" edge @body.before_scope -> @name.pop } @@ -1901,15 +1901,15 @@ inherit .undefined } (pair key:(property_identifier)@key) { - attr (@key.pop) "pop" = @key + attr (@key.pop) pop_node = @key } (pair key:(string)@key) { - attr (@key.pop) "pop" = (replace @key "\"" "") + attr (@key.pop) pop_symbol = (replace @key "\"" "") } (pair key:(number)@key) { - attr (@key.pop) "pop" = @key + attr (@key.pop) pop_node = @key } @@ -1951,7 +1951,7 @@ inherit .undefined ; elements at indices (array (_)@element)@array_expr { attr (@array_expr.element_pop_dot) pop_symbol = "." - attr (@element.index_pop) "pop" = (child-index @element), "definition" + attr (@element.index_pop) pop_symbol = (child-index @element) edge @array_expr.element_pop_dot -> @element.index_pop edge @array_expr.value -> @array_expr.element_pop_dot edge @element.index_pop -> @element.value @@ -2287,7 +2287,7 @@ inherit .undefined (call_expression arguments:(arguments (_)@arg)@arguments) { - attr (@arg.arg_index) "pop" = (child-index @arg) + attr (@arg.arg_index) pop_symbol = (child-index @arg) edge @arguments.arg_scope_no_this -> @arg.arg_index edge @arg.arg_index -> @arg.value } @@ -2432,7 +2432,7 @@ inherit .undefined (new_expression arguments:(arguments (_)@arg)@arguments) { - attr (@arg.arg_index) "pop" = (child-index @arg) + attr (@arg.arg_index) pop_symbol = (child-index @arg) edge @arguments.arg_scope -> @arg.arg_index edge @arg.arg_index -> @arg.value } @@ -2461,7 +2461,7 @@ inherit .undefined ; LATER-TODO this isn't quite right because the update argument can't be an arbitrary expr ; eg f(x)++ doesn't make any sense, you have to have something more like ; (update_expression argument: (lvar)@argument) - attr (@argument.pop) "pop", "definition" + attr (@argument.pop) node_definition = @argument edge @update_expr.value -> @argument.value edge @update_expr.after_scope -> @argument.pop edge @argument.pop -> @argument.value From e922b1b113556c6c35c97ac844a5ba55d5bc6e58 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 14:52:10 +0200 Subject: [PATCH 044/500] [conv] definitions --- .../src/stack-graphs-conv.tsg | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 76cfebe6f..910519200 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -583,7 +583,7 @@ inherit .undefined (export_statement value:(_)@default_expr)@export_stmt { - attr (@export_stmt.default_guard) pop_symbol = "GUARD:DEFAULT", "definition" + attr (@export_stmt.default_guard) symbol_definition = "GUARD:DEFAULT", source_node = @export_stmt edge @default_expr.before_scope -> @export_stmt.before_scope edge @export_stmt.after_scope -> @default_expr.after_scope edge @export_stmt.exports -> @export_stmt.default_guard @@ -856,7 +856,7 @@ inherit .undefined (variable_declarator name:(identifier)@name))@decl { - attr (@name.pop) node_definition = @name, "definition" + attr (@name.pop) node_definition = @name edge @decl.after_scope -> @name.pop } @@ -864,7 +864,7 @@ inherit .undefined (variable_declarator name:(identifier)@name))@decl { - attr (@name.pop) node_definition = @name, "definition" + attr (@name.pop) node_definition = @name edge @decl.after_scope -> @name.pop } @@ -954,12 +954,12 @@ inherit .undefined ; the call sig's before scope comes from the drop node then flows into the body edge @call_sig.before_scope -> @fun_decl.value_drop - attr (@call_sig.this_pop) pop_symbol = "this", "definition" + attr (@call_sig.this_pop) symbol_definition = "this", source_node = @call_sig attr (@call_sig.this_push) push_symbol = "this" edge @call_sig.this_pop -> @call_sig.this_push edge @call_sig.this_push -> @fun_decl.value_arg_scope edge @call_sig.before_scope -> @call_sig.this_pop - attr (@call_sig.arguments_pop) pop_symbol = "arguments", "definition" + attr (@call_sig.arguments_pop) symbol_definition = "arguments", source_node = @call_sig attr (@call_sig.arguments_push) push_symbol = "arguments" edge @call_sig.arguments_pop -> @call_sig.arguments_push edge @call_sig.arguments_push -> @fun_decl.value_arg_scope @@ -1025,12 +1025,12 @@ inherit .undefined ; the call sig's before scope comes from the drop node then flows into the body edge @call_sig.before_scope -> @fun_decl.value_drop - attr (@call_sig.this_pop) pop_symbol = "this", "definition" + attr (@call_sig.this_pop) symbol_definition = "this", source_name = @call_sig attr (@call_sig.this_push) push_symbol = "this" edge @call_sig.this_pop -> @call_sig.this_push edge @call_sig.this_push -> @fun_decl.value_arg_scope edge @call_sig.before_scope -> @call_sig.this_pop - attr (@call_sig.arguments_pop) pop_symbol = "arguments", "definition" + attr (@call_sig.arguments_pop) symbol_definition = "arguments", source_node = @call_sig attr (@call_sig.arguments_push) push_symbol = "arguments" edge @call_sig.arguments_pop -> @call_sig.arguments_push edge @call_sig.arguments_push -> @fun_decl.value_arg_scope @@ -1131,7 +1131,7 @@ inherit .undefined (#eq? @name "constructor") ) { ; augmentation for the constructor - attr (@name.constructor_guard) pop_symbol = "GUARD:CONSTRUCTOR", "definition" + attr (@name.constructor_guard) symbol_definition = "GUARD:CONSTRUCTOR", source_node = @name edge @method_def.after_scope -> @name.constructor_guard edge @name.constructor_guard -> @method_def.method_value } @@ -1548,7 +1548,7 @@ inherit .undefined parameter:(identifier)@name body:(_)@body) { - attr (@name.pop) node_definition = @name, "definition" + attr (@name.pop) node_definition = @name edge @body.before_scope -> @name.pop } @@ -1892,7 +1892,7 @@ inherit .undefined ; This is done differently depending on what the key is. See next rules. ; attr (@key.pop) node_definition = @key - attr (@key.pop) "definition" + attr (@key.pop) node_definition = @key attr (@object.field_pop_dot) pop_symbol = "." edge @key.pop -> @value.value @@ -2030,12 +2030,12 @@ inherit .undefined ; the call sig's before scope comes from the drop node, ; then flows into the body, and includes a variable binding for "this" edge @call_sig.before_scope -> @fun.value_drop - attr (@call_sig.this_pop) pop_symbol = "this", "definition" + attr (@call_sig.this_pop) symbol_definition = "this", source_node = @call_sig attr (@call_sig.this_push) push_symbol = "this" edge @call_sig.this_pop -> @call_sig.this_push edge @call_sig.this_push -> @fun.value_arg_scope edge @call_sig.before_scope -> @call_sig.this_pop - attr (@call_sig.arguments_pop) pop_symbol = "arguments", "definition" + attr (@call_sig.arguments_pop) symbol_definition = "arguments", source_node = @call_sig attr (@call_sig.arguments_push) push_symbol = "arguments" edge @call_sig.arguments_pop -> @call_sig.arguments_push edge @call_sig.arguments_push -> @fun.value_arg_scope @@ -2249,12 +2249,12 @@ inherit .undefined edge @call_expr.return_guard -> @call_expr.call edge @call_expr.call -> @function.value - attr (@arguments.arg_this) pop_symbol = "this", "definition" + attr (@arguments.arg_this) symbol_definition = "this", source_node = @arguments edge @arguments.arg_scope -> @arguments.arg_this edge @arguments.arg_scope -> @arguments.arg_scope_no_this - attr (@arguments.arg_arguments) pop_symbol = "arguments", "definition" + attr (@arguments.arg_arguments) symbol_definition = "arguments", source_node = @arguments attr (@arguments.arg_arguments_dot) pop_symbol = "." edge @arguments.arg_scope -> @arguments.arg_arguments edge @arguments.arg_arguments -> @arguments.arg_arguments_dot @@ -2424,7 +2424,7 @@ inherit .undefined ; value coming from the field decls in the class edge @new_expr.value -> @constructor.value - attr (@arguments.arg_this) pop_symbol = "this", "definition" + attr (@arguments.arg_this) symbol_definition = "this", source_node = @arguments edge @arguments.arg_scope -> @arguments.arg_this edge @arguments.arg_this -> @new_expr.empty_object } From 34ab57a9442948675bef6de380254e805db6f8bb Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 14:53:03 +0200 Subject: [PATCH 045/500] [conv] refs --- .../src/stack-graphs-conv.tsg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 910519200..2d8a5263c 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -1766,7 +1766,7 @@ inherit .undefined edge @this.after_scope -> @this.before_scope ; this is a lookup, ie a push - attr (@this.value) push_symbol = "this", "reference" + attr (@this.value) symbol_reference = "this", source_node = @this edge @this.value -> @this.before_scope } @@ -2370,7 +2370,7 @@ inherit .undefined object: (_)@object index: (string)@index)@subscript_expression { - attr (@index.push) "reference" + attr (@index.push) node_reference = @index attr (@index.push_dot) push_symbol = "." edge @subscript_expression.value -> @index.push @@ -2383,7 +2383,7 @@ inherit .undefined object: (_)@object index: (number)@index)@subscript_expression { - attr (@index.push) "reference" + attr (@index.push) node_reference = @index attr (@index.push_dot) push_symbol = "." edge @subscript_expression.value -> @index.push From b30c60551cbd21c86a3c886baa1cd2db0dfcbc80 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 14:53:47 +0200 Subject: [PATCH 046/500] [conv] definiens --- .../src/stack-graphs-conv.tsg | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 2d8a5263c..d5653d9f1 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -3258,7 +3258,7 @@ inherit .undefined name:(_)@name body:(_)@body)@class_decl { - attr (@name.pop) "definiens" = @class_decl + attr (@name.pop) definiens_node = @class_decl } @@ -3267,7 +3267,7 @@ inherit .undefined parameters:(_)@call_sig body:(_)@body)@fun_decl { - attr (@name.pop) "definiens" = @fun_decl + attr (@name.pop) definiens_node = @fun_decl } @@ -3276,7 +3276,7 @@ inherit .undefined parameters:(_)@call_sig body:(_)@body)@fun_decl { - attr (@name.pop) "definiens" = @fun_decl + attr (@name.pop) definiens_node = @fun_decl } @@ -3285,7 +3285,7 @@ inherit .undefined parameters:(_)@call_sig body:(_)@body)@method_def { - attr (@name.pop) "definiens" = @method_def + attr (@name.pop) definiens_node = @method_def } @@ -3293,7 +3293,7 @@ inherit .undefined name:(_)@name parameters:(_)@call_sig)@fun { - attr (@name.pop) "definiens" = @fun + attr (@name.pop) definiens_node = @fun } @@ -3301,7 +3301,7 @@ inherit .undefined name:(_)@name parameters:(_)@call_sig)@fun { - attr (@name.pop) "definiens" = @fun + attr (@name.pop) definiens_node = @fun } @@ -3309,7 +3309,7 @@ inherit .undefined name:(_)@name body:(_)@body)@class { - attr (@name.pop) "definiens" = @class + attr (@name.pop) definiens_node = @class } @@ -3331,7 +3331,7 @@ inherit .undefined (arrow_function) ]@right) { - attr (@left.pop) "definiens" = @right + attr (@left.pop) definiens_node = @right } @@ -3345,7 +3345,7 @@ inherit .undefined attr (@left.ignore_guard) pop_symbol = "GUARD:GANDALF" attr (@left.definiens_hook) node_definition = @left - attr (@left.definiens_hook) "definiens" = @right + attr (@left.definiens_hook) definiens_node = @right edge ROOT_NODE -> @left.ignore_guard edge @left.ignore_guard -> @left.definiens_hook } @@ -3359,7 +3359,7 @@ inherit .undefined (arrow_function) ]@initializer)) { - attr (@name.pop) "definiens" = @initializer + attr (@name.pop) definiens_node = @initializer } @@ -3372,7 +3372,7 @@ inherit .undefined (arrow_function) ]@initializer)) { - attr (@name.pop) "definiens" = @initializer + attr (@name.pop) definiens_node = @initializer } @@ -3386,7 +3386,7 @@ inherit .undefined attr (@name.ignore_guard) pop_symbol = "GUARD:GANDALF" attr (@name.definiens_hook) node_definition = @name -attr (@name.definiens_hook) "definiens" = @value +attr (@name.definiens_hook) definiens_node = @value edge ROOT_NODE -> @name.ignore_guard edge @name.ignore_guard -> @name.definiens_hook From 9781ab8f8bc17411ca403f6162ddccc2cb18398f Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 14:54:09 +0200 Subject: [PATCH 047/500] [conv] syntax_type --- .../src/stack-graphs-conv.tsg | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index d5653d9f1..2b43406b1 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -937,7 +937,7 @@ inherit .undefined parameters:(_)@call_sig body:(_)@body)@fun_decl { - attr (@name.pop) "syntax_type" = "function" + attr (@name.pop) syntax_type = "function" ; scope flows across the decl edge @fun_decl.after_scope -> @fun_decl.before_scope @@ -1007,7 +1007,7 @@ inherit .undefined parameters:(_)@call_sig body:(_)@body)@fun_decl { - attr (@name.pop) "syntax_type" = "function" + attr (@name.pop) syntax_type = "function" ; scope flows across the decl edge @fun_decl.after_scope -> @fun_decl.before_scope @@ -1077,7 +1077,7 @@ inherit .undefined name:(_)@name body:(_)@body)@class_decl { - attr (@name.pop) "syntax_type" = "class" + attr (@name.pop) syntax_type = "class" attr (@name.pop) node_definition = @name edge @class_decl.after_scope -> @name.pop @@ -1154,7 +1154,7 @@ inherit .undefined parameters:(_)@call_sig body:(_)@body)@method_def { - attr (@name.pop) "syntax_type" = "method" + attr (@name.pop) syntax_type = "method" ; scope flows across the decl edge @method_def.after_scope -> @method_def.before_scope @@ -2005,7 +2005,7 @@ inherit .undefined name:(_)@name parameters:(_)@call_sig)@fun { - attr (@name.pop) "syntax_type" = "function" + attr (@name.pop) syntax_type = "function" ; if the function has a name, this is bound the callsig's before scope attr (@name.pop) node_definition = @name @@ -2165,7 +2165,7 @@ inherit .undefined name:(_)@name parameters:(_)@call_sig)@fun { - attr (@name.pop) "syntax_type" = "function" + attr (@name.pop) syntax_type = "function" ; if the function has a name, this is bound the callsig's before scope attr (@name.pop) node_definition = @name @@ -2653,7 +2653,7 @@ inherit .undefined name:(_)@name body:(_)@body)@class { - attr (@name.pop) "syntax_type" = "class" + attr (@name.pop) syntax_type = "class" attr (@name.pop) node_definition = @name edge @body.before_scope -> @name.pop From 5d24f67daaa71cc19486a7cdd2f6048deba70f3a Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 14:55:33 +0200 Subject: [PATCH 048/500] [conv] drop --- .../src/stack-graphs-conv.tsg | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 2b43406b1..7fb0547ee 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -949,7 +949,7 @@ inherit .undefined ; function values have drop nodes that handle closures, that points to the ; before scope for the function - attr (@fun_decl.value_drop) "drop" + attr (@fun_decl.value_drop) type = "drop_scopes" edge @fun_decl.value_drop -> @fun_decl.before_scope ; the call sig's before scope comes from the drop node then flows into the body @@ -1019,7 +1019,7 @@ inherit .undefined ; function values have drop nodes that handle closures, that points to the ; before scope of the declaration - attr (@fun_decl.value_drop) "drop" + attr (@fun_decl.value_drop) type = "drop_scopes" edge @fun_decl.value_drop -> @fun_decl.before_scope @@ -1161,7 +1161,7 @@ inherit .undefined ; method values have drop nodes that handle closures, that points to the ; before scope from method def - attr (@method_def.method_value_drop) "drop" + attr (@method_def.method_value_drop) type = "drop_scopes" edge @method_def.method_value_drop -> @method_def.before_scope ; the call sig's before scope comes from the drop node then flows into the body @@ -2024,7 +2024,7 @@ inherit .undefined ; function values have drop nodes that handle closures, that points to the ; before scope from the function - attr (@fun.value_drop) "drop" + attr (@fun.value_drop) type = "drop_scopes" edge @fun.value_drop -> @fun.before_scope ; the call sig's before scope comes from the drop node, @@ -2094,7 +2094,7 @@ inherit .undefined ; function values have drop nodes that handle closures, that points to the ; before scope from the function - attr (@fun.value_drop) "drop" + attr (@fun.value_drop) type = "drop_scopes" edge @fun.value_drop -> @fun.before_scope ; the call sig's before scope comes from the drop node then flows into the body @@ -2184,7 +2184,7 @@ inherit .undefined ; function values have drop nodes that handle closures, that points to the ; before scope from the function - attr (@fun.value_drop) "drop" + attr (@fun.value_drop) type = "drop_scopes" edge @fun.value_drop -> @fun.before_scope ; the call sig's before scope comes from the drop node then flows into the body @@ -2540,7 +2540,7 @@ inherit .undefined right: (_)@right)@assignment_expr { ; HACK - attr (@this.drop) "drop" + attr (@this.drop) type = "drop_scopes" edge @this.drop -> @this.pop attr (@this.pop) pop_symbol = "this" attr (@this.pop_dot) pop_symbol = "." From 6d165dd8da02a5c93a639c1e776a829a1beb6893 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 14:57:17 +0200 Subject: [PATCH 049/500] [conv] jump-to --- .../src/stack-graphs-conv.tsg | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 7fb0547ee..e16bf32e1 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -986,7 +986,7 @@ inherit .undefined edge @fun_decl.value_this -> @body.after_scope ; function values have a jump node that lets params connect up to actual arguments - attr (@fun_decl.value_arg_scope) "jump-to" + edge @fun_decl.value_arg_scope -> JUMP_TO_SCOPE_NODE } (function_declaration @@ -1056,7 +1056,7 @@ inherit .undefined edge @fun_decl.value_this -> @body.after_scope ; function values have a jump node that lets params connect up to actual arguments - attr (@fun_decl.value_arg_scope) "jump-to" + edge @fun_decl.value_arg_scope -> JUMP_TO_SCOPE_NODE } (generator_function_declaration @@ -1187,7 +1187,7 @@ inherit .undefined edge @method_def.method_value_this -> @body.after_scope ; method values have a jump node that lets params connect up to actual arguments - attr (@method_def.method_value_arg_scope) "jump-to" + edge @method_def.method_value_arg_scope -> JUMP_TO_SCOPE_NODE } (method_definition @@ -2061,7 +2061,7 @@ inherit .undefined edge @fun.value_this -> @body.after_scope ; function values have a jump node that lets params connect up to actual arguments - attr (@fun.value_arg_scope) "jump-to" + edge @fun.value_arg_scope -> JUMP_TO_SCOPE_NODE } (function @@ -2120,7 +2120,7 @@ inherit .undefined edge @fun.value_this -> @body.after_scope ; function values have a jump node that lets params connect up to actual arguments - attr (@fun.value_arg_scope) "jump-to" + edge @fun.value_arg_scope -> JUMP_TO_SCOPE_NODE } ; arrow functions returning exprs need special rules for getting the return value hooked up @@ -2210,7 +2210,7 @@ inherit .undefined edge @fun.value_this -> @body.after_scope ; function values have a jump node that lets params connect up to actual arguments - attr (@fun.value_arg_scope) "jump-to" + edge @fun.value_arg_scope -> JUMP_TO_SCOPE_NODE } (generator_function From 7424c0dda116610388ed6124a0c3061de88513f8 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 14:59:20 +0200 Subject: [PATCH 050/500] [conv] scoped --- .../src/stack-graphs-conv.tsg | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index e16bf32e1..7a94627af 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -968,7 +968,7 @@ inherit .undefined ; function values have call nodes - attr (@fun_decl.value_call) pop_symbol = "()", "pop-scope" + attr (@fun_decl.value_call) pop_scoped_symbol = "()" edge @fun_decl.value -> @fun_decl.value_call ; function values have return nodes which need to be visible for returns @@ -1038,7 +1038,7 @@ inherit .undefined edge @body.before_scope -> @call_sig.after_scope ; function values have call nodes - attr (@fun_decl.value_call) pop_symbol = "()", "pop-scope" + attr (@fun_decl.value_call) pop_scoped_symbol = "()" edge @fun_decl.value -> @fun_decl.value_call ; function values have return nodes which need to be visible for returns @@ -1169,7 +1169,7 @@ inherit .undefined edge @body.before_scope -> @call_sig.after_scope ; method values have call nodes - attr (@method_def.method_value_call) pop_symbol = "()", "pop-scope" + attr (@method_def.method_value_call) pop_scoped_symbol = "()" edge @method_def.method_value -> @method_def.method_value_call ; method values have return nodes which need to be visible for returns @@ -2043,7 +2043,7 @@ inherit .undefined edge @body.before_scope -> @call_sig.after_scope ; function values have call nodes - attr (@fun.value_call) pop_symbol = "()", "pop-scope" + attr (@fun.value_call) pop_scoped_symbol = "()" edge @fun.value -> @fun.value_call ; function values have return nodes which need to be visible for returns @@ -2102,7 +2102,7 @@ inherit .undefined edge @body.before_scope -> @call_sig.after_scope ; function values have call nodes - attr (@fun.value_call) pop_symbol = "()", "pop-scope" + attr (@fun.value_call) pop_scoped_symbol = "()" edge @fun.value -> @fun.value_call ; function values have return nodes which need to be visible for returns @@ -2192,7 +2192,7 @@ inherit .undefined edge @body.before_scope -> @call_sig.after_scope ; function values have call nodes - attr (@fun.value_call) pop_symbol = "()", "pop-scope" + attr (@fun.value_call) pop_scoped_symbol = "()" edge @fun.value -> @fun.value_call ; function values have return nodes which need to be visible for returns @@ -2244,7 +2244,7 @@ inherit .undefined ; value is a call, ie a push "()" node w/ "push-scope" @arguments attr (@call_expr.return_guard) push_symbol = "GUARD:RETURN" - attr (@call_expr.call) push_symbol = "()", "push-scope" = @arguments.arg_scope + attr (@call_expr.call) push_scoped_symbol = "()", scope = @arguments.arg_scope edge @call_expr.value -> @call_expr.return_guard edge @call_expr.return_guard -> @call_expr.call edge @call_expr.call -> @function.value @@ -2404,7 +2404,7 @@ inherit .undefined edge @arguments.before_scope -> @constructor.after_scope edge @new_expr.after_scope -> @arguments.after_scope - attr (@new_expr.call) push_symbol = "()", "push-scope" = @arguments.arg_scope + attr (@new_expr.call) push_scoped_symbol = "()", scope = @arguments.arg_scope ; we guard for constructors for the case where we have a "true" class attr (@constructor.constructor) push_symbol = "GUARD:CONSTRUCTOR" From a58d0be3d67f20c09c89b4855d2d0293eceef2d8 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 14:59:51 +0200 Subject: [PATCH 051/500] [conv] endpoints --- .../src/stack-graphs-conv.tsg | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 7a94627af..9c96daf42 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -972,14 +972,14 @@ inherit .undefined edge @fun_decl.value -> @fun_decl.value_call ; function values have return nodes which need to be visible for returns - attr (@fun_decl.value_return) "endpoint" + attr (@fun_decl.value_return) is_exported attr (@fun_decl.value_return) pop_symbol = "GUARD:RETURN" edge @fun_decl.value_call -> @fun_decl.value_return let @body.return_or_yield = @fun_decl.value_return ; method values have this nodes which need to be visible for constructor calls attr (@fun_decl.value_this) push_symbol = "this" - attr (@fun_decl.value_this_guard) "endpoint" + attr (@fun_decl.value_this_guard) is_exported attr (@fun_decl.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun_decl.value_call -> @fun_decl.value_this_guard edge @fun_decl.value_this_guard -> @fun_decl.value_this @@ -1042,14 +1042,14 @@ inherit .undefined edge @fun_decl.value -> @fun_decl.value_call ; function values have return nodes which need to be visible for returns - attr (@fun_decl.value_return) "endpoint" + attr (@fun_decl.value_return) is_exported attr (@fun_decl.value_return) pop_symbol = "GUARD:RETURN" edge @fun_decl.value_call -> @fun_decl.value_return let @body.return_or_yield = @fun_decl.value_return ; method values have this nodes which need to be visible for constructor calls attr (@fun_decl.value_this) push_symbol = "this" - attr (@fun_decl.value_this_guard) "endpoint" + attr (@fun_decl.value_this_guard) is_exported attr (@fun_decl.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun_decl.value_call -> @fun_decl.value_this_guard edge @fun_decl.value_this_guard -> @fun_decl.value_this @@ -1173,14 +1173,14 @@ inherit .undefined edge @method_def.method_value -> @method_def.method_value_call ; method values have return nodes which need to be visible for returns - attr (@method_def.method_value_return) "endpoint" + attr (@method_def.method_value_return) is_exported attr (@method_def.method_value_return) pop_symbol = "GUARD:RETURN" edge @method_def.method_value_call -> @method_def.method_value_return let @body.return_or_yield = @method_def.method_value_return ; method values have this nodes which need to be visible for constructor calls attr (@method_def.method_value_this) push_symbol = "this" - attr (@method_def.method_value_this_guard) "endpoint" + attr (@method_def.method_value_this_guard) is_exported attr (@method_def.method_value_this_guard) pop_symbol = "GUARD:THIS" edge @method_def.method_value_call -> @method_def.method_value_this_guard edge @method_def.method_value_this_guard -> @method_def.method_value_this @@ -2047,14 +2047,14 @@ inherit .undefined edge @fun.value -> @fun.value_call ; function values have return nodes which need to be visible for returns - attr (@fun.value_return) "endpoint" + attr (@fun.value_return) is_exported attr (@fun.value_return) pop_symbol = "GUARD:RETURN" edge @fun.value_call -> @fun.value_return let @body.return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls attr (@fun.value_this) push_symbol = "this" - attr (@fun.value_this_guard) "endpoint" + attr (@fun.value_this_guard) is_exported attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun.value_call -> @fun.value_this_guard edge @fun.value_this_guard -> @fun.value_this @@ -2106,14 +2106,14 @@ inherit .undefined edge @fun.value -> @fun.value_call ; function values have return nodes which need to be visible for returns - attr (@fun.value_return) "endpoint" + attr (@fun.value_return) is_exported attr (@fun.value_return) pop_symbol = "GUARD:RETURN" edge @fun.value_call -> @fun.value_return let @body.return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls attr (@fun.value_this) push_symbol = "this" - attr (@fun.value_this_guard) "endpoint" + attr (@fun.value_this_guard) is_exported attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun.value_call -> @fun.value_this_guard edge @fun.value_this_guard -> @fun.value_this @@ -2196,14 +2196,14 @@ inherit .undefined edge @fun.value -> @fun.value_call ; function values have return nodes which need to be visible for returns - attr (@fun.value_return) "endpoint" + attr (@fun.value_return) is_exported attr (@fun.value_return) pop_symbol = "GUARD:RETURN" edge @fun.value_call -> @fun.value_return let @body.return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls attr (@fun.value_this) push_symbol = "this" - attr (@fun.value_this_guard) "endpoint" + attr (@fun.value_this_guard) is_exported attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun.value_call -> @fun.value_this_guard edge @fun.value_this_guard -> @fun.value_this From a34ce9f2a7142e1a56f4f62db50bad70274ac102 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 15:00:45 +0200 Subject: [PATCH 052/500] [conv] typos --- .../src/stack-graphs-conv.tsg | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 9c96daf42..7f4c2f06e 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -301,9 +301,9 @@ inherit .string inherit .undefined (program)@prog { - node @node.Regex_prototype - node @node.arguments_prototype - node @node.empty_object + node @prog.Regex_prototype + node @prog.arguments_prototype + node @prog.empty_object node @prog.boolean node @prog.null node @prog.number @@ -321,7 +321,7 @@ inherit .undefined (program)@prog { scan FILE_PATH { "([^/]+)\.js$" { - attr (@prog.module_pop) symbol_definition = $1, source_node = prog + attr (@prog.module_pop) symbol_definition = $1, source_node = @prog attr (@prog.module_pop) empty_source_span } } @@ -2339,7 +2339,7 @@ inherit .undefined edge @member_expr.after_scope -> @object.after_scope ; value is a member projection on the value of the object ie. a push then push dot - attr (@property.push) node_reference @property + attr (@property.push) node_reference = @property ;attr (@member_expr.value) push_node = @property.pop attr (@member_expr.push_dot) push_symbol = "." edge @property.push -> @member_expr.push_dot From 6be8243d3c6b289305aac30e8896656116911a7f Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 15:09:12 +0200 Subject: [PATCH 053/500] [conv] unused captures --- .../src/stack-graphs-conv.tsg | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 7f4c2f06e..fbcbf6be3 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -546,10 +546,10 @@ inherit .undefined ( (export_specifier - name:(_)@name + name:(_)@_name !alias)@export_specifier - (#eq? @name "default") + (#eq? @_name "default") ) { @@ -564,9 +564,9 @@ inherit .undefined ( (export_specifier name:(_)@name - alias:(_)@alias)@export_specifier + alias:(_)@_alias)@export_specifier - (#eq? @alias "default") + (#eq? @_alias "default") ) { @@ -1443,7 +1443,7 @@ inherit .undefined ;; #### For In (for_in_statement - left:(_)@left + left:(_)@_left right:(_)@right body:(_)@body)@for_in_stmt { @@ -1704,7 +1704,7 @@ inherit .undefined (template_string (template_substitution (_)@left_inner_expr) . - (template_substitution (_)@right_inner_expr))@template_string { + (template_substitution (_)@right_inner_expr))@_template_string { ; scopes propagate from left substitutions to right substitutions edge @right_inner_expr.before_scope -> @left_inner_expr.after_scope } @@ -1843,7 +1843,7 @@ inherit .undefined (_)@left_entry . (_)@right_entry -)@object_expr { +)@_object_expr { ; scopes propagate from left entries to right entries edge @right_entry.before_scope -> @left_entry.after_scope } @@ -2279,7 +2279,7 @@ inherit .undefined ; applies to the negation of (member_expression), but that's not supported by ; tree-sitter currently (call_expression - function: (_)@function + function: (_)@_function arguments:(_)@arguments)@call_expr { edge @arguments.arg_this -> @call_expr.null @@ -2567,7 +2567,7 @@ inherit .undefined ;; #### Augmented Assignment Expressions (augmented_assignment_expression - left: (_)@left + left: (_)@_left right: (_)@right)@augmented_assignment_expr { ; scopes flow into the RHS then back out to the whole expr, augmented by the LHS @@ -2984,13 +2984,13 @@ inherit .undefined } (pair_pattern - key:(property_identifier)@key)@pair_pattern { + key:(property_identifier)@key)@_pair_pattern { attr (@key.push) node_reference = @key } (pair_pattern - key:(string)@key)@pair_pattern { + key:(string)@key)@_pair_pattern { attr (@key.push) symbol_reference = (replace @key "\"" ""), source_node = @key } @@ -3025,7 +3025,7 @@ inherit .undefined ; if the object assignment pattern happens to have an identifier on the LHS it also binds (object_assignment_pattern left:(shorthand_property_identifier_pattern)@left_pat - right:(_)@right_expr)@object_assignment_pat { + right:(_)@_right_expr)@object_assignment_pat { edge @left_pat.after_scope -> @left_pat.before_scope @@ -3156,9 +3156,9 @@ inherit .undefined (call_expression function: (member_expression object: (identifier)@object - property: (_)@extend) + property: (_)@_extend) arguments: (arguments (object)@new_fields))@call_expr - (#eq? @extend "extend") + (#eq? @_extend "extend") ) { attr (@object.pop) node_definition = @object @@ -3187,10 +3187,10 @@ inherit .undefined ( (assignment_expression left: (member_expression - object:(identifier)@exports + object:(identifier)@_exports property:(_)@property) right: (_)@right)@assignment_expr - (#eq? @exports "exports") + (#eq? @_exports "exports") ) { attr (@property.pop) node_definition = @property @@ -3203,11 +3203,11 @@ inherit .undefined ( (assignment_expression left: (member_expression - object:(identifier)@module - property:(_)@exports) + object:(identifier)@_module + property:(_)@_exports) right: (_)@right)@assignment_expr - (#eq? @module "module") - (#eq? @exports "exports") + (#eq? @_module "module") + (#eq? @_exports "exports") ) { edge @assignment_expr.exports -> @right.value @@ -3221,9 +3221,9 @@ inherit .undefined ( (call_expression - function:(_)@require + function:(_)@_require arguments:(arguments (string)@mod_name))@call_expr - (#eq? @require "require") + (#eq? @_require "require") ) { scan @mod_name { @@ -3256,7 +3256,7 @@ inherit .undefined (class_declaration name:(_)@name - body:(_)@body)@class_decl { + body:(_)@_body)@class_decl { attr (@name.pop) definiens_node = @class_decl @@ -3264,8 +3264,8 @@ inherit .undefined (function_declaration name:(_)@name - parameters:(_)@call_sig - body:(_)@body)@fun_decl { + parameters:(_)@_call_sig + body:(_)@_body)@fun_decl { attr (@name.pop) definiens_node = @fun_decl @@ -3273,8 +3273,8 @@ inherit .undefined (generator_function_declaration name:(_)@name - parameters:(_)@call_sig - body:(_)@body)@fun_decl { + parameters:(_)@_call_sig + body:(_)@_body)@fun_decl { attr (@name.pop) definiens_node = @fun_decl @@ -3282,8 +3282,8 @@ inherit .undefined (method_definition name:(_)@name - parameters:(_)@call_sig - body:(_)@body)@method_def { + parameters:(_)@_call_sig + body:(_)@_body)@method_def { attr (@name.pop) definiens_node = @method_def @@ -3291,7 +3291,7 @@ inherit .undefined (function name:(_)@name - parameters:(_)@call_sig)@fun { + parameters:(_)@_call_sig)@fun { attr (@name.pop) definiens_node = @fun @@ -3299,7 +3299,7 @@ inherit .undefined (generator_function name:(_)@name - parameters:(_)@call_sig)@fun { + parameters:(_)@_call_sig)@fun { attr (@name.pop) definiens_node = @fun @@ -3307,7 +3307,7 @@ inherit .undefined (class name:(_)@name - body:(_)@body)@class { + body:(_)@_body)@class { attr (@name.pop) definiens_node = @class From c1418b34e4bec43488d3b815176436ab0760f6fa Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 15:32:56 +0200 Subject: [PATCH 054/500] [conv] align with other TSG --- .../src/stack-graphs-conv.tsg | 140 +++++++++++++----- 1 file changed, 103 insertions(+), 37 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index fbcbf6be3..f327b5fea 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -1,3 +1,38 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Stack graphs definition for JavaScript +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Global Variables +;; ^^^^^^^^^^^^^^^^ + +global FILE_PATH +global ROOT_NODE +global JUMP_TO_SCOPE_NODE + + +;; Attribute Shorthands +;; ^^^^^^^^^^^^^^^^^^^^ + +attribute node_definition = node => type = "pop_symbol", node_symbol = node, is_definition +attribute node_reference = node => type = "push_symbol", node_symbol = node, is_reference +attribute pop_node = node => type = "pop_symbol", node_symbol = node +attribute pop_scoped_node = node => type = "pop_scoped_symbol", node_symbol = node +attribute pop_scoped_symbol = symbol => type = "pop_scoped_symbol", symbol = symbol +attribute pop_symbol = symbol => type = "pop_symbol", symbol = symbol +attribute push_node = node => type = "push_symbol", node_symbol = node +attribute push_scoped_node = node => type = "push_scoped_symbol", node_symbol = node +attribute push_scoped_symbol = symbol => type = "push_scoped_symbol", symbol = symbol +attribute push_symbol = symbol => type = "push_symbol", symbol = symbol +attribute scoped_node_definition = node => type = "pop_scoped_symbol", node_symbol = node, is_definition +attribute scoped_node_reference = node => type = "push_scoped_symbol", node_symbol = node, is_reference +attribute symbol_definition = symbol => type = "pop_symbol", symbol = symbol, is_definition +attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, is_reference + +attribute node_symbol = node => symbol = (source-text node), source_node = node + +;; Stack Graph Rules +;; ^^^^^^^^^^^^^^^^^ + ;; # JavaScript ;; This file defines StackGraph queries for JavaScript. It is written as a @@ -193,33 +228,6 @@ ;; - `GUARD:EXPORTS` - used for the names exported by the module ;; - `GUARD:DEFAULT` - used for the default export value -;; ## Global Variables - -global FILE_PATH -global ROOT_NODE -global JUMP_TO_SCOPE_NODE - - -;; ## Attribute Shorthands - -attribute node_definition = node => type = "pop_symbol", node_symbol = node, is_definition -attribute node_reference = node => type = "push_symbol", node_symbol = node, is_reference -attribute pop_node = node => type = "pop_symbol", node_symbol = node -attribute pop_scoped_node = node => type = "pop_scoped_symbol", node_symbol = node -attribute pop_scoped_symbol = symbol => type = "pop_scoped_symbol", symbol = symbol -attribute pop_symbol = symbol => type = "pop_symbol", symbol = symbol -attribute push_node = node => type = "push_symbol", node_symbol = node -attribute push_scoped_node = node => type = "push_scoped_symbol", node_symbol = node -attribute push_scoped_symbol = symbol => type = "push_scoped_symbol", symbol = symbol -attribute push_symbol = symbol => type = "push_symbol", symbol = symbol -attribute scoped_node_definition = node => type = "pop_scoped_symbol", node_symbol = node, is_definition -attribute scoped_node_reference = node => type = "push_scoped_symbol", node_symbol = node, is_reference -attribute symbol_definition = symbol => type = "pop_symbol", symbol = symbol, is_definition -attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, is_reference - -attribute node_symbol = node => symbol = (source-text node), source_node = node - - ;; ## Nodes (_)@node { @@ -300,16 +308,11 @@ inherit .return_or_yield inherit .string inherit .undefined -(program)@prog { - node @prog.Regex_prototype - node @prog.arguments_prototype - node @prog.empty_object - node @prog.boolean - node @prog.null - node @prog.number - node @prog.string - node @prog.undefined -} +;; ██████ ██████ ██████ ██████ ██████ █████ ███ ███ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ████ ██ +;; ██████ ██████ ██ ██ ██ ███ ██████ ███████ ██ ████ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ██ ██ ██ ██████ ██████ ██ ██ ██ ██ ██ ██ ███████ ;; ## Programs @@ -344,6 +347,15 @@ inherit .undefined attr (@prog.exports_pop) pop_symbol = "GUARD:EXPORTS" edge @prog.module_pop -> @prog.exports_pop edge @prog.exports_pop -> @prog.exports + + node @prog.number + node @prog.string + node @prog.boolean + node @prog.null + node @prog.undefined + node @prog.Regex_prototype + node @prog.arguments_prototype + node @prog.empty_object } ; programs, first statement @@ -384,6 +396,12 @@ inherit .undefined +;; ███████ ████████ █████ ████████ ███████ ███ ███ ███████ ███ ██ ████████ ███████ +;; ██ ██ ██ ██ ██ ██ ████ ████ ██ ████ ██ ██ ██ +;; ███████ ██ ███████ ██ █████ ██ ████ ██ █████ ██ ██ ██ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ███████ ██ ██ ██ ██ ███████ ██ ██ ███████ ██ ████ ██ ███████ + ;; ## Statements ;; ### Attributes Defined on Statements @@ -391,6 +409,12 @@ inherit .undefined ;; ### Statement Queries +;; ███████ ██ ██ ██████ ██████ ██████ ████████ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; █████ ███ ██████ ██ ██ ██████ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ███████ ██ ██ ██ ██████ ██ ██ ██ ███████ + ;; #### Export ; exports of just names @@ -637,6 +661,12 @@ inherit .undefined +;; ██ ███ ███ ██████ ██████ ██████ ████████ ███████ +;; ██ ████ ████ ██ ██ ██ ██ ██ ██ ██ ██ +;; ██ ██ ████ ██ ██████ ██ ██ ██████ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ██ ██ ██ ██ ██████ ██ ██ ██ ███████ + ;; #### Import ; https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import @@ -828,6 +858,18 @@ inherit .undefined +;; ███ ██ ██████ ██████ ███ ███ █████ ██ +;; ████ ██ ██ ██ ██ ██ ████ ████ ██ ██ ██ +;; ██ ██ ██ ██ ██ ██████ ██ ████ ██ ███████ ██ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ██ ████ ██████ ██ ██ ██ ██ ██ ██ ███████ + +;; ███████ ████████ █████ ████████ ███████ ███ ███ ███████ ███ ██ ████████ ███████ +;; ██ ██ ██ ██ ██ ██ ████ ████ ██ ████ ██ ██ ██ +;; ███████ ██ ███████ ██ █████ ██ ████ ██ █████ ██ ██ ██ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ███████ ██ ██ ██ ██ ███████ ██ ██ ███████ ██ ████ ██ ███████ + ;; #### Debugger (debugger_statement)@debugger_stmt { @@ -1645,6 +1687,12 @@ inherit .undefined +;; ███████ ██ ██ ██████ ██████ ███████ ███████ ███████ ██ ██████ ███ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ +;; █████ ███ ██████ ██████ █████ ███████ ███████ ██ ██ ██ ██ ██ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ███████ ██ ██ ██ ██ ██ ███████ ███████ ███████ ██ ██████ ██ ████ ███████ + ;; ## Expressions ;; ### Attributes Defined on Expressions @@ -2669,6 +2717,12 @@ inherit .undefined +;; ██████ █████ ████████ ████████ ███████ ██████ ███ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ +;; ██████ ███████ ██ ██ █████ ██████ ██ ██ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ██ ██ ██ ██ ██ ███████ ██ ██ ██ ████ ███████ + ;; ## Patterns ;; Patterns introduce at least two interesting problems to the task of name @@ -3130,6 +3184,12 @@ inherit .undefined +;; ███████ ██████ ███████ ██████ ██ █████ ██ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ███████ ██████ █████ ██ ██ ███████ ██ +;; ██ ██ ██ ██ ██ ██ ██ ██ +;; ███████ ██ ███████ ██████ ██ ██ ██ ███████ + ;; ## Special Cases ;; ;; There are a number of annoying features that libraries make use of to @@ -3240,6 +3300,12 @@ inherit .undefined } +;; ██████ ███████ ███████ ██ ███ ██ ██ ███████ ███ ██ ███████ +;; ██ ██ ██ ██ ██ ████ ██ ██ ██ ████ ██ ██ +;; ██ ██ █████ █████ ██ ██ ██ ██ ██ █████ ██ ██ ██ ███████ +;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +;; ██████ ███████ ██ ██ ██ ████ ██ ███████ ██ ████ ███████ + ;; ## Definiens Rules ;; These rules explain how defined names relate to syntactic definitions From b316d9a5d42e9fc7dd726005e11988275f36895e Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 15:34:39 +0200 Subject: [PATCH 055/500] [conv] use .builtins_ --- .../src/stack-graphs-conv.tsg | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index f327b5fea..716800515 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -297,16 +297,16 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; ## Inherited -inherit .Regex_prototype -inherit .arguments_prototype -inherit .boolean -inherit .empty_object +inherit .builtins_Regex_prototype +inherit .builtins_arguments_prototype +inherit .builtins_boolean +inherit .builtins_empty_object inherit .exports -inherit .null -inherit .number +inherit .builtins_null +inherit .builtins_number inherit .return_or_yield -inherit .string -inherit .undefined +inherit .builtins_string +inherit .builtins_undefined ;; ██████ ██████ ██████ ██████ ██████ █████ ███ ███ ███████ ;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ████ ██ @@ -348,14 +348,14 @@ inherit .undefined edge @prog.module_pop -> @prog.exports_pop edge @prog.exports_pop -> @prog.exports - node @prog.number - node @prog.string - node @prog.boolean - node @prog.null - node @prog.undefined - node @prog.Regex_prototype - node @prog.arguments_prototype - node @prog.empty_object + node @prog.builtins_number + node @prog.builtins_string + node @prog.builtins_boolean + node @prog.builtins_null + node @prog.builtins_undefined + node @prog.builtins_Regex_prototype + node @prog.builtins_arguments_prototype + node @prog.builtins_empty_object } ; programs, first statement @@ -1720,7 +1720,7 @@ inherit .undefined edge @string.after_scope -> @string.before_scope ; the value of a string is the string primitive - edge @string.value -> @string.string + edge @string.value -> @string.builtins_string } @@ -1772,7 +1772,7 @@ inherit .undefined edge @number.after_scope -> @number.before_scope ; the value of a number is the number primitive - edge @number.value -> @number.number + edge @number.value -> @number.builtins_number } @@ -1795,7 +1795,7 @@ inherit .undefined edge @true.after_scope -> @true.before_scope ; the value of true is a boolean primitive - edge @true.value -> @true.boolean + edge @true.value -> @true.builtins_boolean } (false)@false { @@ -1803,7 +1803,7 @@ inherit .undefined edge @false.after_scope -> @false.before_scope ; the value of false is a boolean primitive - edge @false.value -> @false.boolean + edge @false.value -> @false.builtins_boolean } @@ -1834,7 +1834,7 @@ inherit .undefined edge @null.after_scope -> @null.before_scope ; the value of null is the null primitive - edge @null.value -> @null.null + edge @null.value -> @null.builtins_null } @@ -1845,7 +1845,7 @@ inherit .undefined edge @undefined.after_scope -> @undefined.before_scope ; the value of undefined is the undefined primitive - edge @undefined.value -> @undefined.undefined + edge @undefined.value -> @undefined.builtins_undefined } @@ -1856,7 +1856,7 @@ inherit .undefined edge @regex.after_scope -> @regex.before_scope ; the value of a regex is the Regex prototype - edge @regex.value -> @regex.Regex_prototype + edge @regex.value -> @regex.builtins_Regex_prototype } @@ -2307,7 +2307,7 @@ inherit .undefined edge @arguments.arg_scope -> @arguments.arg_arguments edge @arguments.arg_arguments -> @arguments.arg_arguments_dot edge @arguments.arg_arguments_dot -> @arguments.arg_scope_no_this - edge @arguments.arg_arguments -> @call_expr.arguments_prototype + edge @arguments.arg_arguments -> @call_expr.builtins_arguments_prototype } ; special case to make `this` bind correctly in calls of the forms `x.f(...)` @@ -2330,7 +2330,7 @@ inherit .undefined function: (_)@_function arguments:(_)@arguments)@call_expr { - edge @arguments.arg_this -> @call_expr.null + edge @arguments.arg_this -> @call_expr.builtins_null } (call_expression arguments:(arguments (_)@arg)@arguments) { @@ -2474,7 +2474,7 @@ inherit .undefined attr (@arguments.arg_this) symbol_definition = "this", source_node = @arguments edge @arguments.arg_scope -> @arguments.arg_this - edge @arguments.arg_this -> @new_expr.empty_object + edge @arguments.arg_this -> @new_expr.builtins_empty_object } (new_expression From 20fc95088ada641e01060eab93859c4c6423f883 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 15:35:45 +0200 Subject: [PATCH 056/500] [conv] comment --- .../src/stack-graphs-conv.tsg | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 716800515..c526808c4 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -348,6 +348,7 @@ inherit .builtins_undefined edge @prog.module_pop -> @prog.exports_pop edge @prog.exports_pop -> @prog.exports + ;; builtin types node @prog.builtins_number node @prog.builtins_string node @prog.builtins_boolean From 5e8bdfcc39c9739d74444cf4c055ed00b5b47c99 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 15:46:20 +0200 Subject: [PATCH 057/500] [conv] statements --- .../src/stack-graphs-conv.tsg | 118 +++++++++++++----- 1 file changed, 86 insertions(+), 32 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index c526808c4..49157bf4d 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -897,18 +897,27 @@ inherit .builtins_undefined (variable_declaration (variable_declarator - name:(identifier)@name))@decl { + name:(identifier)@name))@variable_decl +{ + node @variable_decl.name_pop + + attr (@variable_decl.name_pop) node_definition = @name + edge @variable_decl.after_scope -> @variable_decl.name_pop + attr (@variable_decl.after_scope -> @variable_decl.name_pop) precedence = 1 - attr (@name.pop) node_definition = @name - edge @decl.after_scope -> @name.pop } (lexical_declaration (variable_declarator - name:(identifier)@name))@decl { + name:(identifier)@name))@lexical_decl +{ + + node @lexical_decl.name_pop + + attr (@lexical_decl.name_pop) node_definition = @name + edge @lexical_decl.after_scope -> @lexical_decl.name_pop + attr (@lexical_decl.after_scope -> @lexical_decl.name_pop) precedence = 1 - attr (@name.pop) node_definition = @name - edge @decl.after_scope -> @name.pop } (variable_declaration @@ -927,24 +936,27 @@ inherit .builtins_undefined (variable_declaration (variable_declarator - name:(identifier)@name - value:(_)@initializer))@decl { + name:(identifier)@_name + value:(_)@initializer))@variable_decl +{ + + edge @variable_decl.name_pop -> @initializer.value + edge @initializer.before_scope -> @variable_decl.before_scope + edge @variable_decl.after_scope -> @initializer.after_scope - edge @name.pop -> @initializer.value - edge @decl.value -> @initializer.value - edge @initializer.before_scope -> @decl.before_scope - edge @decl.after_scope -> @initializer.after_scope } (lexical_declaration (variable_declarator - name:(identifier)@name - value:(_)@initializer))@decl { + name:(identifier)@_name + value:(_)@initializer))@lexical_decl +{ + + edge @lexical_decl.name_pop -> @initializer.value + edge @initializer.before_scope -> @lexical_decl.before_scope + edge @lexical_decl.after_scope -> @initializer.after_scope + attr (@lexical_decl.after_scope -> @initializer.after_scope) precedence = 0 - edge @name.pop -> @initializer.value - edge @decl.value -> @initializer.value - edge @initializer.before_scope -> @decl.before_scope - edge @decl.after_scope -> @initializer.after_scope } (variable_declaration @@ -1475,7 +1487,7 @@ inherit .builtins_undefined edge @increment.before_scope -> @body.after_scope ; scopes also from from the body back into the condition - edge @condition.before_scope -> @body.after_scope + edge @condition.before_scope -> @increment.after_scope ; scopes also flow from condition out to statement edge @for_stmt.after_scope -> @condition.after_scope @@ -1499,11 +1511,13 @@ inherit .builtins_undefined (for_in_statement left:(identifier)@left right:(_)@right - body:(_)@body) { + body:(_)@body)@for_in_stmt +{ + + attr (@for_in_stmt.pop) node_definition = @left + edge @for_in_stmt.pop -> @right.value + edge @body.before_scope -> @for_in_stmt.pop - attr (@left.pop) node_definition = @left - edge @left.pop -> @right.value - edge @body.before_scope -> @left.pop } @@ -1565,11 +1579,11 @@ inherit .builtins_undefined (try_statement body:(_)@body - finalizer:(_)@finalizer)@try_stmt { + finalizer:(_)@finalizer)@_try_stmt { ; scopes flow from body to finalizer then back out edge @finalizer.before_scope -> @body.after_scope - edge @try_stmt.after_scope -> @finalizer.after_scope + } (try_statement @@ -1589,10 +1603,12 @@ inherit .builtins_undefined (catch_clause parameter:(identifier)@name - body:(_)@body) { + body:(_)@body)@catch_clause +{ + + attr (@catch_clause.pop) node_definition = @name + edge @body.before_scope -> @catch_clause.pop - attr (@name.pop) node_definition = @name - edge @body.before_scope -> @name.pop } (finally_clause body:(_)@body)@finally_clause { @@ -1614,9 +1630,9 @@ inherit .builtins_undefined edge @body.before_scope -> @object.after_scope edge @with_stmt.after_scope -> @body.after_scope - attr (@object.push_dot) push_symbol = "." - edge @object.push_dot -> @object.value - edge @body.before_scope -> @object.push_dot + attr (@with_stmt.push_dot) push_symbol = "GUARD:MEMBER" + edge @with_stmt.push_dot -> @object.value + edge @body.before_scope -> @with_stmt.push_dot } @@ -1628,6 +1644,18 @@ inherit .builtins_undefined edge @break_stmt.after_scope -> @break_stmt.before_scope } +(break_statement (_)@label)@break_stmt { + + node @break_stmt.label_push + node @break_stmt.label_guard + + attr (@break_stmt.label_guard) push_symbol = "GUARD:LABEL" + attr (@break_stmt.label_push) node_reference = @label + + edge @break_stmt.label_push -> @break_stmt.label_guard + edge @break_stmt.label_guard -> @break_stmt.before_scope +} + ;; #### Continue @@ -1637,6 +1665,18 @@ inherit .builtins_undefined edge @continue_stmt.after_scope -> @continue_stmt.before_scope } +(continue_statement (_)@label)@continue_stmt { + + node @continue_stmt.label_push + node @continue_stmt.label_guard + + attr (@continue_stmt.label_guard) push_symbol = "GUARD:LABEL" + attr (@continue_stmt.label_push) node_reference = @label + + edge @continue_stmt.label_push -> @continue_stmt.label_guard + edge @continue_stmt.label_guard -> @continue_stmt.before_scope +} + ;; #### Return @@ -1680,9 +1720,23 @@ inherit .builtins_undefined ;; #### Labeled -(labeled_statement (_)@inner)@labeled_stmt { +(labeled_statement + label:(_)@label + body:(_)@inner)@labeled_stmt +{ + + node @labeled_stmt.before_scope + node @labeled_stmt.after_scope + node @labeled_stmt.label_pop + node @labeled_stmt.label_guard + + attr (@labeled_stmt.label_guard) pop_symbol = "GUARD:LABEL" + attr (@labeled_stmt.label_pop) node_definition = @label + ; scopes flow through the inner statement then back out edge @inner.before_scope -> @labeled_stmt.before_scope + edge @inner.before_scope -> @labeled_stmt.label_guard + edge @labeled_stmt.label_guard -> @labeled_stmt.label_pop edge @labeled_stmt.after_scope -> @inner.after_scope } From 3fd0a98bbe52e034d630f14e889fee4c10592674 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 16:57:26 +0200 Subject: [PATCH 058/500] [conv] align with existing --- .../src/stack-graphs-conv.tsg | 657 ++++++++++-------- 1 file changed, 355 insertions(+), 302 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 49157bf4d..bdec2ff53 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -231,67 +231,75 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ## Nodes (_)@node { - node @node.after_scope - node @node.arg_arguments - node @node.arg_arguments_dot - node @node.arg_index - node @node.arg_scope - node @node.arg_scope_no_this - node @node.arg_this - node @node.arguments_pop - node @node.arguments_push - node @node.before_scope - node @node.boundvar_pop - node @node.call - node @node.constructor - node @node.constructor_guard - node @node.covalue - node @node.default_guard - node @node.definiens_hook - node @node.drop - node @node.element_index_push - node @node.element_index_push_dot - node @node.element_pop_dot - node @node.exports - node @node.exports_pop - node @node.field_pop_dot - node @node.guard_default - node @node.guard_this - node @node.ignore_guard - node @node.index_pop - node @node.method_value - node @node.method_value_arg_scope - node @node.method_value_call - node @node.method_value_drop - node @node.method_value_return - node @node.method_value_this - node @node.method_value_this_guard - node @node.module_guard - node @node.module_pop - node @node.module_scope - node @node.new_bindings - node @node.pop - node @node.pop_dot - node @node.pop_guard_default - node @node.push - node @node.push_dot - node @node.push_exports_guard - node @node.push_guard_default - node @node.push_guard_exports - node @node.return_guard - node @node.rhsvar_before_scope - node @node.rhsvar_value - node @node.source - node @node.string_prototype - node @node.this_pop - node @node.this_push - node @node.value - node @node.value_arg_scope - node @node.value_call - node @node.value_drop - node @node.value_return - node @node.value_this - node @node.value_this_guard + node @node.after_scope + node @node.arg_arguments + node @node.arg_arguments_dot + node @node.arg_index + node @node.arg_scope + node @node.arg_scope_no_this + node @node.arg_this + node @node.arguments_pop + node @node.arguments_push + node @node.before_scope + node @node.boundvar_pop + node @node.call + node @node.constructor + node @node.constructor_guard + node @node.covalue + node @node.default_guard + node @node.definiens_hook + node @node.drop + node @node.element_index_push + node @node.element_index_push_dot + node @node.element_pop_dot + node @node.exports + node @node.exports_pop + node @node.field_pop_dot + node @node.guard_default + node @node.guard_this + node @node.ignore_guard + node @node.index_pop + node @node.index_push + node @node.label_guard + node @node.label_pop + node @node.label_push + node @node.member_pop + node @node.member_push + node @node.method_value + node @node.method_value_arg_scope + node @node.method_value_call + node @node.method_value_drop + node @node.method_value_return + node @node.method_value_this + node @node.method_value_this_guard + node @node.module_guard + node @node.module_pop + node @node.module_scope + node @node.name_pop + node @node.name_push + node @node.new_bindings + node @node.pop + node @node.pop_dot + node @node.pop_guard_default + node @node.push + node @node.push_dot + node @node.push_exports_guard + node @node.push_guard_default + node @node.push_guard_exports + node @node.return_guard + node @node.rhsvar_before_scope + node @node.rhsvar_value + node @node.source + node @node.string_prototype + node @node.this_pop + node @node.this_push + node @node.value + node @node.value_arg_scope + node @node.value_call + node @node.value_drop + node @node.value_return + node @node.value_this + node @node.value_this_guard } @@ -322,41 +330,41 @@ inherit .builtins_undefined ;; ### Program Queries (program)@prog { - scan FILE_PATH { - "([^/]+)\.js$" { - attr (@prog.module_pop) symbol_definition = $1, source_node = @prog - attr (@prog.module_pop) empty_source_span + scan FILE_PATH { + "([^/]+)\.js$" { + attr (@prog.module_pop) symbol_definition = $1, source_node = @prog + attr (@prog.module_pop) empty_source_span + } } - } - edge @prog.before_scope -> ROOT_NODE + edge @prog.before_scope -> ROOT_NODE - attr (@prog.module_scope) pop_symbol = "GUARD:MODULE" - edge ROOT_NODE -> @prog.module_pop - edge @prog.module_pop -> @prog.module_scope - edge @prog.module_scope -> @prog.after_scope + attr (@prog.module_scope) pop_symbol = "GUARD:MODULE" + edge ROOT_NODE -> @prog.module_pop + edge @prog.module_pop -> @prog.module_scope + edge @prog.module_scope -> @prog.after_scope - attr (@prog) empty_source_span - attr (@prog.module_pop) empty_source_span - attr (@prog.module_scope) empty_source_span - attr (@prog.exports) empty_source_span - attr (@prog.exports_pop) empty_source_span - attr (@prog.before_scope) empty_source_span - attr (@prog.after_scope) empty_source_span + attr (@prog) empty_source_span + attr (@prog.module_pop) empty_source_span + attr (@prog.module_scope) empty_source_span + attr (@prog.exports) empty_source_span + attr (@prog.exports_pop) empty_source_span + attr (@prog.before_scope) empty_source_span + attr (@prog.after_scope) empty_source_span - attr (@prog.exports_pop) pop_symbol = "GUARD:EXPORTS" - edge @prog.module_pop -> @prog.exports_pop - edge @prog.exports_pop -> @prog.exports + attr (@prog.exports_pop) pop_symbol = "GUARD:EXPORTS" + edge @prog.module_pop -> @prog.exports_pop + edge @prog.exports_pop -> @prog.exports - ;; builtin types - node @prog.builtins_number - node @prog.builtins_string - node @prog.builtins_boolean - node @prog.builtins_null - node @prog.builtins_undefined - node @prog.builtins_Regex_prototype - node @prog.builtins_arguments_prototype - node @prog.builtins_empty_object + ;; builtin types + node @prog.builtins_number + node @prog.builtins_string + node @prog.builtins_boolean + node @prog.builtins_null + node @prog.builtins_undefined + node @prog.builtins_Regex_prototype + node @prog.builtins_arguments_prototype + node @prog.builtins_empty_object } ; programs, first statement @@ -899,8 +907,6 @@ inherit .builtins_undefined (variable_declarator name:(identifier)@name))@variable_decl { - node @variable_decl.name_pop - attr (@variable_decl.name_pop) node_definition = @name edge @variable_decl.after_scope -> @variable_decl.name_pop attr (@variable_decl.after_scope -> @variable_decl.name_pop) precedence = 1 @@ -912,8 +918,6 @@ inherit .builtins_undefined name:(identifier)@name))@lexical_decl { - node @lexical_decl.name_pop - attr (@lexical_decl.name_pop) node_definition = @name edge @lexical_decl.after_scope -> @lexical_decl.name_pop attr (@lexical_decl.after_scope -> @lexical_decl.name_pop) precedence = 1 @@ -1317,36 +1321,33 @@ inherit .builtins_undefined ;; #### If -(if_statement - condition:(_)@condition)@if_stmt { - - ; scopes flow from the if statement to the condition - edge @condition.before_scope -> @if_stmt.before_scope +(if_statement condition:(_)@condition)@if_stmt { + ; scopes flow from the if statement to the condition + edge @condition.before_scope -> @if_stmt.before_scope } (if_statement condition:(_)@condition - consequence:(_)@consequence)@if_stmt { - - ; scopes flow from the condition to the consequence, then to the if statement - edge @consequence.before_scope -> @condition.after_scope - edge @if_stmt.after_scope -> @consequence.after_scope + consequence:(_)@consequence)@if_stmt +{ + ; scopes flow from the condition to the consequence, then to the if statement + edge @consequence.before_scope -> @condition.after_scope + edge @if_stmt.after_scope -> @consequence.after_scope } (if_statement condition:(_)@condition - alternative:(_)@alternative)@if_stmt { - - ; scopes flow from the condition to the alternative, then to the if statement - edge @alternative.before_scope -> @condition.after_scope - edge @if_stmt.after_scope -> @alternative.after_scope + alternative:(_)@alternative)@if_stmt +{ + ; scopes flow from the condition to the alternative, then to the if statement + edge @alternative.before_scope -> @condition.after_scope + edge @if_stmt.after_scope -> @alternative.after_scope } (else_clause (_)@inner)@else_clause { - - ; scopes flow in and right back out - edge @inner.before_scope -> @else_clause.before_scope - edge @else_clause.after_scope -> @inner.after_scope + ; scopes flow in and right back out + edge @inner.before_scope -> @else_clause.before_scope + edge @else_clause.after_scope -> @inner.after_scope } @@ -1356,12 +1357,12 @@ inherit .builtins_undefined (switch_statement value:(_)@value - body:(switch_body)@body)@switch_stmt { - - ; scopes flow into the value then into the body then back out to the switch - edge @value.before_scope -> @switch_stmt.before_scope - edge @body.before_scope -> @value.after_scope - edge @switch_stmt.after_scope -> @body.after_scope + body:(switch_body)@body)@switch_stmt +{ + ; scopes flow into the value then into the body then back out to the switch + edge @value.before_scope -> @switch_stmt.before_scope + edge @body.before_scope -> @value.after_scope + edge @switch_stmt.after_scope -> @body.after_scope } ; LATER-TODO tree sitter doesn't yet support empty switch bodies @@ -1373,46 +1374,46 @@ inherit .builtins_undefined ; switch body, first choice (switch_body . - (_)@first_choice)@switch_body { - - ; scopes flow from the body into the first choice - edge @first_choice.before_scope -> @switch_body.before_scope + (_)@first_choice)@switch_body +{ + ; scopes flow from the body into the first choice + edge @first_choice.before_scope -> @switch_body.before_scope } ; switch body, between choices (switch_body (_)@left_choice . - (_)@right_choice) { - - ; scopes flow left to right - edge @right_choice.before_scope -> @left_choice.after_scope + (_)@right_choice) +{ + ; scopes flow left to right + edge @right_choice.before_scope -> @left_choice.after_scope } ; switch body, last choice (switch_body (_)@last_choice - .)@switch_body { - - ; scope flows out to the switch body - edge @switch_body.after_scope -> @last_choice.after_scope + .)@switch_body +{ + ; scope flows out to the switch body + edge @switch_body.after_scope -> @last_choice.after_scope } ; LATER-TODO tree sitter doesnt yet support switch case's with no statements ; THIS IS A HUGE HACK AND MUST BE FIXED (switch_case)@switch_case { - edge @switch_case.after_scope -> @switch_case.before_scope + edge @switch_case.after_scope -> @switch_case.before_scope } ; switch case, non-empty statements, first statement (switch_case value:(_)@value . - (_)@first_stmt)@switch_case { - - ; scopes flow into the value then into the first statement - edge @value.before_scope -> @switch_case.before_scope - edge @first_stmt.before_scope -> @value.after_scope + (_)@first_stmt)@switch_case +{ + ; scopes flow into the value then into the first statement + edge @value.before_scope -> @switch_case.before_scope + edge @first_stmt.before_scope -> @value.after_scope } ; switch case, non-empty statements, between statement @@ -1420,10 +1421,10 @@ inherit .builtins_undefined value:(_) (_)@left_stmt . - (_)@right_stmt) { - - ; scopes flow left to right - edge @right_stmt.before_scope -> @left_stmt.after_scope + (_)@right_stmt) +{ + ; scopes flow left to right + edge @right_stmt.before_scope -> @left_stmt.after_scope } ; switch case, non-empty statements, last statement @@ -1445,29 +1446,31 @@ inherit .builtins_undefined ; switch default, non-empty statements, first statement (switch_default . - (_)@first_stmt)@switch_default { - - ; scopes flow into the first statement - edge @first_stmt.before_scope -> @switch_default.before_scope + (_)@first_stmt)@switch_default +{ + ; scopes flow into the first statement + edge @first_stmt.before_scope -> @switch_default.before_scope } ; switch default, non-empty statements, between statements (switch_default (_)@left_stmt . - (_)@right_stmt) { + (_)@right_stmt) +{ - ; scopes flow left to right - edge @right_stmt.before_scope -> @left_stmt.after_scope + ; scopes flow left to right + edge @right_stmt.before_scope -> @left_stmt.after_scope } ; switch default, non-empty statements, last statement (switch_default (_)@last_stmt - .)@switch_default { + .)@switch_default +{ - ; scopes flow out to the default - edge @switch_default.after_scope -> @last_stmt.after_scope + ; scopes flow out to the default + edge @switch_default.after_scope -> @last_stmt.after_scope } @@ -1478,19 +1481,20 @@ inherit .builtins_undefined initializer:(_)@initializer condition:(_)@condition increment:(_)@increment - body:(_)@body)@for_stmt { + body:(_)@body)@for_stmt +{ - ; scopes flow from statement to initializer then test then body then increment - edge @initializer.before_scope -> @for_stmt.before_scope - edge @condition.before_scope -> @initializer.after_scope - edge @body.before_scope -> @condition.after_scope - edge @increment.before_scope -> @body.after_scope + ; scopes flow from statement to initializer then test then body then increment + edge @initializer.before_scope -> @for_stmt.before_scope + edge @condition.before_scope -> @initializer.after_scope + edge @body.before_scope -> @condition.after_scope + edge @increment.before_scope -> @body.after_scope - ; scopes also from from the body back into the condition + ; scopes also from from the body back into the condition edge @condition.before_scope -> @increment.after_scope - ; scopes also flow from condition out to statement - edge @for_stmt.after_scope -> @condition.after_scope + ; scopes also flow from condition out to statement + edge @for_stmt.after_scope -> @condition.after_scope } @@ -1500,12 +1504,13 @@ inherit .builtins_undefined (for_in_statement left:(_)@_left right:(_)@right - body:(_)@body)@for_in_stmt { + body:(_)@body)@for_in_stmt +{ - ; scopes flow from statement to right then to body then back out - edge @right.before_scope -> @for_in_stmt.before_scope - edge @body.before_scope -> @right.after_scope - edge @for_in_stmt.after_scope -> @body.after_scope + ; scopes flow from statement to right then to body then back out + edge @right.before_scope -> @for_in_stmt.before_scope + edge @body.before_scope -> @right.after_scope + edge @for_in_stmt.after_scope -> @body.after_scope } (for_in_statement @@ -1526,15 +1531,16 @@ inherit .builtins_undefined (while_statement condition:(_)@condition - body:(_)@body)@while_stmt { + body:(_)@body)@while_stmt +{ - ; scopes flow from while to condition then to body then back out - edge @condition.before_scope -> @while_stmt.before_scope - edge @body.before_scope -> @condition.after_scope - edge @while_stmt.after_scope -> @body.after_scope + ; scopes flow from while to condition then to body then back out + edge @condition.before_scope -> @while_stmt.before_scope + edge @body.before_scope -> @condition.after_scope + edge @while_stmt.after_scope -> @body.after_scope - ; scopes also flow back into the condition - edge @condition.before_scope -> @body.after_scope + ; scopes also flow back into the condition + edge @condition.before_scope -> @body.after_scope } @@ -1543,15 +1549,16 @@ inherit .builtins_undefined (do_statement body:(_)@body - condition:(_)@condition)@do_stmt { + condition:(_)@condition)@do_stmt +{ - ; scopes flow from statement to body then condition then back to statement - edge @body.before_scope -> @do_stmt.before_scope - edge @condition.before_scope -> @body.after_scope - edge @do_stmt.after_scope -> @condition.after_scope + ; scopes flow from statement to body then condition then back to statement + edge @body.before_scope -> @do_stmt.before_scope + edge @condition.before_scope -> @body.after_scope + edge @do_stmt.after_scope -> @condition.after_scope - ; scopes also flow back to the body from the condition - edge @body.before_scope -> @condition.after_scope + ; scopes also flow back to the body from the condition + edge @body.before_scope -> @condition.after_scope } @@ -1560,45 +1567,49 @@ inherit .builtins_undefined ;; #### Try (try_statement - body:(_)@body)@try_stmt { + body:(_)@body)@try_stmt +{ - ; scopes flow into the body then back out - edge @body.before_scope -> @try_stmt.before_scope - edge @try_stmt.after_scope -> @body.after_scope + ; scopes flow into the body then back out + edge @body.before_scope -> @try_stmt.before_scope + edge @try_stmt.after_scope -> @body.after_scope } (try_statement body:(_)@body - handler:(_)@handler)@try_stmt { + handler:(_)@handler)@try_stmt +{ - ; scopes flow from body to handler then back out - edge @handler.before_scope -> @body.after_scope - edge @try_stmt.after_scope -> @handler.after_scope + ; scopes flow from body to handler then back out + edge @handler.before_scope -> @body.after_scope + edge @try_stmt.after_scope -> @handler.after_scope } (try_statement body:(_)@body - finalizer:(_)@finalizer)@_try_stmt { + finalizer:(_)@finalizer)@_try_stmt +{ - ; scopes flow from body to finalizer then back out - edge @finalizer.before_scope -> @body.after_scope + ; scopes flow from body to finalizer then back out + edge @finalizer.before_scope -> @body.after_scope } (try_statement handler:(_)@handler - finalizer:(_)@finalizer)@try_stmt { + finalizer:(_)@finalizer)@try_stmt +{ - ; scopes flow from handler to finalizer then back out - edge @finalizer.before_scope -> @handler.after_scope - edge @try_stmt.after_scope -> @finalizer.after_scope + ; scopes flow from handler to finalizer then back out + edge @finalizer.before_scope -> @handler.after_scope + edge @try_stmt.after_scope -> @finalizer.after_scope } (catch_clause body:(_)@body)@catch_clause { - ; scopes flow in then back out - edge @body.before_scope -> @catch_clause.before_scope - edge @catch_clause.after_scope -> @body.after_scope + ; scopes flow in then back out + edge @body.before_scope -> @catch_clause.before_scope + edge @catch_clause.after_scope -> @body.after_scope } (catch_clause @@ -1612,9 +1623,9 @@ inherit .builtins_undefined } (finally_clause body:(_)@body)@finally_clause { - ; scopes flow in thenback out - edge @body.before_scope -> @finally_clause.before_scope - edge @finally_clause.after_scope -> @body.after_scope + ; scopes flow in thenback out + edge @body.before_scope -> @finally_clause.before_scope + edge @finally_clause.after_scope -> @body.after_scope } @@ -1623,12 +1634,13 @@ inherit .builtins_undefined (with_statement object:(_)@object - body:(_)@body)@with_stmt { + body:(_)@body)@with_stmt +{ - ; scopes flow from the statement into the object then into the body then back out - edge @object.before_scope -> @with_stmt.before_scope - edge @body.before_scope -> @object.after_scope - edge @with_stmt.after_scope -> @body.after_scope + ; scopes flow from the statement into the object then into the body then back out + edge @object.before_scope -> @with_stmt.before_scope + edge @body.before_scope -> @object.after_scope + edge @with_stmt.after_scope -> @body.after_scope attr (@with_stmt.push_dot) push_symbol = "GUARD:MEMBER" edge @with_stmt.push_dot -> @object.value @@ -1640,15 +1652,12 @@ inherit .builtins_undefined ;; #### Break (break_statement)@break_stmt { - ; scopes flow through unchanged - edge @break_stmt.after_scope -> @break_stmt.before_scope + ; scopes flow through unchanged + edge @break_stmt.after_scope -> @break_stmt.before_scope } (break_statement (_)@label)@break_stmt { - node @break_stmt.label_push - node @break_stmt.label_guard - attr (@break_stmt.label_guard) push_symbol = "GUARD:LABEL" attr (@break_stmt.label_push) node_reference = @label @@ -1661,15 +1670,12 @@ inherit .builtins_undefined ;; #### Continue (continue_statement)@continue_stmt { - ; scopes flow through unchanged - edge @continue_stmt.after_scope -> @continue_stmt.before_scope + ; scopes flow through unchanged + edge @continue_stmt.after_scope -> @continue_stmt.before_scope } (continue_statement (_)@label)@continue_stmt { - node @continue_stmt.label_push - node @continue_stmt.label_guard - attr (@continue_stmt.label_guard) push_symbol = "GUARD:LABEL" attr (@continue_stmt.label_push) node_reference = @label @@ -1725,19 +1731,14 @@ inherit .builtins_undefined body:(_)@inner)@labeled_stmt { - node @labeled_stmt.before_scope - node @labeled_stmt.after_scope - node @labeled_stmt.label_pop - node @labeled_stmt.label_guard - attr (@labeled_stmt.label_guard) pop_symbol = "GUARD:LABEL" attr (@labeled_stmt.label_pop) node_definition = @label - ; scopes flow through the inner statement then back out - edge @inner.before_scope -> @labeled_stmt.before_scope + ; scopes flow through the inner statement then back out + edge @inner.before_scope -> @labeled_stmt.before_scope edge @inner.before_scope -> @labeled_stmt.label_guard edge @labeled_stmt.label_guard -> @labeled_stmt.label_pop - edge @labeled_stmt.after_scope -> @inner.after_scope + edge @labeled_stmt.after_scope -> @inner.after_scope } @@ -1926,6 +1927,13 @@ inherit .builtins_undefined ;; #### Objects +(object)@object { + + attr (@object.member_pop) pop_symbol = "GUARD:MEMBER" + edge @object.value -> @object.member_pop + +} + ; empty objects ; LATER-TODO currently unsupported by tree sitter queries ; THIS IS A HUGE HACK AND MUST BE FIXED @@ -1960,65 +1968,109 @@ inherit .builtins_undefined } ; shorthand property identifier -(object - (shorthand_property_identifier)@keyval)@object { +(object (shorthand_property_identifier)@keyval)@object { + + node rhsvar_before_scope + node rhsvar_after_scope + node rhsvar_value + node key_pop + + attr (rhsvar_value) node_reference = @keyval + attr (key_pop) node_definition = @keyval ; scopes flow into rhsvar, and also straight across b/c they can't be modified - edge @keyval.rhsvar_before_scope -> @keyval.before_scope - edge @keyval.after_scope -> @keyval.before_scope + edge rhsvar_before_scope -> @keyval.before_scope + edge rhsvar_after_scope -> rhsvar_before_scope + edge @keyval.after_scope -> rhsvar_after_scope - ; shorthand property identifiers have secret variable exprs - attr (@keyval.rhsvar_value) node_reference = @keyval - edge @keyval.rhsvar_value -> @keyval.rhsvar_before_scope + edge rhsvar_value -> rhsvar_before_scope ; shorthand property identifiers augment the object value with a member binding - attr (@keyval.boundvar_pop) node_definition = @keyval + edge key_pop -> rhsvar_value + edge @object.member_pop -> key_pop +} + +; pairs + +(computed_property_name (_)@expr)@computed_property_name { + + node @computed_property_name.before_scope + node @computed_property_name.after_scope - attr (@object.field_pop_dot) pop_symbol = "." - edge @keyval.boundvar_pop -> @keyval.rhsvar_value - edge @object.field_pop_dot -> @keyval.boundvar_pop - edge @object.value -> @object.field_pop_dot + edge @expr.before_scope -> @computed_property_name.before_scope + edge @computed_property_name.after_scope -> @expr.after_scope } -; pairs (object (pair - key:(_)@key + key:(_)@_key value: (_)@value)@pair)@object { - ; scopes flow into values then back to the pair - edge @value.before_scope -> @pair.before_scope - edge @pair.after_scope -> @value.after_scope - - ; pairs augment the object value with a member binding + ; pairs augment the object value with a member binding + node @pair.key_pop - ; This is done differently depending on what the key is. See next rules. - ; attr (@key.pop) node_definition = @key - attr (@key.pop) node_definition = @key + ; This is done differently depending on what the key is. See next rules. + ; attr @key.pop "pop" = @key, "definition" + + edge @pair.key_pop -> @value.value + edge @object.member_pop -> @pair.key_pop - attr (@object.field_pop_dot) pop_symbol = "." - edge @key.pop -> @value.value - edge @object.field_pop_dot -> @key.pop - edge @object.value -> @object.field_pop_dot } -(pair key:(property_identifier)@key) { - attr (@key.pop) pop_node = @key +(pair + key:(property_identifier)@key + value:(_)@value)@pair +{ + + attr (@pair.key_pop) node_definition = @key + + ; scopes flow into the value, then back to the pair + edge @value.before_scope -> @pair.before_scope + edge @pair.after_scope -> @value.after_scope + } (pair key:(string)@key) { attr (@key.pop) pop_symbol = (replace @key "\"" "") } -(pair key:(number)@key) { - attr (@key.pop) pop_node = @key +(pair + key:(number)@key + value:(_)@value)@pair +{ + + attr (@pair.key_pop) node_definition = @key + + ; scopes flow into the value, then back to the pair + edge @value.before_scope -> @pair.before_scope + edge @pair.after_scope -> @value.after_scope + +} + +(pair + key:(computed_property_name)@key + value:(_)@value)@pair +{ + + ; scopes flow into the key, then out to the value, then back to the pair + edge @key.before_scope -> @pair.before_scope + edge @value.before_scope -> @key.after_scope + edge @pair.after_scope -> @value.after_scope + } ;; #### Arrays +(array)@array_expr { + + attr (@array_expr.element_pop_dot) pop_symbol = "GUARD:MEMBER" + edge @array_expr.value -> @array_expr.element_pop_dot + +} + ; empty arrays ; LATER-TODO currently unsupported by tree sitter queries ; THIS IS A HUGE HACK AND MUST BE FIXED @@ -2053,11 +2105,13 @@ inherit .builtins_undefined ; elements at indices (array (_)@element)@array_expr { - attr (@array_expr.element_pop_dot) pop_symbol = "." - attr (@element.index_pop) pop_symbol = (child-index @element) - edge @array_expr.element_pop_dot -> @element.index_pop - edge @array_expr.value -> @array_expr.element_pop_dot - edge @element.index_pop -> @element.value + + node element_index_pop + + attr (element_index_pop) symbol_definition = (named-child-index @element) + edge @array_expr.element_pop_dot -> element_index_pop + edge element_index_pop -> @element.value + } @@ -2435,64 +2489,62 @@ inherit .builtins_undefined (member_expression object: (_)@object - property: (_)@property)@member_expr { + property: (_)@property)@member_expr +{ + + node member_push + node property_push ; scopes flow into object then back out edge @object.before_scope -> @member_expr.before_scope edge @member_expr.after_scope -> @object.after_scope ; value is a member projection on the value of the object ie. a push then push dot - attr (@property.push) node_reference = @property - ;attr (@member_expr.value) push_node = @property.pop - attr (@member_expr.push_dot) push_symbol = "." - edge @property.push -> @member_expr.push_dot - ;edge @member_expr.value -> @member_expr.push_dot - edge @member_expr.value -> @property.push - edge @member_expr.push_dot -> @object.value + attr (member_push) push_symbol = "GUARD:MEMBER" + attr (property_push) node_reference = @property + edge property_push -> member_push + edge @member_expr.value -> property_push + edge member_push -> @object.value + } ;; ##### Subscript Expressions (subscript_expression object: (_)@object - index: (_)@index)@subscript_expression { + index: (_)@index)@subscript_expr { ; scopes flow left to right - edge @object.before_scope -> @subscript_expression.before_scope + edge @object.before_scope -> @subscript_expr.before_scope edge @index.before_scope -> @object.after_scope - edge @subscript_expression.after_scope -> @index.after_scope + edge @subscript_expr.after_scope -> @index.after_scope ; value is a subscript lookup, ie a push then push dot + attr (@subscript_expr.push_dot) push_symbol = "GUARD:MEMBER" + edge @subscript_expr.push_dot -> @object.value ; this is done differently depending on what the index is - ; attr (@index.push) node_reference = @index + ; attr @index.push "push" = @index, "reference" + edge @subscript_expr.value -> @subscript_expr.index_push + edge @subscript_expr.index_push -> @subscript_expr.push_dot } (subscript_expression - object: (_)@object - index: (string)@index)@subscript_expression { - - attr (@index.push) node_reference = @index + object: (_)@_object + index: (string)@index)@subscript_expr +{ - attr (@index.push_dot) push_symbol = "." - edge @subscript_expression.value -> @index.push - edge @index.push -> @index.push_dot - edge @index.push_dot -> @object.value - attr (@index.push) push_symbol = (replace @index "\"" "") + attr (@subscript_expr.index_push) push_symbol = (replace (source-text @index) "[\"\']" "") } (subscript_expression - object: (_)@object - index: (number)@index)@subscript_expression { + object: (_)@_object + index: (number)@index)@subscript_expr +{ - attr (@index.push) node_reference = @index + attr (@subscript_expr.index_push) node_reference = @index - attr (@index.push_dot) push_symbol = "." - edge @subscript_expression.value -> @index.push - edge @index.push -> @index.push_dot - edge @index.push_dot -> @object.value - attr (@index.push) push_node = @index } @@ -2564,10 +2616,10 @@ inherit .builtins_undefined ; LATER-TODO this isn't quite right because the update argument can't be an arbitrary expr ; eg f(x)++ doesn't make any sense, you have to have something more like ; (update_expression argument: (lvar)@argument) - attr (@argument.pop) node_definition = @argument + attr (@update_expr.pop) node_definition = @argument edge @update_expr.value -> @argument.value - edge @update_expr.after_scope -> @argument.pop - edge @argument.pop -> @argument.value + edge @update_expr.after_scope -> @update_expr.pop + edge @update_expr.pop -> @argument.value } @@ -2626,13 +2678,13 @@ inherit .builtins_undefined left: (identifier)@left right: (_)@right)@assignment_expr { - ; augments the scope by adding a lookup edge, ie. a pop - attr (@left.pop) node_definition = @left - edge @assignment_expr.after_scope -> @left.pop - edge @left.pop -> @right.value + ; augments the scope by adding a lookup edge, ie. a pop + attr (@assignment_expr.pop) node_definition = @left + edge @assignment_expr.after_scope -> @assignment_expr.pop + edge @assignment_expr.pop -> @right.value - ; ensure the scope flows through the identifier - edge @left.after_scope -> @left.before_scope + ; ensure the scope flows through the identifier + edge @left.after_scope -> @left.before_scope } ; assignment to direct fields on `this` @@ -2683,12 +2735,13 @@ inherit .builtins_undefined right:(_)@right)@augmented_assignment_expr { ; augment the scope - attr (@left.pop) node_definition = @left - attr (@left.push) node_reference = @left - edge @left.push -> @augmented_assignment_expr.before_scope - edge @left.pop -> @left.push - edge @left.pop -> @right.value - edge @augmented_assignment_expr.after_scope -> @left.pop + attr (@augmented_assignment_expr.pop) node_definition = @left + attr (@augmented_assignment_expr.push) node_reference = @left + edge @augmented_assignment_expr.push -> @augmented_assignment_expr.before_scope + edge @augmented_assignment_expr.pop -> @augmented_assignment_expr.push + edge @augmented_assignment_expr.pop -> @right.value + edge @augmented_assignment_expr.after_scope -> @augmented_assignment_expr.pop + } From 72455a80d72a1bec0b1d5ca6f080f423f21a05ea Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 17:01:53 +0200 Subject: [PATCH 059/500] [conv] cleanup attrs --- .../src/stack-graphs-conv.tsg | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index bdec2ff53..9c24e80e2 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -309,12 +309,12 @@ inherit .builtins_Regex_prototype inherit .builtins_arguments_prototype inherit .builtins_boolean inherit .builtins_empty_object -inherit .exports inherit .builtins_null inherit .builtins_number -inherit .return_or_yield inherit .builtins_string inherit .builtins_undefined +inherit .exports +inherit .return_or_yield ;; ██████ ██████ ██████ ██████ ██████ █████ ███ ███ ███████ ;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ████ ██ @@ -333,7 +333,6 @@ inherit .builtins_undefined scan FILE_PATH { "([^/]+)\.js$" { attr (@prog.module_pop) symbol_definition = $1, source_node = @prog - attr (@prog.module_pop) empty_source_span } } @@ -344,7 +343,6 @@ inherit .builtins_undefined edge @prog.module_pop -> @prog.module_scope edge @prog.module_scope -> @prog.after_scope - attr (@prog) empty_source_span attr (@prog.module_pop) empty_source_span attr (@prog.module_scope) empty_source_span attr (@prog.exports) empty_source_span @@ -365,6 +363,9 @@ inherit .builtins_undefined node @prog.builtins_Regex_prototype node @prog.builtins_arguments_prototype node @prog.builtins_empty_object + + ;; fallbacks + node @prog.return_or_yield } ; programs, first statement From 419fd0c9265fbfce7f729b239e074cadc18bf01e Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 17:02:21 +0200 Subject: [PATCH 060/500] [conv] child-index --- .../src/stack-graphs-conv.tsg | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 9c24e80e2..c356edcba 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -1054,7 +1054,7 @@ inherit .return_or_yield (formal_parameters (_)@param))@fun_decl { ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = (child-index @param) + attr (@param.arg_index) push_symbol = (named-child-index @param) edge @param.covalue -> @param.arg_index edge @param.arg_index -> @fun_decl.value_arg_scope } @@ -1124,7 +1124,7 @@ inherit .return_or_yield (formal_parameters (_)@param))@fun_decl { ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = (child-index @param) + attr (@param.arg_index) push_symbol = (named-child-index @param) edge @param.covalue -> @param.arg_index edge @param.arg_index -> @fun_decl.value_arg_scope } @@ -1255,7 +1255,7 @@ inherit .return_or_yield (formal_parameters (_)@param))@method_def { ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = (child-index @param) + attr (@param.arg_index) push_symbol = (named-child-index @param) edge @param.covalue -> @param.arg_index edge @param.arg_index -> @method_def.method_value_arg_scope } @@ -2227,7 +2227,7 @@ inherit .return_or_yield (formal_parameters (_)@param))@fun { ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = (child-index @param) + attr (@param.arg_index) push_symbol = (named-child-index @param) edge @param.covalue -> @param.arg_index edge @param.arg_index -> @fun.value_arg_scope } @@ -2309,7 +2309,7 @@ inherit .return_or_yield (formal_parameters (_)@param))@fun { ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = (child-index @param) + attr (@param.arg_index) push_symbol = (named-child-index @param) edge @param.covalue -> @param.arg_index edge @param.arg_index -> @fun.value_arg_scope } @@ -2376,7 +2376,7 @@ inherit .return_or_yield (formal_parameters (_)@param))@fun { ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = (child-index @param) + attr (@param.arg_index) push_symbol = (named-child-index @param) edge @param.covalue -> @param.arg_index edge @param.arg_index -> @fun.value_arg_scope } @@ -2445,7 +2445,7 @@ inherit .return_or_yield (call_expression arguments:(arguments (_)@arg)@arguments) { - attr (@arg.arg_index) pop_symbol = (child-index @arg) + attr (@arg.arg_index) pop_symbol = (named-child-index @arg) edge @arguments.arg_scope_no_this -> @arg.arg_index edge @arg.arg_index -> @arg.value } @@ -2588,7 +2588,7 @@ inherit .return_or_yield (new_expression arguments:(arguments (_)@arg)@arguments) { - attr (@arg.arg_index) pop_symbol = (child-index @arg) + attr (@arg.arg_index) pop_symbol = (named-child-index @arg) edge @arguments.arg_scope -> @arg.arg_index edge @arg.arg_index -> @arg.value } @@ -3243,7 +3243,7 @@ inherit .return_or_yield ; array pattern elements (array_pattern (_)@element_pat)@array_pat { - attr (@element_pat.element_index_push) push_symbol = (child-index @element_pat) + attr (@element_pat.element_index_push) push_symbol = (named-child-index @element_pat) attr (@array_pat.element_index_push_dot) push_symbol = "." edge @element_pat.covalue -> @element_pat.element_index_push edge @element_pat.element_index_push -> @array_pat.element_index_push_dot From c9a30ad907f34fd5257e9a27688694f7d1741a94 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 17:03:44 +0200 Subject: [PATCH 061/500] [conv] is_endpoint --- .../src/stack-graphs-conv.tsg | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index c356edcba..3b1dd328b 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -1032,14 +1032,14 @@ inherit .return_or_yield edge @fun_decl.value -> @fun_decl.value_call ; function values have return nodes which need to be visible for returns - attr (@fun_decl.value_return) is_exported + attr (@fun_decl.value_return) is_endpoint attr (@fun_decl.value_return) pop_symbol = "GUARD:RETURN" edge @fun_decl.value_call -> @fun_decl.value_return let @body.return_or_yield = @fun_decl.value_return ; method values have this nodes which need to be visible for constructor calls attr (@fun_decl.value_this) push_symbol = "this" - attr (@fun_decl.value_this_guard) is_exported + attr (@fun_decl.value_this_guard) is_endpoint attr (@fun_decl.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun_decl.value_call -> @fun_decl.value_this_guard edge @fun_decl.value_this_guard -> @fun_decl.value_this @@ -1102,14 +1102,14 @@ inherit .return_or_yield edge @fun_decl.value -> @fun_decl.value_call ; function values have return nodes which need to be visible for returns - attr (@fun_decl.value_return) is_exported + attr (@fun_decl.value_return) is_endpoint attr (@fun_decl.value_return) pop_symbol = "GUARD:RETURN" edge @fun_decl.value_call -> @fun_decl.value_return let @body.return_or_yield = @fun_decl.value_return ; method values have this nodes which need to be visible for constructor calls attr (@fun_decl.value_this) push_symbol = "this" - attr (@fun_decl.value_this_guard) is_exported + attr (@fun_decl.value_this_guard) is_endpoint attr (@fun_decl.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun_decl.value_call -> @fun_decl.value_this_guard edge @fun_decl.value_this_guard -> @fun_decl.value_this @@ -1233,14 +1233,14 @@ inherit .return_or_yield edge @method_def.method_value -> @method_def.method_value_call ; method values have return nodes which need to be visible for returns - attr (@method_def.method_value_return) is_exported + attr (@method_def.method_value_return) is_endpoint attr (@method_def.method_value_return) pop_symbol = "GUARD:RETURN" edge @method_def.method_value_call -> @method_def.method_value_return let @body.return_or_yield = @method_def.method_value_return ; method values have this nodes which need to be visible for constructor calls attr (@method_def.method_value_this) push_symbol = "this" - attr (@method_def.method_value_this_guard) is_exported + attr (@method_def.method_value_this_guard) is_endpoint attr (@method_def.method_value_this_guard) pop_symbol = "GUARD:THIS" edge @method_def.method_value_call -> @method_def.method_value_this_guard edge @method_def.method_value_this_guard -> @method_def.method_value_this @@ -2205,14 +2205,14 @@ inherit .return_or_yield edge @fun.value -> @fun.value_call ; function values have return nodes which need to be visible for returns - attr (@fun.value_return) is_exported + attr (@fun.value_return) is_endpoint attr (@fun.value_return) pop_symbol = "GUARD:RETURN" edge @fun.value_call -> @fun.value_return let @body.return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls attr (@fun.value_this) push_symbol = "this" - attr (@fun.value_this_guard) is_exported + attr (@fun.value_this_guard) is_endpoint attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun.value_call -> @fun.value_this_guard edge @fun.value_this_guard -> @fun.value_this @@ -2264,14 +2264,14 @@ inherit .return_or_yield edge @fun.value -> @fun.value_call ; function values have return nodes which need to be visible for returns - attr (@fun.value_return) is_exported + attr (@fun.value_return) is_endpoint attr (@fun.value_return) pop_symbol = "GUARD:RETURN" edge @fun.value_call -> @fun.value_return let @body.return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls attr (@fun.value_this) push_symbol = "this" - attr (@fun.value_this_guard) is_exported + attr (@fun.value_this_guard) is_endpoint attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun.value_call -> @fun.value_this_guard edge @fun.value_this_guard -> @fun.value_this @@ -2354,14 +2354,14 @@ inherit .return_or_yield edge @fun.value -> @fun.value_call ; function values have return nodes which need to be visible for returns - attr (@fun.value_return) is_exported + attr (@fun.value_return) is_endpoint attr (@fun.value_return) pop_symbol = "GUARD:RETURN" edge @fun.value_call -> @fun.value_return let @body.return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls attr (@fun.value_this) push_symbol = "this" - attr (@fun.value_this_guard) is_exported + attr (@fun.value_this_guard) is_endpoint attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun.value_call -> @fun.value_this_guard edge @fun.value_this_guard -> @fun.value_this From 515d6bbd17ca13e7407197513067c1acb6d292cf Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 17:06:48 +0200 Subject: [PATCH 062/500] [conv] attributes --- .../src/stack-graphs-conv.tsg | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 3b1dd328b..e6a91f638 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -236,6 +236,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.arg_arguments_dot node @node.arg_index node @node.arg_scope + attr (@node.arg_scope) is_exported node @node.arg_scope_no_this node @node.arg_this node @node.arguments_pop @@ -1032,14 +1033,12 @@ inherit .return_or_yield edge @fun_decl.value -> @fun_decl.value_call ; function values have return nodes which need to be visible for returns - attr (@fun_decl.value_return) is_endpoint attr (@fun_decl.value_return) pop_symbol = "GUARD:RETURN" edge @fun_decl.value_call -> @fun_decl.value_return let @body.return_or_yield = @fun_decl.value_return ; method values have this nodes which need to be visible for constructor calls attr (@fun_decl.value_this) push_symbol = "this" - attr (@fun_decl.value_this_guard) is_endpoint attr (@fun_decl.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun_decl.value_call -> @fun_decl.value_this_guard edge @fun_decl.value_this_guard -> @fun_decl.value_this @@ -1085,7 +1084,7 @@ inherit .return_or_yield ; the call sig's before scope comes from the drop node then flows into the body edge @call_sig.before_scope -> @fun_decl.value_drop - attr (@call_sig.this_pop) symbol_definition = "this", source_name = @call_sig + attr (@call_sig.this_pop) symbol_definition = "this", source_node = @call_sig attr (@call_sig.this_push) push_symbol = "this" edge @call_sig.this_pop -> @call_sig.this_push edge @call_sig.this_push -> @fun_decl.value_arg_scope @@ -1102,14 +1101,12 @@ inherit .return_or_yield edge @fun_decl.value -> @fun_decl.value_call ; function values have return nodes which need to be visible for returns - attr (@fun_decl.value_return) is_endpoint attr (@fun_decl.value_return) pop_symbol = "GUARD:RETURN" edge @fun_decl.value_call -> @fun_decl.value_return let @body.return_or_yield = @fun_decl.value_return ; method values have this nodes which need to be visible for constructor calls attr (@fun_decl.value_this) push_symbol = "this" - attr (@fun_decl.value_this_guard) is_endpoint attr (@fun_decl.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun_decl.value_call -> @fun_decl.value_this_guard edge @fun_decl.value_this_guard -> @fun_decl.value_this @@ -1233,14 +1230,12 @@ inherit .return_or_yield edge @method_def.method_value -> @method_def.method_value_call ; method values have return nodes which need to be visible for returns - attr (@method_def.method_value_return) is_endpoint attr (@method_def.method_value_return) pop_symbol = "GUARD:RETURN" edge @method_def.method_value_call -> @method_def.method_value_return let @body.return_or_yield = @method_def.method_value_return ; method values have this nodes which need to be visible for constructor calls attr (@method_def.method_value_this) push_symbol = "this" - attr (@method_def.method_value_this_guard) is_endpoint attr (@method_def.method_value_this_guard) pop_symbol = "GUARD:THIS" edge @method_def.method_value_call -> @method_def.method_value_this_guard edge @method_def.method_value_this_guard -> @method_def.method_value_this @@ -2205,14 +2200,12 @@ inherit .return_or_yield edge @fun.value -> @fun.value_call ; function values have return nodes which need to be visible for returns - attr (@fun.value_return) is_endpoint attr (@fun.value_return) pop_symbol = "GUARD:RETURN" edge @fun.value_call -> @fun.value_return let @body.return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls attr (@fun.value_this) push_symbol = "this" - attr (@fun.value_this_guard) is_endpoint attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun.value_call -> @fun.value_this_guard edge @fun.value_this_guard -> @fun.value_this @@ -2264,14 +2257,12 @@ inherit .return_or_yield edge @fun.value -> @fun.value_call ; function values have return nodes which need to be visible for returns - attr (@fun.value_return) is_endpoint attr (@fun.value_return) pop_symbol = "GUARD:RETURN" edge @fun.value_call -> @fun.value_return let @body.return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls attr (@fun.value_this) push_symbol = "this" - attr (@fun.value_this_guard) is_endpoint attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun.value_call -> @fun.value_this_guard edge @fun.value_this_guard -> @fun.value_this @@ -2354,14 +2345,12 @@ inherit .return_or_yield edge @fun.value -> @fun.value_call ; function values have return nodes which need to be visible for returns - attr (@fun.value_return) is_endpoint attr (@fun.value_return) pop_symbol = "GUARD:RETURN" edge @fun.value_call -> @fun.value_return let @body.return_or_yield = @fun.value_return ; function values have this nodes which need to be visible for method calls attr (@fun.value_this) push_symbol = "this" - attr (@fun.value_this_guard) is_endpoint attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" edge @fun.value_call -> @fun.value_this_guard edge @fun.value_this_guard -> @fun.value_this From 643b0ddffd27cf4593c984821a34855c652ca90e Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 17:08:18 +0200 Subject: [PATCH 063/500] [conv] nodes --- .../src/stack-graphs-conv.tsg | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index e6a91f638..d79ddd253 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -236,7 +236,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.arg_arguments_dot node @node.arg_index node @node.arg_scope - attr (@node.arg_scope) is_exported node @node.arg_scope_no_this node @node.arg_this node @node.arguments_pop @@ -261,6 +260,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.ignore_guard node @node.index_pop node @node.index_push + node @node.key_pop + node @node.key_push node @node.label_guard node @node.label_pop node @node.label_push @@ -301,6 +302,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.value_return node @node.value_this node @node.value_this_guard + + attr (@node.arg_scope) is_exported } @@ -1990,9 +1993,6 @@ inherit .return_or_yield (computed_property_name (_)@expr)@computed_property_name { - node @computed_property_name.before_scope - node @computed_property_name.after_scope - edge @expr.before_scope -> @computed_property_name.before_scope edge @computed_property_name.after_scope -> @expr.after_scope @@ -2004,7 +2004,6 @@ inherit .return_or_yield value: (_)@value)@pair)@object { ; pairs augment the object value with a member binding - node @pair.key_pop ; This is done differently depending on what the key is. See next rules. ; attr @key.pop "pop" = @key, "definition" From cb7ac1df660b89e1f2955ec444788b6c3a3279cb Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 17:10:15 +0200 Subject: [PATCH 064/500] [conv] fix array_pat duplicate edge --- .../src/stack-graphs-conv.tsg | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index d79ddd253..19e7b3130 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -3229,13 +3229,17 @@ inherit .return_or_yield edge @array_pat.after_scope -> @last_el_pat.after_scope } +; array pattern +(array_pattern)@array_pat { + edge @array_pat.element_index_push_dot -> @array_pat.covalue + attr (@array_pat.element_index_push_dot) push_symbol = "." +} + ; array pattern elements (array_pattern (_)@element_pat)@array_pat { attr (@element_pat.element_index_push) push_symbol = (named-child-index @element_pat) - attr (@array_pat.element_index_push_dot) push_symbol = "." edge @element_pat.covalue -> @element_pat.element_index_push edge @element_pat.element_index_push -> @array_pat.element_index_push_dot - edge @array_pat.element_index_push_dot -> @array_pat.covalue edge @array_pat.new_bindings -> @element_pat.new_bindings } From a1591c16d84d2ff3f10ed56ce8e5e27df8b8fb7a Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 17:12:18 +0200 Subject: [PATCH 065/500] [conv] source texts --- .../src/stack-graphs-conv.tsg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg index 19e7b3130..14e22a4c2 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg @@ -2027,7 +2027,7 @@ inherit .return_or_yield } (pair key:(string)@key) { - attr (@key.pop) pop_symbol = (replace @key "\"" "") + attr (@key.pop) pop_symbol = (replace (source-text @key) "\"" "") } (pair @@ -3143,7 +3143,7 @@ inherit .return_or_yield (pair_pattern key:(string)@key)@_pair_pattern { - attr (@key.push) symbol_reference = (replace @key "\"" ""), source_node = @key + attr (@key.push) symbol_reference = (replace (source-text @key) "\"" ""), source_node = @key } ; LATER-TODO the left pattern has to be a name, it cant be another pattern @@ -3387,7 +3387,7 @@ inherit .return_or_yield (#eq? @_require "require") ) { - scan @mod_name { + scan (source-text @mod_name) { "\"([^/\"]+)\.js\"$" { attr (@mod_name.push) push_symbol = $1 } From 2a47553102c56d86a7e20ddf796ec4eb97845d9d Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 17:15:27 +0200 Subject: [PATCH 066/500] move converted spec in place --- .../src/stack-graphs-conv.tsg | 3560 ----------------- .../src/stack-graphs.tsg | 3376 +++++++--------- 2 files changed, 1465 insertions(+), 5471 deletions(-) delete mode 100644 languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg deleted file mode 100644 index 14e22a4c2..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs-conv.tsg +++ /dev/null @@ -1,3560 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Stack graphs definition for JavaScript -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; Global Variables -;; ^^^^^^^^^^^^^^^^ - -global FILE_PATH -global ROOT_NODE -global JUMP_TO_SCOPE_NODE - - -;; Attribute Shorthands -;; ^^^^^^^^^^^^^^^^^^^^ - -attribute node_definition = node => type = "pop_symbol", node_symbol = node, is_definition -attribute node_reference = node => type = "push_symbol", node_symbol = node, is_reference -attribute pop_node = node => type = "pop_symbol", node_symbol = node -attribute pop_scoped_node = node => type = "pop_scoped_symbol", node_symbol = node -attribute pop_scoped_symbol = symbol => type = "pop_scoped_symbol", symbol = symbol -attribute pop_symbol = symbol => type = "pop_symbol", symbol = symbol -attribute push_node = node => type = "push_symbol", node_symbol = node -attribute push_scoped_node = node => type = "push_scoped_symbol", node_symbol = node -attribute push_scoped_symbol = symbol => type = "push_scoped_symbol", symbol = symbol -attribute push_symbol = symbol => type = "push_symbol", symbol = symbol -attribute scoped_node_definition = node => type = "pop_scoped_symbol", node_symbol = node, is_definition -attribute scoped_node_reference = node => type = "push_scoped_symbol", node_symbol = node, is_reference -attribute symbol_definition = symbol => type = "pop_symbol", symbol = symbol, is_definition -attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, is_reference - -attribute node_symbol = node => symbol = (source-text node), source_node = node - -;; Stack Graph Rules -;; ^^^^^^^^^^^^^^^^^ - -;; # JavaScript - -;; This file defines StackGraph queries for JavaScript. It is written as a -;; semi-literate file, which is to say, comments starting with `;;` can be -;; treated as Markdown. This file can therefore be converted into a -;; corresponding pure Markdown document by removing the StackGraph comments, and -;; wrapping the uncommented code in Markdown code blocks. - -;; This file has a number of sections that it's divided into, and it's useful to -;; provide an overview here. Aside from conventions, the queries are broken up -;; into groups by what kind of syntactic objects the group covers. There are -;; Programs, Statements, Expressions, Patterns, and Special Cases. - -;; Within each major section, we break things down by the particular syntactic -;; form under consideration. Some particular syntactic forms are not one of the -;; main forms listed, but are tightly associated with other forms -- for -;; example, the branches of an `if` statement are not statements nor -;; expressions, they're simply components of an `if` statement. In that -;; situation, we group them with the primary statement that they're associated -;; with, where possible, and nearby when not. - -;; Additionally, some syntactic constructs have arbitrary numbers of child -;; nodes, which requires us to explain how to relate them as sequences of -;; nodes. In such cases, we have associated queries with the node type in -;; question. - -;; ## Design Conventions - -;; The general convention for how JavaScript is translated into a Stack Graph is -;; to treat the graph as a reverse Control Flow Graph. There are some corner -;; cases for which that analogy doesn't quite work, but it's sufficient for -;; conveying the overall approach. Many things matter for name resolution in a -;; Control Flow Graph, but one of the only ones we can really encode into a -;; Stack Graph, and arguably the most important one, is the flow of the variable -;; environment, and so we create scope nodes for those. - -;; In particular, for each node, during an execution traversal, there is an -;; incoming variable environment that the node will be executed in, and an -;; outgoing variable environment that resulted from executing the node and all -;; the various variable assignments and updates inside it. - -;; An example helps, so let's consider a simplified case: `if` statement with a -;; mandatory `else` branch. If we were to implement an execution function for -;; this fictionalized language, there would be some environment that goes into -;; the execution at the whole `if-then-else` statement, an environment that goes -;; into the evaluation of the test, an environment that comes out of the test -;; (because the test could be something like `x++` which changes the -;; environment), an environment which goes into each branch (which happens to be -;; the same one that came out of the test), and an environment that comes out of -;; each of the branches. So each major AST node has a pair of environments -;; associated with it: the incoming one to execute it in, and the outcoming node -;; that resulted from executing. - -;; We therefore would implement `if-then-else` statements like so: - -;; ``````stgdoc -;; (if_then_else -;; (_)@test -;; (_)@consequent -;; (_)alternative)@if_stmt { -;; -;; edge @test.before_scope -> @if_stmt.before_scope -;; edge @consequent.before_scope -> @test.after_scope -;; edge @alternative.before_scope -> @test.after_scope -;; edge @if_stmt.after_scope -> @consequent.after_scope -;; edge @if_stmt.after_scope -> @alternative.after_scope -;; -;; } -;; `````` -;; -;; Another important way that things build scopes is through values. When an -;; expression is executed and returns a value, that value in many ways acts like -;; a sub-environment, at least in that the value has different parts that can be -;; accessed in various ways. For a simple value, as constructed by a number -;; literal expression, the number itself has no parts. So it has an associated -;; value scope node in the graph, but no edges coming off that: - -;; ``````stgdoc -;; (number)@num { -;; attr (@num.value) pop_symbol = "NUM_VAL" -;; } -;; `````` - -;; Why we use a `pop` attribute here isn't deeply important so we'll gloss over -;; it. - -;; All kinds of expressions have values, what precisely goes into them depends -;; on what the expression is. Objects, for instance, would have corresponding -;; values that point to the values of each of the keys in the object. Arrays -;; would have values that point to the values of each of the indexes. - -;; The primary purpose of values is to act as the targets of assignments, so -;; that names can resolve to something in code. Normally we care only about the -;; location of the assignment, of course, but we also need to be able to do -;; further lookup on the values. For instance, in an expression like `x.y.z`, -;; we need to look up `x` of course, but also then further look up `y` on that, -;; and then `z`. So whatever `x` is assigned to has to also be present in the -;; graph as something which can itself have stuff hanging off it that can be -;; used for lookup. - -;; If you were to run some JavaScript to test whether or not number literals -;; have parts (really, members/fields), you'd discover that actually they do, -;; but not because of which number they are. Rather, their parts are for builtin -;; functionality like `toString`. To handle this, we can point the value to some -;; shared global variable that represents the prototype for the number, like so: - -;; ``````stgdoc -;; (number)@num { -;; attr (@num.value) pop_symbol = "NUM_VAL" -;; edge @num.value -> @num.number_prototype -;; } -;; `````` - -;; In the preamble definition for the `program` node type, we could then also -;; want to define number prototype, something like this: - -;; ``````stgdoc -;; inherit .number_prototype -;; -;; (program)@prog { -;; -;; ... -;; -;; node @prog.number_prototype -;; edge @prog.number_prototype -> @prog.number_prototype_toString_method_value -;; edge @prog.number_prototype -> @prog.number_prototype_valueOf_method_value -;; ...etc -;; -;; ... -;; -;; } -;; `````` - -;; We would then also want to have a bunch of hand-encoded graphs for the values -;; of those fields. That would then allow the number values to point to their -;; prototypes where the fields could be found and used for further lookup on -;; methods. - -;; One caveat of this is that we don't want to get too deep into explaining how -;; some method might be implemented. Indeed, sometimes we *can't*, because it's -;; not implementable in JavaScript at all and is instead some primitive function -;; implemented in the host language. What we want to do, instead, is to provide -;; just enough implementation that other data can flow through as much as -;; possible, to prevent calls to primitive methods from blocking downstream name -;; resolution. For instance, it would be unfortunate if calling `toString` on a -;; number did not let you look up string fields on the resultant value of the -;; call, i.e. if `length` in `(5).toString().length` just simply could not be -;; resolved at all. In such cases, the ideal approach is to implement a bare -;; minimum of `toString` so that we can recover the fact that its returned -;; value is a string. E.g.: - -;; ``````stgdoc -;; (program)@prog { -;; -;; ... -;; -;; edge @prog.number_prototype -> @prog.number_prototype_toString_method_value -;; edge @prog.number_prototype_toString_method_value -> @prog.number_prototype_toString_method_value_return -;; attr (@prog.number_prototype_toString_method_value_return) pop_symbol = "GUARD:RETURN" -;; edge @prog.number_prototype_toString_method_value_return -> @prog.string_prototype -;; -;; ... -;; -;; } -;; `````` - -;; As currently implemented, this document does not contain any rules for -;; builtins because of the scope of that task, but they are currently in the -;; pipeline, using the above approach. - -;; Something you may notice in the above code snippet is this pop node labelled -;; `GUARD:RETURN`. This is another part of the design conventions for this -;; library. We often want to use nodes in the graph to constrain name lookup. -;; In this case, we want to be able to pinpoint some of the graph nodes -;; associated with the body of a function as being the values returned by the -;; function. We do this by creating a so-called guard node, which will only be -;; traversed if there is a corresponding push somewhere else. We would generate -;; such a push node precisely when we call a function. This lets us treat the -;; function *ASTs* as if they have parts that we can inspect *in the graph*. - -;; By convention, this library of queries prefixes all guard nodes with "GUARD:" -;; to distinguish them from nodes that more directly correspond to aspects of -;; execution such as member lookup (labelled with ".") or variable lookup -;; (labelled with the variable name itself). The current names used for guard -;; nodes are - -;; - `GUARD:RETURN` - used for the AST nodes for values returned by a function -;; in the function body -;; - `GUARD:THIS` - used for the implicit `this` argument of a function inside -;; its body -;; - `GUARD:CONSTRUCTOR` - used for the constructor method inside a `Class` -;; - `GUARD:MODULE` - used for the final scope of the module -;; - `GUARD:EXPORTS` - used for the names exported by the module -;; - `GUARD:DEFAULT` - used for the default export value - -;; ## Nodes - -(_)@node { - node @node.after_scope - node @node.arg_arguments - node @node.arg_arguments_dot - node @node.arg_index - node @node.arg_scope - node @node.arg_scope_no_this - node @node.arg_this - node @node.arguments_pop - node @node.arguments_push - node @node.before_scope - node @node.boundvar_pop - node @node.call - node @node.constructor - node @node.constructor_guard - node @node.covalue - node @node.default_guard - node @node.definiens_hook - node @node.drop - node @node.element_index_push - node @node.element_index_push_dot - node @node.element_pop_dot - node @node.exports - node @node.exports_pop - node @node.field_pop_dot - node @node.guard_default - node @node.guard_this - node @node.ignore_guard - node @node.index_pop - node @node.index_push - node @node.key_pop - node @node.key_push - node @node.label_guard - node @node.label_pop - node @node.label_push - node @node.member_pop - node @node.member_push - node @node.method_value - node @node.method_value_arg_scope - node @node.method_value_call - node @node.method_value_drop - node @node.method_value_return - node @node.method_value_this - node @node.method_value_this_guard - node @node.module_guard - node @node.module_pop - node @node.module_scope - node @node.name_pop - node @node.name_push - node @node.new_bindings - node @node.pop - node @node.pop_dot - node @node.pop_guard_default - node @node.push - node @node.push_dot - node @node.push_exports_guard - node @node.push_guard_default - node @node.push_guard_exports - node @node.return_guard - node @node.rhsvar_before_scope - node @node.rhsvar_value - node @node.source - node @node.string_prototype - node @node.this_pop - node @node.this_push - node @node.value - node @node.value_arg_scope - node @node.value_call - node @node.value_drop - node @node.value_return - node @node.value_this - node @node.value_this_guard - - attr (@node.arg_scope) is_exported -} - - -; ## Inherited - -inherit .builtins_Regex_prototype -inherit .builtins_arguments_prototype -inherit .builtins_boolean -inherit .builtins_empty_object -inherit .builtins_null -inherit .builtins_number -inherit .builtins_string -inherit .builtins_undefined -inherit .exports -inherit .return_or_yield - -;; ██████ ██████ ██████ ██████ ██████ █████ ███ ███ ███████ -;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ████ ██ -;; ██████ ██████ ██ ██ ██ ███ ██████ ███████ ██ ████ ██ ███████ -;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ -;; ██ ██ ██ ██████ ██████ ██ ██ ██ ██ ██ ██ ███████ - -;; ## Programs - -;; ### Attributes Defined on Programs -;; TODO - -;; ### Program Queries - -(program)@prog { - scan FILE_PATH { - "([^/]+)\.js$" { - attr (@prog.module_pop) symbol_definition = $1, source_node = @prog - } - } - - edge @prog.before_scope -> ROOT_NODE - - attr (@prog.module_scope) pop_symbol = "GUARD:MODULE" - edge ROOT_NODE -> @prog.module_pop - edge @prog.module_pop -> @prog.module_scope - edge @prog.module_scope -> @prog.after_scope - - attr (@prog.module_pop) empty_source_span - attr (@prog.module_scope) empty_source_span - attr (@prog.exports) empty_source_span - attr (@prog.exports_pop) empty_source_span - attr (@prog.before_scope) empty_source_span - attr (@prog.after_scope) empty_source_span - - attr (@prog.exports_pop) pop_symbol = "GUARD:EXPORTS" - edge @prog.module_pop -> @prog.exports_pop - edge @prog.exports_pop -> @prog.exports - - ;; builtin types - node @prog.builtins_number - node @prog.builtins_string - node @prog.builtins_boolean - node @prog.builtins_null - node @prog.builtins_undefined - node @prog.builtins_Regex_prototype - node @prog.builtins_arguments_prototype - node @prog.builtins_empty_object - - ;; fallbacks - node @prog.return_or_yield -} - -; programs, first statement -(program - . - (_)@first_stmt)@prog { - - ; scopes flow from the program into the first statement - edge @first_stmt.before_scope -> @prog.before_scope -} - -; program, between statements -(program - (_)@left_stmt - . - (_)@right_stmt) { - - ; scopes flow from the left statement to the right one - edge @right_stmt.before_scope -> @left_stmt.after_scope -} - -; program, last statement -(program - (_)@last_stmt - .)@prog { - - ; scopes flow from the last statement to the program - edge @prog.after_scope -> @last_stmt.after_scope -} - -(hash_bang_line)@hashbang { - edge @hashbang.after_scope -> @hashbang.before_scope -} - -(comment)@comment { - edge @comment.after_scope -> @comment.before_scope -} - - - -;; ███████ ████████ █████ ████████ ███████ ███ ███ ███████ ███ ██ ████████ ███████ -;; ██ ██ ██ ██ ██ ██ ████ ████ ██ ████ ██ ██ ██ -;; ███████ ██ ███████ ██ █████ ██ ████ ██ █████ ██ ██ ██ ██ ███████ -;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ -;; ███████ ██ ██ ██ ██ ███████ ██ ██ ███████ ██ ████ ██ ███████ - -;; ## Statements - -;; ### Attributes Defined on Statements -;; TODO - -;; ### Statement Queries - -;; ███████ ██ ██ ██████ ██████ ██████ ████████ ███████ -;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ -;; █████ ███ ██████ ██ ██ ██████ ██ ███████ -;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ -;; ███████ ██ ██ ██ ██████ ██ ██ ██ ███████ - -;; #### Export - -; exports of just names -; eg -; export { foo, bar as baz }; -(export_statement - (export_clause)@export_clause - !source)@export_stmt { - - edge @export_clause.source -> @export_clause.before_scope - - ; scope flows through the export clause - edge @export_clause.before_scope -> @export_stmt.before_scope - edge @export_stmt.after_scope -> @export_clause.after_scope -} - -(export_statement - (export_clause)@export_clause - source:(_)@source)@export_stmt { - - edge @export_clause.source -> @source.push_exports_guard - - attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" - scan @source { - "\"([^/\"]+)\.js\"$" { - attr (@source.push) push_symbol = $1 - } - } - edge @source.push_exports_guard -> @source.push - edge @source.push -> ROOT_NODE - - edge @export_clause.before_scope -> @export_stmt.before_scope - edge @export_stmt.after_scope -> @export_clause.after_scope - - -} - -(export_statement - (declaration)@decl)@export_stmt { - edge @decl.before_scope -> @export_stmt.before_scope - edge @export_stmt.after_scope -> @decl.after_scope -} - -(export_statement - declaration: [ - (function_declaration name:(identifier)@name) - (generator_function_declaration name:(identifier)@name) - (class_declaration name:(identifier)@name) - (lexical_declaration (variable_declarator name:(identifier)@name)) - (variable_declaration (variable_declarator name:(identifier)@name)) - ]@decl)@export_stmt { - - ; TODO this doesn't support destructuring exports - - attr (@name.pop) node_definition = @name - attr (@name.push) push_node = @name - edge @export_stmt.exports -> @name.pop - edge @name.pop -> @decl.value -} - -; TODO -; export let [x,y] = [1,2]; -(export_statement - declaration: [ - (lexical_declaration - (variable_declarator - name: [ - (object_pattern) - (array_pattern) - ]@pattern)) - (variable_declaration - (variable_declarator - name: [ - (object_pattern) - (array_pattern) - ]@pattern)) - ])@export_stmt { - - edge @export_stmt.exports -> @pattern.new_bindings - -} - -; LATER-TODO tree sitter doesn't yet support empty switch bodies -; THIS IS A HUGE HACK AND MUST BE FIXED -(export_clause)@export_clause { - edge @export_clause.after_scope -> @export_clause.before_scope -} - -(export_clause - (_)@export)@export_clause { - - edge @export.source -> @export_clause.source -} - -(export_clause - . - (_)@first_export)@export_clause { - - edge @first_export.before_scope -> @export_clause.before_scope -} - -(export_clause - (_)@left_export - . - (_)@right_export) { - - edge @right_export.before_scope -> @left_export.after_scope -} - -(export_clause - (_)@last_export - .)@export_clause { - - edge @export_clause.after_scope -> @last_export.after_scope -} - -(export_specifier)@export_specifier { - edge @export_specifier.after_scope -> @export_specifier.before_scope -} - -( - (export_specifier - name:(_)@name - !alias)@export_specifier - - (#not-eq? @name "default") -) { - - attr (@name.pop) node_definition = @name - attr (@name.push) node_reference = @name - edge @name.pop -> @name.push - edge @name.push -> @export_specifier.source - - edge @export_specifier.exports -> @name.pop -} - -( - (export_specifier - name:(_)@name - alias:(_)@alias)@export_specifier - - (#not-eq? @alias "default") - -) { - - attr (@alias.pop) node_definition = @alias - attr (@name.push) node_reference = @name - edge @alias.pop -> @name.push - edge @name.push -> @export_specifier.source - - edge @export_specifier.exports -> @alias.pop -} - -( - (export_specifier - name:(_)@_name - !alias)@export_specifier - - (#eq? @_name "default") - -) { - - attr (@export_specifier.pop_guard_default) pop_symbol = "GUARD:DEFAULT" - attr (@export_specifier.push_guard_default) push_symbol = "GUARD:DEFAULT" - edge @export_specifier.exports -> @export_specifier.pop_guard_default - edge @export_specifier.pop_guard_default -> @export_specifier.push_guard_default - edge @export_specifier.push_guard_default -> @export_specifier.source - -} - -( - (export_specifier - name:(_)@name - alias:(_)@_alias)@export_specifier - - (#eq? @_alias "default") - -) { - - attr (@name.push) push_node = @name - attr (@export_specifier.guard_default) pop_symbol = "GUARD:DEFAULT" - edge @name.push -> @export_specifier.source - edge @export_specifier.guard_default -> @name.push - edge @export_specifier.exports -> @export_specifier.guard_default -} - -; simple default exports -; export default ...; - -(export_statement - value:(_)@default_expr)@export_stmt { - - attr (@export_stmt.default_guard) symbol_definition = "GUARD:DEFAULT", source_node = @export_stmt - edge @default_expr.before_scope -> @export_stmt.before_scope - edge @export_stmt.after_scope -> @default_expr.after_scope - edge @export_stmt.exports -> @export_stmt.default_guard - edge @export_stmt.default_guard -> @default_expr.value -} - -; aggregated exports -; export * from "foo.js"; -(export_statement - . - source:(_)@source)@export_statement { - - edge @export_statement.after_scope -> @export_statement.before_scope - - attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" - scan @source { - "\"([^/\"]+)\.js\"$" { - attr (@source.push) push_symbol = $1 - } - } - - edge @export_statement.exports -> @source.push_exports_guard - edge @source.push_exports_guard -> @source.push - edge @source.push -> ROOT_NODE - -} - -; namespace exports -; export * as foo from "bar.js"; -(export_statement - (namespace_export (_)@alias) - source:(_)@source)@export_statement { - - edge @export_statement.after_scope -> @export_statement.before_scope - - attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" - scan @source { - "\"([^/\"]+)\.js\"$" { - attr (@source.push) push_symbol = $1 - } - } - attr (@alias.pop) node_definition = @alias - attr (@alias.pop_dot) pop_symbol = "." - edge @export_statement.exports -> @alias.pop - edge @alias.pop -> @alias.pop_dot - edge @alias.pop_dot -> @source.push_exports_guard - edge @source.push_exports_guard -> @source.push - edge @source.push -> ROOT_NODE - -} - - - -;; ██ ███ ███ ██████ ██████ ██████ ████████ ███████ -;; ██ ████ ████ ██ ██ ██ ██ ██ ██ ██ ██ -;; ██ ██ ████ ██ ██████ ██ ██ ██████ ██ ███████ -;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ -;; ██ ██ ██ ██ ██████ ██ ██ ██ ███████ - -;; #### Import - -; https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import - - -; import "foo.js"; -; only used for side effects not imports. -; HACK this is not a good solution, but we can't do better with the -; current tree sitter grammar -(import_statement)@import_stmt { - edge @import_stmt.after_scope -> @import_stmt.before_scope -} - -; import * as name from "module-name"; -(import_clause - (namespace_import)@namespace_import)@import_clause { - - edge @namespace_import.before_scope -> @import_clause.before_scope - edge @import_clause.after_scope -> @namespace_import.after_scope - edge @namespace_import.source -> @import_clause.source -} - -(namespace_import (identifier)@imported_as)@namespace_import { - - edge @namespace_import.after_scope -> @namespace_import.before_scope - - attr (@imported_as.pop) node_definition = @imported_as - attr (@imported_as.pop_dot) pop_symbol = "." - edge @imported_as.pop -> @imported_as.pop_dot - edge @imported_as.pop_dot -> @namespace_import.source - - edge @namespace_import.after_scope -> @imported_as.pop - -} - -; import { export1 } from "module-name"; -; import { export1 as alias1 } from "module-name"; -; import { export1 , export2 } from "module-name"; -; import { export1 , export2 as alias2 , [...] } from "module-name"; - -(import_statement - (import_clause)@import_clause - source:(_)@source)@import_stmt { - - edge @import_clause.before_scope -> @import_stmt.before_scope - edge @import_stmt.after_scope -> @import_clause.after_scope - - scan @source { - "\"([^/\"]+)\.js\"$" { - attr (@source.push) push_symbol = $1 - } - } - attr (@source.push_guard_exports) push_symbol = "GUARD:EXPORTS" - edge @source.push_guard_exports -> @source.push - edge @source.push -> ROOT_NODE - edge @import_clause.source -> @source.push_guard_exports - -} - -(import_clause - (named_imports)@named_imports)@import_clause { - - edge @named_imports.before_scope -> @import_clause.before_scope - edge @import_clause.after_scope -> @named_imports.after_scope - edge @named_imports.source -> @import_clause.source - -} - -; LATER-TODO tree sitter doesn't yet support empty named imports -; THIS IS A HUGE HACK AND MUST BE FIXED -(named_imports)@named_imports { - edge @named_imports.after_scope -> @named_imports.before_scope -} - -(named_imports - (import_specifier)@import_specifier)@named_imports { - - edge @import_specifier.source -> @named_imports.source -} - -(named_imports - . - (import_specifier)@first_import)@named_imports { - - edge @first_import.before_scope -> @named_imports.before_scope -} - -(named_imports - (import_specifier)@left_import - . - (import_specifier)@right_import) { - - edge @right_import.before_scope -> @left_import.after_scope -} - -(named_imports - (import_specifier)@last_import - .)@named_imports { - - edge @named_imports.after_scope -> @last_import.after_scope -} - -( - - (import_specifier - name:(_)@name - !alias)@import_specifier - - (#not-eq? @name "default") - -) { - - edge @import_specifier.after_scope -> @import_specifier.before_scope - - attr (@name.pop) node_definition = @name - attr (@name.push) node_reference = @name - edge @name.pop -> @name.push - edge @name.push -> @import_specifier.source - edge @import_specifier.after_scope -> @name.pop - -} - -( - - (import_specifier - name:(_)@name - alias:(_)@alias)@import_specifier - - (#not-eq? @name "default") - -) { - - edge @import_specifier.after_scope -> @import_specifier.before_scope - - attr (@alias.pop) node_definition = @alias - attr (@name.push) node_reference = @name - edge @alias.pop -> @name.push - edge @name.push -> @import_specifier.source - edge @import_specifier.after_scope -> @alias.pop - -} - -; (import_statement -; (import_clause -; (named_imports -; (import_specifier -; name:(_)@name -; alias:(_)@alias))) -; source: (_)@mod_name)@import_stmt { -; -; ; scope passes through, augmented by the identifier -; scan @mod_name { -; "\"([^/\"]+)\.js\"$" { -; attr (@mod_name.push) symbol_reference = $1, source_node = @mod_name -; } -; } -; edge @mod_name.push -> ROOT_NODE -; -; attr (@name) node_reference = @name -; attr (@name.push_dot) push_symbol = "." -; edge @name.push_dot -> @mod_name.push -; edge @name -> @name.push_dot -; -; attr (@alias) node_definition = @alias -; edge @alias -> @name -; -; edge @import_stmt.after_scope -> @alias -; } - - -; TODO import defaultExport, { export1 [ , [...] ] } from "module-name"; -; TODO import defaultExport, * as name from "module-name"; -; TODO var promise = import("module-name"); - -; import defaultExport from "module-name"; -(import_clause - (identifier)@default_name)@import_clause { - - edge @import_clause.after_scope -> @import_clause.before_scope - - attr (@default_name.pop) node_definition = @default_name - attr (@default_name.push_guard_default) push_symbol = "GUARD:DEFAULT" - edge @default_name.pop -> @default_name.push_guard_default - edge @default_name.push_guard_default -> @import_clause.source - - edge @import_clause.after_scope -> @default_name.pop - -} - - - -;; ███ ██ ██████ ██████ ███ ███ █████ ██ -;; ████ ██ ██ ██ ██ ██ ████ ████ ██ ██ ██ -;; ██ ██ ██ ██ ██ ██████ ██ ████ ██ ███████ ██ -;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ -;; ██ ████ ██████ ██ ██ ██ ██ ██ ██ ███████ - -;; ███████ ████████ █████ ████████ ███████ ███ ███ ███████ ███ ██ ████████ ███████ -;; ██ ██ ██ ██ ██ ██ ████ ████ ██ ████ ██ ██ ██ -;; ███████ ██ ███████ ██ █████ ██ ████ ██ █████ ██ ██ ██ ██ ███████ -;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ -;; ███████ ██ ██ ██ ██ ███████ ██ ██ ███████ ██ ████ ██ ███████ - -;; #### Debugger - -(debugger_statement)@debugger_stmt { - ; scopes flow through unchanged - edge @debugger_stmt.after_scope -> @debugger_stmt.before_scope -} - - - -;; #### Expression - -(expression_statement (_)@inner)@expr_stmt { - - ; scopes flow in then back out - edge @inner.before_scope -> @expr_stmt.before_scope - edge @expr_stmt.after_scope -> @inner.after_scope -} - - - -;; #### Declarations - -;; ##### Variable Declarations - -(variable_declaration - (variable_declarator - name:(identifier)@name))@variable_decl -{ - attr (@variable_decl.name_pop) node_definition = @name - edge @variable_decl.after_scope -> @variable_decl.name_pop - attr (@variable_decl.after_scope -> @variable_decl.name_pop) precedence = 1 - -} - -(lexical_declaration - (variable_declarator - name:(identifier)@name))@lexical_decl -{ - - attr (@lexical_decl.name_pop) node_definition = @name - edge @lexical_decl.after_scope -> @lexical_decl.name_pop - attr (@lexical_decl.after_scope -> @lexical_decl.name_pop) precedence = 1 - -} - -(variable_declaration - (variable_declarator - !value))@decl { - - edge @decl.after_scope -> @decl.before_scope -} - -(lexical_declaration - (variable_declarator - !value))@decl { - - edge @decl.after_scope -> @decl.before_scope -} - -(variable_declaration - (variable_declarator - name:(identifier)@_name - value:(_)@initializer))@variable_decl -{ - - edge @variable_decl.name_pop -> @initializer.value - edge @initializer.before_scope -> @variable_decl.before_scope - edge @variable_decl.after_scope -> @initializer.after_scope - -} - -(lexical_declaration - (variable_declarator - name:(identifier)@_name - value:(_)@initializer))@lexical_decl -{ - - edge @lexical_decl.name_pop -> @initializer.value - edge @initializer.before_scope -> @lexical_decl.before_scope - edge @lexical_decl.after_scope -> @initializer.after_scope - attr (@lexical_decl.after_scope -> @initializer.after_scope) precedence = 0 - -} - -(variable_declaration - (variable_declarator - name:[(object_pattern) (array_pattern)]@pat - value:(_)@initializer))@decl { - - edge @initializer.before_scope -> @decl.before_scope - edge @pat.before_scope -> @initializer.after_scope - edge @decl.after_scope -> @pat.after_scope - - edge @pat.covalue -> @initializer.value -} - -(lexical_declaration - (variable_declarator - name:[(object_pattern) (array_pattern)]@pat - value:(_)@initializer))@decl { - - edge @initializer.before_scope -> @decl.before_scope - edge @pat.before_scope -> @initializer.after_scope - edge @decl.after_scope -> @pat.after_scope - - edge @pat.covalue -> @initializer.value -} - - - -;; ##### Function Declarations - -(function_declaration - name:(_)@name - parameters:(_)@call_sig - body:(_)@body)@fun_decl { - - attr (@name.pop) syntax_type = "function" - - ; scope flows across the decl - edge @fun_decl.after_scope -> @fun_decl.before_scope - - ; with an augmentation for the function - attr (@name.pop) node_definition = @name - edge @fun_decl.after_scope -> @name.pop - edge @name.pop -> @fun_decl.value - - ; function values have drop nodes that handle closures, that points to the - ; before scope for the function - attr (@fun_decl.value_drop) type = "drop_scopes" - edge @fun_decl.value_drop -> @fun_decl.before_scope - - ; the call sig's before scope comes from the drop node then flows into the body - edge @call_sig.before_scope -> @fun_decl.value_drop - attr (@call_sig.this_pop) symbol_definition = "this", source_node = @call_sig - attr (@call_sig.this_push) push_symbol = "this" - edge @call_sig.this_pop -> @call_sig.this_push - edge @call_sig.this_push -> @fun_decl.value_arg_scope - edge @call_sig.before_scope -> @call_sig.this_pop - attr (@call_sig.arguments_pop) symbol_definition = "arguments", source_node = @call_sig - attr (@call_sig.arguments_push) push_symbol = "arguments" - edge @call_sig.arguments_pop -> @call_sig.arguments_push - edge @call_sig.arguments_push -> @fun_decl.value_arg_scope - edge @call_sig.before_scope -> @call_sig.arguments_pop - edge @body.before_scope -> @call_sig.after_scope - - - ; function values have call nodes - attr (@fun_decl.value_call) pop_scoped_symbol = "()" - edge @fun_decl.value -> @fun_decl.value_call - - ; function values have return nodes which need to be visible for returns - attr (@fun_decl.value_return) pop_symbol = "GUARD:RETURN" - edge @fun_decl.value_call -> @fun_decl.value_return - let @body.return_or_yield = @fun_decl.value_return - - ; method values have this nodes which need to be visible for constructor calls - attr (@fun_decl.value_this) push_symbol = "this" - attr (@fun_decl.value_this_guard) pop_symbol = "GUARD:THIS" - edge @fun_decl.value_call -> @fun_decl.value_this_guard - edge @fun_decl.value_this_guard -> @fun_decl.value_this - edge @fun_decl.value_this -> @body.after_scope - - ; function values have a jump node that lets params connect up to actual arguments - edge @fun_decl.value_arg_scope -> JUMP_TO_SCOPE_NODE -} - -(function_declaration - parameters: - (formal_parameters (_)@param))@fun_decl { - - ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = (named-child-index @param) - edge @param.covalue -> @param.arg_index - edge @param.arg_index -> @fun_decl.value_arg_scope -} - - -;; ##### Generator Function Declarations - -(generator_function_declaration - name:(_)@name - parameters:(_)@call_sig - body:(_)@body)@fun_decl { - - attr (@name.pop) syntax_type = "function" - - ; scope flows across the decl - edge @fun_decl.after_scope -> @fun_decl.before_scope - - ; with an augmentation for the function - attr (@name.pop) node_definition = @name - edge @fun_decl.after_scope -> @name.pop - edge @name.pop -> @fun_decl.value - - ; function values have drop nodes that handle closures, that points to the - ; before scope of the declaration - attr (@fun_decl.value_drop) type = "drop_scopes" - edge @fun_decl.value_drop -> @fun_decl.before_scope - - - ; the call sig's before scope comes from the drop node then flows into the body - edge @call_sig.before_scope -> @fun_decl.value_drop - attr (@call_sig.this_pop) symbol_definition = "this", source_node = @call_sig - attr (@call_sig.this_push) push_symbol = "this" - edge @call_sig.this_pop -> @call_sig.this_push - edge @call_sig.this_push -> @fun_decl.value_arg_scope - edge @call_sig.before_scope -> @call_sig.this_pop - attr (@call_sig.arguments_pop) symbol_definition = "arguments", source_node = @call_sig - attr (@call_sig.arguments_push) push_symbol = "arguments" - edge @call_sig.arguments_pop -> @call_sig.arguments_push - edge @call_sig.arguments_push -> @fun_decl.value_arg_scope - edge @call_sig.before_scope -> @call_sig.arguments_pop - edge @body.before_scope -> @call_sig.after_scope - - ; function values have call nodes - attr (@fun_decl.value_call) pop_scoped_symbol = "()" - edge @fun_decl.value -> @fun_decl.value_call - - ; function values have return nodes which need to be visible for returns - attr (@fun_decl.value_return) pop_symbol = "GUARD:RETURN" - edge @fun_decl.value_call -> @fun_decl.value_return - let @body.return_or_yield = @fun_decl.value_return - - ; method values have this nodes which need to be visible for constructor calls - attr (@fun_decl.value_this) push_symbol = "this" - attr (@fun_decl.value_this_guard) pop_symbol = "GUARD:THIS" - edge @fun_decl.value_call -> @fun_decl.value_this_guard - edge @fun_decl.value_this_guard -> @fun_decl.value_this - edge @fun_decl.value_this -> @body.after_scope - - ; function values have a jump node that lets params connect up to actual arguments - edge @fun_decl.value_arg_scope -> JUMP_TO_SCOPE_NODE -} - -(generator_function_declaration - parameters: - (formal_parameters (_)@param))@fun_decl { - - ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = (named-child-index @param) - edge @param.covalue -> @param.arg_index - edge @param.arg_index -> @fun_decl.value_arg_scope -} - - - -;; #### Classes - -(class_declaration - name:(_)@name - body:(_)@body)@class_decl { - - attr (@name.pop) syntax_type = "class" - - attr (@name.pop) node_definition = @name - edge @class_decl.after_scope -> @name.pop - edge @name.pop -> @class_decl.value - - edge @body.before_scope -> @class_decl.before_scope - edge @class_decl.value -> @body.after_scope - edge @class_decl.after_scope -> @class_decl.before_scope -} - -(class_declaration - (class_heritage (_)@name))@class_decl { - - edge @name.before_scope -> @class_decl.before_scope - edge @class_decl.value -> @name.value -} - - -; LATER-TODO tree sitter doesn't yet support empty switch bodies -; THIS IS A HUGE HACK AND MUST BE FIXED -(class_body)@class_body { - edge @class_body.after_scope -> @class_body.before_scope -} - -(class_body - . - (_)@first_decl)@class_body { - - edge @first_decl.before_scope -> @class_body.before_scope -} - -(class_body - (_)@left_decl - . - (_)@right_decl) { - - edge @right_decl.before_scope -> @left_decl.after_scope -} - -(class_body - (_)@last_decl - .)@class_body { - - edge @class_body.after_scope -> @last_decl.after_scope -} - - -( - (method_definition - name:(_)@name)@method_def - (#eq? @name "constructor") -) { - ; augmentation for the constructor - attr (@name.constructor_guard) symbol_definition = "GUARD:CONSTRUCTOR", source_node = @name - edge @method_def.after_scope -> @name.constructor_guard - edge @name.constructor_guard -> @method_def.method_value -} - -( - (method_definition - name:(_)@name)@method_def - (#not-eq? @name "constructor") -) { - ; augmentation for the method - attr (@name.pop) node_definition = @name - attr (@name.pop_dot) pop_symbol = "." - edge @method_def.after_scope -> @name.pop_dot - edge @name.pop_dot -> @name.pop - edge @name.pop -> @method_def.method_value -} - -(method_definition - name:(_)@name - parameters:(_)@call_sig - body:(_)@body)@method_def { - - attr (@name.pop) syntax_type = "method" - - ; scope flows across the decl - edge @method_def.after_scope -> @method_def.before_scope - - ; method values have drop nodes that handle closures, that points to the - ; before scope from method def - attr (@method_def.method_value_drop) type = "drop_scopes" - edge @method_def.method_value_drop -> @method_def.before_scope - - ; the call sig's before scope comes from the drop node then flows into the body - edge @call_sig.before_scope -> @method_def.method_value_drop - edge @body.before_scope -> @call_sig.after_scope - - ; method values have call nodes - attr (@method_def.method_value_call) pop_scoped_symbol = "()" - edge @method_def.method_value -> @method_def.method_value_call - - ; method values have return nodes which need to be visible for returns - attr (@method_def.method_value_return) pop_symbol = "GUARD:RETURN" - edge @method_def.method_value_call -> @method_def.method_value_return - let @body.return_or_yield = @method_def.method_value_return - - ; method values have this nodes which need to be visible for constructor calls - attr (@method_def.method_value_this) push_symbol = "this" - attr (@method_def.method_value_this_guard) pop_symbol = "GUARD:THIS" - edge @method_def.method_value_call -> @method_def.method_value_this_guard - edge @method_def.method_value_this_guard -> @method_def.method_value_this - edge @method_def.method_value_this -> @body.after_scope - - ; method values have a jump node that lets params connect up to actual arguments - edge @method_def.method_value_arg_scope -> JUMP_TO_SCOPE_NODE -} - -(method_definition - parameters: - (formal_parameters (_)@param))@method_def { - - ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = (named-child-index @param) - edge @param.covalue -> @param.arg_index - edge @param.arg_index -> @method_def.method_value_arg_scope -} - - - -(field_definition - property:(property_identifier)@property)@field_def { - - attr (@property.pop) node_definition = @property - attr (@property.pop_dot) pop_symbol = "." - edge @field_def.after_scope -> @property.pop_dot - edge @property.pop_dot -> @property.pop -} - -(field_definition - !value)@field_def { - - edge @field_def.after_scope -> @field_def.before_scope -} - -(field_definition - property:(_)@property - value:(_)@value)@field_def { - - edge @value.before_scope -> @field_def.before_scope - edge @field_def.after_scope -> @value.after_scope - edge @property.pop -> @value.value -} - - - -;; #### Statement Block - -; statement block, first statement -(statement_block - . - (_)@first_stmt)@block { - - ; scope flows from block to first statement - edge @first_stmt.before_scope -> @block.before_scope -} - -; statement block, between statements -(statement_block - (_)@left_stmt - . - (_)@right_stmt) { - ; scope flows from left to right - edge @right_stmt.before_scope -> @left_stmt.after_scope -} - -; statement block, last statement -(statement_block - (_)@last_stmt - .)@block { - ; scope flows from last statement to block - edge @block.after_scope -> @last_stmt.after_scope -} - - - - - -;; #### If - -(if_statement condition:(_)@condition)@if_stmt { - ; scopes flow from the if statement to the condition - edge @condition.before_scope -> @if_stmt.before_scope -} - -(if_statement - condition:(_)@condition - consequence:(_)@consequence)@if_stmt -{ - ; scopes flow from the condition to the consequence, then to the if statement - edge @consequence.before_scope -> @condition.after_scope - edge @if_stmt.after_scope -> @consequence.after_scope -} - -(if_statement - condition:(_)@condition - alternative:(_)@alternative)@if_stmt -{ - ; scopes flow from the condition to the alternative, then to the if statement - edge @alternative.before_scope -> @condition.after_scope - edge @if_stmt.after_scope -> @alternative.after_scope -} - -(else_clause (_)@inner)@else_clause { - ; scopes flow in and right back out - edge @inner.before_scope -> @else_clause.before_scope - edge @else_clause.after_scope -> @inner.after_scope -} - - - - -;; #### Switch - -(switch_statement - value:(_)@value - body:(switch_body)@body)@switch_stmt -{ - ; scopes flow into the value then into the body then back out to the switch - edge @value.before_scope -> @switch_stmt.before_scope - edge @body.before_scope -> @value.after_scope - edge @switch_stmt.after_scope -> @body.after_scope -} - -; LATER-TODO tree sitter doesn't yet support empty switch bodies -; THIS IS A HUGE HACK AND MUST BE FIXED -(switch_body)@switch_body { - edge @switch_body.after_scope -> @switch_body.before_scope -} - -; switch body, first choice -(switch_body - . - (_)@first_choice)@switch_body -{ - ; scopes flow from the body into the first choice - edge @first_choice.before_scope -> @switch_body.before_scope -} - -; switch body, between choices -(switch_body - (_)@left_choice - . - (_)@right_choice) -{ - ; scopes flow left to right - edge @right_choice.before_scope -> @left_choice.after_scope -} - -; switch body, last choice -(switch_body - (_)@last_choice - .)@switch_body -{ - ; scope flows out to the switch body - edge @switch_body.after_scope -> @last_choice.after_scope -} - -; LATER-TODO tree sitter doesnt yet support switch case's with no statements -; THIS IS A HUGE HACK AND MUST BE FIXED -(switch_case)@switch_case { - edge @switch_case.after_scope -> @switch_case.before_scope -} - -; switch case, non-empty statements, first statement -(switch_case - value:(_)@value - . - (_)@first_stmt)@switch_case -{ - ; scopes flow into the value then into the first statement - edge @value.before_scope -> @switch_case.before_scope - edge @first_stmt.before_scope -> @value.after_scope -} - -; switch case, non-empty statements, between statement -(switch_case - value:(_) - (_)@left_stmt - . - (_)@right_stmt) -{ - ; scopes flow left to right - edge @right_stmt.before_scope -> @left_stmt.after_scope -} - -; switch case, non-empty statements, last statement -(switch_case - value:(_) - (_)@last_stmt - .)@switch_case { - - ; scopes flow out from the last statement to the case - edge @switch_case.after_scope -> @last_stmt.after_scope -} - -; LATER-TODO tree sitter doesnt yet support empty defaults -; THIS IS A HUGE HACK AND MUST BE FIXED -(switch_default)@switch_default { - edge @switch_default.after_scope -> @switch_default.before_scope -} - -; switch default, non-empty statements, first statement -(switch_default - . - (_)@first_stmt)@switch_default -{ - ; scopes flow into the first statement - edge @first_stmt.before_scope -> @switch_default.before_scope -} - -; switch default, non-empty statements, between statements -(switch_default - (_)@left_stmt - . - (_)@right_stmt) -{ - - ; scopes flow left to right - edge @right_stmt.before_scope -> @left_stmt.after_scope -} - -; switch default, non-empty statements, last statement -(switch_default - (_)@last_stmt - .)@switch_default -{ - - ; scopes flow out to the default - edge @switch_default.after_scope -> @last_stmt.after_scope -} - - - -;; #### For - -(for_statement - initializer:(_)@initializer - condition:(_)@condition - increment:(_)@increment - body:(_)@body)@for_stmt -{ - - ; scopes flow from statement to initializer then test then body then increment - edge @initializer.before_scope -> @for_stmt.before_scope - edge @condition.before_scope -> @initializer.after_scope - edge @body.before_scope -> @condition.after_scope - edge @increment.before_scope -> @body.after_scope - - ; scopes also from from the body back into the condition - edge @condition.before_scope -> @increment.after_scope - - ; scopes also flow from condition out to statement - edge @for_stmt.after_scope -> @condition.after_scope -} - - - -;; #### For In - -(for_in_statement - left:(_)@_left - right:(_)@right - body:(_)@body)@for_in_stmt -{ - - ; scopes flow from statement to right then to body then back out - edge @right.before_scope -> @for_in_stmt.before_scope - edge @body.before_scope -> @right.after_scope - edge @for_in_stmt.after_scope -> @body.after_scope -} - -(for_in_statement - left:(identifier)@left - right:(_)@right - body:(_)@body)@for_in_stmt -{ - - attr (@for_in_stmt.pop) node_definition = @left - edge @for_in_stmt.pop -> @right.value - edge @body.before_scope -> @for_in_stmt.pop - -} - - - -;; #### While - -(while_statement - condition:(_)@condition - body:(_)@body)@while_stmt -{ - - ; scopes flow from while to condition then to body then back out - edge @condition.before_scope -> @while_stmt.before_scope - edge @body.before_scope -> @condition.after_scope - edge @while_stmt.after_scope -> @body.after_scope - - ; scopes also flow back into the condition - edge @condition.before_scope -> @body.after_scope -} - - - -;; #### Do - -(do_statement - body:(_)@body - condition:(_)@condition)@do_stmt -{ - - ; scopes flow from statement to body then condition then back to statement - edge @body.before_scope -> @do_stmt.before_scope - edge @condition.before_scope -> @body.after_scope - edge @do_stmt.after_scope -> @condition.after_scope - - ; scopes also flow back to the body from the condition - edge @body.before_scope -> @condition.after_scope - -} - - - -;; #### Try - -(try_statement - body:(_)@body)@try_stmt -{ - - ; scopes flow into the body then back out - edge @body.before_scope -> @try_stmt.before_scope - edge @try_stmt.after_scope -> @body.after_scope - -} - -(try_statement - body:(_)@body - handler:(_)@handler)@try_stmt -{ - - ; scopes flow from body to handler then back out - edge @handler.before_scope -> @body.after_scope - edge @try_stmt.after_scope -> @handler.after_scope -} - -(try_statement - body:(_)@body - finalizer:(_)@finalizer)@_try_stmt -{ - - ; scopes flow from body to finalizer then back out - edge @finalizer.before_scope -> @body.after_scope - -} - -(try_statement - handler:(_)@handler - finalizer:(_)@finalizer)@try_stmt -{ - - ; scopes flow from handler to finalizer then back out - edge @finalizer.before_scope -> @handler.after_scope - edge @try_stmt.after_scope -> @finalizer.after_scope -} - -(catch_clause body:(_)@body)@catch_clause { - ; scopes flow in then back out - edge @body.before_scope -> @catch_clause.before_scope - edge @catch_clause.after_scope -> @body.after_scope -} - -(catch_clause - parameter:(identifier)@name - body:(_)@body)@catch_clause -{ - - attr (@catch_clause.pop) node_definition = @name - edge @body.before_scope -> @catch_clause.pop - -} - -(finally_clause body:(_)@body)@finally_clause { - ; scopes flow in thenback out - edge @body.before_scope -> @finally_clause.before_scope - edge @finally_clause.after_scope -> @body.after_scope -} - - - -;; #### With - -(with_statement - object:(_)@object - body:(_)@body)@with_stmt -{ - - ; scopes flow from the statement into the object then into the body then back out - edge @object.before_scope -> @with_stmt.before_scope - edge @body.before_scope -> @object.after_scope - edge @with_stmt.after_scope -> @body.after_scope - - attr (@with_stmt.push_dot) push_symbol = "GUARD:MEMBER" - edge @with_stmt.push_dot -> @object.value - edge @body.before_scope -> @with_stmt.push_dot -} - - - -;; #### Break - -(break_statement)@break_stmt { - ; scopes flow through unchanged - edge @break_stmt.after_scope -> @break_stmt.before_scope -} - -(break_statement (_)@label)@break_stmt { - - attr (@break_stmt.label_guard) push_symbol = "GUARD:LABEL" - attr (@break_stmt.label_push) node_reference = @label - - edge @break_stmt.label_push -> @break_stmt.label_guard - edge @break_stmt.label_guard -> @break_stmt.before_scope -} - - - -;; #### Continue - -(continue_statement)@continue_stmt { - ; scopes flow through unchanged - edge @continue_stmt.after_scope -> @continue_stmt.before_scope -} - -(continue_statement (_)@label)@continue_stmt { - - attr (@continue_stmt.label_guard) push_symbol = "GUARD:LABEL" - attr (@continue_stmt.label_push) node_reference = @label - - edge @continue_stmt.label_push -> @continue_stmt.label_guard - edge @continue_stmt.label_guard -> @continue_stmt.before_scope -} - - - -;; #### Return - -; LATER-TODO tree sitter doesn't let us express empty returns currently -(return_statement)@return_stmt { - ; scopes flow through unchanged - edge @return_stmt.after_scope -> @return_stmt.before_scope -} - -(return_statement - (_)@returned_expr)@return_stmt { - ; scopes flow through the returned expresssion - edge @returned_expr.before_scope -> @return_stmt.before_scope - edge @return_stmt.after_scope -> @returned_expr.after_scope - - ; return statements hook up to the call node of the function value - edge @return_stmt.return_or_yield -> @returned_expr.value -} - - - -;; #### Throw - -(throw_statement (_)@thrown_expr)@throw_stmt { - ; scopes flow through the returned expresssion - edge @thrown_expr.before_scope -> @throw_stmt.before_scope - edge @throw_stmt.after_scope -> @thrown_expr.after_scope -} - - - -;; #### Empty - -(empty_statement)@empty_stmt { - ; scopes flow through unchaged - edge @empty_stmt.after_scope -> @empty_stmt.before_scope -} - - - -;; #### Labeled - -(labeled_statement - label:(_)@label - body:(_)@inner)@labeled_stmt -{ - - attr (@labeled_stmt.label_guard) pop_symbol = "GUARD:LABEL" - attr (@labeled_stmt.label_pop) node_definition = @label - - ; scopes flow through the inner statement then back out - edge @inner.before_scope -> @labeled_stmt.before_scope - edge @inner.before_scope -> @labeled_stmt.label_guard - edge @labeled_stmt.label_guard -> @labeled_stmt.label_pop - edge @labeled_stmt.after_scope -> @inner.after_scope -} - - - -;; ███████ ██ ██ ██████ ██████ ███████ ███████ ███████ ██ ██████ ███ ██ ███████ -;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ -;; █████ ███ ██████ ██████ █████ ███████ ███████ ██ ██ ██ ██ ██ ██ ███████ -;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ -;; ███████ ██ ██ ██ ██ ██ ███████ ███████ ███████ ██ ██████ ██ ████ ███████ - -;; ## Expressions - -;; ### Attributes Defined on Expressions -;; TODO - -;; ### Expression Queries - - -;; #### Parenthesized - -(parenthesized_expression (_)@inner)@parens { - ; scopes flow right through - edge @inner.before_scope -> @parens.before_scope - edge @parens.after_scope -> @inner.after_scope - - ; as do values - edge @parens.value -> @inner.value -} - - -;; #### Strings - -(string)@string { - ; scopes don't change - edge @string.after_scope -> @string.before_scope - - ; the value of a string is the string primitive - edge @string.value -> @string.builtins_string -} - - -;; #### Template Strings - -; template_strings w/ no substitutions -; LATER-TODO tree sitter queries don't let us find the absence of substitutions -; THIS IS A HUGE HACK AND MUST BE FIXED -(template_string)@template_string { - edge @template_string.after_scope -> @template_string.before_scope -} - -; nonempty template string, value -; LATER-TODO this isn't really right, but it gets flows through the template string -; which may be useful -(template_string (template_substitution (_)@inner_expr))@template_string { - ; the value of a template string is a template string value built from the values of its substitutions - ; attr (@template_string.value) "template_string_value" - edge @template_string.value -> @inner_expr.value -} - -; nonempty template string, first substitution -(template_string . (template_substitution (_)@first_inner_expr))@template_string { - ; scopes propagate into the first subtitution of the template string - edge @first_inner_expr.before_scope -> @template_string.before_scope -} - -; nonempty template string, between substitutions -(template_string - (template_substitution (_)@left_inner_expr) - . - (template_substitution (_)@right_inner_expr))@_template_string { - ; scopes propagate from left substitutions to right substitutions - edge @right_inner_expr.before_scope -> @left_inner_expr.after_scope -} - -; nonempty template string, last substitution -(template_string . (template_substitution (_)@last_inner_expr))@template_string { - ; scopes propagate out of the last substitution to the template string - edge @template_string.after_scope -> @last_inner_expr.after_scope -} - - - -;; #### Numbers - -(number)@number { - ; scopes don't change - edge @number.after_scope -> @number.before_scope - - ; the value of a number is the number primitive - edge @number.value -> @number.builtins_number -} - - -;; #### Variables - -(primary_expression/identifier)@variable { - ; scopes don't change - edge @variable.after_scope -> @variable.before_scope - - ; value is a lookup, ie a push - attr (@variable.value) node_reference = @variable - edge @variable.value -> @variable.before_scope -} - - -;; #### Booleans - -(true)@true { - ; scopes don't change - edge @true.after_scope -> @true.before_scope - - ; the value of true is a boolean primitive - edge @true.value -> @true.builtins_boolean -} - -(false)@false { - ; scopes don't change - edge @false.after_scope -> @false.before_scope - - ; the value of false is a boolean primitive - edge @false.value -> @false.builtins_boolean -} - - -;; #### This - -(this)@this { - ; scopes don't change - edge @this.after_scope -> @this.before_scope - - ; this is a lookup, ie a push - attr (@this.value) symbol_reference = "this", source_node = @this - edge @this.value -> @this.before_scope -} - - -;; #### Super - -(super)@super { - ; scopes don't change - edge @super.after_scope -> @super.before_scope -} - - -;; #### Null - -(null)@null { - ; scopes don't change - edge @null.after_scope -> @null.before_scope - - ; the value of null is the null primitive - edge @null.value -> @null.builtins_null -} - - -;; #### Undefined - -(undefined)@undefined { - ; scopes don't change - edge @undefined.after_scope -> @undefined.before_scope - - ; the value of undefined is the undefined primitive - edge @undefined.value -> @undefined.builtins_undefined -} - - -;; #### Regular Expressions - -(regex)@regex { - ; scopes don't change - edge @regex.after_scope -> @regex.before_scope - - ; the value of a regex is the Regex prototype - edge @regex.value -> @regex.builtins_Regex_prototype -} - - -;; #### Spread Elements - -(spread_element (_)@expr)@spread_elem { - ; scopes flow in then right back out - edge @expr.before_scope -> @spread_elem.before_scope - edge @spread_elem.after_scope -> @expr.after_scope -} - - -;; #### Objects - -(object)@object { - - attr (@object.member_pop) pop_symbol = "GUARD:MEMBER" - edge @object.value -> @object.member_pop - -} - -; empty objects -; LATER-TODO currently unsupported by tree sitter queries -; THIS IS A HUGE HACK AND MUST BE FIXED -(object)@object_expr { - edge @object_expr.after_scope -> @object_expr.before_scope -} - -; non-empty objects, scopes, first entry -(object - . - (_)@first_entry)@object_expr { - ; scopes propagate from the object to the first entry - edge @first_entry.before_scope -> @object_expr.before_scope -} - -; non-empty objects, scopes, between entries -(object - (_)@left_entry - . - (_)@right_entry -)@_object_expr { - ; scopes propagate from left entries to right entries - edge @right_entry.before_scope -> @left_entry.after_scope -} - -; non-empty objects, scopes, last entry -(object - (_)@last_entry - .)@object_expr { - ; scopes propagate from the last entry back to the object - edge @object_expr.after_scope -> @last_entry.after_scope -} - -; shorthand property identifier -(object (shorthand_property_identifier)@keyval)@object { - - node rhsvar_before_scope - node rhsvar_after_scope - node rhsvar_value - node key_pop - - attr (rhsvar_value) node_reference = @keyval - attr (key_pop) node_definition = @keyval - - ; scopes flow into rhsvar, and also straight across b/c they can't be modified - edge rhsvar_before_scope -> @keyval.before_scope - edge rhsvar_after_scope -> rhsvar_before_scope - edge @keyval.after_scope -> rhsvar_after_scope - - edge rhsvar_value -> rhsvar_before_scope - - ; shorthand property identifiers augment the object value with a member binding - edge key_pop -> rhsvar_value - edge @object.member_pop -> key_pop -} - -; pairs - -(computed_property_name (_)@expr)@computed_property_name { - - edge @expr.before_scope -> @computed_property_name.before_scope - edge @computed_property_name.after_scope -> @expr.after_scope - -} - -(object - (pair - key:(_)@_key - value: (_)@value)@pair)@object { - - ; pairs augment the object value with a member binding - - ; This is done differently depending on what the key is. See next rules. - ; attr @key.pop "pop" = @key, "definition" - - edge @pair.key_pop -> @value.value - edge @object.member_pop -> @pair.key_pop - -} - -(pair - key:(property_identifier)@key - value:(_)@value)@pair -{ - - attr (@pair.key_pop) node_definition = @key - - ; scopes flow into the value, then back to the pair - edge @value.before_scope -> @pair.before_scope - edge @pair.after_scope -> @value.after_scope - -} - -(pair key:(string)@key) { - attr (@key.pop) pop_symbol = (replace (source-text @key) "\"" "") -} - -(pair - key:(number)@key - value:(_)@value)@pair -{ - - attr (@pair.key_pop) node_definition = @key - - ; scopes flow into the value, then back to the pair - edge @value.before_scope -> @pair.before_scope - edge @pair.after_scope -> @value.after_scope - -} - -(pair - key:(computed_property_name)@key - value:(_)@value)@pair -{ - - ; scopes flow into the key, then out to the value, then back to the pair - edge @key.before_scope -> @pair.before_scope - edge @value.before_scope -> @key.after_scope - edge @pair.after_scope -> @value.after_scope - -} - - - -;; #### Arrays - -(array)@array_expr { - - attr (@array_expr.element_pop_dot) pop_symbol = "GUARD:MEMBER" - edge @array_expr.value -> @array_expr.element_pop_dot - -} - -; empty arrays -; LATER-TODO currently unsupported by tree sitter queries -; THIS IS A HUGE HACK AND MUST BE FIXED -(array)@array_expr { - edge @array_expr.after_scope -> @array_expr.before_scope -} - -; nonempty arrays, first element -(array - . - (_)@first_element)@array_expr { - ; scopes propagate into the first element of the array - edge @first_element.before_scope -> @array_expr.before_scope -} - -; nonempty arrays, between elements -(array - (_)@left_element - . - (_)@right_element) { - ; scopes propagate from left elements to right elements - edge @right_element.before_scope -> @left_element.after_scope -} - -; nonempty arrays, last element -(array - (_)@last_element - .)@array_expr { - ; scopes propagate out of the last element to the array - edge @array_expr.after_scope -> @last_element.after_scope -} - -; elements at indices -(array (_)@element)@array_expr { - - node element_index_pop - - attr (element_index_pop) symbol_definition = (named-child-index @element) - edge @array_expr.element_pop_dot -> element_index_pop - edge element_index_pop -> @element.value - -} - - - -;; #### Formal Parameters - -; LATER-TODO scope propagation through empty formal parameters -; currently unsupported by tree sitter queries -; THIS IS A HUGE HACK AND MUST BE FIXED - -(formal_parameters)@formal_params { - edge @formal_params.after_scope -> @formal_params.before_scope -} - -; first parameter -(formal_parameters - . - (_)@first_param)@formal_params { - - edge @first_param.before_scope -> @formal_params.before_scope -} - -; between parameters -(formal_parameters - (_)@left_param - . - (_)@right_param) { - - ; scope flows left to right - edge @right_param.before_scope -> @left_param.after_scope -} - -; last parameter -(formal_parameters - (_)@last_param - .)@formal_params { - - ; scope flows from the param to the call sig - edge @formal_params.after_scope -> @last_param.after_scope -} - - - -;; #### Function Literals - -; functions with names -(function - name:(_)@name - parameters:(_)@call_sig)@fun { - - attr (@name.pop) syntax_type = "function" - - ; if the function has a name, this is bound the callsig's before scope - attr (@name.pop) node_definition = @name - edge @call_sig.before_scope -> @name.pop - edge @name.pop -> @fun.value -} - - -; function -(function - parameters:(_)@call_sig - body:(_)@body)@fun { - - ; scope flows across the decl - edge @fun.after_scope -> @fun.before_scope - - ; function values have drop nodes that handle closures, that points to the - ; before scope from the function - attr (@fun.value_drop) type = "drop_scopes" - edge @fun.value_drop -> @fun.before_scope - - ; the call sig's before scope comes from the drop node, - ; then flows into the body, and includes a variable binding for "this" - edge @call_sig.before_scope -> @fun.value_drop - attr (@call_sig.this_pop) symbol_definition = "this", source_node = @call_sig - attr (@call_sig.this_push) push_symbol = "this" - edge @call_sig.this_pop -> @call_sig.this_push - edge @call_sig.this_push -> @fun.value_arg_scope - edge @call_sig.before_scope -> @call_sig.this_pop - attr (@call_sig.arguments_pop) symbol_definition = "arguments", source_node = @call_sig - attr (@call_sig.arguments_push) push_symbol = "arguments" - edge @call_sig.arguments_pop -> @call_sig.arguments_push - edge @call_sig.arguments_push -> @fun.value_arg_scope - edge @call_sig.before_scope -> @call_sig.arguments_pop - edge @body.before_scope -> @call_sig.after_scope - - ; function values have call nodes - attr (@fun.value_call) pop_scoped_symbol = "()" - edge @fun.value -> @fun.value_call - - ; function values have return nodes which need to be visible for returns - attr (@fun.value_return) pop_symbol = "GUARD:RETURN" - edge @fun.value_call -> @fun.value_return - let @body.return_or_yield = @fun.value_return - - ; function values have this nodes which need to be visible for method calls - attr (@fun.value_this) push_symbol = "this" - attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" - edge @fun.value_call -> @fun.value_this_guard - edge @fun.value_this_guard -> @fun.value_this - edge @fun.value_this -> @body.after_scope - - ; function values have a jump node that lets params connect up to actual arguments - edge @fun.value_arg_scope -> JUMP_TO_SCOPE_NODE -} - -(function - parameters: - (formal_parameters (_)@param))@fun { - - ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = (named-child-index @param) - edge @param.covalue -> @param.arg_index - edge @param.arg_index -> @fun.value_arg_scope -} - - - -;; #### Arrow Function Literals - -; function -[ - (arrow_function - parameters:(_)@call_sig - body:(_)@body)@fun - - (arrow_function - parameter:(_)@call_sig - body:(_)@body)@fun -] { - - ; scope flows across the decl - edge @fun.after_scope -> @fun.before_scope - - ; function values have drop nodes that handle closures, that points to the - ; before scope from the function - attr (@fun.value_drop) type = "drop_scopes" - edge @fun.value_drop -> @fun.before_scope - - ; the call sig's before scope comes from the drop node then flows into the body - edge @call_sig.before_scope -> @fun.value_drop - edge @body.before_scope -> @call_sig.after_scope - - ; function values have call nodes - attr (@fun.value_call) pop_scoped_symbol = "()" - edge @fun.value -> @fun.value_call - - ; function values have return nodes which need to be visible for returns - attr (@fun.value_return) pop_symbol = "GUARD:RETURN" - edge @fun.value_call -> @fun.value_return - let @body.return_or_yield = @fun.value_return - - ; function values have this nodes which need to be visible for method calls - attr (@fun.value_this) push_symbol = "this" - attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" - edge @fun.value_call -> @fun.value_this_guard - edge @fun.value_this_guard -> @fun.value_this - edge @fun.value_this -> @body.after_scope - - ; function values have a jump node that lets params connect up to actual arguments - edge @fun.value_arg_scope -> JUMP_TO_SCOPE_NODE -} - -; arrow functions returning exprs need special rules for getting the return value hooked up -(arrow_function - body:(expression)@return_expr) { - edge @return_expr.return_or_yield -> @return_expr.value -} - -(arrow_function - parameter:(_)@param)@fun { - - ; scope flows from the param right back out - edge @param.after_scope -> @param.before_scope - - ; but augmented with a pop, b/c it's not a pattern - attr (@param.pop) node_definition = @param - edge @param.pop -> @param.covalue - edge @param.after_scope -> @param.pop - - ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = "0" - edge @param.covalue -> @param.arg_index - edge @param.arg_index -> @fun.value_arg_scope -} - -(arrow_function - parameters: - (formal_parameters (_)@param))@fun { - - ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = (named-child-index @param) - edge @param.covalue -> @param.arg_index - edge @param.arg_index -> @fun.value_arg_scope -} - - - -;; #### Generator Function Literals - -; generator functions with names -(generator_function - name:(_)@name - parameters:(_)@call_sig)@fun { - - attr (@name.pop) syntax_type = "function" - - ; if the function has a name, this is bound the callsig's before scope - attr (@name.pop) node_definition = @name - edge @call_sig.before_scope -> @name.pop - edge @name.pop -> @fun.value -} - - -; generator function -(generator_function - parameters:(_)@call_sig - body:(_)@body)@fun { - - ; scope flows across the decl - edge @fun.after_scope -> @fun.before_scope - - ; function values have drop nodes that handle closures, that points to the - ; before scope from the function - attr (@fun.value_drop) type = "drop_scopes" - edge @fun.value_drop -> @fun.before_scope - - ; the call sig's before scope comes from the drop node then flows into the body - edge @call_sig.before_scope -> @fun.value_drop - edge @body.before_scope -> @call_sig.after_scope - - ; function values have call nodes - attr (@fun.value_call) pop_scoped_symbol = "()" - edge @fun.value -> @fun.value_call - - ; function values have return nodes which need to be visible for returns - attr (@fun.value_return) pop_symbol = "GUARD:RETURN" - edge @fun.value_call -> @fun.value_return - let @body.return_or_yield = @fun.value_return - - ; function values have this nodes which need to be visible for method calls - attr (@fun.value_this) push_symbol = "this" - attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" - edge @fun.value_call -> @fun.value_this_guard - edge @fun.value_this_guard -> @fun.value_this - edge @fun.value_this -> @body.after_scope - - ; function values have a jump node that lets params connect up to actual arguments - edge @fun.value_arg_scope -> JUMP_TO_SCOPE_NODE -} - -(generator_function - parameters: - (formal_parameters (_)@param))@fun { - - ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = (named-child-index @param) - edge @param.covalue -> @param.arg_index - edge @param.arg_index -> @fun.value_arg_scope -} - - -;; #### Function Calls - -; calls, functions -(call_expression - function:(_)@function - arguments:(_)@arguments)@call_expr { - - ; scopes flow from call expressions into the function - edge @function.before_scope -> @call_expr.before_scope - edge @arguments.before_scope -> @function.after_scope - edge @call_expr.after_scope -> @arguments.after_scope -} - -; calls, values -(call_expression - function:(_)@function - arguments:(_)@arguments)@call_expr { - - ; value is a call, ie a push "()" node w/ "push-scope" @arguments - attr (@call_expr.return_guard) push_symbol = "GUARD:RETURN" - attr (@call_expr.call) push_scoped_symbol = "()", scope = @arguments.arg_scope - edge @call_expr.value -> @call_expr.return_guard - edge @call_expr.return_guard -> @call_expr.call - edge @call_expr.call -> @function.value - - attr (@arguments.arg_this) symbol_definition = "this", source_node = @arguments - edge @arguments.arg_scope -> @arguments.arg_this - - edge @arguments.arg_scope -> @arguments.arg_scope_no_this - - attr (@arguments.arg_arguments) symbol_definition = "arguments", source_node = @arguments - attr (@arguments.arg_arguments_dot) pop_symbol = "." - edge @arguments.arg_scope -> @arguments.arg_arguments - edge @arguments.arg_arguments -> @arguments.arg_arguments_dot - edge @arguments.arg_arguments_dot -> @arguments.arg_scope_no_this - edge @arguments.arg_arguments -> @call_expr.builtins_arguments_prototype -} - -; special case to make `this` bind correctly in calls of the forms `x.f(...)` -; and `x[f](...)` -(call_expression - function:[ - (member_expression object:(_)@object) - (subscript_expression object:(_)@object) - ] - arguments:(_)@arguments) { - - edge @arguments.arg_this -> @object.value -} - - -; TODO this should eventually be removed and replaced with a version that only -; applies to the negation of (member_expression), but that's not supported by -; tree-sitter currently -(call_expression - function: (_)@_function - arguments:(_)@arguments)@call_expr { - - edge @arguments.arg_this -> @call_expr.builtins_null -} -(call_expression - arguments:(arguments (_)@arg)@arguments) { - - attr (@arg.arg_index) pop_symbol = (named-child-index @arg) - edge @arguments.arg_scope_no_this -> @arg.arg_index - edge @arg.arg_index -> @arg.value -} - - - -;; #### Arguments - -; LATER-TODO currently unsupported by tree sitter queries -; THIS IS A HUGE HACK AND MUST BE FIXED -(arguments)@arguments { - edge @arguments.after_scope -> @arguments.before_scope -} - -(arguments - . - (_)@first_arg)@arguments { - - edge @first_arg.before_scope -> @arguments.before_scope -} - -(arguments - (_)@left_arg - . - (_)@right_arg) { - - edge @right_arg.before_scope -> @left_arg.after_scope -} - -(arguments - (_)@last_arg - .)@arguments { - - edge @arguments.after_scope -> @last_arg.after_scope -} - - - -;; #### Property Access - -;; ##### Member Expressions - -(member_expression - object: (_)@object - property: (_)@property)@member_expr -{ - - node member_push - node property_push - - ; scopes flow into object then back out - edge @object.before_scope -> @member_expr.before_scope - edge @member_expr.after_scope -> @object.after_scope - - ; value is a member projection on the value of the object ie. a push then push dot - attr (member_push) push_symbol = "GUARD:MEMBER" - attr (property_push) node_reference = @property - edge property_push -> member_push - edge @member_expr.value -> property_push - edge member_push -> @object.value - -} - -;; ##### Subscript Expressions - -(subscript_expression - object: (_)@object - index: (_)@index)@subscript_expr { - - ; scopes flow left to right - edge @object.before_scope -> @subscript_expr.before_scope - edge @index.before_scope -> @object.after_scope - edge @subscript_expr.after_scope -> @index.after_scope - - ; value is a subscript lookup, ie a push then push dot - attr (@subscript_expr.push_dot) push_symbol = "GUARD:MEMBER" - edge @subscript_expr.push_dot -> @object.value - - ; this is done differently depending on what the index is - ; attr @index.push "push" = @index, "reference" - edge @subscript_expr.value -> @subscript_expr.index_push - edge @subscript_expr.index_push -> @subscript_expr.push_dot - -} - -(subscript_expression - object: (_)@_object - index: (string)@index)@subscript_expr -{ - - attr (@subscript_expr.index_push) push_symbol = (replace (source-text @index) "[\"\']" "") -} - -(subscript_expression - object: (_)@_object - index: (number)@index)@subscript_expr -{ - - attr (@subscript_expr.index_push) node_reference = @index - -} - - - -;; #### Constructor Calls - -(new_expression - constructor:(_)@constructor - arguments:(_)@arguments)@new_expr { - - edge @constructor.before_scope -> @new_expr.before_scope - edge @arguments.before_scope -> @constructor.after_scope - edge @new_expr.after_scope -> @arguments.after_scope - - attr (@new_expr.call) push_scoped_symbol = "()", scope = @arguments.arg_scope - - ; we guard for constructors for the case where we have a "true" class - attr (@constructor.constructor) push_symbol = "GUARD:CONSTRUCTOR" - edge @new_expr.call -> @constructor.constructor - edge @constructor.constructor -> @constructor.value - - ; and also just go right to the value incase we have a function-as-constructor - edge @new_expr.call -> @constructor.value - - - - ; value coming from the constructor call - attr (@new_expr.guard_this) push_symbol = "GUARD:THIS" - edge @new_expr.value -> @new_expr.guard_this - edge @new_expr.guard_this -> @new_expr.call - - ; value coming from the field decls in the class - edge @new_expr.value -> @constructor.value - - attr (@arguments.arg_this) symbol_definition = "this", source_node = @arguments - edge @arguments.arg_scope -> @arguments.arg_this - edge @arguments.arg_this -> @new_expr.builtins_empty_object -} - -(new_expression - arguments:(arguments (_)@arg)@arguments) { - - attr (@arg.arg_index) pop_symbol = (named-child-index @arg) - edge @arguments.arg_scope -> @arg.arg_index - edge @arg.arg_index -> @arg.value -} - - - -;; #### Await - -(await_expression (_)@awaited)@await_expr { - ; scopes flow into the inner expression then back out - edge @awaited.before_scope -> @await_expr.before_scope - edge @await_expr.after_scope -> @awaited.after_scope - - ; value is just propagated up - edge @await_expr.value -> @awaited.value -} - - - -;; #### Update Expressions - -(update_expression argument: (_)@argument)@update_expr { - ; scope propagates through the operand then is updated by the expr - edge @argument.before_scope -> @update_expr.before_scope - edge @update_expr.after_scope -> @argument.after_scope - ; LATER-TODO this isn't quite right because the update argument can't be an arbitrary expr - ; eg f(x)++ doesn't make any sense, you have to have something more like - ; (update_expression argument: (lvar)@argument) - attr (@update_expr.pop) node_definition = @argument - edge @update_expr.value -> @argument.value - edge @update_expr.after_scope -> @update_expr.pop - edge @update_expr.pop -> @argument.value -} - - -;; #### Binary Expressions - -(binary_expression left: (_)@left right: (_)@right)@binary_expr { - ; scopes propagate left to right through the operands unchanged by the binop itself - edge @left.before_scope -> @binary_expr.before_scope - edge @right.before_scope -> @left.after_scope - edge @binary_expr.after_scope -> @right.after_scope - - ; value is a binary op value built from the operands - ; LATER-TODO this isn't quite correct but it permits flow through the expression - ; which can be useful - ; attr (@binary_expr.value) "binary_operation_value" - edge @binary_expr.value -> @left.value - edge @binary_expr.value -> @right.value -} - - -;; #### Unary Expressions - -(unary_expression argument: (_)@argument)@unary_expr { - ; scope propagates through the operand - edge @argument.before_scope -> @unary_expr.before_scope - edge @unary_expr.after_scope -> @argument.after_scope - - ; value is a unaryop value built from the operand - ; LATER-TODO this isn't quite correct but it permits flow through the expression - ; which can be useful - ; attr (@unary_expr.value) "unary_operation_value" - edge @unary_expr.value -> @argument.value -} - - - -;; #### Assignment Expressions; - -; scopes on RHS, values -(assignment_expression - left: (_)@left - right: (_)@right)@assignment_expr { - - ; scopes flow into the RHS then back out to the whole expr, - ; augmented (in subsequent rules) by the LHS - edge @right.before_scope -> @assignment_expr.before_scope - edge @left.before_scope -> @right.after_scope - edge @assignment_expr.after_scope -> @left.after_scope - - ; value of the whole thing is value of the RHS - edge @assignment_expr.value -> @right.value -} - -; augmentation of scope via identifiers -(assignment_expression - left: (identifier)@left - right: (_)@right)@assignment_expr { - - ; augments the scope by adding a lookup edge, ie. a pop - attr (@assignment_expr.pop) node_definition = @left - edge @assignment_expr.after_scope -> @assignment_expr.pop - edge @assignment_expr.pop -> @right.value - - ; ensure the scope flows through the identifier - edge @left.after_scope -> @left.before_scope -} - -; assignment to direct fields on `this` -(assignment_expression - left: (member_expression - object:(this)@this - property:(_)@property) - right: (_)@right)@assignment_expr { - - ; HACK - attr (@this.drop) type = "drop_scopes" - edge @this.drop -> @this.pop - attr (@this.pop) pop_symbol = "this" - attr (@this.pop_dot) pop_symbol = "." - attr (@property.pop) node_definition = @property - edge @assignment_expr.after_scope -> @this.drop - edge @assignment_expr.after_scope -> @this.pop - edge @this.pop -> @this.pop_dot - edge @this.pop_dot -> @property.pop - edge @property.pop -> @right.value -} - -; augmentation of scope via _destructuring_patterns -(assignment_expression - left: [(object_pattern) (array_pattern)]@left - right: (_)@right)@assignment_expr { - - ; scope flows from LHS into pattern then back to assignment - edge @left.before_scope -> @right.after_scope - edge @assignment_expr.after_scope -> @left.after_scope -} - - - -;; #### Augmented Assignment Expressions - -(augmented_assignment_expression - left: (_)@_left - right: (_)@right)@augmented_assignment_expr { - - ; scopes flow into the RHS then back out to the whole expr, augmented by the LHS - edge @right.before_scope -> @augmented_assignment_expr.before_scope - edge @augmented_assignment_expr.after_scope -> @right.after_scope -} - -(augmented_assignment_expression - left:(identifier)@left - right:(_)@right)@augmented_assignment_expr { - - ; augment the scope - attr (@augmented_assignment_expr.pop) node_definition = @left - attr (@augmented_assignment_expr.push) node_reference = @left - edge @augmented_assignment_expr.push -> @augmented_assignment_expr.before_scope - edge @augmented_assignment_expr.pop -> @augmented_assignment_expr.push - edge @augmented_assignment_expr.pop -> @right.value - edge @augmented_assignment_expr.after_scope -> @augmented_assignment_expr.pop - -} - - -;; #### Comma Operator / Sequence Expressions - -(sequence_expression - left: (_)@left - right: (_)@right)@sequence_expr { - - ; scopes propagate left to right - edge @left.before_scope -> @sequence_expr.before_scope - edge @right.before_scope -> @left.after_scope - edge @sequence_expr.after_scope -> @right.after_scope - - ; the value is just the value of the right - edge @sequence_expr.value -> @right.value -} - - -;; #### Ternary Expression - -(ternary_expression - condition: (_)@condition - consequence: (_)@consequence - alternative: (_)@alternative)@ternary_expr { - - ; scopes propagate into condition, then into each branch - edge @condition.before_scope -> @ternary_expr.before_scope - edge @consequence.before_scope -> @condition.after_scope - edge @alternative.before_scope -> @condition.after_scope - edge @ternary_expr.after_scope -> @consequence.after_scope - edge @ternary_expr.after_scope -> @alternative.after_scope - - ; value of the whole thing is a conditional value from the operands - edge @ternary_expr.value -> @consequence.value - edge @ternary_expr.value -> @alternative.value -} - - - -;; #### Yield - -(yield_expression (_)@yielded_expr)@yield_expr { - ; scopes flow in to the yielded expression then back out - edge @yielded_expr.before_scope -> @yield_expr.before_scope - edge @yield_expr.after_scope -> @yielded_expr.after_scope - - ; yield expressions hook up to the call node of the function value - edge @yield_expr.return_or_yield -> @yielded_expr.value -} - - - -;; #### Class Expressions - -(class - body:(_)@body)@class { - - edge @body.before_scope -> @class.before_scope - edge @class.value -> @body.after_scope - edge @class.after_scope -> @class.before_scope -} - -(class - name:(_)@name - body:(_)@body)@class { - - attr (@name.pop) syntax_type = "class" - - attr (@name.pop) node_definition = @name - edge @body.before_scope -> @name.pop - edge @name.pop -> @class.value -} - -(class - (class_heritage (_)@name))@class { - - edge @name.before_scope -> @class.before_scope - edge @class.value -> @name.value -} - - - -;; ██████ █████ ████████ ████████ ███████ ██████ ███ ██ ███████ -;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ -;; ██████ ███████ ██ ██ █████ ██████ ██ ██ ██ ███████ -;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ -;; ██ ██ ██ ██ ██ ███████ ██ ██ ██ ████ ███████ - -;; ## Patterns - -;; Patterns introduce at least two interesting problems to the task of name -;; resolution. On the one hand, patterns by themselves are rich in structure -;; and binding possibilities. On the other, they function to pull apart -;; structure in ways that we would like to make use of in resolving names. Let's -;; look at these in order. - -;; ### Binding Possibilities - -;; If names could only be bound directly either on the LHS of an assignment, or -;; as the formal parameters to a function, or in related places like as -;; arguments to increment or decrement operators, then there would be little -;; trouble saying where a name is bound. But consider a destructuring assignment -;; such as this: - -;; ``````javascript -;; let [x,y,z] = arr; -;; `````` - -;; This assignment has variable names on the LHS of an assignment, sure, but not -;; directly as the LHS. Rather they're buried down inside a pattern. Here they -;; aren't very deep, just one node below the root of the LHS, but they can be -;; arbitrarily far down: - -;; ``````javascript -;; let [x, [y, [z, w], q], r] = arr; -;; `````` - -;; On top of this, patterns in JavaScript permit default assignments, such as - -;; ``````javascript -;; let [x, y = 1] = arr; -;; `````` - -;; These default values can be the result of a computation itself containing -;; variables, such as - -;; ``````javascript -;; let [x, y = 2*z] = arr; -;; `````` - -;; Additionally, those variables referenced in the default value are evaluated -;; *after* the RHS of the assignment. In the following code, `z` is incremented -;; and becomes `2`, and then `x` is assigned to that value. The array on the RHS -;; is only one element long, so the `y` variable gets assigned the default value -;; of `2*z`, which is computed *after* the increment, and so is `2*2` or `4`. - -;; ``````javascript -;; let z = 1; -;; let [x, y = 2*z] = [z++]; -;; `````` - -;; To complicated matters further, the default value can reference the *bound -;; variables to its left*. For instance: - -;; ``````javascript -;; let [x, y = x+1] = arr; -;; `````` - -;; All of this leads to some very interesting and tricky problems for name -;; resolution. The flow of the environment is as follows: First, the environment -;; flows into the RHS of the assignment and is updated by whatever evaluations -;; happen there, then it flows out of the RHS and into the LHS, where it goes -;; through each pattern in the LHS parse tree, in a left-to-right, depth-first -;; traversal. Patterns with no default assignments do nothing to the environment -;; but patterns with a default will pass the environment to the default value, -;; where it may be updated by the evaluation, and then passed further along. -;; Each variable, whether bare or on the left of an assignment, also has to -;; extend the environment because those variables come into scope further along. - -;; ### Structure Decomposition - -;; Let's now look at how patterns decompose structure. Let's consider the effect -;; of an assignment such as this: - -;; ``````javascript -;; let [x,y] = [1,2]; -;; `````` - -;; This assignment binds `x` to `1` and `y` to `2`. It's equivalent to doing - -;; ``````javascript -;; let x = 1, y = 2; -;; `````` - -;; Except, unlike the latter, the array destructuring does not have any obvious -;; pairing up of the names with the expressions that give them their values. -;; Now, perhaps there's some clever hack we can perform for this special case -;; where the RHS is a structure like `[1,2]` where it's manifestly clear out to -;; pair things up, but of course the RHS can come from anywhere. It can come -;; from a local variable assignment: - -;; ``````javascript -;; let arr = [1,2]; -;; let [x,y] = arr; -;; `````` - -;; Or a function call: - -;; ``````javascript -;; function foo(arr) { -;; let [x,y] = arr; -;; ... -;; } -;; foo([1,2]); -;; `````` - -;; Or any other number of places. We would like *all* of these to permit at -;; least *some* amount of name resolution so that we can find that `x` is `1` -;; and `y` is `2`. This should extend also to objects, not just arrays. - -;; The approach we take is to recognize a general pattern of equivalence, which -;; the above double-let assignment is related special case. For arrays, all -;; destructuring assignments of the form - -;; ``````javascript -;; let [..., pat_i, ...] = arr; -;; `````` - -;; are equivalent to - -;; ``````javascript -;; let pat_i = arr[i]; -;; `````` - -;; For any pattern `pat` and expression `arr`. So for instance the simple case -;; of a pattern expression and an array literal - -;; ``````javascript -;; let [x,y] = [1,2]; -;; `````` - -;; is equivalent to a pair of lets - -;; ``````javascript -;; let x = [1,2][0]; -;; let y = [1,2][1]; -;; `````` - -;; Modulo any change in side effects from duplicating the array syntactically, -;; these two are equivalent and this would be a valid code transformation. Or if -;; the pattern were an embedded array destructuring like so: - -;; ``````javascript -;; let [x, [y,z]] = [1, [2,3]]; -;; `````` - -;; then this would be equivalent to - -;; ``````javascript -;; let x = [1, [2,3]][0]; -;; let [y,z] = [1, [2,3]][1]; -;; `````` - -;; And of course the second let here would similarly unfold to be equivalent to -;; a pair of assignments, giving us - -;; ``````javascript -;; let x = [1, [2,3]][0]; -;; let y = [1, [2,3]][1][0]; -;; let z = [1, [2,3]][1][1]; -;; `````` - -;; Similarly for objects, we have the following destructuring equivalence that -;; says an assignment like this: - -;; ``````javascript -;; let {..., k: pat, ...} = obj; -;; `````` - -;; is equivalent to - -;; ``````javascript -;; let pat = obj[k]; -;; `````` - -;; for all patterns `pat` and expressions `obj`. - -;; This lets us then conclude that whatever the graphs are that we generate for -;; patterns ought to be equivalent to the graphs we would general for using -;; array indexing and object indexing. Since array and object indexing are fully -;; capable of participating in name resolution, if we can achieve this -;; equivalence, patterns can also fully participate as well, and we'll be able -;; to say that the assignment `let [x,y] = [1,2]` yields the name `x` resolving -;; to `1` and `y` to `2`, as well as many many more complicated cases. - -;; As mentioned in the intro to this doc, assignments point to values. The -;; simplest way to do this, in the absence of patterns, is just to have an edge -;; from the after scope of the assignment to a pop node for the variable, -;; and then to the value node of the RHS, so for `let x = 1;` it'd be like so: - -;; `````` -;; after_scope ---> POP "x" ---> value_node_for_1 -;; `````` - -;; But the above discussion of destructuring complicates this. What we do to -;; address this is introduce the notion of a "covalue". Just as we can say that -;; an expression *has* a value, or produces a value, etc., we'll say that a -;; pattern *consumes* a value. Expressions have values going "out", while -;; patterns have values coming "in". And so like expressions have an associated -;; `value` node in the graph, patterns have an associated `covalue` node. The -;; covalue corresponds to an incoming value. - -;; We build covalues similar to how we build values. Consider the value for an -;; array such as `["foo", "bar"]`, which will be a scope node with pop nodes -;; going out to the values of the strings, like so: - -;; `````` -;; ,---> POP 0 ---> value_node_of_foo -;; value_node_of_the_array ---| -;; `---> POP 1 ---> value_node_of_bar -;; `````` - -;; Similarly, a covalue for an array pattern will also have nodes for the -;; sub-patterns and nodes for the first and second indexes. But rather than pop -;; nodes, which show you where the 0th and 1st elements are, they'll be push -;; nodes to establish the lookup of those elements. The edges will therefore -;; go the other way around. So for a pattern like `[x,y]`, we have the graph - -;; `````` -;; ,--- PUSH 0 <--- covalue_node_of_x -;; covalue_node_of_the_pattern <---| -;; `--- PUSH 1 <--- covalue_node_of_y -;; `````` - -;; For readers familiar with category theory's notion of duality, this explains -;; why these are called "covalues". The general schema here is that where values -;; have pops, covalues have pushes, and all the arrows get flipped. - -;; ### Attributes Defined on Patterns -;; TODO - -;; ### Pattern Queries - -;; #### Variable Patterns - -; scope propagation through identifier patterns -(pattern/identifier)@ident_pat { - - ; scope flows through, binding via a pop edge that goes to an unknown value - attr (@ident_pat.pop) node_definition = @ident_pat - edge @ident_pat.pop -> @ident_pat.covalue - edge @ident_pat.after_scope -> @ident_pat.before_scope - edge @ident_pat.after_scope -> @ident_pat.pop - - edge @ident_pat.new_bindings -> @ident_pat.pop -} - - -;; #### Object Patterns - -; LATER-TODO scope propagation through empty object patterns -; currently unsupported by tree sitter queries -; THIS IS A HUGE HACK AND MUST BE FIXED -(object_pattern)@object_pat { - edge @object_pat.after_scope -> @object_pat.before_scope -} - -; scope propagation through object patterns, first entry -(object_pattern - . - (_)@first_entry)@object_pat { - - ; scope propagates from object pattern to entry - edge @first_entry.before_scope -> @object_pat.before_scope -} - -; scope propagation through object patterns, between entries -(object_pattern - (_)@left_entry - . - (_)@right_entry) { - - ; scope propagates from left entry to right entry - edge @right_entry.before_scope -> @left_entry.after_scope -} - -; scope propagation through object patterns, last entry -(object_pattern - (_)@last_entry - .)@object_pat { - - ; scope propagates out from last entry to object pattern - edge @object_pat.after_scope -> @last_entry.after_scope -} - -; covalue propagation through object patterns -(object_pattern - (_)@entry)@object_pat { - - ; covalues flow into entries unchanged - edge @entry.covalue -> @object_pat.covalue - - edge @object_pat.new_bindings -> @entry.new_bindings -} - -; object entry pair patterns -(pair_pattern - key:(_)@key - value:(_)@value_pat)@pair_pat { - - ; covalues flow in dotted - attr (@key.push_dot) push_symbol = "." - edge @value_pat.covalue -> @key.push - edge @key.push -> @key.push_dot - edge @key.push_dot -> @pair_pat.covalue - ; scope flows into value pattern then back out - edge @value_pat.before_scope -> @pair_pat.before_scope - edge @pair_pat.after_scope -> @value_pat.after_scope - - edge @pair_pat.new_bindings -> @value_pat.new_bindings -} - -(pair_pattern - key:(property_identifier)@key)@_pair_pattern { - - attr (@key.push) node_reference = @key -} - -(pair_pattern - key:(string)@key)@_pair_pattern { - - attr (@key.push) symbol_reference = (replace (source-text @key) "\"" ""), source_node = @key -} - -; LATER-TODO the left pattern has to be a name, it cant be another pattern -; object entry assignment patterns -(object_assignment_pattern - left:(_)@left_pat - right:(_)@right_expr)@object_assignment_pat { - - ; scope flows both THROUGH and AROUND the RHS, because it's a - ; by-passable default not a guaranteed value - - ; here we go around - edge @left_pat.before_scope -> @object_assignment_pat.before_scope - - ; and here we go through - edge @right_expr.before_scope -> @object_assignment_pat.before_scope - edge @left_pat.before_scope -> @right_expr.after_scope - - ; and in either case we come out the LHS - edge @object_assignment_pat.after_scope -> @left_pat.after_scope - - ; covalues flow both in from the outside and also from the right expression - edge @left_pat.covalue -> @object_assignment_pat.covalue - edge @left_pat.covalue -> @right_expr.value - - edge @object_assignment_pat.new_bindings -> @left_pat.new_bindings - -} - -; if the object assignment pattern happens to have an identifier on the LHS it also binds -(object_assignment_pattern - left:(shorthand_property_identifier_pattern)@left_pat - right:(_)@_right_expr)@object_assignment_pat { - - edge @left_pat.after_scope -> @left_pat.before_scope - - attr (@left_pat.push) node_reference = @left_pat - attr (@left_pat.push_dot) push_symbol = "." - attr (@left_pat.pop) node_definition = @left_pat - edge @left_pat.pop -> @left_pat.push - edge @left_pat.push -> @left_pat.push_dot - edge @left_pat.push_dot -> @left_pat.covalue - edge @object_assignment_pat.after_scope -> @left_pat.pop - - edge @object_assignment_pat.new_bindings -> @left_pat.pop -} - - -;; #### Array Patterns - -; LATER-TODO scope propagation through empty array patterns -; currently unsupported by tree sitter queries -; THIS IS A HUGE HACK AND MUST BE FIXED -(array_pattern)@array_pat { - edge @array_pat.after_scope -> @array_pat.before_scope -} - -; scope propagation through array patterns, first element -(array_pattern - . - (_)@first_el_pat)@array_pat { - - ; scope flows into the first element - edge @first_el_pat.before_scope -> @array_pat.before_scope -} - -; scope propagation through array patterns, between element -(array_pattern - (_)@left_el_pat - . - (_)@right_el_pat) { - - ; scope flows from left to right - edge @right_el_pat.before_scope -> @left_el_pat.after_scope -} - -; scope propagation through array patterns, last element -(array_pattern - (_)@last_el_pat - .)@array_pat { - - ; scope flow out from the last element - edge @array_pat.after_scope -> @last_el_pat.after_scope -} - -; array pattern -(array_pattern)@array_pat { - edge @array_pat.element_index_push_dot -> @array_pat.covalue - attr (@array_pat.element_index_push_dot) push_symbol = "." -} - -; array pattern elements -(array_pattern (_)@element_pat)@array_pat { - attr (@element_pat.element_index_push) push_symbol = (named-child-index @element_pat) - edge @element_pat.covalue -> @element_pat.element_index_push - edge @element_pat.element_index_push -> @array_pat.element_index_push_dot - - edge @array_pat.new_bindings -> @element_pat.new_bindings -} - - -;; #### Assignment Patterns - -; scope propagation through assignment patterns -(assignment_pattern - left:(_)@left_pat - right:(_)@right_expr)@assignment_pat { - - ; scope flows both THROUGH and AROUND the RHS, because it's a - ; by-passable default not a guaranteed value - - ; here we go around - edge @left_pat.before_scope -> @assignment_pat.before_scope - - ; and here we go through - edge @right_expr.before_scope -> @assignment_pat.before_scope - edge @left_pat.before_scope -> @right_expr.after_scope - - ; the pattern's covalue is the whole thing's, and also the RHS - edge @left_pat.covalue -> @assignment_pat.covalue - edge @left_pat.covalue -> @right_expr.value - - ; and in either case we come out the LHS - edge @assignment_pat.after_scope -> @left_pat.after_scope - - edge @assignment_pat.new_bindings -> @left_pat.new_bindings -} - - -;; #### Rest Patterns - -(rest_pattern (_)@name)@rest_pat { - ; scope flows through, binding via a pop edge that goes to an unknown value - - attr (@rest_pat.pop) node_definition = @name - edge @rest_pat.after_scope -> @rest_pat.before_scope - edge @rest_pat.after_scope -> @rest_pat.pop -} - - - -;; ███████ ██████ ███████ ██████ ██ █████ ██ -;; ██ ██ ██ ██ ██ ██ ██ ██ ██ -;; ███████ ██████ █████ ██ ██ ███████ ██ -;; ██ ██ ██ ██ ██ ██ ██ ██ -;; ███████ ██ ███████ ██████ ██ ██ ██ ███████ - -;; ## Special Cases -;; -;; There are a number of annoying features that libraries make use of to -;; effectively add features to JavaScript. While they don't technically change -;; the language in any way, they're broad design patterns that are meant to be -;; used *as if* these things were more language level than not. These often make -;; it hard to do analysis without actually running code, and so instead, we -;; define some special case queries that treat these techniques as if they were -;; indeed core features of the language. -;; -;; ### Extend -;; -;; The extend method is a mass assignment of values to keys on objects and gets -;; used a bunch for building module export objects. We special case it here so -;; that we can do lookup on it because the extend method itself is dependent on -;; state and mutability, and has no good analytical explanation within the -;; Stack Graph formalism. -;; -;; Since we can't extend the actual value, but only the syntactic references to -;; it in the SG formalism, we treat extend as a kind of shadowing binder, -;; similar to how we treat `+=` or `*=`. - -( - (call_expression - function: (member_expression - object: (identifier)@object - property: (_)@_extend) - arguments: (arguments (object)@new_fields))@call_expr - (#eq? @_extend "extend") -) { - - attr (@object.pop) node_definition = @object - edge @call_expr.after_scope -> @object.pop - edge @object.pop -> @new_fields.value - -} - -;; ### CommonJS-style Exports - -;; CommonJS introduced an export style for pre-ES6 JavaScript that permitted -;; modules to export functions using an exports object bound to a top-level -;; variable `exports`. For instance, to export something as `foo`, we would do: - -;; ``````javascript -;; exports.foo = 1; -;; `````` - -;; If we then imported with `require`, the exports object would have `foo` as -;; a field. Alternatively, we can also specify the entire export object, using - -;; ``````javascript -;; module.exports = my_exported_object; -;; `````` - -( - (assignment_expression - left: (member_expression - object:(identifier)@_exports - property:(_)@property) - right: (_)@right)@assignment_expr - (#eq? @_exports "exports") -) { - - attr (@property.pop) node_definition = @property - attr (@property.pop_dot) pop_symbol = "." - edge @assignment_expr.exports -> @property.pop_dot - edge @property.pop_dot -> @property.pop - edge @property.pop -> @right.value -} - -( - (assignment_expression - left: (member_expression - object:(identifier)@_module - property:(_)@_exports) - right: (_)@right)@assignment_expr - (#eq? @_module "module") - (#eq? @_exports "exports") -) { - - edge @assignment_expr.exports -> @right.value -} - -;; ## CommonJS-style Imports - -;; Similar to exports, CommonJS also defines a way to do imports. In general, -;; these look like `require(expr)`, but in practice the expression is a string -;; constant, which is the only case we hand. - -( - (call_expression - function:(_)@_require - arguments:(arguments (string)@mod_name))@call_expr - (#eq? @_require "require") -) { - - scan (source-text @mod_name) { - "\"([^/\"]+)\.js\"$" { - attr (@mod_name.push) push_symbol = $1 - } - } - - attr (@mod_name.module_guard) push_symbol = "GUARD:EXPORTS" - edge @call_expr.value -> @mod_name.module_guard - edge @mod_name.module_guard -> @mod_name.push - edge @mod_name.push -> ROOT_NODE - -} - - -;; ██████ ███████ ███████ ██ ███ ██ ██ ███████ ███ ██ ███████ -;; ██ ██ ██ ██ ██ ████ ██ ██ ██ ████ ██ ██ -;; ██ ██ █████ █████ ██ ██ ██ ██ ██ █████ ██ ██ ██ ███████ -;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ -;; ██████ ███████ ██ ██ ██ ████ ██ ███████ ██ ████ ███████ - -;; ## Definiens Rules - -;; These rules explain how defined names relate to syntactic definitions -;; of various forms. Sometimes that's declared function names mapping to -;; the entire function declaration, and sometimes that's variables in an -;; assignment being mapped to the thing it's assigned to. The purpose of -;; these is not to augment stack graphs, per se, but to permit syntax -;; oriented tools that need to know about approximate call graphs, etc. - -;; ### Basic Definiens Rules - -;; These rules are all about declarations and terms that have the names -;; directly in them. - -(class_declaration - name:(_)@name - body:(_)@_body)@class_decl { - - attr (@name.pop) definiens_node = @class_decl - -} - -(function_declaration - name:(_)@name - parameters:(_)@_call_sig - body:(_)@_body)@fun_decl { - - attr (@name.pop) definiens_node = @fun_decl - -} - -(generator_function_declaration - name:(_)@name - parameters:(_)@_call_sig - body:(_)@_body)@fun_decl { - - attr (@name.pop) definiens_node = @fun_decl - -} - -(method_definition - name:(_)@name - parameters:(_)@_call_sig - body:(_)@_body)@method_def { - - attr (@name.pop) definiens_node = @method_def - -} - -(function - name:(_)@name - parameters:(_)@_call_sig)@fun { - - attr (@name.pop) definiens_node = @fun - -} - -(generator_function - name:(_)@name - parameters:(_)@_call_sig)@fun { - - attr (@name.pop) definiens_node = @fun - -} - -(class - name:(_)@name - body:(_)@_body)@class { - - attr (@name.pop) definiens_node = @class - -} - -;; ### Assignment-like Rules - -;; These rules make up for the fact that JavaScript permits way more -;; kinds of definitions/declarations than just those that show up in -;; syntactic declarations of the thing in question. - -;; These rules are currently way less precise than we would like but -;; do provide at least some information about definiens for these -;; kinds of definitions. - -(assignment_expression - left: (identifier)@left - right: [ - (function) - (generator_function) - (arrow_function) - ]@right) { - - attr (@left.pop) definiens_node = @right - -} - -(assignment_expression - left: (member_expression property:(_)@left) - right: [ - (function) - (generator_function) - (arrow_function) - ]@right) { - - attr (@left.ignore_guard) pop_symbol = "GUARD:GANDALF" - attr (@left.definiens_hook) node_definition = @left - attr (@left.definiens_hook) definiens_node = @right - edge ROOT_NODE -> @left.ignore_guard - edge @left.ignore_guard -> @left.definiens_hook -} - -(variable_declaration - (variable_declarator - name:(identifier)@name - value: [ - (function) - (generator_function) - (arrow_function) - ]@initializer)) { - - attr (@name.pop) definiens_node = @initializer - -} - -(lexical_declaration - (variable_declarator - name:(identifier)@name - value: [ - (function) - (generator_function) - (arrow_function) - ]@initializer)) { - - attr (@name.pop) definiens_node = @initializer - -} - -(pair - key: (_)@name - value: [ - (function) - (generator_function) - (arrow_function) - ]@value) { - -attr (@name.ignore_guard) pop_symbol = "GUARD:GANDALF" -attr (@name.definiens_hook) node_definition = @name -attr (@name.definiens_hook) definiens_node = @value -edge ROOT_NODE -> @name.ignore_guard -edge @name.ignore_guard -> @name.definiens_hook - -} diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 0a20bddac..14e22a4c2 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -9,6 +9,7 @@ global FILE_PATH global ROOT_NODE global JUMP_TO_SCOPE_NODE + ;; Attribute Shorthands ;; ^^^^^^^^^^^^^^^^^^^^ @@ -32,24 +33,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; Stack Graph Rules ;; ^^^^^^^^^^^^^^^^^ - - - - - - - - - - - - - - - - - - ;; # JavaScript ;; This file defines StackGraph queries for JavaScript. It is written as a @@ -129,7 +112,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ``````stgdoc ;; (number)@num { -;; attr @num.value "pop" = "NUM_VAL" +;; attr (@num.value) pop_symbol = "NUM_VAL" ;; } ;; `````` @@ -158,8 +141,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ``````stgdoc ;; (number)@num { -;; attr @num.value "pop" = "NUM_VAL" -;; edge @num.value -> @num::number_prototype +;; attr (@num.value) pop_symbol = "NUM_VAL" +;; edge @num.value -> @num.number_prototype ;; } ;; `````` @@ -167,11 +150,13 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; want to define number prototype, something like this: ;; ``````stgdoc +;; inherit .number_prototype +;; ;; (program)@prog { ;; ;; ... ;; -;; let @prog::number_prototype = @prog.number_prototype +;; node @prog.number_prototype ;; edge @prog.number_prototype -> @prog.number_prototype_toString_method_value ;; edge @prog.number_prototype -> @prog.number_prototype_valueOf_method_value ;; ...etc @@ -206,7 +191,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ;; edge @prog.number_prototype -> @prog.number_prototype_toString_method_value ;; edge @prog.number_prototype_toString_method_value -> @prog.number_prototype_toString_method_value_return -;; attr @prog.number_prototype_toString_method_value_return "pop" = "GUARD:RETURN" +;; attr (@prog.number_prototype_toString_method_value_return) pop_symbol = "GUARD:RETURN" ;; edge @prog.number_prototype_toString_method_value_return -> @prog.string_prototype ;; ;; ... @@ -243,14 +228,97 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; - `GUARD:EXPORTS` - used for the names exported by the module ;; - `GUARD:DEFAULT` - used for the default export value - - - - - - - - +;; ## Nodes + +(_)@node { + node @node.after_scope + node @node.arg_arguments + node @node.arg_arguments_dot + node @node.arg_index + node @node.arg_scope + node @node.arg_scope_no_this + node @node.arg_this + node @node.arguments_pop + node @node.arguments_push + node @node.before_scope + node @node.boundvar_pop + node @node.call + node @node.constructor + node @node.constructor_guard + node @node.covalue + node @node.default_guard + node @node.definiens_hook + node @node.drop + node @node.element_index_push + node @node.element_index_push_dot + node @node.element_pop_dot + node @node.exports + node @node.exports_pop + node @node.field_pop_dot + node @node.guard_default + node @node.guard_this + node @node.ignore_guard + node @node.index_pop + node @node.index_push + node @node.key_pop + node @node.key_push + node @node.label_guard + node @node.label_pop + node @node.label_push + node @node.member_pop + node @node.member_push + node @node.method_value + node @node.method_value_arg_scope + node @node.method_value_call + node @node.method_value_drop + node @node.method_value_return + node @node.method_value_this + node @node.method_value_this_guard + node @node.module_guard + node @node.module_pop + node @node.module_scope + node @node.name_pop + node @node.name_push + node @node.new_bindings + node @node.pop + node @node.pop_dot + node @node.pop_guard_default + node @node.push + node @node.push_dot + node @node.push_exports_guard + node @node.push_guard_default + node @node.push_guard_exports + node @node.return_guard + node @node.rhsvar_before_scope + node @node.rhsvar_value + node @node.source + node @node.string_prototype + node @node.this_pop + node @node.this_push + node @node.value + node @node.value_arg_scope + node @node.value_call + node @node.value_drop + node @node.value_return + node @node.value_this + node @node.value_this_guard + + attr (@node.arg_scope) is_exported +} + + +; ## Inherited + +inherit .builtins_Regex_prototype +inherit .builtins_arguments_prototype +inherit .builtins_boolean +inherit .builtins_empty_object +inherit .builtins_null +inherit .builtins_number +inherit .builtins_string +inherit .builtins_undefined +inherit .exports +inherit .return_or_yield ;; ██████ ██████ ██████ ██████ ██████ █████ ███ ███ ███████ ;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ████ ██ @@ -266,38 +334,26 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ### Program Queries (program)@prog { - - node @prog.before_scope - node @prog.after_scope - node @prog.module_scope - node @prog.module_pop - node @prog.exports - node @prog.exports_pop - scan FILE_PATH { "([^/]+)\.js$" { - attr (@prog.module_pop) pop_symbol = $1 - ;; attr (@prog.module_pop) no_span + attr (@prog.module_pop) symbol_definition = $1, source_node = @prog } } edge @prog.before_scope -> ROOT_NODE - attr (@prog.module_scope) symbol_definition = "GUARD:MODULE" + attr (@prog.module_scope) pop_symbol = "GUARD:MODULE" edge ROOT_NODE -> @prog.module_pop edge @prog.module_pop -> @prog.module_scope edge @prog.module_scope -> @prog.after_scope - ;; attr (@prog) no_span - ;; attr (@prog.module_pop) no_span - ;; attr (@prog.module_scope) no_span - ;; attr (@prog.exports) no_span - ;; attr (@prog.exports_pop) no_span - ;; attr (@prog.before_scope) no_span - ;; attr (@prog.after_scope) no_span + attr (@prog.module_pop) empty_source_span + attr (@prog.module_scope) empty_source_span + attr (@prog.exports) empty_source_span + attr (@prog.exports_pop) empty_source_span + attr (@prog.before_scope) empty_source_span + attr (@prog.after_scope) empty_source_span - let @prog.prog = @prog - ;; let @prog.exports = @prog.exports attr (@prog.exports_pop) pop_symbol = "GUARD:EXPORTS" edge @prog.module_pop -> @prog.exports_pop edge @prog.exports_pop -> @prog.exports @@ -309,19 +365,11 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @prog.builtins_null node @prog.builtins_undefined node @prog.builtins_Regex_prototype + node @prog.builtins_arguments_prototype + node @prog.builtins_empty_object -} - -;; propagate variables to children -(_ (_)@child)@parent { - - let @child.builtins_number = @parent.builtins_number - let @child.builtins_string = @parent.builtins_string - let @child.builtins_boolean = @parent.builtins_boolean - let @child.builtins_null = @parent.builtins_null - let @child.builtins_undefined = @parent.builtins_undefined - let @child.builtins_Regex_prototype = @parent.builtins_Regex_prototype - + ;; fallbacks + node @prog.return_or_yield } ; programs, first statement @@ -329,9 +377,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n . (_)@first_stmt)@prog { - ; scopes flow from the program into the first statement - edge @first_stmt.before_scope -> @prog.before_scope - + ; scopes flow from the program into the first statement + edge @first_stmt.before_scope -> @prog.before_scope } ; program, between statements @@ -340,9 +387,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n . (_)@right_stmt) { - ; scopes flow from the left statement to the right one - edge @right_stmt.before_scope -> @left_stmt.after_scope - + ; scopes flow from the left statement to the right one + edge @right_stmt.before_scope -> @left_stmt.after_scope } ; program, last statement @@ -350,39 +396,20 @@ attribute node_symbol = node => symbol = (source-text node), source_n (_)@last_stmt .)@prog { - ; scopes flow from the last statement to the program - edge @prog.after_scope -> @last_stmt.after_scope - + ; scopes flow from the last statement to the program + edge @prog.after_scope -> @last_stmt.after_scope } (hash_bang_line)@hashbang { - - node @hashbang.before_scope - node @hashbang.after_scope - - edge @hashbang.after_scope -> @hashbang.before_scope - + edge @hashbang.after_scope -> @hashbang.before_scope } (comment)@comment { - - node @comment.before_scope - node @comment.after_scope - node @comment.value - - edge @comment.after_scope -> @comment.before_scope - + edge @comment.after_scope -> @comment.before_scope } - - - - - - - ;; ███████ ████████ █████ ████████ ███████ ███ ███ ███████ ███ ██ ████████ ███████ ;; ██ ██ ██ ██ ██ ██ ████ ████ ██ ████ ██ ██ ██ ;; ███████ ██ ███████ ██ █████ ██ ████ ██ █████ ██ ██ ██ ██ ███████ @@ -393,13 +420,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ### Attributes Defined on Statements ;; TODO -;; node @stmt.before_scope -;; node @stmt.after_scope ;; ### Statement Queries - - ;; ███████ ██ ██ ██████ ██████ ██████ ████████ ███████ ;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ;; █████ ███ ██████ ██ ██ ██████ ██ ███████ @@ -408,254 +431,247 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Export -(export_statement)@export_stmt { - - node @export_stmt.before_scope - node @export_stmt.after_scope - -} - ; exports of just names ; eg ; export { foo, bar as baz }; -;; (export_statement -;; (export_clause)@export_clause -;; !source)@export_stmt { +(export_statement + (export_clause)@export_clause + !source)@export_stmt { -;; edge @export_clause.source -> @export_clause.before_scope + edge @export_clause.source -> @export_clause.before_scope -;; ; scope flows through the export clause -;; edge @export_clause.before_scope -> @export_stmt.before_scope -;; edge @export_stmt.after_scope -> @export_clause.after_scope -;; } + ; scope flows through the export clause + edge @export_clause.before_scope -> @export_stmt.before_scope + edge @export_stmt.after_scope -> @export_clause.after_scope +} -;; (export_statement -;; (export_clause)@export_clause -;; source:(_)@source)@export_stmt { +(export_statement + (export_clause)@export_clause + source:(_)@source)@export_stmt { -;; edge @export_clause.source -> @source.push_exports_guard + edge @export_clause.source -> @source.push_exports_guard -;; attr @source.push_exports_guard "push" = "GUARD:EXPORTS" -;; scan @source { -;; "\"([^/\"]+)\.js\"$" { -;; attr @source.push "push" = $1 -;; } -;; } -;; edge @source.push_exports_guard -> @source.push -;; edge @source.push -> root + attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" + scan @source { + "\"([^/\"]+)\.js\"$" { + attr (@source.push) push_symbol = $1 + } + } + edge @source.push_exports_guard -> @source.push + edge @source.push -> ROOT_NODE -;; edge @export_clause.before_scope -> @export_stmt.before_scope -;; edge @export_stmt.after_scope -> @export_clause.after_scope + edge @export_clause.before_scope -> @export_stmt.before_scope + edge @export_stmt.after_scope -> @export_clause.after_scope -;; } +} -;; (export_statement -;; (declaration)@decl)@export_stmt { -;; edge @decl.before_scope -> @export_stmt.before_scope -;; edge @export_stmt.after_scope -> @decl.after_scope -;; } +(export_statement + (declaration)@decl)@export_stmt { + edge @decl.before_scope -> @export_stmt.before_scope + edge @export_stmt.after_scope -> @decl.after_scope +} -;; (export_statement -;; declaration: [ -;; (function_declaration name:(identifier)@name) -;; (generator_function_declaration name:(identifier)@name) -;; (class_declaration name:(identifier)@name) -;; (lexical_declaration (variable_declarator name:(identifier)@name)) -;; (variable_declaration (variable_declarator name:(identifier)@name)) -;; ]@decl)@export_stmt { - -;; ; TODO this doesn't support destructuring exports - -;; attr @name.pop "pop" = @name, "definition" -;; attr @name.push "push" = @name -;; edge @export_stmt::exports -> @name.pop -;; edge @name.pop -> @decl.value -;; } +(export_statement + declaration: [ + (function_declaration name:(identifier)@name) + (generator_function_declaration name:(identifier)@name) + (class_declaration name:(identifier)@name) + (lexical_declaration (variable_declarator name:(identifier)@name)) + (variable_declaration (variable_declarator name:(identifier)@name)) + ]@decl)@export_stmt { + + ; TODO this doesn't support destructuring exports + + attr (@name.pop) node_definition = @name + attr (@name.push) push_node = @name + edge @export_stmt.exports -> @name.pop + edge @name.pop -> @decl.value +} ; TODO ; export let [x,y] = [1,2]; -;; (export_statement -;; declaration: [ -;; (lexical_declaration -;; (variable_declarator -;; name: [ -;; (object_pattern) -;; (array_pattern) -;; ]@pattern)) -;; (variable_declaration -;; (variable_declarator -;; name: [ -;; (object_pattern) -;; (array_pattern) -;; ]@pattern)) -;; ])@export_stmt { - -;; edge @export_stmt::exports -> @pattern.new_bindings +(export_statement + declaration: [ + (lexical_declaration + (variable_declarator + name: [ + (object_pattern) + (array_pattern) + ]@pattern)) + (variable_declaration + (variable_declarator + name: [ + (object_pattern) + (array_pattern) + ]@pattern)) + ])@export_stmt { + + edge @export_stmt.exports -> @pattern.new_bindings -;; } +} ; LATER-TODO tree sitter doesn't yet support empty switch bodies ; THIS IS A HUGE HACK AND MUST BE FIXED -;; (export_clause)@export_clause { -;; edge @export_clause.after_scope -> @export_clause.before_scope -;; } +(export_clause)@export_clause { + edge @export_clause.after_scope -> @export_clause.before_scope +} -;; (export_clause -;; (_)@export)@export_clause { +(export_clause + (_)@export)@export_clause { -;; edge @export.source -> @export_clause.source -;; } + edge @export.source -> @export_clause.source +} -;; (export_clause -;; . -;; (_)@first_export)@export_clause { +(export_clause + . + (_)@first_export)@export_clause { -;; edge @first_export.before_scope -> @export_clause.before_scope -;; } + edge @first_export.before_scope -> @export_clause.before_scope +} -;; (export_clause -;; (_)@left_export -;; . -;; (_)@right_export) { +(export_clause + (_)@left_export + . + (_)@right_export) { -;; edge @right_export.before_scope -> @left_export.after_scope -;; } + edge @right_export.before_scope -> @left_export.after_scope +} -;; (export_clause -;; (_)@last_export -;; .)@export_clause { +(export_clause + (_)@last_export + .)@export_clause { -;; edge @export_clause.after_scope -> @last_export.after_scope -;; } + edge @export_clause.after_scope -> @last_export.after_scope +} -;; (export_specifier)@export_specifier { -;; edge @export_specifier.after_scope -> @export_specifier.before_scope -;; } +(export_specifier)@export_specifier { + edge @export_specifier.after_scope -> @export_specifier.before_scope +} -;; ( -;; (export_specifier -;; name:(_)@name -;; !alias)@export_specifier +( + (export_specifier + name:(_)@name + !alias)@export_specifier -;; (#not-eq? @name "default") -;; ) { + (#not-eq? @name "default") +) { -;; attr @name.pop "pop" = @name, "definition" -;; attr @name.push "push" = @name, "reference" -;; edge @name.pop -> @name.push -;; edge @name.push -> @export_specifier.source + attr (@name.pop) node_definition = @name + attr (@name.push) node_reference = @name + edge @name.pop -> @name.push + edge @name.push -> @export_specifier.source -;; edge @export_specifier::exports -> @name.pop -;; } + edge @export_specifier.exports -> @name.pop +} -;; ( -;; (export_specifier -;; name:(_)@name -;; alias:(_)@alias)@export_specifier +( + (export_specifier + name:(_)@name + alias:(_)@alias)@export_specifier -;; (#not-eq? @alias "default") + (#not-eq? @alias "default") -;; ) { +) { -;; attr @alias.pop "pop" = @alias, "definition" -;; attr @name.push "push" = @name, "reference" -;; edge @alias.pop -> @name.push -;; edge @name.push -> @export_specifier.source + attr (@alias.pop) node_definition = @alias + attr (@name.push) node_reference = @name + edge @alias.pop -> @name.push + edge @name.push -> @export_specifier.source -;; edge @export_specifier::exports -> @alias.pop -;; } + edge @export_specifier.exports -> @alias.pop +} -;; ( -;; (export_specifier -;; name:(_)@name -;; !alias)@export_specifier +( + (export_specifier + name:(_)@_name + !alias)@export_specifier -;; (#eq? @name "default") + (#eq? @_name "default") -;; ) { +) { -;; attr @export_specifier.pop_guard_default "pop" = "GUARD:DEFAULT" -;; attr @export_specifier.push_guard_default "push" = "GUARD:DEFAULT" -;; edge @export_specifier::exports -> @export_specifier.pop_guard_default -;; edge @export_specifier.pop_guard_default -> @export_specifier.push_guard_default -;; edge @export_specifier.push_guard_default -> @export_specifier.source + attr (@export_specifier.pop_guard_default) pop_symbol = "GUARD:DEFAULT" + attr (@export_specifier.push_guard_default) push_symbol = "GUARD:DEFAULT" + edge @export_specifier.exports -> @export_specifier.pop_guard_default + edge @export_specifier.pop_guard_default -> @export_specifier.push_guard_default + edge @export_specifier.push_guard_default -> @export_specifier.source -;; } +} -;; ( -;; (export_specifier -;; name:(_)@name -;; alias:(_)@alias)@export_specifier +( + (export_specifier + name:(_)@name + alias:(_)@_alias)@export_specifier -;; (#eq? @alias "default") + (#eq? @_alias "default") -;; ) { +) { -;; attr @name.push "push" = @name -;; attr @export_specifier.guard_default "pop" = "GUARD:DEFAULT" -;; edge @name.push -> @export_specifier.source -;; edge @export_specifier.guard_default -> @name.push -;; edge @export_specifier::exports -> @export_specifier.guard_default -;; } + attr (@name.push) push_node = @name + attr (@export_specifier.guard_default) pop_symbol = "GUARD:DEFAULT" + edge @name.push -> @export_specifier.source + edge @export_specifier.guard_default -> @name.push + edge @export_specifier.exports -> @export_specifier.guard_default +} ; simple default exports ; export default ...; -;; (export_statement -;; value:(_)@default_expr)@export_stmt { +(export_statement + value:(_)@default_expr)@export_stmt { -;; attr @export_stmt.default_guard "pop" = "GUARD:DEFAULT", "definition" -;; edge @default_expr.before_scope -> @export_stmt.before_scope -;; edge @export_stmt.after_scope -> @default_expr.after_scope -;; edge @export_stmt::exports -> @export_stmt.default_guard -;; edge @export_stmt.default_guard -> @default_expr.value -;; } + attr (@export_stmt.default_guard) symbol_definition = "GUARD:DEFAULT", source_node = @export_stmt + edge @default_expr.before_scope -> @export_stmt.before_scope + edge @export_stmt.after_scope -> @default_expr.after_scope + edge @export_stmt.exports -> @export_stmt.default_guard + edge @export_stmt.default_guard -> @default_expr.value +} ; aggregated exports ; export * from "foo.js"; -;; (export_statement -;; . -;; source:(_)@source)@export_statement { +(export_statement + . + source:(_)@source)@export_statement { -;; edge @export_statement.after_scope -> @export_statement.before_scope + edge @export_statement.after_scope -> @export_statement.before_scope -;; attr @source.push_exports_guard "push" = "GUARD:EXPORTS" -;; scan @source { -;; "\"([^/\"]+)\.js\"$" { -;; attr @source.push "push" = $1 -;; } -;; } + attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" + scan @source { + "\"([^/\"]+)\.js\"$" { + attr (@source.push) push_symbol = $1 + } + } -;; edge @export_statement::exports -> @source.push_exports_guard -;; edge @source.push_exports_guard -> @source.push -;; edge @source.push -> root + edge @export_statement.exports -> @source.push_exports_guard + edge @source.push_exports_guard -> @source.push + edge @source.push -> ROOT_NODE -;; } +} ; namespace exports ; export * as foo from "bar.js"; -;; (export_statement -;; (namespace_export (_)@alias) -;; source:(_)@source)@export_statement { - -;; edge @export_statement.after_scope -> @export_statement.before_scope - -;; attr @source.push_exports_guard "push" = "GUARD:EXPORTS" -;; scan @source { -;; "\"([^/\"]+)\.js\"$" { -;; attr @source.push "push" = $1 -;; } -;; } -;; attr @alias.pop "pop" = @alias, "definition" -;; attr @alias.pop_dot "pop" = "." -;; edge @export_statement::exports -> @alias.pop -;; edge @alias.pop -> @alias.pop_dot -;; edge @alias.pop_dot -> @source.push_exports_guard -;; edge @source.push_exports_guard -> @source.push -;; edge @source.push -> root +(export_statement + (namespace_export (_)@alias) + source:(_)@source)@export_statement { -;; } + edge @export_statement.after_scope -> @export_statement.before_scope + + attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" + scan @source { + "\"([^/\"]+)\.js\"$" { + attr (@source.push) push_symbol = $1 + } + } + attr (@alias.pop) node_definition = @alias + attr (@alias.pop_dot) pop_symbol = "." + edge @export_statement.exports -> @alias.pop + edge @alias.pop -> @alias.pop_dot + edge @alias.pop_dot -> @source.push_exports_guard + edge @source.push_exports_guard -> @source.push + edge @source.push -> ROOT_NODE + +} @@ -669,149 +685,143 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import -(import_statement)@import_stmt { - - node @import_stmt.before_scope - node @import_stmt.after_scope - -} ; import "foo.js"; ; only used for side effects not imports. ; HACK this is not a good solution, but we can't do better with the ; current tree sitter grammar -;; (import_statement)@import_stmt { -;; edge @import_stmt.after_scope -> @import_stmt.before_scope -;; } +(import_statement)@import_stmt { + edge @import_stmt.after_scope -> @import_stmt.before_scope +} ; import * as name from "module-name"; -;; (import_clause -;; (namespace_import)@namespace_import)@import_clause { +(import_clause + (namespace_import)@namespace_import)@import_clause { -;; edge @namespace_import.before_scope -> @import_clause.before_scope -;; edge @import_clause.after_scope -> @namespace_import.after_scope -;; edge @namespace_import.source -> @import_clause.source -;; } + edge @namespace_import.before_scope -> @import_clause.before_scope + edge @import_clause.after_scope -> @namespace_import.after_scope + edge @namespace_import.source -> @import_clause.source +} -;; (namespace_import (identifier)@imported_as)@namespace_import { +(namespace_import (identifier)@imported_as)@namespace_import { -;; edge @namespace_import.after_scope -> @namespace_import.before_scope + edge @namespace_import.after_scope -> @namespace_import.before_scope -;; attr @imported_as.pop "pop" = @imported_as, "definition" -;; attr @imported_as.pop_dot "pop" = "." -;; edge @imported_as.pop -> @imported_as.pop_dot -;; edge @imported_as.pop_dot -> @namespace_import.source + attr (@imported_as.pop) node_definition = @imported_as + attr (@imported_as.pop_dot) pop_symbol = "." + edge @imported_as.pop -> @imported_as.pop_dot + edge @imported_as.pop_dot -> @namespace_import.source -;; edge @namespace_import.after_scope -> @imported_as.pop + edge @namespace_import.after_scope -> @imported_as.pop -;; } +} ; import { export1 } from "module-name"; ; import { export1 as alias1 } from "module-name"; ; import { export1 , export2 } from "module-name"; ; import { export1 , export2 as alias2 , [...] } from "module-name"; -;; (import_statement -;; (import_clause)@import_clause -;; source:(_)@source)@import_stmt { +(import_statement + (import_clause)@import_clause + source:(_)@source)@import_stmt { -;; edge @import_clause.before_scope -> @import_stmt.before_scope -;; edge @import_stmt.after_scope -> @import_clause.after_scope + edge @import_clause.before_scope -> @import_stmt.before_scope + edge @import_stmt.after_scope -> @import_clause.after_scope -;; scan @source { -;; "\"([^/\"]+)\.js\"$" { -;; attr @source.push "push" = $1 -;; } -;; } -;; attr @source.push_guard_exports "push" = "GUARD:EXPORTS" -;; edge @source.push_guard_exports -> @source.push -;; edge @source.push -> root -;; edge @import_clause.source -> @source.push_guard_exports + scan @source { + "\"([^/\"]+)\.js\"$" { + attr (@source.push) push_symbol = $1 + } + } + attr (@source.push_guard_exports) push_symbol = "GUARD:EXPORTS" + edge @source.push_guard_exports -> @source.push + edge @source.push -> ROOT_NODE + edge @import_clause.source -> @source.push_guard_exports -;; } +} -;; (import_clause -;; (named_imports)@named_imports)@import_clause { +(import_clause + (named_imports)@named_imports)@import_clause { -;; edge @named_imports.before_scope -> @import_clause.before_scope -;; edge @import_clause.after_scope -> @named_imports.after_scope -;; edge @named_imports.source -> @import_clause.source + edge @named_imports.before_scope -> @import_clause.before_scope + edge @import_clause.after_scope -> @named_imports.after_scope + edge @named_imports.source -> @import_clause.source -;; } +} ; LATER-TODO tree sitter doesn't yet support empty named imports ; THIS IS A HUGE HACK AND MUST BE FIXED -;; (named_imports)@named_imports { -;; edge @named_imports.after_scope -> @named_imports.before_scope -;; } +(named_imports)@named_imports { + edge @named_imports.after_scope -> @named_imports.before_scope +} -;; (named_imports -;; (import_specifier)@import_specifier)@named_imports { +(named_imports + (import_specifier)@import_specifier)@named_imports { -;; edge @import_specifier.source -> @named_imports.source -;; } + edge @import_specifier.source -> @named_imports.source +} -;; (named_imports -;; . -;; (import_specifier)@first_import)@named_imports { +(named_imports + . + (import_specifier)@first_import)@named_imports { -;; edge @first_import.before_scope -> @named_imports.before_scope -;; } + edge @first_import.before_scope -> @named_imports.before_scope +} -;; (named_imports -;; (import_specifier)@left_import -;; . -;; (import_specifier)@right_import) { +(named_imports + (import_specifier)@left_import + . + (import_specifier)@right_import) { -;; edge @right_import.before_scope -> @left_import.after_scope -;; } + edge @right_import.before_scope -> @left_import.after_scope +} -;; (named_imports -;; (import_specifier)@last_import -;; .)@named_imports { +(named_imports + (import_specifier)@last_import + .)@named_imports { -;; edge @named_imports.after_scope -> @last_import.after_scope -;; } + edge @named_imports.after_scope -> @last_import.after_scope +} -;; ( +( -;; (import_specifier -;; name:(_)@name -;; !alias)@import_specifier + (import_specifier + name:(_)@name + !alias)@import_specifier -;; (#not-eq? @name "default") + (#not-eq? @name "default") -;; ) { +) { -;; edge @import_specifier.after_scope -> @import_specifier.before_scope + edge @import_specifier.after_scope -> @import_specifier.before_scope -;; attr @name.pop "pop" = @name, "definition" -;; attr @name.push "push" = @name, "reference" -;; edge @name.pop -> @name.push -;; edge @name.push -> @import_specifier.source -;; edge @import_specifier.after_scope -> @name.pop + attr (@name.pop) node_definition = @name + attr (@name.push) node_reference = @name + edge @name.pop -> @name.push + edge @name.push -> @import_specifier.source + edge @import_specifier.after_scope -> @name.pop -;; } +} -;; ( +( -;; (import_specifier -;; name:(_)@name -;; alias:(_)@alias)@import_specifier + (import_specifier + name:(_)@name + alias:(_)@alias)@import_specifier -;; (#not-eq? @name "default") + (#not-eq? @name "default") -;; ) { +) { -;; edge @import_specifier.after_scope -> @import_specifier.before_scope + edge @import_specifier.after_scope -> @import_specifier.before_scope -;; attr @alias.pop "pop" = @alias, "definition" -;; attr @name.push "push" = @name, "reference" -;; edge @alias.pop -> @name.push -;; edge @name.push -> @import_specifier.source -;; edge @import_specifier.after_scope -> @alias.pop + attr (@alias.pop) node_definition = @alias + attr (@name.push) node_reference = @name + edge @alias.pop -> @name.push + edge @name.push -> @import_specifier.source + edge @import_specifier.after_scope -> @alias.pop -;; } +} ; (import_statement ; (import_clause @@ -824,17 +834,17 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; ; scope passes through, augmented by the identifier ; scan @mod_name { ; "\"([^/\"]+)\.js\"$" { -; attr @mod_name.push "push" = $1, "reference" +; attr (@mod_name.push) symbol_reference = $1, source_node = @mod_name ; } ; } -; edge @mod_name.push -> root +; edge @mod_name.push -> ROOT_NODE ; -; attr @name "push", "reference" -; attr @name.push_dot "push" = "." +; attr (@name) node_reference = @name +; attr (@name.push_dot) push_symbol = "." ; edge @name.push_dot -> @mod_name.push ; edge @name -> @name.push_dot ; -; attr @alias "pop", "definition" +; attr (@alias) node_definition = @alias ; edge @alias -> @name ; ; edge @import_stmt.after_scope -> @alias @@ -846,19 +856,19 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; TODO var promise = import("module-name"); ; import defaultExport from "module-name"; -;; (import_clause -;; (identifier)@default_name)@import_clause { +(import_clause + (identifier)@default_name)@import_clause { -;; edge @import_clause.after_scope -> @import_clause.before_scope + edge @import_clause.after_scope -> @import_clause.before_scope -;; attr @default_name.pop "pop" = @default_name, "definition" -;; attr @default_name.push_guard_default "push" = "GUARD:DEFAULT" -;; edge @default_name.pop -> @default_name.push_guard_default -;; edge @default_name.push_guard_default -> @import_clause.source + attr (@default_name.pop) node_definition = @default_name + attr (@default_name.push_guard_default) push_symbol = "GUARD:DEFAULT" + edge @default_name.pop -> @default_name.push_guard_default + edge @default_name.push_guard_default -> @import_clause.source -;; edge @import_clause.after_scope -> @default_name.pop + edge @import_clause.after_scope -> @default_name.pop -;; } +} @@ -877,13 +887,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Debugger (debugger_statement)@debugger_stmt { - - node @debugger_stmt.before_scope - node @debugger_stmt.after_scope - - ; scopes flow through unchanged - edge @debugger_stmt.after_scope -> @debugger_stmt.before_scope - + ; scopes flow through unchanged + edge @debugger_stmt.after_scope -> @debugger_stmt.before_scope } @@ -892,13 +897,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n (expression_statement (_)@inner)@expr_stmt { - node @expr_stmt.before_scope - node @expr_stmt.after_scope - - ; scopes flow in then back out - edge @inner.before_scope -> @expr_stmt.before_scope - edge @expr_stmt.after_scope -> @inner.after_scope - + ; scopes flow in then back out + edge @inner.before_scope -> @expr_stmt.before_scope + edge @expr_stmt.after_scope -> @inner.after_scope } @@ -907,27 +908,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ##### Variable Declarations -(variable_declaration)@variable_decl { - - node @variable_decl.before_scope - node @variable_decl.after_scope - -} - -(lexical_declaration)@lexical_decl { - - node @lexical_decl.before_scope - node @lexical_decl.after_scope - -} - (variable_declaration (variable_declarator name:(identifier)@name))@variable_decl { - - node @variable_decl.name_pop - attr (@variable_decl.name_pop) node_definition = @name edge @variable_decl.after_scope -> @variable_decl.name_pop attr (@variable_decl.after_scope -> @variable_decl.name_pop) precedence = 1 @@ -939,12 +923,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n name:(identifier)@name))@lexical_decl { - node @lexical_decl.name_pop - attr (@lexical_decl.name_pop) node_definition = @name edge @lexical_decl.after_scope -> @lexical_decl.name_pop attr (@lexical_decl.after_scope -> @lexical_decl.name_pop) precedence = 1 - + } (variable_declaration @@ -983,355 +965,329 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @initializer.before_scope -> @lexical_decl.before_scope edge @lexical_decl.after_scope -> @initializer.after_scope attr (@lexical_decl.after_scope -> @initializer.after_scope) precedence = 0 - + } -;; (variable_declaration -;; (variable_declarator -;; name:[(object_pattern) (array_pattern)]@pat -;; value:(_)@initializer))@decl { +(variable_declaration + (variable_declarator + name:[(object_pattern) (array_pattern)]@pat + value:(_)@initializer))@decl { -;; edge @initializer.before_scope -> @decl.before_scope -;; edge @pat.before_scope -> @initializer.after_scope -;; edge @decl.after_scope -> @pat.after_scope + edge @initializer.before_scope -> @decl.before_scope + edge @pat.before_scope -> @initializer.after_scope + edge @decl.after_scope -> @pat.after_scope -;; edge @pat.covalue -> @initializer.value -;; } + edge @pat.covalue -> @initializer.value +} -;; (lexical_declaration -;; (variable_declarator -;; name:[(object_pattern) (array_pattern)]@pat -;; value:(_)@initializer))@decl { +(lexical_declaration + (variable_declarator + name:[(object_pattern) (array_pattern)]@pat + value:(_)@initializer))@decl { -;; edge @initializer.before_scope -> @decl.before_scope -;; edge @pat.before_scope -> @initializer.after_scope -;; edge @decl.after_scope -> @pat.after_scope + edge @initializer.before_scope -> @decl.before_scope + edge @pat.before_scope -> @initializer.after_scope + edge @decl.after_scope -> @pat.after_scope -;; edge @pat.covalue -> @initializer.value -;; } + edge @pat.covalue -> @initializer.value +} ;; ##### Function Declarations (function_declaration - name:(_)@_name - parameters:(_)@_call_sig - body:(_)@_body)@fun_decl -{ + name:(_)@name + parameters:(_)@call_sig + body:(_)@body)@fun_decl { + + attr (@name.pop) syntax_type = "function" + + ; scope flows across the decl + edge @fun_decl.after_scope -> @fun_decl.before_scope + + ; with an augmentation for the function + attr (@name.pop) node_definition = @name + edge @fun_decl.after_scope -> @name.pop + edge @name.pop -> @fun_decl.value + + ; function values have drop nodes that handle closures, that points to the + ; before scope for the function + attr (@fun_decl.value_drop) type = "drop_scopes" + edge @fun_decl.value_drop -> @fun_decl.before_scope + + ; the call sig's before scope comes from the drop node then flows into the body + edge @call_sig.before_scope -> @fun_decl.value_drop + attr (@call_sig.this_pop) symbol_definition = "this", source_node = @call_sig + attr (@call_sig.this_push) push_symbol = "this" + edge @call_sig.this_pop -> @call_sig.this_push + edge @call_sig.this_push -> @fun_decl.value_arg_scope + edge @call_sig.before_scope -> @call_sig.this_pop + attr (@call_sig.arguments_pop) symbol_definition = "arguments", source_node = @call_sig + attr (@call_sig.arguments_push) push_symbol = "arguments" + edge @call_sig.arguments_pop -> @call_sig.arguments_push + edge @call_sig.arguments_push -> @fun_decl.value_arg_scope + edge @call_sig.before_scope -> @call_sig.arguments_pop + edge @body.before_scope -> @call_sig.after_scope + + + ; function values have call nodes + attr (@fun_decl.value_call) pop_scoped_symbol = "()" + edge @fun_decl.value -> @fun_decl.value_call + + ; function values have return nodes which need to be visible for returns + attr (@fun_decl.value_return) pop_symbol = "GUARD:RETURN" + edge @fun_decl.value_call -> @fun_decl.value_return + let @body.return_or_yield = @fun_decl.value_return + + ; method values have this nodes which need to be visible for constructor calls + attr (@fun_decl.value_this) push_symbol = "this" + attr (@fun_decl.value_this_guard) pop_symbol = "GUARD:THIS" + edge @fun_decl.value_call -> @fun_decl.value_this_guard + edge @fun_decl.value_this_guard -> @fun_decl.value_this + edge @fun_decl.value_this -> @body.after_scope + + ; function values have a jump node that lets params connect up to actual arguments + edge @fun_decl.value_arg_scope -> JUMP_TO_SCOPE_NODE +} - node @fun_decl.before_scope - node @fun_decl.after_scope - -;; attr @name.pop "syntax_type" = "function" - -;; ; scope flows across the decl -;; edge @fun_decl.after_scope -> @fun_decl.before_scope - -;; ; with an augmentation for the function -;; attr @name.pop "pop" = @name, "definition" -;; edge @fun_decl.after_scope -> @name.pop -;; edge @name.pop -> @fun_decl.value - -;; ; function values have drop nodes that handle closures, that points to the -;; ; before scope for the function -;; attr @fun_decl.value_drop "drop" -;; edge @fun_decl.value_drop -> @fun_decl.before_scope - -;; ; the call sig's before scope comes from the drop node then flows into the body -;; edge @call_sig.before_scope -> @fun_decl.value_drop -;; attr @call_sig.this_pop "pop" = "this", "definition" -;; attr @call_sig.this_push "push" = "this" -;; edge @call_sig.this_pop -> @call_sig.this_push -;; edge @call_sig.this_push -> @fun_decl.value_arg_scope -;; edge @call_sig.before_scope -> @call_sig.this_pop -;; attr @call_sig.arguments_pop "pop" = "arguments", "definition" -;; attr @call_sig.arguments_push "push" = "arguments" -;; edge @call_sig.arguments_pop -> @call_sig.arguments_push -;; edge @call_sig.arguments_push -> @fun_decl.value_arg_scope -;; edge @call_sig.before_scope -> @call_sig.arguments_pop -;; edge @body.before_scope -> @call_sig.after_scope - - -;; ; function values have call nodes -;; attr @fun_decl.value_call "pop" = "()", "pop-scope" -;; edge @fun_decl.value -> @fun_decl.value_call - -;; ; function values have return nodes which need to be visible for returns -;; attr @fun_decl.value_return "endpoint" -;; attr @fun_decl.value_return "pop" = "GUARD:RETURN" -;; edge @fun_decl.value_call -> @fun_decl.value_return -;; let @body::return_or_yield = @fun_decl.value_return - -;; ; method values have this nodes which need to be visible for constructor calls -;; attr @fun_decl.value_this "push" = "this" -;; attr @fun_decl.value_this_guard "endpoint" -;; attr @fun_decl.value_this_guard "pop" = "GUARD:THIS" -;; edge @fun_decl.value_call -> @fun_decl.value_this_guard -;; edge @fun_decl.value_this_guard -> @fun_decl.value_this -;; edge @fun_decl.value_this -> @body.after_scope - -;; ; function values have a jump node that lets params connect up to actual arguments -;; attr @fun_decl.value_arg_scope "jump-to" -} - -;; (function_declaration -;; parameters: -;; (formal_parameters (_)@param))@fun_decl { - -;; ; parameters jump to the pushed argument scope -;; attr @param.arg_index "push" = (child-index @param) -;; edge @param.covalue -> @param.arg_index -;; edge @param.arg_index -> @fun_decl.value_arg_scope -;; } +(function_declaration + parameters: + (formal_parameters (_)@param))@fun_decl { + ; parameters jump to the pushed argument scope + attr (@param.arg_index) push_symbol = (named-child-index @param) + edge @param.covalue -> @param.arg_index + edge @param.arg_index -> @fun_decl.value_arg_scope +} ;; ##### Generator Function Declarations (generator_function_declaration - name:(_)@_name - parameters:(_)@_call_sig - body:(_)@_body)@gen_fun_decl -{ + name:(_)@name + parameters:(_)@call_sig + body:(_)@body)@fun_decl { + + attr (@name.pop) syntax_type = "function" + + ; scope flows across the decl + edge @fun_decl.after_scope -> @fun_decl.before_scope + + ; with an augmentation for the function + attr (@name.pop) node_definition = @name + edge @fun_decl.after_scope -> @name.pop + edge @name.pop -> @fun_decl.value + + ; function values have drop nodes that handle closures, that points to the + ; before scope of the declaration + attr (@fun_decl.value_drop) type = "drop_scopes" + edge @fun_decl.value_drop -> @fun_decl.before_scope + + + ; the call sig's before scope comes from the drop node then flows into the body + edge @call_sig.before_scope -> @fun_decl.value_drop + attr (@call_sig.this_pop) symbol_definition = "this", source_node = @call_sig + attr (@call_sig.this_push) push_symbol = "this" + edge @call_sig.this_pop -> @call_sig.this_push + edge @call_sig.this_push -> @fun_decl.value_arg_scope + edge @call_sig.before_scope -> @call_sig.this_pop + attr (@call_sig.arguments_pop) symbol_definition = "arguments", source_node = @call_sig + attr (@call_sig.arguments_push) push_symbol = "arguments" + edge @call_sig.arguments_pop -> @call_sig.arguments_push + edge @call_sig.arguments_push -> @fun_decl.value_arg_scope + edge @call_sig.before_scope -> @call_sig.arguments_pop + edge @body.before_scope -> @call_sig.after_scope + + ; function values have call nodes + attr (@fun_decl.value_call) pop_scoped_symbol = "()" + edge @fun_decl.value -> @fun_decl.value_call + + ; function values have return nodes which need to be visible for returns + attr (@fun_decl.value_return) pop_symbol = "GUARD:RETURN" + edge @fun_decl.value_call -> @fun_decl.value_return + let @body.return_or_yield = @fun_decl.value_return + + ; method values have this nodes which need to be visible for constructor calls + attr (@fun_decl.value_this) push_symbol = "this" + attr (@fun_decl.value_this_guard) pop_symbol = "GUARD:THIS" + edge @fun_decl.value_call -> @fun_decl.value_this_guard + edge @fun_decl.value_this_guard -> @fun_decl.value_this + edge @fun_decl.value_this -> @body.after_scope + + ; function values have a jump node that lets params connect up to actual arguments + edge @fun_decl.value_arg_scope -> JUMP_TO_SCOPE_NODE +} - node @gen_fun_decl.before_scope - node @gen_fun_decl.after_scope - -;; attr @name.pop "syntax_type" = "function" - -;; ; scope flows across the decl -;; edge @fun_decl.after_scope -> @fun_decl.before_scope - -;; ; with an augmentation for the function -;; attr @name.pop "pop" = @name, "definition" -;; edge @fun_decl.after_scope -> @name.pop -;; edge @name.pop -> @fun_decl.value - -;; ; function values have drop nodes that handle closures, that points to the -;; ; before scope of the declaration -;; attr @fun_decl.value_drop "drop" -;; edge @fun_decl.value_drop -> @fun_decl.before_scope - - -;; ; the call sig's before scope comes from the drop node then flows into the body -;; edge @call_sig.before_scope -> @fun_decl.value_drop -;; attr @call_sig.this_pop "pop" = "this", "definition" -;; attr @call_sig.this_push "push" = "this" -;; edge @call_sig.this_pop -> @call_sig.this_push -;; edge @call_sig.this_push -> @fun_decl.value_arg_scope -;; edge @call_sig.before_scope -> @call_sig.this_pop -;; attr @call_sig.arguments_pop "pop" = "arguments", "definition" -;; attr @call_sig.arguments_push "push" = "arguments" -;; edge @call_sig.arguments_pop -> @call_sig.arguments_push -;; edge @call_sig.arguments_push -> @fun_decl.value_arg_scope -;; edge @call_sig.before_scope -> @call_sig.arguments_pop -;; edge @body.before_scope -> @call_sig.after_scope - -;; ; function values have call nodes -;; attr @fun_decl.value_call "pop" = "()", "pop-scope" -;; edge @fun_decl.value -> @fun_decl.value_call - -;; ; function values have return nodes which need to be visible for returns -;; attr @fun_decl.value_return "endpoint" -;; attr @fun_decl.value_return "pop" = "GUARD:RETURN" -;; edge @fun_decl.value_call -> @fun_decl.value_return -;; let @body::return_or_yield = @fun_decl.value_return - -;; ; method values have this nodes which need to be visible for constructor calls -;; attr @fun_decl.value_this "push" = "this" -;; attr @fun_decl.value_this_guard "endpoint" -;; attr @fun_decl.value_this_guard "pop" = "GUARD:THIS" -;; edge @fun_decl.value_call -> @fun_decl.value_this_guard -;; edge @fun_decl.value_this_guard -> @fun_decl.value_this -;; edge @fun_decl.value_this -> @body.after_scope - -;; ; function values have a jump node that lets params connect up to actual arguments -;; attr @fun_decl.value_arg_scope "jump-to" -} - -;; (generator_function_declaration -;; parameters: -;; (formal_parameters (_)@param))@fun_decl { - -;; ; parameters jump to the pushed argument scope -;; attr @param.arg_index "push" = (child-index @param) -;; edge @param.covalue -> @param.arg_index -;; edge @param.arg_index -> @fun_decl.value_arg_scope -;; } +(generator_function_declaration + parameters: + (formal_parameters (_)@param))@fun_decl { + + ; parameters jump to the pushed argument scope + attr (@param.arg_index) push_symbol = (named-child-index @param) + edge @param.covalue -> @param.arg_index + edge @param.arg_index -> @fun_decl.value_arg_scope +} ;; #### Classes (class_declaration - name:(_)@_name - body:(_)@_body)@class_decl -{ + name:(_)@name + body:(_)@body)@class_decl { - node @class_decl.before_scope - node @class_decl.after_scope + attr (@name.pop) syntax_type = "class" -;; attr @name.pop "syntax_type" = "class" + attr (@name.pop) node_definition = @name + edge @class_decl.after_scope -> @name.pop + edge @name.pop -> @class_decl.value -;; attr @name.pop "pop" = @name, "definition" -;; edge @class_decl.after_scope -> @name.pop -;; edge @name.pop -> @class_decl.value - -;; edge @body.before_scope -> @class_decl.before_scope -;; edge @class_decl.value -> @body.after_scope -;; edge @class_decl.after_scope -> @class_decl.before_scope -;; } + edge @body.before_scope -> @class_decl.before_scope + edge @class_decl.value -> @body.after_scope + edge @class_decl.after_scope -> @class_decl.before_scope +} -;; (class_declaration -;; (class_heritage (_)@name))@class_decl { +(class_declaration + (class_heritage (_)@name))@class_decl { -;; edge @name.before_scope -> @class_decl.before_scope -;; edge @class_decl.value -> @name.value + edge @name.before_scope -> @class_decl.before_scope + edge @class_decl.value -> @name.value } ; LATER-TODO tree sitter doesn't yet support empty switch bodies ; THIS IS A HUGE HACK AND MUST BE FIXED -;; (class_body)@class_body { -;; edge @class_body.after_scope -> @class_body.before_scope -;; } +(class_body)@class_body { + edge @class_body.after_scope -> @class_body.before_scope +} -;; (class_body -;; . -;; (_)@first_decl)@class_body { +(class_body + . + (_)@first_decl)@class_body { -;; edge @first_decl.before_scope -> @class_body.before_scope -;; } + edge @first_decl.before_scope -> @class_body.before_scope +} -;; (class_body -;; (_)@left_decl -;; . -;; (_)@right_decl) { +(class_body + (_)@left_decl + . + (_)@right_decl) { -;; edge @right_decl.before_scope -> @left_decl.after_scope -;; } + edge @right_decl.before_scope -> @left_decl.after_scope +} -;; (class_body -;; (_)@last_decl -;; .)@class_body { +(class_body + (_)@last_decl + .)@class_body { -;; edge @class_body.after_scope -> @last_decl.after_scope -;; } + edge @class_body.after_scope -> @last_decl.after_scope +} -;; ( -;; (method_definition -;; name:(_)@name)@method_def -;; (#eq? @name "constructor") -;; ) { -;; ; augmentation for the constructor -;; attr @name.constructor_guard "pop" = "GUARD:CONSTRUCTOR", "definition" -;; edge @method_def.after_scope -> @name.constructor_guard -;; edge @name.constructor_guard -> @method_def.method_value -;; } +( + (method_definition + name:(_)@name)@method_def + (#eq? @name "constructor") +) { + ; augmentation for the constructor + attr (@name.constructor_guard) symbol_definition = "GUARD:CONSTRUCTOR", source_node = @name + edge @method_def.after_scope -> @name.constructor_guard + edge @name.constructor_guard -> @method_def.method_value +} -;; ( -;; (method_definition -;; name:(_)@name)@method_def -;; (#not-eq? @name "constructor") -;; ) { -;; ; augmentation for the method -;; attr @name.pop "pop" = @name, "definition" -;; attr @name.pop_dot "pop" = "." -;; edge @method_def.after_scope -> @name.pop_dot -;; edge @name.pop_dot -> @name.pop -;; edge @name.pop -> @method_def.method_value -;; } +( + (method_definition + name:(_)@name)@method_def + (#not-eq? @name "constructor") +) { + ; augmentation for the method + attr (@name.pop) node_definition = @name + attr (@name.pop_dot) pop_symbol = "." + edge @method_def.after_scope -> @name.pop_dot + edge @name.pop_dot -> @name.pop + edge @name.pop -> @method_def.method_value +} -;; (method_definition -;; name:(_)@name -;; parameters:(_)@call_sig -;; body:(_)@body)@method_def { - -;; attr @name.pop "syntax_type" = "method" - -;; ; scope flows across the decl -;; edge @method_def.after_scope -> @method_def.before_scope - -;; ; method values have drop nodes that handle closures, that points to the -;; ; before scope from method def -;; attr @method_def.method_value_drop "drop" -;; edge @method_def.method_value_drop -> @method_def.before_scope - -;; ; the call sig's before scope comes from the drop node then flows into the body -;; edge @call_sig.before_scope -> @method_def.method_value_drop -;; edge @body.before_scope -> @call_sig.after_scope - -;; ; method values have call nodes -;; attr @method_def.method_value_call "pop" = "()", "pop-scope" -;; edge @method_def.method_value -> @method_def.method_value_call - -;; ; method values have return nodes which need to be visible for returns -;; attr @method_def.method_value_return "endpoint" -;; attr @method_def.method_value_return "pop" = "GUARD:RETURN" -;; edge @method_def.method_value_call -> @method_def.method_value_return -;; let @body::return_or_yield = @method_def.method_value_return - -;; ; method values have this nodes which need to be visible for constructor calls -;; attr @method_def.method_value_this "push" = "this" -;; attr @method_def.method_value_this_guard "endpoint" -;; attr @method_def.method_value_this_guard "pop" = "GUARD:THIS" -;; edge @method_def.method_value_call -> @method_def.method_value_this_guard -;; edge @method_def.method_value_this_guard -> @method_def.method_value_this -;; edge @method_def.method_value_this -> @body.after_scope - -;; ; method values have a jump node that lets params connect up to actual arguments -;; attr @method_def.method_value_arg_scope "jump-to" -;; } +(method_definition + name:(_)@name + parameters:(_)@call_sig + body:(_)@body)@method_def { -;; (method_definition -;; parameters: -;; (formal_parameters (_)@param))@method_def { + attr (@name.pop) syntax_type = "method" -;; ; parameters jump to the pushed argument scope -;; attr @param.arg_index "push" = (child-index @param) -;; edge @param.covalue -> @param.arg_index -;; edge @param.arg_index -> @method_def.method_value_arg_scope -;; } + ; scope flows across the decl + edge @method_def.after_scope -> @method_def.before_scope + ; method values have drop nodes that handle closures, that points to the + ; before scope from method def + attr (@method_def.method_value_drop) type = "drop_scopes" + edge @method_def.method_value_drop -> @method_def.before_scope + ; the call sig's before scope comes from the drop node then flows into the body + edge @call_sig.before_scope -> @method_def.method_value_drop + edge @body.before_scope -> @call_sig.after_scope -;; (field_definition -;; property:(property_identifier)@property)@field_def { + ; method values have call nodes + attr (@method_def.method_value_call) pop_scoped_symbol = "()" + edge @method_def.method_value -> @method_def.method_value_call -;; attr @property.pop "pop" = @property, "definition" -;; attr @property.pop_dot "pop" = "." -;; edge @field_def.after_scope -> @property.pop_dot -;; edge @property.pop_dot -> @property.pop -;; } + ; method values have return nodes which need to be visible for returns + attr (@method_def.method_value_return) pop_symbol = "GUARD:RETURN" + edge @method_def.method_value_call -> @method_def.method_value_return + let @body.return_or_yield = @method_def.method_value_return -;; (field_definition -;; !value)@field_def { + ; method values have this nodes which need to be visible for constructor calls + attr (@method_def.method_value_this) push_symbol = "this" + attr (@method_def.method_value_this_guard) pop_symbol = "GUARD:THIS" + edge @method_def.method_value_call -> @method_def.method_value_this_guard + edge @method_def.method_value_this_guard -> @method_def.method_value_this + edge @method_def.method_value_this -> @body.after_scope -;; edge @field_def.after_scope -> @field_def.before_scope -;; } + ; method values have a jump node that lets params connect up to actual arguments + edge @method_def.method_value_arg_scope -> JUMP_TO_SCOPE_NODE +} -;; (field_definition -;; property:(_)@property -;; value:(_)@value)@field_def { +(method_definition + parameters: + (formal_parameters (_)@param))@method_def { -;; edge @value.before_scope -> @field_def.before_scope -;; edge @field_def.after_scope -> @value.after_scope -;; edge @property.pop -> @value.value -;; } + ; parameters jump to the pushed argument scope + attr (@param.arg_index) push_symbol = (named-child-index @param) + edge @param.covalue -> @param.arg_index + edge @param.arg_index -> @method_def.method_value_arg_scope +} -;; #### Statement Block +(field_definition + property:(property_identifier)@property)@field_def { -(statement_block)@stmt_block { + attr (@property.pop) node_definition = @property + attr (@property.pop_dot) pop_symbol = "." + edge @field_def.after_scope -> @property.pop_dot + edge @property.pop_dot -> @property.pop +} - node @stmt_block.before_scope - node @stmt_block.after_scope +(field_definition + !value)@field_def { + edge @field_def.after_scope -> @field_def.before_scope } +(field_definition + property:(_)@property + value:(_)@value)@field_def { + + edge @value.before_scope -> @field_def.before_scope + edge @field_def.after_scope -> @value.after_scope + edge @property.pop -> @value.value +} + + + +;; #### Statement Block + ; statement block, first statement (statement_block . @@ -1365,46 +1321,32 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### If (if_statement condition:(_)@condition)@if_stmt { - - node @if_stmt.before_scope - node @if_stmt.after_scope - ; scopes flow from the if statement to the condition edge @condition.before_scope -> @if_stmt.before_scope - } (if_statement condition:(_)@condition consequence:(_)@consequence)@if_stmt { - ; scopes flow from the condition to the consequence, then to the if statement edge @consequence.before_scope -> @condition.after_scope edge @if_stmt.after_scope -> @consequence.after_scope - } (if_statement condition:(_)@condition alternative:(_)@alternative)@if_stmt { - ; scopes flow from the condition to the alternative, then to the if statement edge @alternative.before_scope -> @condition.after_scope edge @if_stmt.after_scope -> @alternative.after_scope - } (else_clause (_)@inner)@else_clause { - - node @else_clause.before_scope - node @else_clause.after_scope - ; scopes flow in and right back out edge @inner.before_scope -> @else_clause.before_scope edge @else_clause.after_scope -> @inner.after_scope - } @@ -1416,23 +1358,12 @@ attribute node_symbol = node => symbol = (source-text node), source_n value:(_)@value body:(switch_body)@body)@switch_stmt { - - node @switch_stmt.before_scope - node @switch_stmt.after_scope - ; scopes flow into the value then into the body then back out to the switch edge @value.before_scope -> @switch_stmt.before_scope edge @body.before_scope -> @value.after_scope edge @switch_stmt.after_scope -> @body.after_scope } -(switch_body)@switch_body { - - node @switch_body.before_scope - node @switch_body.after_scope - -} - ; LATER-TODO tree sitter doesn't yet support empty switch bodies ; THIS IS A HUGE HACK AND MUST BE FIXED (switch_body)@switch_body { @@ -1444,10 +1375,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n . (_)@first_choice)@switch_body { - ; scopes flow from the body into the first choice edge @first_choice.before_scope -> @switch_body.before_scope - } ; switch body, between choices @@ -1456,10 +1385,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n . (_)@right_choice) { - ; scopes flow left to right edge @right_choice.before_scope -> @left_choice.after_scope - } ; switch body, last choice @@ -1467,17 +1394,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n (_)@last_choice .)@switch_body { - ; scope flows out to the switch body edge @switch_body.after_scope -> @last_choice.after_scope - -} - -(switch_case)@switch_case { - - node @switch_case.before_scope - node @switch_case.after_scope - } ; LATER-TODO tree sitter doesnt yet support switch case's with no statements @@ -1492,11 +1410,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n . (_)@first_stmt)@switch_case { - ; scopes flow into the value then into the first statement edge @value.before_scope -> @switch_case.before_scope edge @first_stmt.before_scope -> @value.after_scope - } ; switch case, non-empty statements, between statement @@ -1506,35 +1422,24 @@ attribute node_symbol = node => symbol = (source-text node), source_n . (_)@right_stmt) { - ; scopes flow left to right edge @right_stmt.before_scope -> @left_stmt.after_scope - } ; switch case, non-empty statements, last statement (switch_case value:(_) (_)@last_stmt - .)@switch_case -{ - - ; scopes flow out from the last statement to the case - edge @switch_case.after_scope -> @last_stmt.after_scope - -} - -(switch_default)@switch_default { - - node @switch_default.before_scope - node @switch_default.after_scope + .)@switch_case { + ; scopes flow out from the last statement to the case + edge @switch_case.after_scope -> @last_stmt.after_scope } ; LATER-TODO tree sitter doesnt yet support empty defaults ; THIS IS A HUGE HACK AND MUST BE FIXED (switch_default)@switch_default { - edge @switch_default.after_scope -> @switch_default.before_scope + edge @switch_default.after_scope -> @switch_default.before_scope } ; switch default, non-empty statements, first statement @@ -1542,10 +1447,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n . (_)@first_stmt)@switch_default { - ; scopes flow into the first statement edge @first_stmt.before_scope -> @switch_default.before_scope - } ; switch default, non-empty statements, between statements @@ -1557,7 +1460,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; scopes flow left to right edge @right_stmt.before_scope -> @left_stmt.after_scope - } ; switch default, non-empty statements, last statement @@ -1568,7 +1470,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; scopes flow out to the default edge @switch_default.after_scope -> @last_stmt.after_scope - } @@ -1582,9 +1483,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n body:(_)@body)@for_stmt { - node @for_stmt.before_scope - node @for_stmt.after_scope - ; scopes flow from statement to initializer then test then body then increment edge @initializer.before_scope -> @for_stmt.before_scope edge @condition.before_scope -> @initializer.after_scope @@ -1608,14 +1506,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n body:(_)@body)@for_in_stmt { - node @for_in_stmt.before_scope - node @for_in_stmt.after_scope - ; scopes flow from statement to right then to body then back out edge @right.before_scope -> @for_in_stmt.before_scope edge @body.before_scope -> @right.after_scope edge @for_in_stmt.after_scope -> @body.after_scope - } (for_in_statement @@ -1624,7 +1518,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n body:(_)@body)@for_in_stmt { - node @for_in_stmt.pop attr (@for_in_stmt.pop) node_definition = @left edge @for_in_stmt.pop -> @right.value edge @body.before_scope -> @for_in_stmt.pop @@ -1640,9 +1533,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n body:(_)@body)@while_stmt { - node @while_stmt.before_scope - node @while_stmt.after_scope - ; scopes flow from while to condition then to body then back out edge @condition.before_scope -> @while_stmt.before_scope edge @body.before_scope -> @condition.after_scope @@ -1661,9 +1551,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n condition:(_)@condition)@do_stmt { - node @do_stmt.before_scope - node @do_stmt.after_scope - ; scopes flow from statement to body then condition then back to statement edge @body.before_scope -> @do_stmt.before_scope edge @condition.before_scope -> @body.after_scope @@ -1678,10 +1565,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Try -(try_statement body:(_)@body)@try_stmt { - - node @try_stmt.before_scope - node @try_stmt.after_scope +(try_statement + body:(_)@body)@try_stmt +{ ; scopes flow into the body then back out edge @body.before_scope -> @try_stmt.before_scope @@ -1697,7 +1583,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; scopes flow from body to handler then back out edge @handler.before_scope -> @body.after_scope edge @try_stmt.after_scope -> @handler.after_scope - } (try_statement @@ -1712,29 +1597,18 @@ attribute node_symbol = node => symbol = (source-text node), source_n (try_statement handler:(_)@handler - finalizer:(_)@finalizer)@_try_stmt + finalizer:(_)@finalizer)@try_stmt { ; scopes flow from handler to finalizer then back out edge @finalizer.before_scope -> @handler.after_scope - -} - -(try_statement finalizer:(_)@finalizer)@try_stmt { - edge @try_stmt.after_scope -> @finalizer.after_scope - } (catch_clause body:(_)@body)@catch_clause { - - node @catch_clause.before_scope - node @catch_clause.after_scope - ; scopes flow in then back out edge @body.before_scope -> @catch_clause.before_scope edge @catch_clause.after_scope -> @body.after_scope - } (catch_clause @@ -1742,21 +1616,15 @@ attribute node_symbol = node => symbol = (source-text node), source_n body:(_)@body)@catch_clause { - node @catch_clause.pop attr (@catch_clause.pop) node_definition = @name edge @body.before_scope -> @catch_clause.pop } (finally_clause body:(_)@body)@finally_clause { - - node @finally_clause.before_scope - node @finally_clause.after_scope - ; scopes flow in thenback out edge @body.before_scope -> @finally_clause.before_scope edge @finally_clause.after_scope -> @body.after_scope - } @@ -1768,10 +1636,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n body:(_)@body)@with_stmt { - node @with_stmt.before_scope - node @with_stmt.after_scope - node @with_stmt.push_dot - ; scopes flow from the statement into the object then into the body then back out edge @object.before_scope -> @with_stmt.before_scope edge @body.before_scope -> @object.after_scope @@ -1787,19 +1651,12 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Break (break_statement)@break_stmt { - - node @break_stmt.before_scope - node @break_stmt.after_scope - ; scopes flow through unchanged edge @break_stmt.after_scope -> @break_stmt.before_scope } (break_statement (_)@label)@break_stmt { - node @break_stmt.label_push - node @break_stmt.label_guard - attr (@break_stmt.label_guard) push_symbol = "GUARD:LABEL" attr (@break_stmt.label_push) node_reference = @label @@ -1812,19 +1669,12 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Continue (continue_statement)@continue_stmt { - - node @continue_stmt.before_scope - node @continue_stmt.after_scope - ; scopes flow through unchanged edge @continue_stmt.after_scope -> @continue_stmt.before_scope } (continue_statement (_)@label)@continue_stmt { - node @continue_stmt.label_push - node @continue_stmt.label_guard - attr (@continue_stmt.label_guard) push_symbol = "GUARD:LABEL" attr (@continue_stmt.label_push) node_reference = @label @@ -1836,41 +1686,30 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Return +; LATER-TODO tree sitter doesn't let us express empty returns currently (return_statement)@return_stmt { - - node @return_stmt.before_scope - node @return_stmt.after_scope - + ; scopes flow through unchanged + edge @return_stmt.after_scope -> @return_stmt.before_scope } -; LATER-TODO tree sitter doesn't let us express empty returns currently -;; (return_statement)@return_stmt { -;; ; scopes flow through unchanged -;; edge @return_stmt.after_scope -> @return_stmt.before_scope -;; } - -;; (return_statement -;; (_)@returned_expr)@return_stmt { -;; ; scopes flow through the returned expresssion -;; edge @returned_expr.before_scope -> @return_stmt.before_scope -;; edge @return_stmt.after_scope -> @returned_expr.after_scope +(return_statement + (_)@returned_expr)@return_stmt { + ; scopes flow through the returned expresssion + edge @returned_expr.before_scope -> @return_stmt.before_scope + edge @return_stmt.after_scope -> @returned_expr.after_scope -;; ; return statements hook up to the call node of the function value -;; edge @return_stmt::return_or_yield -> @returned_expr.value -;; } + ; return statements hook up to the call node of the function value + edge @return_stmt.return_or_yield -> @returned_expr.value +} ;; #### Throw -(throw_statement (_)@_thrown_expr)@throw_stmt { - - node @throw_stmt.before_scope - node @throw_stmt.after_scope - -;; ; scopes flow through the returned expresssion -;; edge @thrown_expr.before_scope -> @throw_stmt.before_scope -;; edge @throw_stmt.after_scope -> @thrown_expr.after_scope +(throw_statement (_)@thrown_expr)@throw_stmt { + ; scopes flow through the returned expresssion + edge @thrown_expr.before_scope -> @throw_stmt.before_scope + edge @throw_stmt.after_scope -> @thrown_expr.after_scope } @@ -1878,12 +1717,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Empty (empty_statement)@empty_stmt { - - node @empty_stmt.before_scope - node @empty_stmt.after_scope - -;; ; scopes flow through unchaged -;; edge @empty_stmt.after_scope -> @empty_stmt.before_scope + ; scopes flow through unchaged + edge @empty_stmt.after_scope -> @empty_stmt.before_scope } @@ -1895,11 +1730,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n body:(_)@inner)@labeled_stmt { - node @labeled_stmt.before_scope - node @labeled_stmt.after_scope - node @labeled_stmt.label_pop - node @labeled_stmt.label_guard - attr (@labeled_stmt.label_guard) pop_symbol = "GUARD:LABEL" attr (@labeled_stmt.label_pop) node_definition = @label @@ -1912,13 +1742,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n - - - - - - - ;; ███████ ██ ██ ██████ ██████ ███████ ███████ ███████ ██ ██████ ███ ██ ███████ ;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ;; █████ ███ ██████ ██████ █████ ███████ ███████ ██ ██ ██ ██ ██ ██ ███████ @@ -1929,61 +1752,35 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ### Attributes Defined on Expressions ;; TODO -;; node @expr.before_scope -;; node @expr.after_scope -;; node @expr.value ;; ### Expression Queries ;; #### Parenthesized -(parenthesized_expression)@parens { - - node @parens.before_scope - node @parens.after_scope - node @parens.value - -} - (parenthesized_expression (_)@inner)@parens { + ; scopes flow right through + edge @inner.before_scope -> @parens.before_scope + edge @parens.after_scope -> @inner.after_scope - ; scopes flow right through - edge @inner.before_scope -> @parens.before_scope - edge @parens.after_scope -> @inner.after_scope - - ; as do values - edge @parens.value -> @inner.value - + ; as do values + edge @parens.value -> @inner.value } ;; #### Strings (string)@string { + ; scopes don't change + edge @string.after_scope -> @string.before_scope - node @string.before_scope - node @string.after_scope - node @string.value - - ; scopes don't change - edge @string.after_scope -> @string.before_scope - - ; the value of a string is the string primitive - edge @string.value -> @string.builtins_string + ; the value of a string is the string primitive + edge @string.value -> @string.builtins_string } ;; #### Template Strings -(template_string)@template_string { - - node @template_string.before_scope - node @template_string.after_scope - node @template_string.value - -} - ; template_strings w/ no substitutions ; LATER-TODO tree sitter queries don't let us find the absence of substitutions ; THIS IS A HUGE HACK AND MUST BE FIXED @@ -1996,7 +1793,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; which may be useful (template_string (template_substitution (_)@inner_expr))@template_string { ; the value of a template string is a template string value built from the values of its substitutions - ; attr @template_string.value "template_string_value" + ; attr (@template_string.value) "template_string_value" edge @template_string.value -> @inner_expr.value } @@ -2026,168 +1823,111 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Numbers (number)@number { + ; scopes don't change + edge @number.after_scope -> @number.before_scope - node @number.before_scope - node @number.after_scope - node @number.value - - ; scopes don't change - edge @number.after_scope -> @number.before_scope - - ; the value of a number is the number primitive - edge @number.value -> @number.builtins_number - + ; the value of a number is the number primitive + edge @number.value -> @number.builtins_number } ;; #### Variables (primary_expression/identifier)@variable { + ; scopes don't change + edge @variable.after_scope -> @variable.before_scope - node @variable.before_scope - node @variable.after_scope - node @variable.value - - ; scopes don't change - edge @variable.after_scope -> @variable.before_scope - - ; value is a lookup, ie a push - attr (@variable.value) node_reference = @variable - edge @variable.value -> @variable.before_scope - + ; value is a lookup, ie a push + attr (@variable.value) node_reference = @variable + edge @variable.value -> @variable.before_scope } ;; #### Booleans (true)@true { + ; scopes don't change + edge @true.after_scope -> @true.before_scope - node @true.before_scope - node @true.after_scope - node @true.value - - ; scopes don't change - edge @true.after_scope -> @true.before_scope - - ; the value of true is a boolean primitive - edge @true.value -> @true.builtins_boolean - + ; the value of true is a boolean primitive + edge @true.value -> @true.builtins_boolean } (false)@false { + ; scopes don't change + edge @false.after_scope -> @false.before_scope - node @false.before_scope - node @false.after_scope - node @false.value - - ; scopes don't change - edge @false.after_scope -> @false.before_scope - - ; the value of false is a boolean primitive - edge @false.value -> @false.builtins_boolean + ; the value of false is a boolean primitive + edge @false.value -> @false.builtins_boolean } ;; #### This (this)@this { + ; scopes don't change + edge @this.after_scope -> @this.before_scope - node @this.before_scope - node @this.after_scope - node @this.value - - ; scopes don't change - edge @this.after_scope -> @this.before_scope - - ;; TODO - ;; ; this is a lookup, ie a push - ;; attr @this.value "push" = "this", "reference" - ;; edge @this.value -> @this.before_scope + ; this is a lookup, ie a push + attr (@this.value) symbol_reference = "this", source_node = @this + edge @this.value -> @this.before_scope } ;; #### Super (super)@super { - - node @super.before_scope - node @super.after_scope - node @super.value - - ; scopes don't change - edge @super.after_scope -> @super.before_scope - + ; scopes don't change + edge @super.after_scope -> @super.before_scope } ;; #### Null (null)@null { + ; scopes don't change + edge @null.after_scope -> @null.before_scope - node @null.before_scope - node @null.after_scope - node @null.value - - ; scopes don't change - edge @null.after_scope -> @null.before_scope - - ; the value of null is the null primitive - edge @null.value -> @null.builtins_null + ; the value of null is the null primitive + edge @null.value -> @null.builtins_null } ;; #### Undefined (undefined)@undefined { + ; scopes don't change + edge @undefined.after_scope -> @undefined.before_scope - node @undefined.before_scope - node @undefined.after_scope - node @undefined.value - - ; scopes don't change - edge @undefined.after_scope -> @undefined.before_scope - - ; the value of undefined is the undefined primitive - edge @undefined.value -> @undefined.builtins_undefined + ; the value of undefined is the undefined primitive + edge @undefined.value -> @undefined.builtins_undefined } ;; #### Regular Expressions (regex)@regex { + ; scopes don't change + edge @regex.after_scope -> @regex.before_scope - node @regex.before_scope - node @regex.after_scope - node @regex.value - - ; scopes don't change - edge @regex.after_scope -> @regex.before_scope - - ; the value of a regex is the Regex prototype - edge @regex.value -> @regex.builtins_Regex_prototype + ; the value of a regex is the Regex prototype + edge @regex.value -> @regex.builtins_Regex_prototype } ;; #### Spread Elements -;; TODO NOW - -;; (spread_element (_)@expr)@spread_elem { -;; ; scopes flow in then right back out -;; edge @expr.before_scope -> @spread_elem.before_scope -;; edge @spread_elem.after_scope -> @expr.after_scope -;; } +(spread_element (_)@expr)@spread_elem { + ; scopes flow in then right back out + edge @expr.before_scope -> @spread_elem.before_scope + edge @spread_elem.after_scope -> @expr.after_scope +} ;; #### Objects (object)@object { - node @object.before_scope - node @object.after_scope - node @object.value - node @object.member_pop - attr (@object.member_pop) pop_symbol = "GUARD:MEMBER" edge @object.value -> @object.member_pop @@ -2197,107 +1937,73 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; LATER-TODO currently unsupported by tree sitter queries ; THIS IS A HUGE HACK AND MUST BE FIXED (object)@object_expr { - - edge @object_expr.after_scope -> @object_expr.before_scope - + edge @object_expr.after_scope -> @object_expr.before_scope } ; non-empty objects, scopes, first entry (object . - (_)@first_entry)@object_expr -{ - - ; scopes propagate from the object to the first entry - edge @first_entry.before_scope -> @object_expr.before_scope - + (_)@first_entry)@object_expr { + ; scopes propagate from the object to the first entry + edge @first_entry.before_scope -> @object_expr.before_scope } ; non-empty objects, scopes, between entries (object (_)@left_entry . - (_)@right_entry) -{ - - ; scopes propagate from left entries to right entries - edge @right_entry.before_scope -> @left_entry.after_scope - + (_)@right_entry +)@_object_expr { + ; scopes propagate from left entries to right entries + edge @right_entry.before_scope -> @left_entry.after_scope } ; non-empty objects, scopes, last entry (object (_)@last_entry - .)@object_expr -{ - - ; scopes propagate from the last entry back to the object - edge @object_expr.after_scope -> @last_entry.after_scope - + .)@object_expr { + ; scopes propagate from the last entry back to the object + edge @object_expr.after_scope -> @last_entry.after_scope } ; shorthand property identifier -(shorthand_property_identifier)@keyval { - - node @keyval.before_scope - node @keyval.after_scope - -} - (object (shorthand_property_identifier)@keyval)@object { - node rhsvar_before_scope - node rhsvar_after_scope - node rhsvar_value - node key_pop - - attr (rhsvar_value) node_reference = @keyval - attr (key_pop) node_definition = @keyval - + node rhsvar_before_scope + node rhsvar_after_scope + node rhsvar_value + node key_pop - ; scopes flow into rhsvar, and also straight across b/c they can't be modified - edge rhsvar_before_scope -> @keyval.before_scope - edge rhsvar_after_scope -> rhsvar_before_scope - edge @keyval.after_scope -> rhsvar_after_scope + attr (rhsvar_value) node_reference = @keyval + attr (key_pop) node_definition = @keyval - edge rhsvar_value -> rhsvar_before_scope + ; scopes flow into rhsvar, and also straight across b/c they can't be modified + edge rhsvar_before_scope -> @keyval.before_scope + edge rhsvar_after_scope -> rhsvar_before_scope + edge @keyval.after_scope -> rhsvar_after_scope - ; shorthand property identifiers augment the object value with a member binding - edge key_pop -> rhsvar_value - edge @object.member_pop -> key_pop + edge rhsvar_value -> rhsvar_before_scope + ; shorthand property identifiers augment the object value with a member binding + edge key_pop -> rhsvar_value + edge @object.member_pop -> key_pop } ; pairs -(computed_property_name (_)@expr)@computed_property_name { - - node @computed_property_name.before_scope - node @computed_property_name.after_scope - - edge @expr.before_scope -> @computed_property_name.before_scope - edge @computed_property_name.after_scope -> @expr.after_scope - -} - -(pair - key:(_)@_key - value: (_)@_value)@pair -{ +(computed_property_name (_)@expr)@computed_property_name { - node @pair.before_scope - node @pair.after_scope + edge @expr.before_scope -> @computed_property_name.before_scope + edge @computed_property_name.after_scope -> @expr.after_scope } (object (pair key:(_)@_key - value:(_)@value)@pair)@object -{ + value: (_)@value)@pair)@object { ; pairs augment the object value with a member binding - node @pair.key_pop ; This is done differently depending on what the key is. See next rules. ; attr @key.pop "pop" = @key, "definition" @@ -2320,9 +2026,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n } -;; (pair key:(string)@key) { -;; attr @key.pop "pop" = (replace @key "\"" "") -;; } +(pair key:(string)@key) { + attr (@key.pop) pop_symbol = (replace (source-text @key) "\"" "") +} (pair key:(number)@key @@ -2355,11 +2061,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n (array)@array_expr { - node @array_expr.before_scope - node @array_expr.after_scope - node @array_expr.value - node @array_expr.element_pop_dot - attr (@array_expr.element_pop_dot) pop_symbol = "GUARD:MEMBER" edge @array_expr.value -> @array_expr.element_pop_dot @@ -2369,42 +2070,32 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; LATER-TODO currently unsupported by tree sitter queries ; THIS IS A HUGE HACK AND MUST BE FIXED (array)@array_expr { - - edge @array_expr.after_scope -> @array_expr.before_scope - + edge @array_expr.after_scope -> @array_expr.before_scope } ; nonempty arrays, first element (array . (_)@first_element)@array_expr { - - ; scopes propagate into the first element of the array - edge @first_element.before_scope -> @array_expr.before_scope - + ; scopes propagate into the first element of the array + edge @first_element.before_scope -> @array_expr.before_scope } ; nonempty arrays, between elements (array (_)@left_element . - (_)@right_element) -{ - - ; scopes propagate from left elements to right elements - edge @right_element.before_scope -> @left_element.after_scope - + (_)@right_element) { + ; scopes propagate from left elements to right elements + edge @right_element.before_scope -> @left_element.after_scope } ; nonempty arrays, last element (array (_)@last_element - .)@array_expr -{ - - ; scopes propagate out of the last element to the array - edge @array_expr.after_scope -> @last_element.after_scope - + .)@array_expr { + ; scopes propagate out of the last element to the array + edge @array_expr.after_scope -> @last_element.after_scope } ; elements at indices @@ -2426,119 +2117,112 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; currently unsupported by tree sitter queries ; THIS IS A HUGE HACK AND MUST BE FIXED -;; (formal_parameters)@formal_params { -;; edge @formal_params.after_scope -> @formal_params.before_scope -;; } +(formal_parameters)@formal_params { + edge @formal_params.after_scope -> @formal_params.before_scope +} ; first parameter -;; (formal_parameters -;; . -;; (_)@first_param)@formal_params { +(formal_parameters + . + (_)@first_param)@formal_params { -;; edge @first_param.before_scope -> @formal_params.before_scope -;; } + edge @first_param.before_scope -> @formal_params.before_scope +} ; between parameters -;; (formal_parameters -;; (_)@left_param -;; . -;; (_)@right_param) { +(formal_parameters + (_)@left_param + . + (_)@right_param) { -;; ; scope flows left to right -;; edge @right_param.before_scope -> @left_param.after_scope -;; } + ; scope flows left to right + edge @right_param.before_scope -> @left_param.after_scope +} ; last parameter -;; (formal_parameters -;; (_)@last_param -;; .)@formal_params { +(formal_parameters + (_)@last_param + .)@formal_params { -;; ; scope flows from the param to the call sig -;; edge @formal_params.after_scope -> @last_param.after_scope -;; } + ; scope flows from the param to the call sig + edge @formal_params.after_scope -> @last_param.after_scope +} ;; #### Function Literals ; functions with names -;; (function -;; name:(_)@name -;; parameters:(_)@call_sig)@fun { +(function + name:(_)@name + parameters:(_)@call_sig)@fun { -;; attr @name.pop "syntax_type" = "function" + attr (@name.pop) syntax_type = "function" -;; ; if the function has a name, this is bound the callsig's before scope -;; attr @name.pop "pop" = @name, "definition" -;; edge @call_sig.before_scope -> @name.pop -;; edge @name.pop -> @fun.value -;; } + ; if the function has a name, this is bound the callsig's before scope + attr (@name.pop) node_definition = @name + edge @call_sig.before_scope -> @name.pop + edge @name.pop -> @fun.value +} ; function (function - parameters:(_)@_call_sig - body:(_)@_body)@fun -{ + parameters:(_)@call_sig + body:(_)@body)@fun { + + ; scope flows across the decl + edge @fun.after_scope -> @fun.before_scope + + ; function values have drop nodes that handle closures, that points to the + ; before scope from the function + attr (@fun.value_drop) type = "drop_scopes" + edge @fun.value_drop -> @fun.before_scope + + ; the call sig's before scope comes from the drop node, + ; then flows into the body, and includes a variable binding for "this" + edge @call_sig.before_scope -> @fun.value_drop + attr (@call_sig.this_pop) symbol_definition = "this", source_node = @call_sig + attr (@call_sig.this_push) push_symbol = "this" + edge @call_sig.this_pop -> @call_sig.this_push + edge @call_sig.this_push -> @fun.value_arg_scope + edge @call_sig.before_scope -> @call_sig.this_pop + attr (@call_sig.arguments_pop) symbol_definition = "arguments", source_node = @call_sig + attr (@call_sig.arguments_push) push_symbol = "arguments" + edge @call_sig.arguments_pop -> @call_sig.arguments_push + edge @call_sig.arguments_push -> @fun.value_arg_scope + edge @call_sig.before_scope -> @call_sig.arguments_pop + edge @body.before_scope -> @call_sig.after_scope + + ; function values have call nodes + attr (@fun.value_call) pop_scoped_symbol = "()" + edge @fun.value -> @fun.value_call + + ; function values have return nodes which need to be visible for returns + attr (@fun.value_return) pop_symbol = "GUARD:RETURN" + edge @fun.value_call -> @fun.value_return + let @body.return_or_yield = @fun.value_return + + ; function values have this nodes which need to be visible for method calls + attr (@fun.value_this) push_symbol = "this" + attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" + edge @fun.value_call -> @fun.value_this_guard + edge @fun.value_this_guard -> @fun.value_this + edge @fun.value_this -> @body.after_scope + + ; function values have a jump node that lets params connect up to actual arguments + edge @fun.value_arg_scope -> JUMP_TO_SCOPE_NODE +} - node @fun.before_scope - node @fun.after_scope - node @fun.value - -;; ; scope flows across the decl -;; edge @fun.after_scope -> @fun.before_scope - -;; ; function values have drop nodes that handle closures, that points to the -;; ; before scope from the function -;; attr @fun.value_drop "drop" -;; edge @fun.value_drop -> @fun.before_scope - -;; ; the call sig's before scope comes from the drop node, -;; ; then flows into the body, and includes a variable binding for "this" -;; edge @call_sig.before_scope -> @fun.value_drop -;; attr @call_sig.this_pop "pop" = "this", "definition" -;; attr @call_sig.this_push "push" = "this" -;; edge @call_sig.this_pop -> @call_sig.this_push -;; edge @call_sig.this_push -> @fun.value_arg_scope -;; edge @call_sig.before_scope -> @call_sig.this_pop -;; attr @call_sig.arguments_pop "pop" = "arguments", "definition" -;; attr @call_sig.arguments_push "push" = "arguments" -;; edge @call_sig.arguments_pop -> @call_sig.arguments_push -;; edge @call_sig.arguments_push -> @fun.value_arg_scope -;; edge @call_sig.before_scope -> @call_sig.arguments_pop -;; edge @body.before_scope -> @call_sig.after_scope - -;; ; function values have call nodes -;; attr @fun.value_call "pop" = "()", "pop-scope" -;; edge @fun.value -> @fun.value_call - -;; ; function values have return nodes which need to be visible for returns -;; attr @fun.value_return "endpoint" -;; attr @fun.value_return "pop" = "GUARD:RETURN" -;; edge @fun.value_call -> @fun.value_return -;; let @body::return_or_yield = @fun.value_return - -;; ; function values have this nodes which need to be visible for method calls -;; attr @fun.value_this "push" = "this" -;; attr @fun.value_this_guard "endpoint" -;; attr @fun.value_this_guard "pop" = "GUARD:THIS" -;; edge @fun.value_call -> @fun.value_this_guard -;; edge @fun.value_this_guard -> @fun.value_this -;; edge @fun.value_this -> @body.after_scope - -;; ; function values have a jump node that lets params connect up to actual arguments -;; attr @fun.value_arg_scope "jump-to" -} - -;; (function -;; parameters: -;; (formal_parameters (_)@param))@fun { - -;; ; parameters jump to the pushed argument scope -;; attr @param.arg_index "push" = (child-index @param) -;; edge @param.covalue -> @param.arg_index -;; edge @param.arg_index -> @fun.value_arg_scope -;; } +(function + parameters: + (formal_parameters (_)@param))@fun { + + ; parameters jump to the pushed argument scope + attr (@param.arg_index) push_symbol = (named-child-index @param) + edge @param.covalue -> @param.arg_index + edge @param.arg_index -> @fun.value_arg_scope +} @@ -2547,231 +2231,212 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; function [ (arrow_function - parameters:(_)@_call_sig - body:(_)@_body)@fun + parameters:(_)@call_sig + body:(_)@body)@fun (arrow_function - parameter:(_)@_call_sig - body:(_)@_body)@fun + parameter:(_)@call_sig + body:(_)@body)@fun ] { - node @fun.before_scope - node @fun.after_scope - node @fun.value - -;; ; scope flows across the decl -;; edge @fun.after_scope -> @fun.before_scope + ; scope flows across the decl + edge @fun.after_scope -> @fun.before_scope -;; ; function values have drop nodes that handle closures, that points to the -;; ; before scope from the function -;; attr @fun.value_drop "drop" -;; edge @fun.value_drop -> @fun.before_scope + ; function values have drop nodes that handle closures, that points to the + ; before scope from the function + attr (@fun.value_drop) type = "drop_scopes" + edge @fun.value_drop -> @fun.before_scope -;; ; the call sig's before scope comes from the drop node then flows into the body -;; edge @call_sig.before_scope -> @fun.value_drop -;; edge @body.before_scope -> @call_sig.after_scope + ; the call sig's before scope comes from the drop node then flows into the body + edge @call_sig.before_scope -> @fun.value_drop + edge @body.before_scope -> @call_sig.after_scope -;; ; function values have call nodes -;; attr @fun.value_call "pop" = "()", "pop-scope" -;; edge @fun.value -> @fun.value_call + ; function values have call nodes + attr (@fun.value_call) pop_scoped_symbol = "()" + edge @fun.value -> @fun.value_call -;; ; function values have return nodes which need to be visible for returns -;; attr @fun.value_return "endpoint" -;; attr @fun.value_return "pop" = "GUARD:RETURN" -;; edge @fun.value_call -> @fun.value_return -;; let @body::return_or_yield = @fun.value_return + ; function values have return nodes which need to be visible for returns + attr (@fun.value_return) pop_symbol = "GUARD:RETURN" + edge @fun.value_call -> @fun.value_return + let @body.return_or_yield = @fun.value_return -;; ; function values have this nodes which need to be visible for method calls -;; attr @fun.value_this "push" = "this" -;; attr @fun.value_this_guard "endpoint" -;; attr @fun.value_this_guard "pop" = "GUARD:THIS" -;; edge @fun.value_call -> @fun.value_this_guard -;; edge @fun.value_this_guard -> @fun.value_this -;; edge @fun.value_this -> @body.after_scope + ; function values have this nodes which need to be visible for method calls + attr (@fun.value_this) push_symbol = "this" + attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" + edge @fun.value_call -> @fun.value_this_guard + edge @fun.value_this_guard -> @fun.value_this + edge @fun.value_this -> @body.after_scope -;; ; function values have a jump node that lets params connect up to actual arguments -;; attr @fun.value_arg_scope "jump-to" + ; function values have a jump node that lets params connect up to actual arguments + edge @fun.value_arg_scope -> JUMP_TO_SCOPE_NODE } ; arrow functions returning exprs need special rules for getting the return value hooked up -;; (arrow_function -;; body:(expression)@return_expr) { -;; edge @return_expr::return_or_yield -> @return_expr.value -;; } +(arrow_function + body:(expression)@return_expr) { + edge @return_expr.return_or_yield -> @return_expr.value +} -;; (arrow_function -;; parameter:(_)@param)@fun { +(arrow_function + parameter:(_)@param)@fun { -;; ; scope flows from the param right back out -;; edge @param.after_scope -> @param.before_scope + ; scope flows from the param right back out + edge @param.after_scope -> @param.before_scope -;; ; but augmented with a pop, b/c it's not a pattern -;; attr @param.pop "pop" = @param, "definition" -;; edge @param.pop -> @param.covalue -;; edge @param.after_scope -> @param.pop + ; but augmented with a pop, b/c it's not a pattern + attr (@param.pop) node_definition = @param + edge @param.pop -> @param.covalue + edge @param.after_scope -> @param.pop -;; ; parameters jump to the pushed argument scope -;; attr @param.arg_index "push" = "0" -;; edge @param.covalue -> @param.arg_index -;; edge @param.arg_index -> @fun.value_arg_scope -;; } + ; parameters jump to the pushed argument scope + attr (@param.arg_index) push_symbol = "0" + edge @param.covalue -> @param.arg_index + edge @param.arg_index -> @fun.value_arg_scope +} -;; (arrow_function -;; parameters: -;; (formal_parameters (_)@param))@fun { +(arrow_function + parameters: + (formal_parameters (_)@param))@fun { -;; ; parameters jump to the pushed argument scope -;; attr @param.arg_index "push" = (child-index @param) -;; edge @param.covalue -> @param.arg_index -;; edge @param.arg_index -> @fun.value_arg_scope -;; } + ; parameters jump to the pushed argument scope + attr (@param.arg_index) push_symbol = (named-child-index @param) + edge @param.covalue -> @param.arg_index + edge @param.arg_index -> @fun.value_arg_scope +} ;; #### Generator Function Literals ; generator functions with names -;; (generator_function -;; name:(_)@name -;; parameters:(_)@call_sig)@gen_fun -;; { +(generator_function + name:(_)@name + parameters:(_)@call_sig)@fun { -;; attr @name.pop "syntax_type" = "function" + attr (@name.pop) syntax_type = "function" -;; ; if the function has a name, this is bound the callsig's before scope -;; attr @name.pop "pop" = @name, "definition" -;; edge @call_sig.before_scope -> @name.pop -;; edge @name.pop -> @fun.value -;; } + ; if the function has a name, this is bound the callsig's before scope + attr (@name.pop) node_definition = @name + edge @call_sig.before_scope -> @name.pop + edge @name.pop -> @fun.value +} ; generator function (generator_function - parameters:(_)@_call_sig - body:(_)@_body)@gen_fun -{ - - node @gen_fun.before_scope - node @gen_fun.after_scope - node @gen_fun.value + parameters:(_)@call_sig + body:(_)@body)@fun { -;; ; scope flows across the decl -;; edge @fun.after_scope -> @fun.before_scope + ; scope flows across the decl + edge @fun.after_scope -> @fun.before_scope -;; ; function values have drop nodes that handle closures, that points to the -;; ; before scope from the function -;; attr @fun.value_drop "drop" -;; edge @fun.value_drop -> @fun.before_scope + ; function values have drop nodes that handle closures, that points to the + ; before scope from the function + attr (@fun.value_drop) type = "drop_scopes" + edge @fun.value_drop -> @fun.before_scope -;; ; the call sig's before scope comes from the drop node then flows into the body -;; edge @call_sig.before_scope -> @fun.value_drop -;; edge @body.before_scope -> @call_sig.after_scope + ; the call sig's before scope comes from the drop node then flows into the body + edge @call_sig.before_scope -> @fun.value_drop + edge @body.before_scope -> @call_sig.after_scope -;; ; function values have call nodes -;; attr @fun.value_call "pop" = "()", "pop-scope" -;; edge @fun.value -> @fun.value_call + ; function values have call nodes + attr (@fun.value_call) pop_scoped_symbol = "()" + edge @fun.value -> @fun.value_call -;; ; function values have return nodes which need to be visible for returns -;; attr @fun.value_return "endpoint" -;; attr @fun.value_return "pop" = "GUARD:RETURN" -;; edge @fun.value_call -> @fun.value_return -;; let @body::return_or_yield = @fun.value_return + ; function values have return nodes which need to be visible for returns + attr (@fun.value_return) pop_symbol = "GUARD:RETURN" + edge @fun.value_call -> @fun.value_return + let @body.return_or_yield = @fun.value_return -;; ; function values have this nodes which need to be visible for method calls -;; attr @fun.value_this "push" = "this" -;; attr @fun.value_this_guard "endpoint" -;; attr @fun.value_this_guard "pop" = "GUARD:THIS" -;; edge @fun.value_call -> @fun.value_this_guard -;; edge @fun.value_this_guard -> @fun.value_this -;; edge @fun.value_this -> @body.after_scope + ; function values have this nodes which need to be visible for method calls + attr (@fun.value_this) push_symbol = "this" + attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" + edge @fun.value_call -> @fun.value_this_guard + edge @fun.value_this_guard -> @fun.value_this + edge @fun.value_this -> @body.after_scope -;; ; function values have a jump node that lets params connect up to actual arguments -;; attr @fun.value_arg_scope "jump-to" + ; function values have a jump node that lets params connect up to actual arguments + edge @fun.value_arg_scope -> JUMP_TO_SCOPE_NODE } -;; (generator_function -;; parameters: -;; (formal_parameters (_)@param))@fun { +(generator_function + parameters: + (formal_parameters (_)@param))@fun { -;; ; parameters jump to the pushed argument scope -;; attr @param.arg_index "push" = (child-index @param) -;; edge @param.covalue -> @param.arg_index -;; edge @param.arg_index -> @fun.value_arg_scope -;; } + ; parameters jump to the pushed argument scope + attr (@param.arg_index) push_symbol = (named-child-index @param) + edge @param.covalue -> @param.arg_index + edge @param.arg_index -> @fun.value_arg_scope +} ;; #### Function Calls ; calls, functions (call_expression - function:(_)@_function - arguments:(_)@_arguments)@call_expr -{ + function:(_)@function + arguments:(_)@arguments)@call_expr { - node @call_expr.before_scope - node @call_expr.after_scope - node @call_expr.value - -;; ; scopes flow from call expressions into the function -;; edge @function.before_scope -> @call_expr.before_scope -;; edge @arguments.before_scope -> @function.after_scope -;; edge @call_expr.after_scope -> @arguments.after_scope + ; scopes flow from call expressions into the function + edge @function.before_scope -> @call_expr.before_scope + edge @arguments.before_scope -> @function.after_scope + edge @call_expr.after_scope -> @arguments.after_scope } ; calls, values -;; (call_expression -;; function:(_)@function -;; arguments:(_)@arguments)@call_expr { - -;; ; value is a call, ie a push "()" node w/ "push-scope" @arguments -;; attr @call_expr.return_guard "push" = "GUARD:RETURN" -;; attr @call_expr.call "push" = "()", "push-scope" = @arguments.arg_scope -;; edge @call_expr.value -> @call_expr.return_guard -;; edge @call_expr.return_guard -> @call_expr.call -;; edge @call_expr.call -> @function.value - -;; attr @arguments.arg_this "pop" = "this", "definition" -;; edge @arguments.arg_scope -> @arguments.arg_this - -;; edge @arguments.arg_scope -> @arguments.arg_scope_no_this - -;; attr @arguments.arg_arguments "pop" = "arguments", "definition" -;; attr @arguments.arg_arguments_dot "pop" = "." -;; edge @arguments.arg_scope -> @arguments.arg_arguments -;; edge @arguments.arg_arguments -> @arguments.arg_arguments_dot -;; edge @arguments.arg_arguments_dot -> @arguments.arg_scope_no_this -;; edge @arguments.arg_arguments -> @call_expr::arguments_prototype -;; } +(call_expression + function:(_)@function + arguments:(_)@arguments)@call_expr { + + ; value is a call, ie a push "()" node w/ "push-scope" @arguments + attr (@call_expr.return_guard) push_symbol = "GUARD:RETURN" + attr (@call_expr.call) push_scoped_symbol = "()", scope = @arguments.arg_scope + edge @call_expr.value -> @call_expr.return_guard + edge @call_expr.return_guard -> @call_expr.call + edge @call_expr.call -> @function.value + + attr (@arguments.arg_this) symbol_definition = "this", source_node = @arguments + edge @arguments.arg_scope -> @arguments.arg_this + + edge @arguments.arg_scope -> @arguments.arg_scope_no_this + + attr (@arguments.arg_arguments) symbol_definition = "arguments", source_node = @arguments + attr (@arguments.arg_arguments_dot) pop_symbol = "." + edge @arguments.arg_scope -> @arguments.arg_arguments + edge @arguments.arg_arguments -> @arguments.arg_arguments_dot + edge @arguments.arg_arguments_dot -> @arguments.arg_scope_no_this + edge @arguments.arg_arguments -> @call_expr.builtins_arguments_prototype +} ; special case to make `this` bind correctly in calls of the forms `x.f(...)` ; and `x[f](...)` -;; (call_expression -;; function:[ -;; (member_expression object:(_)@object) -;; (subscript_expression object:(_)@object) -;; ] -;; arguments:(_)@arguments) { - -;; edge @arguments.arg_this -> @object.value -;; } +(call_expression + function:[ + (member_expression object:(_)@object) + (subscript_expression object:(_)@object) + ] + arguments:(_)@arguments) { + + edge @arguments.arg_this -> @object.value +} ; TODO this should eventually be removed and replaced with a version that only ; applies to the negation of (member_expression), but that's not supported by ; tree-sitter currently -;; (call_expression -;; function: (_)@function -;; arguments:(_)@arguments)@call_expr { +(call_expression + function: (_)@_function + arguments:(_)@arguments)@call_expr { -;; edge @arguments.arg_this -> @call_expr::null -;; } -;; (call_expression -;; arguments:(arguments (_)@arg)@arguments) { + edge @arguments.arg_this -> @call_expr.builtins_null +} +(call_expression + arguments:(arguments (_)@arg)@arguments) { -;; attr @arg.arg_index "pop" = (child-index @arg) -;; edge @arguments.arg_scope_no_this -> @arg.arg_index -;; edge @arg.arg_index -> @arg.value -;; } + attr (@arg.arg_index) pop_symbol = (named-child-index @arg) + edge @arguments.arg_scope_no_this -> @arg.arg_index + edge @arg.arg_index -> @arg.value +} @@ -2779,31 +2444,31 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; LATER-TODO currently unsupported by tree sitter queries ; THIS IS A HUGE HACK AND MUST BE FIXED -;; (arguments)@arguments { -;; edge @arguments.after_scope -> @arguments.before_scope -;; } +(arguments)@arguments { + edge @arguments.after_scope -> @arguments.before_scope +} -;; (arguments -;; . -;; (_)@first_arg)@arguments { +(arguments + . + (_)@first_arg)@arguments { -;; edge @first_arg.before_scope -> @arguments.before_scope -;; } + edge @first_arg.before_scope -> @arguments.before_scope +} -;; (arguments -;; (_)@left_arg -;; . -;; (_)@right_arg) { +(arguments + (_)@left_arg + . + (_)@right_arg) { -;; edge @right_arg.before_scope -> @left_arg.after_scope -;; } + edge @right_arg.before_scope -> @left_arg.after_scope +} -;; (arguments -;; (_)@last_arg -;; .)@arguments { +(arguments + (_)@last_arg + .)@arguments { -;; edge @arguments.after_scope -> @last_arg.after_scope -;; } + edge @arguments.after_scope -> @last_arg.after_scope +} @@ -2816,17 +2481,14 @@ attribute node_symbol = node => symbol = (source-text node), source_n property: (_)@property)@member_expr { - node @member_expr.before_scope - node @member_expr.after_scope - node @member_expr.value node member_push node property_push - ; scopes flow into object then back out - edge @object.before_scope -> @member_expr.before_scope - edge @member_expr.after_scope -> @object.after_scope + ; scopes flow into object then back out + edge @object.before_scope -> @member_expr.before_scope + edge @member_expr.after_scope -> @object.after_scope - ; value is a member projection on the value of the object ie. a push then push dot + ; value is a member projection on the value of the object ie. a push then push dot attr (member_push) push_symbol = "GUARD:MEMBER" attr (property_push) node_reference = @property edge property_push -> member_push @@ -2839,25 +2501,18 @@ attribute node_symbol = node => symbol = (source-text node), source_n (subscript_expression object: (_)@object - index: (_)@index)@subscript_expr -{ - - node @subscript_expr.before_scope - node @subscript_expr.after_scope - node @subscript_expr.value - node @subscript_expr.push_dot - node @subscript_expr.index_push + index: (_)@index)@subscript_expr { - ; scopes flow left to right + ; scopes flow left to right edge @object.before_scope -> @subscript_expr.before_scope - edge @index.before_scope -> @object.after_scope + edge @index.before_scope -> @object.after_scope edge @subscript_expr.after_scope -> @index.after_scope - ; value is a subscript lookup, ie a push then push dot + ; value is a subscript lookup, ie a push then push dot attr (@subscript_expr.push_dot) push_symbol = "GUARD:MEMBER" edge @subscript_expr.push_dot -> @object.value - ; this is done differently depending on what the index is + ; this is done differently depending on what the index is ; attr @index.push "push" = @index, "reference" edge @subscript_expr.value -> @subscript_expr.index_push edge @subscript_expr.index_push -> @subscript_expr.push_dot @@ -2878,7 +2533,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n { attr (@subscript_expr.index_push) node_reference = @index - + } @@ -2886,67 +2541,57 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Constructor Calls (new_expression - constructor:(_)@_constructor - arguments:(_)@_arguments)@new_expr -{ + constructor:(_)@constructor + arguments:(_)@arguments)@new_expr { - node @new_expr.before_scope - node @new_expr.after_scope - node @new_expr.value + edge @constructor.before_scope -> @new_expr.before_scope + edge @arguments.before_scope -> @constructor.after_scope + edge @new_expr.after_scope -> @arguments.after_scope -;; edge @constructor.before_scope -> @new_expr.before_scope -;; edge @arguments.before_scope -> @constructor.after_scope -;; edge @new_expr.after_scope -> @arguments.after_scope + attr (@new_expr.call) push_scoped_symbol = "()", scope = @arguments.arg_scope -;; attr @new_expr.call "push" = "()", "push-scope" = @arguments.arg_scope + ; we guard for constructors for the case where we have a "true" class + attr (@constructor.constructor) push_symbol = "GUARD:CONSTRUCTOR" + edge @new_expr.call -> @constructor.constructor + edge @constructor.constructor -> @constructor.value -;; ; we guard for constructors for the case where we have a "true" class -;; attr @constructor.constructor "push" = "GUARD:CONSTRUCTOR" -;; edge @new_expr.call -> @constructor.constructor -;; edge @constructor.constructor -> @constructor.value + ; and also just go right to the value incase we have a function-as-constructor + edge @new_expr.call -> @constructor.value -;; ; and also just go right to the value incase we have a function-as-constructor -;; edge @new_expr.call -> @constructor.value + ; value coming from the constructor call + attr (@new_expr.guard_this) push_symbol = "GUARD:THIS" + edge @new_expr.value -> @new_expr.guard_this + edge @new_expr.guard_this -> @new_expr.call -;; ; value coming from the constructor call -;; attr @new_expr.guard_this "push" = "GUARD:THIS" -;; edge @new_expr.value -> @new_expr.guard_this -;; edge @new_expr.guard_this -> @new_expr.call + ; value coming from the field decls in the class + edge @new_expr.value -> @constructor.value -;; ; value coming from the field decls in the class -;; edge @new_expr.value -> @constructor.value - -;; attr @arguments.arg_this "pop" = "this", "definition" -;; edge @arguments.arg_scope -> @arguments.arg_this -;; edge @arguments.arg_this -> @new_expr::empty_object + attr (@arguments.arg_this) symbol_definition = "this", source_node = @arguments + edge @arguments.arg_scope -> @arguments.arg_this + edge @arguments.arg_this -> @new_expr.builtins_empty_object } -;; (new_expression -;; arguments:(arguments (_)@arg)@arguments) { +(new_expression + arguments:(arguments (_)@arg)@arguments) { -;; attr @arg.arg_index "pop" = (child-index @arg) -;; edge @arguments.arg_scope -> @arg.arg_index -;; edge @arg.arg_index -> @arg.value -;; } + attr (@arg.arg_index) pop_symbol = (named-child-index @arg) + edge @arguments.arg_scope -> @arg.arg_index + edge @arg.arg_index -> @arg.value +} ;; #### Await (await_expression (_)@awaited)@await_expr { + ; scopes flow into the inner expression then back out + edge @awaited.before_scope -> @await_expr.before_scope + edge @await_expr.after_scope -> @awaited.after_scope - node @await_expr.before_scope - node @await_expr.after_scope - node @await_expr.value - - ; scopes flow into the inner expression then back out - edge @awaited.before_scope -> @await_expr.before_scope - edge @await_expr.after_scope -> @awaited.after_scope - - ; value is just propagated up - edge @await_expr.value -> @awaited.value + ; value is just propagated up + edge @await_expr.value -> @awaited.value } @@ -2954,20 +2599,14 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Update Expressions (update_expression argument: (_)@argument)@update_expr { - - node @update_expr.before_scope - node @update_expr.after_scope - node @update_expr.value - node @update_expr.pop - - ; scope propagates through the operand then is updated by the expr - edge @argument.before_scope -> @update_expr.before_scope - edge @update_expr.after_scope -> @argument.after_scope - ; LATER-TODO this isn't quite right because the update argument can't be an arbitrary expr - ; eg f(x)++ doesn't make any sense, you have to have something more like - ; (update_expression argument: (lvar)@argument) + ; scope propagates through the operand then is updated by the expr + edge @argument.before_scope -> @update_expr.before_scope + edge @update_expr.after_scope -> @argument.after_scope + ; LATER-TODO this isn't quite right because the update argument can't be an arbitrary expr + ; eg f(x)++ doesn't make any sense, you have to have something more like + ; (update_expression argument: (lvar)@argument) attr (@update_expr.pop) node_definition = @argument - edge @update_expr.value -> @argument.value + edge @update_expr.value -> @argument.value edge @update_expr.after_scope -> @update_expr.pop edge @update_expr.pop -> @argument.value } @@ -2976,79 +2615,57 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Binary Expressions (binary_expression left: (_)@left right: (_)@right)@binary_expr { + ; scopes propagate left to right through the operands unchanged by the binop itself + edge @left.before_scope -> @binary_expr.before_scope + edge @right.before_scope -> @left.after_scope + edge @binary_expr.after_scope -> @right.after_scope - node @binary_expr.before_scope - node @binary_expr.after_scope - node @binary_expr.value - - ; scopes propagate left to right through the operands unchanged by the binop itself - edge @left.before_scope -> @binary_expr.before_scope - edge @right.before_scope -> @left.after_scope - edge @binary_expr.after_scope -> @right.after_scope - - ;; ; value is a binary op value built from the operands - ;; ; LATER-TODO this isn't quite correct but it permits flow through the expression - ;; ; which can be useful - ;; ; attr @binary_expr.value "binary_operation_value" - ;; edge @binary_expr.value -> @left.value - ;; edge @binary_expr.value -> @right.value + ; value is a binary op value built from the operands + ; LATER-TODO this isn't quite correct but it permits flow through the expression + ; which can be useful + ; attr (@binary_expr.value) "binary_operation_value" + edge @binary_expr.value -> @left.value + edge @binary_expr.value -> @right.value } ;; #### Unary Expressions (unary_expression argument: (_)@argument)@unary_expr { + ; scope propagates through the operand + edge @argument.before_scope -> @unary_expr.before_scope + edge @unary_expr.after_scope -> @argument.after_scope - node @unary_expr.before_scope - node @unary_expr.after_scope - node @unary_expr.value - - ; scope propagates through the operand - edge @argument.before_scope -> @unary_expr.before_scope - edge @unary_expr.after_scope -> @argument.after_scope - -;; ; value is a unaryop value built from the operand -;; ; LATER-TODO this isn't quite correct but it permits flow through the expression -;; ; which can be useful -;; ; attr @unary_expr.value "unary_operation_value" -;; edge @unary_expr.value -> @argument.value + ; value is a unaryop value built from the operand + ; LATER-TODO this isn't quite correct but it permits flow through the expression + ; which can be useful + ; attr (@unary_expr.value) "unary_operation_value" + edge @unary_expr.value -> @argument.value } ;; #### Assignment Expressions; -; TODO NOW ; scopes on RHS, values (assignment_expression left: (_)@left - right: (_)@right)@assignment_expr -{ + right: (_)@right)@assignment_expr { - node @assignment_expr.before_scope - node @assignment_expr.after_scope - node @assignment_expr.value - - ; scopes flow into the RHS then back out to the whole expr, - ; augmented (in subsequent rules) by the LHS - edge @right.before_scope -> @assignment_expr.before_scope - edge @left.before_scope -> @right.after_scope - edge @assignment_expr.after_scope -> @left.after_scope - - ; value of the whole thing is value of the RHS - edge @assignment_expr.value -> @right.value + ; scopes flow into the RHS then back out to the whole expr, + ; augmented (in subsequent rules) by the LHS + edge @right.before_scope -> @assignment_expr.before_scope + edge @left.before_scope -> @right.after_scope + edge @assignment_expr.after_scope -> @left.after_scope + ; value of the whole thing is value of the RHS + edge @assignment_expr.value -> @right.value } ; augmentation of scope via identifiers (assignment_expression - left: (identifier)@left - right: (_)@right)@assignment_expr -{ - - node @left.before_scope - node @left.after_scope - node @assignment_expr.pop + left: (identifier)@left + right: (_)@right)@assignment_expr { ; augments the scope by adding a lookup edge, ie. a pop attr (@assignment_expr.pop) node_definition = @left @@ -3060,67 +2677,53 @@ attribute node_symbol = node => symbol = (source-text node), source_n } ; assignment to direct fields on `this` -; TODO NOW -;; (assignment_expression -;; left: (member_expression -;; object:(this)@this -;; property:(_)@property) -;; right: (_)@right)@assignment_expr { - -;; ; HACK -;; attr @this.drop "drop" -;; edge @this.drop -> @this.pop -;; attr @this.pop "pop" = "this" -;; attr @this.pop_dot "pop" = "." -;; attr @property.pop "pop" = @property, "definition" -;; edge @assignment_expr.after_scope -> @this.drop -;; edge @assignment_expr.after_scope -> @this.pop -;; edge @this.pop -> @this.pop_dot -;; edge @this.pop_dot -> @property.pop -;; edge @property.pop -> @right.value -;; } +(assignment_expression + left: (member_expression + object:(this)@this + property:(_)@property) + right: (_)@right)@assignment_expr { + + ; HACK + attr (@this.drop) type = "drop_scopes" + edge @this.drop -> @this.pop + attr (@this.pop) pop_symbol = "this" + attr (@this.pop_dot) pop_symbol = "." + attr (@property.pop) node_definition = @property + edge @assignment_expr.after_scope -> @this.drop + edge @assignment_expr.after_scope -> @this.pop + edge @this.pop -> @this.pop_dot + edge @this.pop_dot -> @property.pop + edge @property.pop -> @right.value +} ; augmentation of scope via _destructuring_patterns -;; (assignment_expression -;; left: [(object_pattern) (array_pattern)]@left -;; right: (_)@right)@assignment_expr { +(assignment_expression + left: [(object_pattern) (array_pattern)]@left + right: (_)@right)@assignment_expr { -;; ; scope flows from LHS into pattern then back to assignment -;; edge @left.before_scope -> @right.after_scope -;; edge @assignment_expr.after_scope -> @left.after_scope -;; } + ; scope flows from LHS into pattern then back to assignment + edge @left.before_scope -> @right.after_scope + edge @assignment_expr.after_scope -> @left.after_scope +} ;; #### Augmented Assignment Expressions -; TODO NOW (augmented_assignment_expression left: (_)@_left - right: (_)@right)@augmented_assignment_expr -{ - - node @augmented_assignment_expr.before_scope - node @augmented_assignment_expr.after_scope - node @augmented_assignment_expr.value - - ; scopes flow into the RHS then back out to the whole expr, augmented by the LHS - edge @right.before_scope -> @augmented_assignment_expr.before_scope - edge @augmented_assignment_expr.after_scope -> @right.after_scope + right: (_)@right)@augmented_assignment_expr { + ; scopes flow into the RHS then back out to the whole expr, augmented by the LHS + edge @right.before_scope -> @augmented_assignment_expr.before_scope + edge @augmented_assignment_expr.after_scope -> @right.after_scope } (augmented_assignment_expression left:(identifier)@left - right:(_)@right)@augmented_assignment_expr -{ - - node @left.before_scope - node @left.after_scope - node @augmented_assignment_expr.pop - node @augmented_assignment_expr.push + right:(_)@right)@augmented_assignment_expr { - ; augment the scope + ; augment the scope attr (@augmented_assignment_expr.pop) node_definition = @left attr (@augmented_assignment_expr.push) node_reference = @left edge @augmented_assignment_expr.push -> @augmented_assignment_expr.before_scope @@ -3131,51 +2734,39 @@ attribute node_symbol = node => symbol = (source-text node), source_n } - ;; #### Comma Operator / Sequence Expressions (sequence_expression left: (_)@left - right: (_)@right)@sequence_expr -{ + right: (_)@right)@sequence_expr { - node @sequence_expr.before_scope - node @sequence_expr.after_scope - node @sequence_expr.value + ; scopes propagate left to right + edge @left.before_scope -> @sequence_expr.before_scope + edge @right.before_scope -> @left.after_scope + edge @sequence_expr.after_scope -> @right.after_scope - ; scopes propagate left to right - edge @left.before_scope -> @sequence_expr.before_scope - edge @right.before_scope -> @left.after_scope - edge @sequence_expr.after_scope -> @right.after_scope - - ; the value is just the value of the right - edge @sequence_expr.value -> @right.value + ; the value is just the value of the right + edge @sequence_expr.value -> @right.value } - ;; #### Ternary Expression (ternary_expression condition: (_)@condition consequence: (_)@consequence - alternative: (_)@alternative)@ternary_expr -{ - - node @ternary_expr.before_scope - node @ternary_expr.after_scope - node @ternary_expr.value + alternative: (_)@alternative)@ternary_expr { - ; scopes propagate into condition, then into each branch - edge @condition.before_scope -> @ternary_expr.before_scope - edge @consequence.before_scope -> @condition.after_scope - edge @alternative.before_scope -> @condition.after_scope - edge @ternary_expr.after_scope -> @consequence.after_scope - edge @ternary_expr.after_scope -> @alternative.after_scope + ; scopes propagate into condition, then into each branch + edge @condition.before_scope -> @ternary_expr.before_scope + edge @consequence.before_scope -> @condition.after_scope + edge @alternative.before_scope -> @condition.after_scope + edge @ternary_expr.after_scope -> @consequence.after_scope + edge @ternary_expr.after_scope -> @alternative.after_scope - ; value of the whole thing is a conditional value from the operands - edge @ternary_expr.value -> @consequence.value - edge @ternary_expr.value -> @alternative.value + ; value of the whole thing is a conditional value from the operands + edge @ternary_expr.value -> @consequence.value + edge @ternary_expr.value -> @alternative.value } @@ -3183,60 +2774,43 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; #### Yield (yield_expression (_)@yielded_expr)@yield_expr { + ; scopes flow in to the yielded expression then back out + edge @yielded_expr.before_scope -> @yield_expr.before_scope + edge @yield_expr.after_scope -> @yielded_expr.after_scope - node @yield_expr.before_scope - node @yield_expr.after_scope - node @yield_expr.value - - ; scopes flow in to the yielded expression then back out - edge @yielded_expr.before_scope -> @yield_expr.before_scope - edge @yield_expr.after_scope -> @yielded_expr.after_scope - -; TODO NOW -;; ; yield expressions hook up to the call node of the function value -;; edge @yield_expr::return_or_yield -> @yielded_expr.value + ; yield expressions hook up to the call node of the function value + edge @yield_expr.return_or_yield -> @yielded_expr.value } ;; #### Class Expressions -; TODO NOW -(class body:(_)@_body)@class { +(class + body:(_)@body)@class { - node @class.before_scope - node @class.after_scope - node @class.value - -;; edge @body.before_scope -> @class.before_scope -;; edge @class.value -> @body.after_scope -;; edge @class.after_scope -> @class.before_scope + edge @body.before_scope -> @class.before_scope + edge @class.value -> @body.after_scope + edge @class.after_scope -> @class.before_scope } -;; (class -;; name:(_)@name -;; body:(_)@body)@class { +(class + name:(_)@name + body:(_)@body)@class { -;; attr @name.pop "syntax_type" = "class" - -;; attr @name.pop "pop" = @name, "definition" -;; edge @body.before_scope -> @name.pop -;; edge @name.pop -> @class.value -;; } - -;; (class -;; (class_heritage (_)@name))@class { - -;; edge @name.before_scope -> @class.before_scope -;; edge @class.value -> @name.value -;; } - - - - + attr (@name.pop) syntax_type = "class" + attr (@name.pop) node_definition = @name + edge @body.before_scope -> @name.pop + edge @name.pop -> @class.value +} +(class + (class_heritage (_)@name))@class { + edge @name.before_scope -> @class.before_scope + edge @class.value -> @name.value +} @@ -3478,9 +3052,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ### Attributes Defined on Patterns ;; TODO -;; node @pat.before_scope -;; node @pat.after_scope -;; node @pat.new_bindings ;; ### Pattern Queries @@ -3489,11 +3060,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; scope propagation through identifier patterns (pattern/identifier)@ident_pat { - node @ident_pat.before_scope - node @ident_pat.after_scope - node @ident_pat.new_bindings - node @ident_pat.pop - ; scope flows through, binding via a pop edge that goes to an unknown value attr (@ident_pat.pop) node_definition = @ident_pat edge @ident_pat.pop -> @ident_pat.covalue @@ -3501,7 +3067,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @ident_pat.after_scope -> @ident_pat.pop edge @ident_pat.new_bindings -> @ident_pat.pop - } @@ -3510,121 +3075,121 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; LATER-TODO scope propagation through empty object patterns ; currently unsupported by tree sitter queries ; THIS IS A HUGE HACK AND MUST BE FIXED -;; (object_pattern)@object_pat { -;; edge @object_pat.after_scope -> @object_pat.before_scope -;; } +(object_pattern)@object_pat { + edge @object_pat.after_scope -> @object_pat.before_scope +} ; scope propagation through object patterns, first entry -;; (object_pattern -;; . -;; (_)@first_entry)@object_pat { +(object_pattern + . + (_)@first_entry)@object_pat { -;; ; scope propagates from object pattern to entry -;; edge @first_entry.before_scope -> @object_pat.before_scope -;; } + ; scope propagates from object pattern to entry + edge @first_entry.before_scope -> @object_pat.before_scope +} ; scope propagation through object patterns, between entries -;; (object_pattern -;; (_)@left_entry -;; . -;; (_)@right_entry) { +(object_pattern + (_)@left_entry + . + (_)@right_entry) { -;; ; scope propagates from left entry to right entry -;; edge @right_entry.before_scope -> @left_entry.after_scope -;; } + ; scope propagates from left entry to right entry + edge @right_entry.before_scope -> @left_entry.after_scope +} ; scope propagation through object patterns, last entry -;; (object_pattern -;; (_)@last_entry -;; .)@object_pat { +(object_pattern + (_)@last_entry + .)@object_pat { -;; ; scope propagates out from last entry to object pattern -;; edge @object_pat.after_scope -> @last_entry.after_scope -;; } + ; scope propagates out from last entry to object pattern + edge @object_pat.after_scope -> @last_entry.after_scope +} ; covalue propagation through object patterns -;; (object_pattern -;; (_)@entry)@object_pat { +(object_pattern + (_)@entry)@object_pat { -;; ; covalues flow into entries unchanged -;; edge @entry.covalue -> @object_pat.covalue + ; covalues flow into entries unchanged + edge @entry.covalue -> @object_pat.covalue -;; edge @object_pat.new_bindings -> @entry.new_bindings -;; } + edge @object_pat.new_bindings -> @entry.new_bindings +} ; object entry pair patterns -;; (pair_pattern -;; key:(_)@key -;; value:(_)@value_pat)@pair_pat { - -;; ; covalues flow in dotted -;; attr @key.push_dot "push" = "." -;; edge @value_pat.covalue -> @key.push -;; edge @key.push -> @key.push_dot -;; edge @key.push_dot -> @pair_pat.covalue -;; ; scope flows into value pattern then back out -;; edge @value_pat.before_scope -> @pair_pat.before_scope -;; edge @pair_pat.after_scope -> @value_pat.after_scope - -;; edge @pair_pat.new_bindings -> @value_pat.new_bindings -;; } +(pair_pattern + key:(_)@key + value:(_)@value_pat)@pair_pat { -;; (pair_pattern -;; key:(property_identifier)@key)@pair_pattern { + ; covalues flow in dotted + attr (@key.push_dot) push_symbol = "." + edge @value_pat.covalue -> @key.push + edge @key.push -> @key.push_dot + edge @key.push_dot -> @pair_pat.covalue + ; scope flows into value pattern then back out + edge @value_pat.before_scope -> @pair_pat.before_scope + edge @pair_pat.after_scope -> @value_pat.after_scope -;; attr @key.push "push" = @key, "reference" -;; } + edge @pair_pat.new_bindings -> @value_pat.new_bindings +} -;; (pair_pattern -;; key:(string)@key)@pair_pattern { +(pair_pattern + key:(property_identifier)@key)@_pair_pattern { -;; attr @key.push "push" = (replace @key "\"" ""), "reference" -;; } + attr (@key.push) node_reference = @key +} + +(pair_pattern + key:(string)@key)@_pair_pattern { + + attr (@key.push) symbol_reference = (replace (source-text @key) "\"" ""), source_node = @key +} ; LATER-TODO the left pattern has to be a name, it cant be another pattern ; object entry assignment patterns -;; (object_assignment_pattern -;; left:(_)@left_pat -;; right:(_)@right_expr)@object_assignment_pat { +(object_assignment_pattern + left:(_)@left_pat + right:(_)@right_expr)@object_assignment_pat { -;; ; scope flows both THROUGH and AROUND the RHS, because it's a -;; ; by-passable default not a guaranteed value + ; scope flows both THROUGH and AROUND the RHS, because it's a + ; by-passable default not a guaranteed value -;; ; here we go around -;; edge @left_pat.before_scope -> @object_assignment_pat.before_scope + ; here we go around + edge @left_pat.before_scope -> @object_assignment_pat.before_scope -;; ; and here we go through -;; edge @right_expr.before_scope -> @object_assignment_pat.before_scope -;; edge @left_pat.before_scope -> @right_expr.after_scope + ; and here we go through + edge @right_expr.before_scope -> @object_assignment_pat.before_scope + edge @left_pat.before_scope -> @right_expr.after_scope -;; ; and in either case we come out the LHS -;; edge @object_assignment_pat.after_scope -> @left_pat.after_scope + ; and in either case we come out the LHS + edge @object_assignment_pat.after_scope -> @left_pat.after_scope -;; ; covalues flow both in from the outside and also from the right expression -;; edge @left_pat.covalue -> @object_assignment_pat.covalue -;; edge @left_pat.covalue -> @right_expr.value + ; covalues flow both in from the outside and also from the right expression + edge @left_pat.covalue -> @object_assignment_pat.covalue + edge @left_pat.covalue -> @right_expr.value -;; edge @object_assignment_pat.new_bindings -> @left_pat.new_bindings + edge @object_assignment_pat.new_bindings -> @left_pat.new_bindings -;; } +} ; if the object assignment pattern happens to have an identifier on the LHS it also binds -;; (object_assignment_pattern -;; left:(shorthand_property_identifier_pattern)@left_pat -;; right:(_)@right_expr)@object_assignment_pat { +(object_assignment_pattern + left:(shorthand_property_identifier_pattern)@left_pat + right:(_)@_right_expr)@object_assignment_pat { -;; edge @left_pat.after_scope -> @left_pat.before_scope + edge @left_pat.after_scope -> @left_pat.before_scope -;; attr @left_pat.push "push" = @left_pat, "reference" -;; attr @left_pat.push_dot "push" = "." -;; attr @left_pat.pop "pop" = @left_pat, "definition" -;; edge @left_pat.pop -> @left_pat.push -;; edge @left_pat.push -> @left_pat.push_dot -;; edge @left_pat.push_dot -> @left_pat.covalue -;; edge @object_assignment_pat.after_scope -> @left_pat.pop + attr (@left_pat.push) node_reference = @left_pat + attr (@left_pat.push_dot) push_symbol = "." + attr (@left_pat.pop) node_definition = @left_pat + edge @left_pat.pop -> @left_pat.push + edge @left_pat.push -> @left_pat.push_dot + edge @left_pat.push_dot -> @left_pat.covalue + edge @object_assignment_pat.after_scope -> @left_pat.pop -;; edge @object_assignment_pat.new_bindings -> @left_pat.pop -;; } + edge @object_assignment_pat.new_bindings -> @left_pat.pop +} ;; #### Array Patterns @@ -3632,94 +3197,91 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; LATER-TODO scope propagation through empty array patterns ; currently unsupported by tree sitter queries ; THIS IS A HUGE HACK AND MUST BE FIXED -;; (array_pattern)@array_pat { -;; edge @array_pat.after_scope -> @array_pat.before_scope -;; } +(array_pattern)@array_pat { + edge @array_pat.after_scope -> @array_pat.before_scope +} ; scope propagation through array patterns, first element -;; (array_pattern -;; . -;; (_)@first_el_pat)@array_pat { +(array_pattern + . + (_)@first_el_pat)@array_pat { -;; ; scope flows into the first element -;; edge @first_el_pat.before_scope -> @array_pat.before_scope -;; } + ; scope flows into the first element + edge @first_el_pat.before_scope -> @array_pat.before_scope +} ; scope propagation through array patterns, between element -;; (array_pattern -;; (_)@left_el_pat -;; . -;; (_)@right_el_pat) { +(array_pattern + (_)@left_el_pat + . + (_)@right_el_pat) { -;; ; scope flows from left to right -;; edge @right_el_pat.before_scope -> @left_el_pat.after_scope -;; } + ; scope flows from left to right + edge @right_el_pat.before_scope -> @left_el_pat.after_scope +} ; scope propagation through array patterns, last element -;; (array_pattern -;; (_)@last_el_pat -;; .)@array_pat { +(array_pattern + (_)@last_el_pat + .)@array_pat { -;; ; scope flow out from the last element -;; edge @array_pat.after_scope -> @last_el_pat.after_scope -;; } + ; scope flow out from the last element + edge @array_pat.after_scope -> @last_el_pat.after_scope +} + +; array pattern +(array_pattern)@array_pat { + edge @array_pat.element_index_push_dot -> @array_pat.covalue + attr (@array_pat.element_index_push_dot) push_symbol = "." +} ; array pattern elements -;; (array_pattern (_)@element_pat)@array_pat { -;; attr @element_pat.element_index_push "push" = (child-index @element_pat), "reference" -;; attr @array_pat.element_index_push_dot "push" = "." -;; edge @element_pat.covalue -> @element_pat.element_index_push -;; edge @element_pat.element_index_push -> @array_pat.element_index_push_dot -;; edge @array_pat.element_index_push_dot -> @array_pat.covalue - -;; edge @array_pat.new_bindings -> @element_pat.new_bindings -;; } +(array_pattern (_)@element_pat)@array_pat { + attr (@element_pat.element_index_push) push_symbol = (named-child-index @element_pat) + edge @element_pat.covalue -> @element_pat.element_index_push + edge @element_pat.element_index_push -> @array_pat.element_index_push_dot + + edge @array_pat.new_bindings -> @element_pat.new_bindings +} ;; #### Assignment Patterns ; scope propagation through assignment patterns -;; (assignment_pattern -;; left:(_)@left_pat -;; right:(_)@right_expr)@assignment_pat { +(assignment_pattern + left:(_)@left_pat + right:(_)@right_expr)@assignment_pat { -;; ; scope flows both THROUGH and AROUND the RHS, because it's a -;; ; by-passable default not a guaranteed value + ; scope flows both THROUGH and AROUND the RHS, because it's a + ; by-passable default not a guaranteed value -;; ; here we go around -;; edge @left_pat.before_scope -> @assignment_pat.before_scope + ; here we go around + edge @left_pat.before_scope -> @assignment_pat.before_scope -;; ; and here we go through -;; edge @right_expr.before_scope -> @assignment_pat.before_scope -;; edge @left_pat.before_scope -> @right_expr.after_scope + ; and here we go through + edge @right_expr.before_scope -> @assignment_pat.before_scope + edge @left_pat.before_scope -> @right_expr.after_scope -;; ; the pattern's covalue is the whole thing's, and also the RHS -;; edge @left_pat.covalue -> @assignment_pat.covalue -;; edge @left_pat.covalue -> @right_expr.value + ; the pattern's covalue is the whole thing's, and also the RHS + edge @left_pat.covalue -> @assignment_pat.covalue + edge @left_pat.covalue -> @right_expr.value -;; ; and in either case we come out the LHS -;; edge @assignment_pat.after_scope -> @left_pat.after_scope + ; and in either case we come out the LHS + edge @assignment_pat.after_scope -> @left_pat.after_scope -;; edge @assignment_pat.new_bindings -> @left_pat.new_bindings -;; } + edge @assignment_pat.new_bindings -> @left_pat.new_bindings +} ;; #### Rest Patterns -;; (rest_pattern (_)@name)@rest_pat { -;; ; scope flows through, binding via a pop edge that goes to an unknown value - -;; attr @rest_pat.pop "pop" = @name, "definition" -;; edge @rest_pat.after_scope -> @rest_pat.before_scope -;; edge @rest_pat.after_scope -> @rest_pat.pop -;; } - - - - - - +(rest_pattern (_)@name)@rest_pat { + ; scope flows through, binding via a pop edge that goes to an unknown value + attr (@rest_pat.pop) node_definition = @name + edge @rest_pat.after_scope -> @rest_pat.before_scope + edge @rest_pat.after_scope -> @rest_pat.pop +} @@ -3751,20 +3313,20 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; it in the SG formalism, we treat extend as a kind of shadowing binder, ;; similar to how we treat `+=` or `*=`. -;; ( -;; (call_expression -;; function: (member_expression -;; object: (identifier)@object -;; property: (_)@extend) -;; arguments: (arguments (object)@new_fields))@call_expr -;; (#eq? @extend "extend") -;; ) { +( + (call_expression + function: (member_expression + object: (identifier)@object + property: (_)@_extend) + arguments: (arguments (object)@new_fields))@call_expr + (#eq? @_extend "extend") +) { -;; attr @object.pop "pop" = @object, "definition" -;; edge @call_expr.after_scope -> @object.pop -;; edge @object.pop -> @new_fields.value + attr (@object.pop) node_definition = @object + edge @call_expr.after_scope -> @object.pop + edge @object.pop -> @new_fields.value -;; } +} ;; ### CommonJS-style Exports @@ -3783,34 +3345,34 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; module.exports = my_exported_object; ;; `````` -;; ( -;; (assignment_expression -;; left: (member_expression -;; object:(identifier)@exports -;; property:(_)@property) -;; right: (_)@right)@assignment_expr -;; (#eq? @exports "exports") -;; ) { - -;; attr @property.pop "pop" = @property, "definition" -;; attr @property.pop_dot "pop" = "." -;; edge @assignment_expr::exports -> @property.pop_dot -;; edge @property.pop_dot -> @property.pop -;; edge @property.pop -> @right.value -;; } +( + (assignment_expression + left: (member_expression + object:(identifier)@_exports + property:(_)@property) + right: (_)@right)@assignment_expr + (#eq? @_exports "exports") +) { -;; ( -;; (assignment_expression -;; left: (member_expression -;; object:(identifier)@module -;; property:(_)@exports) -;; right: (_)@right)@assignment_expr -;; (#eq? @module "module") -;; (#eq? @exports "exports") -;; ) { - -;; edge @assignment_expr::exports -> @right.value -;; } + attr (@property.pop) node_definition = @property + attr (@property.pop_dot) pop_symbol = "." + edge @assignment_expr.exports -> @property.pop_dot + edge @property.pop_dot -> @property.pop + edge @property.pop -> @right.value +} + +( + (assignment_expression + left: (member_expression + object:(identifier)@_module + property:(_)@_exports) + right: (_)@right)@assignment_expr + (#eq? @_module "module") + (#eq? @_exports "exports") +) { + + edge @assignment_expr.exports -> @right.value +} ;; ## CommonJS-style Imports @@ -3818,33 +3380,25 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; these look like `require(expr)`, but in practice the expression is a string ;; constant, which is the only case we hand. -;; ( -;; (call_expression -;; function:(_)@require -;; arguments:(arguments (string)@mod_name))@call_expr -;; (#eq? @require "require") -;; ) { - -;; scan @mod_name { -;; "\"([^/\"]+)\.js\"$" { -;; attr @mod_name.push "push" = $1 -;; } -;; } - -;; attr @mod_name.module_guard "push" = "GUARD:EXPORTS" -;; edge @call_expr.value -> @mod_name.module_guard -;; edge @mod_name.module_guard -> @mod_name.push -;; edge @mod_name.push -> root - -;; } - - - - - +( + (call_expression + function:(_)@_require + arguments:(arguments (string)@mod_name))@call_expr + (#eq? @_require "require") +) { + scan (source-text @mod_name) { + "\"([^/\"]+)\.js\"$" { + attr (@mod_name.push) push_symbol = $1 + } + } + attr (@mod_name.module_guard) push_symbol = "GUARD:EXPORTS" + edge @call_expr.value -> @mod_name.module_guard + edge @mod_name.module_guard -> @mod_name.push + edge @mod_name.push -> ROOT_NODE +} ;; ██████ ███████ ███████ ██ ███ ██ ██ ███████ ███ ██ ███████ @@ -3867,64 +3421,64 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; These rules are all about declarations and terms that have the names ;; directly in them. -;; (class_declaration -;; name:(_)@name -;; body:(_)@body)@class_decl { +(class_declaration + name:(_)@name + body:(_)@_body)@class_decl { -;; attr @name.pop "definiens" = @class_decl + attr (@name.pop) definiens_node = @class_decl -;; } +} -;; (function_declaration -;; name:(_)@name -;; parameters:(_)@call_sig -;; body:(_)@body)@fun_decl { +(function_declaration + name:(_)@name + parameters:(_)@_call_sig + body:(_)@_body)@fun_decl { -;; attr @name.pop "definiens" = @fun_decl + attr (@name.pop) definiens_node = @fun_decl -;; } +} -;; (generator_function_declaration -;; name:(_)@name -;; parameters:(_)@call_sig -;; body:(_)@body)@fun_decl { +(generator_function_declaration + name:(_)@name + parameters:(_)@_call_sig + body:(_)@_body)@fun_decl { -;; attr @name.pop "definiens" = @fun_decl + attr (@name.pop) definiens_node = @fun_decl -;; } +} -;; (method_definition -;; name:(_)@name -;; parameters:(_)@call_sig -;; body:(_)@body)@method_def { +(method_definition + name:(_)@name + parameters:(_)@_call_sig + body:(_)@_body)@method_def { -;; attr @name.pop "definiens" = @method_def + attr (@name.pop) definiens_node = @method_def -;; } +} -;; (function -;; name:(_)@name -;; parameters:(_)@call_sig)@fun { +(function + name:(_)@name + parameters:(_)@_call_sig)@fun { -;; attr @name.pop "definiens" = @fun + attr (@name.pop) definiens_node = @fun -;; } +} -;; (generator_function -;; name:(_)@name -;; parameters:(_)@call_sig)@fun { +(generator_function + name:(_)@name + parameters:(_)@_call_sig)@fun { -;; attr @name.pop "definiens" = @fun + attr (@name.pop) definiens_node = @fun -;; } +} -;; (class -;; name:(_)@name -;; body:(_)@body)@class { +(class + name:(_)@name + body:(_)@_body)@class { -;; attr @name.pop "definiens" = @class + attr (@name.pop) definiens_node = @class -;; } +} ;; ### Assignment-like Rules @@ -3936,71 +3490,71 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; do provide at least some information about definiens for these ;; kinds of definitions. -;; (assignment_expression -;; left: (identifier)@left -;; right: [ -;; (function) -;; (generator_function) -;; (arrow_function) -;; ]@right) { +(assignment_expression + left: (identifier)@left + right: [ + (function) + (generator_function) + (arrow_function) + ]@right) { -;; attr @left.pop "definiens" = @right + attr (@left.pop) definiens_node = @right -;; } +} -;; (assignment_expression -;; left: (member_expression property:(_)@left) -;; right: [ -;; (function) -;; (generator_function) -;; (arrow_function) -;; ]@right) { - -;; attr @left.ignore_guard "pop" = "GUARD:GANDALF" -;; attr @left.definiens_hook "pop" = @left, "definition" -;; attr @left.definiens_hook "definiens" = @right -;; edge root -> @left.ignore_guard -;; edge @left.ignore_guard -> @left.definiens_hook -;; } +(assignment_expression + left: (member_expression property:(_)@left) + right: [ + (function) + (generator_function) + (arrow_function) + ]@right) { + + attr (@left.ignore_guard) pop_symbol = "GUARD:GANDALF" + attr (@left.definiens_hook) node_definition = @left + attr (@left.definiens_hook) definiens_node = @right + edge ROOT_NODE -> @left.ignore_guard + edge @left.ignore_guard -> @left.definiens_hook +} -;; (variable_declaration -;; (variable_declarator -;; name:(identifier)@name -;; value: [ -;; (function) -;; (generator_function) -;; (arrow_function) -;; ]@initializer)) { +(variable_declaration + (variable_declarator + name:(identifier)@name + value: [ + (function) + (generator_function) + (arrow_function) + ]@initializer)) { -;; attr @name.pop "definiens" = @initializer + attr (@name.pop) definiens_node = @initializer -;; } +} -;; (lexical_declaration -;; (variable_declarator -;; name:(identifier)@name -;; value: [ -;; (function) -;; (generator_function) -;; (arrow_function) -;; ]@initializer)) { +(lexical_declaration + (variable_declarator + name:(identifier)@name + value: [ + (function) + (generator_function) + (arrow_function) + ]@initializer)) { -;; attr @name.pop "definiens" = @initializer + attr (@name.pop) definiens_node = @initializer -;; } +} -;; (pair -;; key: (_)@name -;; value: [ -;; (function) -;; (generator_function) -;; (arrow_function) -;; ]@value) { - -;; attr @name.ignore_guard "pop" = "GUARD:GANDALF" -;; attr @name.definiens_hook "pop" = @name, "definition" -;; attr @name.definiens_hook "definiens" = @value -;; edge root -> @name.ignore_guard -;; edge @name.ignore_guard -> @name.definiens_hook - -;; } \ No newline at end of file +(pair + key: (_)@name + value: [ + (function) + (generator_function) + (arrow_function) + ]@value) { + +attr (@name.ignore_guard) pop_symbol = "GUARD:GANDALF" +attr (@name.definiens_hook) node_definition = @name +attr (@name.definiens_hook) definiens_node = @value +edge ROOT_NODE -> @name.ignore_guard +edge @name.ignore_guard -> @name.definiens_hook + +} From 4422f4a7b71c62ee9de6d8122b776c9823ac262a Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 17:30:31 +0200 Subject: [PATCH 067/500] [conv] source-text --- .../src/stack-graphs.tsg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 14e22a4c2..275bbc027 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -452,7 +452,7 @@ inherit .return_or_yield edge @export_clause.source -> @source.push_exports_guard attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" - scan @source { + scan (source-text @source) { "\"([^/\"]+)\.js\"$" { attr (@source.push) push_symbol = $1 } @@ -637,7 +637,7 @@ inherit .return_or_yield edge @export_statement.after_scope -> @export_statement.before_scope attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" - scan @source { + scan (source-text @source) { "\"([^/\"]+)\.js\"$" { attr (@source.push) push_symbol = $1 } @@ -658,7 +658,7 @@ inherit .return_or_yield edge @export_statement.after_scope -> @export_statement.before_scope attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" - scan @source { + scan (source-text @source) { "\"([^/\"]+)\.js\"$" { attr (@source.push) push_symbol = $1 } @@ -728,7 +728,7 @@ inherit .return_or_yield edge @import_clause.before_scope -> @import_stmt.before_scope edge @import_stmt.after_scope -> @import_clause.after_scope - scan @source { + scan (source-text @source) { "\"([^/\"]+)\.js\"$" { attr (@source.push) push_symbol = $1 } From c0668e3fa867a5c9947baf6244cc3fdc19fd1819 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 17:42:57 +0200 Subject: [PATCH 068/500] Update dependency versions --- languages/tree-sitter-stack-graphs-javascript/Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml index 7adda795d..51de60edf 100644 --- a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -28,11 +28,11 @@ cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"] [dependencies] anyhow = { version = "1.0", optional = true } clap = { version = "4", optional = true } -stack-graphs = { version = "0.10", path = "../../stack-graphs" } +stack-graphs = { version = "0.11", path = "../../stack-graphs" } tree-sitter = "=0.20.9" -tree-sitter-stack-graphs = { version = "0.6", path = "../../tree-sitter-stack-graphs" } +tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs" } tree-sitter-javascript = { git = "https://github.com/tree-sitter/tree-sitter-javascript", rev = "5720b249490b3c17245ba772f6be4a43edb4e3b7" } [dev-dependencies] anyhow = "1.0" -tree-sitter-stack-graphs = { version = "0.6", path = "../../tree-sitter-stack-graphs", features = ["cli"] } +tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs", features = ["cli"] } From e42a1e927890664d65c7f2380479bac698562e94 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 17:43:50 +0200 Subject: [PATCH 069/500] Do not create inherited .exports for every node --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 275bbc027..d624dc7b1 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -252,7 +252,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.element_index_push node @node.element_index_push_dot node @node.element_pop_dot - node @node.exports node @node.exports_pop node @node.field_pop_dot node @node.guard_default @@ -354,6 +353,7 @@ inherit .return_or_yield attr (@prog.before_scope) empty_source_span attr (@prog.after_scope) empty_source_span + node @prog.exports attr (@prog.exports_pop) pop_symbol = "GUARD:EXPORTS" edge @prog.module_pop -> @prog.exports_pop edge @prog.exports_pop -> @prog.exports From f766d377357cf369b2073072aa86a5cb30b9f749 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 17:46:44 +0200 Subject: [PATCH 070/500] Reenable old tests --- .../binding/default_arguments_from_enclosing_scope.js | 0 .../binding/default_arguments_from_other_arguments.js | 0 .../test/{old.skip => old}/binding/destructuring_assignments.js | 0 ...estructuring_assignments_with_defaults_from_enclosing_scope.js | 0 ...estructuring_assignments_with_defaults_from_other_variables.js | 0 .../test/{old.skip => old}/binding/destructuring_parameters.js | 0 .../test/{old.skip => old}/binding/object_assignment_patterns.js | 0 .../test/{old.skip => old}/binding/simple.js | 0 .../test/{old.skip => old}/bug_regressions/2141.js | 0 .../test/{old.skip => old}/bug_regressions/2227.js | 0 .../test/{old.skip => old}/bug_regressions/2291.js | 0 .../{old.skip => old}/classes_and_instances/class_declaration.js | 0 .../{old.skip => old}/classes_and_instances/class_expression.js | 0 .../classes_and_instances/class_expression_superclasses.js | 0 .../classes_and_instances/class_expression_this_field_access.js | 0 .../{old.skip => old}/classes_and_instances/field_declaration.js | 0 .../classes_and_instances/function_class_this_field_access.js | 0 .../classes_and_instances/method_call_this_argument.js | 0 .../{old.skip => old}/classes_and_instances/method_definition.js | 0 .../test/{old.skip => old}/classes_and_instances/superclasses.js | 0 .../{old.skip => old}/classes_and_instances/this_field_access.js | 0 .../test/{old.skip => old}/compound_literals/arrays.js | 0 .../{old.skip => old}/compound_literals/object_extend_method.js | 0 .../test/{old.skip => old}/compound_literals/objects.js | 0 .../test/{old.skip => old}/control_flow_statements/dowhile.js | 0 .../test/{old.skip => old}/control_flow_statements/for.js | 0 .../test/{old.skip => old}/control_flow_statements/forin.js | 0 .../test/{old.skip => old}/control_flow_statements/if.js | 0 .../test/{old.skip => old}/control_flow_statements/try.js | 0 .../test/{old.skip => old}/control_flow_statements/while.js | 0 .../test/{old.skip => old}/control_flow_statements/with.js | 0 .../{old.skip => old}/functions_and_calls/arguments_variable.js | 0 .../arrow_function_values_with_param_lists_and_block_bodies.js | 0 .../arrow_function_values_with_param_lists_and_expr_bodies.js | 0 .../arrow_function_values_with_single_param_and_block_bodies.js | 0 .../arrow_function_values_with_single_param_and_expr_bodies.js | 0 .../test/{old.skip => old}/functions_and_calls/call_arguments.js | 0 .../functions_and_calls/function_declarations.js | 0 .../test/{old.skip => old}/functions_and_calls/function_values.js | 0 .../functions_and_calls/generator_function_declarations.js | 0 .../functions_and_calls/generator_function_values.js | 0 .../imports_and_exports/commonjs_imports_and_exports.js | 0 .../imports_and_exports/es6_imports_and_exports.js | 0 43 files changed, 0 insertions(+), 0 deletions(-) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/binding/default_arguments_from_enclosing_scope.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/binding/default_arguments_from_other_arguments.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/binding/destructuring_assignments.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/binding/destructuring_assignments_with_defaults_from_enclosing_scope.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/binding/destructuring_assignments_with_defaults_from_other_variables.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/binding/destructuring_parameters.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/binding/object_assignment_patterns.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/binding/simple.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/bug_regressions/2141.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/bug_regressions/2227.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/bug_regressions/2291.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/classes_and_instances/class_declaration.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/classes_and_instances/class_expression.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/classes_and_instances/class_expression_superclasses.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/classes_and_instances/class_expression_this_field_access.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/classes_and_instances/field_declaration.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/classes_and_instances/function_class_this_field_access.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/classes_and_instances/method_call_this_argument.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/classes_and_instances/method_definition.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/classes_and_instances/superclasses.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/classes_and_instances/this_field_access.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/compound_literals/arrays.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/compound_literals/object_extend_method.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/compound_literals/objects.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/control_flow_statements/dowhile.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/control_flow_statements/for.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/control_flow_statements/forin.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/control_flow_statements/if.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/control_flow_statements/try.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/control_flow_statements/while.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/control_flow_statements/with.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/functions_and_calls/arguments_variable.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/functions_and_calls/arrow_function_values_with_param_lists_and_block_bodies.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/functions_and_calls/arrow_function_values_with_param_lists_and_expr_bodies.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/functions_and_calls/arrow_function_values_with_single_param_and_block_bodies.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/functions_and_calls/arrow_function_values_with_single_param_and_expr_bodies.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/functions_and_calls/call_arguments.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/functions_and_calls/function_declarations.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/functions_and_calls/function_values.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/functions_and_calls/generator_function_declarations.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/functions_and_calls/generator_function_values.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/imports_and_exports/commonjs_imports_and_exports.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{old.skip => old}/imports_and_exports/es6_imports_and_exports.js (100%) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/default_arguments_from_enclosing_scope.js b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/default_arguments_from_enclosing_scope.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/default_arguments_from_enclosing_scope.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/binding/default_arguments_from_enclosing_scope.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/default_arguments_from_other_arguments.js b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/default_arguments_from_other_arguments.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/default_arguments_from_other_arguments.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/binding/default_arguments_from_other_arguments.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/destructuring_assignments.js b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/destructuring_assignments.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/destructuring_assignments_with_defaults_from_enclosing_scope.js b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments_with_defaults_from_enclosing_scope.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/destructuring_assignments_with_defaults_from_enclosing_scope.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments_with_defaults_from_enclosing_scope.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/destructuring_assignments_with_defaults_from_other_variables.js b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments_with_defaults_from_other_variables.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/destructuring_assignments_with_defaults_from_other_variables.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments_with_defaults_from_other_variables.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/destructuring_parameters.js b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_parameters.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/destructuring_parameters.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_parameters.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/object_assignment_patterns.js b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/object_assignment_patterns.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/object_assignment_patterns.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/binding/object_assignment_patterns.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/simple.js b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/simple.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/binding/simple.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/binding/simple.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/bug_regressions/2141.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/2141.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/bug_regressions/2141.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/2141.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/bug_regressions/2227.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/2227.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/bug_regressions/2227.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/2227.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/bug_regressions/2291.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/2291.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/bug_regressions/2291.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/2291.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/class_declaration.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_declaration.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/class_declaration.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_declaration.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/class_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_expression.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/class_expression.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_expression.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/class_expression_superclasses.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_expression_superclasses.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/class_expression_superclasses.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_expression_superclasses.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/class_expression_this_field_access.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_expression_this_field_access.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/class_expression_this_field_access.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/class_expression_this_field_access.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/field_declaration.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/field_declaration.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/field_declaration.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/field_declaration.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/function_class_this_field_access.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/function_class_this_field_access.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/function_class_this_field_access.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/function_class_this_field_access.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/method_call_this_argument.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/method_call_this_argument.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/method_call_this_argument.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/method_call_this_argument.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/method_definition.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/method_definition.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/method_definition.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/method_definition.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/superclasses.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/superclasses.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/superclasses.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/superclasses.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/this_field_access.js b/languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/this_field_access.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/classes_and_instances/this_field_access.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/classes_and_instances/this_field_access.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/compound_literals/arrays.js b/languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/arrays.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/compound_literals/arrays.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/arrays.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/compound_literals/object_extend_method.js b/languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/object_extend_method.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/compound_literals/object_extend_method.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/object_extend_method.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/compound_literals/objects.js b/languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/objects.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/compound_literals/objects.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/objects.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/dowhile.js b/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/dowhile.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/dowhile.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/dowhile.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/for.js b/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/for.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/for.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/for.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/forin.js b/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/forin.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/forin.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/forin.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/if.js b/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/if.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/if.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/if.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/try.js b/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/try.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/try.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/try.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/while.js b/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/while.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/while.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/while.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/with.js b/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/with.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/control_flow_statements/with.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/with.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arguments_variable.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arguments_variable.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arguments_variable.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arguments_variable.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arrow_function_values_with_param_lists_and_block_bodies.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_param_lists_and_block_bodies.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arrow_function_values_with_param_lists_and_block_bodies.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_param_lists_and_block_bodies.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arrow_function_values_with_param_lists_and_expr_bodies.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_param_lists_and_expr_bodies.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arrow_function_values_with_param_lists_and_expr_bodies.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_param_lists_and_expr_bodies.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arrow_function_values_with_single_param_and_block_bodies.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_single_param_and_block_bodies.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arrow_function_values_with_single_param_and_block_bodies.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_single_param_and_block_bodies.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arrow_function_values_with_single_param_and_expr_bodies.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_single_param_and_expr_bodies.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/arrow_function_values_with_single_param_and_expr_bodies.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/arrow_function_values_with_single_param_and_expr_bodies.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/call_arguments.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/call_arguments.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/call_arguments.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/call_arguments.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/function_declarations.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/function_declarations.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/function_declarations.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/function_declarations.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/function_values.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/function_values.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/function_values.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/function_values.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/generator_function_declarations.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/generator_function_declarations.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/generator_function_declarations.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/generator_function_declarations.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/generator_function_values.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/generator_function_values.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/functions_and_calls/generator_function_values.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/generator_function_values.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/imports_and_exports/commonjs_imports_and_exports.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/commonjs_imports_and_exports.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/imports_and_exports/commonjs_imports_and_exports.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/commonjs_imports_and_exports.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old.skip/imports_and_exports/es6_imports_and_exports.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/es6_imports_and_exports.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old.skip/imports_and_exports/es6_imports_and_exports.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/es6_imports_and_exports.js From 2c16b0afe1b97e1495e41b2b971993809c7f27f4 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 17:47:05 +0200 Subject: [PATCH 071/500] Fix test expectation --- .../test/old/binding/simple.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/binding/simple.js b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/simple.js index c0197e565..5f504b306 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/binding/simple.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/simple.js @@ -7,4 +7,4 @@ const z = 3; /**/ y; // ^ defined: 2 /**/ z; -// ^ defined: 1 \ No newline at end of file +// ^ defined: 3 \ No newline at end of file From 9e04e6029c958564eca84e868223bab4ff3d1206 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 17:50:03 +0200 Subject: [PATCH 072/500] Fix test expectation --- .../test/old/functions_and_calls/call_arguments.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/call_arguments.js b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/call_arguments.js index 864a78766..9ee96ece9 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/call_arguments.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/functions_and_calls/call_arguments.js @@ -2,6 +2,6 @@ let x = 1; let y = 2; let z = foo(x, y++, y); -// ^ defined: 1, 4 -// ^ defined: 2, 4, 4 -// ^ defined: 2, 4, 4 +// ^ defined: 1 +// ^ defined: 2 +// ^ defined: 2, 4 From dc7f04273408df022e5141f9692fb0eced87e8b4 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 17:54:03 +0200 Subject: [PATCH 073/500] Revert `GUARD:MEMBER` to `.` --- .../src/stack-graphs.tsg | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index d624dc7b1..7d8b0b983 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -1641,7 +1641,7 @@ inherit .return_or_yield edge @body.before_scope -> @object.after_scope edge @with_stmt.after_scope -> @body.after_scope - attr (@with_stmt.push_dot) push_symbol = "GUARD:MEMBER" + attr (@with_stmt.push_dot) push_symbol = "." edge @with_stmt.push_dot -> @object.value edge @body.before_scope -> @with_stmt.push_dot } @@ -1928,7 +1928,7 @@ inherit .return_or_yield (object)@object { - attr (@object.member_pop) pop_symbol = "GUARD:MEMBER" + attr (@object.member_pop) pop_symbol = "." edge @object.value -> @object.member_pop } @@ -2061,7 +2061,7 @@ inherit .return_or_yield (array)@array_expr { - attr (@array_expr.element_pop_dot) pop_symbol = "GUARD:MEMBER" + attr (@array_expr.element_pop_dot) pop_symbol = "." edge @array_expr.value -> @array_expr.element_pop_dot } @@ -2489,7 +2489,7 @@ inherit .return_or_yield edge @member_expr.after_scope -> @object.after_scope ; value is a member projection on the value of the object ie. a push then push dot - attr (member_push) push_symbol = "GUARD:MEMBER" + attr (member_push) push_symbol = "." attr (property_push) node_reference = @property edge property_push -> member_push edge @member_expr.value -> property_push @@ -2509,7 +2509,7 @@ inherit .return_or_yield edge @subscript_expr.after_scope -> @index.after_scope ; value is a subscript lookup, ie a push then push dot - attr (@subscript_expr.push_dot) push_symbol = "GUARD:MEMBER" + attr (@subscript_expr.push_dot) push_symbol = "." edge @subscript_expr.push_dot -> @object.value ; this is done differently depending on what the index is From be944eaa8262c335e56691327104a2c63e98979a Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 18:01:27 +0200 Subject: [PATCH 074/500] Don't make indices definitions --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 7d8b0b983..f6b669d72 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -2103,7 +2103,7 @@ inherit .return_or_yield node element_index_pop - attr (element_index_pop) symbol_definition = (named-child-index @element) + attr (element_index_pop) pop_symbol = (named-child-index @element) edge @array_expr.element_pop_dot -> element_index_pop edge element_index_pop -> @element.value From a2145cfac6c68fbb78a3cc2ed47290b2a3462f4d Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 18:01:53 +0200 Subject: [PATCH 075/500] Connect exports to existing @name.pop nodes --- .../src/stack-graphs.tsg | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index f6b669d72..4d9911fe1 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -276,8 +276,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.module_guard node @node.module_pop node @node.module_scope - node @node.name_pop - node @node.name_push node @node.new_bindings node @node.pop node @node.pop_dot @@ -479,14 +477,11 @@ inherit .return_or_yield (class_declaration name:(identifier)@name) (lexical_declaration (variable_declarator name:(identifier)@name)) (variable_declaration (variable_declarator name:(identifier)@name)) - ]@decl)@export_stmt { + ]@_decl)@export_stmt { ; TODO this doesn't support destructuring exports - attr (@name.pop) node_definition = @name - attr (@name.push) push_node = @name edge @export_stmt.exports -> @name.pop - edge @name.pop -> @decl.value } ; TODO @@ -912,9 +907,9 @@ inherit .return_or_yield (variable_declarator name:(identifier)@name))@variable_decl { - attr (@variable_decl.name_pop) node_definition = @name - edge @variable_decl.after_scope -> @variable_decl.name_pop - attr (@variable_decl.after_scope -> @variable_decl.name_pop) precedence = 1 + attr (@name.pop) node_definition = @name + edge @variable_decl.after_scope -> @name.pop + attr (@variable_decl.after_scope -> @name.pop) precedence = 1 } @@ -923,9 +918,9 @@ inherit .return_or_yield name:(identifier)@name))@lexical_decl { - attr (@lexical_decl.name_pop) node_definition = @name - edge @lexical_decl.after_scope -> @lexical_decl.name_pop - attr (@lexical_decl.after_scope -> @lexical_decl.name_pop) precedence = 1 + attr (@name.pop) node_definition = @name + edge @lexical_decl.after_scope -> @name.pop + attr (@lexical_decl.after_scope -> @name.pop) precedence = 1 } @@ -945,11 +940,11 @@ inherit .return_or_yield (variable_declaration (variable_declarator - name:(identifier)@_name + name:(identifier)@name value:(_)@initializer))@variable_decl { - edge @variable_decl.name_pop -> @initializer.value + edge @name.pop -> @initializer.value edge @initializer.before_scope -> @variable_decl.before_scope edge @variable_decl.after_scope -> @initializer.after_scope @@ -957,11 +952,11 @@ inherit .return_or_yield (lexical_declaration (variable_declarator - name:(identifier)@_name + name:(identifier)@name value:(_)@initializer))@lexical_decl { - edge @lexical_decl.name_pop -> @initializer.value + edge @name.pop -> @initializer.value edge @initializer.before_scope -> @lexical_decl.before_scope edge @lexical_decl.after_scope -> @initializer.after_scope attr (@lexical_decl.after_scope -> @initializer.after_scope) precedence = 0 From ff5fce9259f74e410f899e52e904693da8b1c350 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 18:06:03 +0200 Subject: [PATCH 076/500] adjust test expectations --- .../test/old/binding/destructuring_assignments.js | 4 ++-- .../test/old/compound_literals/objects.js | 4 ++-- .../test/old/imports_and_exports/es6_imports_and_exports.js | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments.js b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments.js index 9daed0d96..4fcaa1d7e 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/destructuring_assignments.js @@ -13,7 +13,7 @@ let [w, q] = [1,2]; w; -// ^ defined: 12, 13 +// ^ defined: 12 q; -// ^ defined: 13, 13 +// ^ defined: 13 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/objects.js b/languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/objects.js index d9a093743..fe5bf1c55 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/objects.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/objects.js @@ -11,5 +11,5 @@ let z = obj_z; // ^ defined: 1, 9 let obj2 = { x, y }; -// ^ defined: 1, 2, 3, 13 -// ^ defined: 1, 5, 6, 13 +// ^ defined: 1, 2, 3 +// ^ defined: 1, 5, 6 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/es6_imports_and_exports.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/es6_imports_and_exports.js index ae771b453..0508a5ee6 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/es6_imports_and_exports.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/es6_imports_and_exports.js @@ -72,7 +72,7 @@ import * as mod from "a_basic.js"; // ^ defined: 24, 24 mod.j; -// ^ defined: 25, 26 +// ^ defined: 25 mod.k; // ^ defined: 26, 26 From 297feec6e14a14476fd68a95823d2b13649d0a08 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 18:08:43 +0200 Subject: [PATCH 077/500] adjust test expectations --- .../test/old/control_flow_statements/for.js | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/for.js b/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/for.js index fa0fa36fd..aaca4ded4 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/for.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/control_flow_statements/for.js @@ -1,17 +1,19 @@ var x = 1; -for (let y = 2; x + y < 2; y++, x--) { - // ^ defined: 1, 11 - // ^ defined: 3, 12 - // ^ defined: 3, 12 - // ^ defined: 1, 11 +for (let y = 2; + x + y < 2; + //^ defined: 1, 7, 13 + // ^ defined: 3, 7, 14 + y++, x--) { + //^ defined: 3, 7, 14 + // ^ defined: 1, 7, 13 alert(x + y); - // ^ defined: 1, 11 - // ^ defined: 3, 12 + // ^ defined: 1, 7, 13 + // ^ defined: 3, 7, 14 x = 2; y = 3; } const z = x - y; -// ^ defined: 1, 11 -// ^ defined: 3, 12 +// ^ defined: 1, 7, 13 +// ^ defined: 3, 7, 14 From f8009e10bb86e04a7876745350cc55657a9391ce Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 12 Jul 2023 18:59:30 +0200 Subject: [PATCH 078/500] Add definiens_node and syntax_type attributes --- tree-sitter-stack-graphs/src/lib.rs | 73 ++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 21 deletions(-) diff --git a/tree-sitter-stack-graphs/src/lib.rs b/tree-sitter-stack-graphs/src/lib.rs index 47f97e82a..3f31b8700 100644 --- a/tree-sitter-stack-graphs/src/lib.rs +++ b/tree-sitter-stack-graphs/src/lib.rs @@ -364,6 +364,7 @@ static SCOPE_TYPE: &'static str = "scope"; // Node attribute names static DEBUG_ATTR_PREFIX: &'static str = "debug_"; +static DEFINIENS_NODE_ATTR: &'static str = "definiens_node"; static EMPTY_SOURCE_SPAN_ATTR: &'static str = "empty_source_span"; static IS_DEFINITION_ATTR: &'static str = "is_definition"; static IS_ENDPOINT_ATTR: &'static str = "is_endpoint"; @@ -372,13 +373,28 @@ static IS_REFERENCE_ATTR: &'static str = "is_reference"; static SCOPE_ATTR: &'static str = "scope"; static SOURCE_NODE_ATTR: &'static str = "source_node"; static SYMBOL_ATTR: &'static str = "symbol"; +static SYNTAX_TYPE_ATTR: &'static str = "syntax_type"; static TYPE_ATTR: &'static str = "type"; // Expected attributes per node type -static POP_SCOPED_SYMBOL_ATTRS: Lazy> = - Lazy::new(|| HashSet::from([TYPE_ATTR, SYMBOL_ATTR, IS_DEFINITION_ATTR])); -static POP_SYMBOL_ATTRS: Lazy> = - Lazy::new(|| HashSet::from([TYPE_ATTR, SYMBOL_ATTR, IS_DEFINITION_ATTR])); +static POP_SCOPED_SYMBOL_ATTRS: Lazy> = Lazy::new(|| { + HashSet::from([ + TYPE_ATTR, + SYMBOL_ATTR, + IS_DEFINITION_ATTR, + DEFINIENS_NODE_ATTR, + SYNTAX_TYPE_ATTR, + ]) +}); +static POP_SYMBOL_ATTRS: Lazy> = Lazy::new(|| { + HashSet::from([ + TYPE_ATTR, + SYMBOL_ATTR, + IS_DEFINITION_ATTR, + DEFINIENS_NODE_ATTR, + SYNTAX_TYPE_ATTR, + ]) +}); static PUSH_SCOPED_SYMBOL_ATTRS: Lazy> = Lazy::new(|| HashSet::from([TYPE_ATTR, SYMBOL_ATTR, SCOPE_ATTR, IS_REFERENCE_ATTR])); static PUSH_SYMBOL_ATTRS: Lazy> = @@ -881,7 +897,7 @@ impl<'a> Builder<'a> { NodeType::PushSymbol => self.load_push_symbol(node_ref)?, NodeType::Scope => self.load_scope(node_ref)?, }; - self.load_span(node_ref, handle)?; + self.load_source_info(node_ref, handle)?; self.load_node_debug_info(node_ref, handle)?; } @@ -1087,28 +1103,43 @@ impl<'a> Builder<'a> { } } - fn load_span( + fn load_source_info( &mut self, node_ref: GraphNodeRef, node_handle: Handle, ) -> Result<(), BuildError> { let node = &self.graph[node_ref]; - let source_node = match node.attributes.get(SOURCE_NODE_ATTR) { - Some(source_node) => &self.graph[source_node.as_syntax_node_ref()?], - None => return Ok(()), - }; - let mut span = self.span_calculator.for_node(source_node); - if match node.attributes.get(EMPTY_SOURCE_SPAN_ATTR) { - Some(empty_source_span) => empty_source_span.as_boolean()?, - None => false, - } { - span.end = span.start.clone(); + + if let Some(source_node) = node.attributes.get(SOURCE_NODE_ATTR) { + let source_node = &self.graph[source_node.as_syntax_node_ref()?]; + let mut source_span = self.span_calculator.for_node(source_node); + if match node.attributes.get(EMPTY_SOURCE_SPAN_ATTR) { + Some(empty_source_span) => empty_source_span.as_boolean()?, + None => false, + } { + source_span.end = source_span.start.clone(); + } + let containing_line = &self.source[source_span.start.containing_line.clone()]; + let containing_line = self.stack_graph.add_string(containing_line); + let source_info = self.stack_graph.source_info_mut(node_handle); + source_info.span = source_span; + source_info.containing_line = ControlledOption::some(containing_line); + } + + if let Some(syntax_type) = node.attributes.get(SYNTAX_TYPE_ATTR) { + let syntax_type = syntax_type.as_str()?; + let syntax_type = self.stack_graph.add_string(syntax_type); + let source_info = self.stack_graph.source_info_mut(node_handle); + source_info.syntax_type = syntax_type.into(); + } + + if let Some(definiens_node) = node.attributes.get(DEFINIENS_NODE_ATTR) { + let definiens_node = &self.graph[definiens_node.as_syntax_node_ref()?]; + let definiens_span = self.span_calculator.for_node(definiens_node); + let source_info = self.stack_graph.source_info_mut(node_handle); + source_info.definiens_span = definiens_span; } - let containing_line = &self.source[span.start.containing_line.clone()]; - let containing_line = self.stack_graph.add_string(containing_line); - let source_info = self.stack_graph.source_info_mut(node_handle); - source_info.span = span; - source_info.containing_line = ControlledOption::some(containing_line); + Ok(()) } From 9465fbc19e18a5efc2439dba660be77f1655a1a2 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Wed, 12 Jul 2023 16:01:36 -0700 Subject: [PATCH 079/500] Re-adds organizational whitespace --- .../src/stack-graphs.tsg | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 4d9911fe1..0a5ba6651 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -317,6 +317,15 @@ inherit .builtins_undefined inherit .exports inherit .return_or_yield + + + + + + + + + ;; ██████ ██████ ██████ ██████ ██████ █████ ███ ███ ███████ ;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ████ ██ ;; ██████ ██████ ██ ██ ██ ███ ██████ ███████ ██ ████ ██ ███████ @@ -408,6 +417,13 @@ inherit .return_or_yield + + + + + + + ;; ███████ ████████ █████ ████████ ███████ ███ ███ ███████ ███ ██ ████████ ███████ ;; ██ ██ ██ ██ ██ ██ ████ ████ ██ ████ ██ ██ ██ ;; ███████ ██ ███████ ██ █████ ██ ████ ██ █████ ██ ██ ██ ██ ███████ @@ -421,6 +437,8 @@ inherit .return_or_yield ;; ### Statement Queries + + ;; ███████ ██ ██ ██████ ██████ ██████ ████████ ███████ ;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ;; █████ ███ ██████ ██ ██ ██████ ██ ███████ @@ -1737,6 +1755,13 @@ inherit .return_or_yield + + + + + + + ;; ███████ ██ ██ ██████ ██████ ███████ ███████ ███████ ██ ██████ ███ ██ ███████ ;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ;; █████ ███ ██████ ██████ █████ ███████ ███████ ██ ██ ██ ██ ██ ██ ███████ @@ -2809,6 +2834,13 @@ inherit .return_or_yield + + + + + + + ;; ██████ █████ ████████ ████████ ███████ ██████ ███ ██ ███████ ;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ;; ██████ ███████ ██ ██ █████ ██████ ██ ██ ██ ███████ @@ -3280,6 +3312,13 @@ inherit .return_or_yield + + + + + + + ;; ███████ ██████ ███████ ██████ ██ █████ ██ ;; ██ ██ ██ ██ ██ ██ ██ ██ ██ ;; ███████ ██████ █████ ██ ██ ███████ ██ @@ -3396,6 +3435,14 @@ inherit .return_or_yield } + + + + + + + + ;; ██████ ███████ ███████ ██ ███ ██ ██ ███████ ███ ██ ███████ ;; ██ ██ ██ ██ ██ ████ ██ ██ ██ ████ ██ ██ ;; ██ ██ █████ █████ ██ ██ ██ ██ ██ █████ ██ ██ ██ ███████ From 8622de8d85bb8657d1fb1e9d44a7407995c9140b Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 13 Jul 2023 14:35:25 -0700 Subject: [PATCH 080/500] Pushes after_scope down into lower positions --- .../src/stack-graphs.tsg | 150 +++++++++++++++++- 1 file changed, 149 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 0a5ba6651..a5ff21427 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -231,7 +231,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ## Nodes (_)@node { - node @node.after_scope + ; node @node.after_scope !!!! TODO REMOVE node @node.arg_arguments node @node.arg_arguments_dot node @node.arg_index @@ -337,6 +337,10 @@ inherit .return_or_yield ;; ### Attributes Defined on Programs ;; TODO +(program)@prog { + node @prog.after_scope +} + ;; ### Program Queries (program)@prog { @@ -408,10 +412,12 @@ inherit .return_or_yield } (hash_bang_line)@hashbang { + node @hashbang.after_scope edge @hashbang.after_scope -> @hashbang.before_scope } (comment)@comment { + node @comment.after_scope edge @comment.after_scope -> @comment.before_scope } @@ -435,6 +441,35 @@ inherit .return_or_yield ;; ### Attributes Defined on Statements ;; TODO +[ + (export_statement) + (import_statement) + (debugger_statement) + (expression_statement) + (function_declaration) + (generator_function_declaration) + (class_declaration) + (lexical_declaration) + (variable_declaration) + (statement_block) + (if_statement) + (switch_statement) + (for_statement) + (for_in_statement) + (while_statement) + (do_statement) + (try_statement) + (with_statement) + (break_statement) + (continue_statement) + (return_statement) + (throw_statement) + (empty_statement) + (labeled_statement) +]@stmt { + node @stmt.after_scope +} + ;; ### Statement Queries @@ -524,6 +559,10 @@ inherit .return_or_yield } +(export_clause)@export_clause { + node @export_clause.after_scope +} + ; LATER-TODO tree sitter doesn't yet support empty switch bodies ; THIS IS A HUGE HACK AND MUST BE FIXED (export_clause)@export_clause { @@ -559,6 +598,7 @@ inherit .return_or_yield } (export_specifier)@export_specifier { + node @export_specifier.after_scope edge @export_specifier.after_scope -> @export_specifier.before_scope } @@ -707,6 +747,10 @@ inherit .return_or_yield edge @import_stmt.after_scope -> @import_stmt.before_scope } +(import_clause)@import_clause { + node @import_clause.after_scope +} + ; import * as name from "module-name"; (import_clause (namespace_import)@namespace_import)@import_clause { @@ -718,6 +762,7 @@ inherit .return_or_yield (namespace_import (identifier)@imported_as)@namespace_import { + node @namespace_import.after_scope edge @namespace_import.after_scope -> @namespace_import.before_scope attr (@imported_as.pop) node_definition = @imported_as @@ -762,6 +807,10 @@ inherit .return_or_yield } +(named_imports)@named_imports { + node @named_imports.after_scope +} + ; LATER-TODO tree sitter doesn't yet support empty named imports ; THIS IS A HUGE HACK AND MUST BE FIXED (named_imports)@named_imports { @@ -796,6 +845,10 @@ inherit .return_or_yield edge @named_imports.after_scope -> @last_import.after_scope } +(import_specifier)@import_specifier { + node @import_specifier.after_scope +} + ( (import_specifier @@ -925,6 +978,7 @@ inherit .return_or_yield (variable_declarator name:(identifier)@name))@variable_decl { + attr (@name.pop) node_definition = @name edge @variable_decl.after_scope -> @name.pop attr (@variable_decl.after_scope -> @name.pop) precedence = 1 @@ -1150,6 +1204,8 @@ inherit .return_or_yield name:(_)@name body:(_)@body)@class_decl { + node @class_decl.class_value + attr (@name.pop) syntax_type = "class" attr (@name.pop) node_definition = @name @@ -1172,6 +1228,7 @@ inherit .return_or_yield ; LATER-TODO tree sitter doesn't yet support empty switch bodies ; THIS IS A HUGE HACK AND MUST BE FIXED (class_body)@class_body { + node @class_body.after_scope edge @class_body.after_scope -> @class_body.before_scope } @@ -1197,6 +1254,11 @@ inherit .return_or_yield edge @class_body.after_scope -> @last_decl.after_scope } +(method_definition)@method_def { + + node @method_def.after_scope + +} ( (method_definition @@ -1276,6 +1338,7 @@ inherit .return_or_yield (field_definition property:(property_identifier)@property)@field_def { + node @field_def.after_scope attr (@property.pop) node_definition = @property attr (@property.pop_dot) pop_symbol = "." edge @field_def.after_scope -> @property.pop_dot @@ -1357,6 +1420,7 @@ inherit .return_or_yield } (else_clause (_)@inner)@else_clause { + node @else_clause.after_scope ; scopes flow in and right back out edge @inner.before_scope -> @else_clause.before_scope edge @else_clause.after_scope -> @inner.after_scope @@ -1380,6 +1444,7 @@ inherit .return_or_yield ; LATER-TODO tree sitter doesn't yet support empty switch bodies ; THIS IS A HUGE HACK AND MUST BE FIXED (switch_body)@switch_body { + node @switch_body.after_scope edge @switch_body.after_scope -> @switch_body.before_scope } @@ -1411,6 +1476,10 @@ inherit .return_or_yield edge @switch_body.after_scope -> @last_choice.after_scope } +(switch_case)@switch_case { + node @switch_case.after_scope +} + ; LATER-TODO tree sitter doesnt yet support switch case's with no statements ; THIS IS A HUGE HACK AND MUST BE FIXED (switch_case)@switch_case { @@ -1449,6 +1518,10 @@ inherit .return_or_yield edge @switch_case.after_scope -> @last_stmt.after_scope } +(switch_default)@switch_default { + node @switch_default.after_scope +} + ; LATER-TODO tree sitter doesnt yet support empty defaults ; THIS IS A HUGE HACK AND MUST BE FIXED (switch_default)@switch_default { @@ -1619,6 +1692,7 @@ inherit .return_or_yield } (catch_clause body:(_)@body)@catch_clause { + node @catch_clause.after_scope ; scopes flow in then back out edge @body.before_scope -> @catch_clause.before_scope edge @catch_clause.after_scope -> @body.after_scope @@ -1635,6 +1709,7 @@ inherit .return_or_yield } (finally_clause body:(_)@body)@finally_clause { + node @finally_clause.after_scope ; scopes flow in thenback out edge @body.before_scope -> @finally_clause.before_scope edge @finally_clause.after_scope -> @body.after_scope @@ -1773,6 +1848,46 @@ inherit .return_or_yield ;; ### Attributes Defined on Expressions ;; TODO +[ + (primary_expression/subscript_expression) + (primary_expression/member_expression) + (parenthesized_expression) + (undefined) + (primary_expression/identifier) + (this) + (super) + (number) + (string) + (template_string) + (regex) + (true) + (false) + (null) + (sequence_expression) + (import) + (object) + (array) + (function) + (arrow_function) + (generator_function) + (class) + (meta_property) + (call_expression) + (assignment_expression) + (augmented_assignment_expression) + (await_expression) + (unary_expression) + (binary_expression) + (ternary_expression) + (update_expression) + (new_expression) + (yield_expression) +]@expr { + + node @expr.after_scope + +} + ;; ### Expression Queries @@ -1987,6 +2102,12 @@ inherit .return_or_yield } ; shorthand property identifier +(shorthand_property_identifier)@shorthand_property_identifier { + + node @shorthand_property_identifier.after_scope + +} + (object (shorthand_property_identifier)@keyval)@object { node rhsvar_before_scope @@ -2013,6 +2134,7 @@ inherit .return_or_yield (computed_property_name (_)@expr)@computed_property_name { + node @computed_property_name.after_scope edge @expr.before_scope -> @computed_property_name.before_scope edge @computed_property_name.after_scope -> @expr.after_scope @@ -2033,6 +2155,10 @@ inherit .return_or_yield } +(pair)@pair { + node @pair.after_scope +} + (pair key:(property_identifier)@key value:(_)@value)@pair @@ -2138,6 +2264,7 @@ inherit .return_or_yield ; THIS IS A HUGE HACK AND MUST BE FIXED (formal_parameters)@formal_params { + node @formal_params.after_scope edge @formal_params.after_scope -> @formal_params.before_scope } @@ -2300,6 +2427,8 @@ inherit .return_or_yield (arrow_function parameter:(_)@param)@fun { + node @param.after_scope + ; scope flows from the param right back out edge @param.after_scope -> @param.before_scope @@ -2465,6 +2594,7 @@ inherit .return_or_yield ; LATER-TODO currently unsupported by tree sitter queries ; THIS IS A HUGE HACK AND MUST BE FIXED (arguments)@arguments { + node @arguments.after_scope edge @arguments.after_scope -> @arguments.before_scope } @@ -3079,6 +3209,24 @@ inherit .return_or_yield ;; ### Attributes Defined on Patterns ;; TODO +[ + (pattern/member_expression)@pattern + (pattern/subscript_expression)@pattern + (assignment_expression left:(_)@pattern) + (assignment_pattern)@pattern + (object_pattern)@pattern + (array_pattern)@pattern + (rest_pattern)@pattern + (pair_pattern)@pattern + (pattern/identifier)@pattern + (pattern/property_identifier)@pattern + (object_assignment_pattern)@pattern + (shorthand_property_identifier_pattern)@pattern +] { + + node @pattern.after_scope + +} ;; ### Pattern Queries From dc6d6468e1f64d328484ab328c3c1dcc69fc7638 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Mon, 17 Jul 2023 16:35:56 -0700 Subject: [PATCH 081/500] Adds before_scope --- .../src/stack-graphs.tsg | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index a5ff21427..053f743c5 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -240,7 +240,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.arg_this node @node.arguments_pop node @node.arguments_push - node @node.before_scope + ; node @node.before_scope !!!! TODO REMOVE node @node.boundvar_pop node @node.call node @node.constructor @@ -339,6 +339,7 @@ inherit .return_or_yield (program)@prog { node @prog.after_scope + node @prog.before_scope } ;; ### Program Queries @@ -413,11 +414,13 @@ inherit .return_or_yield (hash_bang_line)@hashbang { node @hashbang.after_scope + node @hashbang.before_scope edge @hashbang.after_scope -> @hashbang.before_scope } (comment)@comment { node @comment.after_scope + node @comment.before_scope edge @comment.after_scope -> @comment.before_scope } @@ -468,6 +471,7 @@ inherit .return_or_yield (labeled_statement) ]@stmt { node @stmt.after_scope + node @stmt.before_scope } ;; ### Statement Queries @@ -561,6 +565,7 @@ inherit .return_or_yield (export_clause)@export_clause { node @export_clause.after_scope + node @export_clause.before_scope } ; LATER-TODO tree sitter doesn't yet support empty switch bodies @@ -599,6 +604,7 @@ inherit .return_or_yield (export_specifier)@export_specifier { node @export_specifier.after_scope + node @export_specifier.before_scope edge @export_specifier.after_scope -> @export_specifier.before_scope } @@ -749,6 +755,7 @@ inherit .return_or_yield (import_clause)@import_clause { node @import_clause.after_scope + node @import_clause.before_scope } ; import * as name from "module-name"; @@ -763,6 +770,7 @@ inherit .return_or_yield (namespace_import (identifier)@imported_as)@namespace_import { node @namespace_import.after_scope + node @namespace_import.before_scope edge @namespace_import.after_scope -> @namespace_import.before_scope attr (@imported_as.pop) node_definition = @imported_as @@ -809,6 +817,7 @@ inherit .return_or_yield (named_imports)@named_imports { node @named_imports.after_scope + node @named_imports.before_scope } ; LATER-TODO tree sitter doesn't yet support empty named imports @@ -847,6 +856,7 @@ inherit .return_or_yield (import_specifier)@import_specifier { node @import_specifier.after_scope + node @import_specifier.before_scope } ( @@ -1229,6 +1239,7 @@ inherit .return_or_yield ; THIS IS A HUGE HACK AND MUST BE FIXED (class_body)@class_body { node @class_body.after_scope + node @class_body.before_scope edge @class_body.after_scope -> @class_body.before_scope } @@ -1257,6 +1268,7 @@ inherit .return_or_yield (method_definition)@method_def { node @method_def.after_scope + node @method_def.before_scope } @@ -1339,6 +1351,7 @@ inherit .return_or_yield property:(property_identifier)@property)@field_def { node @field_def.after_scope + node @field_def.before_scope attr (@property.pop) node_definition = @property attr (@property.pop_dot) pop_symbol = "." edge @field_def.after_scope -> @property.pop_dot @@ -1421,6 +1434,7 @@ inherit .return_or_yield (else_clause (_)@inner)@else_clause { node @else_clause.after_scope + node @else_clause.before_scope ; scopes flow in and right back out edge @inner.before_scope -> @else_clause.before_scope edge @else_clause.after_scope -> @inner.after_scope @@ -1445,6 +1459,7 @@ inherit .return_or_yield ; THIS IS A HUGE HACK AND MUST BE FIXED (switch_body)@switch_body { node @switch_body.after_scope + node @switch_body.before_scope edge @switch_body.after_scope -> @switch_body.before_scope } @@ -1478,6 +1493,7 @@ inherit .return_or_yield (switch_case)@switch_case { node @switch_case.after_scope + node @switch_case.before_scope } ; LATER-TODO tree sitter doesnt yet support switch case's with no statements @@ -1520,6 +1536,7 @@ inherit .return_or_yield (switch_default)@switch_default { node @switch_default.after_scope + node @switch_default.before_scope } ; LATER-TODO tree sitter doesnt yet support empty defaults @@ -1693,6 +1710,7 @@ inherit .return_or_yield (catch_clause body:(_)@body)@catch_clause { node @catch_clause.after_scope + node @catch_clause.before_scope ; scopes flow in then back out edge @body.before_scope -> @catch_clause.before_scope edge @catch_clause.after_scope -> @body.after_scope @@ -1710,6 +1728,7 @@ inherit .return_or_yield (finally_clause body:(_)@body)@finally_clause { node @finally_clause.after_scope + node @finally_clause.before_scope ; scopes flow in thenback out edge @body.before_scope -> @finally_clause.before_scope edge @finally_clause.after_scope -> @body.after_scope @@ -1885,6 +1904,7 @@ inherit .return_or_yield ]@expr { node @expr.after_scope + node @expr.before_scope } @@ -2105,6 +2125,7 @@ inherit .return_or_yield (shorthand_property_identifier)@shorthand_property_identifier { node @shorthand_property_identifier.after_scope + node @shorthand_property_identifier.before_scope } @@ -2135,6 +2156,7 @@ inherit .return_or_yield (computed_property_name (_)@expr)@computed_property_name { node @computed_property_name.after_scope + node @computed_property_name.before_scope edge @expr.before_scope -> @computed_property_name.before_scope edge @computed_property_name.after_scope -> @expr.after_scope @@ -2157,6 +2179,7 @@ inherit .return_or_yield (pair)@pair { node @pair.after_scope + node @pair.before_scope } (pair @@ -2265,6 +2288,7 @@ inherit .return_or_yield (formal_parameters)@formal_params { node @formal_params.after_scope + node @formal_params.before_scope edge @formal_params.after_scope -> @formal_params.before_scope } @@ -2428,6 +2452,7 @@ inherit .return_or_yield parameter:(_)@param)@fun { node @param.after_scope + node @param.before_scope ; scope flows from the param right back out edge @param.after_scope -> @param.before_scope @@ -2595,6 +2620,7 @@ inherit .return_or_yield ; THIS IS A HUGE HACK AND MUST BE FIXED (arguments)@arguments { node @arguments.after_scope + node @arguments.before_scope edge @arguments.after_scope -> @arguments.before_scope } @@ -3225,6 +3251,7 @@ inherit .return_or_yield ] { node @pattern.after_scope + node @pattern.before_scope } From a006cb7f1cfb028662744cea38a0bd06c67772e3 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Mon, 17 Jul 2023 17:00:05 -0700 Subject: [PATCH 082/500] Fix some issues with after/before_scopes --- .../src/stack-graphs.tsg | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 053f743c5..2be62dd7d 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -1868,8 +1868,8 @@ inherit .return_or_yield ;; TODO [ - (primary_expression/subscript_expression) - (primary_expression/member_expression) + (subscript_expression) + (member_expression) (parenthesized_expression) (undefined) (primary_expression/identifier) @@ -3236,9 +3236,7 @@ inherit .return_or_yield ;; ### Attributes Defined on Patterns ;; TODO [ - (pattern/member_expression)@pattern - (pattern/subscript_expression)@pattern - (assignment_expression left:(_)@pattern) + (assignment_expression left:(identifier)@pattern) (assignment_pattern)@pattern (object_pattern)@pattern (array_pattern)@pattern From fa721b8f88402913f5f9b2c343289f334261b549 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Mon, 17 Jul 2023 17:00:15 -0700 Subject: [PATCH 083/500] Lowers values --- .../src/stack-graphs.tsg | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 2be62dd7d..2e79ae24f 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -292,7 +292,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.string_prototype node @node.this_pop node @node.this_push - node @node.value + ; node @node.value node @node.value_arg_scope node @node.value_call node @node.value_drop @@ -421,6 +421,7 @@ inherit .return_or_yield (comment)@comment { node @comment.after_scope node @comment.before_scope + node @comment.value edge @comment.after_scope -> @comment.before_scope } @@ -1078,6 +1079,7 @@ inherit .return_or_yield parameters:(_)@call_sig body:(_)@body)@fun_decl { + node @fun_decl.function_value attr (@name.pop) syntax_type = "function" ; scope flows across the decl @@ -1086,7 +1088,7 @@ inherit .return_or_yield ; with an augmentation for the function attr (@name.pop) node_definition = @name edge @fun_decl.after_scope -> @name.pop - edge @name.pop -> @fun_decl.value + edge @name.pop -> @fun_decl.function_value ; function values have drop nodes that handle closures, that points to the ; before scope for the function @@ -1110,7 +1112,7 @@ inherit .return_or_yield ; function values have call nodes attr (@fun_decl.value_call) pop_scoped_symbol = "()" - edge @fun_decl.value -> @fun_decl.value_call + edge @fun_decl.function_value -> @fun_decl.value_call ; function values have return nodes which need to be visible for returns attr (@fun_decl.value_return) pop_symbol = "GUARD:RETURN" @@ -1146,6 +1148,7 @@ inherit .return_or_yield parameters:(_)@call_sig body:(_)@body)@fun_decl { + node @fun_decl.function_value attr (@name.pop) syntax_type = "function" ; scope flows across the decl @@ -1154,7 +1157,7 @@ inherit .return_or_yield ; with an augmentation for the function attr (@name.pop) node_definition = @name edge @fun_decl.after_scope -> @name.pop - edge @name.pop -> @fun_decl.value + edge @name.pop -> @fun_decl.function_value ; function values have drop nodes that handle closures, that points to the ; before scope of the declaration @@ -1178,7 +1181,7 @@ inherit .return_or_yield ; function values have call nodes attr (@fun_decl.value_call) pop_scoped_symbol = "()" - edge @fun_decl.value -> @fun_decl.value_call + edge @fun_decl.function_value -> @fun_decl.value_call ; function values have return nodes which need to be visible for returns attr (@fun_decl.value_return) pop_symbol = "GUARD:RETURN" @@ -1220,10 +1223,10 @@ inherit .return_or_yield attr (@name.pop) node_definition = @name edge @class_decl.after_scope -> @name.pop - edge @name.pop -> @class_decl.value + edge @name.pop -> @class_decl.class_value edge @body.before_scope -> @class_decl.before_scope - edge @class_decl.value -> @body.after_scope + edge @class_decl.class_value -> @body.after_scope edge @class_decl.after_scope -> @class_decl.before_scope } @@ -1231,7 +1234,7 @@ inherit .return_or_yield (class_heritage (_)@name))@class_decl { edge @name.before_scope -> @class_decl.before_scope - edge @class_decl.value -> @name.value + edge @class_decl.class_value -> @name.value } @@ -1905,6 +1908,7 @@ inherit .return_or_yield node @expr.after_scope node @expr.before_scope + node @expr.value } From 2fbd99cfb3794def2f86a2e5a21096bfecb9d174 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Mon, 17 Jul 2023 17:15:01 -0700 Subject: [PATCH 084/500] Lowers covalues --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 2e79ae24f..f7c4c0812 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -245,7 +245,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.call node @node.constructor node @node.constructor_guard - node @node.covalue + ; node @node.covalue !!!! TODO REMOVE node @node.default_guard node @node.definiens_hook node @node.drop @@ -2457,6 +2457,7 @@ inherit .return_or_yield node @param.after_scope node @param.before_scope + node @param.covalue ; scope flows from the param right back out edge @param.after_scope -> @param.before_scope @@ -3254,6 +3255,7 @@ inherit .return_or_yield node @pattern.after_scope node @pattern.before_scope + node @pattern.covalue } From c38d8fad9b43dac3b04279efb454899345340860 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Mon, 17 Jul 2023 17:16:38 -0700 Subject: [PATCH 085/500] Removes lowered vars --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 4 ---- 1 file changed, 4 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index f7c4c0812..faa3c5a53 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -231,7 +231,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ## Nodes (_)@node { - ; node @node.after_scope !!!! TODO REMOVE node @node.arg_arguments node @node.arg_arguments_dot node @node.arg_index @@ -240,12 +239,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.arg_this node @node.arguments_pop node @node.arguments_push - ; node @node.before_scope !!!! TODO REMOVE node @node.boundvar_pop node @node.call node @node.constructor node @node.constructor_guard - ; node @node.covalue !!!! TODO REMOVE node @node.default_guard node @node.definiens_hook node @node.drop @@ -292,7 +289,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.string_prototype node @node.this_pop node @node.this_push - ; node @node.value node @node.value_arg_scope node @node.value_call node @node.value_drop From 482dc986e928ebe246aaa6047661270e4c0808f1 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 18 Jul 2023 14:27:24 -0700 Subject: [PATCH 086/500] Lowers pop vars --- .../src/stack-graphs.tsg | 59 ++++++++++++++++--- 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index faa3c5a53..5eadf2b84 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -274,7 +274,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.module_pop node @node.module_scope node @node.new_bindings - node @node.pop node @node.pop_dot node @node.pop_guard_default node @node.push @@ -613,6 +612,7 @@ inherit .return_or_yield (#not-eq? @name "default") ) { + node @name.pop attr (@name.pop) node_definition = @name attr (@name.push) node_reference = @name edge @name.pop -> @name.push @@ -630,6 +630,7 @@ inherit .return_or_yield ) { + node @alias.pop attr (@alias.pop) node_definition = @alias attr (@name.push) node_reference = @name edge @alias.pop -> @name.push @@ -711,6 +712,8 @@ inherit .return_or_yield (namespace_export (_)@alias) source:(_)@source)@export_statement { + node @alias.pop + edge @export_statement.after_scope -> @export_statement.before_scope attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" @@ -766,6 +769,7 @@ inherit .return_or_yield (namespace_import (identifier)@imported_as)@namespace_import { + node @imported_as.pop node @namespace_import.after_scope node @namespace_import.before_scope edge @namespace_import.after_scope -> @namespace_import.before_scope @@ -866,6 +870,8 @@ inherit .return_or_yield ) { + node @name.pop + edge @import_specifier.after_scope -> @import_specifier.before_scope attr (@name.pop) node_definition = @name @@ -886,6 +892,8 @@ inherit .return_or_yield ) { + node @alias.pop + edge @import_specifier.after_scope -> @import_specifier.before_scope attr (@alias.pop) node_definition = @alias @@ -932,6 +940,8 @@ inherit .return_or_yield (import_clause (identifier)@default_name)@import_clause { + node @default_name.pop + edge @import_clause.after_scope -> @import_clause.before_scope attr (@default_name.pop) node_definition = @default_name @@ -986,6 +996,7 @@ inherit .return_or_yield name:(identifier)@name))@variable_decl { + node @name.pop attr (@name.pop) node_definition = @name edge @variable_decl.after_scope -> @name.pop attr (@variable_decl.after_scope -> @name.pop) precedence = 1 @@ -997,6 +1008,7 @@ inherit .return_or_yield name:(identifier)@name))@lexical_decl { + node @name.pop attr (@name.pop) node_definition = @name edge @lexical_decl.after_scope -> @name.pop attr (@lexical_decl.after_scope -> @name.pop) precedence = 1 @@ -1075,6 +1087,7 @@ inherit .return_or_yield parameters:(_)@call_sig body:(_)@body)@fun_decl { + node @name.pop node @fun_decl.function_value attr (@name.pop) syntax_type = "function" @@ -1144,6 +1157,7 @@ inherit .return_or_yield parameters:(_)@call_sig body:(_)@body)@fun_decl { + node @name.pop node @fun_decl.function_value attr (@name.pop) syntax_type = "function" @@ -1213,6 +1227,7 @@ inherit .return_or_yield name:(_)@name body:(_)@body)@class_decl { + node @name.pop node @class_decl.class_value attr (@name.pop) syntax_type = "class" @@ -1264,8 +1279,9 @@ inherit .return_or_yield edge @class_body.after_scope -> @last_decl.after_scope } -(method_definition)@method_def { +(method_definition name:(_)@name)@method_def { + node @name.pop node @method_def.after_scope node @method_def.before_scope @@ -1287,6 +1303,7 @@ inherit .return_or_yield name:(_)@name)@method_def (#not-eq? @name "constructor") ) { + ; augmentation for the method attr (@name.pop) node_definition = @name attr (@name.pop_dot) pop_symbol = "." @@ -1351,6 +1368,8 @@ inherit .return_or_yield node @field_def.after_scope node @field_def.before_scope + node @property.pop + attr (@property.pop) node_definition = @property attr (@property.pop_dot) pop_symbol = "." edge @field_def.after_scope -> @property.pop_dot @@ -1620,6 +1639,7 @@ inherit .return_or_yield body:(_)@body)@for_in_stmt { + node @for_in_stmt.pop attr (@for_in_stmt.pop) node_definition = @left edge @for_in_stmt.pop -> @right.value edge @body.before_scope -> @for_in_stmt.pop @@ -1720,6 +1740,7 @@ inherit .return_or_yield body:(_)@body)@catch_clause { + node @catch_clause.pop attr (@catch_clause.pop) node_definition = @name edge @body.before_scope -> @catch_clause.pop @@ -2196,6 +2217,8 @@ inherit .return_or_yield } (pair key:(string)@key) { + + node @key.pop attr (@key.pop) pop_symbol = (replace (source-text @key) "\"" "") } @@ -2328,6 +2351,7 @@ inherit .return_or_yield name:(_)@name parameters:(_)@call_sig)@fun { + node @name.pop attr (@name.pop) syntax_type = "function" ; if the function has a name, this is bound the callsig's before scope @@ -2454,6 +2478,7 @@ inherit .return_or_yield node @param.after_scope node @param.before_scope node @param.covalue + node @param.pop ; scope flows from the param right back out edge @param.after_scope -> @param.before_scope @@ -2488,6 +2513,7 @@ inherit .return_or_yield name:(_)@name parameters:(_)@call_sig)@fun { + node @name.pop attr (@name.pop) syntax_type = "function" ; if the function has a name, this is bound the callsig's before scope @@ -2776,16 +2802,19 @@ inherit .return_or_yield ;; #### Update Expressions (update_expression argument: (_)@argument)@update_expr { + + node @update_expr.pop ; scope propagates through the operand then is updated by the expr edge @argument.before_scope -> @update_expr.before_scope edge @update_expr.after_scope -> @argument.after_scope ; LATER-TODO this isn't quite right because the update argument can't be an arbitrary expr ; eg f(x)++ doesn't make any sense, you have to have something more like ; (update_expression argument: (lvar)@argument) - attr (@update_expr.pop) node_definition = @argument + attr (@update_expr.pop) node_definition = @argument edge @update_expr.value -> @argument.value - edge @update_expr.after_scope -> @update_expr.pop - edge @update_expr.pop -> @argument.value + edge @update_expr.after_scope -> @update_expr.pop + edge @update_expr.pop -> @argument.value + } @@ -2844,6 +2873,8 @@ inherit .return_or_yield left: (identifier)@left right: (_)@right)@assignment_expr { + node @assignment_expr.pop + ; augments the scope by adding a lookup edge, ie. a pop attr (@assignment_expr.pop) node_definition = @left edge @assignment_expr.after_scope -> @assignment_expr.pop @@ -2860,6 +2891,9 @@ inherit .return_or_yield property:(_)@property) right: (_)@right)@assignment_expr { + node @property.pop + node @this.pop + ; HACK attr (@this.drop) type = "drop_scopes" edge @this.drop -> @this.pop @@ -2900,6 +2934,8 @@ inherit .return_or_yield left:(identifier)@left right:(_)@right)@augmented_assignment_expr { + node @augmented_assignment_expr.pop + ; augment the scope attr (@augmented_assignment_expr.pop) node_definition = @left attr (@augmented_assignment_expr.push) node_reference = @left @@ -2975,6 +3011,7 @@ inherit .return_or_yield name:(_)@name body:(_)@body)@class { + node @name.pop attr (@name.pop) syntax_type = "class" attr (@name.pop) node_definition = @name @@ -3262,6 +3299,8 @@ inherit .return_or_yield ; scope propagation through identifier patterns (pattern/identifier)@ident_pat { + node @ident_pat.pop + ; scope flows through, binding via a pop edge that goes to an unknown value attr (@ident_pat.pop) node_definition = @ident_pat edge @ident_pat.pop -> @ident_pat.covalue @@ -3380,6 +3419,8 @@ inherit .return_or_yield left:(shorthand_property_identifier_pattern)@left_pat right:(_)@_right_expr)@object_assignment_pat { + node @left_pat.pop + edge @left_pat.after_scope -> @left_pat.before_scope attr (@left_pat.push) node_reference = @left_pat @@ -3531,6 +3572,7 @@ inherit .return_or_yield (#eq? @_extend "extend") ) { + node @object.pop attr (@object.pop) node_definition = @object edge @call_expr.after_scope -> @object.pop edge @object.pop -> @new_fields.value @@ -3563,6 +3605,7 @@ inherit .return_or_yield (#eq? @_exports "exports") ) { + node @property.pop attr (@property.pop) node_definition = @property attr (@property.pop_dot) pop_symbol = "." edge @assignment_expr.exports -> @property.pop_dot @@ -3708,14 +3751,14 @@ inherit .return_or_yield ;; kinds of definitions. (assignment_expression - left: (identifier)@left + left: (identifier)@_left right: [ (function) (generator_function) (arrow_function) - ]@right) { + ]@right)@assignment_expr { - attr (@left.pop) definiens_node = @right + attr (@assignment_expr.pop) definiens_node = @right } From 139b48f5f76af15d3d68f16e503f8575330e9e1c Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 18 Jul 2023 15:33:01 -0700 Subject: [PATCH 087/500] Lowers pop_dot --- .../src/stack-graphs.tsg | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 5eadf2b84..bdb4cef32 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -274,7 +274,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.module_pop node @node.module_scope node @node.new_bindings - node @node.pop_dot + ;; node @node.pop_dot node @node.pop_guard_default node @node.push node @node.push_dot @@ -713,6 +713,7 @@ inherit .return_or_yield source:(_)@source)@export_statement { node @alias.pop + node @alias.pop_dot edge @export_statement.after_scope -> @export_statement.before_scope @@ -770,6 +771,7 @@ inherit .return_or_yield (namespace_import (identifier)@imported_as)@namespace_import { node @imported_as.pop + node @imported_as.pop_dot node @namespace_import.after_scope node @namespace_import.before_scope edge @namespace_import.after_scope -> @namespace_import.before_scope @@ -1304,6 +1306,7 @@ inherit .return_or_yield (#not-eq? @name "constructor") ) { + node @name.pop_dot ; augmentation for the method attr (@name.pop) node_definition = @name attr (@name.pop_dot) pop_symbol = "." @@ -1369,6 +1372,7 @@ inherit .return_or_yield node @field_def.after_scope node @field_def.before_scope node @property.pop + node @property.pop_dot attr (@property.pop) node_definition = @property attr (@property.pop_dot) pop_symbol = "." @@ -2893,6 +2897,7 @@ inherit .return_or_yield node @property.pop node @this.pop + node @this.pop_dot ; HACK attr (@this.drop) type = "drop_scopes" @@ -3606,6 +3611,7 @@ inherit .return_or_yield ) { node @property.pop + node @property.pop_dot attr (@property.pop) node_definition = @property attr (@property.pop_dot) pop_symbol = "." edge @assignment_expr.exports -> @property.pop_dot From cb54a988139e9aa1604863d438177f6f8a3f5e39 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 18 Jul 2023 15:33:23 -0700 Subject: [PATCH 088/500] Removes old pop_dot --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 1 - 1 file changed, 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index bdb4cef32..7bc189e76 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -274,7 +274,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.module_pop node @node.module_scope node @node.new_bindings - ;; node @node.pop_dot node @node.pop_guard_default node @node.push node @node.push_dot From a86ab1bbd8b768f259ea61aae3c65bae43a1e126 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 18 Jul 2023 15:53:43 -0700 Subject: [PATCH 089/500] Lowers push and push_dot --- .../src/stack-graphs.tsg | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 7bc189e76..275e9a59c 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -275,8 +275,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.module_scope node @node.new_bindings node @node.pop_guard_default - node @node.push - node @node.push_dot node @node.push_exports_guard node @node.push_guard_default node @node.push_guard_exports @@ -499,6 +497,8 @@ inherit .return_or_yield (export_clause)@export_clause source:(_)@source)@export_stmt { + node @source.push + edge @export_clause.source -> @source.push_exports_guard attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" @@ -612,6 +612,8 @@ inherit .return_or_yield ) { node @name.pop + node @name.push + attr (@name.pop) node_definition = @name attr (@name.push) node_reference = @name edge @name.pop -> @name.push @@ -630,6 +632,8 @@ inherit .return_or_yield ) { node @alias.pop + node @name.push + attr (@alias.pop) node_definition = @alias attr (@name.push) node_reference = @name edge @alias.pop -> @name.push @@ -664,6 +668,8 @@ inherit .return_or_yield ) { + node @name.push + attr (@name.push) push_node = @name attr (@export_specifier.guard_default) pop_symbol = "GUARD:DEFAULT" edge @name.push -> @export_specifier.source @@ -690,6 +696,8 @@ inherit .return_or_yield . source:(_)@source)@export_statement { + node @source.push + edge @export_statement.after_scope -> @export_statement.before_scope attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" @@ -713,6 +721,7 @@ inherit .return_or_yield node @alias.pop node @alias.pop_dot + node @source.push edge @export_statement.after_scope -> @export_statement.before_scope @@ -793,6 +802,8 @@ inherit .return_or_yield (import_clause)@import_clause source:(_)@source)@import_stmt { + node @source.push + edge @import_clause.before_scope -> @import_stmt.before_scope edge @import_stmt.after_scope -> @import_clause.after_scope @@ -872,6 +883,7 @@ inherit .return_or_yield ) { node @name.pop + node @name.push edge @import_specifier.after_scope -> @import_specifier.before_scope @@ -894,6 +906,7 @@ inherit .return_or_yield ) { node @alias.pop + node @name.push edge @import_specifier.after_scope -> @import_specifier.before_scope @@ -1766,6 +1779,8 @@ inherit .return_or_yield body:(_)@body)@with_stmt { + node @with_stmt.push_dot + ; scopes flow from the statement into the object then into the body then back out edge @object.before_scope -> @with_stmt.before_scope edge @body.before_scope -> @object.after_scope @@ -2709,6 +2724,8 @@ inherit .return_or_yield object: (_)@object index: (_)@index)@subscript_expr { + node @subscript_expr.push_dot + ; scopes flow left to right edge @object.before_scope -> @subscript_expr.before_scope edge @index.before_scope -> @object.after_scope @@ -2939,6 +2956,7 @@ inherit .return_or_yield right:(_)@right)@augmented_assignment_expr { node @augmented_assignment_expr.pop + node @augmented_assignment_expr.push ; augment the scope attr (@augmented_assignment_expr.pop) node_definition = @left @@ -3367,6 +3385,9 @@ inherit .return_or_yield key:(_)@key value:(_)@value_pat)@pair_pat { + node @key.push + node @key.push_dot + ; covalues flow in dotted attr (@key.push_dot) push_symbol = "." edge @value_pat.covalue -> @key.push @@ -3424,6 +3445,8 @@ inherit .return_or_yield right:(_)@_right_expr)@object_assignment_pat { node @left_pat.pop + node @left_pat.push + node @left_pat.push_dot edge @left_pat.after_scope -> @left_pat.before_scope @@ -3650,6 +3673,8 @@ inherit .return_or_yield } } + node @mod_name.push + attr (@mod_name.module_guard) push_symbol = "GUARD:EXPORTS" edge @call_expr.value -> @mod_name.module_guard edge @mod_name.module_guard -> @mod_name.push From 221a9c6df9e14002b9b6593cbe28bf2503fdb4c0 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 18 Jul 2023 16:51:05 -0700 Subject: [PATCH 090/500] Lowers various arg vars --- .../src/stack-graphs.tsg | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 275e9a59c..611bb0959 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -231,12 +231,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ## Nodes (_)@node { - node @node.arg_arguments - node @node.arg_arguments_dot - node @node.arg_index - node @node.arg_scope - node @node.arg_scope_no_this - node @node.arg_this node @node.arguments_pop node @node.arguments_push node @node.boundvar_pop @@ -291,8 +285,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.value_return node @node.value_this node @node.value_this_guard - - attr (@node.arg_scope) is_exported } @@ -1157,6 +1149,8 @@ inherit .return_or_yield parameters: (formal_parameters (_)@param))@fun_decl { + node @param.arg_index + ; parameters jump to the pushed argument scope attr (@param.arg_index) push_symbol = (named-child-index @param) edge @param.covalue -> @param.arg_index @@ -1227,6 +1221,8 @@ inherit .return_or_yield parameters: (formal_parameters (_)@param))@fun_decl { + node @param.arg_index + ; parameters jump to the pushed argument scope attr (@param.arg_index) push_symbol = (named-child-index @param) edge @param.covalue -> @param.arg_index @@ -1370,6 +1366,8 @@ inherit .return_or_yield parameters: (formal_parameters (_)@param))@method_def { + node @param.arg_index + ; parameters jump to the pushed argument scope attr (@param.arg_index) push_symbol = (named-child-index @param) edge @param.covalue -> @param.arg_index @@ -2431,6 +2429,8 @@ inherit .return_or_yield parameters: (formal_parameters (_)@param))@fun { + node @param.arg_index + ; parameters jump to the pushed argument scope attr (@param.arg_index) push_symbol = (named-child-index @param) edge @param.covalue -> @param.arg_index @@ -2494,6 +2494,7 @@ inherit .return_or_yield parameter:(_)@param)@fun { node @param.after_scope + node @param.arg_index node @param.before_scope node @param.covalue node @param.pop @@ -2516,6 +2517,8 @@ inherit .return_or_yield parameters: (formal_parameters (_)@param))@fun { + node @param.arg_index + ; parameters jump to the pushed argument scope attr (@param.arg_index) push_symbol = (named-child-index @param) edge @param.covalue -> @param.arg_index @@ -2582,6 +2585,8 @@ inherit .return_or_yield parameters: (formal_parameters (_)@param))@fun { + node @param.arg_index + ; parameters jump to the pushed argument scope attr (@param.arg_index) push_symbol = (named-child-index @param) edge @param.covalue -> @param.arg_index @@ -2607,6 +2612,13 @@ inherit .return_or_yield function:(_)@function arguments:(_)@arguments)@call_expr { + node @arguments.arg_arguments + node @arguments.arg_arguments_dot + node @arguments.arg_scope + attr (@arguments.arg_scope) is_exported + node @arguments.arg_scope_no_this + node @arguments.arg_this + ; value is a call, ie a push "()" node w/ "push-scope" @arguments attr (@call_expr.return_guard) push_symbol = "GUARD:RETURN" attr (@call_expr.call) push_scoped_symbol = "()", scope = @arguments.arg_scope @@ -2652,6 +2664,7 @@ inherit .return_or_yield (call_expression arguments:(arguments (_)@arg)@arguments) { + node @arg.arg_index attr (@arg.arg_index) pop_symbol = (named-child-index @arg) edge @arguments.arg_scope_no_this -> @arg.arg_index edge @arg.arg_index -> @arg.value @@ -2767,6 +2780,10 @@ inherit .return_or_yield constructor:(_)@constructor arguments:(_)@arguments)@new_expr { + node @arguments.arg_scope + attr (@arguments.arg_scope) is_exported + node @arguments.arg_this + edge @constructor.before_scope -> @new_expr.before_scope edge @arguments.before_scope -> @constructor.after_scope edge @new_expr.after_scope -> @arguments.after_scope @@ -2799,6 +2816,8 @@ inherit .return_or_yield (new_expression arguments:(arguments (_)@arg)@arguments) { + node @arg.arg_index + attr (@arg.arg_index) pop_symbol = (named-child-index @arg) edge @arguments.arg_scope -> @arg.arg_index edge @arg.arg_index -> @arg.value From ad5d5fc153bf03456296c0f357e59d8412931129 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 18 Jul 2023 17:35:19 -0700 Subject: [PATCH 091/500] Lowers arguments nodes --- .../src/stack-graphs.tsg | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 611bb0959..a77629c43 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -231,8 +231,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; ## Nodes (_)@node { - node @node.arguments_pop - node @node.arguments_push node @node.boundvar_pop node @node.call node @node.constructor @@ -1093,8 +1091,11 @@ inherit .return_or_yield parameters:(_)@call_sig body:(_)@body)@fun_decl { + node @call_sig.arguments_pop + node @call_sig.arguments_push node @name.pop node @fun_decl.function_value + attr (@name.pop) syntax_type = "function" ; scope flows across the decl @@ -1165,8 +1166,11 @@ inherit .return_or_yield parameters:(_)@call_sig body:(_)@body)@fun_decl { + node @call_sig.arguments_pop + node @call_sig.arguments_push node @name.pop node @fun_decl.function_value + attr (@name.pop) syntax_type = "function" ; scope flows across the decl @@ -2382,6 +2386,9 @@ inherit .return_or_yield parameters:(_)@call_sig body:(_)@body)@fun { + node @call_sig.arguments_pop + node @call_sig.arguments_push + ; scope flows across the decl edge @fun.after_scope -> @fun.before_scope From 0233f980dd5b06ce177721f2c5427a1d2e58b73a Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 18 Jul 2023 17:37:08 -0700 Subject: [PATCH 092/500] Lowers constructor vars --- .../src/stack-graphs.tsg | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index a77629c43..ab60ed634 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -233,8 +233,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n (_)@node { node @node.boundvar_pop node @node.call - node @node.constructor - node @node.constructor_guard node @node.default_guard node @node.definiens_hook node @node.drop @@ -1306,6 +1304,9 @@ inherit .return_or_yield name:(_)@name)@method_def (#eq? @name "constructor") ) { + + node @name.constructor_guard + ; augmentation for the constructor attr (@name.constructor_guard) symbol_definition = "GUARD:CONSTRUCTOR", source_node = @name edge @method_def.after_scope -> @name.constructor_guard @@ -2790,6 +2791,7 @@ inherit .return_or_yield node @arguments.arg_scope attr (@arguments.arg_scope) is_exported node @arguments.arg_this + node @constructor.constructor edge @constructor.before_scope -> @new_expr.before_scope edge @arguments.before_scope -> @constructor.after_scope From 36bf6f379be3b9faa4013d7fbc848915e1bc5a83 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 18 Jul 2023 17:38:51 -0700 Subject: [PATCH 093/500] Lowers call var --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index ab60ed634..e1e0ab38f 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -232,7 +232,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n (_)@node { node @node.boundvar_pop - node @node.call node @node.default_guard node @node.definiens_hook node @node.drop @@ -2626,6 +2625,7 @@ inherit .return_or_yield attr (@arguments.arg_scope) is_exported node @arguments.arg_scope_no_this node @arguments.arg_this + node @call_expr.call ; value is a call, ie a push "()" node w/ "push-scope" @arguments attr (@call_expr.return_guard) push_symbol = "GUARD:RETURN" @@ -2792,6 +2792,7 @@ inherit .return_or_yield attr (@arguments.arg_scope) is_exported node @arguments.arg_this node @constructor.constructor + node @new_expr.call edge @constructor.before_scope -> @new_expr.before_scope edge @arguments.before_scope -> @constructor.after_scope From 33fc0b7a0f8df283fe99a2cf0046b0527b705bf1 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 18 Jul 2023 17:39:39 -0700 Subject: [PATCH 094/500] Lowers drop var --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index e1e0ab38f..0e77c5a3b 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -234,7 +234,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.boundvar_pop node @node.default_guard node @node.definiens_hook - node @node.drop node @node.element_index_push node @node.element_index_push_dot node @node.element_pop_dot @@ -2941,6 +2940,7 @@ inherit .return_or_yield right: (_)@right)@assignment_expr { node @property.pop + node @this.drop node @this.pop node @this.pop_dot From f1b286a6fcd2a781a6c902e9009ffe2da7c3462e Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 18 Jul 2023 17:43:21 -0700 Subject: [PATCH 095/500] Lowers element vars --- .../src/stack-graphs.tsg | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 0e77c5a3b..b6099e450 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -234,9 +234,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.boundvar_pop node @node.default_guard node @node.definiens_hook - node @node.element_index_push - node @node.element_index_push_dot - node @node.element_pop_dot node @node.exports_pop node @node.field_pop_dot node @node.guard_default @@ -2272,6 +2269,7 @@ inherit .return_or_yield (array)@array_expr { + node @array_expr.element_pop_dot attr (@array_expr.element_pop_dot) pop_symbol = "." edge @array_expr.value -> @array_expr.element_pop_dot @@ -3530,12 +3528,16 @@ inherit .return_or_yield ; array pattern (array_pattern)@array_pat { + node @array_pat.element_index_push_dot edge @array_pat.element_index_push_dot -> @array_pat.covalue attr (@array_pat.element_index_push_dot) push_symbol = "." } ; array pattern elements (array_pattern (_)@element_pat)@array_pat { + + node @element_pat.element_index_push + attr (@element_pat.element_index_push) push_symbol = (named-child-index @element_pat) edge @element_pat.covalue -> @element_pat.element_index_push edge @element_pat.element_index_push -> @array_pat.element_index_push_dot From 31a45ed2f7f364674e199e177c28e273b92d13bd Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 18 Jul 2023 17:44:57 -0700 Subject: [PATCH 096/500] Lowers index vars --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index b6099e450..201e35718 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -239,8 +239,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.guard_default node @node.guard_this node @node.ignore_guard - node @node.index_pop - node @node.index_push node @node.key_pop node @node.key_push node @node.label_guard @@ -2742,6 +2740,7 @@ inherit .return_or_yield object: (_)@object index: (_)@index)@subscript_expr { + node @subscript_expr.index_push node @subscript_expr.push_dot ; scopes flow left to right From cc0940504d43b7c66c9a153b30b74b769ab3af44 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 18 Jul 2023 17:46:08 -0700 Subject: [PATCH 097/500] Lower member vars --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 201e35718..5cda44966 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -244,8 +244,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.label_guard node @node.label_pop node @node.label_push - node @node.member_pop - node @node.member_push node @node.method_value node @node.method_value_arg_scope node @node.method_value_call @@ -2118,6 +2116,7 @@ inherit .return_or_yield (object)@object { + node @object.member_pop attr (@object.member_pop) pop_symbol = "." edge @object.value -> @object.member_pop From 95abdb06eb6a29040fc9bdc6b14553941c9b3aae Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 18 Jul 2023 17:47:35 -0700 Subject: [PATCH 098/500] Lowers this vars --- .../src/stack-graphs.tsg | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 5cda44966..45aca38ae 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -264,8 +264,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.rhsvar_value node @node.source node @node.string_prototype - node @node.this_pop - node @node.this_push node @node.value_arg_scope node @node.value_call node @node.value_drop @@ -1082,6 +1080,8 @@ inherit .return_or_yield node @call_sig.arguments_pop node @call_sig.arguments_push + node @call_sig.this_pop + node @call_sig.this_push node @name.pop node @fun_decl.function_value @@ -1157,6 +1157,8 @@ inherit .return_or_yield node @call_sig.arguments_pop node @call_sig.arguments_push + node @call_sig.this_pop + node @call_sig.this_push node @name.pop node @fun_decl.function_value @@ -2382,6 +2384,8 @@ inherit .return_or_yield node @call_sig.arguments_pop node @call_sig.arguments_push + node @call_sig.this_pop + node @call_sig.this_push ; scope flows across the decl edge @fun.after_scope -> @fun.before_scope From fc58b4d25edc5b2e9b72fab095aa2ee5db159ec8 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 18 Jul 2023 17:48:21 -0700 Subject: [PATCH 099/500] Lower key vars --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 45aca38ae..2dae30c3c 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -239,8 +239,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.guard_default node @node.guard_this node @node.ignore_guard - node @node.key_pop - node @node.key_push node @node.label_guard node @node.label_pop node @node.label_push @@ -2208,6 +2206,7 @@ inherit .return_or_yield ; This is done differently depending on what the key is. See next rules. ; attr @key.pop "pop" = @key, "definition" + node @pair.key_pop edge @pair.key_pop -> @value.value edge @object.member_pop -> @pair.key_pop From 23920bbd185c9a45f79a32a378c0017075802efd Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 18 Jul 2023 17:50:09 -0700 Subject: [PATCH 100/500] Lower label vars --- .../src/stack-graphs.tsg | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 2dae30c3c..4c426f5a3 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -239,9 +239,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.guard_default node @node.guard_this node @node.ignore_guard - node @node.label_guard - node @node.label_pop - node @node.label_push node @node.method_value node @node.method_value_arg_scope node @node.method_value_call @@ -1796,6 +1793,9 @@ inherit .return_or_yield (break_statement (_)@label)@break_stmt { + node @break_stmt.label_guard + node @break_stmt.label_push + attr (@break_stmt.label_guard) push_symbol = "GUARD:LABEL" attr (@break_stmt.label_push) node_reference = @label @@ -1814,6 +1814,9 @@ inherit .return_or_yield (continue_statement (_)@label)@continue_stmt { + node @continue_stmt.label_guard + node @continue_stmt.label_push + attr (@continue_stmt.label_guard) push_symbol = "GUARD:LABEL" attr (@continue_stmt.label_push) node_reference = @label @@ -1869,6 +1872,9 @@ inherit .return_or_yield body:(_)@inner)@labeled_stmt { + node @labeled_stmt.label_guard + node @labeled_stmt.label_pop + attr (@labeled_stmt.label_guard) pop_symbol = "GUARD:LABEL" attr (@labeled_stmt.label_pop) node_definition = @label From 1c79f94fba824a8398df11c01fa20fa0b77a4c23 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 18 Jul 2023 17:51:32 -0700 Subject: [PATCH 101/500] Lower new_bindings --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 4c426f5a3..835753790 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -249,7 +249,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.module_guard node @node.module_pop node @node.module_scope - node @node.new_bindings node @node.pop_guard_default node @node.push_exports_guard node @node.push_guard_default @@ -3345,6 +3344,7 @@ inherit .return_or_yield node @pattern.after_scope node @pattern.before_scope node @pattern.covalue + node @pattern.new_bindings } From b1997b8c368dcb2dc89feb7a9fff67ac57bd210a Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 18 Jul 2023 17:52:35 -0700 Subject: [PATCH 102/500] Lower return guard --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 835753790..b4127affa 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -253,7 +253,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.push_exports_guard node @node.push_guard_default node @node.push_guard_exports - node @node.return_guard node @node.rhsvar_before_scope node @node.rhsvar_value node @node.source @@ -2628,6 +2627,7 @@ inherit .return_or_yield node @arguments.arg_scope_no_this node @arguments.arg_this node @call_expr.call + node @call_expr.return_guard ; value is a call, ie a push "()" node w/ "push-scope" @arguments attr (@call_expr.return_guard) push_symbol = "GUARD:RETURN" From 91dbef53180bd2dfdea37fb4db08cc4d356d7b8d Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 18 Jul 2023 17:54:09 -0700 Subject: [PATCH 103/500] Remove unused string prototype var --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 1 - 1 file changed, 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index b4127affa..5ab35cb1b 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -256,7 +256,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.rhsvar_before_scope node @node.rhsvar_value node @node.source - node @node.string_prototype node @node.value_arg_scope node @node.value_call node @node.value_drop From 4552bfe49d168f61a3fbedea054c5aaa784c4a06 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 18 Jul 2023 17:54:50 -0700 Subject: [PATCH 104/500] Remove unused rhsvar vars --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 -- 1 file changed, 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 5ab35cb1b..67ec1ba78 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -253,8 +253,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.push_exports_guard node @node.push_guard_default node @node.push_guard_exports - node @node.rhsvar_before_scope - node @node.rhsvar_value node @node.source node @node.value_arg_scope node @node.value_call From d1ef86dbb1585e178972c0d57c8142a1cecb9fd9 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 20 Jul 2023 14:41:29 -0700 Subject: [PATCH 105/500] Lowers remainder of scoped vars --- .../src/stack-graphs.tsg | 136 +++++++++++------- 1 file changed, 87 insertions(+), 49 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 67ec1ba78..cae38c73b 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -228,41 +228,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; - `GUARD:EXPORTS` - used for the names exported by the module ;; - `GUARD:DEFAULT` - used for the default export value -;; ## Nodes - -(_)@node { - node @node.boundvar_pop - node @node.default_guard - node @node.definiens_hook - node @node.exports_pop - node @node.field_pop_dot - node @node.guard_default - node @node.guard_this - node @node.ignore_guard - node @node.method_value - node @node.method_value_arg_scope - node @node.method_value_call - node @node.method_value_drop - node @node.method_value_return - node @node.method_value_this - node @node.method_value_this_guard - node @node.module_guard - node @node.module_pop - node @node.module_scope - node @node.pop_guard_default - node @node.push_exports_guard - node @node.push_guard_default - node @node.push_guard_exports - node @node.source - node @node.value_arg_scope - node @node.value_call - node @node.value_drop - node @node.value_return - node @node.value_this - node @node.value_this_guard -} - - ; ## Inherited inherit .builtins_Regex_prototype @@ -304,6 +269,11 @@ inherit .return_or_yield ;; ### Program Queries (program)@prog { + + node @prog.module_pop + node @prog.module_scope + node @prog.exports_pop + scan FILE_PATH { "([^/]+)\.js$" { attr (@prog.module_pop) symbol_definition = $1, source_node = @prog @@ -465,16 +435,17 @@ inherit .return_or_yield source:(_)@source)@export_stmt { node @source.push + node @source.push_guard_exports - edge @export_clause.source -> @source.push_exports_guard + edge @export_clause.source -> @source.push_guard_exports - attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" + attr (@source.push_guard_exports) push_symbol = "GUARD:EXPORTS" scan (source-text @source) { "\"([^/\"]+)\.js\"$" { attr (@source.push) push_symbol = $1 } } - edge @source.push_exports_guard -> @source.push + edge @source.push_guard_exports -> @source.push edge @source.push -> ROOT_NODE edge @export_clause.before_scope -> @export_stmt.before_scope @@ -528,6 +499,7 @@ inherit .return_or_yield (export_clause)@export_clause { node @export_clause.after_scope node @export_clause.before_scope + node @export_clause.source } ; LATER-TODO tree sitter doesn't yet support empty switch bodies @@ -565,9 +537,13 @@ inherit .return_or_yield } (export_specifier)@export_specifier { + node @export_specifier.after_scope node @export_specifier.before_scope + node @export_specifier.source + edge @export_specifier.after_scope -> @export_specifier.before_scope + } ( @@ -618,6 +594,8 @@ inherit .return_or_yield ) { + node @export_specifier.pop_guard_default + attr (@export_specifier.pop_guard_default) pop_symbol = "GUARD:DEFAULT" attr (@export_specifier.push_guard_default) push_symbol = "GUARD:DEFAULT" edge @export_specifier.exports -> @export_specifier.pop_guard_default @@ -635,6 +613,7 @@ inherit .return_or_yield ) { + node @export_specifier.guard_default node @name.push attr (@name.push) push_node = @name @@ -650,6 +629,8 @@ inherit .return_or_yield (export_statement value:(_)@default_expr)@export_stmt { + node @export_stmt.default_guard + attr (@export_stmt.default_guard) symbol_definition = "GUARD:DEFAULT", source_node = @export_stmt edge @default_expr.before_scope -> @export_stmt.before_scope edge @export_stmt.after_scope -> @default_expr.after_scope @@ -664,18 +645,19 @@ inherit .return_or_yield source:(_)@source)@export_statement { node @source.push + node @source.push_guard_exports edge @export_statement.after_scope -> @export_statement.before_scope - attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" + attr (@source.push_guard_exports) push_symbol = "GUARD:EXPORTS" scan (source-text @source) { "\"([^/\"]+)\.js\"$" { attr (@source.push) push_symbol = $1 } } - edge @export_statement.exports -> @source.push_exports_guard - edge @source.push_exports_guard -> @source.push + edge @export_statement.exports -> @source.push_guard_exports + edge @source.push_guard_exports -> @source.push edge @source.push -> ROOT_NODE } @@ -689,10 +671,11 @@ inherit .return_or_yield node @alias.pop node @alias.pop_dot node @source.push + node @source.push_guard_exports edge @export_statement.after_scope -> @export_statement.before_scope - attr (@source.push_exports_guard) push_symbol = "GUARD:EXPORTS" + attr (@source.push_guard_exports) push_symbol = "GUARD:EXPORTS" scan (source-text @source) { "\"([^/\"]+)\.js\"$" { attr (@source.push) push_symbol = $1 @@ -702,8 +685,8 @@ inherit .return_or_yield attr (@alias.pop_dot) pop_symbol = "." edge @export_statement.exports -> @alias.pop edge @alias.pop -> @alias.pop_dot - edge @alias.pop_dot -> @source.push_exports_guard - edge @source.push_exports_guard -> @source.push + edge @alias.pop_dot -> @source.push_guard_exports + edge @source.push_guard_exports -> @source.push edge @source.push -> ROOT_NODE } @@ -732,6 +715,7 @@ inherit .return_or_yield (import_clause)@import_clause { node @import_clause.after_scope node @import_clause.before_scope + node @import_clause.source } ; import * as name from "module-name"; @@ -749,6 +733,8 @@ inherit .return_or_yield node @imported_as.pop_dot node @namespace_import.after_scope node @namespace_import.before_scope + node @namespace_import.source + edge @namespace_import.after_scope -> @namespace_import.before_scope attr (@imported_as.pop) node_definition = @imported_as @@ -770,6 +756,7 @@ inherit .return_or_yield source:(_)@source)@import_stmt { node @source.push + node @source.push_guard_exports edge @import_clause.before_scope -> @import_stmt.before_scope edge @import_stmt.after_scope -> @import_clause.after_scope @@ -798,6 +785,7 @@ inherit .return_or_yield (named_imports)@named_imports { node @named_imports.after_scope node @named_imports.before_scope + node @named_imports.source } ; LATER-TODO tree sitter doesn't yet support empty named imports @@ -837,6 +825,7 @@ inherit .return_or_yield (import_specifier)@import_specifier { node @import_specifier.after_scope node @import_specifier.before_scope + node @import_specifier.source } ( @@ -922,6 +911,7 @@ inherit .return_or_yield (identifier)@default_name)@import_clause { node @default_name.pop + node @default_name.push_guard_default edge @import_clause.after_scope -> @import_clause.before_scope @@ -1074,6 +1064,12 @@ inherit .return_or_yield node @call_sig.this_push node @name.pop node @fun_decl.function_value + node @fun_decl.value_arg_scope + node @fun_decl.value_call + node @fun_decl.value_drop + node @fun_decl.value_return + node @fun_decl.value_this + node @fun_decl.value_this_guard attr (@name.pop) syntax_type = "function" @@ -1151,6 +1147,12 @@ inherit .return_or_yield node @call_sig.this_push node @name.pop node @fun_decl.function_value + node @fun_decl.value_arg_scope + node @fun_decl.value_call + node @fun_decl.value_drop + node @fun_decl.value_return + node @fun_decl.value_this + node @fun_decl.value_this_guard attr (@name.pop) syntax_type = "function" @@ -1279,6 +1281,7 @@ inherit .return_or_yield node @name.pop node @method_def.after_scope node @method_def.before_scope + node @method_def.method_value } @@ -1316,6 +1319,13 @@ inherit .return_or_yield parameters:(_)@call_sig body:(_)@body)@method_def { + node @method_def.method_value_arg_scope + node @method_def.method_value_call + node @method_def.method_value_drop + node @method_def.method_value_return + node @method_def.method_value_this + node @method_def.method_value_this_guard + attr (@name.pop) syntax_type = "method" ; scope flows across the decl @@ -2386,6 +2396,12 @@ inherit .return_or_yield node @call_sig.arguments_push node @call_sig.this_pop node @call_sig.this_push + node @fun.value_arg_scope + node @fun.value_call + node @fun.value_drop + node @fun.value_return + node @fun.value_this + node @fun.value_this_guard ; scope flows across the decl edge @fun.after_scope -> @fun.before_scope @@ -2457,6 +2473,13 @@ inherit .return_or_yield body:(_)@body)@fun ] { + node @fun.value_arg_scope + node @fun.value_call + node @fun.value_drop + node @fun.value_return + node @fun.value_this + node @fun.value_this_guard + ; scope flows across the decl edge @fun.after_scope -> @fun.before_scope @@ -2554,6 +2577,13 @@ inherit .return_or_yield parameters:(_)@call_sig body:(_)@body)@fun { + node @fun.value_arg_scope + node @fun.value_call + node @fun.value_drop + node @fun.value_return + node @fun.value_this + node @fun.value_this_guard + ; scope flows across the decl edge @fun.after_scope -> @fun.before_scope @@ -2793,6 +2823,7 @@ inherit .return_or_yield node @arguments.arg_this node @constructor.constructor node @new_expr.call + node @new_expr.guard_this edge @constructor.before_scope -> @new_expr.before_scope edge @arguments.before_scope -> @constructor.after_scope @@ -3708,6 +3739,7 @@ inherit .return_or_yield } } + node @mod_name.module_guard node @mod_name.push attr (@mod_name.module_guard) push_symbol = "GUARD:EXPORTS" @@ -3835,6 +3867,9 @@ inherit .return_or_yield (arrow_function) ]@right) { + node @left.definiens_hook + node @left.ignore_guard + attr (@left.ignore_guard) pop_symbol = "GUARD:GANDALF" attr (@left.definiens_hook) node_definition = @left attr (@left.definiens_hook) definiens_node = @right @@ -3876,10 +3911,13 @@ inherit .return_or_yield (arrow_function) ]@value) { -attr (@name.ignore_guard) pop_symbol = "GUARD:GANDALF" -attr (@name.definiens_hook) node_definition = @name -attr (@name.definiens_hook) definiens_node = @value -edge ROOT_NODE -> @name.ignore_guard -edge @name.ignore_guard -> @name.definiens_hook + node @name.definiens_hook + node @name.ignore_guard + + attr (@name.ignore_guard) pop_symbol = "GUARD:GANDALF" + attr (@name.definiens_hook) node_definition = @name + attr (@name.definiens_hook) definiens_node = @value + edge ROOT_NODE -> @name.ignore_guard + edge @name.ignore_guard -> @name.definiens_hook } From d4d2ca60981f4e33e3965c1269df3dd56111d1a4 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 20 Jul 2023 14:44:20 -0700 Subject: [PATCH 106/500] Documents more guard nodes --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index cae38c73b..6a2996dd3 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -227,6 +227,11 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; - `GUARD:MODULE` - used for the final scope of the module ;; - `GUARD:EXPORTS` - used for the names exported by the module ;; - `GUARD:DEFAULT` - used for the default export value +;; - `GUARD:GANDALF` - used for situations where parts of a graph must be accessible +;; in order to avoid pruning, but which never the less should not be actually reached +;; during any normal traversals. By only ever popping, and never pushing, we can get +;; a connected subgraph that is never the less never traversed. +;; - `GUARD:LABEL` - used for the names of labels ; ## Inherited From ff591b0e21f5e65c3c92aa4283b896ccc5233b37 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 20 Jul 2023 14:48:41 -0700 Subject: [PATCH 107/500] Renames "." to "GUARD:MEMBER" and documents it --- .../src/stack-graphs.tsg | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 6a2996dd3..f5f35faaf 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -215,7 +215,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; By convention, this library of queries prefixes all guard nodes with "GUARD:" ;; to distinguish them from nodes that more directly correspond to aspects of -;; execution such as member lookup (labelled with ".") or variable lookup +;; execution such as member lookup (labelled with "GUARD:MEMBER") or variable lookup ;; (labelled with the variable name itself). The current names used for guard ;; nodes are @@ -232,6 +232,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; during any normal traversals. By only ever popping, and never pushing, we can get ;; a connected subgraph that is never the less never traversed. ;; - `GUARD:LABEL` - used for the names of labels +;; - `GUARD:MEMBER` - used for the members/fields/properties of objects ; ## Inherited @@ -687,7 +688,7 @@ inherit .return_or_yield } } attr (@alias.pop) node_definition = @alias - attr (@alias.pop_dot) pop_symbol = "." + attr (@alias.pop_dot) pop_symbol = "GUARD:MEMBER" edge @export_statement.exports -> @alias.pop edge @alias.pop -> @alias.pop_dot edge @alias.pop_dot -> @source.push_guard_exports @@ -743,7 +744,7 @@ inherit .return_or_yield edge @namespace_import.after_scope -> @namespace_import.before_scope attr (@imported_as.pop) node_definition = @imported_as - attr (@imported_as.pop_dot) pop_symbol = "." + attr (@imported_as.pop_dot) pop_symbol = "GUARD:MEMBER" edge @imported_as.pop -> @imported_as.pop_dot edge @imported_as.pop_dot -> @namespace_import.source @@ -896,7 +897,7 @@ inherit .return_or_yield ; edge @mod_name.push -> ROOT_NODE ; ; attr (@name) node_reference = @name -; attr (@name.push_dot) push_symbol = "." +; attr (@name.push_dot) push_symbol = "GUARD:MEMBER" ; edge @name.push_dot -> @mod_name.push ; edge @name -> @name.push_dot ; @@ -1313,7 +1314,7 @@ inherit .return_or_yield node @name.pop_dot ; augmentation for the method attr (@name.pop) node_definition = @name - attr (@name.pop_dot) pop_symbol = "." + attr (@name.pop_dot) pop_symbol = "GUARD:MEMBER" edge @method_def.after_scope -> @name.pop_dot edge @name.pop_dot -> @name.pop edge @name.pop -> @method_def.method_value @@ -1388,7 +1389,7 @@ inherit .return_or_yield node @property.pop_dot attr (@property.pop) node_definition = @property - attr (@property.pop_dot) pop_symbol = "." + attr (@property.pop_dot) pop_symbol = "GUARD:MEMBER" edge @field_def.after_scope -> @property.pop_dot edge @property.pop_dot -> @property.pop } @@ -1787,7 +1788,7 @@ inherit .return_or_yield edge @body.before_scope -> @object.after_scope edge @with_stmt.after_scope -> @body.after_scope - attr (@with_stmt.push_dot) push_symbol = "." + attr (@with_stmt.push_dot) push_symbol = "GUARD:MEMBER" edge @with_stmt.push_dot -> @object.value edge @body.before_scope -> @with_stmt.push_dot } @@ -2133,7 +2134,7 @@ inherit .return_or_yield (object)@object { node @object.member_pop - attr (@object.member_pop) pop_symbol = "." + attr (@object.member_pop) pop_symbol = "GUARD:MEMBER" edge @object.value -> @object.member_pop } @@ -2284,7 +2285,7 @@ inherit .return_or_yield (array)@array_expr { node @array_expr.element_pop_dot - attr (@array_expr.element_pop_dot) pop_symbol = "." + attr (@array_expr.element_pop_dot) pop_symbol = "GUARD:MEMBER" edge @array_expr.value -> @array_expr.element_pop_dot } @@ -2674,7 +2675,7 @@ inherit .return_or_yield edge @arguments.arg_scope -> @arguments.arg_scope_no_this attr (@arguments.arg_arguments) symbol_definition = "arguments", source_node = @arguments - attr (@arguments.arg_arguments_dot) pop_symbol = "." + attr (@arguments.arg_arguments_dot) pop_symbol = "GUARD:MEMBER" edge @arguments.arg_scope -> @arguments.arg_arguments edge @arguments.arg_arguments -> @arguments.arg_arguments_dot edge @arguments.arg_arguments_dot -> @arguments.arg_scope_no_this @@ -2765,7 +2766,7 @@ inherit .return_or_yield edge @member_expr.after_scope -> @object.after_scope ; value is a member projection on the value of the object ie. a push then push dot - attr (member_push) push_symbol = "." + attr (member_push) push_symbol = "GUARD:MEMBER" attr (property_push) node_reference = @property edge property_push -> member_push edge @member_expr.value -> property_push @@ -2788,7 +2789,7 @@ inherit .return_or_yield edge @subscript_expr.after_scope -> @index.after_scope ; value is a subscript lookup, ie a push then push dot - attr (@subscript_expr.push_dot) push_symbol = "." + attr (@subscript_expr.push_dot) push_symbol = "GUARD:MEMBER" edge @subscript_expr.push_dot -> @object.value ; this is done differently depending on what the index is @@ -2985,7 +2986,7 @@ inherit .return_or_yield attr (@this.drop) type = "drop_scopes" edge @this.drop -> @this.pop attr (@this.pop) pop_symbol = "this" - attr (@this.pop_dot) pop_symbol = "." + attr (@this.pop_dot) pop_symbol = "GUARD:MEMBER" attr (@property.pop) node_definition = @property edge @assignment_expr.after_scope -> @this.drop edge @assignment_expr.after_scope -> @this.pop @@ -3456,7 +3457,7 @@ inherit .return_or_yield node @key.push_dot ; covalues flow in dotted - attr (@key.push_dot) push_symbol = "." + attr (@key.push_dot) push_symbol = "GUARD:MEMBER" edge @value_pat.covalue -> @key.push edge @key.push -> @key.push_dot edge @key.push_dot -> @pair_pat.covalue @@ -3518,7 +3519,7 @@ inherit .return_or_yield edge @left_pat.after_scope -> @left_pat.before_scope attr (@left_pat.push) node_reference = @left_pat - attr (@left_pat.push_dot) push_symbol = "." + attr (@left_pat.push_dot) push_symbol = "GUARD:MEMBER" attr (@left_pat.pop) node_definition = @left_pat edge @left_pat.pop -> @left_pat.push edge @left_pat.push -> @left_pat.push_dot @@ -3570,7 +3571,7 @@ inherit .return_or_yield (array_pattern)@array_pat { node @array_pat.element_index_push_dot edge @array_pat.element_index_push_dot -> @array_pat.covalue - attr (@array_pat.element_index_push_dot) push_symbol = "." + attr (@array_pat.element_index_push_dot) push_symbol = "GUARD:MEMBER" } ; array pattern elements @@ -3706,7 +3707,7 @@ inherit .return_or_yield node @property.pop node @property.pop_dot attr (@property.pop) node_definition = @property - attr (@property.pop_dot) pop_symbol = "." + attr (@property.pop_dot) pop_symbol = "GUARD:MEMBER" edge @assignment_expr.exports -> @property.pop_dot edge @property.pop_dot -> @property.pop edge @property.pop -> @right.value From dc1019e13d3163f1d72c2748acb08f5bed8d3745 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 20 Jul 2023 14:49:53 -0700 Subject: [PATCH 108/500] Sorts guard docs --- .../src/stack-graphs.tsg | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index f5f35faaf..43fd5c0b9 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -219,20 +219,20 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; (labelled with the variable name itself). The current names used for guard ;; nodes are -;; - `GUARD:RETURN` - used for the AST nodes for values returned by a function -;; in the function body -;; - `GUARD:THIS` - used for the implicit `this` argument of a function inside -;; its body ;; - `GUARD:CONSTRUCTOR` - used for the constructor method inside a `Class` -;; - `GUARD:MODULE` - used for the final scope of the module -;; - `GUARD:EXPORTS` - used for the names exported by the module ;; - `GUARD:DEFAULT` - used for the default export value +;; - `GUARD:EXPORTS` - used for the names exported by the module ;; - `GUARD:GANDALF` - used for situations where parts of a graph must be accessible ;; in order to avoid pruning, but which never the less should not be actually reached ;; during any normal traversals. By only ever popping, and never pushing, we can get ;; a connected subgraph that is never the less never traversed. ;; - `GUARD:LABEL` - used for the names of labels ;; - `GUARD:MEMBER` - used for the members/fields/properties of objects +;; - `GUARD:MODULE` - used for the final scope of the module +;; - `GUARD:RETURN` - used for the AST nodes for values returned by a function +;; in the function body +;; - `GUARD:THIS` - used for the implicit `this` argument of a function inside +;; its body ; ## Inherited From af19a185c55bc6ebf42c5bd3334d74ce2cf83756 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 20 Jul 2023 16:15:37 -0700 Subject: [PATCH 109/500] Lowers return_or_yield --- .../src/stack-graphs.tsg | 7 ++++-- .../test/base_syntax.js | 5 ++-- .../simple_expressions/yield_expression.js | 24 ++++++++++--------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 43fd5c0b9..d78a082f4 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -315,8 +315,6 @@ inherit .return_or_yield node @prog.builtins_arguments_prototype node @prog.builtins_empty_object - ;; fallbacks - node @prog.return_or_yield } ; programs, first statement @@ -1070,6 +1068,7 @@ inherit .return_or_yield node @call_sig.this_push node @name.pop node @fun_decl.function_value + node @fun_decl.return_or_yield node @fun_decl.value_arg_scope node @fun_decl.value_call node @fun_decl.value_drop @@ -1153,6 +1152,7 @@ inherit .return_or_yield node @call_sig.this_push node @name.pop node @fun_decl.function_value + node @fun_decl.return_or_yield node @fun_decl.value_arg_scope node @fun_decl.value_call node @fun_decl.value_drop @@ -2402,6 +2402,7 @@ inherit .return_or_yield node @call_sig.arguments_push node @call_sig.this_pop node @call_sig.this_push + node @fun.return_or_yield node @fun.value_arg_scope node @fun.value_call node @fun.value_drop @@ -2479,6 +2480,7 @@ inherit .return_or_yield body:(_)@body)@fun ] { + node @fun.return_or_yield node @fun.value_arg_scope node @fun.value_call node @fun.value_drop @@ -2583,6 +2585,7 @@ inherit .return_or_yield parameters:(_)@call_sig body:(_)@body)@fun { + node @fun.return_or_yield node @fun.value_arg_scope node @fun.value_call node @fun.value_drop diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index 92b611208..858f854cd 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -44,9 +44,9 @@ undefined; }; []; [1, 2, 3]; -function () { }; +function () { return; }; () => { }; -function* () { }; +function* () { yield 1; }; foo(); foo(bar); foo.bar; @@ -62,5 +62,4 @@ x++; x += 1; (1, 2); 1 ? 2 : 3; -yield 1; class { }; \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js index ff2bab226..2903e806b 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js @@ -1,18 +1,20 @@ -let x = 1; +function* () { + let x = 1; -// Flow in + // Flow in -yield x; -// ^ defined: 1 + yield x; + // ^ defined: 2 -// Flow out + // Flow out -yield y = 1; + yield y = 1; -/**/ y; -// ^ defined: 10 + /**/ y; + // ^ defined: 11 -// Flow around + // Flow around -/**/ x; -// ^ defined: 1 \ No newline at end of file + /**/ x; + // ^ defined: 2 +} \ No newline at end of file From b45d455c74f9c70e656f9204f7d0c08d9e677613 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 20 Jul 2023 16:16:14 -0700 Subject: [PATCH 110/500] Fixes minor bug --- .../test/simple_expressions/yield_expression.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js index 2903e806b..77fa2c453 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js @@ -1,4 +1,4 @@ -function* () { +function* f() { let x = 1; // Flow in From 2742965113fc0b9dd65cab502899d14b8c254b5c Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Fri, 21 Jul 2023 09:35:48 -0700 Subject: [PATCH 111/500] Removes external visibility of many vars --- .../src/stack-graphs.tsg | 929 +++++++++--------- 1 file changed, 466 insertions(+), 463 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index d78a082f4..f655742c5 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -276,34 +276,34 @@ inherit .return_or_yield (program)@prog { - node @prog.module_pop - node @prog.module_scope - node @prog.exports_pop + node prog_module_pop + node prog_module_scope + node prog_exports_pop + node @prog.exports scan FILE_PATH { "([^/]+)\.js$" { - attr (@prog.module_pop) symbol_definition = $1, source_node = @prog + attr (prog_module_pop) symbol_definition = $1, source_node = @prog } } edge @prog.before_scope -> ROOT_NODE - attr (@prog.module_scope) pop_symbol = "GUARD:MODULE" - edge ROOT_NODE -> @prog.module_pop - edge @prog.module_pop -> @prog.module_scope - edge @prog.module_scope -> @prog.after_scope + attr (prog_module_scope) pop_symbol = "GUARD:MODULE" + edge ROOT_NODE -> prog_module_pop + edge prog_module_pop -> prog_module_scope + edge prog_module_scope -> @prog.after_scope - attr (@prog.module_pop) empty_source_span - attr (@prog.module_scope) empty_source_span + attr (prog_module_pop) empty_source_span + attr (prog_module_scope) empty_source_span attr (@prog.exports) empty_source_span - attr (@prog.exports_pop) empty_source_span + attr (prog_exports_pop) empty_source_span attr (@prog.before_scope) empty_source_span attr (@prog.after_scope) empty_source_span - node @prog.exports - attr (@prog.exports_pop) pop_symbol = "GUARD:EXPORTS" - edge @prog.module_pop -> @prog.exports_pop - edge @prog.exports_pop -> @prog.exports + attr (prog_exports_pop) pop_symbol = "GUARD:EXPORTS" + edge prog_module_pop -> prog_exports_pop + edge prog_exports_pop -> @prog.exports ;; builtin types node @prog.builtins_number @@ -438,19 +438,19 @@ inherit .return_or_yield (export_clause)@export_clause source:(_)@source)@export_stmt { - node @source.push - node @source.push_guard_exports + node source_push + node source_push_guard_exports - edge @export_clause.source -> @source.push_guard_exports + edge @export_clause.source -> source_push_guard_exports - attr (@source.push_guard_exports) push_symbol = "GUARD:EXPORTS" + attr (source_push_guard_exports) push_symbol = "GUARD:EXPORTS" scan (source-text @source) { "\"([^/\"]+)\.js\"$" { - attr (@source.push) push_symbol = $1 + attr (source_push) push_symbol = $1 } } - edge @source.push_guard_exports -> @source.push - edge @source.push -> ROOT_NODE + edge source_push_guard_exports -> source_push + edge source_push -> ROOT_NODE edge @export_clause.before_scope -> @export_stmt.before_scope edge @export_stmt.after_scope -> @export_clause.after_scope @@ -558,15 +558,15 @@ inherit .return_or_yield (#not-eq? @name "default") ) { - node @name.pop - node @name.push + node name_pop + node name_push - attr (@name.pop) node_definition = @name - attr (@name.push) node_reference = @name - edge @name.pop -> @name.push - edge @name.push -> @export_specifier.source + attr (name_pop) node_definition = @name + attr (name_push) node_reference = @name + edge name_pop -> name_push + edge name_push -> @export_specifier.source - edge @export_specifier.exports -> @name.pop + edge @export_specifier.exports -> name_pop } ( @@ -578,15 +578,15 @@ inherit .return_or_yield ) { - node @alias.pop - node @name.push + node alias_pop + node name_push - attr (@alias.pop) node_definition = @alias - attr (@name.push) node_reference = @name - edge @alias.pop -> @name.push - edge @name.push -> @export_specifier.source + attr (alias_pop) node_definition = @alias + attr (name_push) node_reference = @name + edge alias_pop -> name_push + edge name_push -> @export_specifier.source - edge @export_specifier.exports -> @alias.pop + edge @export_specifier.exports -> alias_pop } ( @@ -598,13 +598,14 @@ inherit .return_or_yield ) { - node @export_specifier.pop_guard_default + node export_specifier_pop_guard_default + node export_specifier_push_guard_default - attr (@export_specifier.pop_guard_default) pop_symbol = "GUARD:DEFAULT" - attr (@export_specifier.push_guard_default) push_symbol = "GUARD:DEFAULT" - edge @export_specifier.exports -> @export_specifier.pop_guard_default - edge @export_specifier.pop_guard_default -> @export_specifier.push_guard_default - edge @export_specifier.push_guard_default -> @export_specifier.source + attr (export_specifier_pop_guard_default) pop_symbol = "GUARD:DEFAULT" + attr (export_specifier_push_guard_default) push_symbol = "GUARD:DEFAULT" + edge @export_specifier.exports -> export_specifier_pop_guard_default + edge export_specifier_pop_guard_default -> export_specifier_push_guard_default + edge export_specifier_push_guard_default -> @export_specifier.source } @@ -617,14 +618,14 @@ inherit .return_or_yield ) { - node @export_specifier.guard_default - node @name.push + node export_specifier_guard_default + node name_push - attr (@name.push) push_node = @name - attr (@export_specifier.guard_default) pop_symbol = "GUARD:DEFAULT" - edge @name.push -> @export_specifier.source - edge @export_specifier.guard_default -> @name.push - edge @export_specifier.exports -> @export_specifier.guard_default + attr (name_push) push_node = @name + attr (export_specifier_guard_default) pop_symbol = "GUARD:DEFAULT" + edge name_push -> @export_specifier.source + edge export_specifier_guard_default -> name_push + edge @export_specifier.exports -> export_specifier_guard_default } ; simple default exports @@ -633,13 +634,13 @@ inherit .return_or_yield (export_statement value:(_)@default_expr)@export_stmt { - node @export_stmt.default_guard + node export_stmt_default_guard - attr (@export_stmt.default_guard) symbol_definition = "GUARD:DEFAULT", source_node = @export_stmt + attr (export_stmt_default_guard) symbol_definition = "GUARD:DEFAULT", source_node = @export_stmt edge @default_expr.before_scope -> @export_stmt.before_scope edge @export_stmt.after_scope -> @default_expr.after_scope - edge @export_stmt.exports -> @export_stmt.default_guard - edge @export_stmt.default_guard -> @default_expr.value + edge @export_stmt.exports -> export_stmt_default_guard + edge export_stmt_default_guard -> @default_expr.value } ; aggregated exports @@ -648,21 +649,21 @@ inherit .return_or_yield . source:(_)@source)@export_statement { - node @source.push - node @source.push_guard_exports + node source_push + node source_push_guard_exports edge @export_statement.after_scope -> @export_statement.before_scope - attr (@source.push_guard_exports) push_symbol = "GUARD:EXPORTS" + attr (source_push_guard_exports) push_symbol = "GUARD:EXPORTS" scan (source-text @source) { "\"([^/\"]+)\.js\"$" { - attr (@source.push) push_symbol = $1 + attr (source_push) push_symbol = $1 } } - edge @export_statement.exports -> @source.push_guard_exports - edge @source.push_guard_exports -> @source.push - edge @source.push -> ROOT_NODE + edge @export_statement.exports -> source_push_guard_exports + edge source_push_guard_exports -> source_push + edge source_push -> ROOT_NODE } @@ -672,26 +673,26 @@ inherit .return_or_yield (namespace_export (_)@alias) source:(_)@source)@export_statement { - node @alias.pop - node @alias.pop_dot - node @source.push - node @source.push_guard_exports + node alias_pop + node alias_pop_dot + node source_push + node source_push_guard_exports edge @export_statement.after_scope -> @export_statement.before_scope - attr (@source.push_guard_exports) push_symbol = "GUARD:EXPORTS" + attr (source_push_guard_exports) push_symbol = "GUARD:EXPORTS" scan (source-text @source) { "\"([^/\"]+)\.js\"$" { - attr (@source.push) push_symbol = $1 + attr (source_push) push_symbol = $1 } } - attr (@alias.pop) node_definition = @alias - attr (@alias.pop_dot) pop_symbol = "GUARD:MEMBER" - edge @export_statement.exports -> @alias.pop - edge @alias.pop -> @alias.pop_dot - edge @alias.pop_dot -> @source.push_guard_exports - edge @source.push_guard_exports -> @source.push - edge @source.push -> ROOT_NODE + attr (alias_pop) node_definition = @alias + attr (alias_pop_dot) pop_symbol = "GUARD:MEMBER" + edge @export_statement.exports -> alias_pop + edge alias_pop -> alias_pop_dot + edge alias_pop_dot -> source_push_guard_exports + edge source_push_guard_exports -> source_push + edge source_push -> ROOT_NODE } @@ -733,20 +734,20 @@ inherit .return_or_yield (namespace_import (identifier)@imported_as)@namespace_import { - node @imported_as.pop - node @imported_as.pop_dot + node imported_as_pop + node imported_as_pop_dot node @namespace_import.after_scope node @namespace_import.before_scope node @namespace_import.source edge @namespace_import.after_scope -> @namespace_import.before_scope - attr (@imported_as.pop) node_definition = @imported_as - attr (@imported_as.pop_dot) pop_symbol = "GUARD:MEMBER" - edge @imported_as.pop -> @imported_as.pop_dot - edge @imported_as.pop_dot -> @namespace_import.source + attr (imported_as_pop) node_definition = @imported_as + attr (imported_as_pop_dot) pop_symbol = "GUARD:MEMBER" + edge imported_as_pop -> imported_as_pop_dot + edge imported_as_pop_dot -> @namespace_import.source - edge @namespace_import.after_scope -> @imported_as.pop + edge @namespace_import.after_scope -> imported_as_pop } @@ -759,21 +760,21 @@ inherit .return_or_yield (import_clause)@import_clause source:(_)@source)@import_stmt { - node @source.push - node @source.push_guard_exports + node source_push + node source_push_guard_exports edge @import_clause.before_scope -> @import_stmt.before_scope edge @import_stmt.after_scope -> @import_clause.after_scope scan (source-text @source) { "\"([^/\"]+)\.js\"$" { - attr (@source.push) push_symbol = $1 + attr (source_push) push_symbol = $1 } } - attr (@source.push_guard_exports) push_symbol = "GUARD:EXPORTS" - edge @source.push_guard_exports -> @source.push - edge @source.push -> ROOT_NODE - edge @import_clause.source -> @source.push_guard_exports + attr (source_push_guard_exports) push_symbol = "GUARD:EXPORTS" + edge source_push_guard_exports -> source_push + edge source_push -> ROOT_NODE + edge @import_clause.source -> source_push_guard_exports } @@ -842,16 +843,16 @@ inherit .return_or_yield ) { - node @name.pop - node @name.push + node name_pop + node name_push edge @import_specifier.after_scope -> @import_specifier.before_scope - attr (@name.pop) node_definition = @name - attr (@name.push) node_reference = @name - edge @name.pop -> @name.push - edge @name.push -> @import_specifier.source - edge @import_specifier.after_scope -> @name.pop + attr (name_pop) node_definition = @name + attr (name_push) node_reference = @name + edge name_pop -> name_push + edge name_push -> @import_specifier.source + edge @import_specifier.after_scope -> name_pop } @@ -865,16 +866,16 @@ inherit .return_or_yield ) { - node @alias.pop - node @name.push + node alias_pop + node name_push edge @import_specifier.after_scope -> @import_specifier.before_scope - attr (@alias.pop) node_definition = @alias - attr (@name.push) node_reference = @name - edge @alias.pop -> @name.push - edge @name.push -> @import_specifier.source - edge @import_specifier.after_scope -> @alias.pop + attr (alias_pop) node_definition = @alias + attr (name_push) node_reference = @name + edge alias_pop -> name_push + edge name_push -> @import_specifier.source + edge @import_specifier.after_scope -> alias_pop } @@ -895,9 +896,9 @@ inherit .return_or_yield ; edge @mod_name.push -> ROOT_NODE ; ; attr (@name) node_reference = @name -; attr (@name.push_dot) push_symbol = "GUARD:MEMBER" -; edge @name.push_dot -> @mod_name.push -; edge @name -> @name.push_dot +; attr (name_push_dot) push_symbol = "GUARD:MEMBER" +; edge name_push_dot -> @mod_name.push +; edge name -> @name_push_dot ; ; attr (@alias) node_definition = @alias ; edge @alias -> @name @@ -914,17 +915,17 @@ inherit .return_or_yield (import_clause (identifier)@default_name)@import_clause { - node @default_name.pop - node @default_name.push_guard_default + node default_name_pop + node default_name_push_guard_default edge @import_clause.after_scope -> @import_clause.before_scope - attr (@default_name.pop) node_definition = @default_name - attr (@default_name.push_guard_default) push_symbol = "GUARD:DEFAULT" - edge @default_name.pop -> @default_name.push_guard_default - edge @default_name.push_guard_default -> @import_clause.source + attr (default_name_pop) node_definition = @default_name + attr (default_name_push_guard_default) push_symbol = "GUARD:DEFAULT" + edge default_name_pop -> default_name_push_guard_default + edge default_name_push_guard_default -> @import_clause.source - edge @import_clause.after_scope -> @default_name.pop + edge @import_clause.after_scope -> default_name_pop } @@ -1062,19 +1063,19 @@ inherit .return_or_yield parameters:(_)@call_sig body:(_)@body)@fun_decl { - node @call_sig.arguments_pop - node @call_sig.arguments_push - node @call_sig.this_pop - node @call_sig.this_push + node call_sig_arguments_pop + node call_sig_arguments_push + node call_sig_this_pop + node call_sig_this_push node @name.pop - node @fun_decl.function_value + node fun_decl_function_value node @fun_decl.return_or_yield node @fun_decl.value_arg_scope - node @fun_decl.value_call - node @fun_decl.value_drop - node @fun_decl.value_return - node @fun_decl.value_this - node @fun_decl.value_this_guard + node fun_decl_value_call + node fun_decl_value_drop + node fun_decl_value_return + node fun_decl_value_this + node fun_decl_value_this_guard attr (@name.pop) syntax_type = "function" @@ -1084,43 +1085,43 @@ inherit .return_or_yield ; with an augmentation for the function attr (@name.pop) node_definition = @name edge @fun_decl.after_scope -> @name.pop - edge @name.pop -> @fun_decl.function_value + edge @name.pop -> fun_decl_function_value ; function values have drop nodes that handle closures, that points to the ; before scope for the function - attr (@fun_decl.value_drop) type = "drop_scopes" - edge @fun_decl.value_drop -> @fun_decl.before_scope + attr (fun_decl_value_drop) type = "drop_scopes" + edge fun_decl_value_drop -> @fun_decl.before_scope ; the call sig's before scope comes from the drop node then flows into the body - edge @call_sig.before_scope -> @fun_decl.value_drop - attr (@call_sig.this_pop) symbol_definition = "this", source_node = @call_sig - attr (@call_sig.this_push) push_symbol = "this" - edge @call_sig.this_pop -> @call_sig.this_push - edge @call_sig.this_push -> @fun_decl.value_arg_scope - edge @call_sig.before_scope -> @call_sig.this_pop - attr (@call_sig.arguments_pop) symbol_definition = "arguments", source_node = @call_sig - attr (@call_sig.arguments_push) push_symbol = "arguments" - edge @call_sig.arguments_pop -> @call_sig.arguments_push - edge @call_sig.arguments_push -> @fun_decl.value_arg_scope - edge @call_sig.before_scope -> @call_sig.arguments_pop + edge @call_sig.before_scope -> fun_decl_value_drop + attr (call_sig_this_pop) symbol_definition = "this", source_node = @call_sig + attr (call_sig_this_push) push_symbol = "this" + edge call_sig_this_pop -> call_sig_this_push + edge call_sig_this_push -> @fun_decl.value_arg_scope + edge @call_sig.before_scope -> call_sig_this_pop + attr (call_sig_arguments_pop) symbol_definition = "arguments", source_node = @call_sig + attr (call_sig_arguments_push) push_symbol = "arguments" + edge call_sig_arguments_pop -> call_sig_arguments_push + edge call_sig_arguments_push -> @fun_decl.value_arg_scope + edge @call_sig.before_scope -> call_sig_arguments_pop edge @body.before_scope -> @call_sig.after_scope ; function values have call nodes - attr (@fun_decl.value_call) pop_scoped_symbol = "()" - edge @fun_decl.function_value -> @fun_decl.value_call + attr (fun_decl_value_call) pop_scoped_symbol = "()" + edge fun_decl_function_value -> fun_decl_value_call ; function values have return nodes which need to be visible for returns - attr (@fun_decl.value_return) pop_symbol = "GUARD:RETURN" - edge @fun_decl.value_call -> @fun_decl.value_return - let @body.return_or_yield = @fun_decl.value_return + attr (fun_decl_value_return) pop_symbol = "GUARD:RETURN" + edge fun_decl_value_call -> fun_decl_value_return + let @body.return_or_yield = fun_decl_value_return ; method values have this nodes which need to be visible for constructor calls - attr (@fun_decl.value_this) push_symbol = "this" - attr (@fun_decl.value_this_guard) pop_symbol = "GUARD:THIS" - edge @fun_decl.value_call -> @fun_decl.value_this_guard - edge @fun_decl.value_this_guard -> @fun_decl.value_this - edge @fun_decl.value_this -> @body.after_scope + attr (fun_decl_value_this) push_symbol = "this" + attr (fun_decl_value_this_guard) pop_symbol = "GUARD:THIS" + edge fun_decl_value_call -> fun_decl_value_this_guard + edge fun_decl_value_this_guard -> fun_decl_value_this + edge fun_decl_value_this -> @body.after_scope ; function values have a jump node that lets params connect up to actual arguments edge @fun_decl.value_arg_scope -> JUMP_TO_SCOPE_NODE @@ -1130,12 +1131,12 @@ inherit .return_or_yield parameters: (formal_parameters (_)@param))@fun_decl { - node @param.arg_index + node param_arg_index ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = (named-child-index @param) - edge @param.covalue -> @param.arg_index - edge @param.arg_index -> @fun_decl.value_arg_scope + attr (param_arg_index) push_symbol = (named-child-index @param) + edge @param.covalue -> param_arg_index + edge param_arg_index -> @fun_decl.value_arg_scope } @@ -1146,19 +1147,19 @@ inherit .return_or_yield parameters:(_)@call_sig body:(_)@body)@fun_decl { - node @call_sig.arguments_pop - node @call_sig.arguments_push - node @call_sig.this_pop - node @call_sig.this_push + node call_sig_arguments_pop + node call_sig_arguments_push + node call_sig_this_pop + node call_sig_this_push node @name.pop - node @fun_decl.function_value + node fun_decl_function_value node @fun_decl.return_or_yield node @fun_decl.value_arg_scope - node @fun_decl.value_call - node @fun_decl.value_drop - node @fun_decl.value_return - node @fun_decl.value_this - node @fun_decl.value_this_guard + node fun_decl_value_call + node fun_decl_value_drop + node fun_decl_value_return + node fun_decl_value_this + node fun_decl_value_this_guard attr (@name.pop) syntax_type = "function" @@ -1168,43 +1169,43 @@ inherit .return_or_yield ; with an augmentation for the function attr (@name.pop) node_definition = @name edge @fun_decl.after_scope -> @name.pop - edge @name.pop -> @fun_decl.function_value + edge @name.pop -> fun_decl_function_value ; function values have drop nodes that handle closures, that points to the ; before scope of the declaration - attr (@fun_decl.value_drop) type = "drop_scopes" - edge @fun_decl.value_drop -> @fun_decl.before_scope + attr (fun_decl_value_drop) type = "drop_scopes" + edge fun_decl_value_drop -> @fun_decl.before_scope ; the call sig's before scope comes from the drop node then flows into the body - edge @call_sig.before_scope -> @fun_decl.value_drop - attr (@call_sig.this_pop) symbol_definition = "this", source_node = @call_sig - attr (@call_sig.this_push) push_symbol = "this" - edge @call_sig.this_pop -> @call_sig.this_push - edge @call_sig.this_push -> @fun_decl.value_arg_scope - edge @call_sig.before_scope -> @call_sig.this_pop - attr (@call_sig.arguments_pop) symbol_definition = "arguments", source_node = @call_sig - attr (@call_sig.arguments_push) push_symbol = "arguments" - edge @call_sig.arguments_pop -> @call_sig.arguments_push - edge @call_sig.arguments_push -> @fun_decl.value_arg_scope - edge @call_sig.before_scope -> @call_sig.arguments_pop + edge @call_sig.before_scope -> fun_decl_value_drop + attr (call_sig_this_pop) symbol_definition = "this", source_node = @call_sig + attr (call_sig_this_push) push_symbol = "this" + edge call_sig_this_pop -> call_sig_this_push + edge call_sig_this_push -> @fun_decl.value_arg_scope + edge @call_sig.before_scope -> call_sig_this_pop + attr (call_sig_arguments_pop) symbol_definition = "arguments", source_node = @call_sig + attr (call_sig_arguments_push) push_symbol = "arguments" + edge call_sig_arguments_pop -> call_sig_arguments_push + edge call_sig_arguments_push -> @fun_decl.value_arg_scope + edge @call_sig.before_scope -> call_sig_arguments_pop edge @body.before_scope -> @call_sig.after_scope ; function values have call nodes - attr (@fun_decl.value_call) pop_scoped_symbol = "()" - edge @fun_decl.function_value -> @fun_decl.value_call + attr (fun_decl_value_call) pop_scoped_symbol = "()" + edge fun_decl_function_value -> fun_decl_value_call ; function values have return nodes which need to be visible for returns - attr (@fun_decl.value_return) pop_symbol = "GUARD:RETURN" - edge @fun_decl.value_call -> @fun_decl.value_return - let @body.return_or_yield = @fun_decl.value_return + attr (fun_decl_value_return) pop_symbol = "GUARD:RETURN" + edge fun_decl_value_call -> fun_decl_value_return + let @body.return_or_yield = fun_decl_value_return ; method values have this nodes which need to be visible for constructor calls - attr (@fun_decl.value_this) push_symbol = "this" - attr (@fun_decl.value_this_guard) pop_symbol = "GUARD:THIS" - edge @fun_decl.value_call -> @fun_decl.value_this_guard - edge @fun_decl.value_this_guard -> @fun_decl.value_this - edge @fun_decl.value_this -> @body.after_scope + attr (fun_decl_value_this) push_symbol = "this" + attr (fun_decl_value_this_guard) pop_symbol = "GUARD:THIS" + edge fun_decl_value_call -> fun_decl_value_this_guard + edge fun_decl_value_this_guard -> fun_decl_value_this + edge fun_decl_value_this -> @body.after_scope ; function values have a jump node that lets params connect up to actual arguments edge @fun_decl.value_arg_scope -> JUMP_TO_SCOPE_NODE @@ -1214,12 +1215,12 @@ inherit .return_or_yield parameters: (formal_parameters (_)@param))@fun_decl { - node @param.arg_index + node param_arg_index ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = (named-child-index @param) - edge @param.covalue -> @param.arg_index - edge @param.arg_index -> @fun_decl.value_arg_scope + attr (param_arg_index) push_symbol = (named-child-index @param) + edge @param.covalue -> param_arg_index + edge param_arg_index -> @fun_decl.value_arg_scope } @@ -1297,12 +1298,12 @@ inherit .return_or_yield (#eq? @name "constructor") ) { - node @name.constructor_guard + node name_constructor_guard ; augmentation for the constructor - attr (@name.constructor_guard) symbol_definition = "GUARD:CONSTRUCTOR", source_node = @name - edge @method_def.after_scope -> @name.constructor_guard - edge @name.constructor_guard -> @method_def.method_value + attr (name_constructor_guard) symbol_definition = "GUARD:CONSTRUCTOR", source_node = @name + edge @method_def.after_scope -> name_constructor_guard + edge name_constructor_guard -> @method_def.method_value } ( @@ -1311,12 +1312,12 @@ inherit .return_or_yield (#not-eq? @name "constructor") ) { - node @name.pop_dot + node name_pop_dot ; augmentation for the method attr (@name.pop) node_definition = @name - attr (@name.pop_dot) pop_symbol = "GUARD:MEMBER" - edge @method_def.after_scope -> @name.pop_dot - edge @name.pop_dot -> @name.pop + attr (name_pop_dot) pop_symbol = "GUARD:MEMBER" + edge @method_def.after_scope -> name_pop_dot + edge name_pop_dot -> @name.pop edge @name.pop -> @method_def.method_value } @@ -1326,11 +1327,11 @@ inherit .return_or_yield body:(_)@body)@method_def { node @method_def.method_value_arg_scope - node @method_def.method_value_call - node @method_def.method_value_drop - node @method_def.method_value_return - node @method_def.method_value_this - node @method_def.method_value_this_guard + node method_def_method_value_call + node method_def_method_value_drop + node method_def_method_value_return + node method_def_method_value_this + node method_def_method_value_this_guard attr (@name.pop) syntax_type = "method" @@ -1339,28 +1340,28 @@ inherit .return_or_yield ; method values have drop nodes that handle closures, that points to the ; before scope from method def - attr (@method_def.method_value_drop) type = "drop_scopes" - edge @method_def.method_value_drop -> @method_def.before_scope + attr (method_def_method_value_drop) type = "drop_scopes" + edge method_def_method_value_drop -> @method_def.before_scope ; the call sig's before scope comes from the drop node then flows into the body - edge @call_sig.before_scope -> @method_def.method_value_drop + edge @call_sig.before_scope -> method_def_method_value_drop edge @body.before_scope -> @call_sig.after_scope ; method values have call nodes - attr (@method_def.method_value_call) pop_scoped_symbol = "()" - edge @method_def.method_value -> @method_def.method_value_call + attr (method_def_method_value_call) pop_scoped_symbol = "()" + edge @method_def.method_value -> method_def_method_value_call ; method values have return nodes which need to be visible for returns - attr (@method_def.method_value_return) pop_symbol = "GUARD:RETURN" - edge @method_def.method_value_call -> @method_def.method_value_return - let @body.return_or_yield = @method_def.method_value_return + attr (method_def_method_value_return) pop_symbol = "GUARD:RETURN" + edge method_def_method_value_call -> method_def_method_value_return + let @body.return_or_yield = method_def_method_value_return ; method values have this nodes which need to be visible for constructor calls - attr (@method_def.method_value_this) push_symbol = "this" - attr (@method_def.method_value_this_guard) pop_symbol = "GUARD:THIS" - edge @method_def.method_value_call -> @method_def.method_value_this_guard - edge @method_def.method_value_this_guard -> @method_def.method_value_this - edge @method_def.method_value_this -> @body.after_scope + attr (method_def_method_value_this) push_symbol = "this" + attr (method_def_method_value_this_guard) pop_symbol = "GUARD:THIS" + edge method_def_method_value_call -> method_def_method_value_this_guard + edge method_def_method_value_this_guard -> method_def_method_value_this + edge method_def_method_value_this -> @body.after_scope ; method values have a jump node that lets params connect up to actual arguments edge @method_def.method_value_arg_scope -> JUMP_TO_SCOPE_NODE @@ -1370,12 +1371,12 @@ inherit .return_or_yield parameters: (formal_parameters (_)@param))@method_def { - node @param.arg_index + node param_arg_index ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = (named-child-index @param) - edge @param.covalue -> @param.arg_index - edge @param.arg_index -> @method_def.method_value_arg_scope + attr (param_arg_index) push_symbol = (named-child-index @param) + edge @param.covalue -> param_arg_index + edge param_arg_index -> @method_def.method_value_arg_scope } @@ -1386,12 +1387,12 @@ inherit .return_or_yield node @field_def.after_scope node @field_def.before_scope node @property.pop - node @property.pop_dot + node property_pop_dot attr (@property.pop) node_definition = @property - attr (@property.pop_dot) pop_symbol = "GUARD:MEMBER" - edge @field_def.after_scope -> @property.pop_dot - edge @property.pop_dot -> @property.pop + attr (property_pop_dot) pop_symbol = "GUARD:MEMBER" + edge @field_def.after_scope -> property_pop_dot + edge property_pop_dot -> @property.pop } (field_definition @@ -1654,13 +1655,13 @@ inherit .return_or_yield (for_in_statement left:(identifier)@left right:(_)@right - body:(_)@body)@for_in_stmt + body:(_)@body)@_for_in_stmt { - node @for_in_stmt.pop - attr (@for_in_stmt.pop) node_definition = @left - edge @for_in_stmt.pop -> @right.value - edge @body.before_scope -> @for_in_stmt.pop + node for_in_stmt_pop + attr (for_in_stmt_pop) node_definition = @left + edge for_in_stmt_pop -> @right.value + edge @body.before_scope -> for_in_stmt_pop } @@ -1755,12 +1756,12 @@ inherit .return_or_yield (catch_clause parameter:(identifier)@name - body:(_)@body)@catch_clause + body:(_)@body)@_catch_clause { - node @catch_clause.pop - attr (@catch_clause.pop) node_definition = @name - edge @body.before_scope -> @catch_clause.pop + node catch_clause_pop + attr (catch_clause_pop) node_definition = @name + edge @body.before_scope -> catch_clause_pop } @@ -1781,16 +1782,16 @@ inherit .return_or_yield body:(_)@body)@with_stmt { - node @with_stmt.push_dot + node with_stmt_push_dot ; scopes flow from the statement into the object then into the body then back out edge @object.before_scope -> @with_stmt.before_scope edge @body.before_scope -> @object.after_scope edge @with_stmt.after_scope -> @body.after_scope - attr (@with_stmt.push_dot) push_symbol = "GUARD:MEMBER" - edge @with_stmt.push_dot -> @object.value - edge @body.before_scope -> @with_stmt.push_dot + attr (with_stmt_push_dot) push_symbol = "GUARD:MEMBER" + edge with_stmt_push_dot -> @object.value + edge @body.before_scope -> with_stmt_push_dot } @@ -1804,14 +1805,14 @@ inherit .return_or_yield (break_statement (_)@label)@break_stmt { - node @break_stmt.label_guard - node @break_stmt.label_push + node break_stmt_label_guard + node break_stmt_label_push - attr (@break_stmt.label_guard) push_symbol = "GUARD:LABEL" - attr (@break_stmt.label_push) node_reference = @label + attr (break_stmt_label_guard) push_symbol = "GUARD:LABEL" + attr (break_stmt_label_push) node_reference = @label - edge @break_stmt.label_push -> @break_stmt.label_guard - edge @break_stmt.label_guard -> @break_stmt.before_scope + edge break_stmt_label_push -> break_stmt_label_guard + edge break_stmt_label_guard -> @break_stmt.before_scope } @@ -1825,14 +1826,14 @@ inherit .return_or_yield (continue_statement (_)@label)@continue_stmt { - node @continue_stmt.label_guard - node @continue_stmt.label_push + node continue_stmt_label_guard + node continue_stmt_label_push - attr (@continue_stmt.label_guard) push_symbol = "GUARD:LABEL" - attr (@continue_stmt.label_push) node_reference = @label + attr (continue_stmt_label_guard) push_symbol = "GUARD:LABEL" + attr (continue_stmt_label_push) node_reference = @label - edge @continue_stmt.label_push -> @continue_stmt.label_guard - edge @continue_stmt.label_guard -> @continue_stmt.before_scope + edge continue_stmt_label_push -> continue_stmt_label_guard + edge continue_stmt_label_guard -> @continue_stmt.before_scope } @@ -1883,16 +1884,16 @@ inherit .return_or_yield body:(_)@inner)@labeled_stmt { - node @labeled_stmt.label_guard - node @labeled_stmt.label_pop + node labeled_stmt_label_guard + node labeled_stmt_label_pop - attr (@labeled_stmt.label_guard) pop_symbol = "GUARD:LABEL" - attr (@labeled_stmt.label_pop) node_definition = @label + attr (labeled_stmt_label_guard) pop_symbol = "GUARD:LABEL" + attr (labeled_stmt_label_pop) node_definition = @label ; scopes flow through the inner statement then back out edge @inner.before_scope -> @labeled_stmt.before_scope - edge @inner.before_scope -> @labeled_stmt.label_guard - edge @labeled_stmt.label_guard -> @labeled_stmt.label_pop + edge @inner.before_scope -> labeled_stmt_label_guard + edge labeled_stmt_label_guard -> labeled_stmt_label_pop edge @labeled_stmt.after_scope -> @inner.after_scope } @@ -2398,56 +2399,56 @@ inherit .return_or_yield parameters:(_)@call_sig body:(_)@body)@fun { - node @call_sig.arguments_pop - node @call_sig.arguments_push - node @call_sig.this_pop - node @call_sig.this_push + node call_sig_arguments_pop + node call_sig_arguments_push + node call_sig_this_pop + node call_sig_this_push node @fun.return_or_yield node @fun.value_arg_scope - node @fun.value_call - node @fun.value_drop - node @fun.value_return - node @fun.value_this - node @fun.value_this_guard + node fun_value_call + node fun_value_drop + node fun_value_return + node fun_value_this + node fun_value_this_guard ; scope flows across the decl edge @fun.after_scope -> @fun.before_scope ; function values have drop nodes that handle closures, that points to the ; before scope from the function - attr (@fun.value_drop) type = "drop_scopes" - edge @fun.value_drop -> @fun.before_scope + attr (fun_value_drop) type = "drop_scopes" + edge fun_value_drop -> @fun.before_scope ; the call sig's before scope comes from the drop node, ; then flows into the body, and includes a variable binding for "this" - edge @call_sig.before_scope -> @fun.value_drop - attr (@call_sig.this_pop) symbol_definition = "this", source_node = @call_sig - attr (@call_sig.this_push) push_symbol = "this" - edge @call_sig.this_pop -> @call_sig.this_push - edge @call_sig.this_push -> @fun.value_arg_scope - edge @call_sig.before_scope -> @call_sig.this_pop - attr (@call_sig.arguments_pop) symbol_definition = "arguments", source_node = @call_sig - attr (@call_sig.arguments_push) push_symbol = "arguments" - edge @call_sig.arguments_pop -> @call_sig.arguments_push - edge @call_sig.arguments_push -> @fun.value_arg_scope - edge @call_sig.before_scope -> @call_sig.arguments_pop + edge @call_sig.before_scope -> fun_value_drop + attr (call_sig_this_pop) symbol_definition = "this", source_node = @call_sig + attr (call_sig_this_push) push_symbol = "this" + edge call_sig_this_pop -> call_sig_this_push + edge call_sig_this_push -> @fun.value_arg_scope + edge @call_sig.before_scope -> call_sig_this_pop + attr (call_sig_arguments_pop) symbol_definition = "arguments", source_node = @call_sig + attr (call_sig_arguments_push) push_symbol = "arguments" + edge call_sig_arguments_pop -> call_sig_arguments_push + edge call_sig_arguments_push -> @fun.value_arg_scope + edge @call_sig.before_scope -> call_sig_arguments_pop edge @body.before_scope -> @call_sig.after_scope ; function values have call nodes - attr (@fun.value_call) pop_scoped_symbol = "()" - edge @fun.value -> @fun.value_call + attr (fun_value_call) pop_scoped_symbol = "()" + edge @fun.value -> fun_value_call ; function values have return nodes which need to be visible for returns - attr (@fun.value_return) pop_symbol = "GUARD:RETURN" - edge @fun.value_call -> @fun.value_return - let @body.return_or_yield = @fun.value_return + attr (fun_value_return) pop_symbol = "GUARD:RETURN" + edge fun_value_call -> fun_value_return + let @body.return_or_yield = fun_value_return ; function values have this nodes which need to be visible for method calls - attr (@fun.value_this) push_symbol = "this" - attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" - edge @fun.value_call -> @fun.value_this_guard - edge @fun.value_this_guard -> @fun.value_this - edge @fun.value_this -> @body.after_scope + attr (fun_value_this) push_symbol = "this" + attr (fun_value_this_guard) pop_symbol = "GUARD:THIS" + edge fun_value_call -> fun_value_this_guard + edge fun_value_this_guard -> fun_value_this + edge fun_value_this -> @body.after_scope ; function values have a jump node that lets params connect up to actual arguments edge @fun.value_arg_scope -> JUMP_TO_SCOPE_NODE @@ -2457,12 +2458,12 @@ inherit .return_or_yield parameters: (formal_parameters (_)@param))@fun { - node @param.arg_index + node param_arg_index ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = (named-child-index @param) - edge @param.covalue -> @param.arg_index - edge @param.arg_index -> @fun.value_arg_scope + attr (param_arg_index) push_symbol = (named-child-index @param) + edge @param.covalue -> param_arg_index + edge param_arg_index -> @fun.value_arg_scope } @@ -2482,39 +2483,39 @@ inherit .return_or_yield node @fun.return_or_yield node @fun.value_arg_scope - node @fun.value_call - node @fun.value_drop - node @fun.value_return - node @fun.value_this - node @fun.value_this_guard + node fun_value_call + node fun_value_drop + node fun_value_return + node fun_value_this + node fun_value_this_guard ; scope flows across the decl edge @fun.after_scope -> @fun.before_scope ; function values have drop nodes that handle closures, that points to the ; before scope from the function - attr (@fun.value_drop) type = "drop_scopes" - edge @fun.value_drop -> @fun.before_scope + attr (fun_value_drop) type = "drop_scopes" + edge fun_value_drop -> @fun.before_scope ; the call sig's before scope comes from the drop node then flows into the body - edge @call_sig.before_scope -> @fun.value_drop + edge @call_sig.before_scope -> fun_value_drop edge @body.before_scope -> @call_sig.after_scope ; function values have call nodes - attr (@fun.value_call) pop_scoped_symbol = "()" - edge @fun.value -> @fun.value_call + attr (fun_value_call) pop_scoped_symbol = "()" + edge @fun.value -> fun_value_call ; function values have return nodes which need to be visible for returns - attr (@fun.value_return) pop_symbol = "GUARD:RETURN" - edge @fun.value_call -> @fun.value_return - let @body.return_or_yield = @fun.value_return + attr (fun_value_return) pop_symbol = "GUARD:RETURN" + edge fun_value_call -> fun_value_return + let @body.return_or_yield = fun_value_return ; function values have this nodes which need to be visible for method calls - attr (@fun.value_this) push_symbol = "this" - attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" - edge @fun.value_call -> @fun.value_this_guard - edge @fun.value_this_guard -> @fun.value_this - edge @fun.value_this -> @body.after_scope + attr (fun_value_this) push_symbol = "this" + attr (fun_value_this_guard) pop_symbol = "GUARD:THIS" + edge fun_value_call -> fun_value_this_guard + edge fun_value_this_guard -> fun_value_this + edge fun_value_this -> @body.after_scope ; function values have a jump node that lets params connect up to actual arguments edge @fun.value_arg_scope -> JUMP_TO_SCOPE_NODE @@ -2530,35 +2531,35 @@ inherit .return_or_yield parameter:(_)@param)@fun { node @param.after_scope - node @param.arg_index + node param_arg_index node @param.before_scope node @param.covalue - node @param.pop + node param_pop ; scope flows from the param right back out edge @param.after_scope -> @param.before_scope ; but augmented with a pop, b/c it's not a pattern - attr (@param.pop) node_definition = @param - edge @param.pop -> @param.covalue - edge @param.after_scope -> @param.pop + attr (param_pop) node_definition = @param + edge param_pop -> @param.covalue + edge @param.after_scope -> param_pop ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = "0" - edge @param.covalue -> @param.arg_index - edge @param.arg_index -> @fun.value_arg_scope + attr (param_arg_index) push_symbol = "0" + edge @param.covalue -> param_arg_index + edge param_arg_index -> @fun.value_arg_scope } (arrow_function parameters: (formal_parameters (_)@param))@fun { - node @param.arg_index + node param_arg_index ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = (named-child-index @param) - edge @param.covalue -> @param.arg_index - edge @param.arg_index -> @fun.value_arg_scope + attr (param_arg_index) push_symbol = (named-child-index @param) + edge @param.covalue -> param_arg_index + edge param_arg_index -> @fun.value_arg_scope } @@ -2587,39 +2588,39 @@ inherit .return_or_yield node @fun.return_or_yield node @fun.value_arg_scope - node @fun.value_call - node @fun.value_drop - node @fun.value_return - node @fun.value_this - node @fun.value_this_guard + node fun_value_call + node fun_value_drop + node fun_value_return + node fun_value_this + node fun_value_this_guard ; scope flows across the decl edge @fun.after_scope -> @fun.before_scope ; function values have drop nodes that handle closures, that points to the ; before scope from the function - attr (@fun.value_drop) type = "drop_scopes" - edge @fun.value_drop -> @fun.before_scope + attr (fun_value_drop) type = "drop_scopes" + edge fun_value_drop -> @fun.before_scope ; the call sig's before scope comes from the drop node then flows into the body - edge @call_sig.before_scope -> @fun.value_drop + edge @call_sig.before_scope -> fun_value_drop edge @body.before_scope -> @call_sig.after_scope ; function values have call nodes - attr (@fun.value_call) pop_scoped_symbol = "()" - edge @fun.value -> @fun.value_call + attr (fun_value_call) pop_scoped_symbol = "()" + edge @fun.value -> fun_value_call ; function values have return nodes which need to be visible for returns - attr (@fun.value_return) pop_symbol = "GUARD:RETURN" - edge @fun.value_call -> @fun.value_return - let @body.return_or_yield = @fun.value_return + attr (fun_value_return) pop_symbol = "GUARD:RETURN" + edge fun_value_call -> fun_value_return + let @body.return_or_yield = fun_value_return ; function values have this nodes which need to be visible for method calls - attr (@fun.value_this) push_symbol = "this" - attr (@fun.value_this_guard) pop_symbol = "GUARD:THIS" - edge @fun.value_call -> @fun.value_this_guard - edge @fun.value_this_guard -> @fun.value_this - edge @fun.value_this -> @body.after_scope + attr (fun_value_this) push_symbol = "this" + attr (fun_value_this_guard) pop_symbol = "GUARD:THIS" + edge fun_value_call -> fun_value_this_guard + edge fun_value_this_guard -> fun_value_this + edge fun_value_this -> @body.after_scope ; function values have a jump node that lets params connect up to actual arguments edge @fun.value_arg_scope -> JUMP_TO_SCOPE_NODE @@ -2629,12 +2630,12 @@ inherit .return_or_yield parameters: (formal_parameters (_)@param))@fun { - node @param.arg_index + node param_arg_index ; parameters jump to the pushed argument scope - attr (@param.arg_index) push_symbol = (named-child-index @param) - edge @param.covalue -> @param.arg_index - edge @param.arg_index -> @fun.value_arg_scope + attr (param_arg_index) push_symbol = (named-child-index @param) + edge @param.covalue -> param_arg_index + edge param_arg_index -> @fun.value_arg_scope } @@ -2656,33 +2657,33 @@ inherit .return_or_yield function:(_)@function arguments:(_)@arguments)@call_expr { - node @arguments.arg_arguments - node @arguments.arg_arguments_dot + node arguments_arg_arguments + node arguments_arg_arguments_dot node @arguments.arg_scope attr (@arguments.arg_scope) is_exported node @arguments.arg_scope_no_this node @arguments.arg_this - node @call_expr.call - node @call_expr.return_guard + node call_expr_call + node call_expr_return_guard ; value is a call, ie a push "()" node w/ "push-scope" @arguments - attr (@call_expr.return_guard) push_symbol = "GUARD:RETURN" - attr (@call_expr.call) push_scoped_symbol = "()", scope = @arguments.arg_scope - edge @call_expr.value -> @call_expr.return_guard - edge @call_expr.return_guard -> @call_expr.call - edge @call_expr.call -> @function.value + attr (call_expr_return_guard) push_symbol = "GUARD:RETURN" + attr (call_expr_call) push_scoped_symbol = "()", scope = @arguments.arg_scope + edge @call_expr.value -> call_expr_return_guard + edge call_expr_return_guard -> call_expr_call + edge call_expr_call -> @function.value attr (@arguments.arg_this) symbol_definition = "this", source_node = @arguments edge @arguments.arg_scope -> @arguments.arg_this edge @arguments.arg_scope -> @arguments.arg_scope_no_this - attr (@arguments.arg_arguments) symbol_definition = "arguments", source_node = @arguments - attr (@arguments.arg_arguments_dot) pop_symbol = "GUARD:MEMBER" - edge @arguments.arg_scope -> @arguments.arg_arguments - edge @arguments.arg_arguments -> @arguments.arg_arguments_dot - edge @arguments.arg_arguments_dot -> @arguments.arg_scope_no_this - edge @arguments.arg_arguments -> @call_expr.builtins_arguments_prototype + attr (arguments_arg_arguments) symbol_definition = "arguments", source_node = @arguments + attr (arguments_arg_arguments_dot) pop_symbol = "GUARD:MEMBER" + edge @arguments.arg_scope -> arguments_arg_arguments + edge arguments_arg_arguments -> arguments_arg_arguments_dot + edge arguments_arg_arguments_dot -> @arguments.arg_scope_no_this + edge arguments_arg_arguments -> @call_expr.builtins_arguments_prototype } ; special case to make `this` bind correctly in calls of the forms `x.f(...)` @@ -2710,10 +2711,10 @@ inherit .return_or_yield (call_expression arguments:(arguments (_)@arg)@arguments) { - node @arg.arg_index - attr (@arg.arg_index) pop_symbol = (named-child-index @arg) - edge @arguments.arg_scope_no_this -> @arg.arg_index - edge @arg.arg_index -> @arg.value + node arg_arg_index + attr (arg_arg_index) pop_symbol = (named-child-index @arg) + edge @arguments.arg_scope_no_this -> arg_arg_index + edge arg_arg_index -> @arg.value } @@ -2784,7 +2785,7 @@ inherit .return_or_yield index: (_)@index)@subscript_expr { node @subscript_expr.index_push - node @subscript_expr.push_dot + node subscript_expr_push_dot ; scopes flow left to right edge @object.before_scope -> @subscript_expr.before_scope @@ -2792,13 +2793,13 @@ inherit .return_or_yield edge @subscript_expr.after_scope -> @index.after_scope ; value is a subscript lookup, ie a push then push dot - attr (@subscript_expr.push_dot) push_symbol = "GUARD:MEMBER" - edge @subscript_expr.push_dot -> @object.value + attr (subscript_expr_push_dot) push_symbol = "GUARD:MEMBER" + edge subscript_expr_push_dot -> @object.value ; this is done differently depending on what the index is ; attr @index.push "push" = @index, "reference" edge @subscript_expr.value -> @subscript_expr.index_push - edge @subscript_expr.index_push -> @subscript_expr.push_dot + edge @subscript_expr.index_push -> subscript_expr_push_dot } @@ -2830,30 +2831,30 @@ inherit .return_or_yield node @arguments.arg_scope attr (@arguments.arg_scope) is_exported node @arguments.arg_this - node @constructor.constructor - node @new_expr.call - node @new_expr.guard_this + node constructor_constructor + node new_expr_call + node new_expr_guard_this edge @constructor.before_scope -> @new_expr.before_scope edge @arguments.before_scope -> @constructor.after_scope edge @new_expr.after_scope -> @arguments.after_scope - attr (@new_expr.call) push_scoped_symbol = "()", scope = @arguments.arg_scope + attr (new_expr_call) push_scoped_symbol = "()", scope = @arguments.arg_scope ; we guard for constructors for the case where we have a "true" class - attr (@constructor.constructor) push_symbol = "GUARD:CONSTRUCTOR" - edge @new_expr.call -> @constructor.constructor - edge @constructor.constructor -> @constructor.value + attr (constructor_constructor) push_symbol = "GUARD:CONSTRUCTOR" + edge new_expr_call -> constructor_constructor + edge constructor_constructor -> @constructor.value ; and also just go right to the value incase we have a function-as-constructor - edge @new_expr.call -> @constructor.value + edge new_expr_call -> @constructor.value ; value coming from the constructor call - attr (@new_expr.guard_this) push_symbol = "GUARD:THIS" - edge @new_expr.value -> @new_expr.guard_this - edge @new_expr.guard_this -> @new_expr.call + attr (new_expr_guard_this) push_symbol = "GUARD:THIS" + edge @new_expr.value -> new_expr_guard_this + edge new_expr_guard_this -> new_expr_call ; value coming from the field decls in the class edge @new_expr.value -> @constructor.value @@ -2866,11 +2867,11 @@ inherit .return_or_yield (new_expression arguments:(arguments (_)@arg)@arguments) { - node @arg.arg_index + node arg_arg_index - attr (@arg.arg_index) pop_symbol = (named-child-index @arg) - edge @arguments.arg_scope -> @arg.arg_index - edge @arg.arg_index -> @arg.value + attr (arg_arg_index) pop_symbol = (named-child-index @arg) + edge @arguments.arg_scope -> arg_arg_index + edge arg_arg_index -> @arg.value } @@ -2892,17 +2893,17 @@ inherit .return_or_yield (update_expression argument: (_)@argument)@update_expr { - node @update_expr.pop + node update_expr_pop ; scope propagates through the operand then is updated by the expr edge @argument.before_scope -> @update_expr.before_scope edge @update_expr.after_scope -> @argument.after_scope ; LATER-TODO this isn't quite right because the update argument can't be an arbitrary expr ; eg f(x)++ doesn't make any sense, you have to have something more like ; (update_expression argument: (lvar)@argument) - attr (@update_expr.pop) node_definition = @argument + attr (update_expr_pop) node_definition = @argument edge @update_expr.value -> @argument.value - edge @update_expr.after_scope -> @update_expr.pop - edge @update_expr.pop -> @argument.value + edge @update_expr.after_scope -> update_expr_pop + edge update_expr_pop -> @argument.value } @@ -2976,26 +2977,26 @@ inherit .return_or_yield ; assignment to direct fields on `this` (assignment_expression left: (member_expression - object:(this)@this + object:(this)@_this property:(_)@property) right: (_)@right)@assignment_expr { - node @property.pop - node @this.drop - node @this.pop - node @this.pop_dot + node property_pop + node this_drop + node this_pop + node this_pop_dot ; HACK - attr (@this.drop) type = "drop_scopes" - edge @this.drop -> @this.pop - attr (@this.pop) pop_symbol = "this" - attr (@this.pop_dot) pop_symbol = "GUARD:MEMBER" - attr (@property.pop) node_definition = @property - edge @assignment_expr.after_scope -> @this.drop - edge @assignment_expr.after_scope -> @this.pop - edge @this.pop -> @this.pop_dot - edge @this.pop_dot -> @property.pop - edge @property.pop -> @right.value + attr (this_drop) type = "drop_scopes" + edge this_drop -> this_pop + attr (this_pop) pop_symbol = "this" + attr (this_pop_dot) pop_symbol = "GUARD:MEMBER" + attr (property_pop) node_definition = @property + edge @assignment_expr.after_scope -> this_drop + edge @assignment_expr.after_scope -> this_pop + edge this_pop -> this_pop_dot + edge this_pop_dot -> property_pop + edge property_pop -> @right.value } ; augmentation of scope via _destructuring_patterns @@ -3025,16 +3026,16 @@ inherit .return_or_yield left:(identifier)@left right:(_)@right)@augmented_assignment_expr { - node @augmented_assignment_expr.pop - node @augmented_assignment_expr.push + node augmented_assignment_expr_pop + node augmented_assignment_expr_push ; augment the scope - attr (@augmented_assignment_expr.pop) node_definition = @left - attr (@augmented_assignment_expr.push) node_reference = @left - edge @augmented_assignment_expr.push -> @augmented_assignment_expr.before_scope - edge @augmented_assignment_expr.pop -> @augmented_assignment_expr.push - edge @augmented_assignment_expr.pop -> @right.value - edge @augmented_assignment_expr.after_scope -> @augmented_assignment_expr.pop + attr (augmented_assignment_expr_pop) node_definition = @left + attr (augmented_assignment_expr_push) node_reference = @left + edge augmented_assignment_expr_push -> @augmented_assignment_expr.before_scope + edge augmented_assignment_expr_pop -> augmented_assignment_expr_push + edge augmented_assignment_expr_pop -> @right.value + edge @augmented_assignment_expr.after_scope -> augmented_assignment_expr_pop } @@ -3392,15 +3393,15 @@ inherit .return_or_yield ; scope propagation through identifier patterns (pattern/identifier)@ident_pat { - node @ident_pat.pop + node ident_pat_pop ; scope flows through, binding via a pop edge that goes to an unknown value - attr (@ident_pat.pop) node_definition = @ident_pat - edge @ident_pat.pop -> @ident_pat.covalue + attr (ident_pat_pop) node_definition = @ident_pat + edge ident_pat_pop -> @ident_pat.covalue edge @ident_pat.after_scope -> @ident_pat.before_scope - edge @ident_pat.after_scope -> @ident_pat.pop + edge @ident_pat.after_scope -> ident_pat_pop - edge @ident_pat.new_bindings -> @ident_pat.pop + edge @ident_pat.new_bindings -> ident_pat_pop } @@ -3457,13 +3458,13 @@ inherit .return_or_yield value:(_)@value_pat)@pair_pat { node @key.push - node @key.push_dot + node key_push_dot ; covalues flow in dotted - attr (@key.push_dot) push_symbol = "GUARD:MEMBER" + attr (key_push_dot) push_symbol = "GUARD:MEMBER" edge @value_pat.covalue -> @key.push - edge @key.push -> @key.push_dot - edge @key.push_dot -> @pair_pat.covalue + edge @key.push -> key_push_dot + edge key_push_dot -> @pair_pat.covalue ; scope flows into value pattern then back out edge @value_pat.before_scope -> @pair_pat.before_scope edge @pair_pat.after_scope -> @value_pat.after_scope @@ -3515,21 +3516,21 @@ inherit .return_or_yield left:(shorthand_property_identifier_pattern)@left_pat right:(_)@_right_expr)@object_assignment_pat { - node @left_pat.pop - node @left_pat.push - node @left_pat.push_dot + node left_pat_pop + node left_pat_push + node left_pat_push_dot edge @left_pat.after_scope -> @left_pat.before_scope - attr (@left_pat.push) node_reference = @left_pat - attr (@left_pat.push_dot) push_symbol = "GUARD:MEMBER" - attr (@left_pat.pop) node_definition = @left_pat - edge @left_pat.pop -> @left_pat.push - edge @left_pat.push -> @left_pat.push_dot - edge @left_pat.push_dot -> @left_pat.covalue - edge @object_assignment_pat.after_scope -> @left_pat.pop + attr (left_pat_push) node_reference = @left_pat + attr (left_pat_push_dot) push_symbol = "GUARD:MEMBER" + attr (left_pat_pop) node_definition = @left_pat + edge left_pat_pop -> left_pat_push + edge left_pat_push -> left_pat_push_dot + edge left_pat_push_dot -> @left_pat.covalue + edge @object_assignment_pat.after_scope -> left_pat_pop - edge @object_assignment_pat.new_bindings -> @left_pat.pop + edge @object_assignment_pat.new_bindings -> left_pat_pop } @@ -3580,11 +3581,11 @@ inherit .return_or_yield ; array pattern elements (array_pattern (_)@element_pat)@array_pat { - node @element_pat.element_index_push + node element_pat_element_index_push - attr (@element_pat.element_index_push) push_symbol = (named-child-index @element_pat) - edge @element_pat.covalue -> @element_pat.element_index_push - edge @element_pat.element_index_push -> @array_pat.element_index_push_dot + attr (element_pat_element_index_push) push_symbol = (named-child-index @element_pat) + edge @element_pat.covalue -> element_pat_element_index_push + edge element_pat_element_index_push -> @array_pat.element_index_push_dot edge @array_pat.new_bindings -> @element_pat.new_bindings } @@ -3621,11 +3622,12 @@ inherit .return_or_yield ;; #### Rest Patterns (rest_pattern (_)@name)@rest_pat { + node rest_pat_pop ; scope flows through, binding via a pop edge that goes to an unknown value - attr (@rest_pat.pop) node_definition = @name + attr (rest_pat_pop) node_definition = @name edge @rest_pat.after_scope -> @rest_pat.before_scope - edge @rest_pat.after_scope -> @rest_pat.pop + edge @rest_pat.after_scope -> rest_pat_pop } @@ -3674,10 +3676,10 @@ inherit .return_or_yield (#eq? @_extend "extend") ) { - node @object.pop - attr (@object.pop) node_definition = @object - edge @call_expr.after_scope -> @object.pop - edge @object.pop -> @new_fields.value + node object_pop + attr (object_pop) node_definition = @object + edge @call_expr.after_scope -> object_pop + edge object_pop -> @new_fields.value } @@ -3707,13 +3709,13 @@ inherit .return_or_yield (#eq? @_exports "exports") ) { - node @property.pop - node @property.pop_dot - attr (@property.pop) node_definition = @property - attr (@property.pop_dot) pop_symbol = "GUARD:MEMBER" - edge @assignment_expr.exports -> @property.pop_dot - edge @property.pop_dot -> @property.pop - edge @property.pop -> @right.value + node property_pop + node property_pop_dot + attr (property_pop) node_definition = @property + attr (property_pop_dot) pop_symbol = "GUARD:MEMBER" + edge @assignment_expr.exports -> property_pop_dot + edge property_pop_dot -> property_pop + edge property_pop -> @right.value } ( @@ -3742,19 +3744,20 @@ inherit .return_or_yield (#eq? @_require "require") ) { + node mod_name_module_guard + node mod_name_push + scan (source-text @mod_name) { "\"([^/\"]+)\.js\"$" { - attr (@mod_name.push) push_symbol = $1 + attr (mod_name_push) push_symbol = $1 } } - node @mod_name.module_guard - node @mod_name.push - attr (@mod_name.module_guard) push_symbol = "GUARD:EXPORTS" - edge @call_expr.value -> @mod_name.module_guard - edge @mod_name.module_guard -> @mod_name.push - edge @mod_name.push -> ROOT_NODE + attr (mod_name_module_guard) push_symbol = "GUARD:EXPORTS" + edge @call_expr.value -> mod_name_module_guard + edge mod_name_module_guard -> mod_name_push + edge mod_name_push -> ROOT_NODE } @@ -3876,14 +3879,14 @@ inherit .return_or_yield (arrow_function) ]@right) { - node @left.definiens_hook - node @left.ignore_guard + node left_definiens_hook + node left_ignore_guard - attr (@left.ignore_guard) pop_symbol = "GUARD:GANDALF" - attr (@left.definiens_hook) node_definition = @left - attr (@left.definiens_hook) definiens_node = @right - edge ROOT_NODE -> @left.ignore_guard - edge @left.ignore_guard -> @left.definiens_hook + attr (left_ignore_guard) pop_symbol = "GUARD:GANDALF" + attr (left_definiens_hook) node_definition = @left + attr (left_definiens_hook) definiens_node = @right + edge ROOT_NODE -> left_ignore_guard + edge left_ignore_guard -> left_definiens_hook } (variable_declaration @@ -3920,13 +3923,13 @@ inherit .return_or_yield (arrow_function) ]@value) { - node @name.definiens_hook - node @name.ignore_guard + node name_definiens_hook + node name_ignore_guard - attr (@name.ignore_guard) pop_symbol = "GUARD:GANDALF" - attr (@name.definiens_hook) node_definition = @name - attr (@name.definiens_hook) definiens_node = @value - edge ROOT_NODE -> @name.ignore_guard - edge @name.ignore_guard -> @name.definiens_hook + attr (name_ignore_guard) pop_symbol = "GUARD:GANDALF" + attr (name_definiens_hook) node_definition = @name + attr (name_definiens_hook) definiens_node = @value + edge ROOT_NODE -> name_ignore_guard + edge name_ignore_guard -> name_definiens_hook } From 73e72de3bc8e42caca65685b8408df7af34e4fb1 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Mon, 24 Jul 2023 18:34:12 -0700 Subject: [PATCH 112/500] Adds some missing tests, fixes naming error --- ...w.js => object_computed_property_name_flow.js} | 0 .../test/statements/debugger_statement.js | 8 ++++++++ .../test/statements/empty_statement.js | 8 ++++++++ .../test/statements/throw_statement.js | 15 +++++++++++++++ 4 files changed, 31 insertions(+) rename languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/{object_computed_proprety_name_flow.js => object_computed_property_name_flow.js} (100%) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/debugger_statement.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/empty_statement.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/throw_statement.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object_computed_proprety_name_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object_computed_property_name_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object_computed_proprety_name_flow.js rename to languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object_computed_property_name_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/debugger_statement.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/debugger_statement.js new file mode 100644 index 000000000..68839e773 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/debugger_statement.js @@ -0,0 +1,8 @@ +let x = 1; + +debugger; + +// Flow around + +/**/ x; +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/empty_statement.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/empty_statement.js new file mode 100644 index 000000000..a12d041a7 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/empty_statement.js @@ -0,0 +1,8 @@ +let x = 1; + +; + +// Flow around + +/**/ x; +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/throw_statement.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/throw_statement.js new file mode 100644 index 000000000..01d9c2e2d --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/throw_statement.js @@ -0,0 +1,15 @@ +let x = 1; + +// Flow In +throw x, y = 1; +// ^ defined: 1 + +// Flow Out + +/**/ y; +// ^ defined: 4 + +// Flow around + +/**/ x; +// ^ defined: 1 From 1fa3e5abebb766ab3832a5436bfd2ca6556bf71c Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Mon, 24 Jul 2023 18:44:52 -0700 Subject: [PATCH 113/500] Reorgs --- .../test/compound_expressions/array.js | 29 ------------------- .../array_index_flow.js | 10 +++++++ .../member_object_flow.js | 0 .../object_computed_property_name_flow.js | 0 ...ject_shorthand_property_identifier_flow.js | 0 .../subscript_array_flow.js | 0 .../subscript_object_flow.js | 0 .../test/expressions/array.js | 20 +++++++++++++ .../assignment_expression.js | 0 .../augmented_assignment_expression.js | 0 .../await.js | 0 .../binary_expression.js | 0 .../booleans.js | 0 .../comma.js | 0 .../member_expression.js | 0 .../null.js | 0 .../number.js | 0 .../object.js | 0 .../parenthesized_expression.js | 0 .../regex.js | 0 .../string.js | 0 .../subscript_expression.js | 0 .../super.js | 0 .../template_strings.js | 0 .../ternary_expression.js | 0 .../this.js | 0 .../unary_expression.js | 0 .../undefined.js | 0 .../update_expression.js | 0 .../variable.js | 0 .../yield_expression.js | 0 31 files changed, 30 insertions(+), 29 deletions(-) delete mode 100644 languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/array.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/array_index_flow.js rename languages/tree-sitter-stack-graphs-javascript/test/{compound_expressions => expression_computation_flow}/member_object_flow.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{compound_expressions => expression_computation_flow}/object_computed_property_name_flow.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{compound_expressions => expression_computation_flow}/object_shorthand_property_identifier_flow.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{compound_expressions => expression_computation_flow}/subscript_array_flow.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{compound_expressions => expression_computation_flow}/subscript_object_flow.js (100%) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/expressions/array.js rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/assignment_expression.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/augmented_assignment_expression.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/await.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/binary_expression.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/booleans.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/comma.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{compound_expressions => expressions}/member_expression.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/null.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/number.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{compound_expressions => expressions}/object.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/parenthesized_expression.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/regex.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/string.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{compound_expressions => expressions}/subscript_expression.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/super.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/template_strings.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/ternary_expression.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/this.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/unary_expression.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/undefined.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/update_expression.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/variable.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{simple_expressions => expressions}/yield_expression.js (100%) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/array.js b/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/array.js deleted file mode 100644 index 77e7269d4..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/array.js +++ /dev/null @@ -1,29 +0,0 @@ -let x = 1; - -// Flow in - -[0, x]; -// ^ defined: 1 - -// Flow out - -[y = 1, - 0, y]; -// ^ defined: 10 - -/**/ y; -// ^ defined: 10 - -// Flow around - -/**/ x; -// ^ defined: 1 - -let arr = [0, x]; -let x2 = arg[0]; - -/**/ x2; -// ^ defined: 23 -// let one = arr[1].x; -// // defined: 1 -// // defined: 2 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/array_index_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/array_index_flow.js new file mode 100644 index 000000000..88492c222 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/array_index_flow.js @@ -0,0 +1,10 @@ +let x = 1; +let arr = [0, x]; +let y = arr[0]; +let z = arr[1]; + +/**/ y; +// ^ defined: 3 + +/**/ z; +// ^ defined: 1, 4 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/member_object_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/member_object_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/member_object_flow.js rename to languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/member_object_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object_computed_property_name_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/object_computed_property_name_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object_computed_property_name_flow.js rename to languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/object_computed_property_name_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object_shorthand_property_identifier_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/object_shorthand_property_identifier_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object_shorthand_property_identifier_flow.js rename to languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/object_shorthand_property_identifier_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/subscript_array_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/subscript_array_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/subscript_array_flow.js rename to languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/subscript_array_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/subscript_object_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/subscript_object_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/subscript_object_flow.js rename to languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/subscript_object_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expressions/array.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/array.js new file mode 100644 index 000000000..c80b26d79 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/expressions/array.js @@ -0,0 +1,20 @@ +let x = 1; + +// Flow in + +[0, x]; +// ^ defined: 1 + +// Flow out + +[y = 1, + 0, y]; +// ^ defined: 10 + +/**/ y; +// ^ defined: 10 + +// Flow around + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/assignment_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/assignment_expression.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/assignment_expression.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/assignment_expression.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/augmented_assignment_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/augmented_assignment_expression.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/augmented_assignment_expression.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/augmented_assignment_expression.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/await.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/await.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/await.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/await.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/binary_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/binary_expression.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/binary_expression.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/binary_expression.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/booleans.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/booleans.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/booleans.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/booleans.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/comma.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/comma.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/comma.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/comma.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/member_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/member_expression.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/member_expression.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/member_expression.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/null.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/null.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/null.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/null.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/number.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/number.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/number.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/number.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/object.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/object.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/object.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/parenthesized_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/parenthesized_expression.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/parenthesized_expression.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/parenthesized_expression.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/regex.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/regex.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/regex.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/regex.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/string.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/string.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/string.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/string.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/subscript_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/subscript_expression.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/compound_expressions/subscript_expression.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/subscript_expression.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/super.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/super.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/super.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/super.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/template_strings.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/template_strings.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/template_strings.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/template_strings.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/ternary_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/ternary_expression.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/ternary_expression.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/ternary_expression.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/this.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/this.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/this.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/this.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/unary_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/unary_expression.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/unary_expression.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/unary_expression.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/undefined.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/undefined.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/undefined.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/undefined.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/update_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/update_expression.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/update_expression.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/update_expression.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variable.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/variable.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/variable.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/variable.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/yield_expression.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/simple_expressions/yield_expression.js rename to languages/tree-sitter-stack-graphs-javascript/test/expressions/yield_expression.js From 9b1f5e633ee79f939b4d7f0fe003b916eb0c62bb Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Mon, 24 Jul 2023 19:05:15 -0700 Subject: [PATCH 114/500] Adds some missing tests --- .../test/expressions/arrow_function.js | 33 +++++++++++++++++ .../test/expressions/call_expression.js | 24 +++++++++++++ .../test/expressions/function.js | 31 ++++++++++++++++ .../test/expressions/generator_function.js | 31 ++++++++++++++++ .../test/expressions/new_expression.js | 24 +++++++++++++ .../test/statements/function_declaration.js | 35 +++++++++++++++++++ .../generator_function_declaration.js | 35 +++++++++++++++++++ .../test/statements/hash_bang_line.js | 5 +++ .../test/statements/return_statement.js | 20 +++++++++++ 9 files changed, 238 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/expressions/arrow_function.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/expressions/call_expression.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/expressions/function.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/expressions/generator_function.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/expressions/new_expression.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/function_declaration.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/generator_function_declaration.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/hash_bang_line.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/return_statement.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expressions/arrow_function.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/arrow_function.js new file mode 100644 index 000000000..8aa55f72b --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/expressions/arrow_function.js @@ -0,0 +1,33 @@ +// +// READ ME +// +// This test does NOT test complex arguments. See the `binding` test dir. +// + +let x = 1; + +// Flow In + +() => x; +// ^ defined: 7 + +() => { x }; +// ^ defined: 7 + +// Flow Out + +() => y = 1; + +/**/ y; +// ^ defined: +// y should not be defined here + +// Flow Around + +/**/ x; +// ^ defined: 7 + +// Flow In from Arg +y => + y + 1; +// ^ defined: 31 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expressions/call_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/call_expression.js new file mode 100644 index 000000000..c659699ea --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/expressions/call_expression.js @@ -0,0 +1,24 @@ +let x = 1; +let f = 2; + +// Flow in +/**/ f(x); +// ^ defined: 1 +// ^ defined: 2 + +// Flow around + +/**/ x; +// ^ defined: 1 + +// Flow out + +(y = 1)( + z = 2 +); + +/**/ y; +// ^ defined: 16 + +/**/ z; +// ^ defined: 17 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expressions/function.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/function.js new file mode 100644 index 000000000..29061f3b0 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/expressions/function.js @@ -0,0 +1,31 @@ +// +// READ ME +// +// This test does NOT test complex arguments. See the `binding` test dir. +// + +let x = 1; + +// Flow In + +(function () { x; }); +// ^ defined: 7 + +// Flow Out + +(function () { y = 1; }); + +/**/ y; +// ^ defined: +// y should not be defined here + +// Flow Around + +/**/ x; +// ^ defined: 7 + +// Flow In from Arg +(function (y) { + /**/ y; + // ^ defined: 28 +}); \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expressions/generator_function.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/generator_function.js new file mode 100644 index 000000000..5e11f4664 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/expressions/generator_function.js @@ -0,0 +1,31 @@ +// +// READ ME +// +// This test does NOT test complex arguments. See the `binding` test dir. +// + +let x = 1; + +// Flow In + +(function* () { x; }); +// ^ defined: 7 + +// Flow Out + +(function* () { y = 1; }); + +/**/ y; +// ^ defined: +// y should not be defined here + +// Flow Around + +/**/ x; +// ^ defined: 7 + +// Flow In from Arg +(function* (y) { + /**/ y; + // ^ defined: 28 +}); \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expressions/new_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/new_expression.js new file mode 100644 index 000000000..2a3655759 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/expressions/new_expression.js @@ -0,0 +1,24 @@ +let x = 1; +let f = 2; + +// Flow in +/**/ new f(x); +// ^ defined: 1 +// ^ defined: 2 + +// Flow around + +/**/ x; +// ^ defined: 1 + +// Flow out + +new (y = 1)( + z = 2 +); + +/**/ y; +// ^ defined: 16 + +/**/ z; +// ^ defined: 17 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/function_declaration.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/function_declaration.js new file mode 100644 index 000000000..a3094f1a5 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/function_declaration.js @@ -0,0 +1,35 @@ +// +// READ ME +// +// This test does NOT test complex arguments. See the `binding` test dir. +// + +let x = 1; + +// Flow In + +function foo() { + /**/ x; + // ^ defined: 7 +} + +// Flow Out + +function bar() { + y = 1; +} + +/**/ y; +// ^ defined: +// y should not be defined here + +// Flow Around + +/**/ x; +// ^ defined: 7 + +// Flow In from Arg +function baz(y) { + /**/ y; + // ^ defined: 32 +} \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/generator_function_declaration.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/generator_function_declaration.js new file mode 100644 index 000000000..2bd9f050f --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/generator_function_declaration.js @@ -0,0 +1,35 @@ +// +// READ ME +// +// This test does NOT test complex arguments. See the `binding` test dir. +// + +let x = 1; + +// Flow In + +function* foo() { + /**/ x; + // ^ defined: 7 +} + +// Flow Out + +function* bar() { + y = 1; +} + +/**/ y; +// ^ defined: +// y should not be defined here + +// Flow Around + +/**/ x; +// ^ defined: 7 + +// Flow In from Arg +function* baz(y) { + /**/ y; + // ^ defined: 32 +} \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/hash_bang_line.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/hash_bang_line.js new file mode 100644 index 000000000..babd2b2dd --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/hash_bang_line.js @@ -0,0 +1,5 @@ +#! foo +let x = 1; + +/**/ x; +// ^ defined: 2 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/return_statement.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/return_statement.js new file mode 100644 index 000000000..4bec4d573 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/return_statement.js @@ -0,0 +1,20 @@ +function* f() { + let x = 1; + + // Flow in + + return x; + // ^ defined: 2 + + // Flow out + + return y = 1; + + /**/ y; + // ^ defined: 11 + + // Flow around + + /**/ x; + // ^ defined: 2 +} \ No newline at end of file From 5823da7f17e0a1d4d1a9e94754f4f0959abc449c Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 27 Jul 2023 16:25:36 -0700 Subject: [PATCH 115/500] Adds class expression and class declaration tests --- .../test/expressions/class.js | 36 +++++++++++++++++++ .../test/statements/class_declaration.js | 36 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/expressions/class.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/class_declaration.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expressions/class.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/class.js new file mode 100644 index 000000000..7a5f7ea91 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/expressions/class.js @@ -0,0 +1,36 @@ +let x = 1; + +// Flow In + +(class extends x { + // ^ defined: 1 + z = x; + // ^ defined: 1 + + bar() { + /**/ x; + // ^ defined: 1 + + /**/ z; + // ^ defined: + // z should not be defined here + + this.z; + // !!!! TODO defined: 7 + } +}); + +// Flow Out + +(class { + y = 1; +}); + +/**/ y; +// ^ defined: +// y should not be defined here + +// Flow Around + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/class_declaration.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/class_declaration.js new file mode 100644 index 000000000..cb95068b2 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/class_declaration.js @@ -0,0 +1,36 @@ +let x = 1; + +// Flow In + +class Foo extends x { + // ^ defined: 1 + z = x; + // ^ defined: 1 + + bar() { + /**/ x; + // ^ defined: 1 + + /**/ z; + // ^ defined: + // z should not be defined here + + this.z; + // !!!! TODO defined: 7 + } +} + +// Flow Out + +class Baz { + y = 1; +} + +/**/ y; +// ^ defined: +// y should not be defined here + +// Flow Around + +/**/ x; +// ^ defined: 1 \ No newline at end of file From 62944fdc22159b299263b12fed93544abfd1d206 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 27 Jul 2023 16:25:43 -0700 Subject: [PATCH 116/500] Adds import tests --- .../test/statements/import_statement.js | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/import_statement.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/import_statement.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/import_statement.js new file mode 100644 index 000000000..c3370b624 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/import_statement.js @@ -0,0 +1,25 @@ +let x = 1; + +// Flow Out + +import * as y from "mod"; +import { z } from "mod"; +import { y as w } from "mod"; +import q from "mod"; + +/**/ y; +// ^ defined: 5 + +/**/ z; +// defined: 6 + +/**/ w; +// defined: 7 + +/**/ q; +// defined: 8 + +// Flow Around + +/**/ x; +// ^ defined: 1 \ No newline at end of file From b2af299a3a9c5750bb8a2bc2364e82ccc541a276 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 27 Jul 2023 16:35:11 -0700 Subject: [PATCH 117/500] Adds export statement tests --- .../test/statements/export_statement.js | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/statements/export_statement.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/export_statement.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/export_statement.js new file mode 100644 index 000000000..a954a1f34 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/export_statement.js @@ -0,0 +1,31 @@ +let x = 1; + +// Flow In + +export { x }; +// ^ defined: 1 +export { x as _ }; +// ^ defined: 1 +export let _ = x; +// ^ defined: 1 +export function f() { + /**/ x; + // ^ defined: 1 +}; +export default function () { + /**/ x; + // ^ defined: 1 +}; + +// Flow Out + +export { _ as y }; + +/**/ y; +// ^ defined: +// y should not be defined here + +// Flow Around + +/**/ x; +// ^ defined: 1 \ No newline at end of file From 3e6450a22e496f9b18909b0f0c0d4abd4d58d169 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Wed, 2 Aug 2023 18:00:27 -0700 Subject: [PATCH 118/500] Add argument return/yield flow tests --- .../function_call_arguments_variable_flow.js | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_arguments_variable_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_arguments_variable_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_arguments_variable_flow.js new file mode 100644 index 000000000..0b89b5b2d --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_arguments_variable_flow.js @@ -0,0 +1,79 @@ +let obj = { + x: 1 +}; + + + +// function declaration +function func_1() { + return arguments; +} + +func_1(obj)[0].x; +// ^ defined: 2 + + + +// generator function declaration +function* gen_func_1() { + yield arguments; +} + +gen_func_1(obj)[0].x; +// ^ defined: 2 + + + +// assigned function +let func_2 = function () { + return arguments; +}; + +func_2(obj)[0].x; +// ^ defined: 2 + + + +// assigned generator function +let gen_func_2 = function* () { + yield arguments; +}; + +gen_func_2(obj)[0].x; +// ^ defined: 2 + + + +// assigned single-param expression-body arrow function +let func_3 = o => arguments; + +func_3(obj)[0].x; +// ^ defined: +// arrow functions have no `arguments`! + + + +// assigned multi-param expression-body arrow function +let func_4 = () => arguments; + +func_4(obj, 1)[0].x; +// ^ defined: +// arrow functions have no `arguments`! + + + +// assigned single-param statement-body arrow function +let func_5 = o => { return arguments; }; + +func_5(obj)[0].x; +// ^ defined: +// arrow functions have no `arguments`! + + + +// assigned multi-param statement-body arrow function +let func_6 = () => { return arguments; }; + +func_6(obj, 1)[0].x; +// ^ defined: +// arrow functions have no `arguments`! \ No newline at end of file From a3561c1b59a74d5c7fc7a84b9adef0b52a8f7298 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Wed, 2 Aug 2023 18:00:35 -0700 Subject: [PATCH 119/500] Add constant return/yield tests --- .../function_call_constant_flow.js | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_constant_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_constant_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_constant_flow.js new file mode 100644 index 000000000..93fcaa84e --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_constant_flow.js @@ -0,0 +1,88 @@ +// function declaration +function func_1() { + return { + x: 1 + }; +} + +func_1().x; +// ^ defined: 4 + + + +// generator function declaration +function* gen_func_1() { + yield { + x: 1 + }; +} + +gen_func_1().x; +// ^ defined: 16 + + + +// assigned function +let func_2 = function () { + return { + x: 1 + }; +} + +func_2().x; +// ^ defined: 28 + + + +// assigned generator function +let gen_func_2 = function* () { + yield { + x: 1 + }; +} +gen_func_2().x; +// ^ defined: 40 + + + +// assigned single-param expression-body arrow function +let func_3 = o => ({ + x: 1 +}); + +func_3(1).x; +// ^ defined: 50 + + + +// assigned multi-param expression-body arrow function +let func_4 = () => ({ + x: 1 +}); + +func_4().x; +// ^ defined: 60 + + + +// assigned single-param statement-body arrow function +let func_5 = o => { + return { + x: 1 + }; +}; + +func_5(1).x; +// ^ defined: 71 + + + +// assigned multi-param statement-body arrow function +let func_6 = () => { + return { + x: 1 + }; +}; + +func_6().x; +// ^ defined: 83 \ No newline at end of file From a4350cee8ff7286247b7b2f4c4f1058f89980968 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Wed, 2 Aug 2023 18:01:00 -0700 Subject: [PATCH 120/500] Add arguments var return/yield tests plus bug fix --- .../src/stack-graphs.tsg | 17 ++++- .../function_call_argument_flow.js | 74 +++++++++++++++++++ 2 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_argument_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index f655742c5..abc6c0790 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -2586,6 +2586,10 @@ inherit .return_or_yield parameters:(_)@call_sig body:(_)@body)@fun { + node call_sig_arguments_pop + node call_sig_arguments_push + node call_sig_this_pop + node call_sig_this_push node @fun.return_or_yield node @fun.value_arg_scope node fun_value_call @@ -2602,8 +2606,19 @@ inherit .return_or_yield attr (fun_value_drop) type = "drop_scopes" edge fun_value_drop -> @fun.before_scope - ; the call sig's before scope comes from the drop node then flows into the body + ; the call sig's before scope comes from the drop node, + ; then flows into the body, and includes a variable binding for "this" edge @call_sig.before_scope -> fun_value_drop + attr (call_sig_this_pop) symbol_definition = "this", source_node = @call_sig + attr (call_sig_this_push) push_symbol = "this" + edge call_sig_this_pop -> call_sig_this_push + edge call_sig_this_push -> @fun.value_arg_scope + edge @call_sig.before_scope -> call_sig_this_pop + attr (call_sig_arguments_pop) symbol_definition = "arguments", source_node = @call_sig + attr (call_sig_arguments_push) push_symbol = "arguments" + edge call_sig_arguments_pop -> call_sig_arguments_push + edge call_sig_arguments_push -> @fun.value_arg_scope + edge @call_sig.before_scope -> call_sig_arguments_pop edge @body.before_scope -> @call_sig.after_scope ; function values have call nodes diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_argument_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_argument_flow.js new file mode 100644 index 000000000..e9f45c3bd --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_argument_flow.js @@ -0,0 +1,74 @@ +let obj = { + x: 1 +}; + + + +// function declaration +function func_1(o) { + return o; +} + +func_1(obj).x; +// ^ defined: 2 + + + +// generator function declaration +function* gen_func_1(o) { + yield o; +} + +gen_func_1(obj).x; +// ^ defined: 2 + + + +// assigned function +let func_2 = function (o) { + return o; +} + +func_2(obj).x; +// ^ defined: 2 + + + +// assigned generator function +let gen_func_2 = function* (o) { + yield o; +} +gen_func_2(obj).x; +// ^ defined: 2 + + + +// assigned single-param expression-body arrow function +let func_3 = o => o; + +func_3(obj).x; +// ^ defined: 2 + + + +// assigned multi-param expression-body arrow function +let func_4 = (o, p) => o; + +func_4(obj, 1).x; +// ^ defined: 2 + + + +// assigned single-param statement-body arrow function +let func_5 = o => { return o; }; + +func_5(obj).x; +// ^ defined: 2 + + + +// assigned multi-param statement-body arrow function +let func_6 = (o, p) => { return o; }; + +func_6(obj, 1).x; +// ^ defined: 2 \ No newline at end of file From 5b67320cc63152d80fbbe380ab8029032a23a43a Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Wed, 2 Aug 2023 18:46:48 -0700 Subject: [PATCH 121/500] Adds this keyword flow tests --- .../function_call_this_keyword_flow.js | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_this_keyword_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_this_keyword_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_this_keyword_flow.js new file mode 100644 index 000000000..bd5e41c66 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_this_keyword_flow.js @@ -0,0 +1,22 @@ +function foo() { + this.x = 1; +} + +let obj = new foo(); + +obj.x; +// ^ defined: 2 + + + +function bar(y) { + this.z = y; +} + +let obj_2 = new bar({ + w: 1 +}); + +obj_2.z.w; +// ^ defined: 17 +// ^ defined: 12, 13 \ No newline at end of file From 5388d8689ec8f7e89e7eb5bef0d6a77be8aaf688 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Wed, 2 Aug 2023 18:46:59 -0700 Subject: [PATCH 122/500] Add closure flow tests --- .../function_call_closure_flow.js | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_closure_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_closure_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_closure_flow.js new file mode 100644 index 000000000..4867c77d2 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_closure_flow.js @@ -0,0 +1,74 @@ +let obj = { + x: 1 +}; + + + +// function declaration +function func_1() { + return obj; +} + +func_1().x; +// ^ defined: 2 + + + +// generator function declaration +function* gen_func_1() { + yield obj; +} + +gen_func_1().x; +// ^ defined: 2 + + + +// assigned function +let func_2 = function () { + return obj; +} + +func_2().x; +// ^ defined: 2 + + + +// assigned generator function +let gen_func_2 = function* () { + yield obj; +} +gen_func_2().x; +// ^ defined: 2 + + + +// assigned single-param expression-body arrow function +let func_3 = y => obj; + +func_3().x; +// ^ defined: 2 + + + +// assigned multi-param expression-body arrow function +let func_4 = () => obj; + +func_4().x; +// ^ defined: 2 + + + +// assigned single-param statement-body arrow function +let func_5 = y => { return obj; }; + +func_5().x; +// ^ defined: 2 + + + +// assigned multi-param statement-body arrow function +let func_6 = () => { return obj; }; + +func_6().x; +// ^ defined: 2 \ No newline at end of file From 585d15af0cff622a1799f6d72f825d62a8b0bd00 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Wed, 2 Aug 2023 18:47:30 -0700 Subject: [PATCH 123/500] Reorgs --- .../array_index_flow.js | 0 .../function_call_argument_flow.js | 0 .../function_call_arguments_variable_flow.js | 0 .../function_call_closure_flow.js | 0 .../function_call_constant_flow.js | 0 .../function_call_this_keyword_flow.js | 0 .../member_object_flow.js | 0 .../object_computed_property_name_flow.js | 0 .../object_shorthand_property_identifier_flow.js | 0 .../subscript_array_flow.js | 0 .../subscript_object_flow.js | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename languages/tree-sitter-stack-graphs-javascript/test/{expression_computation_flow => computation_flow}/array_index_flow.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{expression_computation_flow => computation_flow}/function_call_argument_flow.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{expression_computation_flow => computation_flow}/function_call_arguments_variable_flow.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{expression_computation_flow => computation_flow}/function_call_closure_flow.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{expression_computation_flow => computation_flow}/function_call_constant_flow.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{expression_computation_flow => computation_flow}/function_call_this_keyword_flow.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{expression_computation_flow => computation_flow}/member_object_flow.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{expression_computation_flow => computation_flow}/object_computed_property_name_flow.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{expression_computation_flow => computation_flow}/object_shorthand_property_identifier_flow.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{expression_computation_flow => computation_flow}/subscript_array_flow.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/{expression_computation_flow => computation_flow}/subscript_object_flow.js (100%) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/array_index_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/array_index_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/array_index_flow.js rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/array_index_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_argument_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_call_argument_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_argument_flow.js rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_call_argument_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_arguments_variable_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_call_arguments_variable_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_arguments_variable_flow.js rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_call_arguments_variable_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_closure_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_call_closure_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_closure_flow.js rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_call_closure_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_constant_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_call_constant_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_constant_flow.js rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_call_constant_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_this_keyword_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_call_this_keyword_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/function_call_this_keyword_flow.js rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_call_this_keyword_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/member_object_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/member_object_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/member_object_flow.js rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/member_object_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/object_computed_property_name_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/object_computed_property_name_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/object_computed_property_name_flow.js rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/object_computed_property_name_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/object_shorthand_property_identifier_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/object_shorthand_property_identifier_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/object_shorthand_property_identifier_flow.js rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/object_shorthand_property_identifier_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/subscript_array_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/subscript_array_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/subscript_array_flow.js rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/subscript_array_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/subscript_object_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/subscript_object_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/expression_computation_flow/subscript_object_flow.js rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/subscript_object_flow.js From da1a05b57074accc1483e7bd4430298b87d12360 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Mon, 7 Aug 2023 16:55:20 -0700 Subject: [PATCH 124/500] Adds many class tests, including some failing TODO tests --- .../class_declaration_field_definitions.js | 20 +++++++++++++++ ...s_declaration_method_call_argument_flow.js | 25 +++++++++++++++++++ ...ethod_call_arguments_variable_flow.js.TODO | 25 +++++++++++++++++++ ...ss_declaration_method_call_closure_flow.js | 25 +++++++++++++++++++ ...s_declaration_method_call_constant_flow.js | 23 +++++++++++++++++ ..._methods_not_visible_outside_class.js.TODO | 9 +++++++ ...eclaration_methods_visible_on_instances.js | 9 +++++++ ...laration_super_reference_to_method.js.TODO | 15 +++++++++++ ...declaration_superclass_field_definition.js | 22 ++++++++++++++++ ...superclass_methods_visible_on_instances.js | 11 ++++++++ ..._declaration_this_field_and_method.js.TODO | 12 +++++++++ .../class_expression_field_definition.js | 20 +++++++++++++++ ...ss_expression_method_call_argument_flow.js | 25 +++++++++++++++++++ ...ethod_call_arguments_variable_flow.js.TODO | 25 +++++++++++++++++++ ...ass_expression_method_call_closure_flow.js | 25 +++++++++++++++++++ ...ss_expression_method_call_constant_flow.js | 23 +++++++++++++++++ ..._methods_not_visible_outside_class.js.TODO | 9 +++++++ ...expression_methods_visible_on_instances.js | 9 +++++++ ...pression_super_reference_to_method.js.TODO | 15 +++++++++++ ..._expression_superclass_field_definition.js | 22 ++++++++++++++++ ...superclass_methods_visible_on_instances.js | 11 ++++++++ ...s_expression_this_field_and_method.js.TODO | 12 +++++++++ .../test/expressions/class.js | 3 --- .../test/statements/class_declaration.js | 3 --- 24 files changed, 392 insertions(+), 6 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_field_definitions.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_argument_flow.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_arguments_variable_flow.js.TODO create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_closure_flow.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_constant_flow.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_methods_not_visible_outside_class.js.TODO create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_methods_visible_on_instances.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_super_reference_to_method.js.TODO create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_superclass_field_definition.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_superclass_methods_visible_on_instances.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_this_field_and_method.js.TODO create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_field_definition.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_argument_flow.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_arguments_variable_flow.js.TODO create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_closure_flow.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_constant_flow.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_methods_not_visible_outside_class.js.TODO create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_methods_visible_on_instances.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_super_reference_to_method.js.TODO create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_superclass_field_definition.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_superclass_methods_visible_on_instances.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_this_field_and_method.js.TODO diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_field_definitions.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_field_definitions.js new file mode 100644 index 000000000..bd59589aa --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_field_definitions.js @@ -0,0 +1,20 @@ +class Foo { + bar; + baz = 1; + static quux; + static doo = 1; +} + +let obj = new Foo(); + +obj.bar; +// ^ defined: 2 + +obj.baz; +// ^ defined: 3 + +obj.quux; +// ^ defined: 4 + +obj.doo; +// ^ defined: 5 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_argument_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_argument_flow.js new file mode 100644 index 000000000..8392a7f73 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_argument_flow.js @@ -0,0 +1,25 @@ +let obj = { + x: 1 +}; + + + +class Foo { + // method declaration + meth_1(o) { + return o; + } + + // generator method declaration + * gen_meth_1(o) { + yield o; + } +} + +let foo = new Foo(); + +foo.meth_1(obj).x; +// ^ defined: 2 + +foo.gen_meth_1(obj).x; +// ^ defined: 2 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_arguments_variable_flow.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_arguments_variable_flow.js.TODO new file mode 100644 index 000000000..d21008426 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_arguments_variable_flow.js.TODO @@ -0,0 +1,25 @@ +let obj = { + x: 1 +}; + + + +class Foo { + // method declaration + meth_1() { + return arguments; + } + + // generator method declaration + * gen_meth_1() { + yield arguments; + } +} + +let foo = new Foo(); + +foo.meth_1(obj)[0].x; +// ^ defined: 2 + +foo.gen_meth_1(obj)[0].x; +// ^ defined: 2 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_closure_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_closure_flow.js new file mode 100644 index 000000000..1b129f7d9 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_closure_flow.js @@ -0,0 +1,25 @@ +let obj = { + x: 1 +}; + + + +class Foo { + // method declaration + meth_1() { + return obj; + } + + // generator method declaration + * gen_meth_1() { + yield obj; + } +} + +let foo = new Foo(); + +foo.meth_1().x; +// ^ defined: 2 + +foo.gen_meth_1().x; +// ^ defined: 2 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_constant_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_constant_flow.js new file mode 100644 index 000000000..05b73e602 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_constant_flow.js @@ -0,0 +1,23 @@ +class Foo { + // method declaration + meth_1() { + return { + x: 1 + }; + } + + // generator method declaration + * gen_meth_1() { + yield { + x: 1 + }; + } +} + +let foo = new Foo(); + +foo.meth_1().x; +// ^ defined: 5 + +foo.gen_meth_1().x; +// ^ defined: 12 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_methods_not_visible_outside_class.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_methods_not_visible_outside_class.js.TODO new file mode 100644 index 000000000..9098635ca --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_methods_not_visible_outside_class.js.TODO @@ -0,0 +1,9 @@ +class Foo { + bar() { + + } +} + +Foo.bar; +// ^ defined: +// bar should not be visible here \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_methods_visible_on_instances.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_methods_visible_on_instances.js new file mode 100644 index 000000000..d02aa0823 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_methods_visible_on_instances.js @@ -0,0 +1,9 @@ +class Foo { + bar() { + + } +} + +let obj = new Foo(); +obj.bar; +// ^ defined: 2 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_super_reference_to_method.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_super_reference_to_method.js.TODO new file mode 100644 index 000000000..31b2628ab --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_super_reference_to_method.js.TODO @@ -0,0 +1,15 @@ +class Foo { + bar() { + + } +} + +class Baz extends Foo { + bar() { + + } + quux() { + super.bar; + // ^ defined: 2 + } +} \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_superclass_field_definition.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_superclass_field_definition.js new file mode 100644 index 000000000..12f894d72 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_superclass_field_definition.js @@ -0,0 +1,22 @@ +class Foo { + bar; + baz = 1; + static quux; + static doo = 1; +} + +class Garply extends Foo { } + +let obj = new Garply(); + +obj.bar; +// ^ defined: 2 + +obj.baz; +// ^ defined: 3 + +obj.quux; +// ^ defined: 4 + +obj.doo; +// ^ defined: 5 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_superclass_methods_visible_on_instances.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_superclass_methods_visible_on_instances.js new file mode 100644 index 000000000..3cfe06241 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_superclass_methods_visible_on_instances.js @@ -0,0 +1,11 @@ +class Foo { + bar() { + + } +} + +class Baz extends Foo { } + +let obj = new Baz(); +obj.bar; +// ^ defined: 2 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_this_field_and_method.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_this_field_and_method.js.TODO new file mode 100644 index 000000000..bf891fa27 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_this_field_and_method.js.TODO @@ -0,0 +1,12 @@ +class Foo { + bar; + baz() { + + } + quux() { + this.bar; + // ^ defined: 2 + this.baz; + // ^ defined: 3 + } +} \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_field_definition.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_field_definition.js new file mode 100644 index 000000000..38d00377f --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_field_definition.js @@ -0,0 +1,20 @@ +let Foo = class { + bar; + baz = 1; + static quux; + static doo = 1; +}; + +let obj = new Foo(); + +obj.bar; +// ^ defined: 2 + +obj.baz; +// ^ defined: 3 + +obj.quux; +// ^ defined: 4 + +obj.doo; +// ^ defined: 5 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_argument_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_argument_flow.js new file mode 100644 index 000000000..06725bc9d --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_argument_flow.js @@ -0,0 +1,25 @@ +let obj = { + x: 1 +}; + + + +let Foo = class { + // method declaration + meth_1(o) { + return o; + } + + // generator method declaration + * gen_meth_1(o) { + yield o; + } +}; + +let foo = new Foo(); + +foo.meth_1(obj).x; +// ^ defined: 2 + +foo.gen_meth_1(obj).x; +// ^ defined: 2 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_arguments_variable_flow.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_arguments_variable_flow.js.TODO new file mode 100644 index 000000000..6a04b5900 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_arguments_variable_flow.js.TODO @@ -0,0 +1,25 @@ +let obj = { + x: 1 +}; + + + +let Foo = class { + // method declaration + meth_1() { + return arguments; + } + + // generator method declaration + * gen_meth_1() { + yield arguments; + } +}; + +let foo = new Foo(); + +foo.meth_1(obj)[0].x; +// ^ defined: 2 + +foo.gen_meth_1(obj)[0].x; +// ^ defined: 2 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_closure_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_closure_flow.js new file mode 100644 index 000000000..a155cab18 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_closure_flow.js @@ -0,0 +1,25 @@ +let obj = { + x: 1 +}; + + + +let Foo = class { + // method declaration + meth_1() { + return obj; + } + + // generator method declaration + * gen_meth_1() { + yield obj; + } +}; + +let foo = new Foo(); + +foo.meth_1().x; +// ^ defined: 2 + +foo.gen_meth_1().x; +// ^ defined: 2 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_constant_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_constant_flow.js new file mode 100644 index 000000000..0177a7e94 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_constant_flow.js @@ -0,0 +1,23 @@ +let Foo = class { + // method declaration + meth_1() { + return { + x: 1 + }; + } + + // generator method declaration + * gen_meth_1() { + yield { + x: 1 + }; + } +}; + +let foo = new Foo(); + +foo.meth_1().x; +// ^ defined: 5 + +foo.gen_meth_1().x; +// ^ defined: 12 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_methods_not_visible_outside_class.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_methods_not_visible_outside_class.js.TODO new file mode 100644 index 000000000..e1a573d14 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_methods_not_visible_outside_class.js.TODO @@ -0,0 +1,9 @@ +let Foo = class { + bar() { + + } +}; + +Foo.bar; +// ^ defined: +// bar should not be visible here \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_methods_visible_on_instances.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_methods_visible_on_instances.js new file mode 100644 index 000000000..6137bc781 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_methods_visible_on_instances.js @@ -0,0 +1,9 @@ +let Foo = class { + bar() { + + } +}; + +let obj = new Foo(); +obj.bar; +// ^ defined: 2 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_super_reference_to_method.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_super_reference_to_method.js.TODO new file mode 100644 index 000000000..a9edf537b --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_super_reference_to_method.js.TODO @@ -0,0 +1,15 @@ +let Foo = class { + bar() { + + } +}; + +let Bar = class extends Foo { + bar() { + + } + quux() { + super.bar; + // ^ defined: 2 + } +}; \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_superclass_field_definition.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_superclass_field_definition.js new file mode 100644 index 000000000..69cf71afd --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_superclass_field_definition.js @@ -0,0 +1,22 @@ +let Foo = class { + bar; + baz = 1; + static quux; + static doo = 1; +}; + +let Garply = class extends Foo { }; + +let obj = new Garply(); + +obj.bar; +// ^ defined: 2 + +obj.baz; +// ^ defined: 3 + +obj.quux; +// ^ defined: 4 + +obj.doo; +// ^ defined: 5 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_superclass_methods_visible_on_instances.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_superclass_methods_visible_on_instances.js new file mode 100644 index 000000000..305302523 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_superclass_methods_visible_on_instances.js @@ -0,0 +1,11 @@ +let Foo = class { + bar() { + + } +}; + +let Baz = class extends Foo { }; + +let obj = new Baz(); +obj.bar; +// ^ defined: 2 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_this_field_and_method.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_this_field_and_method.js.TODO new file mode 100644 index 000000000..ba8fd3879 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_this_field_and_method.js.TODO @@ -0,0 +1,12 @@ +let Foo = class { + bar; + baz() { + + } + quux() { + this.bar; + // ^ defined: 2 + this.baz; + // ^ defined: 3 + } +}; \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expressions/class.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/class.js index 7a5f7ea91..5786cffe5 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/expressions/class.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/expressions/class.js @@ -14,9 +14,6 @@ let x = 1; /**/ z; // ^ defined: // z should not be defined here - - this.z; - // !!!! TODO defined: 7 } }); diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/class_declaration.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/class_declaration.js index cb95068b2..57cd8d5e2 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/statements/class_declaration.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/class_declaration.js @@ -14,9 +14,6 @@ class Foo extends x { /**/ z; // ^ defined: // z should not be defined here - - this.z; - // !!!! TODO defined: 7 } } From bb3a2462fb4d3adfe6d447e28aa41e14c05fecbc Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 8 Aug 2023 15:05:58 -0700 Subject: [PATCH 125/500] Fixes minor test bug --- .../old/imports_and_exports/commonjs_imports_and_exports.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/commonjs_imports_and_exports.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/commonjs_imports_and_exports.js index 70cda6893..14c1afb3e 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/commonjs_imports_and_exports.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/commonjs_imports_and_exports.js @@ -5,7 +5,7 @@ module.exports = { bar: 2 }; -/*--- path b.js ---*/ +/*--- path: b.js ---*/ const mod1 = require("a.js"); From 3657f41b6ab619a1c68980cbe8bf969d2eb640db Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 7 Aug 2023 11:15:08 +0200 Subject: [PATCH 126/500] Make more util items crate-local --- tree-sitter-stack-graphs/src/cli/util.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tree-sitter-stack-graphs/src/cli/util.rs b/tree-sitter-stack-graphs/src/cli/util.rs index e222fe434..65c6de1bd 100644 --- a/tree-sitter-stack-graphs/src/cli/util.rs +++ b/tree-sitter-stack-graphs/src/cli/util.rs @@ -297,13 +297,13 @@ pub struct SourceSpan { } impl SourceSpan { - pub fn first_line(&self) -> usize { + pub(crate) fn first_line(&self) -> usize { self.span.start.line } /// Returns a range for the first line of this span. If multiple lines are spanned, it /// will use usize::MAX for the range's end. - pub fn first_line_column_range(&self) -> Range { + pub(crate) fn first_line_column_range(&self) -> Range { let start = self.span.start.column.grapheme_offset; let end = if self.span.start.line == self.span.end.line { self.span.end.column.grapheme_offset @@ -314,13 +314,13 @@ impl SourceSpan { } } -pub fn duration_from_seconds_str(s: &str) -> Result { +pub(crate) fn duration_from_seconds_str(s: &str) -> Result { let seconds = s.parse::()?; Ok(Duration::new(seconds, 0)) } #[cfg(feature = "lsp")] -pub fn duration_from_milliseconds_str(s: &str) -> Result { +pub(crate) fn duration_from_milliseconds_str(s: &str) -> Result { let milliseconds = s.parse::()?; let seconds = milliseconds / 1000; let nano_seconds = (milliseconds % 1000) as u32 * 1_000_000; @@ -533,13 +533,13 @@ impl FileLogger for ConsoleFileLogger<'_> { } } -pub fn sha1(value: &str) -> String { +pub(crate) fn sha1(value: &str) -> String { let mut hasher = Sha1::new(); hasher.update(value); base64::prelude::BASE64_STANDARD_NO_PAD.encode(hasher.finalize()) } -pub fn wait_for_input() -> anyhow::Result<()> { +pub(crate) fn wait_for_input() -> anyhow::Result<()> { print!(""); std::io::stdout().flush()?; let mut input = String::new(); @@ -548,7 +548,7 @@ pub fn wait_for_input() -> anyhow::Result<()> { } /// Wraps a build error with the relevant sources -pub struct BuildErrorWithSource<'a> { +pub(crate) struct BuildErrorWithSource<'a> { pub inner: crate::BuildError, pub source_path: PathBuf, pub source_str: &'a str, From d0a31d7393205abc2c4b562d8db70616a1cf2d57 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 10 Aug 2023 15:43:13 -0700 Subject: [PATCH 127/500] Updates version for newest Stack Graph support --- languages/tree-sitter-stack-graphs-javascript/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml index 51de60edf..4305bab57 100644 --- a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -28,7 +28,7 @@ cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"] [dependencies] anyhow = { version = "1.0", optional = true } clap = { version = "4", optional = true } -stack-graphs = { version = "0.11", path = "../../stack-graphs" } +stack-graphs = { version = "0.12", path = "../../stack-graphs" } tree-sitter = "=0.20.9" tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs" } tree-sitter-javascript = { git = "https://github.com/tree-sitter/tree-sitter-javascript", rev = "5720b249490b3c17245ba772f6be4a43edb4e3b7" } From 641fb542d18a0f2b3409c0d292df09761465436b Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 10 Aug 2023 16:42:35 -0700 Subject: [PATCH 128/500] Adds pattern tests --- .../src/stack-graphs.tsg | 45 +++++++++--------- .../assignment_destructuring_array_pattern.js | 10 ++++ ...assignment_destructuring_object_pattern.js | 16 +++++++ .../function_call_this_flow.js.TODO | 16 +++++++ .../with_statement_binding_flow.js | 4 ++ ...ith_statement_scope_shadowing_flow.js.TODO | 9 ++++ .../test/patterns/array_pattern.js | 33 +++++++++++++ .../test/patterns/assignment_pattern.js | 28 +++++++++++ ...n_declaration_formal_parameter_patterns.js | 16 +++++++ ...d_declaration_formal_parameter_patterns.js | 18 +++++++ .../test/patterns/object_pattern.js | 47 +++++++++++++++++++ 11 files changed, 218 insertions(+), 24 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/assignment_destructuring_array_pattern.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/assignment_destructuring_object_pattern.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_call_this_flow.js.TODO create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/with_statement_binding_flow.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/with_statement_scope_shadowing_flow.js.TODO create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/patterns/array_pattern.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/patterns/assignment_pattern.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/patterns/function_declaration_formal_parameter_patterns.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/patterns/method_declaration_formal_parameter_patterns.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/patterns/object_pattern.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index abc6c0790..690316e48 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -2960,15 +2960,13 @@ inherit .return_or_yield ; scopes on RHS, values (assignment_expression - left: (_)@left + left: (_)@_left right: (_)@right)@assignment_expr { ; scopes flow into the RHS then back out to the whole expr, ; augmented (in subsequent rules) by the LHS edge @right.before_scope -> @assignment_expr.before_scope - edge @left.before_scope -> @right.after_scope - edge @assignment_expr.after_scope -> @left.after_scope - + ; value of the whole thing is value of the RHS edge @assignment_expr.value -> @right.value } @@ -2984,9 +2982,8 @@ inherit .return_or_yield attr (@assignment_expr.pop) node_definition = @left edge @assignment_expr.after_scope -> @assignment_expr.pop edge @assignment_expr.pop -> @right.value + edge @assignment_expr.after_scope -> @right.after_scope - ; ensure the scope flows through the identifier - edge @left.after_scope -> @left.before_scope } ; assignment to direct fields on `this` @@ -3016,7 +3013,11 @@ inherit .return_or_yield ; augmentation of scope via _destructuring_patterns (assignment_expression - left: [(object_pattern) (array_pattern)]@left + left: [ + (object_pattern) + (array_pattern) + (assignment_pattern) + ]@left right: (_)@right)@assignment_expr { ; scope flows from LHS into pattern then back to assignment @@ -3526,26 +3527,22 @@ inherit .return_or_yield } -; if the object assignment pattern happens to have an identifier on the LHS it also binds -(object_assignment_pattern - left:(shorthand_property_identifier_pattern)@left_pat - right:(_)@_right_expr)@object_assignment_pat { - - node left_pat_pop - node left_pat_push - node left_pat_push_dot +(shorthand_property_identifier_pattern)@shorthand_prop_pat { + node pat_pop + node pat_push + node pat_push_dot - edge @left_pat.after_scope -> @left_pat.before_scope + edge @shorthand_prop_pat.after_scope -> @shorthand_prop_pat.before_scope - attr (left_pat_push) node_reference = @left_pat - attr (left_pat_push_dot) push_symbol = "GUARD:MEMBER" - attr (left_pat_pop) node_definition = @left_pat - edge left_pat_pop -> left_pat_push - edge left_pat_push -> left_pat_push_dot - edge left_pat_push_dot -> @left_pat.covalue - edge @object_assignment_pat.after_scope -> left_pat_pop + attr (pat_push) node_reference = @shorthand_prop_pat + attr (pat_push_dot) push_symbol = "GUARD:MEMBER" + attr (pat_pop) node_definition = @shorthand_prop_pat + edge pat_pop -> pat_push + edge pat_push -> pat_push_dot + edge pat_push_dot -> @shorthand_prop_pat.covalue + edge @shorthand_prop_pat.after_scope -> pat_pop - edge @object_assignment_pat.new_bindings -> left_pat_pop + edge @shorthand_prop_pat.new_bindings -> pat_pop } diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/assignment_destructuring_array_pattern.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/assignment_destructuring_array_pattern.js new file mode 100644 index 000000000..cab97c11d --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/assignment_destructuring_array_pattern.js @@ -0,0 +1,10 @@ +let arr = [ + 1, + { + x: 2 + } +]; +let [num, obj] = arr; + +obj.x; +// ^ defined: 4 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/assignment_destructuring_object_pattern.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/assignment_destructuring_object_pattern.js new file mode 100644 index 000000000..0d1bdae26 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/assignment_destructuring_object_pattern.js @@ -0,0 +1,16 @@ +let obj = { + x: 1, + y: { + x: 2 + } +}; +let { + x: num, + y: obj2 +} = obj; + +/**/ obj2; +// ^ defined: 3, 9 + +obj2.x; +// ^ defined: 4 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_call_this_flow.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_call_this_flow.js.TODO new file mode 100644 index 000000000..f3854b9ad --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_call_this_flow.js.TODO @@ -0,0 +1,16 @@ +function foo() { + return this; +} + +foo().x; +// ^ defined: + +foo.apply({ + x: 1 +}).x +// ^ defined: 9 + +foo.call({ + x: 1 +}).x +// ^ defined: 14 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/with_statement_binding_flow.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/with_statement_binding_flow.js new file mode 100644 index 000000000..15ab7f6c3 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/with_statement_binding_flow.js @@ -0,0 +1,4 @@ +with ({ x: 1 }) { + /**/ x; + // ^ defined: 1 +} \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/with_statement_scope_shadowing_flow.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/with_statement_scope_shadowing_flow.js.TODO new file mode 100644 index 000000000..d6b31f760 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/with_statement_scope_shadowing_flow.js.TODO @@ -0,0 +1,9 @@ +let x = 1; + +with ({ x: 2 }) { + /**/ x; + // ^ defined: 3 +} + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/patterns/array_pattern.js b/languages/tree-sitter-stack-graphs-javascript/test/patterns/array_pattern.js new file mode 100644 index 000000000..c3391b10f --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/patterns/array_pattern.js @@ -0,0 +1,33 @@ +let x = 1; + +// Flow In + +let [y = x] = arr; +// ^ defined: 1 +// have to use assignment patterns here to get flow in + +// Flow Out + +let [ + z +] = arr; + +/**/ z; +// ^ defined: 12 + +// Flow Around + +/**/ x; +// ^ defined: 1 + +// Flow In From RHS + +let [w = x] = x++; +// ^ defined: 1, 25 +// have to use assignment patterns here to get flow out + +// Flow Into Subsequent Patterns From Earlier Patterns + +let [q, + r = q] = arr; + // ^ defined: 31 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/patterns/assignment_pattern.js b/languages/tree-sitter-stack-graphs-javascript/test/patterns/assignment_pattern.js new file mode 100644 index 000000000..0b8f402fb --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/patterns/assignment_pattern.js @@ -0,0 +1,28 @@ +let x = 1; + +// Flow In + +[y = x] = 2; +// ^ defined: 1 +// have to use array patterns or something else here to get a pattern +// on the LHS that can contain an assignment pattern + +// Flow Out + +[z = 1] = 2; +/**/ z; +// ^ defined: 12 +// have to use array patterns or something else here to get a pattern +// on the LHS that can contain an assignment pattern + +// Flow Around + +/**/ x; +// ^ defined: 1 + +// Flow In From RHS + +[w = x] = x++; +// ^ defined: 1, 25 +// have to use array patterns or something else here to get a pattern +// on the LHS that can contain an assignment pattern \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/patterns/function_declaration_formal_parameter_patterns.js b/languages/tree-sitter-stack-graphs-javascript/test/patterns/function_declaration_formal_parameter_patterns.js new file mode 100644 index 000000000..7be165815 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/patterns/function_declaration_formal_parameter_patterns.js @@ -0,0 +1,16 @@ +let x = 1; + +// Flow In and Out To Body + +function foo(y = x, [z] = arr) { + // ^ defined: 1 + /**/ y; + // ^ defined: 5, 1 + /**/ z; + // ^ defined: 5 +} + +// Flow Out + +/**/ z; +// ^ defined: \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/patterns/method_declaration_formal_parameter_patterns.js b/languages/tree-sitter-stack-graphs-javascript/test/patterns/method_declaration_formal_parameter_patterns.js new file mode 100644 index 000000000..0d5082948 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/patterns/method_declaration_formal_parameter_patterns.js @@ -0,0 +1,18 @@ +let x = 1; + +// Flow In and Out To Body + +class Foo { + foo(y = x, [z] = arr) { + // ^ defined: 1 + /**/ y; + // ^ defined: 6, 1 + /**/ z; + // ^ defined: 6 + } +} + +// Flow Out + +/**/ z; +// ^ defined: \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/patterns/object_pattern.js b/languages/tree-sitter-stack-graphs-javascript/test/patterns/object_pattern.js new file mode 100644 index 000000000..c71c5ccf5 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/patterns/object_pattern.js @@ -0,0 +1,47 @@ +let x = 1; + +// Flow In + +let { z: y = x } = obj; +// ^ defined: 1 +// have to use assignment patterns here to get flow in + +// Flow Out + +let { + z: w +} = obj; + +/**/ w; +// ^ defined: 12 + +// Flow Around + +/**/ x; +// ^ defined: 1 + +// Flow In From RHS + +let { z: q = r } = + // ^ defined: 27 + r++; + +// Flow Into Subsequent Patterns From Earlier Patterns + +let { z: s, + z: t = s } = obj; +// ^ defined: 31 + +// Flow Out From Shorthand Property Identifier Pattern + +let { u } = obj; + +/**/ u; +// ^ defined: 37 + +// Flow Out From Object Assignment Pattern + +let { v = 1 } = obj; + +/**/ v; +// ^ defined: 44 \ No newline at end of file From 0fcb846823f203ec903bc502ead8e08cdc7f89ee Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 11 Aug 2023 14:08:14 +0200 Subject: [PATCH 129/500] Bump enumset version --- stack-graphs/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack-graphs/Cargo.toml b/stack-graphs/Cargo.toml index e283e25f6..2e55e1768 100644 --- a/stack-graphs/Cargo.toml +++ b/stack-graphs/Cargo.toml @@ -28,7 +28,7 @@ bincode = { version = "2.0.0-rc.3", optional = true } bitvec = "1.0" controlled-option = "0.4" either = "1.6" -enumset = "1.0" +enumset = "1.1" fxhash = "0.2" itertools = "0.10" libc = "0.2" From 75a3d3a666e8dd40a4fe542fddf8ff01b3682f20 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 11 Aug 2023 15:59:51 +0200 Subject: [PATCH 130/500] Introduce a public Reporter trait --- tree-sitter-stack-graphs/Cargo.toml | 6 +- tree-sitter-stack-graphs/src/cli.rs | 2 +- tree-sitter-stack-graphs/src/cli/index.rs | 91 ++++++--- tree-sitter-stack-graphs/src/cli/lsp.rs | 102 +++------- tree-sitter-stack-graphs/src/cli/query.rs | 30 +-- tree-sitter-stack-graphs/src/cli/status.rs | 26 ++- tree-sitter-stack-graphs/src/cli/test.rs | 48 +++-- tree-sitter-stack-graphs/src/cli/util.rs | 189 +++++------------- .../src/cli/util/reporter.rs | 178 +++++++++++++++++ 9 files changed, 400 insertions(+), 272 deletions(-) create mode 100644 tree-sitter-stack-graphs/src/cli/util/reporter.rs diff --git a/tree-sitter-stack-graphs/Cargo.toml b/tree-sitter-stack-graphs/Cargo.toml index 7b5abd92b..2d6dabbd1 100644 --- a/tree-sitter-stack-graphs/Cargo.toml +++ b/tree-sitter-stack-graphs/Cargo.toml @@ -26,8 +26,8 @@ cli = [ "base64", "clap", "colored", - "dirs", "dialoguer", + "dirs", "env_logger", "indoc", "pathdiff", @@ -52,12 +52,12 @@ lsp = [ anyhow = "1.0" base64 = { version = "0.21", optional = true } capture-it = { version = "0.3", optional = true } -clap = { version = "4", optional = true, features=["derive"] } +clap = { version = "4", optional = true, features = ["derive"] } colored = { version = "2.0", optional = true } controlled-option = ">=0.4" crossbeam-channel = { version = "0.5", optional = true } dialoguer = { version = "0.10", optional = true } -dirs = { version = "5", optional=true } +dirs = { version = "5", optional = true } env_logger = { version = "0.9", optional = true } indoc = { version = "1.0", optional = true } itertools = "0.10" diff --git a/tree-sitter-stack-graphs/src/cli.rs b/tree-sitter-stack-graphs/src/cli.rs index 859cbb5c2..830378708 100644 --- a/tree-sitter-stack-graphs/src/cli.rs +++ b/tree-sitter-stack-graphs/src/cli.rs @@ -69,7 +69,7 @@ pub mod parse; pub mod query; pub mod status; pub mod test; -mod util; +pub mod util; pub mod visualize; pub mod path_loading { diff --git a/tree-sitter-stack-graphs/src/cli/index.rs b/tree-sitter-stack-graphs/src/cli/index.rs index 633866379..6d612a851 100644 --- a/tree-sitter-stack-graphs/src/cli/index.rs +++ b/tree-sitter-stack-graphs/src/cli/index.rs @@ -31,13 +31,14 @@ use crate::NoCancellation; use super::util::duration_from_seconds_str; use super::util::iter_files_and_directories; +use super::util::reporter::ConsoleReporter; +use super::util::reporter::Level; +use super::util::reporter::Reporter; use super::util::sha1; use super::util::wait_for_input; use super::util::BuildErrorWithSource; -use super::util::ConsoleLogger; +use super::util::CLIFileReporter; use super::util::ExistingPathBufValueParser; -use super::util::FileLogger; -use super::util::Logger; #[derive(Args)] pub struct IndexArgs { @@ -101,8 +102,8 @@ impl IndexArgs { wait_for_input()?; } let mut db = SQLiteWriter::open(&db_path)?; - let logger = ConsoleLogger::new(self.verbose, !self.hide_error_details); - let mut indexer = Indexer::new(&mut db, &mut loader, &logger); + let reporter = self.get_reporter(); + let mut indexer = Indexer::new(&mut db, &mut loader, &reporter); indexer.force = self.force; indexer.max_file_time = self.max_file_time; @@ -114,12 +115,37 @@ impl IndexArgs { indexer.index_all(source_paths, self.continue_from, &NoCancellation)?; Ok(()) } + + fn get_reporter(&self) -> ConsoleReporter { + return ConsoleReporter { + skipped_level: if self.verbose { + Level::Summary + } else { + Level::None + }, + succeeded_level: if self.verbose { + Level::Summary + } else { + Level::None + }, + failed_level: if self.hide_error_details { + Level::Summary + } else { + Level::Details + }, + canceled_level: if self.hide_error_details { + Level::Summary + } else { + Level::Details + }, + }; + } } pub struct Indexer<'a> { db: &'a mut SQLiteWriter, loader: &'a mut Loader, - logger: &'a dyn Logger, + reporter: &'a dyn Reporter, /// Index files, even if they already exist in the database. pub force: bool, /// Maximum time per file. @@ -127,11 +153,15 @@ pub struct Indexer<'a> { } impl<'a> Indexer<'a> { - pub fn new(db: &'a mut SQLiteWriter, loader: &'a mut Loader, logger: &'a dyn Logger) -> Self { + pub fn new( + db: &'a mut SQLiteWriter, + loader: &'a mut Loader, + reporter: &'a dyn Reporter, + ) -> Self { Self { db, loader, - logger, + reporter, force: false, max_file_time: None, } @@ -149,6 +179,7 @@ impl<'a> Indexer<'a> { Q: AsRef, { for (source_root, source_path, strict) in iter_files_and_directories(source_paths) { + let mut file_status = CLIFileReporter::new(self.reporter, &source_path); cancellation_flag.check("indexing all files")?; self.index_file( &source_root, @@ -156,7 +187,9 @@ impl<'a> Indexer<'a> { strict, &mut continue_from, cancellation_flag, + &mut file_status, )?; + file_status.assert_reported(); } Ok(()) } @@ -167,13 +200,16 @@ impl<'a> Indexer<'a> { source_path: &Path, cancellation_flag: &dyn CancellationFlag, ) -> Result<()> { + let mut file_status = CLIFileReporter::new(self.reporter, source_path); self.index_file( &source_root, &source_path, true, &mut None::<&Path>, cancellation_flag, + &mut file_status, )?; + file_status.assert_reported(); Ok(()) } @@ -185,22 +221,25 @@ impl<'a> Indexer<'a> { missing_is_error: bool, continue_from: &mut Option

, cancellation_flag: &dyn CancellationFlag, + file_status: &mut CLIFileReporter, ) -> Result<()> where P: AsRef, { - let mut file_status = self.logger.file(source_path); match self.index_file_inner( source_root, source_path, missing_is_error, continue_from, cancellation_flag, - file_status.as_mut(), + file_status, ) { - ok @ Ok(_) => ok, + ok @ Ok(_) => { + file_status.assert_reported(); + ok + } err @ Err(_) => { - file_status.default_failure("error", Some(&format!("Error analyzing file {}. To continue analysis from this file later, add: --continue-from {}", source_path.display(), source_path.display()))); + file_status.failure_if_processing("error", Some(&format!("Error analyzing file {}. To continue analysis from this file later, add: --continue-from {}", source_path.display(), source_path.display()))); err } } @@ -213,7 +252,7 @@ impl<'a> Indexer<'a> { missing_is_error: bool, continue_from: &mut Option

, cancellation_flag: &dyn CancellationFlag, - file_status: &mut dyn FileLogger, + file_status: &mut CLIFileReporter<'_>, ) -> Result<()> where P: AsRef, @@ -245,22 +284,28 @@ impl<'a> Indexer<'a> { let source = file_reader.get(source_path)?; let tag = sha1(source); - if !self.force { - match self - .db - .status_for_file(&source_path.to_string_lossy(), Some(&tag))? - { - FileStatus::Missing => {} - FileStatus::Indexed => { + let success_status = match self + .db + .status_for_file(&source_path.to_string_lossy(), Some(&tag))? + { + FileStatus::Missing => "indexed", + FileStatus::Indexed => { + if self.force { + "reindexed" + } else { file_status.skipped("cached index", None); return Ok(()); } - FileStatus::Error(error) => { + } + FileStatus::Error(error) => { + if self.force { + "reindexed" + } else { file_status.skipped(&format!("cached error ({})", error), None); return Ok(()); } } - } + }; let file_cancellation_flag = CancelAfterDuration::from_option(self.max_file_time); let cancellation_flag = cancellation_flag | file_cancellation_flag.as_ref(); @@ -331,7 +376,7 @@ impl<'a> Indexer<'a> { self.db .store_result_for_file(&graph, file, &tag, &mut partials, &paths)?; - file_status.success("success", None); + file_status.success(success_status, None); Ok(()) } diff --git a/tree-sitter-stack-graphs/src/cli/lsp.rs b/tree-sitter-stack-graphs/src/cli/lsp.rs index 3b80ff420..ed4437758 100644 --- a/tree-sitter-stack-graphs/src/cli/lsp.rs +++ b/tree-sitter-stack-graphs/src/cli/lsp.rs @@ -38,8 +38,7 @@ use super::query::Querier; use super::query::QueryError; use super::util::duration_from_milliseconds_str; use super::util::duration_from_seconds_str; -use super::util::FileLogger; -use super::util::Logger; +use super::util::reporter::Reporter; use super::util::SourcePosition; use super::util::SourceSpan; @@ -208,14 +207,14 @@ impl Backend { } }; - let logger = LspLogger { + let reporter = LspReporter { handle: handle.clone(), logger: self.logger.clone(), }; let folder_cancellation_flag = CancelAfterDuration::from_option(self.args.max_folder_index_time); let cancellation_flag = cancellation_flag | folder_cancellation_flag.as_ref(); - let mut indexer = Indexer::new(&mut db, &mut loader, &logger); + let mut indexer = Indexer::new(&mut db, &mut loader, &reporter); indexer.max_file_time = self.args.max_file_index_time; let result = indexer.index_all(vec![path], None::<&Path>, &cancellation_flag); @@ -283,12 +282,12 @@ impl Backend { }; let handle = Handle::current(); - let logger = LspLogger { + let reporter = LspReporter { handle: handle.clone(), logger: self.logger.clone(), }; let result = { - let mut querier = Querier::new(&mut db, &logger); + let mut querier = Querier::new(&mut db, &reporter); let cancellation_flag = CancelAfterDuration::from_option(self.args.max_query_time); querier.definitions(reference, cancellation_flag.as_ref()) }; @@ -530,16 +529,16 @@ struct BackendLogger { } impl BackendLogger { - async fn info(&self, message: M) { - self.client.log_message(MessageType::INFO, message).await + async fn log(&self, level: MessageType, message: M) { + self.client.log_message(level, message).await } - async fn warning(&self, message: M) { - self.client.log_message(MessageType::WARNING, message).await + async fn info(&self, message: M) { + self.log(MessageType::INFO, message).await } async fn error(&self, message: M) { - self.client.log_message(MessageType::ERROR, message).await + self.log(MessageType::ERROR, message).await } } @@ -596,90 +595,43 @@ impl Job { } } -struct LspLogger { - handle: Handle, - logger: BackendLogger, -} -struct LspFileLogger<'a> { - path: &'a Path, +struct LspReporter { handle: Handle, logger: BackendLogger, } -impl Logger for LspLogger { - fn file<'a>(&self, path: &'a Path) -> Box { - Box::new(LspFileLogger { - path, - handle: self.handle.clone(), - logger: self.logger.clone(), - }) - } -} - -impl FileLogger for LspFileLogger<'_> { - fn default_failure(&mut self, status: &str, _details: Option<&dyn std::fmt::Display>) { +impl LspReporter { + fn report(&self, level: MessageType, path: &Path, status: &str) { let logger = self.logger.clone(); - let path = self.path.to_owned(); + let path = path.to_owned(); let status = status.to_owned(); self.handle.spawn(async move { logger - .error(format!("{}: {}", path.display(), status)) + .log(level, format!("{}: {}", path.display(), status)) .await; }); } +} - fn failure(&mut self, status: &str, _details: Option<&dyn std::fmt::Display>) { - let logger = self.logger.clone(); - let path = self.path.to_owned(); - let status = status.to_owned(); - self.handle.spawn(async move { - logger - .error(format!("{}: {}", path.display(), status)) - .await; - }); +impl Reporter for LspReporter { + fn skipped(&self, path: &Path, summary: &str, _details: Option<&dyn std::fmt::Display>) { + self.report(MessageType::INFO, path, summary) } - fn skipped(&mut self, status: &str, _details: Option<&dyn std::fmt::Display>) { - let logger = self.logger.clone(); - let path = self.path.to_owned(); - let status = status.to_owned(); - self.handle.spawn(async move { - logger - .info(format!("{}: skipped: {}", path.display(), status)) - .await; - }); + fn started(&self, path: &Path) { + self.report(MessageType::INFO, path, "started") } - fn warning(&mut self, status: &str, _details: Option<&dyn std::fmt::Display>) { - let logger = self.logger.clone(); - let path = self.path.to_owned(); - let status = status.to_owned(); - self.handle.spawn(async move { - logger - .warning(format!("{}: {}", path.display(), status)) - .await; - }); + fn succeeded(&self, path: &Path, summary: &str, _details: Option<&dyn std::fmt::Display>) { + self.report(MessageType::INFO, path, summary) } - fn success(&mut self, status: &str, _details: Option<&dyn std::fmt::Display>) { - let logger = self.logger.clone(); - let path = self.path.to_owned(); - let status = status.to_owned(); - self.handle.spawn(async move { - logger - .info(format!("{}: success: {}", path.display(), status)) - .await; - }); + fn failed(&self, path: &Path, summary: &str, _details: Option<&dyn std::fmt::Display>) { + self.report(MessageType::ERROR, path, summary) } - fn processing(&mut self) { - let logger = self.logger.clone(); - let path = self.path.to_owned(); - self.handle.spawn(async move { - logger - .info(format!("{}: processing...", path.display())) - .await; - }); + fn cancelled(&self, path: &Path, summary: &str, _details: Option<&dyn std::fmt::Display>) { + self.report(MessageType::WARNING, path, summary) } } diff --git a/tree-sitter-stack-graphs/src/cli/query.rs b/tree-sitter-stack-graphs/src/cli/query.rs index f0256bc67..10e7c7d35 100644 --- a/tree-sitter-stack-graphs/src/cli/query.rs +++ b/tree-sitter-stack-graphs/src/cli/query.rs @@ -20,10 +20,10 @@ use crate::loader::FileReader; use crate::CancellationFlag; use crate::NoCancellation; +use super::util::reporter::ConsoleReporter; +use super::util::reporter::Reporter; use super::util::sha1; use super::util::wait_for_input; -use super::util::ConsoleLogger; -use super::util::Logger; use super::util::SourcePosition; use super::util::SourceSpan; @@ -54,8 +54,8 @@ pub enum Target { impl Target { pub fn run(self, db: &mut SQLiteReader) -> anyhow::Result<()> { - let logger = ConsoleLogger::new(true, true); - let mut querier = Querier::new(db, &logger); + let reporter = ConsoleReporter::details(); + let mut querier = Querier::new(db, &reporter); match self { Self::Definition(cmd) => cmd.run(&mut querier), } @@ -135,12 +135,12 @@ impl Definition { pub struct Querier<'a> { db: &'a mut SQLiteReader, - logger: &'a dyn Logger, + reporter: &'a dyn Reporter, } impl<'a> Querier<'a> { - pub fn new(db: &'a mut SQLiteReader, logger: &'a dyn Logger) -> Self { - Self { db, logger } + pub fn new(db: &'a mut SQLiteReader, reporter: &'a dyn Reporter) -> Self { + Self { db, reporter } } pub fn definitions( @@ -149,7 +149,6 @@ impl<'a> Querier<'a> { cancellation_flag: &dyn CancellationFlag, ) -> Result> { let log_path = PathBuf::from(reference.to_string()); - let mut logger = self.logger.file(&log_path); let mut file_reader = FileReader::new(); let tag = file_reader.get(&reference.path).ok().map(sha1); @@ -159,12 +158,13 @@ impl<'a> Querier<'a> { { FileStatus::Indexed => {} _ => { - logger.failure("file not indexed", None); + self.reporter.started(&log_path); + self.reporter.failed(&log_path, "file not indexed", None); return Ok(Vec::default()); } } - logger.processing(); + self.reporter.started(&log_path); self.db .load_graph_for_file(&reference.path.to_string_lossy())?; @@ -172,7 +172,8 @@ impl<'a> Querier<'a> { let starting_nodes = reference.iter_references(graph).collect::>(); if starting_nodes.is_empty() { - logger.warning("no references at location", None); + self.reporter + .cancelled(&log_path, "no references at location", None); return Ok(Vec::default()); } @@ -191,7 +192,7 @@ impl<'a> Querier<'a> { reference_paths.push(p.clone()); }, ) { - logger.failure("query timed out", None); + self.reporter.failed(&log_path, "query timed out", None); return Err(err.into()); } @@ -199,7 +200,7 @@ impl<'a> Querier<'a> { let mut actual_paths = Vec::new(); for reference_path in &reference_paths { if let Err(err) = cancellation_flag.check("shadowing") { - logger.failure("query timed out", None); + self.reporter.failed(&log_path, "query timed out", None); return Err(err.into()); } if reference_paths @@ -232,7 +233,8 @@ impl<'a> Querier<'a> { } let count: usize = result.iter().map(|r| r.targets.len()).sum(); - logger.success( + self.reporter.succeeded( + &log_path, &format!( "found {} definitions for {} references", count, diff --git a/tree-sitter-stack-graphs/src/cli/status.rs b/tree-sitter-stack-graphs/src/cli/status.rs index d877d29bc..24a3b0cfd 100644 --- a/tree-sitter-stack-graphs/src/cli/status.rs +++ b/tree-sitter-stack-graphs/src/cli/status.rs @@ -14,8 +14,8 @@ use stack_graphs::storage::SQLiteReader; use std::path::Path; use std::path::PathBuf; -use super::util::ConsoleFileLogger; -use super::util::FileLogger; +use super::util::reporter::ConsoleReporter; +use super::util::reporter::Reporter; #[derive(Args)] #[clap(group( @@ -41,38 +41,48 @@ pub struct StatusArgs { impl StatusArgs { pub fn run(self, db_path: &Path) -> anyhow::Result<()> { + let reporter = self.get_reporter(); let mut db = SQLiteReader::open(&db_path)?; if self.all { let mut files = db.list_all()?; let mut entries = files.try_iter()?; - self.status(&mut entries)?; + self.status(&mut entries, &reporter)?; } else { for source_path in &self.source_paths { let source_path = source_path.canonicalize()?; let mut files = db.list_file_or_directory(&source_path)?; let mut entries = files.try_iter()?; - self.status(&mut entries)?; + self.status(&mut entries, &reporter)?; } } Ok(()) } + fn get_reporter(&self) -> ConsoleReporter { + if self.verbose { + ConsoleReporter::details() + } else { + ConsoleReporter::summary() + } + } + fn status( &self, entries: &mut impl Iterator>, + reporter: &dyn Reporter, ) -> anyhow::Result<()> { for entry in entries { let entry = entry?; - let mut logger = ConsoleFileLogger::new(&Path::new(&entry.path), true, self.verbose); + reporter.started(&entry.path); match &entry.status { FileStatus::Missing => { - logger.skipped("missing", None); + reporter.cancelled(&entry.path, "missing", None); } FileStatus::Indexed => { - logger.success("indexed", None); + reporter.succeeded(&entry.path, "indexed", None); } FileStatus::Error(error) => { - logger.failure("failed", Some(error)); + reporter.failed(&entry.path, "failed", Some(error)); } } } diff --git a/tree-sitter-stack-graphs/src/cli/test.rs b/tree-sitter-stack-graphs/src/cli/test.rs index 195f9a532..ac00639bc 100644 --- a/tree-sitter-stack-graphs/src/cli/test.rs +++ b/tree-sitter-stack-graphs/src/cli/test.rs @@ -24,9 +24,7 @@ use tree_sitter_graph::Variables; use crate::cli::util::duration_from_seconds_str; use crate::cli::util::iter_files_and_directories; -use crate::cli::util::ConsoleFileLogger; use crate::cli::util::ExistingPathBufValueParser; -use crate::cli::util::FileLogger; use crate::cli::util::PathSpec; use crate::loader::ContentProvider; use crate::loader::FileReader; @@ -37,6 +35,10 @@ use crate::test::TestResult; use crate::CancelAfterDuration; use crate::CancellationFlag; +use super::util::reporter::ConsoleReporter; +use super::util::reporter::Level; +use super::util::CLIFileReporter; + #[derive(Args)] #[clap(after_help = r#"PATH SPECIFICATIONS: Output filenames can be specified using placeholders based on the input file. @@ -171,9 +173,13 @@ impl TestArgs { } pub fn run(self, mut loader: Loader) -> anyhow::Result<()> { + let reporter = self.get_reporter(); let mut total_result = TestResult::new(); for (test_root, test_path, _) in iter_files_and_directories(self.test_paths.clone()) { - let test_result = self.run_test(&test_root, &test_path, &mut loader)?; + let mut file_status = CLIFileReporter::new(&reporter, &test_path); + let test_result = + self.run_test(&test_root, &test_path, &mut loader, &mut file_status)?; + file_status.assert_reported(); total_result.absorb(test_result); } if total_result.failure_count() > 0 { @@ -182,19 +188,39 @@ impl TestArgs { Ok(()) } + fn get_reporter(&self) -> ConsoleReporter { + return ConsoleReporter { + skipped_level: if self.show_skipped { + Level::Summary + } else { + Level::None + }, + succeeded_level: if self.quiet { + Level::None + } else { + Level::Summary + }, + failed_level: if self.hide_error_details { + Level::Summary + } else { + Level::Details + }, + canceled_level: Level::Details, // tester doesn't report canceled + }; + } + /// Run test file. Takes care of the output when an error is returned. fn run_test( &self, test_root: &Path, test_path: &Path, loader: &mut Loader, + file_status: &mut CLIFileReporter, ) -> anyhow::Result { - let mut file_status = - ConsoleFileLogger::new(test_path, !self.quiet, !self.hide_error_details); - match self.run_test_inner(test_root, test_path, loader, &mut file_status) { + match self.run_test_inner(test_root, test_path, loader, file_status) { ok @ Ok(_) => ok, err @ Err(_) => { - file_status.default_failure("error", None); + file_status.failure_if_processing("error", None); err } } @@ -205,7 +231,7 @@ impl TestArgs { test_root: &Path, test_path: &Path, loader: &mut Loader, - file_status: &mut ConsoleFileLogger, + file_status: &mut CLIFileReporter, ) -> anyhow::Result { let cancellation_flag = CancelAfterDuration::from_option(self.max_test_time); @@ -230,9 +256,7 @@ impl TestArgs { .map_or(false, |e| e == "skip"), _ => false, }) { - if self.show_skipped { - file_status.warning("skipped", None); - } + file_status.skipped("skipped", None); return Ok(TestResult::new()); } @@ -345,7 +369,7 @@ impl TestArgs { fn handle_result( &self, result: &TestResult, - file_status: &mut ConsoleFileLogger, + file_status: &mut CLIFileReporter, ) -> anyhow::Result { let success = result.failure_count() == 0; if success { diff --git a/tree-sitter-stack-graphs/src/cli/util.rs b/tree-sitter-stack-graphs/src/cli/util.rs index 65c6de1bd..66181a1fd 100644 --- a/tree-sitter-stack-graphs/src/cli/util.rs +++ b/tree-sitter-stack-graphs/src/cli/util.rs @@ -12,7 +12,6 @@ use clap::builder::TypedValueParser; use clap::error::ContextKind; use clap::error::ContextValue; use clap::error::ErrorKind; -use colored::Colorize; use lsp_positions::Span; use sha1::Digest; use sha1::Sha1; @@ -26,10 +25,12 @@ use std::ops::Range; use std::path::Path; use std::path::PathBuf; use std::time::Duration; -#[cfg(debug_assertions)] -use std::time::Instant; use walkdir::WalkDir; +use self::reporter::Reporter; + +pub mod reporter; + #[derive(Clone)] pub(crate) struct ExistingPathBufValueParser; @@ -364,173 +365,89 @@ where .flatten() } -pub trait Logger { - fn file<'a>(&self, path: &'a Path) -> Box; -} - -pub trait FileLogger { - fn processing(&mut self) {} - fn failure(&mut self, _status: &str, _details: Option<&dyn std::fmt::Display>) {} - fn skipped(&mut self, _status: &str, _details: Option<&dyn std::fmt::Display>) {} - fn success(&mut self, _status: &str, _details: Option<&dyn std::fmt::Display>) {} - fn warning(&mut self, _status: &str, _details: Option<&dyn std::fmt::Display>) {} - fn default_failure(&mut self, _status: &str, _details: Option<&dyn std::fmt::Display>) {} -} - -pub struct ConsoleLogger { - show_info: bool, - show_details: bool, -} - -impl ConsoleLogger { - pub fn new(show_info: bool, show_details: bool) -> Self { - Self { - show_info, - show_details, - } - } -} - -impl Logger for ConsoleLogger { - fn file<'a>(&self, path: &'a Path) -> Box { - Box::new(ConsoleFileLogger::new( - path, - self.show_info, - self.show_details, - )) - } -} - -pub struct ConsoleFileLogger<'a> { +/// Wraps a reporter and ensures that reporter is called properly without requiring +/// the caller of the wrapper to be overly careful about which methods must be called +/// in which order +pub(super) struct CLIFileReporter<'a> { + reporter: &'a dyn Reporter, path: &'a Path, - show_info: bool, - show_details: bool, path_logged: bool, - #[cfg(debug_assertions)] - processing_started: Option, + status_logged: bool, } -impl<'a> ConsoleFileLogger<'a> { - pub fn new(path: &'a Path, show_info: bool, show_details: bool) -> Self { +impl<'a> CLIFileReporter<'a> { + pub(super) fn new(reporter: &'a dyn Reporter, path: &'a Path) -> Self { Self { + reporter, path, - show_info, - show_details, path_logged: false, - #[cfg(debug_assertions)] - processing_started: None, + status_logged: false, } } - fn print_path(&mut self) { + pub(super) fn processing(&mut self) { if self.path_logged { - return; + panic!("Already started or finished"); } - print!("{}: ", self.path.display()); + self.reporter.started(self.path); self.path_logged = true; } - #[cfg(debug_assertions)] - fn print_processing_time(&mut self) { - if let Some(processing_started) = self.processing_started { - print!(" [{:.2} s]", processing_started.elapsed().as_secs_f64()); - } - } - - fn flush(&mut self) { - std::io::stdout().flush().expect("flush should succeed"); - } -} - -impl FileLogger for ConsoleFileLogger<'_> { - fn processing(&mut self) { - #[cfg(debug_assertions)] - { - self.processing_started = Some(Instant::now()); + fn ensure_started(&mut self) { + if self.status_logged { + panic!("Status already logged"); } - if !self.show_info { - return; + if !self.path_logged { + self.reporter.started(self.path); + self.path_logged = true; } - self.print_path(); - self.flush(); } - fn success(&mut self, status: &str, details: Option<&dyn std::fmt::Display>) { - if !self.show_info { - return; - } - self.print_path(); - print!("{}", status.green()); - #[cfg(debug_assertions)] - self.print_processing_time(); - println!(); - self.path_logged = false; - self.flush(); - if !self.show_details { - return; - } - if let Some(details) = details { - println!("{}", details); - } + pub(super) fn success(&mut self, status: &str, details: Option<&dyn std::fmt::Display>) { + self.ensure_started(); + self.reporter.succeeded(self.path, status, details); + self.status_logged = true; } - fn skipped(&mut self, status: &str, details: Option<&dyn std::fmt::Display>) { - if !self.show_info { - return; - } - self.print_path(); - print!("{}", status.dimmed()); - #[cfg(debug_assertions)] - self.print_processing_time(); - println!(); - self.path_logged = false; - self.flush(); - if !self.show_details { - return; + pub(super) fn skipped(&mut self, status: &str, details: Option<&dyn std::fmt::Display>) { + if self.path_logged { + panic!("Skipped after starting"); } - if let Some(details) = details { - println!("{}", details); + if self.status_logged { + panic!("Status already logged"); } + self.reporter.skipped(self.path, status, details); + self.status_logged = true; } - fn warning(&mut self, status: &str, details: Option<&dyn std::fmt::Display>) { - self.print_path(); - print!("{}", status.yellow()); - #[cfg(debug_assertions)] - self.print_processing_time(); - println!(); - self.path_logged = false; - self.flush(); - if !self.show_details { - return; - } - if let Some(details) = details { - println!("{}", details); - } + pub(super) fn warning(&mut self, status: &str, details: Option<&dyn std::fmt::Display>) { + self.ensure_started(); + self.reporter.cancelled(self.path, status, details); + self.status_logged = true; } - fn failure(&mut self, status: &str, details: Option<&dyn std::fmt::Display>) { - self.print_path(); - print!("{}", status.red()); - #[cfg(debug_assertions)] - self.print_processing_time(); - println!(); - self.path_logged = false; - self.flush(); - if !self.show_details { - return; - } - if let Some(details) = details { - println!("{}", details); - } + pub(super) fn failure(&mut self, status: &str, details: Option<&dyn std::fmt::Display>) { + self.ensure_started(); + self.reporter.failed(self.path, status, details); + self.status_logged = true; } - fn default_failure(&mut self, status: &str, details: Option<&dyn std::fmt::Display>) { + pub(super) fn failure_if_processing( + &mut self, + status: &str, + details: Option<&dyn std::fmt::Display>, + ) { if !self.path_logged { return; } self.failure(status, details); } + + pub(super) fn assert_reported(&mut self) { + if self.path_logged && !self.status_logged { + panic!("status not reported"); + } + } } pub(crate) fn sha1(value: &str) -> String { diff --git a/tree-sitter-stack-graphs/src/cli/util/reporter.rs b/tree-sitter-stack-graphs/src/cli/util/reporter.rs new file mode 100644 index 000000000..787c50ba4 --- /dev/null +++ b/tree-sitter-stack-graphs/src/cli/util/reporter.rs @@ -0,0 +1,178 @@ +// -*- coding: utf-8 -*- +// ------------------------------------------------------------------------------------------------ +// Copyright © 2023, stack-graphs authors. +// Licensed under either of Apache License, Version 2.0, or MIT license, at your option. +// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. +// ------------------------------------------------------------------------------------------------ + +use colored::ColoredString; +use colored::Colorize; +use std::io::Write; +use std::path::Path; + +/// Trait that supports reporting file processing status. +/// +/// For each file, either +/// - [`skipped`] is called once, or +/// - [`started`] and one of [`succeeded`], [`failed`], or [`canceled`] are called. +/// +/// Guidance for severity of these statuses: +/// - Failed files should be reported as errors. +/// - Canceled files can be reported as warnings. +/// - Succeeded and skipped files can be reported as info. +pub trait Reporter { + /// File was skipped. + fn skipped(&self, path: &Path, summary: &str, details: Option<&dyn std::fmt::Display>); + + /// File processing started. + fn started(&self, path: &Path); + + /// File was processed and succeeded. + fn succeeded(&self, path: &Path, summary: &str, details: Option<&dyn std::fmt::Display>); + + /// File was processed and failed. + fn failed(&self, path: &Path, summary: &str, details: Option<&dyn std::fmt::Display>); + + /// File could not be processed and was canceled. + fn cancelled(&self, path: &Path, summary: &str, details: Option<&dyn std::fmt::Display>); +} + +/// An enum describing the level of detail that should be reported. +#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub enum Level { + None, + Summary, + Details, +} + +/// A console reporter that outputs the path when processing starts, and appends +/// the status once finished. +#[derive(Clone, Copy, Debug)] +pub struct ConsoleReporter { + pub skipped_level: Level, + pub succeeded_level: Level, + pub failed_level: Level, + pub canceled_level: Level, +} + +impl ConsoleReporter { + pub fn none() -> Self { + Self { + skipped_level: Level::None, + succeeded_level: Level::None, + failed_level: Level::None, + canceled_level: Level::None, + } + } + + pub fn summary() -> Self { + Self { + skipped_level: Level::Summary, + succeeded_level: Level::Summary, + failed_level: Level::Summary, + canceled_level: Level::Summary, + } + } + + pub fn details() -> Self { + Self { + skipped_level: Level::Details, + succeeded_level: Level::Details, + failed_level: Level::Details, + canceled_level: Level::Details, + } + } + fn all_results_are_reported(&self) -> bool { + *[self.succeeded_level, self.failed_level, self.canceled_level] + .iter() + .min() + .unwrap() + > Level::None + } + + fn print_path(&self, path: &Path) { + print!("{}: ", path.display()); + self.flush(); + } + + fn print_result( + &self, + print_details: bool, + summary: ColoredString, + details: Option<&dyn std::fmt::Display>, + ) { + println!("{}", summary); + if !print_details { + return; + } + if let Some(details) = details { + println!("{}", details); + } + } + + fn flush(&self) { + std::io::stdout().flush().expect("flush should succeed"); + } +} + +impl Reporter for ConsoleReporter { + fn skipped(&self, path: &Path, summary: &str, details: Option<&dyn std::fmt::Display>) { + if self.skipped_level < Level::Summary { + return; + } + self.print_path(path); + self.print_result( + self.skipped_level >= Level::Details, + summary.dimmed(), + details, + ); + } + + fn started(&self, path: &Path) { + if self.all_results_are_reported() { + // we can already output the path + self.print_path(path); + } + } + + fn succeeded(&self, path: &Path, summary: &str, details: Option<&dyn std::fmt::Display>) { + if self.succeeded_level < Level::Summary { + return; + } + if !self.all_results_are_reported() { + // the path wasn't outputed when started + self.print_path(path); + } + self.print_result( + self.succeeded_level >= Level::Details, + summary.green(), + details, + ) + } + + fn failed(&self, path: &Path, summary: &str, details: Option<&dyn std::fmt::Display>) { + if self.failed_level < Level::Summary { + return; + } + if !self.all_results_are_reported() { + // the path wasn't outputed when started + self.print_path(path); + } + self.print_result(self.failed_level >= Level::Details, summary.red(), details) + } + + fn cancelled(&self, path: &Path, summary: &str, details: Option<&dyn std::fmt::Display>) { + if self.canceled_level < Level::Summary { + return; + } + if !self.all_results_are_reported() { + // the path wasn't outputed when started + self.print_path(path); + } + self.print_result( + self.canceled_level >= Level::Details, + summary.yellow(), + details, + ) + } +} From 676fe49ddae1ce0f3ffb01dc22acd02d4572dad0 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 11 Aug 2023 16:16:30 +0200 Subject: [PATCH 131/500] Only use reporter to output from `Querier` The `Querier` is a reusable type that should not assume it is used in a console output where printing things is okay. This change ensures all output is reported to the reporter only. --- tree-sitter-stack-graphs/src/cli/test.rs | 70 ++++++++++++++---------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/tree-sitter-stack-graphs/src/cli/test.rs b/tree-sitter-stack-graphs/src/cli/test.rs index ac00639bc..0eba68107 100644 --- a/tree-sitter-stack-graphs/src/cli/test.rs +++ b/tree-sitter-stack-graphs/src/cli/test.rs @@ -338,8 +338,8 @@ impl TestArgs { )?; } let result = test.run(&mut partials, &mut db, cancellation_flag.as_ref())?; - let success = self.handle_result(&result, file_status)?; - if self.output_mode.test(!success) { + let success = result.failure_count() == 0; + let outputs = if self.output_mode.test(!success) { let files = test.fragments.iter().map(|f| f.file).collect::>(); self.save_output( test_root, @@ -350,8 +350,30 @@ impl TestArgs { &|_: &StackGraph, h: &Handle| files.contains(h), success, cancellation_flag.as_ref(), - )?; + )? + } else { + Vec::default() + }; + + if success { + let details = outputs.join("\n"); + file_status.success("success", Some(&details)); + } else { + let details = result + .failures_iter() + .map(|f| f.to_string()) + .chain(outputs) + .join("\n"); + file_status.failure( + &format!( + "{}/{} assertions failed", + result.failure_count(), + result.count(), + ), + Some(&details), + ); } + Ok(result) } @@ -366,27 +388,6 @@ impl TestArgs { Ok(()) } - fn handle_result( - &self, - result: &TestResult, - file_status: &mut CLIFileReporter, - ) -> anyhow::Result { - let success = result.failure_count() == 0; - if success { - file_status.success("success", None); - } else { - file_status.failure( - &format!( - "{}/{} assertions failed", - result.failure_count(), - result.count(), - ), - Some(&result.failures_iter().join("\n")), - ); - } - Ok(success) - } - fn save_output( &self, test_root: &Path, @@ -397,7 +398,8 @@ impl TestArgs { filter: &dyn Filter, success: bool, cancellation_flag: &dyn CancellationFlag, - ) -> anyhow::Result<()> { + ) -> anyhow::Result> { + let mut outputs = Vec::with_capacity(3); let save_graph = self .save_graph .as_ref() @@ -414,7 +416,11 @@ impl TestArgs { if let Some(path) = save_graph { self.save_graph(&path, &graph, filter)?; if !success || !self.quiet { - println!("{}: graph at {}", test_path.display(), path.display()); + outputs.push(format!( + "{}: graph at {}", + test_path.display(), + path.display() + )); } } @@ -427,21 +433,25 @@ impl TestArgs { if let Some(path) = save_paths { self.save_paths(&path, graph, partials, &mut db, filter)?; if !success || !self.quiet { - println!("{}: paths at {}", test_path.display(), path.display()); + outputs.push(format!( + "{}: paths at {}", + test_path.display(), + path.display() + )); } } if let Some(path) = save_visualization { self.save_visualization(&path, graph, partials, &mut db, filter, &test_path)?; if !success || !self.quiet { - println!( + outputs.push(format!( "{}: visualization at {}", test_path.display(), path.display() - ); + )); } } - Ok(()) + Ok(outputs) } fn save_graph( From da45bcc5f682c56d80dc499b646aa807f1030161 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Fri, 11 Aug 2023 10:03:45 -0700 Subject: [PATCH 132/500] Moves .TODO files to officially supported .skip --- ...class_declaration_method_call_arguments_variable_flow.js.skip} | 0 ...> class_declaration_methods_not_visible_outside_class.js.skip} | 0 ...s.TODO => class_declaration_super_reference_to_method.js.skip} | 0 ...od.js.TODO => class_declaration_this_field_and_method.js.skip} | 0 ... class_expression_method_call_arguments_variable_flow.js.skip} | 0 ...=> class_expression_methods_not_visible_outside_class.js.skip} | 0 ...js.TODO => class_expression_super_reference_to_method.js.skip} | 0 ...hod.js.TODO => class_expression_this_field_and_method.js.skip} | 0 ...ion_call_this_flow.js.TODO => function_call_this_flow.js.skip} | 0 ...g_flow.js.TODO => with_statement_scope_shadowing_flow.js.skip} | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename languages/tree-sitter-stack-graphs-javascript/test/computation_flow/{class_declaration_method_call_arguments_variable_flow.js.TODO => class_declaration_method_call_arguments_variable_flow.js.skip} (100%) rename languages/tree-sitter-stack-graphs-javascript/test/computation_flow/{class_declaration_methods_not_visible_outside_class.js.TODO => class_declaration_methods_not_visible_outside_class.js.skip} (100%) rename languages/tree-sitter-stack-graphs-javascript/test/computation_flow/{class_declaration_super_reference_to_method.js.TODO => class_declaration_super_reference_to_method.js.skip} (100%) rename languages/tree-sitter-stack-graphs-javascript/test/computation_flow/{class_declaration_this_field_and_method.js.TODO => class_declaration_this_field_and_method.js.skip} (100%) rename languages/tree-sitter-stack-graphs-javascript/test/computation_flow/{class_expression_method_call_arguments_variable_flow.js.TODO => class_expression_method_call_arguments_variable_flow.js.skip} (100%) rename languages/tree-sitter-stack-graphs-javascript/test/computation_flow/{class_expression_methods_not_visible_outside_class.js.TODO => class_expression_methods_not_visible_outside_class.js.skip} (100%) rename languages/tree-sitter-stack-graphs-javascript/test/computation_flow/{class_expression_super_reference_to_method.js.TODO => class_expression_super_reference_to_method.js.skip} (100%) rename languages/tree-sitter-stack-graphs-javascript/test/computation_flow/{class_expression_this_field_and_method.js.TODO => class_expression_this_field_and_method.js.skip} (100%) rename languages/tree-sitter-stack-graphs-javascript/test/computation_flow/{function_call_this_flow.js.TODO => function_call_this_flow.js.skip} (100%) rename languages/tree-sitter-stack-graphs-javascript/test/computation_flow/{with_statement_scope_shadowing_flow.js.TODO => with_statement_scope_shadowing_flow.js.skip} (100%) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_arguments_variable_flow.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_arguments_variable_flow.js.skip similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_arguments_variable_flow.js.TODO rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_arguments_variable_flow.js.skip diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_methods_not_visible_outside_class.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_methods_not_visible_outside_class.js.skip similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_methods_not_visible_outside_class.js.TODO rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_methods_not_visible_outside_class.js.skip diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_super_reference_to_method.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_super_reference_to_method.js.skip similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_super_reference_to_method.js.TODO rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_super_reference_to_method.js.skip diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_this_field_and_method.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_this_field_and_method.js.skip similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_this_field_and_method.js.TODO rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_this_field_and_method.js.skip diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_arguments_variable_flow.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_arguments_variable_flow.js.skip similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_arguments_variable_flow.js.TODO rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_arguments_variable_flow.js.skip diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_methods_not_visible_outside_class.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_methods_not_visible_outside_class.js.skip similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_methods_not_visible_outside_class.js.TODO rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_methods_not_visible_outside_class.js.skip diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_super_reference_to_method.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_super_reference_to_method.js.skip similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_super_reference_to_method.js.TODO rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_super_reference_to_method.js.skip diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_this_field_and_method.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_this_field_and_method.js.skip similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_this_field_and_method.js.TODO rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_this_field_and_method.js.skip diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_call_this_flow.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_call_this_flow.js.skip similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_call_this_flow.js.TODO rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_call_this_flow.js.skip diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/with_statement_scope_shadowing_flow.js.TODO b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/with_statement_scope_shadowing_flow.js.skip similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/computation_flow/with_statement_scope_shadowing_flow.js.TODO rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/with_statement_scope_shadowing_flow.js.skip From f15237a0691e37b5265fca2f613f70c57a7cee39 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 15 Aug 2023 15:43:13 -0700 Subject: [PATCH 133/500] Fixes method arguments variable flow bug --- .../src/stack-graphs.tsg | 7 +++++++ ...ass_declaration_method_call_arguments_variable_flow.js} | 0 ...lass_expression_method_call_arguments_variable_flow.js} | 0 3 files changed, 7 insertions(+) rename languages/tree-sitter-stack-graphs-javascript/test/computation_flow/{class_declaration_method_call_arguments_variable_flow.js.skip => class_declaration_method_call_arguments_variable_flow.js} (100%) rename languages/tree-sitter-stack-graphs-javascript/test/computation_flow/{class_expression_method_call_arguments_variable_flow.js.skip => class_expression_method_call_arguments_variable_flow.js} (100%) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 690316e48..9258e3363 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -1326,6 +1326,8 @@ inherit .return_or_yield parameters:(_)@call_sig body:(_)@body)@method_def { + node call_sig_arguments_pop + node call_sig_arguments_push node @method_def.method_value_arg_scope node method_def_method_value_call node method_def_method_value_drop @@ -1345,6 +1347,11 @@ inherit .return_or_yield ; the call sig's before scope comes from the drop node then flows into the body edge @call_sig.before_scope -> method_def_method_value_drop + attr (call_sig_arguments_pop) symbol_definition = "arguments", source_node = @call_sig + attr (call_sig_arguments_push) push_symbol = "arguments" + edge call_sig_arguments_pop -> call_sig_arguments_push + edge call_sig_arguments_push -> @method_def.method_value_arg_scope + edge @call_sig.before_scope -> call_sig_arguments_pop edge @body.before_scope -> @call_sig.after_scope ; method values have call nodes diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_arguments_variable_flow.js.skip b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_arguments_variable_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_arguments_variable_flow.js.skip rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_method_call_arguments_variable_flow.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_arguments_variable_flow.js.skip b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_arguments_variable_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_arguments_variable_flow.js.skip rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_method_call_arguments_variable_flow.js From 3953a88157d8c0e4753051e97a2445421f606b45 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 15 Aug 2023 17:24:49 -0700 Subject: [PATCH 134/500] Fixes field and method visibility bug --- .../src/stack-graphs.tsg | 52 ++++++++++++++++--- .../class_declaration_constructor_field.js | 9 ++++ ...s_and_methods_not_visible_outside_class.js | 14 +++++ ..._methods_not_visible_outside_class.js.skip | 9 ---- .../class_expression_constructor_field.js | 9 ++++ ...s_and_methods_not_visible_outside_class.js | 14 +++++ ..._methods_not_visible_outside_class.js.skip | 9 ---- 7 files changed, 92 insertions(+), 24 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_constructor_field.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_fields_and_methods_not_visible_outside_class.js delete mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_methods_not_visible_outside_class.js.skip create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_constructor_field.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_fields_and_methods_not_visible_outside_class.js delete mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_methods_not_visible_outside_class.js.skip diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 9258e3363..7b7a87580 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -246,6 +246,8 @@ inherit .builtins_string inherit .builtins_undefined inherit .exports inherit .return_or_yield +inherit .class_value +inherit .constructor @@ -1233,23 +1235,36 @@ inherit .return_or_yield node @name.pop node @class_decl.class_value + node guard_prototype + node @class_decl.prototype + node @class_decl.constructor attr (@name.pop) syntax_type = "class" attr (@name.pop) node_definition = @name + attr (guard_prototype) pop_symbol = "GUARD:PROTOTYPE" edge @class_decl.after_scope -> @name.pop edge @name.pop -> @class_decl.class_value + edge @class_decl.class_value -> guard_prototype + edge guard_prototype -> @class_decl.prototype edge @body.before_scope -> @class_decl.before_scope - edge @class_decl.class_value -> @body.after_scope + edge @class_decl.prototype -> @body.after_scope edge @class_decl.after_scope -> @class_decl.before_scope } (class_declaration (class_heritage (_)@name))@class_decl { + node guard_prototype + node guard_constructor + attr (guard_prototype) push_symbol = "GUARD:PROTOTYPE" + attr (guard_constructor) push_symbol = "GUARD:CONSTRUCTOR" edge @name.before_scope -> @class_decl.before_scope - edge @class_decl.class_value -> @name.value + edge @class_decl.prototype -> guard_prototype + edge guard_prototype -> @name.value + edge @class_decl.constructor -> guard_constructor + edge guard_constructor -> @name.value } @@ -1302,8 +1317,9 @@ inherit .return_or_yield ; augmentation for the constructor attr (name_constructor_guard) symbol_definition = "GUARD:CONSTRUCTOR", source_node = @name - edge @method_def.after_scope -> name_constructor_guard - edge name_constructor_guard -> @method_def.method_value + edge @method_def.class_value -> name_constructor_guard + edge name_constructor_guard -> @method_def.constructor + edge @method_def.constructor -> @method_def.method_value } ( @@ -2881,6 +2897,12 @@ inherit .return_or_yield ; value coming from the field decls in the class edge @new_expr.value -> @constructor.value + ; value also coming from the prototype + node guard_prototype + attr (guard_prototype) push_symbol = "GUARD:PROTOTYPE" + edge @new_expr.value -> guard_prototype + edge guard_prototype -> @constructor.value + attr (@arguments.arg_this) symbol_definition = "this", source_node = @arguments edge @arguments.arg_scope -> @arguments.arg_this edge @arguments.arg_this -> @new_expr.builtins_empty_object @@ -3118,8 +3140,18 @@ inherit .return_or_yield (class body:(_)@body)@class { + node @class.class_value + node guard_prototype + node @class.prototype + node @class.constructor + attr (guard_prototype) pop_symbol = "GUARD:PROTOTYPE" + edge @body.before_scope -> @class.before_scope - edge @class.value -> @body.after_scope + edge @class.value -> @class.class_value + edge @class.class_value -> guard_prototype + edge guard_prototype -> @class.prototype + edge @class.class_value -> @class.constructor + edge @class.prototype -> @body.after_scope edge @class.after_scope -> @class.before_scope } @@ -3138,8 +3170,16 @@ inherit .return_or_yield (class (class_heritage (_)@name))@class { + node guard_prototype + node guard_constructor + attr (guard_prototype) push_symbol = "GUARD:PROTOTYPE" + attr (guard_constructor) push_symbol = "GUARD:CONSTRUCTOR" edge @name.before_scope -> @class.before_scope - edge @class.value -> @name.value + edge @class.prototype -> guard_prototype + edge guard_prototype -> @name.value + edge @class.constructor -> guard_constructor + edge guard_constructor -> @name.value + edge @class.after_scope -> @name.after_scope } diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_constructor_field.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_constructor_field.js new file mode 100644 index 000000000..3861e37c9 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_constructor_field.js @@ -0,0 +1,9 @@ +class Foo { + constructor() { + this.bar = 5; + } +}; + +let x = new Foo(); +x.bar; +// ^ defined: 3 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_fields_and_methods_not_visible_outside_class.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_fields_and_methods_not_visible_outside_class.js new file mode 100644 index 000000000..7a8101f2c --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_fields_and_methods_not_visible_outside_class.js @@ -0,0 +1,14 @@ +class Foo { + bar = 1; + baz() { + + } +} + +Foo.bar; +// ^ defined: +// bar should not be visible here + +Foo.baz; +// ^ defined: +// baz should not be visible here \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_methods_not_visible_outside_class.js.skip b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_methods_not_visible_outside_class.js.skip deleted file mode 100644 index 9098635ca..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_methods_not_visible_outside_class.js.skip +++ /dev/null @@ -1,9 +0,0 @@ -class Foo { - bar() { - - } -} - -Foo.bar; -// ^ defined: -// bar should not be visible here \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_constructor_field.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_constructor_field.js new file mode 100644 index 000000000..9caaf5ada --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_constructor_field.js @@ -0,0 +1,9 @@ +let Foo = class { + constructor() { + this.bar = 5; + } +}; + +let x = new Foo(); +x.bar; +// ^ defined: 3 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_fields_and_methods_not_visible_outside_class.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_fields_and_methods_not_visible_outside_class.js new file mode 100644 index 000000000..4b02b50be --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_fields_and_methods_not_visible_outside_class.js @@ -0,0 +1,14 @@ +let Foo = class { + bar = 1; + baz() { + + } +}; + +Foo.bar; +// ^ defined: +// bar should not be visible here + +Foo.baz; +// ^ defined: +// baz should not be visible here \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_methods_not_visible_outside_class.js.skip b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_methods_not_visible_outside_class.js.skip deleted file mode 100644 index e1a573d14..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_expression_methods_not_visible_outside_class.js.skip +++ /dev/null @@ -1,9 +0,0 @@ -let Foo = class { - bar() { - - } -}; - -Foo.bar; -// ^ defined: -// bar should not be visible here \ No newline at end of file From 1a0fc62d9d9aa3028f4120867b7784c528910001 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 15 Aug 2023 17:42:20 -0700 Subject: [PATCH 135/500] Fixes with statement shadowing bug --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 4 ++++ ...ng_flow.js.skip => with_statement_scope_shadowing_flow.js} | 0 2 files changed, 4 insertions(+) rename languages/tree-sitter-stack-graphs-javascript/test/computation_flow/{with_statement_scope_shadowing_flow.js.skip => with_statement_scope_shadowing_flow.js} (100%) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 7b7a87580..62e67b515 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -1811,10 +1811,14 @@ inherit .constructor edge @object.before_scope -> @with_stmt.before_scope edge @body.before_scope -> @object.after_scope edge @with_stmt.after_scope -> @body.after_scope + edge @with_stmt.after_scope -> @with_stmt.before_scope + attr (@with_stmt.after_scope -> @with_stmt.before_scope) precedence = 1 + attr (with_stmt_push_dot) push_symbol = "GUARD:MEMBER" edge with_stmt_push_dot -> @object.value edge @body.before_scope -> with_stmt_push_dot + attr (@body.before_scope -> with_stmt_push_dot) precedence = 1 } diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/with_statement_scope_shadowing_flow.js.skip b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/with_statement_scope_shadowing_flow.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/computation_flow/with_statement_scope_shadowing_flow.js.skip rename to languages/tree-sitter-stack-graphs-javascript/test/computation_flow/with_statement_scope_shadowing_flow.js From ea08fc72fcc73cf47e8f85e8a3c1a1eb2d8d9db2 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 13 Sep 2023 17:28:21 +0200 Subject: [PATCH 136/500] Replace super:: with crate:: imports --- tree-sitter-stack-graphs/src/cli.rs | 6 ++---- tree-sitter-stack-graphs/src/cli/index.rs | 21 +++++++++---------- tree-sitter-stack-graphs/src/cli/lsp.rs | 17 +++++++-------- tree-sitter-stack-graphs/src/cli/parse.rs | 3 +-- tree-sitter-stack-graphs/src/cli/query.rs | 13 ++++++------ tree-sitter-stack-graphs/src/cli/status.rs | 4 ++-- tree-sitter-stack-graphs/src/cli/test.rs | 7 +++---- .../src/cli/util/reporter.rs | 2 +- 8 files changed, 33 insertions(+), 40 deletions(-) diff --git a/tree-sitter-stack-graphs/src/cli.rs b/tree-sitter-stack-graphs/src/cli.rs index 830378708..719ce8f18 100644 --- a/tree-sitter-stack-graphs/src/cli.rs +++ b/tree-sitter-stack-graphs/src/cli.rs @@ -78,6 +78,7 @@ pub mod path_loading { use clap::Subcommand; use crate::cli::clean::CleanArgs; + use crate::cli::database::DatabaseArgs; use crate::cli::index::IndexArgs; use crate::cli::init::InitArgs; use crate::cli::load::PathLoaderArgs; @@ -90,8 +91,6 @@ pub mod path_loading { use crate::cli::test::TestArgs; use crate::cli::visualize::VisualizeArgs; - use super::database::DatabaseArgs; - #[derive(Subcommand)] pub enum Subcommands { Clean(Clean), @@ -297,6 +296,7 @@ pub mod provided_languages { use clap::Subcommand; use crate::cli::clean::CleanArgs; + use crate::cli::database::DatabaseArgs; use crate::cli::index::IndexArgs; use crate::cli::init::InitArgs; use crate::cli::load::LanguageConfigurationsLoaderArgs; @@ -310,8 +310,6 @@ pub mod provided_languages { use crate::cli::visualize::VisualizeArgs; use crate::loader::LanguageConfiguration; - use super::database::DatabaseArgs; - #[derive(Subcommand)] pub enum Subcommands { Clean(Clean), diff --git a/tree-sitter-stack-graphs/src/cli/index.rs b/tree-sitter-stack-graphs/src/cli/index.rs index 6d612a851..a90056f4b 100644 --- a/tree-sitter-stack-graphs/src/cli/index.rs +++ b/tree-sitter-stack-graphs/src/cli/index.rs @@ -21,6 +21,16 @@ use std::time::Duration; use thiserror::Error; use tree_sitter_graph::Variables; +use crate::cli::util::duration_from_seconds_str; +use crate::cli::util::iter_files_and_directories; +use crate::cli::util::reporter::ConsoleReporter; +use crate::cli::util::reporter::Level; +use crate::cli::util::reporter::Reporter; +use crate::cli::util::sha1; +use crate::cli::util::wait_for_input; +use crate::cli::util::BuildErrorWithSource; +use crate::cli::util::CLIFileReporter; +use crate::cli::util::ExistingPathBufValueParser; use crate::loader::FileLanguageConfigurations; use crate::loader::FileReader; use crate::loader::Loader; @@ -29,17 +39,6 @@ use crate::CancelAfterDuration; use crate::CancellationFlag; use crate::NoCancellation; -use super::util::duration_from_seconds_str; -use super::util::iter_files_and_directories; -use super::util::reporter::ConsoleReporter; -use super::util::reporter::Level; -use super::util::reporter::Reporter; -use super::util::sha1; -use super::util::wait_for_input; -use super::util::BuildErrorWithSource; -use super::util::CLIFileReporter; -use super::util::ExistingPathBufValueParser; - #[derive(Args)] pub struct IndexArgs { /// Source file or directory paths to index. diff --git a/tree-sitter-stack-graphs/src/cli/lsp.rs b/tree-sitter-stack-graphs/src/cli/lsp.rs index ed4437758..03f1c8060 100644 --- a/tree-sitter-stack-graphs/src/cli/lsp.rs +++ b/tree-sitter-stack-graphs/src/cli/lsp.rs @@ -28,20 +28,19 @@ use tower_lsp::LanguageServer; use tower_lsp::LspService; use tower_lsp::Server; +use crate::cli::index::Indexer; +use crate::cli::query::Querier; +use crate::cli::query::QueryError; +use crate::cli::util::duration_from_milliseconds_str; +use crate::cli::util::duration_from_seconds_str; +use crate::cli::util::reporter::Reporter; +use crate::cli::util::SourcePosition; +use crate::cli::util::SourceSpan; use crate::loader::Loader; use crate::AtomicCancellationFlag; use crate::CancelAfterDuration; use crate::CancellationFlag; -use super::index::Indexer; -use super::query::Querier; -use super::query::QueryError; -use super::util::duration_from_milliseconds_str; -use super::util::duration_from_seconds_str; -use super::util::reporter::Reporter; -use super::util::SourcePosition; -use super::util::SourceSpan; - #[derive(Args, Clone)] pub struct LspArgs { /// Maximum index runtime per workspace folder in seconds. diff --git a/tree-sitter-stack-graphs/src/cli/parse.rs b/tree-sitter-stack-graphs/src/cli/parse.rs index b4cc688f8..aff7681b1 100644 --- a/tree-sitter-stack-graphs/src/cli/parse.rs +++ b/tree-sitter-stack-graphs/src/cli/parse.rs @@ -13,13 +13,12 @@ use std::path::PathBuf; use tree_sitter::Parser; use tree_sitter_graph::parse_error::ParseError; +use crate::cli::util::ExistingPathBufValueParser; use crate::loader::FileReader; use crate::loader::Loader; use crate::util::DisplayParseErrorsPretty; use crate::BuildError; -use super::util::ExistingPathBufValueParser; - #[derive(Args)] pub struct ParseArgs { /// Source file path to parse. diff --git a/tree-sitter-stack-graphs/src/cli/query.rs b/tree-sitter-stack-graphs/src/cli/query.rs index 10e7c7d35..583aee85b 100644 --- a/tree-sitter-stack-graphs/src/cli/query.rs +++ b/tree-sitter-stack-graphs/src/cli/query.rs @@ -16,17 +16,16 @@ use std::path::PathBuf; use thiserror::Error; use tree_sitter_graph::parse_error::Excerpt; +use crate::cli::util::reporter::ConsoleReporter; +use crate::cli::util::reporter::Reporter; +use crate::cli::util::sha1; +use crate::cli::util::wait_for_input; +use crate::cli::util::SourcePosition; +use crate::cli::util::SourceSpan; use crate::loader::FileReader; use crate::CancellationFlag; use crate::NoCancellation; -use super::util::reporter::ConsoleReporter; -use super::util::reporter::Reporter; -use super::util::sha1; -use super::util::wait_for_input; -use super::util::SourcePosition; -use super::util::SourceSpan; - #[derive(Args)] pub struct QueryArgs { /// Wait for user input before starting analysis. Useful for profiling. diff --git a/tree-sitter-stack-graphs/src/cli/status.rs b/tree-sitter-stack-graphs/src/cli/status.rs index 24a3b0cfd..847837b80 100644 --- a/tree-sitter-stack-graphs/src/cli/status.rs +++ b/tree-sitter-stack-graphs/src/cli/status.rs @@ -14,8 +14,8 @@ use stack_graphs::storage::SQLiteReader; use std::path::Path; use std::path::PathBuf; -use super::util::reporter::ConsoleReporter; -use super::util::reporter::Reporter; +use crate::cli::util::reporter::ConsoleReporter; +use crate::cli::util::reporter::Reporter; #[derive(Args)] #[clap(group( diff --git a/tree-sitter-stack-graphs/src/cli/test.rs b/tree-sitter-stack-graphs/src/cli/test.rs index 0eba68107..9566687f1 100644 --- a/tree-sitter-stack-graphs/src/cli/test.rs +++ b/tree-sitter-stack-graphs/src/cli/test.rs @@ -24,6 +24,9 @@ use tree_sitter_graph::Variables; use crate::cli::util::duration_from_seconds_str; use crate::cli::util::iter_files_and_directories; +use crate::cli::util::reporter::ConsoleReporter; +use crate::cli::util::reporter::Level; +use crate::cli::util::CLIFileReporter; use crate::cli::util::ExistingPathBufValueParser; use crate::cli::util::PathSpec; use crate::loader::ContentProvider; @@ -35,10 +38,6 @@ use crate::test::TestResult; use crate::CancelAfterDuration; use crate::CancellationFlag; -use super::util::reporter::ConsoleReporter; -use super::util::reporter::Level; -use super::util::CLIFileReporter; - #[derive(Args)] #[clap(after_help = r#"PATH SPECIFICATIONS: Output filenames can be specified using placeholders based on the input file. diff --git a/tree-sitter-stack-graphs/src/cli/util/reporter.rs b/tree-sitter-stack-graphs/src/cli/util/reporter.rs index 787c50ba4..0dc249a4a 100644 --- a/tree-sitter-stack-graphs/src/cli/util/reporter.rs +++ b/tree-sitter-stack-graphs/src/cli/util/reporter.rs @@ -14,7 +14,7 @@ use std::path::Path; /// /// For each file, either /// - [`skipped`] is called once, or -/// - [`started`] and one of [`succeeded`], [`failed`], or [`canceled`] are called. +/// - [`started`] and then one of [`succeeded`], [`failed`], or [`canceled`] are called. /// /// Guidance for severity of these statuses: /// - Failed files should be reported as errors. From c2bd36309644b6493e02c0db36c0a482bebff23d Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 13 Sep 2023 17:36:09 +0200 Subject: [PATCH 137/500] Update changelog --- tree-sitter-stack-graphs/CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tree-sitter-stack-graphs/CHANGELOG.md b/tree-sitter-stack-graphs/CHANGELOG.md index d4e1d197f..8d8ef7ca1 100644 --- a/tree-sitter-stack-graphs/CHANGELOG.md +++ b/tree-sitter-stack-graphs/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Library + +#### Changed + +- A new `Reporter` trait is used to support reporting status from CLI actions such as indexing and testing. The CLI actions have been cleaned up to ensure that they are not writing directly to the console anymore, but only call the reporter for output. The `Reporter` trait replaces the old inaccessible `Logger` trait so that clients can more easily implement their own reporters if necessary. A `ConsoleLogger` is provided for clients who just need console printing. + ## v0.7.1 -- 2023-07-27 Support `stack-graphs` version `0.12`. From 4a271ca1e908fb26d97b707a74a9929eb597c0d1 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 13 Sep 2023 17:38:36 +0200 Subject: [PATCH 138/500] Explicitly use pre-2021 resolver for workspace --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index e4469123a..587e70d61 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +resolver = "1" members = [ # library projects "lsp-positions", From c27f4ef0749d4dbefe307abacd897274bbf05c61 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 30 Jun 2023 11:51:03 +0200 Subject: [PATCH 139/500] Rename `Candidates` to `ForwardCandidates` This is to keep consistent with the `ForwardPartialPathStitcher` and it keeps to option open to introduce `Backward` versions in the future. --- stack-graphs/src/stitching.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index cf1ecbdd7..3416bbff0 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -174,8 +174,8 @@ where /// A trait to support finding candidates for partial path extension. Requires an accompanying /// [`ToAppendable`] implementation to convert the candidate handles into [`Appendable`]s. -pub trait Candidates { - fn find_candidates( +pub trait ForwardCandidates { + fn find_forward_candidates( &mut self, graph: &StackGraph, partials: &mut PartialPaths, @@ -197,8 +197,8 @@ impl ToAppendable for GraphEdges { } } -impl Candidates for GraphEdges { - fn find_candidates( +impl ForwardCandidates for GraphEdges { + fn find_forward_candidates( &mut self, graph: &StackGraph, _partials: &mut PartialPaths, @@ -500,8 +500,8 @@ impl ToAppendable, PartialPath> for Database { } } -impl Candidates> for Database { - fn find_candidates( +impl ForwardCandidates> for Database { + fn find_forward_candidates( &mut self, graph: &StackGraph, partials: &mut PartialPaths, @@ -764,7 +764,7 @@ impl ForwardPartialPathStitcher { ) -> usize where A: Appendable, - Db: Candidates + ToAppendable, + Db: ForwardCandidates + ToAppendable, { copious_debugging!(" Extend {}", partial_path.display(graph, partials)); @@ -794,7 +794,7 @@ impl ForwardPartialPathStitcher { // find candidates to append self.candidates.clear(); - db.find_candidates(graph, partials, partial_path, &mut self.candidates); + db.find_forward_candidates(graph, partials, partial_path, &mut self.candidates); // try to extend path with candidates let extension_count = self.candidates.len(); @@ -860,7 +860,7 @@ impl ForwardPartialPathStitcher { extend_while: E, ) where A: Appendable, - Db: Candidates + ToAppendable, + Db: ForwardCandidates + ToAppendable, E: Fn(&StackGraph, &mut PartialPaths, &PartialPath) -> bool, { copious_debugging!("==> Start phase {}", self.phase_number); @@ -986,7 +986,7 @@ impl ForwardPartialPathStitcher { where I: IntoIterator>, A: Appendable, - Db: Candidates + ToAppendable, + Db: ForwardCandidates + ToAppendable, F: FnMut(&StackGraph, &mut PartialPaths, &PartialPath), { let initial_paths = starting_nodes From b20ac57671bc5a803a5879bafbbe1da3fd0c5fe8 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 30 Jun 2023 15:03:18 +0200 Subject: [PATCH 140/500] Allow `ForwardPartialPathStitcher` to work directly on a `SQLiteReader` These changes add support for using `ForwardPartialPathStitcher` directly on a `SQLiteReader` (besides the already supported graph edges and `Database`). This required pushing the `StackGraph` + `PartialPaths` + `ToAppendable` values into the `ForwardCandidates` trait, to allow the candidates implementation to lazily load data during the stitching process. --- stack-graphs/CHANGELOG.md | 6 +- stack-graphs/src/assert.rs | 5 +- stack-graphs/src/c.rs | 14 +- stack-graphs/src/stitching.rs | 229 ++++++++++++------ stack-graphs/src/storage.rs | 74 +++--- .../tests/it/can_jump_to_definition.rs | 7 +- ...ion_with_forward_partial_path_stitching.rs | 5 +- stack-graphs/tests/it/cycles.rs | 4 +- tree-sitter-stack-graphs/src/cli/query.rs | 10 +- tree-sitter-stack-graphs/src/cli/test.rs | 5 +- tree-sitter-stack-graphs/src/cli/visualize.rs | 12 +- 11 files changed, 218 insertions(+), 153 deletions(-) diff --git a/stack-graphs/CHANGELOG.md b/stack-graphs/CHANGELOG.md index ee5b6404f..c61221e8e 100644 --- a/stack-graphs/CHANGELOG.md +++ b/stack-graphs/CHANGELOG.md @@ -15,7 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - The `Appendable` trait has been simplified. Its `Ctx` type parameter is gone, in favor of a separate trait `ToAppendable` that is used to find appendables for a handle. The type itself moved from the `cycles` to the `stitching` module. -- The `ForwardPartialPathStitcher` has been generalized so that it can be used to build paths from a database or from graph edges. It now takes a type parameter indicating the type of candidates it uses. Instead of a `Database` instance, it expects a value that implements the `Candidates` and `ToAppendable` traits. The `ForwardPartialPathStitcher::process_next_phase` expects an additional `extend_until` closure that controls whether the extended paths are considered for further extension or not (using `|_,_,_| true` retains old behavior). +- The `ForwardPartialPathStitcher` has been generalized so that it can be used to build paths from a database, graph edges, or a SQL reader. It now takes a type parameter indicating the type of candidates it uses. Instead `StackGraph`, `PartialPaths` and `Database` instances, it expects a value that implements the `ForwardCandidates` trait. The `ForwardPartialPathStitcher::process_next_phase` expects an additional `extend_until` closure that controls whether the extended paths are considered for further extension or not (using `|_,_,_| true` retains old behavior). - The SQLite database implementation is using a new schema which stores binary instead of JSON values, resulting in faster write times and smaller databases. - Renamed method `SQLiteReader::load_graph_for_file_or_directory` to `SQLiteReader::load_graphs_for_file_or_directory`. @@ -30,7 +30,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - The `ForwardPartialPathStitcher::from_nodes` function has been removed. Callers are responsible for creating the right initial paths, which can be done using `PartialPath::from_node`. - The `PartialPaths::find_minimal_partial_path_set_in_file` method has been removed in favor of `ForwardPartialPathStitcher::find_minimal_partial_path_set_in_file`. -- The `PartialPaths::find_all_complete_paths` method has been removed in favor of `ForwardPartialPathStitcher::find_all_complete_partial_paths` using `GraphEdges(None)` for the `db` argument. +- The `PartialPaths::find_all_complete_paths` method has been removed in favor of `ForwardPartialPathStitcher::find_all_complete_partial_paths` using a `GraphEdgeCandidates` instance for the `candidates` argument. +- The `Database::find_all_complete_paths` method has been removed in favor of `ForwardPartialPathStitcher::find_all_complete_partial_paths` using a `DatabaseCandidates` instance for the `candidates` argument. +- The `SQLiteReader::find_all_complete_partial_paths` method has been removed in favor of `ForwardPartialPathStitcher::find_all_complete_partial_paths` using a `SQLiteReader` instance for the `candidates` argument. - The `OwnedOrDatabasePath` has been removed because it was obsolete with the changes to `Appendable`. ## v0.11.0 -- 2023-06-08 diff --git a/stack-graphs/src/assert.rs b/stack-graphs/src/assert.rs index c00087eae..70237614c 100644 --- a/stack-graphs/src/assert.rs +++ b/stack-graphs/src/assert.rs @@ -18,6 +18,7 @@ use crate::graph::Symbol; use crate::partial::PartialPath; use crate::partial::PartialPaths; use crate::stitching::Database; +use crate::stitching::DatabaseCandidates; use crate::stitching::ForwardPartialPathStitcher; use crate::CancellationError; use crate::CancellationFlag; @@ -179,9 +180,7 @@ impl Assertion { for reference in &references { let mut reference_paths = Vec::new(); ForwardPartialPathStitcher::find_all_complete_partial_paths( - graph, - partials, - db, + &mut DatabaseCandidates::new(graph, partials, db), vec![*reference], cancellation_flag, |_, _, p| { diff --git a/stack-graphs/src/c.rs b/stack-graphs/src/c.rs index 1b4c95a34..f4857c791 100644 --- a/stack-graphs/src/c.rs +++ b/stack-graphs/src/c.rs @@ -29,8 +29,9 @@ use crate::partial::PartialScopeStack; use crate::partial::PartialScopedSymbol; use crate::partial::PartialSymbolStack; use crate::stitching::Database; +use crate::stitching::DatabaseCandidates; use crate::stitching::ForwardPartialPathStitcher; -use crate::stitching::GraphEdges; +use crate::stitching::GraphEdgeCandidates; use crate::CancellationError; use crate::CancellationFlag; @@ -1218,9 +1219,7 @@ pub extern "C" fn sg_partial_path_arena_find_all_complete_paths( let cancellation_flag: Option<&AtomicUsize> = unsafe { std::mem::transmute(cancellation_flag.as_ref()) }; ForwardPartialPathStitcher::find_all_complete_partial_paths( - graph, - partials, - &mut GraphEdges(None), + &mut GraphEdgeCandidates::new(graph, partials, None), starting_nodes.iter().copied().map(sg_node_handle::into), &AtomicUsizeCancellationFlag(cancellation_flag), |graph, _partials, path| { @@ -1535,9 +1534,10 @@ pub extern "C" fn sg_forward_partial_path_stitcher_process_next_phase( let partials = unsafe { &mut (*partials).inner }; let db = unsafe { &mut (*db).inner }; let stitcher = unsafe { &mut *(stitcher as *mut InternalForwardPartialPathStitcher) }; - stitcher - .stitcher - .process_next_phase(graph, partials, db, |_, _, _| true); + stitcher.stitcher.process_next_phase( + &mut DatabaseCandidates::new(graph, partials, db), + |_, _, _| true, + ); stitcher.update_previous_phase_partial_paths(partials); } diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index 3416bbff0..ece844b5a 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -174,44 +174,79 @@ where /// A trait to support finding candidates for partial path extension. Requires an accompanying /// [`ToAppendable`] implementation to convert the candidate handles into [`Appendable`]s. -pub trait ForwardCandidates { - fn find_forward_candidates( +pub trait ForwardCandidates +where + A: Appendable, + Db: ToAppendable, +{ + /// Load possible forward candidates for the given partial path. + fn load_forward_candidates( &mut self, - graph: &StackGraph, - partials: &mut PartialPaths, - path: &PartialPath, - result: &mut R, - ) where + _path: &PartialPath, + _cancellation_flag: &dyn CancellationFlag, + ) -> Result<(), CancellationError> { + Ok(()) + } + + /// Get forward candidates for extending the given partial path and add them to the provided + /// result instance. If the trait implementation loads data lazily, this only considers already + /// loaded data. + fn get_forward_candidates(&mut self, path: &PartialPath, result: &mut R) + where R: std::iter::Extend; + + fn get_graph_and_partials(&mut self) -> (&StackGraph, &mut PartialPaths, &Db); } //------------------------------------------------------------------------------------------------- // FileEdges /// Acts as a database of the edges in the graph. -pub struct GraphEdges(pub Option>); +pub struct GraphEdgeCandidates<'a> { + graph: &'a StackGraph, + partials: &'a mut PartialPaths, + file: Option>, + edges: GraphEdges, +} -impl ToAppendable for GraphEdges { - fn get_appendable<'a>(&'a self, value: &'a Edge) -> &'a Edge { - value +impl<'a> GraphEdgeCandidates<'a> { + pub fn new( + graph: &'a StackGraph, + partials: &'a mut PartialPaths, + file: Option>, + ) -> Self { + Self { + graph, + partials, + file, + edges: GraphEdges, + } } } -impl ForwardCandidates for GraphEdges { - fn find_forward_candidates( - &mut self, - graph: &StackGraph, - _partials: &mut PartialPaths, - path: &PartialPath, - result: &mut R, - ) where +impl ForwardCandidates for GraphEdgeCandidates<'_> { + fn get_forward_candidates(&mut self, path: &PartialPath, result: &mut R) + where R: std::iter::Extend, { - result.extend( - graph - .outgoing_edges(path.end_node) - .filter(|e| self.0.map_or(true, |file| graph[e.sink].is_in_file(file))), - ); + result.extend(self.graph.outgoing_edges(path.end_node).filter(|e| { + self.file + .map_or(true, |file| self.graph[e.sink].is_in_file(file)) + })); + } + + fn get_graph_and_partials(&mut self) -> (&StackGraph, &mut PartialPaths, &GraphEdges) { + (self.graph, self.partials, &self.edges) + } +} + +/// A dummy type to act as the "database" for graph edges. Its [`ToAppendable`] implementation +/// is the identity on edges. +pub struct GraphEdges; + +impl ToAppendable for GraphEdges { + fn get_appendable<'a>(&'a self, edge: &'a Edge) -> &'a Edge { + edge } } @@ -303,6 +338,32 @@ impl Database { handle } + /// Find all partial paths in this database that start at the given path's end node. + /// If the end node is the root node, returns paths with a symbol stack precondition + /// that are compatible with the path's symbol stack post condition. + pub fn find_candidate_partial_paths( + &mut self, + graph: &StackGraph, + partials: &mut PartialPaths, + path: &PartialPath, + result: &mut R, + ) where + R: std::iter::Extend>, + { + if graph[path.end_node].is_root() { + // The join node is root, so there's no need to use half-open symbol stacks here, as we + // do for [`PartialPath::concatenate`][]. + let key = SymbolStackKey::from_partial_symbol_stack( + partials, + self, + path.symbol_stack_postcondition, + ); + self.find_candidate_partial_paths_from_root(graph, partials, Some(key), result); + } else { + self.find_candidate_partial_paths_from_node(graph, partials, path.end_node, result); + } + } + /// Find all partial paths in this database that start at the root node, and have a symbol /// stack precondition that is compatible with a given symbol stack. #[cfg_attr(not(feature = "copious-debugging"), allow(unused_variables))] @@ -500,28 +561,37 @@ impl ToAppendable, PartialPath> for Database { } } -impl ForwardCandidates> for Database { - fn find_forward_candidates( - &mut self, - graph: &StackGraph, - partials: &mut PartialPaths, - path: &PartialPath, - result: &mut R, - ) where +pub struct DatabaseCandidates<'a> { + graph: &'a StackGraph, + partials: &'a mut PartialPaths, + database: &'a mut Database, +} + +impl<'a> DatabaseCandidates<'a> { + pub fn new( + graph: &'a StackGraph, + partials: &'a mut PartialPaths, + database: &'a mut Database, + ) -> Self { + Self { + graph, + partials, + database, + } + } +} + +impl ForwardCandidates, PartialPath, Database> for DatabaseCandidates<'_> { + fn get_forward_candidates(&mut self, path: &PartialPath, result: &mut R) + where R: std::iter::Extend>, { - if graph[path.end_node].is_root() { - // The join node is root, so there's no need to use half-open symbol stacks here, as we - // do for [`PartialPath::concatenate`][]. - let key = SymbolStackKey::from_partial_symbol_stack( - partials, - self, - path.symbol_stack_postcondition, - ); - self.find_candidate_partial_paths_from_root(graph, partials, Some(key), result); - } else { - self.find_candidate_partial_paths_from_node(graph, partials, path.end_node, result); - } + self.database + .find_candidate_partial_paths(self.graph, self.partials, path, result); + } + + fn get_graph_and_partials(&mut self) -> (&StackGraph, &mut PartialPaths, &Database) { + (self.graph, self.partials, self.database) } } @@ -754,18 +824,18 @@ impl ForwardPartialPathStitcher { /// Attempts to extend one partial path as part of the algorithm. When calling this function, /// you are responsible for ensuring that `db` already contains all of the possible appendables /// that we might want to extend `partial_path` with. - fn extend( + fn extend( &mut self, - graph: &StackGraph, - partials: &mut PartialPaths, - db: &mut Db, + candidates: &mut C, partial_path: &PartialPath, cycle_detector: AppendingCycleDetector, ) -> usize where A: Appendable, - Db: ForwardCandidates + ToAppendable, + Db: ToAppendable, + C: ForwardCandidates, { + let (graph, partials, db) = candidates.get_graph_and_partials(); copious_debugging!(" Extend {}", partial_path.display(graph, partials)); // check is path is cyclic, in which case we do not extend it @@ -794,13 +864,14 @@ impl ForwardPartialPathStitcher { // find candidates to append self.candidates.clear(); - db.find_forward_candidates(graph, partials, partial_path, &mut self.candidates); + candidates.get_forward_candidates(partial_path, &mut self.candidates); // try to extend path with candidates let extension_count = self.candidates.len(); self.next_iteration.0.reserve(extension_count); self.next_iteration.1.reserve(extension_count); for extension in &self.candidates { + let (graph, partials, db) = candidates.get_graph_and_partials(); let extension_path = db.get_appendable(extension); copious_debugging!(" with {}", extension_path.display(graph, partials)); @@ -852,15 +923,11 @@ impl ForwardPartialPathStitcher { /// or not. It is not called on the initial paths. /// /// [`previous_phase_partial_paths`]: #method.previous_phase_partial_paths - pub fn process_next_phase( - &mut self, - graph: &StackGraph, - partials: &mut PartialPaths, - db: &mut Db, - extend_while: E, - ) where + pub fn process_next_phase(&mut self, candidates: &mut C, extend_while: E) + where A: Appendable, - Db: ForwardCandidates + ToAppendable, + Db: ToAppendable, + C: ForwardCandidates, E: Fn(&StackGraph, &mut PartialPaths, &PartialPath) -> bool, { copious_debugging!("==> Start phase {}", self.phase_number); @@ -872,6 +939,7 @@ impl ForwardPartialPathStitcher { ); let mut work_performed = 0; while let Some((partial_path, cycle_detector)) = self.queue.pop_front() { + let (graph, partials, _) = candidates.get_graph_and_partials(); copious_debugging!( "--> Candidate partial path {}", partial_path.display(graph, partials) @@ -885,7 +953,7 @@ impl ForwardPartialPathStitcher { ); continue; } - work_performed += self.extend(graph, partials, db, &partial_path, cycle_detector); + work_performed += self.extend(candidates, &partial_path, cycle_detector); if work_performed >= self.max_work_per_phase { break; } @@ -948,9 +1016,7 @@ impl ForwardPartialPathStitcher { while !stitcher.is_complete() { cancellation_flag.check("finding complete partial paths")?; stitcher.process_next_phase( - graph, - partials, - &mut GraphEdges(Some(file)), + &mut GraphEdgeCandidates::new(graph, partials, Some(file)), |g, _ps, p| !as_complete_as_necessary(g, p), ); for path in stitcher.previous_phase_partial_paths() { @@ -975,10 +1041,8 @@ impl ForwardPartialPathStitcher { /// [`process_next_phase`][] manually. /// /// [`process_next_phase`]: #method.process_next_phase - pub fn find_all_complete_partial_paths( - graph: &StackGraph, - partials: &mut PartialPaths, - db: &mut Db, + pub fn find_all_complete_partial_paths( + candidates: &mut C, starting_nodes: I, cancellation_flag: &dyn CancellationFlag, mut visit: F, @@ -986,23 +1050,30 @@ impl ForwardPartialPathStitcher { where I: IntoIterator>, A: Appendable, - Db: ForwardCandidates + ToAppendable, + Db: ToAppendable, + C: ForwardCandidates, F: FnMut(&StackGraph, &mut PartialPaths, &PartialPath), { - let initial_paths = starting_nodes - .into_iter() - .filter(|n| graph[*n].is_reference()) - .map(|n| { - let mut p = PartialPath::from_node(graph, partials, n); - p.eliminate_precondition_stack_variables(partials); - p - }) - .collect::>(); - let mut stitcher = - ForwardPartialPathStitcher::from_partial_paths(graph, partials, initial_paths); + let mut stitcher = { + let (graph, partials, _) = candidates.get_graph_and_partials(); + let initial_paths = starting_nodes + .into_iter() + .filter(|n| graph[*n].is_reference()) + .map(|n| { + let mut p = PartialPath::from_node(graph, partials, n); + p.eliminate_precondition_stack_variables(partials); + p + }) + .collect::>(); + ForwardPartialPathStitcher::from_partial_paths(graph, partials, initial_paths) + }; while !stitcher.is_complete() { cancellation_flag.check("finding complete partial paths")?; - stitcher.process_next_phase(graph, partials, db, |_, _, _| true); + for path in stitcher.previous_phase_partial_paths() { + candidates.load_forward_candidates(path, cancellation_flag)?; + } + stitcher.process_next_phase(candidates, |_, _, _| true); + let (graph, partials, _) = candidates.get_graph_and_partials(); for path in stitcher.previous_phase_partial_paths() { if path.is_complete(graph) { visit(graph, partials, path); diff --git a/stack-graphs/src/storage.rs b/stack-graphs/src/storage.rs index 808697a4a..c60c65617 100644 --- a/stack-graphs/src/storage.rs +++ b/stack-graphs/src/storage.rs @@ -28,9 +28,10 @@ use crate::partial::PartialSymbolStack; use crate::serde; use crate::serde::FileFilter; use crate::stitching::Database; -use crate::stitching::ForwardPartialPathStitcher; +use crate::stitching::ForwardCandidates; use crate::CancellationError; use crate::CancellationFlag; +use crate::NoCancellation; const VERSION: usize = 5; @@ -684,51 +685,6 @@ impl SQLiteReader { pub fn get(&mut self) -> (&StackGraph, &mut PartialPaths, &mut Database) { (&self.graph, &mut self.partials, &mut self.db) } - - /// Find all paths using the given path stitcher. Data is lazily loaded if necessary. - pub fn find_all_complete_partial_paths( - &mut self, - starting_nodes: I, - cancellation_flag: &dyn CancellationFlag, - mut visit: F, - ) -> Result<()> - where - I: IntoIterator>, - F: FnMut(&StackGraph, &mut PartialPaths, &PartialPath), - { - let initial_paths = starting_nodes - .into_iter() - .map(|n| { - let mut p = PartialPath::from_node(&self.graph, &mut self.partials, n); - p.eliminate_precondition_stack_variables(&mut self.partials); - p - }) - .collect::>(); - let mut stitcher = ForwardPartialPathStitcher::from_partial_paths( - &self.graph, - &mut self.partials, - initial_paths, - ); - stitcher.set_max_work_per_phase(128); - while !stitcher.is_complete() { - cancellation_flag.check("find_all_complete_partial_paths")?; - for path in stitcher.previous_phase_partial_paths() { - self.load_partial_path_extensions(path, cancellation_flag)?; - } - stitcher.process_next_phase( - &self.graph, - &mut self.partials, - &mut self.db, - |_, _, _| true, - ); - for path in stitcher.previous_phase_partial_paths() { - if path.is_complete(&self.graph) { - visit(&self.graph, &mut self.partials, path); - } - } - } - Ok(()) - } } impl PartialSymbolStack { @@ -764,6 +720,32 @@ impl PartialSymbolStack { } } +impl ForwardCandidates, PartialPath, Database> for SQLiteReader { + fn load_forward_candidates( + &mut self, + path: &PartialPath, + _cancellation_flag: &dyn CancellationFlag, + ) -> std::result::Result<(), CancellationError> { + // TODO what about other errors? + match self.load_partial_path_extensions(path, &NoCancellation) { + Err(StorageError::Cancelled(msg)) => Err(CancellationError(msg)), + _ => Ok(()), + } + } + + fn get_forward_candidates(&mut self, path: &PartialPath, result: &mut R) + where + R: std::iter::Extend>, + { + self.db + .find_candidate_partial_paths(&self.graph, &mut self.partials, path, result); + } + + fn get_graph_and_partials(&mut self) -> (&StackGraph, &mut PartialPaths, &Database) { + (&self.graph, &mut self.partials, &self.db) + } +} + /// Check if the database has the version supported by this library version. fn check_version(conn: &Connection) -> Result<()> { let version = conn.query_row("SELECT version FROM metadata", [], |r| r.get::<_, usize>(0))?; diff --git a/stack-graphs/tests/it/can_jump_to_definition.rs b/stack-graphs/tests/it/can_jump_to_definition.rs index 7fde42161..965207f4c 100644 --- a/stack-graphs/tests/it/can_jump_to_definition.rs +++ b/stack-graphs/tests/it/can_jump_to_definition.rs @@ -10,7 +10,8 @@ use std::collections::BTreeSet; use pretty_assertions::assert_eq; use stack_graphs::graph::StackGraph; use stack_graphs::partial::PartialPaths; -use stack_graphs::stitching::{ForwardPartialPathStitcher, GraphEdges}; +use stack_graphs::stitching::ForwardPartialPathStitcher; +use stack_graphs::stitching::GraphEdgeCandidates; use stack_graphs::NoCancellation; use crate::test_graphs; @@ -22,9 +23,7 @@ fn check_jump_to_definition(graph: &StackGraph, expected_paths: &[&str]) { .iter_nodes() .filter(|handle| graph[*handle].is_reference()); ForwardPartialPathStitcher::find_all_complete_partial_paths( - graph, - &mut paths, - &mut GraphEdges(None), + &mut GraphEdgeCandidates::new(graph, &mut paths, None), references, &NoCancellation, |graph, paths, path| { diff --git a/stack-graphs/tests/it/can_jump_to_definition_with_forward_partial_path_stitching.rs b/stack-graphs/tests/it/can_jump_to_definition_with_forward_partial_path_stitching.rs index 85984e814..d45e96afc 100644 --- a/stack-graphs/tests/it/can_jump_to_definition_with_forward_partial_path_stitching.rs +++ b/stack-graphs/tests/it/can_jump_to_definition_with_forward_partial_path_stitching.rs @@ -11,6 +11,7 @@ use pretty_assertions::assert_eq; use stack_graphs::graph::StackGraph; use stack_graphs::partial::PartialPaths; use stack_graphs::stitching::Database; +use stack_graphs::stitching::DatabaseCandidates; use stack_graphs::stitching::ForwardPartialPathStitcher; use stack_graphs::NoCancellation; @@ -39,9 +40,7 @@ fn check_jump_to_definition(graph: &StackGraph, expected_partial_paths: &[&str]) .filter(|handle| graph[*handle].is_reference()); let mut complete_partial_paths = Vec::new(); ForwardPartialPathStitcher::find_all_complete_partial_paths( - graph, - &mut partials, - &mut db, + &mut DatabaseCandidates::new(graph, &mut partials, &mut db), references, &NoCancellation, |_, _, p| { diff --git a/stack-graphs/tests/it/cycles.rs b/stack-graphs/tests/it/cycles.rs index e9584dd2f..12c8b5672 100644 --- a/stack-graphs/tests/it/cycles.rs +++ b/stack-graphs/tests/it/cycles.rs @@ -171,7 +171,7 @@ fn finding_simple_identity_cycle_is_detected() { { let mut edges = Appendables::new(); let mut cd = AppendingCycleDetector::new(); - let db = &GraphEdges(None); + let db = &GraphEdges; for edge in &[ edge(r, foo_ref, 0), @@ -261,7 +261,7 @@ fn finding_composite_identity_cycle_is_detected() { { let mut edges = Appendables::new(); let mut cd = AppendingCycleDetector::new(); - let db = &GraphEdges(None); + let db = &GraphEdges; for edge in &[ edge(r, s, 0), edge(r, s, 0), diff --git a/tree-sitter-stack-graphs/src/cli/query.rs b/tree-sitter-stack-graphs/src/cli/query.rs index 583aee85b..08ede0b93 100644 --- a/tree-sitter-stack-graphs/src/cli/query.rs +++ b/tree-sitter-stack-graphs/src/cli/query.rs @@ -9,6 +9,7 @@ use clap::Args; use clap::Parser; use clap::Subcommand; use clap::ValueHint; +use stack_graphs::stitching::ForwardPartialPathStitcher; use stack_graphs::storage::FileStatus; use stack_graphs::storage::SQLiteReader; use std::path::Path; @@ -184,7 +185,8 @@ impl<'a> Querier<'a> { }; let mut reference_paths = Vec::new(); - if let Err(err) = self.db.find_all_complete_partial_paths( + if let Err(err) = ForwardPartialPathStitcher::find_all_complete_partial_paths( + self.db, std::iter::once(node), &cancellation_flag, |_g, _ps, p| { @@ -256,6 +258,12 @@ pub enum QueryError { StorageError(#[from] stack_graphs::storage::StorageError), } +impl From for QueryError { + fn from(value: stack_graphs::CancellationError) -> Self { + Self::Cancelled(value.0) + } +} + impl From for QueryError { fn from(value: crate::CancellationError) -> Self { Self::Cancelled(value.0) diff --git a/tree-sitter-stack-graphs/src/cli/test.rs b/tree-sitter-stack-graphs/src/cli/test.rs index 9566687f1..4bcb47171 100644 --- a/tree-sitter-stack-graphs/src/cli/test.rs +++ b/tree-sitter-stack-graphs/src/cli/test.rs @@ -16,6 +16,7 @@ use stack_graphs::graph::StackGraph; use stack_graphs::partial::PartialPaths; use stack_graphs::serde::Filter; use stack_graphs::stitching::Database; +use stack_graphs::stitching::DatabaseCandidates; use stack_graphs::stitching::ForwardPartialPathStitcher; use std::path::Path; use std::path::PathBuf; @@ -481,9 +482,7 @@ impl TestArgs { .collect::>(); let mut paths = Vec::new(); ForwardPartialPathStitcher::find_all_complete_partial_paths( - graph, - partials, - db, + &mut DatabaseCandidates::new(graph, partials, db), references.clone(), &cancellation_flag, |_, _, p| { diff --git a/tree-sitter-stack-graphs/src/cli/visualize.rs b/tree-sitter-stack-graphs/src/cli/visualize.rs index fd947c1d9..e0665c353 100644 --- a/tree-sitter-stack-graphs/src/cli/visualize.rs +++ b/tree-sitter-stack-graphs/src/cli/visualize.rs @@ -9,6 +9,7 @@ use clap::Args; use clap::ValueHint; use stack_graphs::serde::NoFilter; use stack_graphs::stitching::Database; +use stack_graphs::stitching::ForwardPartialPathStitcher; use stack_graphs::storage::SQLiteReader; use stack_graphs::NoCancellation; use std::path::Path; @@ -53,9 +54,14 @@ impl VisualizeArgs { .filter(|n| graph[*n].is_reference()) .collect::>(); let mut complete_paths_db = Database::new(); - db.find_all_complete_partial_paths(starting_nodes, cancellation_flag, |g, ps, p| { - complete_paths_db.add_partial_path(g, ps, p.clone()); - })?; + ForwardPartialPathStitcher::find_all_complete_partial_paths( + &mut db, + starting_nodes, + cancellation_flag, + |g, ps, p| { + complete_paths_db.add_partial_path(g, ps, p.clone()); + }, + )?; let (graph, partials, _) = db.get(); let html = graph.to_html_string("stack-graph", partials, &mut complete_paths_db, &NoFilter)?; From dc43a646908a28061781a1c3cb9d2a2a5ed0815e Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 30 Jun 2023 15:26:32 +0200 Subject: [PATCH 141/500] Thread `ForwardCandidates` errors through `ForwardPartialPathStitcher` --- stack-graphs/src/stitching.rs | 25 ++++++++++++++----------- stack-graphs/src/storage.rs | 13 ++++--------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index ece844b5a..0e98914a3 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -174,7 +174,7 @@ where /// A trait to support finding candidates for partial path extension. Requires an accompanying /// [`ToAppendable`] implementation to convert the candidate handles into [`Appendable`]s. -pub trait ForwardCandidates +pub trait ForwardCandidates where A: Appendable, Db: ToAppendable, @@ -184,7 +184,7 @@ where &mut self, _path: &PartialPath, _cancellation_flag: &dyn CancellationFlag, - ) -> Result<(), CancellationError> { + ) -> Result<(), Err> { Ok(()) } @@ -224,7 +224,7 @@ impl<'a> GraphEdgeCandidates<'a> { } } -impl ForwardCandidates for GraphEdgeCandidates<'_> { +impl ForwardCandidates for GraphEdgeCandidates<'_> { fn get_forward_candidates(&mut self, path: &PartialPath, result: &mut R) where R: std::iter::Extend, @@ -581,7 +581,9 @@ impl<'a> DatabaseCandidates<'a> { } } -impl ForwardCandidates, PartialPath, Database> for DatabaseCandidates<'_> { +impl ForwardCandidates, PartialPath, Database, CancellationError> + for DatabaseCandidates<'_> +{ fn get_forward_candidates(&mut self, path: &PartialPath, result: &mut R) where R: std::iter::Extend>, @@ -824,7 +826,7 @@ impl ForwardPartialPathStitcher { /// Attempts to extend one partial path as part of the algorithm. When calling this function, /// you are responsible for ensuring that `db` already contains all of the possible appendables /// that we might want to extend `partial_path` with. - fn extend( + fn extend( &mut self, candidates: &mut C, partial_path: &PartialPath, @@ -833,7 +835,7 @@ impl ForwardPartialPathStitcher { where A: Appendable, Db: ToAppendable, - C: ForwardCandidates, + C: ForwardCandidates, { let (graph, partials, db) = candidates.get_graph_and_partials(); copious_debugging!(" Extend {}", partial_path.display(graph, partials)); @@ -923,11 +925,11 @@ impl ForwardPartialPathStitcher { /// or not. It is not called on the initial paths. /// /// [`previous_phase_partial_paths`]: #method.previous_phase_partial_paths - pub fn process_next_phase(&mut self, candidates: &mut C, extend_while: E) + pub fn process_next_phase(&mut self, candidates: &mut C, extend_while: E) where A: Appendable, Db: ToAppendable, - C: ForwardCandidates, + C: ForwardCandidates, E: Fn(&StackGraph, &mut PartialPaths, &PartialPath) -> bool, { copious_debugging!("==> Start phase {}", self.phase_number); @@ -1041,18 +1043,19 @@ impl ForwardPartialPathStitcher { /// [`process_next_phase`][] manually. /// /// [`process_next_phase`]: #method.process_next_phase - pub fn find_all_complete_partial_paths( + pub fn find_all_complete_partial_paths( candidates: &mut C, starting_nodes: I, cancellation_flag: &dyn CancellationFlag, mut visit: F, - ) -> Result<(), CancellationError> + ) -> Result<(), Err> where I: IntoIterator>, A: Appendable, Db: ToAppendable, - C: ForwardCandidates, + C: ForwardCandidates, F: FnMut(&StackGraph, &mut PartialPaths, &PartialPath), + Err: std::convert::From, { let mut stitcher = { let (graph, partials, _) = candidates.get_graph_and_partials(); diff --git a/stack-graphs/src/storage.rs b/stack-graphs/src/storage.rs index c60c65617..b61baf608 100644 --- a/stack-graphs/src/storage.rs +++ b/stack-graphs/src/storage.rs @@ -31,7 +31,6 @@ use crate::stitching::Database; use crate::stitching::ForwardCandidates; use crate::CancellationError; use crate::CancellationFlag; -use crate::NoCancellation; const VERSION: usize = 5; @@ -720,17 +719,13 @@ impl PartialSymbolStack { } } -impl ForwardCandidates, PartialPath, Database> for SQLiteReader { +impl ForwardCandidates, PartialPath, Database, StorageError> for SQLiteReader { fn load_forward_candidates( &mut self, path: &PartialPath, - _cancellation_flag: &dyn CancellationFlag, - ) -> std::result::Result<(), CancellationError> { - // TODO what about other errors? - match self.load_partial_path_extensions(path, &NoCancellation) { - Err(StorageError::Cancelled(msg)) => Err(CancellationError(msg)), - _ => Ok(()), - } + cancellation_flag: &dyn CancellationFlag, + ) -> std::result::Result<(), StorageError> { + self.load_partial_path_extensions(path, cancellation_flag) } fn get_forward_candidates(&mut self, path: &PartialPath, result: &mut R) From 233e8279643294ad4abefa4dbc1581a2a8785d09 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 30 Jun 2023 15:58:43 +0200 Subject: [PATCH 142/500] Improve comments --- stack-graphs/src/stitching.rs | 29 ++++++++++++++++------------- stack-graphs/src/storage.rs | 2 +- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index 0e98914a3..b332389c1 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -172,14 +172,16 @@ where //------------------------------------------------------------------------------------------------- // Candidates -/// A trait to support finding candidates for partial path extension. Requires an accompanying -/// [`ToAppendable`] implementation to convert the candidate handles into [`Appendable`]s. +/// A trait to support finding candidates for partial path extension. The candidates are represented +/// by handles `H`, which are mapped to appendables `A` using the database `Db`. Loading errors are +/// reported as values of the `Err` type. pub trait ForwardCandidates where A: Appendable, Db: ToAppendable, { - /// Load possible forward candidates for the given partial path. + /// Load possible forward candidates for the given partial path into this candidates instance. + /// Must be called before [`get_forward_candidates`] to allow lazy-loading implementations. fn load_forward_candidates( &mut self, _path: &PartialPath, @@ -189,13 +191,14 @@ where } /// Get forward candidates for extending the given partial path and add them to the provided - /// result instance. If the trait implementation loads data lazily, this only considers already - /// loaded data. + /// result instance. If this instance loads data lazily, this only considers previously loaded + /// data. fn get_forward_candidates(&mut self, path: &PartialPath, result: &mut R) where R: std::iter::Extend; - fn get_graph_and_partials(&mut self) -> (&StackGraph, &mut PartialPaths, &Db); + /// Get the graph, partial path arena, and database backing this candidates instance. + fn get_graph_partials_and_db(&mut self) -> (&StackGraph, &mut PartialPaths, &Db); } //------------------------------------------------------------------------------------------------- @@ -235,7 +238,7 @@ impl ForwardCandidates for GraphEdgeC })); } - fn get_graph_and_partials(&mut self) -> (&StackGraph, &mut PartialPaths, &GraphEdges) { + fn get_graph_partials_and_db(&mut self) -> (&StackGraph, &mut PartialPaths, &GraphEdges) { (self.graph, self.partials, &self.edges) } } @@ -592,7 +595,7 @@ impl ForwardCandidates, PartialPath, Database, CancellationE .find_candidate_partial_paths(self.graph, self.partials, path, result); } - fn get_graph_and_partials(&mut self) -> (&StackGraph, &mut PartialPaths, &Database) { + fn get_graph_partials_and_db(&mut self) -> (&StackGraph, &mut PartialPaths, &Database) { (self.graph, self.partials, self.database) } } @@ -837,7 +840,7 @@ impl ForwardPartialPathStitcher { Db: ToAppendable, C: ForwardCandidates, { - let (graph, partials, db) = candidates.get_graph_and_partials(); + let (graph, partials, db) = candidates.get_graph_partials_and_db(); copious_debugging!(" Extend {}", partial_path.display(graph, partials)); // check is path is cyclic, in which case we do not extend it @@ -873,7 +876,7 @@ impl ForwardPartialPathStitcher { self.next_iteration.0.reserve(extension_count); self.next_iteration.1.reserve(extension_count); for extension in &self.candidates { - let (graph, partials, db) = candidates.get_graph_and_partials(); + let (graph, partials, db) = candidates.get_graph_partials_and_db(); let extension_path = db.get_appendable(extension); copious_debugging!(" with {}", extension_path.display(graph, partials)); @@ -941,7 +944,7 @@ impl ForwardPartialPathStitcher { ); let mut work_performed = 0; while let Some((partial_path, cycle_detector)) = self.queue.pop_front() { - let (graph, partials, _) = candidates.get_graph_and_partials(); + let (graph, partials, _) = candidates.get_graph_partials_and_db(); copious_debugging!( "--> Candidate partial path {}", partial_path.display(graph, partials) @@ -1058,7 +1061,7 @@ impl ForwardPartialPathStitcher { Err: std::convert::From, { let mut stitcher = { - let (graph, partials, _) = candidates.get_graph_and_partials(); + let (graph, partials, _) = candidates.get_graph_partials_and_db(); let initial_paths = starting_nodes .into_iter() .filter(|n| graph[*n].is_reference()) @@ -1076,7 +1079,7 @@ impl ForwardPartialPathStitcher { candidates.load_forward_candidates(path, cancellation_flag)?; } stitcher.process_next_phase(candidates, |_, _, _| true); - let (graph, partials, _) = candidates.get_graph_and_partials(); + let (graph, partials, _) = candidates.get_graph_partials_and_db(); for path in stitcher.previous_phase_partial_paths() { if path.is_complete(graph) { visit(graph, partials, path); diff --git a/stack-graphs/src/storage.rs b/stack-graphs/src/storage.rs index b61baf608..3cd89d797 100644 --- a/stack-graphs/src/storage.rs +++ b/stack-graphs/src/storage.rs @@ -736,7 +736,7 @@ impl ForwardCandidates, PartialPath, Database, StorageError> .find_candidate_partial_paths(&self.graph, &mut self.partials, path, result); } - fn get_graph_and_partials(&mut self) -> (&StackGraph, &mut PartialPaths, &Database) { + fn get_graph_partials_and_db(&mut self) -> (&StackGraph, &mut PartialPaths, &Database) { (&self.graph, &mut self.partials, &self.db) } } From 936abecc62bc19c0a1a73890d26958ecd6abacf2 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 4 Oct 2023 19:53:52 +0200 Subject: [PATCH 143/500] Add tests --- .../commonjs_imports_and_exports.js | 7 +- .../es6_imports_and_exports.js | 102 +++++++++++++++--- .../test/old/packages/acme_foo.js | 21 ++++ .../test/old/packages/bar.js | 20 ++++ .../test/old/packages/foo.js | 13 +++ 5 files changed, 144 insertions(+), 19 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/packages/acme_foo.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/packages/bar.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/packages/foo.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/commonjs_imports_and_exports.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/commonjs_imports_and_exports.js index 14c1afb3e..05db804f8 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/commonjs_imports_and_exports.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/commonjs_imports_and_exports.js @@ -1,16 +1,17 @@ /*--- path: a.js ---*/ exports.foo = 1; + module.exports = { - bar: 2 + /**/ bar: 2 }; /*--- path: b.js ---*/ -const mod1 = require("a.js"); +const mod1 = require("./a.js"); mod1.foo; // ^ defined: 3 mod1.bar; -// ^ defined: 5 +// ^ defined: 6 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/es6_imports_and_exports.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/es6_imports_and_exports.js index 0508a5ee6..02129907c 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/es6_imports_and_exports.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/es6_imports_and_exports.js @@ -29,7 +29,7 @@ export const { m = 1 } = { "m": 2 }; /*--- path: b_basic_0.js ---*/ -import { a, b as b2 } from "a_basic.js"; +import { a, b as b2 } from "./a_basic.js"; a; // ^ defined: 10, 32 @@ -39,7 +39,7 @@ import { a, b as b2 } from "a_basic.js"; /*--- path: b_basic_1.js ---*/ -import * as mod from "a_basic.js"; +import * as mod from "./a_basic.js"; mod; // ^ defined: 42 @@ -72,7 +72,7 @@ import * as mod from "a_basic.js"; // ^ defined: 24, 24 mod.j; -// ^ defined: 25 +// ^ defined: 25, 26 mod.k; // ^ defined: 26, 26 @@ -119,10 +119,10 @@ export { o as default }; /*--- path: b_default.js ---*/ -import p from "a_default_0.js" -import q from "a_default_1.js" -import r from "a_default_2.js" -import s from "a_default_3.js" +import p from "./a_default_0.js" +import q from "./a_default_1.js" +import r from "./a_default_2.js" +import s from "./a_default_3.js" p; // ^ defined: 95, 96, 122 @@ -145,27 +145,27 @@ import s from "a_default_3.js" /*--- path: b_aggregating_0.js ---*/ -export * from "a_basic.js"; +export * from "./a_basic.js"; /*--- path: b_aggregating_1.js ---*/ -export * as t from "a_basic.js"; +export * as t from "./a_basic.js"; /*--- path: b_aggregating_2.js ---*/ -export { c, D as D1 } from "a_basic.js"; +export { c, D as D1 } from "./a_basic.js"; /*--- path: b_aggregating_3.js ---*/ -export { e as default } from "a_basic.js"; +export { e as default } from "./a_basic.js"; /*--- path: c_aggregating.js ---*/ -import { a } from "b_aggregating_0.js"; +import { a } from "./b_aggregating_0.js"; a; // ^ defined: 10, 168 @@ -173,13 +173,13 @@ import { a } from "b_aggregating_0.js"; b; // ^ defined: -import { t } from "b_aggregating_1.js"; +import { t } from "./b_aggregating_1.js"; t.a; // ^ defined: 153, 176 // ^ defined: 10 -import { c, D1 } from "b_aggregating_2.js"; +import { c, D1 } from "./b_aggregating_2.js"; c; // ^ defined: 12, 158, 182 @@ -187,7 +187,77 @@ import { c, D1 } from "b_aggregating_2.js"; D1; // ^ defined: 13, 158, 182 -import e2 from "b_aggregating_3.js"; +import e2 from "./b_aggregating_3.js"; e2; -// ^ defined: 16, 17, 190 +// ^ defined: 16, 17, 163, 190 + +//////////////////////////////////////////////////////////////////////////////// +// +// Imports from super and subdirectories +// +//////////////////////////////////////////////////////////////////////////////// + +/*--- path: dirs/foo.js ---*/ + +export let x = 42; + +/*--- path: dirs/bar/baz.js ---*/ + +export let x = 42; + +/*--- path: dirs/test_0.js ---*/ + +import { x } from "./foo" +// ^ defined: 211, 203 + +/*--- path: dirs/test_1.js ---*/ + +import { x } from "./bar/baz" +// ^ defined: 216, 207 + +/*--- path: dirs/bar/test_2.js ---*/ + +import { x } from "../foo" +// ^ defined: 221, 203 + +//////////////////////////////////////////////////////////////////////////////// +// +// Import using `import()` function +// +//////////////////////////////////////////////////////////////////////////////// + +/*--- path: b_function_1.js ---*/ + +const mod = await import("./a_basic.js"); + + mod; +// ^ defined: 232 + + mod.a; +// ^ defined: 10 + +//////////////////////////////////////////////////////////////////////////////// +// +// Import directory with `index.js` +// +//////////////////////////////////////////////////////////////////////////////// + +/*--- path: dir_imports/foo/index.js ---*/ + +export let x = 42; + +/*--- path: dir_imports/test_0.js ---*/ + +import { x } from "./foo/" +// ^ defined: 252, 248 + +/*--- path: dir_imports/foo/test_1.js ---*/ + +import { x } from "./" +// ^ defined: 257, 248 + +/*--- path: dir_imports/bar/test_2.js ---*/ + +import { x } from "../foo/" +// ^ defined: 262, 248 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/packages/acme_foo.js b/languages/tree-sitter-stack-graphs-javascript/test/old/packages/acme_foo.js new file mode 100644 index 000000000..4333dd0e0 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/packages/acme_foo.js @@ -0,0 +1,21 @@ +/* --- path: package.json --- */ + +{ + "name": "@acme/foo", + "version": "1.0", + "main": "./api" +} + +/* --- path: core.js --- */ + +export let x; + + x; +//^ defined: 11 + +/* --- path: api.js --- */ + +export let x; + + x; +//^ defined: 18 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/packages/bar.js b/languages/tree-sitter-stack-graphs-javascript/test/old/packages/bar.js new file mode 100644 index 000000000..5c6d13b91 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/packages/bar.js @@ -0,0 +1,20 @@ +/* --- path: package.json --- */ + +{ + "name_missing": "/* name omitted to ensure that doesn't error */", + "dependencies": { + "foo": "1", + "@acme/foo": "1" + } +} + +/* --- path: app.js --- */ + +import { x } from "@acme/foo" +// ^ defined: 13 + +import { x } from "foo" +// ^ defined: 16 + +import { x } from "@acme/foo/core" +// ^ defined: 19 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/packages/foo.js b/languages/tree-sitter-stack-graphs-javascript/test/old/packages/foo.js new file mode 100644 index 000000000..db65c04cb --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/packages/foo.js @@ -0,0 +1,13 @@ +/* --- path: package.json --- */ + +{ + "name": "foo", + "version": "1.0" +} + +/* --- path: src/index.js --- */ + +export let x; + + x; +//^ defined: 10 From fe94270aa56b7d0245219a179b3840d4a329b0b1 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 4 Oct 2023 20:06:57 +0200 Subject: [PATCH 144/500] Add package.json analyzer --- .../Cargo.toml | 2 + .../rust/lib.rs | 8 +- .../rust/npm_package.rs | 119 +++++++++++ .../rust/util.rs | 184 ++++++++++++++++++ 4 files changed, 312 insertions(+), 1 deletion(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs create mode 100644 languages/tree-sitter-stack-graphs-javascript/rust/util.rs diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml index 4305bab57..42960b6fb 100644 --- a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -28,6 +28,8 @@ cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"] [dependencies] anyhow = { version = "1.0", optional = true } clap = { version = "4", optional = true } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" stack-graphs = { version = "0.12", path = "../../stack-graphs" } tree-sitter = "=0.20.9" tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs" } diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/lib.rs b/languages/tree-sitter-stack-graphs-javascript/rust/lib.rs index d9b6a0886..508ba58b9 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/lib.rs @@ -10,6 +10,11 @@ use tree_sitter_stack_graphs::loader::LanguageConfiguration; use tree_sitter_stack_graphs::loader::LoadError; use tree_sitter_stack_graphs::CancellationFlag; +use crate::npm_package::NpmPackageAnalyzer; + +mod npm_package; +mod util; + /// The stack graphs tsg source for this language. pub const STACK_GRAPHS_TSG_PATH: &str = "src/stack-graphs.tsg"; /// The stack graphs tsg source for this language. @@ -24,6 +29,7 @@ pub const STACK_GRAPHS_BUILTINS_SOURCE: &str = include_str!("../src/builtins.js" /// The name of the file path global variable. pub const FILE_PATH_VAR: &str = "FILE_PATH"; +pub const PROJECT_NAME_VAR: &str = "PROJECT_NAME"; pub fn language_configuration(cancellation_flag: &dyn CancellationFlag) -> LanguageConfiguration { try_language_configuration(cancellation_flag).unwrap_or_else(|err| panic!("{}", err)) @@ -44,7 +50,7 @@ pub fn try_language_configuration( STACK_GRAPHS_BUILTINS_SOURCE, )), Some(STACK_GRAPHS_BUILTINS_CONFIG), - FileAnalyzers::new(), + FileAnalyzers::new().add("package.json".to_string(), NpmPackageAnalyzer {}), cancellation_flag, ) } diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs new file mode 100644 index 000000000..8f8c5f7a6 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs @@ -0,0 +1,119 @@ +// -*- coding: utf-8 -*- +// ------------------------------------------------------------------------------------------------ +// Copyright © 2022, stack-graphs authors. +// Licensed under either of Apache License, Version 2.0, or MIT license, at your option. +// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. +// ------------------------------------------------------------------------------------------------ + +use serde::Deserialize; +use std::collections::HashMap; +use std::path::Path; +use std::path::PathBuf; + +use stack_graphs::arena::Handle; +use stack_graphs::graph::File; +use stack_graphs::graph::StackGraph; +use tree_sitter_stack_graphs::BuildError; +use tree_sitter_stack_graphs::FileAnalyzer; + +use crate::util::*; + +pub struct NpmPackageAnalyzer {} + +impl FileAnalyzer for NpmPackageAnalyzer { + fn build_stack_graph_into<'a>( + &self, + graph: &mut StackGraph, + file: Handle, + _path: &Path, + source: &str, + _all_paths: &mut dyn Iterator, + globals: &HashMap, + _cancellation_flag: &dyn tree_sitter_stack_graphs::CancellationFlag, + ) -> Result<(), tree_sitter_stack_graphs::BuildError> { + // read globals + let pkg_internal_name = globals + .get(crate::PROJECT_NAME_VAR) + .map(String::as_str) + .unwrap_or_default(); + + // parse source + let npm_pkg: NpmPackage = + serde_json::from_str(source).map_err(|_| BuildError::ParseError)?; + + let root = StackGraph::root_node(); + + // reach package internals from root + // + // [root] -> [pop "GUARD:PKG_INTERNAL"] -> [pop pkg_internal_name] + // + let pkg_internal_guard_pop = add_pop(graph, file, root, PKG_INTERNAL_GUARD, ""); + let pkg_internal_name_pop = + add_pop(graph, file, pkg_internal_guard_pop, pkg_internal_name, ""); + + // reach package internals via root + // + // [push pkg_internal_name] -> [push "GUARD:PKG_INTERNAL"] -> [root] + // + let pkg_internal_guard_push = add_push(graph, file, root, PKG_INTERNAL_GUARD, ""); + let pkg_internal_name_push = + add_push(graph, file, pkg_internal_guard_push, pkg_internal_name, ""); + + // reach exports via package name + // + // [root] -> [pop "GUARD:PKG"] -> [pop PKG_NAME]* -> [push PKG_INTERNAL_NAME] -> [push "GUARD:PKG_INTERNAL"] -> [root] + // + if !npm_pkg.name.is_empty() { + // reach package internals via package name + // + // [root] -> [pop "GUARD:PKG"] -> [pop pkg_name]* -> [push pkg_internal_name] + // + let pkg_guard_pop = add_pop(graph, file, root, PKG_GUARD, ""); + let pkg_name_pop = + add_module_pops(graph, file, Path::new(&npm_pkg.name), pkg_guard_pop, ""); + add_edge(graph, pkg_name_pop, pkg_internal_name_push, 0); + + // reach main exports directly via package name (with precedence) + // + // [pop pkg_name] -1-> [pop "GUARD:EXPORTS"] -> [push "GUARD:EXPORTS"] -> [push main]* -> [push pkg_internal_name] + // + let exports_guard_pop = add_pop(graph, file, pkg_name_pop, EXPORTS_GUARD, ""); + replace_edge(graph, pkg_name_pop, exports_guard_pop, 1); + let main = NormalizedRelativePath::from_str(&npm_pkg.main) + .map(|p| p.into_path_buf()) + .unwrap_or(PathBuf::from("index")) + .with_extension("") + .with_extension(""); + let main_push = add_module_pushes(graph, file, &main, pkg_internal_name_push, ""); + let exports_guard_push = add_push(graph, file, main_push, EXPORTS_GUARD, ""); + add_edge(graph, exports_guard_pop, exports_guard_push, 0); + } + + // reach dependencies via package internal name + // + // [pop pkg_internal_name] -> [pop "GUARD:PKG"] -> [pop dep_name]* -> [push dep_name]* -> [push "GUARD:PKG"] -> [root] + // + let dep_guard_pop = add_pop(graph, file, pkg_internal_name_pop, PKG_GUARD, ""); + let dep_guard_push = add_push(graph, file, root, PKG_GUARD, ""); + for (_, (dep_name, _)) in npm_pkg.dependencies.iter().enumerate() { + if dep_name.is_empty() { + continue; + } + let dep_name_pop = add_module_pops(graph, file, Path::new(dep_name), dep_guard_pop, ""); + let dep_name_push = + add_module_pushes(graph, file, Path::new(dep_name), dep_guard_push, ""); + add_edge(graph, dep_name_pop, dep_name_push, 0); + } + + Ok(()) + } +} + +#[derive(Default, Debug, Clone, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct NpmPackage { + pub name: String, + pub main: String, + #[serde(default)] + pub dependencies: HashMap, +} diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/util.rs b/languages/tree-sitter-stack-graphs-javascript/rust/util.rs new file mode 100644 index 000000000..1bed520cd --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/rust/util.rs @@ -0,0 +1,184 @@ +// -*- coding: utf-8 -*- +// ------------------------------------------------------------------------------------------------ +// Copyright © 2022, stack-graphs authors. +// Licensed under either of Apache License, Version 2.0, or MIT license, at your option. +// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. +// ------------------------------------------------------------------------------------------------ + +use stack_graphs::graph::Node; +use std::path::Component; +use std::path::Path; +use std::path::PathBuf; + +use stack_graphs::arena::Handle; +use stack_graphs::graph::File; +use stack_graphs::graph::StackGraph; + +pub const EXPORTS_GUARD: &str = "GUARD:EXPORTS"; +pub const PKG_GUARD: &str = "GUARD:PKG"; +pub const PKG_INTERNAL_GUARD: &str = "GUARD:PKG_INTERNAL"; + +pub fn add_debug_name(graph: &mut StackGraph, node: Handle, name: &str) { + let key = graph.add_string("name"); + let value = graph.add_string(name); + graph.node_debug_info_mut(node).add(key, value); +} + +pub fn add_pop( + graph: &mut StackGraph, + file: Handle, + from: Handle, + name: &str, + debug_name: &str, +) -> Handle { + let id = graph.new_node_id(file); + let sym = graph.add_symbol(name); + let node = graph.add_pop_symbol_node(id, sym, false).unwrap(); + graph.add_edge(from, node, 0); + add_debug_name(graph, node, debug_name); + node +} + +pub fn add_push( + graph: &mut StackGraph, + file: Handle, + to: Handle, + name: &str, + debug_name: &str, +) -> Handle { + let id = graph.new_node_id(file); + let sym = graph.add_symbol(name); + let node = graph.add_push_symbol_node(id, sym, false).unwrap(); + graph.add_edge(node, to, 0); + add_debug_name(graph, node, debug_name); + node +} + +pub fn add_edge(graph: &mut StackGraph, from: Handle, to: Handle, precedence: i32) { + if from == to { + return; + } + graph.add_edge(from, to, precedence); +} + +pub fn replace_edge(graph: &mut StackGraph, from: Handle, to: Handle, precedence: i32) { + if from == to { + return; + } + graph.remove_edge(from, to); + graph.add_edge(from, to, precedence); +} + +pub fn add_module_pops( + graph: &mut StackGraph, + file: Handle, + path: &Path, + mut from: Handle, + debug_prefix: &str, +) -> Handle { + for (i, c) in path.components().enumerate() { + match c { + Component::Normal(name) => { + from = add_pop( + graph, + file, + from, + &name.to_string_lossy(), + &format!("{}[{}]", debug_prefix, i), + ); + } + _ => { + eprintln!( + "add_module_pops: expecting normalized, non-escaping, relative paths, got {}", + path.display() + ) + } + } + } + from +} + +pub fn add_module_pushes( + graph: &mut StackGraph, + file: Handle, + path: &Path, + mut to: Handle, + debug_prefix: &str, +) -> Handle { + for (i, c) in path.components().enumerate() { + match c { + Component::Normal(name) => { + to = add_push( + graph, + file, + to, + &name.to_string_lossy(), + &format!("{}[{}]", debug_prefix, i), + ); + } + _ => { + eprintln!( + "add_module_pushes: expecting normalized, non-escaping, relative paths, got {}", + path.display() + ) + } + } + } + to +} + +pub struct NormalizedRelativePath(PathBuf); + +impl NormalizedRelativePath { + pub fn from_str(path: &str) -> Option { + Self::from_path(Path::new(path)) + } + + /// Creates a new normalized, relative path from a path. + pub fn from_path(path: &Path) -> Option { + let mut np = PathBuf::new(); + let mut normal_components = 0usize; + for c in path.components() { + match c { + Component::Prefix(_) => { + return None; + } + Component::RootDir => { + return None; + } + Component::CurDir => {} + Component::ParentDir => { + if normal_components > 0 { + // we can pop a normal component + normal_components -= 1; + np.pop(); + } else { + // add the `..` to the beginning of this relative path which has no normal components + np.push(c); + } + } + Component::Normal(_) => { + normal_components += 1; + np.push(c); + } + } + } + Some(Self(np)) + } + + pub fn into_path_buf(self) -> PathBuf { + self.0 + } +} + +impl AsRef for NormalizedRelativePath { + fn as_ref(&self) -> &Path { + &self.0 + } +} + +impl Into for NormalizedRelativePath { + fn into(self) -> PathBuf { + self.0 + } +} From 16655515360a04dc9c6fdcb3399714459d0c41ed Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 4 Oct 2023 21:19:00 +0200 Subject: [PATCH 145/500] Stack graph rule changes --- .../src/stack-graphs.tsg | 101 +++++++++++++----- 1 file changed, 72 insertions(+), 29 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 62e67b515..7e87df854 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -5,10 +5,12 @@ ;; Global Variables ;; ^^^^^^^^^^^^^^^^ -global FILE_PATH global ROOT_NODE global JUMP_TO_SCOPE_NODE +global FILE_PATH +global PROJECT_NAME = "" + ;; Attribute Shorthands ;; ^^^^^^^^^^^^^^^^^^^^ @@ -232,7 +234,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; - `GUARD:RETURN` - used for the AST nodes for values returned by a function ;; in the function body ;; - `GUARD:THIS` - used for the implicit `this` argument of a function inside -;; its body +;; - `GUARD:PKG_INTERNAL` - used for the package internal structure that should not +;; be accessible directly from the root ; ## Inherited @@ -244,10 +247,12 @@ inherit .builtins_null inherit .builtins_number inherit .builtins_string inherit .builtins_undefined -inherit .exports -inherit .return_or_yield inherit .class_value inherit .constructor +inherit .exports +inherit .pkg_pop +inherit .pkg_push +inherit .return_or_yield @@ -281,21 +286,50 @@ inherit .constructor node prog_module_pop node prog_module_scope node prog_exports_pop + node prog_pkg_pop_guard + node prog_pkg_push_guard + node prog_legacy_qname_guard node @prog.exports - - scan FILE_PATH { - "([^/]+)\.js$" { - attr (prog_module_pop) symbol_definition = $1, source_node = @prog - } + node @prog.pkg_pop + node @prog.pkg_push + + attr (prog_pkg_pop_guard) pop_symbol = "GUARD:PKG_INTERNAL" + attr (@prog.pkg_pop) pop_symbol = PROJECT_NAME + edge ROOT_NODE -> prog_pkg_pop_guard + edge prog_pkg_pop_guard -> @prog.pkg_pop + + attr (@prog.pkg_push) push_symbol = PROJECT_NAME + attr (prog_pkg_push_guard) push_symbol = "GUARD:PKG_INTERNAL" + edge @prog.pkg_push -> prog_pkg_push_guard + edge prog_pkg_push_guard -> ROOT_NODE + + node prog_module_pop_start + var module_pop_end = prog_module_pop_start + let module_name = (replace FILE_PATH "\.js$" "") + scan module_name { + "([^/]+)/" { + attr (module_pop_end) pop_symbol = $1 + node module_pop_end_next + edge module_pop_end -> module_pop_end_next + set module_pop_end = module_pop_end_next + } + "([^/]+)$" { + attr (module_pop_end) symbol_definition = $1, source_node = @prog + attr (module_pop_end) empty_source_span + } } - edge @prog.before_scope -> ROOT_NODE + edge @prog.before_scope -> @prog.pkg_push attr (prog_module_scope) pop_symbol = "GUARD:MODULE" - edge ROOT_NODE -> prog_module_pop + edge @prog.pkg_pop -> prog_module_pop_start edge prog_module_pop -> prog_module_scope edge prog_module_scope -> @prog.after_scope + attr (prog_legacy_qname_guard) push_symbol = "GUARD:LEGACY_QNAME" + edge @prog.before_scope -> prog_legacy_qname_guard + edge prog_legacy_qname_guard -> ROOT_NODE + attr (prog_module_pop) empty_source_span attr (prog_module_scope) empty_source_span attr (@prog.exports) empty_source_span @@ -307,6 +341,10 @@ inherit .constructor edge prog_module_pop -> prog_exports_pop edge prog_exports_pop -> @prog.exports + ; allow direct access from the package to the modules exports + ; this is used from package.json + edge @prog.pkg_pop -> prog_exports_pop + ;; builtin types node @prog.builtins_number node @prog.builtins_string @@ -895,7 +933,7 @@ inherit .constructor ; attr (@mod_name.push) symbol_reference = $1, source_node = @mod_name ; } ; } -; edge @mod_name.push -> ROOT_NODE +; edge @mod_name.push -> @import_stmt.pkg_push ; ; attr (@name) node_reference = @name ; attr (name_push_dot) push_symbol = "GUARD:MEMBER" @@ -3746,6 +3784,26 @@ inherit .constructor } +;; ## ES6-style Imports + +;; ES6 modules can also be imported using an import function. In general, +;; these look like `require(expr)`, but in practice the expression is a string +;; constant, which is the only case we handle. + +( + (call_expression + function:(_)@_import + arguments:(arguments (string)@source))@call_expr + (#eq? @_import "import") +) { + + node call_expr_pop_dot + + attr (call_expr_pop_dot) pop_symbol = "GUARD:MEMBER" + edge @call_expr.value -> call_expr_pop_dot + edge call_expr_pop_dot -> @source.exports +} + ;; ### CommonJS-style Exports ;; CommonJS introduced an export style for pre-ES6 JavaScript that permitted @@ -3803,25 +3861,10 @@ inherit .constructor ( (call_expression function:(_)@_require - arguments:(arguments (string)@mod_name))@call_expr + arguments:(arguments (string)@source))@call_expr (#eq? @_require "require") ) { - - node mod_name_module_guard - node mod_name_push - - scan (source-text @mod_name) { - "\"([^/\"]+)\.js\"$" { - attr (mod_name_push) push_symbol = $1 - } - } - - - attr (mod_name_module_guard) push_symbol = "GUARD:EXPORTS" - edge @call_expr.value -> mod_name_module_guard - edge mod_name_module_guard -> mod_name_push - edge mod_name_push -> ROOT_NODE - + edge @call_expr.value -> @source.exports } From 9419a525d565bcc17a01c00e0b2a9a6fc60e42a6 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 5 Oct 2023 03:16:46 +0200 Subject: [PATCH 146/500] Merge package test into single file --- .../test/old/packages/acme_foo.js | 21 ------- .../test/old/packages/bar.js | 20 ------ .../test/old/packages/foo.js | 13 ---- .../test/old/packages/package_dependencies.js | 61 +++++++++++++++++++ 4 files changed, 61 insertions(+), 54 deletions(-) delete mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/packages/acme_foo.js delete mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/packages/bar.js delete mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/packages/foo.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/packages/package_dependencies.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/packages/acme_foo.js b/languages/tree-sitter-stack-graphs-javascript/test/old/packages/acme_foo.js deleted file mode 100644 index 4333dd0e0..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/packages/acme_foo.js +++ /dev/null @@ -1,21 +0,0 @@ -/* --- path: package.json --- */ - -{ - "name": "@acme/foo", - "version": "1.0", - "main": "./api" -} - -/* --- path: core.js --- */ - -export let x; - - x; -//^ defined: 11 - -/* --- path: api.js --- */ - -export let x; - - x; -//^ defined: 18 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/packages/bar.js b/languages/tree-sitter-stack-graphs-javascript/test/old/packages/bar.js deleted file mode 100644 index 5c6d13b91..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/packages/bar.js +++ /dev/null @@ -1,20 +0,0 @@ -/* --- path: package.json --- */ - -{ - "name_missing": "/* name omitted to ensure that doesn't error */", - "dependencies": { - "foo": "1", - "@acme/foo": "1" - } -} - -/* --- path: app.js --- */ - -import { x } from "@acme/foo" -// ^ defined: 13 - -import { x } from "foo" -// ^ defined: 16 - -import { x } from "@acme/foo/core" -// ^ defined: 19 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/packages/foo.js b/languages/tree-sitter-stack-graphs-javascript/test/old/packages/foo.js deleted file mode 100644 index db65c04cb..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/packages/foo.js +++ /dev/null @@ -1,13 +0,0 @@ -/* --- path: package.json --- */ - -{ - "name": "foo", - "version": "1.0" -} - -/* --- path: src/index.js --- */ - -export let x; - - x; -//^ defined: 10 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/packages/package_dependencies.js b/languages/tree-sitter-stack-graphs-javascript/test/old/packages/package_dependencies.js new file mode 100644 index 000000000..7a67a873a --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/packages/package_dependencies.js @@ -0,0 +1,61 @@ +/* --- path: foo/package.json --- */ +/* --- global: FILE_PATH=package.json --- */ +/* --- global: PROJECT_NAME=foo --- */ + +{ + "name": "foo", + "version": "1.0" +} + +/* --- path: foo/src/index.js --- */ +/* --- global: FILE_PATH=src/index.js --- */ +/* --- global: PROJECT_NAME=foo --- */ + +export let x; + +/* --- path: acme_foo/package.json --- */ +/* --- global: FILE_PATH=package.json --- */ +/* --- global: PROJECT_NAME=acme_foo --- */ + +{ + "name": "@acme/foo", + "version": "1.0", + "main": "./api" +} + +/* --- path: acme_foo/core.js --- */ +/* --- global: FILE_PATH=core.js --- */ +/* --- global: PROJECT_NAME=acme_foo --- */ + +export let x; + +/* --- path: acme_foo/api.js --- */ +/* --- global: FILE_PATH=api.js --- */ +/* --- global: PROJECT_NAME=acme_foo --- */ + +export let x; + +/* --- path: bar/package.json --- */ +/* --- global: FILE_PATH=package.json --- */ +/* --- global: PROJECT_NAME=bar --- */ + +{ + "name": "bar", + "dependencies": { + "foo": "1", + "@acme/foo": "1" + } +} + +/* --- path: bar/app.js --- */ +/* --- global: FILE_PATH=app.js --- */ +/* --- global: PROJECT_NAME=bar --- */ + +import { x } from "@acme/foo" +// ^ defined: 36 + +import { x } from "foo" +// ^ defined: 14 + +import { x } from "@acme/foo/core" +// ^ defined: 30 From f470da020aa4f597db245e76ef4160ef7de48ad9 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 5 Oct 2023 03:39:55 +0200 Subject: [PATCH 147/500] Make all package.json fields optional --- .../rust/npm_package.rs | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs index 8f8c5f7a6..da9412a29 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs @@ -77,16 +77,18 @@ impl FileAnalyzer for NpmPackageAnalyzer { // // [pop pkg_name] -1-> [pop "GUARD:EXPORTS"] -> [push "GUARD:EXPORTS"] -> [push main]* -> [push pkg_internal_name] // - let exports_guard_pop = add_pop(graph, file, pkg_name_pop, EXPORTS_GUARD, ""); - replace_edge(graph, pkg_name_pop, exports_guard_pop, 1); - let main = NormalizedRelativePath::from_str(&npm_pkg.main) - .map(|p| p.into_path_buf()) - .unwrap_or(PathBuf::from("index")) - .with_extension("") - .with_extension(""); - let main_push = add_module_pushes(graph, file, &main, pkg_internal_name_push, ""); - let exports_guard_push = add_push(graph, file, main_push, EXPORTS_GUARD, ""); - add_edge(graph, exports_guard_pop, exports_guard_push, 0); + if !npm_pkg.main.is_empty() { + let exports_guard_pop = add_pop(graph, file, pkg_name_pop, EXPORTS_GUARD, ""); + replace_edge(graph, pkg_name_pop, exports_guard_pop, 1); + let main = NormalizedRelativePath::from_str(&npm_pkg.main) + .map(|p| p.into_path_buf()) + .unwrap_or(PathBuf::from("index")) + .with_extension("") + .with_extension(""); + let main_push = add_module_pushes(graph, file, &main, pkg_internal_name_push, ""); + let exports_guard_push = add_push(graph, file, main_push, EXPORTS_GUARD, ""); + add_edge(graph, exports_guard_pop, exports_guard_push, 0); + } } // reach dependencies via package internal name @@ -112,7 +114,9 @@ impl FileAnalyzer for NpmPackageAnalyzer { #[derive(Default, Debug, Clone, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct NpmPackage { + #[serde(default)] pub name: String, + #[serde(default)] pub main: String, #[serde(default)] pub dependencies: HashMap, From 2b8618c84d9c7bf4e6f0a91dffdc4677a6901949 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 5 Oct 2023 04:44:02 +0200 Subject: [PATCH 148/500] Port more stack graph changes --- .../rust/npm_package.rs | 43 +++-- .../src/stack-graphs.tsg | 155 ++++++++++++------ 2 files changed, 123 insertions(+), 75 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs index da9412a29..3a3c98b05 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs @@ -47,17 +47,17 @@ impl FileAnalyzer for NpmPackageAnalyzer { // // [root] -> [pop "GUARD:PKG_INTERNAL"] -> [pop pkg_internal_name] // - let pkg_internal_guard_pop = add_pop(graph, file, root, PKG_INTERNAL_GUARD, ""); + let pkg_internal_guard_pop = add_pop(graph, file, root, PKG_INTERNAL_GUARD, "pkg_internal_guard_pop"); let pkg_internal_name_pop = - add_pop(graph, file, pkg_internal_guard_pop, pkg_internal_name, ""); + add_pop(graph, file, pkg_internal_guard_pop, pkg_internal_name, "pkg_internal_name_pop"); // reach package internals via root // // [push pkg_internal_name] -> [push "GUARD:PKG_INTERNAL"] -> [root] // - let pkg_internal_guard_push = add_push(graph, file, root, PKG_INTERNAL_GUARD, ""); + let pkg_internal_guard_push = add_push(graph, file, root, PKG_INTERNAL_GUARD, "pkg_internal_guard_push"); let pkg_internal_name_push = - add_push(graph, file, pkg_internal_guard_push, pkg_internal_name, ""); + add_push(graph, file, pkg_internal_guard_push, pkg_internal_name, "pkg_internal_name_push"); // reach exports via package name // @@ -68,42 +68,39 @@ impl FileAnalyzer for NpmPackageAnalyzer { // // [root] -> [pop "GUARD:PKG"] -> [pop pkg_name]* -> [push pkg_internal_name] // - let pkg_guard_pop = add_pop(graph, file, root, PKG_GUARD, ""); + let pkg_guard_pop = add_pop(graph, file, root, PKG_GUARD, "pkg_guard_pop"); let pkg_name_pop = - add_module_pops(graph, file, Path::new(&npm_pkg.name), pkg_guard_pop, ""); + add_module_pops(graph, file, Path::new(&npm_pkg.name), pkg_guard_pop, "pkg_name_pop"); add_edge(graph, pkg_name_pop, pkg_internal_name_push, 0); // reach main exports directly via package name (with precedence) // // [pop pkg_name] -1-> [pop "GUARD:EXPORTS"] -> [push "GUARD:EXPORTS"] -> [push main]* -> [push pkg_internal_name] // - if !npm_pkg.main.is_empty() { - let exports_guard_pop = add_pop(graph, file, pkg_name_pop, EXPORTS_GUARD, ""); - replace_edge(graph, pkg_name_pop, exports_guard_pop, 1); - let main = NormalizedRelativePath::from_str(&npm_pkg.main) - .map(|p| p.into_path_buf()) - .unwrap_or(PathBuf::from("index")) - .with_extension("") - .with_extension(""); - let main_push = add_module_pushes(graph, file, &main, pkg_internal_name_push, ""); - let exports_guard_push = add_push(graph, file, main_push, EXPORTS_GUARD, ""); - add_edge(graph, exports_guard_pop, exports_guard_push, 0); - } + let exports_guard_pop = add_pop(graph, file, pkg_name_pop, EXPORTS_GUARD, "exports_guard_pop"); + replace_edge(graph, pkg_name_pop, exports_guard_pop, 1); + let main = NormalizedRelativePath::from_str(&npm_pkg.main) + .map(|p| p.into_path_buf()) + .unwrap_or(PathBuf::from("index")) + .with_extension(""); + let main_push = add_module_pushes(graph, file, &main, pkg_internal_name_push, "main_push"); + let exports_guard_push = add_push(graph, file, main_push, EXPORTS_GUARD, "exports_guard_push"); + add_edge(graph, exports_guard_pop, exports_guard_push, 0); } // reach dependencies via package internal name // // [pop pkg_internal_name] -> [pop "GUARD:PKG"] -> [pop dep_name]* -> [push dep_name]* -> [push "GUARD:PKG"] -> [root] // - let dep_guard_pop = add_pop(graph, file, pkg_internal_name_pop, PKG_GUARD, ""); - let dep_guard_push = add_push(graph, file, root, PKG_GUARD, ""); - for (_, (dep_name, _)) in npm_pkg.dependencies.iter().enumerate() { + let dep_guard_pop = add_pop(graph, file, pkg_internal_name_pop, PKG_GUARD, "dep_guard_pop"); + let dep_guard_push = add_push(graph, file, root, PKG_GUARD, "dep_guard_push"); + for (i, (dep_name, _)) in npm_pkg.dependencies.iter().enumerate() { if dep_name.is_empty() { continue; } - let dep_name_pop = add_module_pops(graph, file, Path::new(dep_name), dep_guard_pop, ""); + let dep_name_pop = add_module_pops(graph, file, Path::new(dep_name), dep_guard_pop, &format!("dep_name_pop[{}]", i)); let dep_name_push = - add_module_pushes(graph, file, Path::new(dep_name), dep_guard_push, ""); + add_module_pushes(graph, file, Path::new(dep_name), dep_guard_push, &format!("dep_name_push[{}", i)); add_edge(graph, dep_name_pop, dep_name_push, 0); } diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 7e87df854..00249fb35 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -323,7 +323,7 @@ inherit .return_or_yield attr (prog_module_scope) pop_symbol = "GUARD:MODULE" edge @prog.pkg_pop -> prog_module_pop_start - edge prog_module_pop -> prog_module_scope + edge module_pop_end -> prog_module_scope edge prog_module_scope -> @prog.after_scope attr (prog_legacy_qname_guard) push_symbol = "GUARD:LEGACY_QNAME" @@ -338,7 +338,7 @@ inherit .return_or_yield attr (@prog.after_scope) empty_source_span attr (prog_exports_pop) pop_symbol = "GUARD:EXPORTS" - edge prog_module_pop -> prog_exports_pop + edge module_pop_end -> prog_exports_pop edge prog_exports_pop -> @prog.exports ; allow direct access from the package to the modules exports @@ -478,24 +478,10 @@ inherit .return_or_yield (export_clause)@export_clause source:(_)@source)@export_stmt { - node source_push - node source_push_guard_exports - - edge @export_clause.source -> source_push_guard_exports - - attr (source_push_guard_exports) push_symbol = "GUARD:EXPORTS" - scan (source-text @source) { - "\"([^/\"]+)\.js\"$" { - attr (source_push) push_symbol = $1 - } - } - edge source_push_guard_exports -> source_push - edge source_push -> ROOT_NODE + edge @export_clause.source -> @source.exports edge @export_clause.before_scope -> @export_stmt.before_scope edge @export_stmt.after_scope -> @export_clause.after_scope - - } (export_statement @@ -666,6 +652,7 @@ inherit .return_or_yield edge name_push -> @export_specifier.source edge export_specifier_guard_default -> name_push edge @export_specifier.exports -> export_specifier_guard_default + } ; simple default exports @@ -681,6 +668,7 @@ inherit .return_or_yield edge @export_stmt.after_scope -> @default_expr.after_scope edge @export_stmt.exports -> export_stmt_default_guard edge export_stmt_default_guard -> @default_expr.value + } ; aggregated exports @@ -689,21 +677,9 @@ inherit .return_or_yield . source:(_)@source)@export_statement { - node source_push - node source_push_guard_exports - edge @export_statement.after_scope -> @export_statement.before_scope - attr (source_push_guard_exports) push_symbol = "GUARD:EXPORTS" - scan (source-text @source) { - "\"([^/\"]+)\.js\"$" { - attr (source_push) push_symbol = $1 - } - } - - edge @export_statement.exports -> source_push_guard_exports - edge source_push_guard_exports -> source_push - edge source_push -> ROOT_NODE + edge @export_statement.exports -> @source.exports } @@ -720,19 +696,11 @@ inherit .return_or_yield edge @export_statement.after_scope -> @export_statement.before_scope - attr (source_push_guard_exports) push_symbol = "GUARD:EXPORTS" - scan (source-text @source) { - "\"([^/\"]+)\.js\"$" { - attr (source_push) push_symbol = $1 - } - } attr (alias_pop) node_definition = @alias attr (alias_pop_dot) pop_symbol = "GUARD:MEMBER" edge @export_statement.exports -> alias_pop edge alias_pop -> alias_pop_dot - edge alias_pop_dot -> source_push_guard_exports - edge source_push_guard_exports -> source_push - edge source_push -> ROOT_NODE + edge alias_pop_dot -> @source.exports } @@ -746,8 +714,102 @@ inherit .return_or_yield ;; #### Import -; https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import +;; We distinguish two kinds of imports, based on the shape of the path: +;; +;; - Relative imports, whose path starts with `.` or `..`. These are resolved relative +;; to the current module, in the same package. +;; - Non-relative or bare imports, which do not start with `.`, `..`, or `/`. These are +;; resolved as package names. Note that the package definitions are introduced in the +;; Go code based on `package.json`, not in this query file. +;; +;; Import paths may include optional `.js` extensions, but behave the same regardless of +;; whether the extension is present. +;; +;; ## Limitations +;; +;; - Absolute imports, whose paths start with `/`, are not supported. +;; - Non-relative imports can resolve into a package (i.e., start with package name +;; components and then module name components inside that package). However, because +;; we don't detect source roots for JavaScript, this might not always work. For example, +;; a module `mod.js` inside a `src/` directory of package `foo` would be accessible as +;; `foo/src/mod`, while `foo/mod` is probably intended. +;; +;; ## References +;; +;; - ES6: https://nodejs.org/api/esm.html, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import +;; - CommonJS: https://nodejs.org/api/modules.html + +[ + (import_statement source:(_)@source) + (export_statement source:(_)@source) + ( (call_expression function:(_)@_require arguments:(arguments (string)@source)) (#eq? @_require "require") ) + ( (call_expression function:(_)@_import arguments:(arguments (string)@source)) (#eq? @_import "import") ) +] { + + node source_push_guard_exports + node source_push_guard_pkg + node @source.exports + attr (source_push_guard_exports) push_symbol = "GUARD:EXPORTS" + + scan (source-text @source) { + "^[\"']((\.|\.\.)/.*)[\"']$" { + ; relative import + let name = (replace (path-normalize (path-join (path-dir FILE_PATH) $1)) "\.js$" "") + + node source_push_end + var push_start = source_push_end + scan name { + "([^/]+)/" { + attr (push_start) push_symbol = $1 + node push_start_prev + edge push_start_prev -> push_start + set push_start = push_start_prev + } + "([^/]+)$" { + attr (push_start) push_symbol = $1 + } + } + scan $1 { + "/$" { + node push_start_prev + edge push_start_prev -> push_start + set push_start = push_start_prev + attr (push_start) push_symbol = "index" + } + } + attr (push_start) is_reference, source_node = @source + + edge @source.exports -> source_push_guard_exports + edge source_push_guard_exports -> push_start + edge source_push_end -> @source.pkg_push + } + "^[\"']([^\./].*)[\"']$" { + ; package import + let name = (replace $1 "\.js$" "") + + node source_push_end + var push_start = source_push_end + scan name { + "([^/]+)/" { + attr (push_start) push_symbol = $1 + node push_start_prev + edge push_start_prev -> push_start + set push_start = push_start_prev + } + "([^/]+)$" { + attr (push_start) symbol_reference = $1, source_node = @source + } + } + + edge @source.exports -> source_push_guard_exports + edge source_push_guard_exports -> push_start + edge source_push_end -> source_push_guard_pkg + attr (source_push_guard_pkg) push_symbol = "GUARD:PKG" + edge source_push_guard_pkg -> @source.pkg_push + } + } +} ; import "foo.js"; ; only used for side effects not imports. @@ -800,21 +862,10 @@ inherit .return_or_yield (import_clause)@import_clause source:(_)@source)@import_stmt { - node source_push - node source_push_guard_exports - edge @import_clause.before_scope -> @import_stmt.before_scope edge @import_stmt.after_scope -> @import_clause.after_scope - scan (source-text @source) { - "\"([^/\"]+)\.js\"$" { - attr (source_push) push_symbol = $1 - } - } - attr (source_push_guard_exports) push_symbol = "GUARD:EXPORTS" - edge source_push_guard_exports -> source_push - edge source_push -> ROOT_NODE - edge @import_clause.source -> source_push_guard_exports + edge @import_clause.source -> @source.exports } From 38919a37e249b019ab3e7f8a207548cccef7e2f6 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 5 Oct 2023 04:55:53 +0200 Subject: [PATCH 149/500] A few more changes --- .../src/stack-graphs.tsg | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 00249fb35..1eac5069d 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4034,15 +4034,15 @@ inherit .return_or_yield (function) (generator_function) (arrow_function) - ]@right) { + ]@assignment_expr) { node left_definiens_hook node left_ignore_guard attr (left_ignore_guard) pop_symbol = "GUARD:GANDALF" attr (left_definiens_hook) node_definition = @left - attr (left_definiens_hook) definiens_node = @right - edge ROOT_NODE -> left_ignore_guard + attr (left_definiens_hook) definiens_node = @assignment_expr + edge @assignment_expr.pkg_pop -> left_ignore_guard edge left_ignore_guard -> left_definiens_hook } @@ -4078,7 +4078,7 @@ inherit .return_or_yield (function) (generator_function) (arrow_function) - ]@value) { + ]@value)@pair_expr { node name_definiens_hook node name_ignore_guard @@ -4086,7 +4086,7 @@ inherit .return_or_yield attr (name_ignore_guard) pop_symbol = "GUARD:GANDALF" attr (name_definiens_hook) node_definition = @name attr (name_definiens_hook) definiens_node = @value - edge ROOT_NODE -> name_ignore_guard + edge @pair_expr.pkg_pop -> name_ignore_guard edge name_ignore_guard -> name_definiens_hook } From 0505878ac6bd6f2c276a44d8e0aee7ff0db7fa99 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 5 Oct 2023 04:56:07 +0200 Subject: [PATCH 150/500] cargo fmt --- .../rust/npm_package.rs | 82 +++++++++++++++---- 1 file changed, 67 insertions(+), 15 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs index 3a3c98b05..d5e1ad944 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs @@ -47,17 +47,39 @@ impl FileAnalyzer for NpmPackageAnalyzer { // // [root] -> [pop "GUARD:PKG_INTERNAL"] -> [pop pkg_internal_name] // - let pkg_internal_guard_pop = add_pop(graph, file, root, PKG_INTERNAL_GUARD, "pkg_internal_guard_pop"); - let pkg_internal_name_pop = - add_pop(graph, file, pkg_internal_guard_pop, pkg_internal_name, "pkg_internal_name_pop"); + let pkg_internal_guard_pop = add_pop( + graph, + file, + root, + PKG_INTERNAL_GUARD, + "pkg_internal_guard_pop", + ); + let pkg_internal_name_pop = add_pop( + graph, + file, + pkg_internal_guard_pop, + pkg_internal_name, + "pkg_internal_name_pop", + ); // reach package internals via root // // [push pkg_internal_name] -> [push "GUARD:PKG_INTERNAL"] -> [root] // - let pkg_internal_guard_push = add_push(graph, file, root, PKG_INTERNAL_GUARD, "pkg_internal_guard_push"); - let pkg_internal_name_push = - add_push(graph, file, pkg_internal_guard_push, pkg_internal_name, "pkg_internal_name_push"); + let pkg_internal_guard_push = add_push( + graph, + file, + root, + PKG_INTERNAL_GUARD, + "pkg_internal_guard_push", + ); + let pkg_internal_name_push = add_push( + graph, + file, + pkg_internal_guard_push, + pkg_internal_name, + "pkg_internal_name_push", + ); // reach exports via package name // @@ -69,22 +91,35 @@ impl FileAnalyzer for NpmPackageAnalyzer { // [root] -> [pop "GUARD:PKG"] -> [pop pkg_name]* -> [push pkg_internal_name] // let pkg_guard_pop = add_pop(graph, file, root, PKG_GUARD, "pkg_guard_pop"); - let pkg_name_pop = - add_module_pops(graph, file, Path::new(&npm_pkg.name), pkg_guard_pop, "pkg_name_pop"); + let pkg_name_pop = add_module_pops( + graph, + file, + Path::new(&npm_pkg.name), + pkg_guard_pop, + "pkg_name_pop", + ); add_edge(graph, pkg_name_pop, pkg_internal_name_push, 0); // reach main exports directly via package name (with precedence) // // [pop pkg_name] -1-> [pop "GUARD:EXPORTS"] -> [push "GUARD:EXPORTS"] -> [push main]* -> [push pkg_internal_name] // - let exports_guard_pop = add_pop(graph, file, pkg_name_pop, EXPORTS_GUARD, "exports_guard_pop"); + let exports_guard_pop = add_pop( + graph, + file, + pkg_name_pop, + EXPORTS_GUARD, + "exports_guard_pop", + ); replace_edge(graph, pkg_name_pop, exports_guard_pop, 1); let main = NormalizedRelativePath::from_str(&npm_pkg.main) .map(|p| p.into_path_buf()) .unwrap_or(PathBuf::from("index")) .with_extension(""); - let main_push = add_module_pushes(graph, file, &main, pkg_internal_name_push, "main_push"); - let exports_guard_push = add_push(graph, file, main_push, EXPORTS_GUARD, "exports_guard_push"); + let main_push = + add_module_pushes(graph, file, &main, pkg_internal_name_push, "main_push"); + let exports_guard_push = + add_push(graph, file, main_push, EXPORTS_GUARD, "exports_guard_push"); add_edge(graph, exports_guard_pop, exports_guard_push, 0); } @@ -92,15 +127,32 @@ impl FileAnalyzer for NpmPackageAnalyzer { // // [pop pkg_internal_name] -> [pop "GUARD:PKG"] -> [pop dep_name]* -> [push dep_name]* -> [push "GUARD:PKG"] -> [root] // - let dep_guard_pop = add_pop(graph, file, pkg_internal_name_pop, PKG_GUARD, "dep_guard_pop"); + let dep_guard_pop = add_pop( + graph, + file, + pkg_internal_name_pop, + PKG_GUARD, + "dep_guard_pop", + ); let dep_guard_push = add_push(graph, file, root, PKG_GUARD, "dep_guard_push"); for (i, (dep_name, _)) in npm_pkg.dependencies.iter().enumerate() { if dep_name.is_empty() { continue; } - let dep_name_pop = add_module_pops(graph, file, Path::new(dep_name), dep_guard_pop, &format!("dep_name_pop[{}]", i)); - let dep_name_push = - add_module_pushes(graph, file, Path::new(dep_name), dep_guard_push, &format!("dep_name_push[{}", i)); + let dep_name_pop = add_module_pops( + graph, + file, + Path::new(dep_name), + dep_guard_pop, + &format!("dep_name_pop[{}]", i), + ); + let dep_name_push = add_module_pushes( + graph, + file, + Path::new(dep_name), + dep_guard_push, + &format!("dep_name_push[{}", i), + ); add_edge(graph, dep_name_pop, dep_name_push, 0); } From efeab7917f9ca6657eeb0c42c4940d1e0d2c5fdc Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 5 Oct 2023 04:58:42 +0200 Subject: [PATCH 151/500] A few more changes --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 1eac5069d..b5bb51bf8 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4034,14 +4034,14 @@ inherit .return_or_yield (function) (generator_function) (arrow_function) - ]@assignment_expr) { + ]@right)@assignment_expr { node left_definiens_hook node left_ignore_guard attr (left_ignore_guard) pop_symbol = "GUARD:GANDALF" attr (left_definiens_hook) node_definition = @left - attr (left_definiens_hook) definiens_node = @assignment_expr + attr (left_definiens_hook) definiens_node = @right edge @assignment_expr.pkg_pop -> left_ignore_guard edge left_ignore_guard -> left_definiens_hook } From 2849522fffd2cd0f2d3281f9f9c2e5790da58cea Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 5 Oct 2023 14:01:55 +0200 Subject: [PATCH 152/500] Fix unrealistic expectations --- .../es6_imports_and_exports.js | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/es6_imports_and_exports.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/es6_imports_and_exports.js index 02129907c..ab78f0cb1 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/es6_imports_and_exports.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/es6_imports_and_exports.js @@ -66,22 +66,22 @@ import * as mod from "./a_basic.js"; // ^ defined: 20, 21 mod.h; -// ^ defined: 24, 24 +// ^ defined: 24 mod.i; -// ^ defined: 24, 24 +// ^ defined: 24 mod.j; -// ^ defined: 25, 26 +// ^ defined: 25 mod.k; -// ^ defined: 26, 26 +// ^ defined: 26 mod.l; -// ^ defined: 27, 27 +// ^ defined: 27 mod.m; -// ^ defined: 28, 28 +// ^ defined: 28 //////////////////////////////////////////////////////////////////////////////// @@ -209,17 +209,17 @@ export let x = 42; /*--- path: dirs/test_0.js ---*/ import { x } from "./foo" -// ^ defined: 211, 203 +// ^ defined: 203 /*--- path: dirs/test_1.js ---*/ import { x } from "./bar/baz" -// ^ defined: 216, 207 +// ^ defined: 207 /*--- path: dirs/bar/test_2.js ---*/ import { x } from "../foo" -// ^ defined: 221, 203 +// ^ defined: 203 //////////////////////////////////////////////////////////////////////////////// // @@ -250,14 +250,14 @@ export let x = 42; /*--- path: dir_imports/test_0.js ---*/ import { x } from "./foo/" -// ^ defined: 252, 248 +// ^ defined: 248 /*--- path: dir_imports/foo/test_1.js ---*/ import { x } from "./" -// ^ defined: 257, 248 +// ^ defined: 248 /*--- path: dir_imports/bar/test_2.js ---*/ import { x } from "../foo/" -// ^ defined: 262, 248 +// ^ defined: 248 From 1449ad4a4d40e7b9e9a84f0b09f20f6cfb718e9e Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 5 Oct 2023 15:32:48 +0200 Subject: [PATCH 153/500] Fix grammar versions Tree-sitter grammar versions are not semantic. Therefore, we depend on precise versions and don't allow e.g. a new patch version to break our code. --- languages/tree-sitter-stack-graphs-java/Cargo.toml | 2 +- languages/tree-sitter-stack-graphs-typescript/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-java/Cargo.toml b/languages/tree-sitter-stack-graphs-java/Cargo.toml index 814447be8..8bd3e5f93 100644 --- a/languages/tree-sitter-stack-graphs-java/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-java/Cargo.toml @@ -37,4 +37,4 @@ harness = false # need to provide own main function to handle running tests anyhow = "1.0" clap = { version = "4", features = ["derive"] } tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs", features=["cli"] } -tree-sitter-java = { version = "~0.20.0" } +tree-sitter-java = { version = "=0.20.0" } diff --git a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml index 65511e3f8..da5df7ef9 100644 --- a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml @@ -34,7 +34,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" stack-graphs = { version = ">=0.11, <=0.12", path = "../../stack-graphs" } tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs" } -tree-sitter-typescript = "0.20.2" +tree-sitter-typescript = "=0.20.2" tsconfig = "0.1.0" [dev-dependencies] From 2d8b96ee255bd8eff72e9e10af6b68c7b007c841 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Oct 2023 14:37:39 +0000 Subject: [PATCH 154/500] Bump semver in /languages/tree-sitter-stack-graphs-typescript/vscode Bumps [semver](https://github.com/npm/node-semver) from 7.3.8 to 7.5.4. - [Release notes](https://github.com/npm/node-semver/releases) - [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md) - [Commits](https://github.com/npm/node-semver/compare/v7.3.8...v7.5.4) --- updated-dependencies: - dependency-name: semver dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .../vscode/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-typescript/vscode/package-lock.json b/languages/tree-sitter-stack-graphs-typescript/vscode/package-lock.json index b1153da95..9cc00e7ae 100644 --- a/languages/tree-sitter-stack-graphs-typescript/vscode/package-lock.json +++ b/languages/tree-sitter-stack-graphs-typescript/vscode/package-lock.json @@ -68,9 +68,9 @@ } }, "node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, From d0754f7059e32c6e287e56c43ca35bdb3023ea12 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 5 Oct 2023 16:47:46 +0200 Subject: [PATCH 155/500] Ensure all default guards are references/definitions --- .../src/stack-graphs.tsg | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index b5bb51bf8..600c77376 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -617,18 +617,18 @@ inherit .return_or_yield ( (export_specifier - name:(_)@_name + name:(_)@name !alias)@export_specifier - (#eq? @_name "default") + (#eq? @name "default") ) { node export_specifier_pop_guard_default node export_specifier_push_guard_default - attr (export_specifier_pop_guard_default) pop_symbol = "GUARD:DEFAULT" - attr (export_specifier_push_guard_default) push_symbol = "GUARD:DEFAULT" + attr (export_specifier_pop_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @name + attr (export_specifier_push_guard_default) symbol_reference = "GUARD:DEFAULT", source_node = @name edge @export_specifier.exports -> export_specifier_pop_guard_default edge export_specifier_pop_guard_default -> export_specifier_push_guard_default edge export_specifier_push_guard_default -> @export_specifier.source @@ -638,9 +638,9 @@ inherit .return_or_yield ( (export_specifier name:(_)@name - alias:(_)@_alias)@export_specifier + alias:(_)@alias)@export_specifier - (#eq? @_alias "default") + (#eq? @alias "default") ) { @@ -648,7 +648,7 @@ inherit .return_or_yield node name_push attr (name_push) push_node = @name - attr (export_specifier_guard_default) pop_symbol = "GUARD:DEFAULT" + attr (export_specifier_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @alias edge name_push -> @export_specifier.source edge export_specifier_guard_default -> name_push edge @export_specifier.exports -> export_specifier_guard_default @@ -1012,7 +1012,7 @@ inherit .return_or_yield edge @import_clause.after_scope -> @import_clause.before_scope attr (default_name_pop) node_definition = @default_name - attr (default_name_push_guard_default) push_symbol = "GUARD:DEFAULT" + attr (default_name_push_guard_default) symbol_reference = "GUARD:DEFAULT", source_node = @default_name edge default_name_pop -> default_name_push_guard_default edge default_name_push_guard_default -> @import_clause.source From 6a857acd255fc01afa433ec57b013f143971eaff Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 9 Oct 2023 17:04:54 +0200 Subject: [PATCH 156/500] Add support for definiens_node --- tree-sitter-stack-graphs/src/lib.rs | 38 +++++++++++++--------- tree-sitter-stack-graphs/tests/it/nodes.rs | 27 +++++++++++++++ 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/tree-sitter-stack-graphs/src/lib.rs b/tree-sitter-stack-graphs/src/lib.rs index e2377f853..31b679a5c 100644 --- a/tree-sitter-stack-graphs/src/lib.rs +++ b/tree-sitter-stack-graphs/src/lib.rs @@ -364,6 +364,7 @@ static SCOPE_TYPE: &'static str = "scope"; // Node attribute names static DEBUG_ATTR_PREFIX: &'static str = "debug_"; +static DEFINIENS_NODE: &'static str = "definiens_node"; static EMPTY_SOURCE_SPAN_ATTR: &'static str = "empty_source_span"; static IS_DEFINITION_ATTR: &'static str = "is_definition"; static IS_ENDPOINT_ATTR: &'static str = "is_endpoint"; @@ -885,7 +886,7 @@ impl<'a> Builder<'a> { NodeType::PushSymbol => self.load_push_symbol(node_ref)?, NodeType::Scope => self.load_scope(node_ref)?, }; - self.load_span(node_ref, handle)?; + self.load_source_info(node_ref, handle)?; self.load_node_debug_info(node_ref, handle)?; } @@ -1091,28 +1092,33 @@ impl<'a> Builder<'a> { } } - fn load_span( + fn load_source_info( &mut self, node_ref: GraphNodeRef, node_handle: Handle, ) -> Result<(), BuildError> { let node = &self.graph[node_ref]; - let source_node = match node.attributes.get(SOURCE_NODE_ATTR) { - Some(source_node) => &self.graph[source_node.as_syntax_node_ref()?], - None => return Ok(()), + if let Some(source_node) = node.attributes.get(SOURCE_NODE_ATTR) { + let source_node = &self.graph[source_node.as_syntax_node_ref()?]; + let mut span = self.span_calculator.for_node(source_node); + if match node.attributes.get(EMPTY_SOURCE_SPAN_ATTR) { + Some(empty_source_span) => empty_source_span.as_boolean()?, + None => false, + } { + span.end = span.start.clone(); + } + let containing_line = &self.source[span.start.containing_line.clone()]; + let containing_line = self.stack_graph.add_string(containing_line); + let source_info = self.stack_graph.source_info_mut(node_handle); + source_info.span = span; + source_info.containing_line = ControlledOption::some(containing_line); }; - let mut span = self.span_calculator.for_node(source_node); - if match node.attributes.get(EMPTY_SOURCE_SPAN_ATTR) { - Some(empty_source_span) => empty_source_span.as_boolean()?, - None => false, - } { - span.end = span.start.clone(); + if let Some(definiens_node) = node.attributes.get(DEFINIENS_NODE) { + let definiens_node = &self.graph[definiens_node.as_syntax_node_ref()?]; + let span = self.span_calculator.for_node(definiens_node); + let source_info = self.stack_graph.source_info_mut(node_handle); + source_info.definiens_span = span; } - let containing_line = &self.source[span.start.containing_line.clone()]; - let containing_line = self.stack_graph.add_string(containing_line); - let source_info = self.stack_graph.source_info_mut(node_handle); - source_info.span = span; - source_info.containing_line = ControlledOption::some(containing_line); Ok(()) } diff --git a/tree-sitter-stack-graphs/tests/it/nodes.rs b/tree-sitter-stack-graphs/tests/it/nodes.rs index 2befc6a95..5306929d4 100644 --- a/tree-sitter-stack-graphs/tests/it/nodes.rs +++ b/tree-sitter-stack-graphs/tests/it/nodes.rs @@ -284,3 +284,30 @@ fn can_calculate_spans() { let trimmed_line = &python[source_info.span.start.trimmed_line.clone()]; assert_eq!(trimmed_line, "a"); } + +#[test] +fn can_set_definiens() { + let tsg = r#" + (function_definition body:(_)@body) { + node result + attr (result) definiens_node = @body + } + "#; + let python = r#" + def foo(): + pass + "#; + + let (graph, file) = build_stack_graph(python, tsg).unwrap(); + let node_handle = graph.nodes_for_file(file).next().unwrap(); + let source_info = graph.source_info(node_handle).unwrap(); + + let actual_span = format!( + "{}:{}-{}:{}", + source_info.definiens_span.start.line, + source_info.definiens_span.start.column.utf8_offset, + source_info.definiens_span.end.line, + source_info.definiens_span.end.column.utf8_offset, + ); + assert_eq!("2:8-2:12", actual_span) +} From 76e28700129cfc025584598f6650c86e1887e9b4 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 9 Oct 2023 17:06:43 +0200 Subject: [PATCH 157/500] Add syntax_type support --- tree-sitter-stack-graphs/src/lib.rs | 7 ++++++ tree-sitter-stack-graphs/tests/it/nodes.rs | 25 ++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/tree-sitter-stack-graphs/src/lib.rs b/tree-sitter-stack-graphs/src/lib.rs index 31b679a5c..672463bdc 100644 --- a/tree-sitter-stack-graphs/src/lib.rs +++ b/tree-sitter-stack-graphs/src/lib.rs @@ -373,6 +373,7 @@ static IS_REFERENCE_ATTR: &'static str = "is_reference"; static SCOPE_ATTR: &'static str = "scope"; static SOURCE_NODE_ATTR: &'static str = "source_node"; static SYMBOL_ATTR: &'static str = "symbol"; +static SYNTAX_TYPE: &'static str = "syntax_type"; static TYPE_ATTR: &'static str = "type"; // Expected attributes per node type @@ -1119,6 +1120,12 @@ impl<'a> Builder<'a> { let source_info = self.stack_graph.source_info_mut(node_handle); source_info.definiens_span = span; } + if let Some(syntax_type) = node.attributes.get(SYNTAX_TYPE) { + let syntax_type = syntax_type.as_str()?; + let interned_string = self.stack_graph.add_string(syntax_type); + let source_info = self.stack_graph.source_info_mut(node_handle); + source_info.syntax_type = interned_string.into(); + } Ok(()) } diff --git a/tree-sitter-stack-graphs/tests/it/nodes.rs b/tree-sitter-stack-graphs/tests/it/nodes.rs index 5306929d4..d200ed05d 100644 --- a/tree-sitter-stack-graphs/tests/it/nodes.rs +++ b/tree-sitter-stack-graphs/tests/it/nodes.rs @@ -311,3 +311,28 @@ fn can_set_definiens() { ); assert_eq!("2:8-2:12", actual_span) } + +#[test] +fn can_set_syntax_type() { + let tsg = r#" + (function_definition) { + node result + attr (result) syntax_type = "function" + } + "#; + let python = r#" + def foo(): + pass + "#; + + let (graph, file) = build_stack_graph(python, tsg).unwrap(); + let node_handle = graph.nodes_for_file(file).next().unwrap(); + let source_info = graph.source_info(node_handle).unwrap(); + + let syntax_type = source_info + .syntax_type + .into_option() + .map(|s| &graph[s]) + .unwrap_or("MISSING"); + assert_eq!("function", syntax_type) +} From 1c39888ab2ab1231e270aebd1b227791f9f7f518 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 9 Oct 2023 17:09:49 +0200 Subject: [PATCH 158/500] Document syntax_type attribute --- tree-sitter-stack-graphs/src/lib.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tree-sitter-stack-graphs/src/lib.rs b/tree-sitter-stack-graphs/src/lib.rs index 672463bdc..9a1ba8996 100644 --- a/tree-sitter-stack-graphs/src/lib.rs +++ b/tree-sitter-stack-graphs/src/lib.rs @@ -160,6 +160,19 @@ //! } //! ``` //! +//! ### Annotating nodes with syntax type information +//! +//! You can annotate any stack graph node with information about its syntax type. To do this, add a `syntax_type` +//! attribute, whose value is a string indicating the syntax type. +//! +//! ``` skip +//! (function_definition name: (identifier) @id) @func { +//! node def +//! ; ... +//! attr (def) syntax_type = "function" +//! } +//! ``` +//! //! ### Connecting stack graph nodes with edges //! //! To connect two stack graph nodes, use the `edge` statement to add an edge between them: From 0d4f95a968a6189c8834c1efe1c7fb2ff6054f16 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 9 Oct 2023 17:29:47 +0200 Subject: [PATCH 159/500] Only load definions for definitions --- tree-sitter-stack-graphs/src/lib.rs | 42 +++++++++++++++------- tree-sitter-stack-graphs/tests/it/nodes.rs | 3 +- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/tree-sitter-stack-graphs/src/lib.rs b/tree-sitter-stack-graphs/src/lib.rs index 9a1ba8996..564b32ba2 100644 --- a/tree-sitter-stack-graphs/src/lib.rs +++ b/tree-sitter-stack-graphs/src/lib.rs @@ -391,9 +391,9 @@ static TYPE_ATTR: &'static str = "type"; // Expected attributes per node type static POP_SCOPED_SYMBOL_ATTRS: Lazy> = - Lazy::new(|| HashSet::from([TYPE_ATTR, SYMBOL_ATTR, IS_DEFINITION_ATTR])); + Lazy::new(|| HashSet::from([TYPE_ATTR, SYMBOL_ATTR, IS_DEFINITION_ATTR, DEFINIENS_NODE])); static POP_SYMBOL_ATTRS: Lazy> = - Lazy::new(|| HashSet::from([TYPE_ATTR, SYMBOL_ATTR, IS_DEFINITION_ATTR])); + Lazy::new(|| HashSet::from([TYPE_ATTR, SYMBOL_ATTR, IS_DEFINITION_ATTR, DEFINIENS_NODE])); static PUSH_SCOPED_SYMBOL_ATTRS: Lazy> = Lazy::new(|| HashSet::from([TYPE_ATTR, SYMBOL_ATTR, SCOPE_ATTR, IS_REFERENCE_ATTR])); static PUSH_SYMBOL_ATTRS: Lazy> = @@ -1019,10 +1019,14 @@ impl<'a> Builder<'a> { let id = self.node_id_for_graph_node(node_ref); let is_definition = self.load_flag(node, IS_DEFINITION_ATTR)?; self.verify_attributes(node, POP_SCOPED_SYMBOL_TYPE, &POP_SCOPED_SYMBOL_ATTRS); - Ok(self + let node_handle = self .stack_graph .add_pop_scoped_symbol_node(id, symbol, is_definition) - .unwrap()) + .unwrap(); + if is_definition { + self.load_definiens_info(node_ref, node_handle)?; + } + Ok(node_handle) } fn load_pop_symbol(&mut self, node_ref: GraphNodeRef) -> Result, BuildError> { @@ -1035,10 +1039,14 @@ impl<'a> Builder<'a> { let id = self.node_id_for_graph_node(node_ref); let is_definition = self.load_flag(node, IS_DEFINITION_ATTR)?; self.verify_attributes(node, POP_SYMBOL_TYPE, &POP_SYMBOL_ATTRS); - Ok(self + let node_handle = self .stack_graph .add_pop_symbol_node(id, symbol, is_definition) - .unwrap()) + .unwrap(); + if is_definition { + self.load_definiens_info(node_ref, node_handle)?; + } + Ok(node_handle) } fn load_push_scoped_symbol( @@ -1127,12 +1135,6 @@ impl<'a> Builder<'a> { source_info.span = span; source_info.containing_line = ControlledOption::some(containing_line); }; - if let Some(definiens_node) = node.attributes.get(DEFINIENS_NODE) { - let definiens_node = &self.graph[definiens_node.as_syntax_node_ref()?]; - let span = self.span_calculator.for_node(definiens_node); - let source_info = self.stack_graph.source_info_mut(node_handle); - source_info.definiens_span = span; - } if let Some(syntax_type) = node.attributes.get(SYNTAX_TYPE) { let syntax_type = syntax_type.as_str()?; let interned_string = self.stack_graph.add_string(syntax_type); @@ -1142,6 +1144,22 @@ impl<'a> Builder<'a> { Ok(()) } + fn load_definiens_info( + &mut self, + node_ref: GraphNodeRef, + node_handle: Handle, + ) -> Result<(), BuildError> { + let node = &self.graph[node_ref]; + let definiens_node = match node.attributes.get(DEFINIENS_NODE) { + Some(definiens_node) => &self.graph[definiens_node.as_syntax_node_ref()?], + None => return Ok(()), + }; + let span = self.span_calculator.for_node(definiens_node); + let source_info = self.stack_graph.source_info_mut(node_handle); + source_info.definiens_span = span; + Ok(()) + } + fn load_node_debug_info( &mut self, node_ref: GraphNodeRef, diff --git a/tree-sitter-stack-graphs/tests/it/nodes.rs b/tree-sitter-stack-graphs/tests/it/nodes.rs index d200ed05d..ccb3e220e 100644 --- a/tree-sitter-stack-graphs/tests/it/nodes.rs +++ b/tree-sitter-stack-graphs/tests/it/nodes.rs @@ -288,8 +288,9 @@ fn can_calculate_spans() { #[test] fn can_set_definiens() { let tsg = r#" - (function_definition body:(_)@body) { + (function_definition name:(_)@name body:(_)@body) { node result + attr (result) type = "pop_symbol", symbol = (source-text @name), source_node = @name, is_definition attr (result) definiens_node = @body } "#; From 31fbee70cdb9a12cd43d0257634a37a785e937a5 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 9 Oct 2023 17:29:56 +0200 Subject: [PATCH 160/500] Document definiens_node --- tree-sitter-stack-graphs/src/lib.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tree-sitter-stack-graphs/src/lib.rs b/tree-sitter-stack-graphs/src/lib.rs index 564b32ba2..bca687b70 100644 --- a/tree-sitter-stack-graphs/src/lib.rs +++ b/tree-sitter-stack-graphs/src/lib.rs @@ -173,6 +173,20 @@ //! } //! ``` //! +//! ### Annotating definitions with definiens information +//! +//! You cannot annotate definitions with a definiens, which is the thing the definition covers. For example, for +//! a function definition, the definiens would be the function body. To do this, add a `definiens_node` attribute, +//! whose value is a syntax node that spans the definiens. +//! +//! ``` skip +//! (function_definition name: (identifier) @id body: (_) @body) @func { +//! node def +//! ; ... +//! attr (def) definiens_node = @body +//! } +//! ``` +//! //! ### Connecting stack graph nodes with edges //! //! To connect two stack graph nodes, use the `edge` statement to add an edge between them: From edc71106e3a10edc00434f9e3c88169fe02c35e6 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 9 Oct 2023 17:39:58 +0200 Subject: [PATCH 161/500] Allow null values for definiens_node --- tree-sitter-stack-graphs/src/lib.rs | 3 +++ tree-sitter-stack-graphs/tests/it/nodes.rs | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/tree-sitter-stack-graphs/src/lib.rs b/tree-sitter-stack-graphs/src/lib.rs index bca687b70..e8bdd7492 100644 --- a/tree-sitter-stack-graphs/src/lib.rs +++ b/tree-sitter-stack-graphs/src/lib.rs @@ -187,6 +187,8 @@ //! } //! ``` //! +//! Definiens are optional and setting them to `#null` explicitly is allowed. +//! //! ### Connecting stack graph nodes with edges //! //! To connect two stack graph nodes, use the `edge` statement to add an edge between them: @@ -1165,6 +1167,7 @@ impl<'a> Builder<'a> { ) -> Result<(), BuildError> { let node = &self.graph[node_ref]; let definiens_node = match node.attributes.get(DEFINIENS_NODE) { + Some(Value::Null) => return Ok(()), Some(definiens_node) => &self.graph[definiens_node.as_syntax_node_ref()?], None => return Ok(()), }; diff --git a/tree-sitter-stack-graphs/tests/it/nodes.rs b/tree-sitter-stack-graphs/tests/it/nodes.rs index ccb3e220e..c36a08744 100644 --- a/tree-sitter-stack-graphs/tests/it/nodes.rs +++ b/tree-sitter-stack-graphs/tests/it/nodes.rs @@ -313,6 +313,26 @@ fn can_set_definiens() { assert_eq!("2:8-2:12", actual_span) } +#[test] +fn can_set_null_definiens() { + let tsg = r#" + (function_definition name:(_)@name) { + node result + attr (result) type = "pop_symbol", symbol = (source-text @name), source_node = @name, is_definition + attr (result) definiens_node = #null + } + "#; + let python = r#" + def foo(): + pass + "#; + + let (graph, file) = build_stack_graph(python, tsg).unwrap(); + let node_handle = graph.nodes_for_file(file).next().unwrap(); + let source_info = graph.source_info(node_handle).unwrap(); + assert_eq!(lsp_positions::Span::default(), source_info.definiens_span) +} + #[test] fn can_set_syntax_type() { let tsg = r#" From 0afdd2a04ba9382cee780e9c77aa4eea56bb85b4 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 9 Oct 2023 16:25:38 +0200 Subject: [PATCH 162/500] Adds missing syntax types Co-authored-by: Rebecca Valentine --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 600c77376..90e593b0d 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4025,6 +4025,7 @@ inherit .return_or_yield ]@right)@assignment_expr { attr (@assignment_expr.pop) definiens_node = @right + attr (@assignment_expr.pop) syntax_type = "function" } @@ -4042,6 +4043,7 @@ inherit .return_or_yield attr (left_ignore_guard) pop_symbol = "GUARD:GANDALF" attr (left_definiens_hook) node_definition = @left attr (left_definiens_hook) definiens_node = @right + attr (left_definiens_hook) syntax_type = "function" edge @assignment_expr.pkg_pop -> left_ignore_guard edge left_ignore_guard -> left_definiens_hook } @@ -4056,6 +4058,7 @@ inherit .return_or_yield ]@initializer)) { attr (@name.pop) definiens_node = @initializer + attr (@name.pop) syntax_type = "function" } @@ -4069,6 +4072,7 @@ inherit .return_or_yield ]@initializer)) { attr (@name.pop) definiens_node = @initializer + attr (@name.pop) syntax_type = "function" } @@ -4086,6 +4090,7 @@ inherit .return_or_yield attr (name_ignore_guard) pop_symbol = "GUARD:GANDALF" attr (name_definiens_hook) node_definition = @name attr (name_definiens_hook) definiens_node = @value + attr (name_definiens_hook) syntax_type = "function" edge @pair_expr.pkg_pop -> name_ignore_guard edge name_ignore_guard -> name_definiens_hook From a352c39c59d88b4c6ac9508bfdf41f07c4f3c248 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 9 Oct 2023 17:55:26 +0200 Subject: [PATCH 163/500] Adds class to definiens rules for assignments etc Co-authored-by: Rebecca Valentine --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 90e593b0d..9d55380d9 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4022,6 +4022,7 @@ inherit .return_or_yield (function) (generator_function) (arrow_function) + (class) ]@right)@assignment_expr { attr (@assignment_expr.pop) definiens_node = @right @@ -4035,6 +4036,7 @@ inherit .return_or_yield (function) (generator_function) (arrow_function) + (class) ]@right)@assignment_expr { node left_definiens_hook @@ -4055,6 +4057,7 @@ inherit .return_or_yield (function) (generator_function) (arrow_function) + (class) ]@initializer)) { attr (@name.pop) definiens_node = @initializer @@ -4069,6 +4072,7 @@ inherit .return_or_yield (function) (generator_function) (arrow_function) + (class) ]@initializer)) { attr (@name.pop) definiens_node = @initializer @@ -4082,6 +4086,7 @@ inherit .return_or_yield (function) (generator_function) (arrow_function) + (class) ]@value)@pair_expr { node name_definiens_hook From 46dde3eef9a0c9fb759d89ea6afa77dfbffecfd0 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 9 Oct 2023 17:57:24 +0200 Subject: [PATCH 164/500] Excludes CommonJS exports from definiens Co-authored-by: Rebecca Valentine --- .../src/stack-graphs.tsg | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 9d55380d9..b3cc547bc 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4030,14 +4030,20 @@ inherit .return_or_yield } -(assignment_expression - left: (member_expression property:(_)@left) - right: [ - (function) - (generator_function) - (arrow_function) - (class) - ]@right)@assignment_expr { +( + (assignment_expression + left: (member_expression + object:(identifier)@_object + property:(_)@left + ) + right: [ + (function) + (generator_function) + (arrow_function) + ]@right)@assignment_expr + (#not-eq @_object "module") + (#not-eq @left "exports") +) { node left_definiens_hook node left_ignore_guard From e53474a1ff09d1c129025bb2c360333f70672a22 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 9 Oct 2023 18:24:31 +0200 Subject: [PATCH 165/500] Adds test case and fix Co-authored-by: Rebecca Valentine --- .../src/stack-graphs.tsg | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index b3cc547bc..8f22cdf7c 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3838,7 +3838,7 @@ inherit .return_or_yield ;; ## ES6-style Imports ;; ES6 modules can also be imported using an import function. In general, -;; these look like `require(expr)`, but in practice the expression is a string +;; these look like `import(expr)`, but in practice the expression is a string ;; constant, which is the only case we handle. ( @@ -3881,11 +3881,15 @@ inherit .return_or_yield (#eq? @_exports "exports") ) { + node property_pop node property_pop_dot attr (property_pop) node_definition = @property attr (property_pop_dot) pop_symbol = "GUARD:MEMBER" - edge @assignment_expr.exports -> property_pop_dot + node assignment_expr_guard_default + attr (assignment_expr_guard_default) pop_symbol = "GUARD:DEFAULT" + edge assignment_expr_guard_default -> property_pop_dot + edge @assignment_expr.exports -> assignment_expr_guard_default edge property_pop_dot -> property_pop edge property_pop -> @right.value } @@ -3893,14 +3897,17 @@ inherit .return_or_yield ( (assignment_expression left: (member_expression - object:(identifier)@_module + object:(_)@_module property:(_)@_exports) right: (_)@right)@assignment_expr (#eq? @_module "module") (#eq? @_exports "exports") ) { - edge @assignment_expr.exports -> @right.value + node assignment_expr_guard_default + attr (assignment_expr_guard_default) pop_symbol = "GUARD:DEFAULT" + edge assignment_expr_guard_default -> @right.value + edge @assignment_expr.exports -> assignment_expr_guard_default } ;; ## CommonJS-style Imports @@ -3915,7 +3922,11 @@ inherit .return_or_yield arguments:(arguments (string)@source))@call_expr (#eq? @_require "require") ) { - edge @call_expr.value -> @source.exports + + node require_guard_default + attr (require_guard_default) push_symbol = "GUARD:DEFAULT" + edge require_guard_default -> @source.exports + edge @call_expr.value -> require_guard_default } From f3bb1d80345275f6b1c1cf2bedd6e89c23f2eef5 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 9 Oct 2023 18:27:05 +0200 Subject: [PATCH 166/500] Fix test assertion --- .../test/statements/for_statement.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/statements/for_statement.js b/languages/tree-sitter-stack-graphs-javascript/test/statements/for_statement.js index 7a1f8b29f..7cdc5e19f 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/statements/for_statement.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/statements/for_statement.js @@ -28,4 +28,4 @@ for (let y = (x, 1); // Flow around /**/ x; -// ^ defined 1 \ No newline at end of file +// ^ defined: 1 \ No newline at end of file From 0ffa7b4587d7bcc3b439280a06fe2fe28a512774 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 9 Oct 2023 18:42:48 +0200 Subject: [PATCH 167/500] Adds fix for default CommonJS default imports Co-authored-by: Rebecca Valentine --- .../src/stack-graphs.tsg | 21 +++++++++---------- ..._default_export_with_ES6_default_import.js | 12 +++++++++++ .../CommonJS_default_import_of_functions.js | 15 +++++++++++++ 3 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_default_export_with_ES6_default_import.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_default_import_of_functions.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 8f22cdf7c..c5822999f 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -747,10 +747,13 @@ inherit .return_or_yield ] { node source_push_guard_exports + node source_push_guard_default node source_push_guard_pkg node @source.exports attr (source_push_guard_exports) push_symbol = "GUARD:EXPORTS" + attr (source_push_guard_default) push_symbol = "GUARD:DEFAULT" + edge source_push_guard_default -> source_push_guard_exports scan (source-text @source) { "^[\"']((\.|\.\.)/.*)[\"']$" { @@ -781,6 +784,7 @@ inherit .return_or_yield attr (push_start) is_reference, source_node = @source edge @source.exports -> source_push_guard_exports + edge @source.exports -> source_push_guard_default edge source_push_guard_exports -> push_start edge source_push_end -> @source.pkg_push } @@ -803,6 +807,7 @@ inherit .return_or_yield } edge @source.exports -> source_push_guard_exports + edge @source.exports -> source_push_guard_default edge source_push_guard_exports -> push_start edge source_push_end -> source_push_guard_pkg attr (source_push_guard_pkg) push_symbol = "GUARD:PKG" @@ -3886,10 +3891,7 @@ inherit .return_or_yield node property_pop_dot attr (property_pop) node_definition = @property attr (property_pop_dot) pop_symbol = "GUARD:MEMBER" - node assignment_expr_guard_default - attr (assignment_expr_guard_default) pop_symbol = "GUARD:DEFAULT" - edge assignment_expr_guard_default -> property_pop_dot - edge @assignment_expr.exports -> assignment_expr_guard_default + edge @assignment_expr.exports -> property_pop_dot edge property_pop_dot -> property_pop edge property_pop -> @right.value } @@ -3898,14 +3900,14 @@ inherit .return_or_yield (assignment_expression left: (member_expression object:(_)@_module - property:(_)@_exports) + property:(_)@exports) right: (_)@right)@assignment_expr (#eq? @_module "module") - (#eq? @_exports "exports") + (#eq? @exports "exports") ) { node assignment_expr_guard_default - attr (assignment_expr_guard_default) pop_symbol = "GUARD:DEFAULT" + attr (assignment_expr_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @exports edge assignment_expr_guard_default -> @right.value edge @assignment_expr.exports -> assignment_expr_guard_default } @@ -3923,10 +3925,7 @@ inherit .return_or_yield (#eq? @_require "require") ) { - node require_guard_default - attr (require_guard_default) push_symbol = "GUARD:DEFAULT" - edge require_guard_default -> @source.exports - edge @call_expr.value -> require_guard_default + edge @call_expr.value -> @source.exports } diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_default_export_with_ES6_default_import.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_default_export_with_ES6_default_import.js new file mode 100644 index 000000000..5cecaa6f4 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_default_export_with_ES6_default_import.js @@ -0,0 +1,12 @@ +/*--- path: a.js ---*/ + +const f = 5; + +module.exports = f; + +/*--- path: b.js ---*/ + +import g from './a.js'; + +/**/ g; +// ^ defined: 3, 5, 9 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_default_import_of_functions.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_default_import_of_functions.js new file mode 100644 index 000000000..62f351e66 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_default_import_of_functions.js @@ -0,0 +1,15 @@ +/*--- path: a.js ---*/ +module.exports = function () { + +}; + +/*--- path: b.js ---*/ +let mod = require("./a.js"); + +/**/ mod; +// ^ defined: 2, 7 + +class Quux { + bar() { + } +} From 1bce68795d94db34dfec41d944fe972b3abfb789 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 9 Oct 2023 21:10:27 +0200 Subject: [PATCH 168/500] Adds current versions of tests, etc. Co-authored-by: Rebecca Valentine --- .../src/stack-graphs.tsg | 158 +++++++++--------- .../name_default_alias_default.js | 14 ++ .../name_default_alias_nondefault.js | 14 ++ .../name_nondefault_alias_default.js | 14 ++ .../unaliased_name_default.js | 14 ++ 5 files changed, 136 insertions(+), 78 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/name_default_alias_default.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/name_default_alias_nondefault.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/name_nondefault_alias_default.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/unaliased_name_default.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index c5822999f..b3f16d696 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -576,82 +576,77 @@ inherit .return_or_yield } +; export { default } from ... +; export { default as ... } from ... ( (export_specifier name:(_)@name - !alias)@export_specifier + )@export_specifier (#not-eq? @name "default") ) { - node name_pop node name_push - - attr (name_pop) node_definition = @name attr (name_push) node_reference = @name - edge name_pop -> name_push + edge @export_specifier.pop -> name_push edge name_push -> @export_specifier.source - edge @export_specifier.exports -> name_pop } +; export { foo } from ... +; export { foo as ... } from ... ( (export_specifier name:(_)@name - alias:(_)@alias)@export_specifier - - (#not-eq? @alias "default") + )@export_specifier + (#eq? @name "default") ) { - node alias_pop - node name_push - - attr (alias_pop) node_definition = @alias - attr (name_push) node_reference = @name - edge alias_pop -> name_push - edge name_push -> @export_specifier.source + node export_specifier_push_guard_default + attr (export_specifier_push_guard_default) symbol_reference = "GUARD:DEFAULT", source_node = @name + edge @export_specifier.pop -> export_specifier_push_guard_default + edge export_specifier_push_guard_default -> @export_specifier.source - edge @export_specifier.exports -> alias_pop } -( - (export_specifier - name:(_)@name - !alias)@export_specifier - - (#eq? @name "default") +; export { foo } from ... +; export { ... as foo } from ... +( [ + (export_specifier + name:(_)@alias + !alias)@export_specifier + (export_specifier + name:(_) + alias:(_)@alias)@export_specifier + ] + (#not-eq? @alias "default") ) { - node export_specifier_pop_guard_default - node export_specifier_push_guard_default - - attr (export_specifier_pop_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @name - attr (export_specifier_push_guard_default) symbol_reference = "GUARD:DEFAULT", source_node = @name - edge @export_specifier.exports -> export_specifier_pop_guard_default - edge export_specifier_pop_guard_default -> export_specifier_push_guard_default - edge export_specifier_push_guard_default -> @export_specifier.source + node @export_specifier.pop + attr (@export_specifier.pop) node_definition = @alias + edge @export_specifier.exports -> @export_specifier.pop } -( - (export_specifier - name:(_)@name - alias:(_)@alias)@export_specifier +; export { default } from ... +; export { ... as default } from ... +( [ + (export_specifier + name:(_)@alias + !alias)@export_specifier + (export_specifier + name:(_) + alias:(_)@alias)@export_specifier + ] (#eq? @alias "default") - ) { - node export_specifier_guard_default - node name_push - - attr (name_push) push_node = @name - attr (export_specifier_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @alias - edge name_push -> @export_specifier.source - edge export_specifier_guard_default -> name_push - edge @export_specifier.exports -> export_specifier_guard_default + node @export_specifier.pop + attr (@export_specifier.pop) symbol_definition = "GUARD:DEFAULT", source_node = @alias + edge @export_specifier.exports -> @export_specifier.pop } @@ -747,13 +742,10 @@ inherit .return_or_yield ] { node source_push_guard_exports - node source_push_guard_default node source_push_guard_pkg node @source.exports attr (source_push_guard_exports) push_symbol = "GUARD:EXPORTS" - attr (source_push_guard_default) push_symbol = "GUARD:DEFAULT" - edge source_push_guard_default -> source_push_guard_exports scan (source-text @source) { "^[\"']((\.|\.\.)/.*)[\"']$" { @@ -784,7 +776,6 @@ inherit .return_or_yield attr (push_start) is_reference, source_node = @source edge @source.exports -> source_push_guard_exports - edge @source.exports -> source_push_guard_default edge source_push_guard_exports -> push_start edge source_push_end -> @source.pkg_push } @@ -807,7 +798,6 @@ inherit .return_or_yield } edge @source.exports -> source_push_guard_exports - edge @source.exports -> source_push_guard_default edge source_push_guard_exports -> push_start edge source_push_end -> source_push_guard_pkg attr (source_push_guard_pkg) push_symbol = "GUARD:PKG" @@ -3109,6 +3099,8 @@ inherit .return_or_yield attr (@assignment_expr.pop) node_definition = @left edge @assignment_expr.after_scope -> @assignment_expr.pop edge @assignment_expr.pop -> @right.value + + ; ensure the scope flows through the identifier edge @assignment_expr.after_scope -> @right.after_scope } @@ -3840,26 +3832,6 @@ inherit .return_or_yield } -;; ## ES6-style Imports - -;; ES6 modules can also be imported using an import function. In general, -;; these look like `import(expr)`, but in practice the expression is a string -;; constant, which is the only case we handle. - -( - (call_expression - function:(_)@_import - arguments:(arguments (string)@source))@call_expr - (#eq? @_import "import") -) { - - node call_expr_pop_dot - - attr (call_expr_pop_dot) pop_symbol = "GUARD:MEMBER" - edge @call_expr.value -> call_expr_pop_dot - edge call_expr_pop_dot -> @source.exports -} - ;; ### CommonJS-style Exports ;; CommonJS introduced an export style for pre-ES6 JavaScript that permitted @@ -3880,20 +3852,24 @@ inherit .return_or_yield ( (assignment_expression left: (member_expression - object:(identifier)@_exports + object:(identifier)@exports property:(_)@property) right: (_)@right)@assignment_expr - (#eq? @_exports "exports") + (#eq? @exports "exports") ) { - node property_pop node property_pop_dot + node assignment_expr_guard_default + attr (property_pop) node_definition = @property attr (property_pop_dot) pop_symbol = "GUARD:MEMBER" - edge @assignment_expr.exports -> property_pop_dot - edge property_pop_dot -> property_pop edge property_pop -> @right.value + edge property_pop_dot -> property_pop + attr (assignment_expr_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @exports + edge assignment_expr_guard_default -> property_pop_dot + edge @assignment_expr.exports -> assignment_expr_guard_default + } ( @@ -3907,25 +3883,51 @@ inherit .return_or_yield ) { node assignment_expr_guard_default + attr (assignment_expr_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @exports edge assignment_expr_guard_default -> @right.value edge @assignment_expr.exports -> assignment_expr_guard_default + edge @assignment_expr.exports -> @right.value + +} + +;; ## ES6-style Imports + +;; ES6 modules can also be imported using an import function. In general, +;; these look like `import(expr)`, but in practice the expression is a string +;; constant, which is the only case we handle. + +( + (call_expression + function:(_)@_import + arguments:(arguments (string)@source))@call_expr + (#eq? @_import "import") +) { + + node call_expr_pop_dot + + attr (call_expr_pop_dot) pop_symbol = "GUARD:MEMBER" + edge @call_expr.value -> call_expr_pop_dot + edge call_expr_pop_dot -> @source.exports } ;; ## CommonJS-style Imports ;; Similar to exports, CommonJS also defines a way to do imports. In general, ;; these look like `require(expr)`, but in practice the expression is a string -;; constant, which is the only case we hand. +;; constant, which is the only case we handle. ( (call_expression - function:(_)@_require + function:(_)@require arguments:(arguments (string)@source))@call_expr - (#eq? @_require "require") + (#eq? @require "require") ) { - edge @call_expr.value -> @source.exports + node default_guard_push + attr (default_guard_push) symbol_reference = "GUARD:DEFAULT", source_node = @require + edge @call_expr.value -> default_guard_push + edge default_guard_push -> @source.exports } diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/name_default_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/name_default_alias_default.js new file mode 100644 index 000000000..9febf034b --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/name_default_alias_default.js @@ -0,0 +1,14 @@ +/*--- path: a.js ---*/ + +export default 1; + +/*--- path: b.js ---*/ + +export { default as default } from "./a.js"; + +/*--- path: c.js ---*/ + +import foo from "./b.js"; + +/**/ foo; +// ^ defined: 3, 7, 11 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/name_default_alias_nondefault.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/name_default_alias_nondefault.js new file mode 100644 index 000000000..108abcf58 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/name_default_alias_nondefault.js @@ -0,0 +1,14 @@ +/*--- path: a.js ---*/ + +export default 1; + +/*--- path: b.js ---*/ + +export { default as foo } from "./a.js"; + +/*--- path: c.js ---*/ + +import { foo } from "./b.js"; + +/**/ foo; +// ^ defined: 3, 7, 11 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/name_nondefault_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/name_nondefault_alias_default.js new file mode 100644 index 000000000..3af922d65 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/name_nondefault_alias_default.js @@ -0,0 +1,14 @@ +/*--- path: a.js ---*/ + +export let foo = 1; + +/*--- path: b.js ---*/ + +export { foo as default } from "./a.js"; + +/*--- path: c.js ---*/ + +import bar from "./b.js"; + +/**/ bar; +// ^ defined: 3, 7, 11 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/unaliased_name_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/unaliased_name_default.js new file mode 100644 index 000000000..7f4853703 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/unaliased_name_default.js @@ -0,0 +1,14 @@ +/*--- path: a.js ---*/ + +export default 1; + +/*--- path: b.js ---*/ + +export { default } from "./a.js"; + +/*--- path: c.js ---*/ + +import foo from "./b.js"; + +/**/ foo; +// ^ defined: 3, 7, 11 From 5e978ce400188d52b66e62822fafc4ae19d0bfd7 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 10 Oct 2023 11:03:58 +0200 Subject: [PATCH 169/500] Reorgs Co-authored-by: Rebecca Valentine --- .../name_default_alias_default.js | 0 .../name_default_alias_nondefault.js | 0 .../name_nondefault_alias_default.js | 0 .../unaliased_name_default.js | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/{ES6_exports_using_the_name_or_alias_default => ES6_imports_and_exports_using_the_name_or_alias_default}/name_default_alias_default.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/{ES6_exports_using_the_name_or_alias_default => ES6_imports_and_exports_using_the_name_or_alias_default}/name_default_alias_nondefault.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/{ES6_exports_using_the_name_or_alias_default => ES6_imports_and_exports_using_the_name_or_alias_default}/name_nondefault_alias_default.js (100%) rename languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/{ES6_exports_using_the_name_or_alias_default => ES6_imports_and_exports_using_the_name_or_alias_default}/unaliased_name_default.js (100%) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/name_default_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/name_default_alias_default.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/name_default_alias_default.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/name_default_alias_default.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/name_default_alias_nondefault.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/name_default_alias_nondefault.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/name_default_alias_nondefault.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/name_default_alias_nondefault.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/name_nondefault_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/name_nondefault_alias_default.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/name_nondefault_alias_default.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/name_nondefault_alias_default.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/unaliased_name_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/unaliased_name_default.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_exports_using_the_name_or_alias_default/unaliased_name_default.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/unaliased_name_default.js From 664772ed8e815830180f887f4aafac3c2123b2a2 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 10 Oct 2023 11:15:04 +0200 Subject: [PATCH 170/500] Reorg (cont.) Co-authored-by: Rebecca Valentine --- ...alias_default.js => export_with_name_default_alias_default.js} | 0 ...nondefault.js => export_with_name_default_alias_nondefault.js} | 0 ...as_default.js => export_with_name_nondefault_alias_default.js} | 0 ...ased_name_default.js => export_with_unaliased_name_default.js} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/{name_default_alias_default.js => export_with_name_default_alias_default.js} (100%) rename languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/{name_default_alias_nondefault.js => export_with_name_default_alias_nondefault.js} (100%) rename languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/{name_nondefault_alias_default.js => export_with_name_nondefault_alias_default.js} (100%) rename languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/{unaliased_name_default.js => export_with_unaliased_name_default.js} (100%) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/name_default_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/export_with_name_default_alias_default.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/name_default_alias_default.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/export_with_name_default_alias_default.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/name_default_alias_nondefault.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/export_with_name_default_alias_nondefault.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/name_default_alias_nondefault.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/export_with_name_default_alias_nondefault.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/name_nondefault_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/export_with_name_nondefault_alias_default.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/name_nondefault_alias_default.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/export_with_name_nondefault_alias_default.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/unaliased_name_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/export_with_unaliased_name_default.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/unaliased_name_default.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/export_with_unaliased_name_default.js From ecba922a5b9cbb93b4c039ba1d6ff6704b53ad33 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 10 Oct 2023 11:34:26 +0200 Subject: [PATCH 171/500] Adds default import test & Fixes bugs Co-authored-by: Rebecca Valentine --- .../src/stack-graphs.tsg | 70 ++++++++++++------- .../export_with_name_default_alias_default.js | 4 +- ...port_with_name_default_alias_nondefault.js | 10 +++ 3 files changed, 58 insertions(+), 26 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/import_with_name_default_alias_nondefault.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index b3f16d696..3bfd69b77 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -917,54 +917,76 @@ inherit .return_or_yield node @import_specifier.after_scope node @import_specifier.before_scope node @import_specifier.source + + edge @import_specifier.after_scope -> @import_specifier.before_scope } ( - (import_specifier name:(_)@name - !alias)@import_specifier + )@import_specifier (#not-eq? @name "default") - ) { - node name_pop - node name_push - - edge @import_specifier.after_scope -> @import_specifier.before_scope + node @import_specifier.push - attr (name_pop) node_definition = @name - attr (name_push) node_reference = @name - edge name_pop -> name_push - edge name_push -> @import_specifier.source - edge @import_specifier.after_scope -> name_pop + attr (@import_specifier.push) node_reference = @name + edge @import_specifier.push -> @import_specifier.source } ( - (import_specifier name:(_)@name - alias:(_)@alias)@import_specifier - - (#not-eq? @name "default") + )@import_specifier + (#eq? @name "default") ) { - node alias_pop - node name_push + node @import_specifier.push - edge @import_specifier.after_scope -> @import_specifier.before_scope + attr (@import_specifier.push) symbol_reference = "GUARD:DEFAULT", source_node = @name + edge @import_specifier.push -> @import_specifier.source - attr (alias_pop) node_definition = @alias - attr (name_push) node_reference = @name - edge alias_pop -> name_push - edge name_push -> @import_specifier.source - edge @import_specifier.after_scope -> alias_pop +} + +( [ + (import_specifier + name:(_)@alias + !alias)@import_specifier + (import_specifier + name:(_) + alias:(_)@alias)@import_specifier + ] + + (#not-eq? @alias "default") +) { + + node name_pop + + attr (name_pop) node_definition = @alias + edge name_pop -> @import_specifier.push + edge @import_specifier.after_scope -> name_pop } +; ( [ +; (import_specifier +; name:(_)@alias +; !alias)@import_specifier +; (import_specifier +; name:(_) +; alias:(_)@alias)@import_specifier +; ] +; +; (#eq? @name "default") +; ) { +; +; ;; IMPOSSIBLE SHOULD, NEVER HAPPEN +; +; } + ; (import_statement ; (import_clause ; (named_imports diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/export_with_name_default_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/export_with_name_default_alias_default.js index 9febf034b..2dcd4f19f 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/export_with_name_default_alias_default.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/export_with_name_default_alias_default.js @@ -8,7 +8,7 @@ export { default as default } from "./a.js"; /*--- path: c.js ---*/ -import foo from "./b.js"; +import bar from "./b.js"; -/**/ foo; +/**/ bar; // ^ defined: 3, 7, 11 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/import_with_name_default_alias_nondefault.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/import_with_name_default_alias_nondefault.js new file mode 100644 index 000000000..d34fd8898 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/import_with_name_default_alias_nondefault.js @@ -0,0 +1,10 @@ +/*--- path: a.js ---*/ + +export default 1; + +/*--- path: b.js ---*/ + +import { default as foo } from "./a.js"; + +/**/ foo; +// ^ defined: 3, 7 From 352530637e7d3010fe348bf204839e1dea6ef651 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 10 Oct 2023 11:45:12 +0200 Subject: [PATCH 172/500] Adds CJS versions of tests Co-authored-by: Rebecca Valentine --- .../export_with_name_default_alias_default.js | 14 ++++++++++++++ .../export_with_name_default_alias_nondefault.js | 14 ++++++++++++++ .../export_with_name_nondefault_alias_default.js | 15 +++++++++++++++ .../import_with_name_default_alias_nondefault.js | 10 ++++++++++ 4 files changed, 53 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_imports_and_exports_using_defaults/export_with_name_default_alias_default.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_imports_and_exports_using_defaults/export_with_name_default_alias_nondefault.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_imports_and_exports_using_defaults/export_with_name_nondefault_alias_default.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_imports_and_exports_using_defaults/import_with_name_default_alias_nondefault.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_imports_and_exports_using_defaults/export_with_name_default_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_imports_and_exports_using_defaults/export_with_name_default_alias_default.js new file mode 100644 index 000000000..97e1f028e --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_imports_and_exports_using_defaults/export_with_name_default_alias_default.js @@ -0,0 +1,14 @@ +/*--- path: a.js ---*/ + +module.exports = 1; + +/*--- path: b.js ---*/ + +module.exports = require("./a.js"); + +/*--- path: c.js ---*/ + +let bar = require("./b.js"); + +/**/ bar; +// ^ defined: 3, 7, 11 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_imports_and_exports_using_defaults/export_with_name_default_alias_nondefault.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_imports_and_exports_using_defaults/export_with_name_default_alias_nondefault.js new file mode 100644 index 000000000..9c7d90fc2 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_imports_and_exports_using_defaults/export_with_name_default_alias_nondefault.js @@ -0,0 +1,14 @@ +/*--- path: a.js ---*/ + +module.exports = 1; + +/*--- path: b.js ---*/ + +exports.foo = require("./a.js"); + +/*--- path: c.js ---*/ + +let { foo } = require("./b.js"); + +/**/ foo; +// ^ defined: 3, 7, 11 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_imports_and_exports_using_defaults/export_with_name_nondefault_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_imports_and_exports_using_defaults/export_with_name_nondefault_alias_default.js new file mode 100644 index 000000000..8b99bd45f --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_imports_and_exports_using_defaults/export_with_name_nondefault_alias_default.js @@ -0,0 +1,15 @@ +/*--- path: a.js ---*/ + +exports.foo = 1; + +/*--- path: b.js ---*/ + +let { foo } = require("./a.js"); +module.exports = foo; + +/*--- path: c.js ---*/ + +let bar = require("./b.js"); + +/**/ bar; +// ^ defined: 3, 7, 8, 12 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_imports_and_exports_using_defaults/import_with_name_default_alias_nondefault.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_imports_and_exports_using_defaults/import_with_name_default_alias_nondefault.js new file mode 100644 index 000000000..d9052a27f --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/CommonJS_imports_and_exports_using_defaults/import_with_name_default_alias_nondefault.js @@ -0,0 +1,10 @@ +/*--- path: a.js ---*/ + +module.exports = 1; + +/*--- path: b.js ---*/ + +let foo = require("./a.js"); + +/**/ foo; +// ^ defined: 3, 7 From 37ef4a2866450360f3ca5292716a101cff3474c4 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 10 Oct 2023 11:47:59 +0200 Subject: [PATCH 173/500] Removes some commented out queries Co-authored-by: Rebecca Valentine --- .../src/stack-graphs.tsg | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 3bfd69b77..944fb9996 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -921,6 +921,17 @@ inherit .return_or_yield edge @import_specifier.after_scope -> @import_specifier.before_scope } +;; The following two cases should never happen in valid code: +;; +;; - aliased name, with alias = `default` +;; - non-aliased name, with name = `default` +;; +;; These are both invalid JavaScript and so should never actually +;; occur in valid code. But, of course, sometimes people write +;; bad code, and also they do parse according to the Tree-sitter +;; grammar. We should never ever match against them and produce +;; any sort of graph components however. + ( (import_specifier name:(_)@name @@ -971,22 +982,6 @@ inherit .return_or_yield } -; ( [ -; (import_specifier -; name:(_)@alias -; !alias)@import_specifier -; (import_specifier -; name:(_) -; alias:(_)@alias)@import_specifier -; ] -; -; (#eq? @name "default") -; ) { -; -; ;; IMPOSSIBLE SHOULD, NEVER HAPPEN -; -; } - ; (import_statement ; (import_clause ; (named_imports From a59505546927347f0e3c559465c7e5db9aa0d94a Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 10 Oct 2023 12:18:29 +0200 Subject: [PATCH 174/500] Adds first vea test Co-authored-by: Rebecca Valentine --- .../export_with_name_default_alias_default.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_default.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_default.js new file mode 100644 index 000000000..a928b3438 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_default.js @@ -0,0 +1,14 @@ +/*--- path: a.js ---*/ + +export default function foo() { } + +/*--- path: index.js ---*/ + +export { default as default } from "./a.js"; + +// --- path: index2.js --- + +import bar from "./index.js"; + +/**/ bar; +// ^ defined: 3, 7, 11 From 8b4bfee5811c4b9f657a2038a72be5bbd53da744 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 10 Oct 2023 11:54:02 +0200 Subject: [PATCH 175/500] Fixes small bug Co-authored-by: Rebecca Valentine --- .../src/stack-graphs.tsg | 11 +++++++++++ ...ort_function_with_name_default_alias_default.js | 14 ++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/export_function_with_name_default_alias_default.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 944fb9996..d25804497 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -486,8 +486,19 @@ inherit .return_or_yield (export_statement (declaration)@decl)@export_stmt { + edge @decl.before_scope -> @export_stmt.before_scope edge @export_stmt.after_scope -> @decl.after_scope + + ; !!!! TODO HACK + ; the tree-sitter grammar doesn't make it possible to distinguish + ; between default exports and non-default exports so this is required + ; to ensure that default exports work properly + node export_stmt_pop_guard_default + attr (export_stmt_pop_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @decl + edge @export_stmt.exports -> export_stmt_pop_guard_default + ;; edge export_stmt_pop_guard_default -> @decl.value ;; FIXME declarations have no .value + } (export_statement diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/export_function_with_name_default_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/export_function_with_name_default_alias_default.js new file mode 100644 index 000000000..bf0ff8f1e --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ES6_imports_and_exports_using_the_name_or_alias_default/export_function_with_name_default_alias_default.js @@ -0,0 +1,14 @@ +/*--- path: a.js ---*/ + +export default function foo() { }; + +/*--- path: b.js ---*/ + +export { default as default } from "./a.js"; + +/*--- path: c.js ---*/ + +import bar from "./b.js"; + +/**/ bar; +// ^ defined: 3, 7, 11 From c4f5b45b3d7ed9ca5983f493818a8341831cefc5 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 10 Oct 2023 12:07:11 +0200 Subject: [PATCH 176/500] Adds bug fixes for transitive callers Co-authored-by: Rebecca Valentine --- .../src/stack-graphs.tsg | 38 +++++++++++++++---- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index d25804497..56489cc70 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -249,7 +249,9 @@ inherit .builtins_string inherit .builtins_undefined inherit .class_value inherit .constructor +inherit .export_statement inherit .exports +inherit .import_statement inherit .pkg_pop inherit .pkg_push inherit .return_or_yield @@ -460,6 +462,10 @@ inherit .return_or_yield ;; #### Export +(export_statement)@export_stmt { + let @export_stmt.export_statement = @export_stmt +} + ; exports of just names ; eg ; export { foo, bar as baz }; @@ -495,7 +501,7 @@ inherit .return_or_yield ; between default exports and non-default exports so this is required ; to ensure that default exports work properly node export_stmt_pop_guard_default - attr (export_stmt_pop_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @decl + attr (export_stmt_pop_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @decl, definiens_node = @export_stmt.export_statement edge @export_stmt.exports -> export_stmt_pop_guard_default ;; edge export_stmt_pop_guard_default -> @decl.value ;; FIXME declarations have no .value @@ -513,6 +519,18 @@ inherit .return_or_yield ; TODO this doesn't support destructuring exports edge @export_stmt.exports -> @name.pop + +} + +; set definiens for exported declarations that do not normally have a definiens associated +(export_statement + declaration: [ + (lexical_declaration (variable_declarator name:(identifier)@name)) + (variable_declaration (variable_declarator name:(identifier)@name)) + ]@decl)@_export_stmt { + + attr (@name.pop) definiens_node = @decl + } ; TODO @@ -636,7 +654,7 @@ inherit .return_or_yield ) { node @export_specifier.pop - attr (@export_specifier.pop) node_definition = @alias + attr (@export_specifier.pop) node_definition = @alias, definiens_node = @export_specifier.export_statement edge @export_specifier.exports -> @export_specifier.pop } @@ -656,7 +674,7 @@ inherit .return_or_yield ) { node @export_specifier.pop - attr (@export_specifier.pop) symbol_definition = "GUARD:DEFAULT", source_node = @alias + attr (@export_specifier.pop) symbol_definition = "GUARD:DEFAULT", source_node = @alias, definiens_node = @export_specifier.export_statement edge @export_specifier.exports -> @export_specifier.pop } @@ -669,7 +687,7 @@ inherit .return_or_yield node export_stmt_default_guard - attr (export_stmt_default_guard) symbol_definition = "GUARD:DEFAULT", source_node = @export_stmt + attr (export_stmt_default_guard) symbol_definition = "GUARD:DEFAULT", source_node = @export_stmt, definiens_node = @export_stmt.export_statement edge @default_expr.before_scope -> @export_stmt.before_scope edge @export_stmt.after_scope -> @default_expr.after_scope edge @export_stmt.exports -> export_stmt_default_guard @@ -702,7 +720,7 @@ inherit .return_or_yield edge @export_statement.after_scope -> @export_statement.before_scope - attr (alias_pop) node_definition = @alias + attr (alias_pop) node_definition = @alias, definiens_node = @export_statement.export_statement attr (alias_pop_dot) pop_symbol = "GUARD:MEMBER" edge @export_statement.exports -> alias_pop edge alias_pop -> alias_pop_dot @@ -745,6 +763,10 @@ inherit .return_or_yield ;; - ES6: https://nodejs.org/api/esm.html, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import ;; - CommonJS: https://nodejs.org/api/modules.html +(import_statement)@import_stmt { + let @import_stmt.import_statement = @import_stmt +} + [ (import_statement source:(_)@source) (export_statement source:(_)@source) @@ -850,7 +872,7 @@ inherit .return_or_yield edge @namespace_import.after_scope -> @namespace_import.before_scope - attr (imported_as_pop) node_definition = @imported_as + attr (imported_as_pop) node_definition = @imported_as, definiens_node = @namespace_import.import_statement attr (imported_as_pop_dot) pop_symbol = "GUARD:MEMBER" edge imported_as_pop -> imported_as_pop_dot edge imported_as_pop_dot -> @namespace_import.source @@ -987,7 +1009,7 @@ inherit .return_or_yield node name_pop - attr (name_pop) node_definition = @alias + attr (name_pop) node_definition = @alias, definiens_node = @import_specifier.import_statement edge name_pop -> @import_specifier.push edge @import_specifier.after_scope -> name_pop @@ -1034,7 +1056,7 @@ inherit .return_or_yield edge @import_clause.after_scope -> @import_clause.before_scope - attr (default_name_pop) node_definition = @default_name + attr (default_name_pop) node_definition = @default_name, definiens_node = @import_clause.import_statement attr (default_name_push_guard_default) symbol_reference = "GUARD:DEFAULT", source_node = @default_name edge default_name_pop -> default_name_push_guard_default edge default_name_push_guard_default -> @import_clause.source From 050a6cbb65a03daccc656e73c245a750bb4d8601 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 10 Oct 2023 13:40:10 +0200 Subject: [PATCH 177/500] Adds some new tests and fixes Co-authored-by: Rebecca Valentine --- .../src/stack-graphs.tsg | 23 +++++++++++++++++++ .../export_with_name_default_alias_default.js | 14 +++++++++++ .../export_with_name_default_alias_default.js | 4 ++-- ...port_with_name_default_alias_nondefault.js | 12 ++++++++++ ...port_with_name_nondefault_alias_default.js | 12 ++++++++++ ...t_with_name_nondefault_alias_nondefault.js | 12 ++++++++++ ...port_with_name_nondefault_alias_default.js | 14 +++++++++++ 7 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/CommonJS_import_export_patterns/export_with_name_default_alias_default.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_nondefault.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_nondefault_alias_default.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_nondefault_alias_nondefault.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/import_with_name_nondefault_alias_default.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 56489cc70..4010eba31 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4118,6 +4118,29 @@ inherit .return_or_yield edge left_ignore_guard -> left_definiens_hook } +( + (assignment_expression + left: (member_expression + object:(identifier)@_object + property:(_)@left + ) + right: (_)@right)@assignment_expr + (#eq @_object "module") + (#eq @left "exports") +) { + + node left_definiens_hook + node left_ignore_guard + + attr (left_ignore_guard) pop_symbol = "GUARD:GANDALF" + attr (left_definiens_hook) node_definition = @left + attr (left_definiens_hook) definiens_node = @right + attr (left_definiens_hook) syntax_type = "function" + edge @assignment_expr.pkg_pop -> left_ignore_guard + edge left_ignore_guard -> left_definiens_hook + +} + (variable_declaration (variable_declarator name:(identifier)@name diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/CommonJS_import_export_patterns/export_with_name_default_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/CommonJS_import_export_patterns/export_with_name_default_alias_default.js new file mode 100644 index 000000000..26cd74c45 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/CommonJS_import_export_patterns/export_with_name_default_alias_default.js @@ -0,0 +1,14 @@ +/*--- path: a.js ---*/ + +module.exports = function foo() { }; + +/*--- path: index.js ---*/ + +module.exports = require("./a.js"); + +/*--- path: index2.js ---*/ + +let bar = require("./index.js"); + +/**/ bar; +// ^ defined: 3, 7, 11 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_default.js index a928b3438..33dbb2713 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_default.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_default.js @@ -6,9 +6,9 @@ export default function foo() { } export { default as default } from "./a.js"; -// --- path: index2.js --- +/*--- path: index2.js ---*/ import bar from "./index.js"; /**/ bar; -// ^ defined: 3, 7, 11 +// ^ defined: 3, 7, 11 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_nondefault.js b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_nondefault.js new file mode 100644 index 000000000..4e0b9ab39 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_nondefault.js @@ -0,0 +1,12 @@ +/*--- path: a.js ---*/ + +export default function foo() { } + +/*--- path: index.js ---*/ + +export { default as bar } from "./a.js"; + +// --- path: index2.js --- + +import { bar } from "./index.js"; +// ^ defined: 3, 7 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_nondefault_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_nondefault_alias_default.js new file mode 100644 index 000000000..574df9d55 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_nondefault_alias_default.js @@ -0,0 +1,12 @@ +/*--- path: a.js ---*/ + +export function foo() { } + +/*--- path: index.js ---*/ + +export { foo as default } from "./a.js"; + +/*--- path: index2.js ---*/ + +import bar from "./index.js"; +// ^ defined: 3, 7 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_nondefault_alias_nondefault.js b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_nondefault_alias_nondefault.js new file mode 100644 index 000000000..4b3c50203 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_nondefault_alias_nondefault.js @@ -0,0 +1,12 @@ +/*--- path: a.js ---*/ + +export function foo() { } + +/*--- path: index.js ---*/ + +export { foo as bar } from "./a.js"; + +/*--- path: index2.js ---*/ + +import { bar } from "./index"; +// ^ defined: 3, 7 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/import_with_name_nondefault_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/import_with_name_nondefault_alias_default.js new file mode 100644 index 000000000..02178ff18 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/import_with_name_nondefault_alias_default.js @@ -0,0 +1,14 @@ +/*--- path: a.js ---*/ + +export default function foo() { } + +/*--- path: index.js ---*/ + +import { default as foo } from "./a.js"; + +export { foo }; + +/*--- path: index2.js ---*/ + +import { foo } from "./index.js"; +// ^ defined: 3, 7, 9 \ No newline at end of file From f6a6b0851fab87f54afe5c0fc7f396d63f5146b5 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 11 Oct 2023 11:35:16 +0200 Subject: [PATCH 178/500] Removes no-longer-needed definition baselines Co-authored-by: Rebecca Valentine --- .../test/old/binding/simple.js | 10 ---------- .../export_with_name_default_alias_default.js | 14 -------------- .../export_with_name_default_alias_default.js | 14 -------------- .../export_with_name_default_alias_nondefault.js | 12 ------------ .../export_with_name_nondefault_alias_default.js | 12 ------------ ...export_with_name_nondefault_alias_nondefault.js | 12 ------------ .../import_with_name_nondefault_alias_default.js | 14 -------------- 7 files changed, 88 deletions(-) delete mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/binding/simple.js delete mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/CommonJS_import_export_patterns/export_with_name_default_alias_default.js delete mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_default.js delete mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_nondefault.js delete mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_nondefault_alias_default.js delete mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_nondefault_alias_nondefault.js delete mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/import_with_name_nondefault_alias_default.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/binding/simple.js b/languages/tree-sitter-stack-graphs-javascript/test/old/binding/simple.js deleted file mode 100644 index 5f504b306..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/binding/simple.js +++ /dev/null @@ -1,10 +0,0 @@ -var x = 1; -let y = 2; -const z = 3; - -/**/ x; -// ^ defined: 1 -/**/ y; -// ^ defined: 2 -/**/ z; -// ^ defined: 3 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/CommonJS_import_export_patterns/export_with_name_default_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/CommonJS_import_export_patterns/export_with_name_default_alias_default.js deleted file mode 100644 index 26cd74c45..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/CommonJS_import_export_patterns/export_with_name_default_alias_default.js +++ /dev/null @@ -1,14 +0,0 @@ -/*--- path: a.js ---*/ - -module.exports = function foo() { }; - -/*--- path: index.js ---*/ - -module.exports = require("./a.js"); - -/*--- path: index2.js ---*/ - -let bar = require("./index.js"); - -/**/ bar; -// ^ defined: 3, 7, 11 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_default.js deleted file mode 100644 index 33dbb2713..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_default.js +++ /dev/null @@ -1,14 +0,0 @@ -/*--- path: a.js ---*/ - -export default function foo() { } - -/*--- path: index.js ---*/ - -export { default as default } from "./a.js"; - -/*--- path: index2.js ---*/ - -import bar from "./index.js"; - -/**/ bar; -// ^ defined: 3, 7, 11 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_nondefault.js b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_nondefault.js deleted file mode 100644 index 4e0b9ab39..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_default_alias_nondefault.js +++ /dev/null @@ -1,12 +0,0 @@ -/*--- path: a.js ---*/ - -export default function foo() { } - -/*--- path: index.js ---*/ - -export { default as bar } from "./a.js"; - -// --- path: index2.js --- - -import { bar } from "./index.js"; -// ^ defined: 3, 7 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_nondefault_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_nondefault_alias_default.js deleted file mode 100644 index 574df9d55..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_nondefault_alias_default.js +++ /dev/null @@ -1,12 +0,0 @@ -/*--- path: a.js ---*/ - -export function foo() { } - -/*--- path: index.js ---*/ - -export { foo as default } from "./a.js"; - -/*--- path: index2.js ---*/ - -import bar from "./index.js"; -// ^ defined: 3, 7 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_nondefault_alias_nondefault.js b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_nondefault_alias_nondefault.js deleted file mode 100644 index 4b3c50203..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/export_with_name_nondefault_alias_nondefault.js +++ /dev/null @@ -1,12 +0,0 @@ -/*--- path: a.js ---*/ - -export function foo() { } - -/*--- path: index.js ---*/ - -export { foo as bar } from "./a.js"; - -/*--- path: index2.js ---*/ - -import { bar } from "./index"; -// ^ defined: 3, 7 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/import_with_name_nondefault_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/import_with_name_nondefault_alias_default.js deleted file mode 100644 index 02178ff18..000000000 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/vea_validation_definition_baselines/ES6_import_export_patterns/import_with_name_nondefault_alias_default.js +++ /dev/null @@ -1,14 +0,0 @@ -/*--- path: a.js ---*/ - -export default function foo() { } - -/*--- path: index.js ---*/ - -import { default as foo } from "./a.js"; - -export { foo }; - -/*--- path: index2.js ---*/ - -import { foo } from "./index.js"; -// ^ defined: 3, 7, 9 \ No newline at end of file From b2f53702642ad8c14e38158d94bbd5e632cb5ddb Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 11 Oct 2023 11:41:30 +0200 Subject: [PATCH 179/500] Adds more tests and some bug fixes Co-authored-by: Rebecca Valentine --- .../src/stack-graphs.tsg | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 4010eba31..fe4354358 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -522,17 +522,6 @@ inherit .return_or_yield } -; set definiens for exported declarations that do not normally have a definiens associated -(export_statement - declaration: [ - (lexical_declaration (variable_declarator name:(identifier)@name)) - (variable_declaration (variable_declarator name:(identifier)@name)) - ]@decl)@_export_stmt { - - attr (@name.pop) definiens_node = @decl - -} - ; TODO ; export let [x,y] = [1,2]; (export_statement @@ -4141,6 +4130,22 @@ inherit .return_or_yield } +(variable_declaration + (variable_declarator + name:(identifier)@name))@decl { + + attr (@name.pop) definiens_node = @decl + +} + +(lexical_declaration + (variable_declarator + name:(identifier)@name))@decl { + + attr (@name.pop) definiens_node = @decl + +} + (variable_declaration (variable_declarator name:(identifier)@name @@ -4149,9 +4154,8 @@ inherit .return_or_yield (generator_function) (arrow_function) (class) - ]@initializer)) { + ])) { - attr (@name.pop) definiens_node = @initializer attr (@name.pop) syntax_type = "function" } @@ -4164,9 +4168,8 @@ inherit .return_or_yield (generator_function) (arrow_function) (class) - ]@initializer)) { + ])) { - attr (@name.pop) definiens_node = @initializer attr (@name.pop) syntax_type = "function" } From 5c817dc2a6d5e27f7a78be4bfe55376aceb2308c Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 11 Oct 2023 12:52:08 +0200 Subject: [PATCH 180/500] Reorgs and fixes some bugs Co-authored-by: Rebecca Valentine --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index fe4354358..c5dda28e5 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -288,6 +288,7 @@ inherit .return_or_yield node prog_module_pop node prog_module_scope node prog_exports_pop + node prog_exports_pop_dot node prog_pkg_pop_guard node prog_pkg_push_guard node prog_legacy_qname_guard @@ -342,6 +343,9 @@ inherit .return_or_yield attr (prog_exports_pop) pop_symbol = "GUARD:EXPORTS" edge module_pop_end -> prog_exports_pop edge prog_exports_pop -> @prog.exports + attr (prog_exports_pop_dot) pop_symbol = "GUARD:MEMBER" + edge prog_exports_pop -> prog_exports_pop_dot + edge prog_exports_pop_dot -> @prog.exports ; allow direct access from the package to the modules exports ; this is used from package.json From fec4e4574541b8a5c7b2c7f62da5385839ca1e79 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Oct 2023 11:45:07 +0200 Subject: [PATCH 181/500] Add remaining tests and bug fixes Co-authored-by: Rebecca Valentine --- .../src/stack-graphs.tsg | 152 ++++++++++++------ .../export_with_name_default.js | 11 ++ .../export_with_name_nondefault.js | 10 ++ ...port_with_name_default_alias_nondefault.js | 16 ++ ...eexport_with_name_default_alias_default.js | 15 ++ ...port_with_name_default_alias_nondefault.js | 14 ++ ...port_with_name_nondefault_alias_default.js | 15 ++ ...t_with_name_nondefault_alias_nondefault.js | 14 ++ .../reexport_with_unaliased_name.js | 14 ++ .../export_with_name_default.js | 18 +++ .../export_with_name_nondefault.js | 17 ++ ...port_with_name_default_alias_nondefault.js | 22 +++ ...eexport_with_name_default_alias_default.js | 23 +++ ...port_with_name_default_alias_nondefault.js | 22 +++ ...port_with_name_nondefault_alias_default.js | 23 +++ ...t_with_name_nondefault_alias_nondefault.js | 22 +++ .../reexport_with_unaliased_name.js | 21 +++ ...iable_visible_through_nonbinding_import.js | 6 + 18 files changed, 389 insertions(+), 46 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/export_with_name_default.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/export_with_name_nondefault.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/import_with_name_default_alias_nondefault.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_name_default_alias_default.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_name_default_alias_nondefault.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_name_nondefault_alias_default.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_name_nondefault_alias_nondefault.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_unaliased_name.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/export_with_name_default.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/export_with_name_nondefault.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/import_with_name_default_alias_nondefault.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_name_default_alias_default.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_name_default_alias_nondefault.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_name_nondefault_alias_default.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_name_nondefault_alias_nondefault.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_unaliased_name.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/variable_visible_through_nonbinding_import.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index c5dda28e5..eb86ac913 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -288,7 +288,6 @@ inherit .return_or_yield node prog_module_pop node prog_module_scope node prog_exports_pop - node prog_exports_pop_dot node prog_pkg_pop_guard node prog_pkg_push_guard node prog_legacy_qname_guard @@ -343,9 +342,6 @@ inherit .return_or_yield attr (prog_exports_pop) pop_symbol = "GUARD:EXPORTS" edge module_pop_end -> prog_exports_pop edge prog_exports_pop -> @prog.exports - attr (prog_exports_pop_dot) pop_symbol = "GUARD:MEMBER" - edge prog_exports_pop -> prog_exports_pop_dot - edge prog_exports_pop_dot -> @prog.exports ; allow direct access from the package to the modules exports ; this is used from package.json @@ -801,7 +797,6 @@ inherit .return_or_yield } attr (push_start) is_reference, source_node = @source - edge @source.exports -> source_push_guard_exports edge source_push_guard_exports -> push_start edge source_push_end -> @source.pkg_push } @@ -823,13 +818,15 @@ inherit .return_or_yield } } - edge @source.exports -> source_push_guard_exports edge source_push_guard_exports -> push_start edge source_push_end -> source_push_guard_pkg attr (source_push_guard_pkg) push_symbol = "GUARD:PKG" edge source_push_guard_pkg -> @source.pkg_push } } + + edge @source.exports -> source_push_guard_exports + } ; import "foo.js"; @@ -3894,24 +3891,43 @@ inherit .return_or_yield ( (assignment_expression - left: (member_expression - object:(identifier)@exports - property:(_)@property) + left: [ + ( ; exports.foo = ... + (member_expression + object:(identifier)@exports + property:(_)@property) + (#eq? @exports "exports") + ) + ( ; module.exports.foo = ... + (member_expression + object:(member_expression + object:(identifier)@_module + property:(_)@exports) + property:(_)@property) + (#eq? @_module "module") + (#eq? @exports "exports") + ) + ] right: (_)@right)@assignment_expr - (#eq? @exports "exports") + ) { - node property_pop - node property_pop_dot - node assignment_expr_guard_default + node pop_default_guard + node pop_dot + node pop_name - attr (property_pop) node_definition = @property - attr (property_pop_dot) pop_symbol = "GUARD:MEMBER" - edge property_pop -> @right.value - edge property_pop_dot -> property_pop - attr (assignment_expr_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @exports - edge assignment_expr_guard_default -> property_pop_dot - edge @assignment_expr.exports -> assignment_expr_guard_default + attr (pop_default_guard) symbol_definition = "GUARD:DEFAULT", source_node = @exports + edge @assignment_expr.exports -> pop_default_guard + + attr (pop_dot) pop_symbol = "GUARD:MEMBER" + edge pop_default_guard -> pop_dot + + attr (pop_name) node_definition = @property + edge pop_dot -> pop_name + edge pop_name -> @right.value + + ;; For ES6 interoperability, expose members as named exports + edge @assignment_expr.exports -> pop_name } @@ -3925,36 +3941,21 @@ inherit .return_or_yield (#eq? @exports "exports") ) { - node assignment_expr_guard_default - - attr (assignment_expr_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @exports - edge assignment_expr_guard_default -> @right.value - edge @assignment_expr.exports -> assignment_expr_guard_default - edge @assignment_expr.exports -> @right.value + node pop_default_guard + node pop_dot -} - -;; ## ES6-style Imports + attr (pop_default_guard) symbol_definition = "GUARD:DEFAULT", source_node = @exports + edge @assignment_expr.exports -> pop_default_guard + edge pop_default_guard -> @right.value -;; ES6 modules can also be imported using an import function. In general, -;; these look like `import(expr)`, but in practice the expression is a string -;; constant, which is the only case we handle. + ;; For ES6 interoperability, expose members as named exports + attr (pop_dot) pop_symbol = "GAURD:MEMBER" + edge @assignment_expr.exports -> pop_dot + edge pop_dot -> @right.value -( - (call_expression - function:(_)@_import - arguments:(arguments (string)@source))@call_expr - (#eq? @_import "import") -) { - - node call_expr_pop_dot - - attr (call_expr_pop_dot) pop_symbol = "GUARD:MEMBER" - edge @call_expr.value -> call_expr_pop_dot - edge call_expr_pop_dot -> @source.exports } -;; ## CommonJS-style Imports +;; ### CommonJS-style Imports ;; Similar to exports, CommonJS also defines a way to do imports. In general, ;; these look like `require(expr)`, but in practice the expression is a string @@ -3962,19 +3963,78 @@ inherit .return_or_yield ( (call_expression - function:(_)@require + function:(identifier)@require arguments:(arguments (string)@source))@call_expr (#eq? @require "require") ) { node default_guard_push + attr (default_guard_push) symbol_reference = "GUARD:DEFAULT", source_node = @require edge @call_expr.value -> default_guard_push edge default_guard_push -> @source.exports + } +;; ### Dynamic Imports + +;; Both ES6 and CommonJS modules can be imported using an import function. +;; In general, these look like `import(expr)`, but in practice the expression +;; is a string constant, which is the only case we handle. +;; +;; The return value of the import function is an object whose properties are +;; the exports of the module. The default export is assigned to the `default` +;; property. +;; +;; The import function is async and returns a promise. Since we do not support +;; async functions and promises, we only support the case where the function +;; is called as `await import(...)`. + +( + (await_expression + (call_expression + function:(_)@_import + arguments:(arguments (string)@source)) + )@await_expr + (#eq? @_import "import") +) { + node pop_dot + node pop_default + node push_guard_default + attr (pop_dot) pop_symbol = "GUARD:MEMBER" + edge @await_expr.value -> pop_dot + edge pop_dot -> @source.exports + + attr (pop_default) pop_symbol = "default" + edge pop_dot -> pop_default + + attr (push_guard_default) push_symbol = "GUARD:DEFAULT" + edge pop_default -> push_guard_default + edge push_guard_default -> @source.exports + +} + +;; ### ES6 and CommonJS interoperability + +;; Nodes supports some interoperability between ES6 and CommonJS modules. +;; +;; A CommonJS module can be imported in an ES6 module: +;; +;; - `import foo from "cjs_module"` binds `foo` to the value of `module.exports`. +;; - `import { foo } from "cjs_module"` binds `foo` to the value of `module.exports.foo`. +;; - `import("cjs_module")` returns (a promise to) an object with +;; - property `default` bound to the value of `module.exports`, and +;; - other properties bound to the value of those properties in `module.exports` +;; (e.g., `foo` binds `module.exports.foo`). +;; +;; A ES6 module can be import in an CommonJS module: +;; +;; - `import("es6_module")` returns (a promise to) an object with +;; - property default bound to the value of `export default`, and +;; - other properties bound to named exports (e.g., `foo` binds `export { foo }`). +;; - `require("es6_module")` is not supported. diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/export_with_name_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/export_with_name_default.js new file mode 100644 index 000000000..cb450bf73 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/export_with_name_default.js @@ -0,0 +1,11 @@ +/*--- path: index.js ---*/ + +export default function foo() { } + +/*--- path: index2.js ---*/ + +let bar = await import("./index.js"); + +/**/ bar.default; +// ^ defined: 7 +// ^ defined: 3 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/export_with_name_nondefault.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/export_with_name_nondefault.js new file mode 100644 index 000000000..6c4ed5062 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/export_with_name_nondefault.js @@ -0,0 +1,10 @@ +/*--- path: index.js ---*/ + +export function foo() { } + +/*--- path: index2.js ---*/ + +let { foo } = await import("./index.js"); + +/**/ foo; +// ^ defined: 3, 7 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/import_with_name_default_alias_nondefault.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/import_with_name_default_alias_nondefault.js new file mode 100644 index 000000000..2c12f935f --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/import_with_name_default_alias_nondefault.js @@ -0,0 +1,16 @@ +/*--- path: a.js ---*/ + +export default function foo() { } + +/*--- path: index.js ---*/ + +import { default as bar } from "./a.js"; + +export { bar }; + +/*--- path: index2.js ---*/ + +let { bar } = await import("./index.js"); + +/**/ bar; +// ^ defined: 3, 7, 9, 13 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_name_default_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_name_default_alias_default.js new file mode 100644 index 000000000..cee2ee151 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_name_default_alias_default.js @@ -0,0 +1,15 @@ +/*--- path: a.js ---*/ + +export default function foo() { } + +/*--- path: index.js ---*/ + +export { default as default } from "./a.js"; + +/*--- path: index2.js ---*/ + +let bar = await import("./index.js"); + +/**/ bar.default; +// ^ defined: 11 +// ^ defined: 3, 7 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_name_default_alias_nondefault.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_name_default_alias_nondefault.js new file mode 100644 index 000000000..e99346fa5 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_name_default_alias_nondefault.js @@ -0,0 +1,14 @@ +/*--- path: a.js ---*/ + +export default function foo() { } + +/*--- path: index.js ---*/ + +export { default as bar } from "./a.js"; + +/*--- path: index2.js ---*/ + +let { bar } = await import("./index.js"); + +/**/ bar; +// ^ defined: 3, 7, 11 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_name_nondefault_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_name_nondefault_alias_default.js new file mode 100644 index 000000000..99e922f17 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_name_nondefault_alias_default.js @@ -0,0 +1,15 @@ +/*--- path: a.js ---*/ + +export function foo() { } + +/*--- path: index.js ---*/ + +export { foo as default } from "./a.js"; + +/*--- path: index2.js ---*/ + +let bar = await import("./index.js"); + +/**/ bar.default; +// ^ defined: 11 +// ^ defined: 3, 7 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_name_nondefault_alias_nondefault.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_name_nondefault_alias_nondefault.js new file mode 100644 index 000000000..a806336b8 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_name_nondefault_alias_nondefault.js @@ -0,0 +1,14 @@ +/*--- path: a.js ---*/ + +export function foo() { } + +/*--- path: index.js ---*/ + +export { foo as bar } from "./a.js"; + +/*--- path: index2.js ---*/ + +let { bar } = await import("./index.js"); + +/**/ bar; +// ^ defined: 3, 7, 11 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_unaliased_name.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_unaliased_name.js new file mode 100644 index 000000000..18bbc303c --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/reexport_with_unaliased_name.js @@ -0,0 +1,14 @@ +/*--- path: a.js ---*/ + +export function foo() { } + +/*--- path: index.js ---*/ + +export { foo } from "./a.js"; + +/*--- path: index2.js ---*/ + +let { foo } = await import("./index.js"); + +/**/ foo; +// ^ defined: 3, 7, 11 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/export_with_name_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/export_with_name_default.js new file mode 100644 index 000000000..70afda69a --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/export_with_name_default.js @@ -0,0 +1,18 @@ +/*--- path: index.js ---*/ + +module.exports = function foo() { }; + +/*--- path: index2.js ---*/ + +import bar from "./index.js"; + +/**/ bar; +// ^ defined: 3, 7 + +/*--- path: index3.js ---*/ + +let bar = await import("./index.js"); + +/**/ bar.default; +// ^ defined: 14 +// ^ defined: 3 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/export_with_name_nondefault.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/export_with_name_nondefault.js new file mode 100644 index 000000000..a1ff71b5d --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/export_with_name_nondefault.js @@ -0,0 +1,17 @@ +/*--- path: index.js ---*/ + +exports.foo = function () { }; + +/*--- path: index2.js ---*/ + +import { foo } from "./index.js"; + +/**/ foo; +// ^ defined: 3, 7 + +/*--- path: index3.js ---*/ + +let { foo } = await import("./index.js"); + +/**/ foo; +// ^ defined: 3, 14 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/import_with_name_default_alias_nondefault.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/import_with_name_default_alias_nondefault.js new file mode 100644 index 000000000..a059a5a81 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/import_with_name_default_alias_nondefault.js @@ -0,0 +1,22 @@ +/*--- path: a.js ---*/ + +module.exports = function foo() { }; + +/*--- path: index.js ---*/ + +let mod = require("./a.js"); +exports.bar = mod; + +/*--- path: index2.js ---*/ + +import { bar } from "./index.js"; + +/**/ bar; +// ^ defined: 3, 7, 8, 12 + +/*--- path: index3.js ---*/ + +let { bar } = await import("./index.js"); + +/**/ bar; +// ^ defined: 3, 7, 8, 19 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_name_default_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_name_default_alias_default.js new file mode 100644 index 000000000..3275812e4 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_name_default_alias_default.js @@ -0,0 +1,23 @@ +/*--- path: a.js ---*/ + +module.exports = function foo() { }; + +/*--- path: index.js ---*/ + +let mod = require("./a.js"); +module.exports = mod; + +/*--- path: index2.js ---*/ + +import bar from "./index.js"; + +/**/ bar; +// ^ defined: 3, 7, 8, 12 + +/*--- path: index3.js ---*/ + +let bar = await import("./index.js"); + +/**/ bar.default; +// ^ defined: 19 +// ^ defined: 3, 7, 8 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_name_default_alias_nondefault.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_name_default_alias_nondefault.js new file mode 100644 index 000000000..a059a5a81 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_name_default_alias_nondefault.js @@ -0,0 +1,22 @@ +/*--- path: a.js ---*/ + +module.exports = function foo() { }; + +/*--- path: index.js ---*/ + +let mod = require("./a.js"); +exports.bar = mod; + +/*--- path: index2.js ---*/ + +import { bar } from "./index.js"; + +/**/ bar; +// ^ defined: 3, 7, 8, 12 + +/*--- path: index3.js ---*/ + +let { bar } = await import("./index.js"); + +/**/ bar; +// ^ defined: 3, 7, 8, 19 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_name_nondefault_alias_default.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_name_nondefault_alias_default.js new file mode 100644 index 000000000..cc1722f16 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_name_nondefault_alias_default.js @@ -0,0 +1,23 @@ +/*--- path: a.js ---*/ + +exports.foo = function () { }; + +/*--- path: index.js ---*/ + +let mod = require("./a.js"); +module.exports = mod.foo + +/*--- path: index2.js ---*/ + +import bar from "./index.js"; + +/**/ bar; +// ^ defined: 3, 8, 12 + +/*--- path: index3.js ---*/ + +let bar = await import("./index.js"); + +/**/ bar.default; +// ^ defined: 19 +// ^ defined: 3, 8 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_name_nondefault_alias_nondefault.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_name_nondefault_alias_nondefault.js new file mode 100644 index 000000000..6963f7c5e --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_name_nondefault_alias_nondefault.js @@ -0,0 +1,22 @@ +/*--- path: a.js ---*/ + +exports.foo = function () { }; + +/*--- path: index.js ---*/ + +let mod = require("./a.js"); +exports.bar = mod.foo; + +/*--- path: index2.js ---*/ + +import { bar } from "./index.js"; + +/**/ bar; +// ^ defined: 3, 8, 12 + +/*--- path: index3.js ---*/ + +let { bar } = await import("./index.js"); + +/**/ bar; +// ^ defined: 3, 8, 19 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_unaliased_name.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_unaliased_name.js new file mode 100644 index 000000000..1dd099e14 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/reexport_with_unaliased_name.js @@ -0,0 +1,21 @@ +/*--- path: a.js ---*/ + +exports.foo = function () { }; +/*--- path: index.js ---*/ + +let mod = require("./a.js"); +exports.foo = mod.foo; + +/*--- path: index2.js ---*/ + +import { foo } from "./index.js"; + +/**/ foo; +// ^ defined: 3, 7, 11 + +/*--- path: index3.js ---*/ + +let { foo } = await import("./index.js"); + +/**/ foo; +// ^ defined: 3, 7, 18 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/variable_visible_through_nonbinding_import.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/variable_visible_through_nonbinding_import.js new file mode 100644 index 000000000..8ce998c2c --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/variable_visible_through_nonbinding_import.js @@ -0,0 +1,6 @@ +let x = 42; + +import "./foo"; + +/**/ x; +// ^ defined: 1 From 2f582a91c5d5981693ec20abde1228519f50e993 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Oct 2023 11:55:41 +0200 Subject: [PATCH 182/500] Adds more tests and testing info Co-authored-by: Rebecca Valentine --- ...fault_object_import_of_exported_default_object.js | 12 ++++++++++++ ...ault_object_import_of_exported_nondefault_name.js | 10 ++++++++++ ...fault_object_import_of_exported_default_object.js | 12 ++++++++++++ ...ault_object_import_of_exported_nondefault_name.js | 10 ++++++++++ ...fault_object_import_of_exported_default_object.js | 12 ++++++++++++ ...ault_object_import_of_exported_nondefault_name.js | 10 ++++++++++ ...fault_object_import_of_exported_default_object.js | 12 ++++++++++++ ...ault_object_import_of_exported_nondefault_name.js | 10 ++++++++++ 8 files changed, 88 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/field_on_default_object_import_of_exported_default_object.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/field_on_default_object_import_of_exported_nondefault_name.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_export/field_on_default_object_import_of_exported_default_object.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_export/field_on_default_object_import_of_exported_nondefault_name.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/field_on_default_object_import_of_exported_default_object.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/field_on_default_object_import_of_exported_nondefault_name.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_export/field_on_default_object_import_of_exported_default_object.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_export/field_on_default_object_import_of_exported_nondefault_name.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/field_on_default_object_import_of_exported_default_object.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/field_on_default_object_import_of_exported_default_object.js new file mode 100644 index 000000000..2e3c427c8 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/field_on_default_object_import_of_exported_default_object.js @@ -0,0 +1,12 @@ +/*--- path: index.js ---*/ + +export default { + foo: 1 +}; + +/*--- path: index2.js ---*/ + +let mod = await import("./index.js"); + +mod.default.foo; +// ^ defined: 4 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/field_on_default_object_import_of_exported_nondefault_name.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/field_on_default_object_import_of_exported_nondefault_name.js new file mode 100644 index 000000000..9bc1a8120 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_ES6_export/field_on_default_object_import_of_exported_nondefault_name.js @@ -0,0 +1,10 @@ +/*--- path: index.js ---*/ + +export function foo() { } + +/*--- path: index2.js ---*/ + +let mod = await import("./index.js"); + +mod.foo; +// ^ defined: 3 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_export/field_on_default_object_import_of_exported_default_object.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_export/field_on_default_object_import_of_exported_default_object.js new file mode 100644 index 000000000..8bfed4d87 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_export/field_on_default_object_import_of_exported_default_object.js @@ -0,0 +1,12 @@ +/*--- path: index.js ---*/ + +module.exports = { + foo: 1 +}; + +/*--- path: index2.js ---*/ + +let mod = require("./index.js"); + +mod.foo; +// ^ defined: 4 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_export/field_on_default_object_import_of_exported_nondefault_name.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_export/field_on_default_object_import_of_exported_nondefault_name.js new file mode 100644 index 000000000..a699fc2a5 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_export/field_on_default_object_import_of_exported_nondefault_name.js @@ -0,0 +1,10 @@ +/*--- path: index.js ---*/ + +exports.foo = function () { }; + +/*--- path: index2.js ---*/ + +let mod = require("./index.js"); + +mod.foo; +// ^ defined: 3 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/field_on_default_object_import_of_exported_default_object.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/field_on_default_object_import_of_exported_default_object.js new file mode 100644 index 000000000..c05ea891d --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/field_on_default_object_import_of_exported_default_object.js @@ -0,0 +1,12 @@ +/*--- path: index.js ---*/ + +module.exports = { + foo: 1 +}; + +/*--- path: index2.js ---*/ + +import mod from "./index.js"; + +mod.foo; +// ^ defined: 4 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/field_on_default_object_import_of_exported_nondefault_name.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/field_on_default_object_import_of_exported_nondefault_name.js new file mode 100644 index 000000000..a091abeaf --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/field_on_default_object_import_of_exported_nondefault_name.js @@ -0,0 +1,10 @@ +/*--- path: index.js ---*/ + +exports.foo = function () { }; + +/*--- path: index2.js ---*/ + +import mod from "./index.js"; + +mod.foo; +// ^ defined: 3 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_export/field_on_default_object_import_of_exported_default_object.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_export/field_on_default_object_import_of_exported_default_object.js new file mode 100644 index 000000000..ed6a119c7 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_export/field_on_default_object_import_of_exported_default_object.js @@ -0,0 +1,12 @@ +/*--- path: index.js ---*/ + +export default { + foo: 1 +}; + +/*--- path: index2.js ---*/ + +import mod from "./index.js"; + +mod.foo; +// ^ defined: 4 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_export/field_on_default_object_import_of_exported_nondefault_name.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_export/field_on_default_object_import_of_exported_nondefault_name.js new file mode 100644 index 000000000..b8cf8d0c9 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_export/field_on_default_object_import_of_exported_nondefault_name.js @@ -0,0 +1,10 @@ +/*--- path: index.js ---*/ + +export function foo() { } + +/*--- path: index2.js ---*/ + +import mod from "./index.js"; + +mod.foo; +// ^ defined: From e0f66aade03e84c6ca418383ce70d03d0c656269 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Oct 2023 12:12:23 +0200 Subject: [PATCH 183/500] Fixes definiens syntax types Co-authored-by: Rebecca Valentine --- .../src/stack-graphs.tsg | 98 ++++++++++++++----- 1 file changed, 75 insertions(+), 23 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index eb86ac913..e25345fd5 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3130,15 +3130,15 @@ inherit .return_or_yield ; augmentation of scope via identifiers (assignment_expression - left: (identifier)@left + left: (identifier)@name right: (_)@right)@assignment_expr { - node @assignment_expr.pop + node @name.pop ; augments the scope by adding a lookup edge, ie. a pop - attr (@assignment_expr.pop) node_definition = @left - edge @assignment_expr.after_scope -> @assignment_expr.pop - edge @assignment_expr.pop -> @right.value + attr (@name.pop) node_definition = @name + edge @assignment_expr.after_scope -> @name.pop + edge @name.pop -> @right.value ; ensure the scope flows through the identifier edge @assignment_expr.after_scope -> @right.after_scope @@ -4132,16 +4132,39 @@ inherit .return_or_yield ;; kinds of definitions. (assignment_expression - left: (identifier)@_left + left: [ + (identifier)@left + ; (member_expression property:(_)@left) ; FIXME member expressions are references and have no .pop + ] + right: [ + (function) + (generator_function) + (arrow_function) + ]) { + + attr (@left.pop) syntax_type = "function" +} + +(assignment_expression + left: [ + (identifier)@left + ; (member_expression property:(_)@left) ; FIXME member expressions are references and have no .pop + ] + right: (class)) { + + attr (@left.pop) syntax_type = "class" +} + +(assignment_expression + left: (identifier)@left right: [ (function) (generator_function) (arrow_function) (class) - ]@right)@assignment_expr { + ]@right) { - attr (@assignment_expr.pop) definiens_node = @right - attr (@assignment_expr.pop) syntax_type = "function" + attr (@left.pop) definiens_node = @right } @@ -4151,11 +4174,7 @@ inherit .return_or_yield object:(identifier)@_object property:(_)@left ) - right: [ - (function) - (generator_function) - (arrow_function) - ]@right)@assignment_expr + right: (_)@right)@assignment_expr (#not-eq @_object "module") (#not-eq @left "exports") ) { @@ -4166,7 +4185,6 @@ inherit .return_or_yield attr (left_ignore_guard) pop_symbol = "GUARD:GANDALF" attr (left_definiens_hook) node_definition = @left attr (left_definiens_hook) definiens_node = @right - attr (left_definiens_hook) syntax_type = "function" edge @assignment_expr.pkg_pop -> left_ignore_guard edge left_ignore_guard -> left_definiens_hook } @@ -4188,7 +4206,6 @@ inherit .return_or_yield attr (left_ignore_guard) pop_symbol = "GUARD:GANDALF" attr (left_definiens_hook) node_definition = @left attr (left_definiens_hook) definiens_node = @right - attr (left_definiens_hook) syntax_type = "function" edge @assignment_expr.pkg_pop -> left_ignore_guard edge left_ignore_guard -> left_definiens_hook @@ -4217,13 +4234,21 @@ inherit .return_or_yield (function) (generator_function) (arrow_function) - (class) ])) { attr (@name.pop) syntax_type = "function" } +(variable_declaration + (variable_declarator + name:(identifier)@name + value: (class))) { + + attr (@name.pop) syntax_type = "class" + +} + (lexical_declaration (variable_declarator name:(identifier)@name @@ -4231,13 +4256,41 @@ inherit .return_or_yield (function) (generator_function) (arrow_function) - (class) ])) { attr (@name.pop) syntax_type = "function" } +(lexical_declaration + (variable_declarator + name:(identifier)@name + value: (class))) { + + attr (@name.pop) syntax_type = "class" + +} + +(pair + key: (_)@name + value: [ + (function) + (generator_function) + (arrow_function) + ]) { + + attr (@name.definiens_hook) syntax_type = "function" + +} + +(pair + key: (_)@name + value: (class)) { + + attr (@name.definiens_hook) syntax_type = "class" + +} + (pair key: (_)@name value: [ @@ -4247,14 +4300,13 @@ inherit .return_or_yield (class) ]@value)@pair_expr { - node name_definiens_hook + node @name.definiens_hook node name_ignore_guard attr (name_ignore_guard) pop_symbol = "GUARD:GANDALF" - attr (name_definiens_hook) node_definition = @name - attr (name_definiens_hook) definiens_node = @value - attr (name_definiens_hook) syntax_type = "function" + attr (@name.definiens_hook) node_definition = @name + attr (@name.definiens_hook) definiens_node = @value edge @pair_expr.pkg_pop -> name_ignore_guard - edge name_ignore_guard -> name_definiens_hook + edge name_ignore_guard -> @name.definiens_hook } From 310995db7c528c458b4b3fc50b396d3f5bfa4ae4 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Oct 2023 12:17:59 +0200 Subject: [PATCH 184/500] Remove unnecessary patterns Co-authored-by: Rebecca Valentine --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index e25345fd5..91bd88610 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3894,14 +3894,14 @@ inherit .return_or_yield left: [ ( ; exports.foo = ... (member_expression - object:(identifier)@exports + object:(_)@exports property:(_)@property) (#eq? @exports "exports") ) ( ; module.exports.foo = ... (member_expression object:(member_expression - object:(identifier)@_module + object:(_)@_module property:(_)@exports) property:(_)@property) (#eq? @_module "module") From 9b13fc1e37af5cb107d3d549b4a2f24edbc9fc6e Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Oct 2023 12:28:47 +0200 Subject: [PATCH 185/500] Adds empty statement block bug fix Co-authored-by: Rebecca Valentine --- .../src/stack-graphs.tsg | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 91bd88610..94dedc6a1 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -1561,6 +1561,12 @@ inherit .return_or_yield ;; #### Statement Block +(statement_block (_)* @stmts)@statement_block { + if (is-empty @stmts) { + edge @statement_block.after_scope -> @statement_block.before_scope + } +} + ; statement block, first statement (statement_block . From a543dbdcdc439d280472c13b6244bdcbca04830f Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Oct 2023 13:10:26 +0200 Subject: [PATCH 186/500] Hoisting changes: - Adds hoisting tests - Fixes strange bug in test case - Adds base hoist points - Adds more hoisting tests - Adds fixes for new hoisting tests Co-authored-by: Rebecca Valentine --- .../src/stack-graphs.tsg | 82 ++++++++- .../test/old/hoisting/basic_functions.js | 8 + .../old/hoisting/functions_in_subscopes.js | 163 ++++++++++++++++++ .../test/old/hoisting/imports.js | 10 ++ 4 files changed, 257 insertions(+), 6 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/hoisting/basic_functions.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/hoisting/functions_in_subscopes.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/hoisting/imports.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 94dedc6a1..cf6bc5424 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -251,6 +251,7 @@ inherit .class_value inherit .constructor inherit .export_statement inherit .exports +inherit .hoist_point inherit .import_statement inherit .pkg_pop inherit .pkg_push @@ -292,6 +293,7 @@ inherit .return_or_yield node prog_pkg_push_guard node prog_legacy_qname_guard node @prog.exports + node @prog.hoist_point node @prog.pkg_pop node @prog.pkg_push @@ -322,6 +324,7 @@ inherit .return_or_yield } edge @prog.before_scope -> @prog.pkg_push + edge @prog.before_scope -> @prog.hoist_point attr (prog_module_scope) pop_symbol = "GUARD:MODULE" edge @prog.pkg_pop -> prog_module_pop_start @@ -880,8 +883,10 @@ inherit .return_or_yield (import_clause)@import_clause source:(_)@source)@import_stmt { + edge @import_stmt.after_scope -> @import_stmt.before_scope + edge @import_clause.before_scope -> @import_stmt.before_scope - edge @import_stmt.after_scope -> @import_clause.after_scope + edge @import_stmt.hoist_point -> @import_clause.after_scope edge @import_clause.source -> @source.exports @@ -1210,7 +1215,7 @@ inherit .return_or_yield ; with an augmentation for the function attr (@name.pop) node_definition = @name - edge @fun_decl.after_scope -> @name.pop + edge @fun_decl.hoist_point -> @name.pop edge @name.pop -> fun_decl_function_value ; function values have drop nodes that handle closures, that points to the @@ -1294,7 +1299,7 @@ inherit .return_or_yield ; with an augmentation for the function attr (@name.pop) node_definition = @name - edge @fun_decl.after_scope -> @name.pop + edge @fun_decl.hoist_point -> @name.pop edge @name.pop -> fun_decl_function_value ; function values have drop nodes that handle closures, that points to the @@ -1561,6 +1566,13 @@ inherit .return_or_yield ;; #### Statement Block +(statement_block)@statement_block { + + node @statement_block.hoist_point + edge @statement_block.before_scope -> @statement_block.hoist_point + +} + (statement_block (_)* @stmts)@statement_block { if (is-empty @stmts) { edge @statement_block.after_scope -> @statement_block.before_scope @@ -1599,6 +1611,13 @@ inherit .return_or_yield ;; #### If +(if_statement + consequence:(_)@consequence)@if_stmt { + + let @if_stmt.hoist_point = @consequence.before_scope + +} + (if_statement condition:(_)@condition)@if_stmt { ; scopes flow from the if statement to the condition edge @condition.before_scope -> @if_stmt.before_scope @@ -1611,6 +1630,7 @@ inherit .return_or_yield ; scopes flow from the condition to the consequence, then to the if statement edge @consequence.before_scope -> @condition.after_scope edge @if_stmt.after_scope -> @consequence.after_scope + } (if_statement @@ -1622,6 +1642,13 @@ inherit .return_or_yield edge @if_stmt.after_scope -> @alternative.after_scope } +(else_clause + (_)@inner)@else_clause { + + let @else_clause.hoist_point = @inner.before_scope + +} + (else_clause (_)@inner)@else_clause { node @else_clause.after_scope node @else_clause.before_scope @@ -1650,7 +1677,15 @@ inherit .return_or_yield (switch_body)@switch_body { node @switch_body.after_scope node @switch_body.before_scope - edge @switch_body.after_scope -> @switch_body.before_scope + node @switch_body.hoist_point + + edge @switch_body.before_scope -> @switch_body.hoist_point +} + +(switch_body (_)* @choices)@switch_body { + if (is-empty @choices) { + edge @switch_body.after_scope -> @switch_body.before_scope + } } ; switch body, first choice @@ -1769,6 +1804,13 @@ inherit .return_or_yield ;; #### For +(for_statement + body:(_)@body)@for_stmt { + + let @for_stmt.hoist_point = @body.before_scope + +} + (for_statement initializer:(_)@initializer condition:(_)@condition @@ -1787,12 +1829,20 @@ inherit .return_or_yield ; scopes also flow from condition out to statement edge @for_stmt.after_scope -> @condition.after_scope + } ;; #### For In +(for_in_statement + body:(_)@body)@for_in_stmt { + + let @for_in_stmt.hoist_point = @body.before_scope + +} + (for_in_statement left:(_)@_left right:(_)@right @@ -1822,6 +1872,13 @@ inherit .return_or_yield ;; #### While +(while_statement + body:(_)@body)@while_stmt { + + let @while_stmt.hoist_point = @body.before_scope + +} + (while_statement condition:(_)@condition body:(_)@body)@while_stmt @@ -1834,12 +1891,20 @@ inherit .return_or_yield ; scopes also flow back into the condition edge @condition.before_scope -> @body.after_scope + } ;; #### Do +(do_statement + body:(_)@body)@do_stmt { + + let @do_stmt.hoist_point = @body.before_scope + +} + (do_statement body:(_)@body condition:(_)@condition)@do_stmt @@ -1930,12 +1995,18 @@ inherit .return_or_yield ;; #### With +(with_statement body:(_)@body)@with_stmt { + + let @with_stmt.hoist_point = @body.before_scope + +} + (with_statement object:(_)@object body:(_)@body)@with_stmt { - node with_stmt_push_dot + node with_stmt_push_dot ; scopes flow from the statement into the object then into the body then back out edge @object.before_scope -> @with_stmt.before_scope @@ -1944,7 +2015,6 @@ inherit .return_or_yield edge @with_stmt.after_scope -> @with_stmt.before_scope attr (@with_stmt.after_scope -> @with_stmt.before_scope) precedence = 1 - attr (with_stmt_push_dot) push_symbol = "GUARD:MEMBER" edge with_stmt_push_dot -> @object.value edge @body.before_scope -> with_stmt_push_dot diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/hoisting/basic_functions.js b/languages/tree-sitter-stack-graphs-javascript/test/old/hoisting/basic_functions.js new file mode 100644 index 000000000..69382ca19 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/hoisting/basic_functions.js @@ -0,0 +1,8 @@ +/**/ foo; +// ^ defined: 7 + +/**/ bar; +// ^ defined: 8 + +function foo() { } +function* bar() { } \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/hoisting/functions_in_subscopes.js b/languages/tree-sitter-stack-graphs-javascript/test/old/hoisting/functions_in_subscopes.js new file mode 100644 index 000000000..a6c25ada4 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/hoisting/functions_in_subscopes.js @@ -0,0 +1,163 @@ +/**/ f1; +// ^ defined: +/**/ f2; +// ^ defined: +/**/ f3; +// ^ defined: +/**/ f4; +// ^ defined: +/**/ f5; +// ^ defined: +/**/ f6; +// ^ defined: +/**/ f7; +// ^ defined: +/**/ f8; +// ^ defined: +/**/ f9; +// ^ defined: +/**/ f10; +// ^ defined: +/**/ f11; +// ^ defined: +/**/ f12; +// ^ defined: +/**/ f13; +// ^ defined: +/**/ f14; +// ^ defined: +/**/ f15; +// ^ defined: +/**/ f16; +// ^ defined: +/**/ f17; +// ^ defined: + +while (x) { + /**/ f1; + // ^ defined: 40 + + function f1() { } +} + +for (let x = 0; x < 10; x++) { + /**/ f2; + // ^ defined: 47 + + function f2() { } +} + +if (x) { + /**/ f3; + // ^ defined: 54 + + function f3() { } +} else { + /**/ f4; + // ^ defined: 59 + + function f4() { } +} + +for (x in y) { + /**/ f5; + // ^ defined: 66 + + function f5() { } +} + +do { + /**/ f6; + // ^ defined: 73 + + function f6() { } +} while (x); + +try { + /**/ f7; + // ^ defined: 80 + + function f7() { } +} catch { + /**/ f8; + // ^ defined: 85 + + function f8() { } +} finally { + /**/ f9; + // ^ defined: 90 + + function f9() { } +} + +with (x) { + /**/ f10; + // ^ defined: 97 + + function f10() { } +} + +switch (x) { + case 0: + /**/ f11; + // ^ defined: 105 + + function f11() { } +} + +{ + /**/ f12; + // ^ defined: 112 + + function f12() { } +} + +function foo() { + /**/ f13; + // ^ defined: 119 + + function f13() { } +} + +function* foo() { + /**/ f14; + // ^ defined: 126 + + function f14() { } +} + +(function () { + /**/ f15; + // ^ defined: 133 + + function f15() { } +}); + +(function* () { + /**/ f16; + // ^ defined: 140 + + function f16() { } +}); + +(() => { + /**/ f17; + // ^ defined: 147 + + function f17() { } +}); + +// Some tests of bare single-statement bodies + +while (x) function f1() { } + +for (let x = 0; x < 10; x++) function f2() { } + +if (x) function f3() { } +else function f4() { } + +for (x in y) function f5() { } + +do function f6() { } while (x); + +with (x) function f10() { } diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/hoisting/imports.js b/languages/tree-sitter-stack-graphs-javascript/test/old/hoisting/imports.js new file mode 100644 index 000000000..1045e5512 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/hoisting/imports.js @@ -0,0 +1,10 @@ +/*--- path: a.js ---*/ + +export let foo = 1; + +/*--- path: b.js ---*/ + +/**/ bar; +// ^ defined: 3, 10 + +import { foo as bar } from "./a.js"; \ No newline at end of file From 182ab99bf7154f9b49ce8d750b4ad76ecf7e9ab8 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Oct 2023 13:13:35 +0200 Subject: [PATCH 187/500] Adds support for `import`'s default field Co-authored-by: Rebecca Valentine --- .../imports_and_exports/import_function.js | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/import_function.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/import_function.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/import_function.js new file mode 100644 index 000000000..02b9de496 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/import_function.js @@ -0,0 +1,20 @@ +/*--- path: a.js ---*/ + +exports.foo = 2; +module.exports = 1; + +/*--- path: b.js ---*/ + +let mod = await import("./a.js"); + +mod.foo; +// ^ defined: 3 + +mod.default; +// ^ defined: 3, 4 +// !!!! TODO 3 is here because the `exports.foo` on line 3 also defines +// the default object. this is a current limitation of the import/export +// system to support CommonJS behavior + +mod.default.foo; +// ^ defined: 3 From b9d5119ae435bf69798087ca028bb6b93a54c574 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Oct 2023 13:18:34 +0200 Subject: [PATCH 188/500] Adds tests for module.exports.foo pattern Co-authored-by: Rebecca Valentine --- ...t_object_import_of_exported_default_object_field.js | 10 ++++++++++ ...t_object_import_of_exported_default_object_field.js | 10 ++++++++++ 2 files changed, 20 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_export/field_on_default_object_import_of_exported_default_object_field.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/field_on_default_object_import_of_exported_default_object_field.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_export/field_on_default_object_import_of_exported_default_object_field.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_export/field_on_default_object_import_of_exported_default_object_field.js new file mode 100644 index 000000000..16d60547a --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/CommonJS_import_export/field_on_default_object_import_of_exported_default_object_field.js @@ -0,0 +1,10 @@ +/*--- path: a.js ---*/ + +module.exports.foo = 1; + +/*--- path: b.js ---*/ + +let mod = require("./a.js"); + +mod.foo; +// ^ defined: 3 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/field_on_default_object_import_of_exported_default_object_field.js b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/field_on_default_object_import_of_exported_default_object_field.js new file mode 100644 index 000000000..b3b8c5456 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/imports_and_exports/ES6_import_CommonJS_export/field_on_default_object_import_of_exported_default_object_field.js @@ -0,0 +1,10 @@ +/*--- path: a.js ---*/ + +module.exports.foo = 1; + +/*--- path: b.js ---*/ + +import { foo } from "./a.js"; + +/**/ foo; +// ^ defined: 3, 7 \ No newline at end of file From 6c33f752af76745162b8727a2af96874b2777305 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Oct 2023 13:27:08 +0200 Subject: [PATCH 189/500] Adds fix for ES6 default exports Co-authored-by: Rebecca Valentine --- .../src/stack-graphs.tsg | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index cf6bc5424..120611406 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -499,10 +499,11 @@ inherit .return_or_yield edge @decl.before_scope -> @export_stmt.before_scope edge @export_stmt.after_scope -> @decl.after_scope - ; !!!! TODO HACK - ; the tree-sitter grammar doesn't make it possible to distinguish - ; between default exports and non-default exports so this is required - ; to ensure that default exports work properly +} + +(export_statement "default" + (declaration)@decl)@export_stmt { + node export_stmt_pop_guard_default attr (export_stmt_pop_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @decl, definiens_node = @export_stmt.export_statement edge @export_stmt.exports -> export_stmt_pop_guard_default From 83a470ca37c1833a7d4d1a7a9044f2f9384cb058 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 10 Oct 2023 14:03:29 +0200 Subject: [PATCH 190/500] Add comment explaining import & export specifier rules --- .../src/stack-graphs.tsg | 87 ++++++++++++------- 1 file changed, 55 insertions(+), 32 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 120611406..7d86b629b 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -588,16 +588,27 @@ inherit .return_or_yield edge @export_clause.after_scope -> @last_export.after_scope } +;; Export specifiers have several cases: +;; - the reference into the source module can be default or named +;; - the definition from this module can be default or named. +;; +;; We model this using seperate sets of rules, two rules for the reference, +;; and two rules for the definition. The `.def_to_ref` node is used to connect +;; the two. + (export_specifier)@export_specifier { node @export_specifier.after_scope node @export_specifier.before_scope + node @export_specifier.def_to_ref node @export_specifier.source edge @export_specifier.after_scope -> @export_specifier.before_scope } +;; Export specifier reference rules + ; export { default } from ... ; export { default as ... } from ... ( @@ -610,7 +621,7 @@ inherit .return_or_yield node name_push attr (name_push) node_reference = @name - edge @export_specifier.pop -> name_push + edge @export_specifier.def_to_ref -> name_push edge name_push -> @export_specifier.source } @@ -625,13 +636,16 @@ inherit .return_or_yield (#eq? @name "default") ) { - node export_specifier_push_guard_default - attr (export_specifier_push_guard_default) symbol_reference = "GUARD:DEFAULT", source_node = @name - edge @export_specifier.pop -> export_specifier_push_guard_default - edge export_specifier_push_guard_default -> @export_specifier.source + node push_guard_default + + attr (push_guard_default) symbol_reference = "GUARD:DEFAULT", source_node = @name + edge @export_specifier.def_to_ref -> push_guard_default + edge push_guard_default -> @export_specifier.source } +;; Export specifier definition rules + ; export { foo } from ... ; export { ... as foo } from ... ( [ @@ -646,9 +660,11 @@ inherit .return_or_yield (#not-eq? @alias "default") ) { - node @export_specifier.pop - attr (@export_specifier.pop) node_definition = @alias, definiens_node = @export_specifier.export_statement - edge @export_specifier.exports -> @export_specifier.pop + node name_pop + + attr (name_pop) node_definition = @alias, definiens_node = @export_specifier.export_statement + edge @export_specifier.exports -> name_pop + edge name_pop -> @export_specifier.def_to_ref } @@ -666,9 +682,11 @@ inherit .return_or_yield (#eq? @alias "default") ) { - node @export_specifier.pop - attr (@export_specifier.pop) symbol_definition = "GUARD:DEFAULT", source_node = @alias, definiens_node = @export_specifier.export_statement - edge @export_specifier.exports -> @export_specifier.pop + node pop_guard_default + + attr (pop_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @alias, definiens_node = @export_specifier.export_statement + edge @export_specifier.exports -> pop_guard_default + edge pop_guard_default -> @export_specifier.def_to_ref } @@ -678,13 +696,13 @@ inherit .return_or_yield (export_statement value:(_)@default_expr)@export_stmt { - node export_stmt_default_guard + node pop_default_guard - attr (export_stmt_default_guard) symbol_definition = "GUARD:DEFAULT", source_node = @export_stmt, definiens_node = @export_stmt.export_statement + attr (pop_default_guard) symbol_definition = "GUARD:DEFAULT", source_node = @export_stmt, definiens_node = @export_stmt.export_statement edge @default_expr.before_scope -> @export_stmt.before_scope edge @export_stmt.after_scope -> @default_expr.after_scope - edge @export_stmt.exports -> export_stmt_default_guard - edge export_stmt_default_guard -> @default_expr.value + edge @export_stmt.exports -> pop_default_guard + edge pop_default_guard -> @default_expr.value } @@ -942,24 +960,25 @@ inherit .return_or_yield edge @named_imports.after_scope -> @last_import.after_scope } +;; Import specifiers have several cases: +;; - the reference into the source module can be default or named +;; - the definition from this module can be default or named. +;; The case where the definition is default instead of named is invalid. +;; +;; We model this using seperate sets of rules, two rules for the reference, +;; and one rules for the definition. The `.def_to_ref` node is used to connect +;; the two. + (import_specifier)@import_specifier { node @import_specifier.after_scope node @import_specifier.before_scope + node @import_specifier.def_to_ref node @import_specifier.source edge @import_specifier.after_scope -> @import_specifier.before_scope } -;; The following two cases should never happen in valid code: -;; -;; - aliased name, with alias = `default` -;; - non-aliased name, with name = `default` -;; -;; These are both invalid JavaScript and so should never actually -;; occur in valid code. But, of course, sometimes people write -;; bad code, and also they do parse according to the Tree-sitter -;; grammar. We should never ever match against them and produce -;; any sort of graph components however. +;; Import specifier reference rules ( (import_specifier @@ -969,10 +988,11 @@ inherit .return_or_yield (#not-eq? @name "default") ) { - node @import_specifier.push + node name_push - attr (@import_specifier.push) node_reference = @name - edge @import_specifier.push -> @import_specifier.source + attr (name_push) node_reference = @name + edge name_push -> @import_specifier.source + edge @import_specifier.def_to_ref -> name_push } @@ -984,13 +1004,16 @@ inherit .return_or_yield (#eq? @name "default") ) { - node @import_specifier.push + node push_guard_default - attr (@import_specifier.push) symbol_reference = "GUARD:DEFAULT", source_node = @name - edge @import_specifier.push -> @import_specifier.source + attr (push_guard_default) symbol_reference = "GUARD:DEFAULT", source_node = @name + edge push_guard_default -> @import_specifier.source + edge @import_specifier.def_to_ref -> push_guard_default } +;; Import specifier definition rules + ( [ (import_specifier name:(_)@alias @@ -1006,7 +1029,7 @@ inherit .return_or_yield node name_pop attr (name_pop) node_definition = @alias, definiens_node = @import_specifier.import_statement - edge name_pop -> @import_specifier.push + edge name_pop -> @import_specifier.def_to_ref edge @import_specifier.after_scope -> name_pop } From 03d755d8898a953a1a1075ccc7299e998ec1de1c Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 10 Oct 2023 14:19:54 +0200 Subject: [PATCH 191/500] Fix definiens warning --- .../src/stack-graphs.tsg | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 7d86b629b..b3a6b4454 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -1466,12 +1466,10 @@ inherit .return_or_yield (#eq? @name "constructor") ) { - node name_constructor_guard - ; augmentation for the constructor - attr (name_constructor_guard) symbol_definition = "GUARD:CONSTRUCTOR", source_node = @name - edge @method_def.class_value -> name_constructor_guard - edge name_constructor_guard -> @method_def.constructor + attr (@name.pop) symbol_definition = "GUARD:CONSTRUCTOR", source_node = @name + edge @method_def.class_value -> @name.pop + edge @name.pop -> @method_def.constructor edge @method_def.constructor -> @method_def.method_value } From 2e2e221352b0da92b8128a053e534460cf7e7c08 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 10 Oct 2023 14:46:35 +0200 Subject: [PATCH 192/500] Drop explicit tree-sitter version dependency --- languages/tree-sitter-stack-graphs-javascript/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml index 42960b6fb..624edbab2 100644 --- a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -31,7 +31,6 @@ clap = { version = "4", optional = true } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" stack-graphs = { version = "0.12", path = "../../stack-graphs" } -tree-sitter = "=0.20.9" tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs" } tree-sitter-javascript = { git = "https://github.com/tree-sitter/tree-sitter-javascript", rev = "5720b249490b3c17245ba772f6be4a43edb4e3b7" } From d8e6c282b191db3416d95ba42d9184eaa2a8ebfa Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 11 Oct 2023 10:17:27 +0200 Subject: [PATCH 193/500] Remove unconditional scope pass-throughs for empty elements Elements that could be empty (i.e., not have subnodes) connected their before and after scopes unconditionally. This could lead to exponential blow ups when they were not empty: the direct pass through and the path through the elements were equivalent. Guarding the pass-through with a conditional that ensures it is only created when there are indeed no sub nodes prevents this. --- .../src/stack-graphs.tsg | 104 +++++++++--------- 1 file changed, 54 insertions(+), 50 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index b3a6b4454..402ec18ed 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -554,10 +554,10 @@ inherit .return_or_yield node @export_clause.source } -; LATER-TODO tree sitter doesn't yet support empty switch bodies -; THIS IS A HUGE HACK AND MUST BE FIXED -(export_clause)@export_clause { - edge @export_clause.after_scope -> @export_clause.before_scope +(export_clause (_)* @clauses)@export_clause { + if (is-empty @clauses) { + edge @export_clause.after_scope -> @export_clause.before_scope + } } (export_clause @@ -853,9 +853,7 @@ inherit .return_or_yield ; import "foo.js"; ; only used for side effects not imports. -; HACK this is not a good solution, but we can't do better with the -; current tree sitter grammar -(import_statement)@import_stmt { +(import_statement . source:(_))@import_stmt { edge @import_stmt.after_scope -> @import_stmt.before_scope } @@ -926,10 +924,10 @@ inherit .return_or_yield node @named_imports.source } -; LATER-TODO tree sitter doesn't yet support empty named imports -; THIS IS A HUGE HACK AND MUST BE FIXED -(named_imports)@named_imports { - edge @named_imports.after_scope -> @named_imports.before_scope +(named_imports (_)* @specs)@named_imports { + if (is-empty @specs) { + edge @named_imports.after_scope -> @named_imports.before_scope + } } (named_imports @@ -1421,12 +1419,15 @@ inherit .return_or_yield } -; LATER-TODO tree sitter doesn't yet support empty switch bodies -; THIS IS A HUGE HACK AND MUST BE FIXED (class_body)@class_body { node @class_body.after_scope node @class_body.before_scope - edge @class_body.after_scope -> @class_body.before_scope +} + +(class_body (_)* @decls)@class_body { + if (is-empty @decls) { + edge @class_body.after_scope -> @class_body.before_scope + } } (class_body @@ -1694,8 +1695,6 @@ inherit .return_or_yield edge @switch_stmt.after_scope -> @body.after_scope } -; LATER-TODO tree sitter doesn't yet support empty switch bodies -; THIS IS A HUGE HACK AND MUST BE FIXED (switch_body)@switch_body { node @switch_body.after_scope node @switch_body.before_scope @@ -1743,10 +1742,10 @@ inherit .return_or_yield node @switch_case.before_scope } -; LATER-TODO tree sitter doesnt yet support switch case's with no statements -; THIS IS A HUGE HACK AND MUST BE FIXED -(switch_case)@switch_case { +(switch_case (_)* @stmts)@switch_case { + if (is-empty @stmts) { edge @switch_case.after_scope -> @switch_case.before_scope + } } ; switch case, non-empty statements, first statement @@ -1786,10 +1785,10 @@ inherit .return_or_yield node @switch_default.before_scope } -; LATER-TODO tree sitter doesnt yet support empty defaults -; THIS IS A HUGE HACK AND MUST BE FIXED -(switch_default)@switch_default { - edge @switch_default.after_scope -> @switch_default.before_scope +(switch_default (_)* @defaults)@switch_default { + if (is-empty @defaults) { + edge @switch_default.after_scope -> @switch_default.before_scope + } } ; switch default, non-empty statements, first statement @@ -2237,10 +2236,10 @@ inherit .return_or_yield ;; #### Template Strings ; template_strings w/ no substitutions -; LATER-TODO tree sitter queries don't let us find the absence of substitutions -; THIS IS A HUGE HACK AND MUST BE FIXED -(template_string)@template_string { - edge @template_string.after_scope -> @template_string.before_scope +(template_string (_)* @substs)@template_string { + if (is-empty @substs) { + edge @template_string.after_scope -> @template_string.before_scope + } } ; nonempty template string, value @@ -2390,10 +2389,10 @@ inherit .return_or_yield } ; empty objects -; LATER-TODO currently unsupported by tree sitter queries -; THIS IS A HUGE HACK AND MUST BE FIXED -(object)@object_expr { - edge @object_expr.after_scope -> @object_expr.before_scope +(object (_)* @entries)@object_expr { + if (is-empty @entries) { + edge @object_expr.after_scope -> @object_expr.before_scope + } } ; non-empty objects, scopes, first entry @@ -2541,10 +2540,10 @@ inherit .return_or_yield } ; empty arrays -; LATER-TODO currently unsupported by tree sitter queries -; THIS IS A HUGE HACK AND MUST BE FIXED -(array)@array_expr { - edge @array_expr.after_scope -> @array_expr.before_scope +(array (_)* @elems)@array_expr { + if (is-empty @elems) { + edge @array_expr.after_scope -> @array_expr.before_scope + } } ; nonempty arrays, first element @@ -2587,14 +2586,15 @@ inherit .return_or_yield ;; #### Formal Parameters -; LATER-TODO scope propagation through empty formal parameters -; currently unsupported by tree sitter queries -; THIS IS A HUGE HACK AND MUST BE FIXED - (formal_parameters)@formal_params { node @formal_params.after_scope node @formal_params.before_scope - edge @formal_params.after_scope -> @formal_params.before_scope +} + +(formal_parameters (_)* @params)@formal_params { + if (is-empty @params) { + edge @formal_params.after_scope -> @formal_params.before_scope + } } ; first parameter @@ -2985,12 +2985,15 @@ inherit .return_or_yield ;; #### Arguments -; LATER-TODO currently unsupported by tree sitter queries -; THIS IS A HUGE HACK AND MUST BE FIXED (arguments)@arguments { node @arguments.after_scope node @arguments.before_scope - edge @arguments.after_scope -> @arguments.before_scope +} + +(arguments (_)* @args)@arguments { + if (is-empty @args) { + edge @arguments.after_scope -> @arguments.before_scope + } } (arguments @@ -3701,8 +3704,10 @@ inherit .return_or_yield ; LATER-TODO scope propagation through empty object patterns ; currently unsupported by tree sitter queries ; THIS IS A HUGE HACK AND MUST BE FIXED -(object_pattern)@object_pat { - edge @object_pat.after_scope -> @object_pat.before_scope +(object_pattern (_)* @entries)@object_pat { + if (is-empty @entries) { + edge @object_pat.after_scope -> @object_pat.before_scope + } } ; scope propagation through object patterns, first entry @@ -3823,11 +3828,10 @@ inherit .return_or_yield ;; #### Array Patterns -; LATER-TODO scope propagation through empty array patterns -; currently unsupported by tree sitter queries -; THIS IS A HUGE HACK AND MUST BE FIXED -(array_pattern)@array_pat { - edge @array_pat.after_scope -> @array_pat.before_scope +(array_pattern (_)* @pats)@array_pat { + if (is-empty @pats) { + edge @array_pat.after_scope -> @array_pat.before_scope + } } ; scope propagation through array patterns, first element From 4be77c5fc4eb043766eb2a65befbc1532cb5bc39 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Oct 2023 17:16:05 +0200 Subject: [PATCH 194/500] Fix bug when main is unset in package.json and clarify behavior --- .../rust/npm_package.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs index d5e1ad944..5a46d6ee1 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs @@ -86,6 +86,10 @@ impl FileAnalyzer for NpmPackageAnalyzer { // [root] -> [pop "GUARD:PKG"] -> [pop PKG_NAME]* -> [push PKG_INTERNAL_NAME] -> [push "GUARD:PKG_INTERNAL"] -> [root] // if !npm_pkg.name.is_empty() { + // NOTE Because all modules expose their exports at the top-level, both paths created below are equivalent for + // exports of the main module. This means multiple equivalent paths to those exports, which is bad for + // performance. At the moment, we have no mechanism to prevent this from happening. + // reach package internals via package name // // [root] -> [pop "GUARD:PKG"] -> [pop pkg_name]* -> [push pkg_internal_name] @@ -112,7 +116,9 @@ impl FileAnalyzer for NpmPackageAnalyzer { "exports_guard_pop", ); replace_edge(graph, pkg_name_pop, exports_guard_pop, 1); - let main = NormalizedRelativePath::from_str(&npm_pkg.main) + let main = Some(npm_pkg.main) + .filter(|main| !main.is_empty()) + .and_then(|main| NormalizedRelativePath::from_str(&main)) .map(|p| p.into_path_buf()) .unwrap_or(PathBuf::from("index")) .with_extension(""); From 80d73caab8b2b32d0443308cfa683415a7433ff0 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 13 Oct 2023 11:58:52 +0200 Subject: [PATCH 195/500] Make subscripts proper references --- .../src/stack-graphs.tsg | 4 ++-- .../test/old/compound_literals/objects.js | 21 +++++++++++++------ .../test/old/simple_expressions/comma.js | 7 +++++++ .../simple_expressions/template_strings.js | 4 ++++ .../test/old/simple_expressions/ternary.js | 4 ++++ .../test/old/simple_expressions/variables.js | 9 ++++++++ 6 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/simple_expressions/comma.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/simple_expressions/template_strings.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/simple_expressions/ternary.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/simple_expressions/variables.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 402ec18ed..e918457d7 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3064,7 +3064,6 @@ inherit .return_or_yield edge subscript_expr_push_dot -> @object.value ; this is done differently depending on what the index is - ; attr @index.push "push" = @index, "reference" edge @subscript_expr.value -> @subscript_expr.index_push edge @subscript_expr.index_push -> subscript_expr_push_dot @@ -3075,7 +3074,8 @@ inherit .return_or_yield index: (string)@index)@subscript_expr { - attr (@subscript_expr.index_push) push_symbol = (replace (source-text @index) "[\"\']" "") + attr (@subscript_expr.index_push) symbol_reference = (replace (source-text @index) "[\"\']" ""), source_node = @index + } (subscript_expression diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/objects.js b/languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/objects.js index fe5bf1c55..6d4bb76b5 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/objects.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/compound_literals/objects.js @@ -1,15 +1,24 @@ -let obj = { x: 1, y: 2, 0: "z" }; +let obj = { + x: 1, y: 2, 0: "z" }; + let obj_x = obj.x; +// ^ defined: 1 +// ^ defined: 2 let x = obj_x; -// ^ defined: 1, 2 +// ^ defined: 4, 2 + let obj_y = obj["y"]; +// ^ defined: 1 +// ^ defined: 2 let y = obj_y; -// ^ defined: 1, 5 +// ^ defined: 10, 2 let obj_z = obj[0]; +// ^ defined: 1 +// ^ defined: 2 let z = obj_z; -// ^ defined: 1, 9 +// ^ defined: 16, 2 let obj2 = { x, y }; -// ^ defined: 1, 2, 3 -// ^ defined: 1, 5, 6 +// ^ defined: 7, 4, 2 +// ^ defined: 13, 10, 2 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/simple_expressions/comma.js b/languages/tree-sitter-stack-graphs-javascript/test/old/simple_expressions/comma.js new file mode 100644 index 000000000..58a51610e --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/simple_expressions/comma.js @@ -0,0 +1,7 @@ +let x = 1; +let y = (1, x); +// ^ defined: 1 + +let y = (1, x = 5); +let z = x; +// ^ defined: 1, 5 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/simple_expressions/template_strings.js b/languages/tree-sitter-stack-graphs-javascript/test/old/simple_expressions/template_strings.js new file mode 100644 index 000000000..099cd1d37 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/simple_expressions/template_strings.js @@ -0,0 +1,4 @@ +let x = 1; + +let y = `template ${ x } string`; +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/simple_expressions/ternary.js b/languages/tree-sitter-stack-graphs-javascript/test/old/simple_expressions/ternary.js new file mode 100644 index 000000000..4c7947e5a --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/simple_expressions/ternary.js @@ -0,0 +1,4 @@ +let x = 1; +let y = true ? x++ : 2; +let z = x; +// ^ defined: 1, 2 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/simple_expressions/variables.js b/languages/tree-sitter-stack-graphs-javascript/test/old/simple_expressions/variables.js new file mode 100644 index 000000000..394da591f --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/simple_expressions/variables.js @@ -0,0 +1,9 @@ +let x = 1; +const y = 2; + +var z = x + y; +// ^ defined: 1 +// ^ defined: 2 + +let w = z; +// ^ defined: 1, 2, 4 From 00ea067d0d6df3985d9cadf084a1b6c56a984709 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 13 Oct 2023 15:14:46 +0200 Subject: [PATCH 196/500] Add definiens for CommonJS exports --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index e918457d7..db2aecd64 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4025,6 +4025,7 @@ inherit .return_or_yield edge pop_default_guard -> pop_dot attr (pop_name) node_definition = @property + attr (pop_name) definiens_node = @assignment_expr edge pop_dot -> pop_name edge pop_name -> @right.value @@ -4047,6 +4048,7 @@ inherit .return_or_yield node pop_dot attr (pop_default_guard) symbol_definition = "GUARD:DEFAULT", source_node = @exports + attr (pop_default_guard) definiens_node = @assignment_expr edge @assignment_expr.exports -> pop_default_guard edge pop_default_guard -> @right.value From 271df519f0833301deef085102dc9b2ead7dfe61 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 13 Oct 2023 15:36:11 +0200 Subject: [PATCH 197/500] Fix some default guard definiens --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index db2aecd64..570f11bae 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4074,7 +4074,7 @@ inherit .return_or_yield node default_guard_push - attr (default_guard_push) symbol_reference = "GUARD:DEFAULT", source_node = @require + attr (default_guard_push) symbol_reference = "GUARD:DEFAULT", source_node = @source edge @call_expr.value -> default_guard_push edge default_guard_push -> @source.exports @@ -4114,7 +4114,7 @@ inherit .return_or_yield attr (pop_default) pop_symbol = "default" edge pop_dot -> pop_default - attr (push_guard_default) push_symbol = "GUARD:DEFAULT" + attr (push_guard_default) symbol_reference = "GUARD:DEFAULT", source_node = @source edge pop_default -> push_guard_default edge push_guard_default -> @source.exports From a25b9c4d87c2775df52ea0ea1eac2629e5f8ae43 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 13 Oct 2023 17:02:08 +0200 Subject: [PATCH 198/500] Use statement as definiens like the old code --- .../src/stack-graphs.tsg | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 570f11bae..3b81b02b8 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4067,9 +4067,9 @@ inherit .return_or_yield ( (call_expression - function:(identifier)@require + function:(identifier)@_require arguments:(arguments (string)@source))@call_expr - (#eq? @require "require") + (#eq? @_require "require") ) { node default_guard_push @@ -4266,9 +4266,9 @@ inherit .return_or_yield (generator_function) (arrow_function) (class) - ]@right) { + ])@assignment_expr { - attr (@left.pop) definiens_node = @right + attr (@left.pop) definiens_node = @assignment_expr } @@ -4402,14 +4402,14 @@ inherit .return_or_yield (generator_function) (arrow_function) (class) - ]@value)@pair_expr { + ])@pair_expr { node @name.definiens_hook node name_ignore_guard attr (name_ignore_guard) pop_symbol = "GUARD:GANDALF" attr (@name.definiens_hook) node_definition = @name - attr (@name.definiens_hook) definiens_node = @value + attr (@name.definiens_hook) definiens_node = @pair_expr edge @pair_expr.pkg_pop -> name_ignore_guard edge name_ignore_guard -> @name.definiens_hook From 84015cc6d71838a88c43843aae053dd0b4ac8b44 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 13 Oct 2023 17:17:15 +0200 Subject: [PATCH 199/500] Consolidate syntax type rules --- .../src/stack-graphs.tsg | 107 ++++++++---------- 1 file changed, 47 insertions(+), 60 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 3b81b02b8..731f44764 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4235,30 +4235,6 @@ inherit .return_or_yield ;; do provide at least some information about definiens for these ;; kinds of definitions. -(assignment_expression - left: [ - (identifier)@left - ; (member_expression property:(_)@left) ; FIXME member expressions are references and have no .pop - ] - right: [ - (function) - (generator_function) - (arrow_function) - ]) { - - attr (@left.pop) syntax_type = "function" -} - -(assignment_expression - left: [ - (identifier)@left - ; (member_expression property:(_)@left) ; FIXME member expressions are references and have no .pop - ] - right: (class)) { - - attr (@left.pop) syntax_type = "class" -} - (assignment_expression left: (identifier)@left right: [ @@ -4331,50 +4307,39 @@ inherit .return_or_yield } -(variable_declaration - (variable_declarator - name:(identifier)@name - value: [ - (function) - (generator_function) - (arrow_function) - ])) { - - attr (@name.pop) syntax_type = "function" - -} - -(variable_declaration - (variable_declarator - name:(identifier)@name - value: (class))) { - - attr (@name.pop) syntax_type = "class" - -} - -(lexical_declaration - (variable_declarator - name:(identifier)@name - value: [ +[ + (variable_declaration + (variable_declarator + name:(identifier)@name + value: [ + (function) + (generator_function) + (arrow_function) + ])) + (lexical_declaration + (variable_declarator + name:(identifier)@name + value: [ + (function) + (generator_function) + (arrow_function) + ])) + (assignment_expression + left: [ + (identifier)@name + ; (member_expression property:(_)@name) ; FIXME member expressions are references and have no .pop + ] + right: [ (function) (generator_function) (arrow_function) - ])) { + ]) +] { attr (@name.pop) syntax_type = "function" } -(lexical_declaration - (variable_declarator - name:(identifier)@name - value: (class))) { - - attr (@name.pop) syntax_type = "class" - -} - (pair key: (_)@name value: [ @@ -4387,6 +4352,28 @@ inherit .return_or_yield } + +[ + (variable_declaration + (variable_declarator + name:(identifier)@name + value: (class))) + (lexical_declaration + (variable_declarator + name:(identifier)@name + value: (class))) + (assignment_expression + left: [ + (identifier)@name + ; (member_expression property:(_)@name) ; FIXME member expressions are references and have no .pop + ] + right: (class)) +] { + + attr (@name.pop) syntax_type = "class" + +} + (pair key: (_)@name value: (class)) { From 1178fc26e38a39b930a8af9a9d477ea2a390c7d0 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 13 Oct 2023 17:53:49 +0200 Subject: [PATCH 200/500] Port detour nodes --- .../src/stack-graphs.tsg | 112 +++++++++++++++++- 1 file changed, 109 insertions(+), 3 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 731f44764..35818168d 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -504,11 +504,49 @@ inherit .return_or_yield (export_statement "default" (declaration)@decl)@export_stmt { - node export_stmt_pop_guard_default - attr (export_stmt_pop_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @decl, definiens_node = @export_stmt.export_statement - edge @export_stmt.exports -> export_stmt_pop_guard_default + node pop_guard_default + attr (pop_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @decl, definiens_node = @export_stmt.export_statement + edge @export_stmt.exports -> pop_guard_default ;; edge export_stmt_pop_guard_default -> @decl.value ;; FIXME declarations have no .value + ; !!!! HACK These detour nodes are a massive hack to allow find all refs land on defs + ; for the default values of modules that have useful names like the module name or + ; package name + + node detour_push + node detour_pop + + scan FILE_PATH { + + "^(.+/)?([^/]+)/index\.js$" { + let module_name = $2 + attr (detour_push) push_symbol = module_name + attr (detour_pop) symbol_definition = module_name, source_node = @decl, definiens_node = @export_stmt + edge pop_guard_default -> detour_push + edge detour_push -> detour_pop + ; edge detour_pop -> @decl.value ;; FIXME declarations have no .value + } + + "^(.+/)?([^/]+)\.js$" { + let module_name = $2 + attr (detour_push) push_symbol = module_name + attr (detour_pop) symbol_definition = module_name, source_node = @decl, definiens_node = @export_stmt + edge pop_guard_default -> detour_push + edge detour_push -> detour_pop + ; edge detour_pop -> @decl.value ;; FIXME declarations have no .value + } + + } + + node default_detour_push + node default_detour_pop + + attr (default_detour_push) push_symbol = "default" + attr (default_detour_pop) symbol_definition = "default", source_node = @decl, definiens_node = @decl + edge pop_guard_default -> default_detour_push + edge default_detour_push -> default_detour_pop + ; edge default_detour_pop -> @decl.value ;; FIXME declarations have no .value + } (export_statement @@ -4032,6 +4070,40 @@ inherit .return_or_yield ;; For ES6 interoperability, expose members as named exports edge @assignment_expr.exports -> pop_name + node detour_push + node detour_pop + + scan FILE_PATH { + + "^(.+/)?([^/]+)/index\.js$" { + let module_name = $2 + attr (detour_push) push_symbol = module_name + attr (detour_pop) symbol_definition = module_name, source_node = @assignment_expr, definiens_node = @assignment_expr + edge pop_default_guard -> detour_push + edge detour_push -> detour_pop + edge detour_pop -> @right.value + } + + "^(.+/)?([^/]+)\.js$" { + let module_name = $2 + attr (detour_push) push_symbol = module_name + attr (detour_pop) symbol_definition = module_name, source_node = @assignment_expr, definiens_node = @assignment_expr + edge pop_default_guard -> detour_push + edge detour_push -> detour_pop + edge detour_pop -> @right.value + } + + } + + node default_detour_push + node default_detour_pop + + attr (default_detour_push) push_symbol = "default" + attr (default_detour_pop) symbol_definition = "default", source_node = @assignment_expr, definiens_node = @assignment_expr + edge pop_default_guard -> default_detour_push + edge default_detour_push -> default_detour_pop + edge default_detour_pop -> @right.value + } ( @@ -4057,6 +4129,40 @@ inherit .return_or_yield edge @assignment_expr.exports -> pop_dot edge pop_dot -> @right.value + node detour_push + node detour_pop + + scan FILE_PATH { + + "^(.+/)?([^/]+)/index\.js$" { + let module_name = $2 + attr (detour_push) push_symbol = module_name + attr (detour_pop) symbol_definition = module_name, source_node = @assignment_expr, definiens_node = @assignment_expr + edge pop_default_guard -> detour_push + edge detour_push -> detour_pop + edge detour_pop -> @right.value + } + + "^(.+/)?([^/]+)\.js$" { + let module_name = $2 + attr (detour_push) push_symbol = module_name + attr (detour_pop) symbol_definition = module_name, source_node = @assignment_expr, definiens_node = @assignment_expr + edge pop_default_guard -> detour_push + edge detour_push -> detour_pop + edge detour_pop -> @right.value + } + + } + + node default_detour_push + node default_detour_pop + + attr (default_detour_push) push_symbol = "default" + attr (default_detour_pop) symbol_definition = "default", source_node = @assignment_expr, definiens_node = @assignment_expr + edge pop_default_guard -> default_detour_push + edge default_detour_push -> default_detour_pop + edge default_detour_pop -> @right.value + } ;; ### CommonJS-style Imports From 2a81b45c5c3081e66115c0dc3e0ee231ad63ff3b Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 13 Oct 2023 18:23:24 +0200 Subject: [PATCH 201/500] Add missing expression --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 35818168d..4219fd877 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -2237,6 +2237,7 @@ inherit .return_or_yield (update_expression) (new_expression) (yield_expression) + (spread_element) ]@expr { node @expr.after_scope From 769d9841fc92e2888ab560e98c0cf8f3c9a9a633 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Sat, 14 Oct 2023 17:13:55 +0200 Subject: [PATCH 202/500] Fix scope after member assignment --- .../src/stack-graphs.tsg | 30 ++++++++++++++----- .../array_assignment_interrupts_scope.js | 10 +++++++ 2 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/array_assignment_interrupts_scope.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 4219fd877..ed789146e 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3094,17 +3094,17 @@ inherit .return_or_yield node subscript_expr_push_dot ; scopes flow left to right - edge @object.before_scope -> @subscript_expr.before_scope + edge @object.before_scope -> @subscript_expr.before_scope edge @index.before_scope -> @object.after_scope - edge @subscript_expr.after_scope -> @index.after_scope + edge @subscript_expr.after_scope -> @index.after_scope ; value is a subscript lookup, ie a push then push dot - attr (subscript_expr_push_dot) push_symbol = "GUARD:MEMBER" - edge subscript_expr_push_dot -> @object.value + attr (subscript_expr_push_dot) push_symbol = "GUARD:MEMBER" + edge subscript_expr_push_dot -> @object.value ; this is done differently depending on what the index is - edge @subscript_expr.value -> @subscript_expr.index_push - edge @subscript_expr.index_push -> subscript_expr_push_dot + edge @subscript_expr.value -> @subscript_expr.index_push + edge @subscript_expr.index_push -> subscript_expr_push_dot } @@ -3263,7 +3263,7 @@ inherit .return_or_yield ; scopes flow into the RHS then back out to the whole expr, ; augmented (in subsequent rules) by the LHS edge @right.before_scope -> @assignment_expr.before_scope - + ; value of the whole thing is value of the RHS edge @assignment_expr.value -> @right.value } @@ -3285,6 +3285,21 @@ inherit .return_or_yield } +(assignment_expression + left: [ + (member_expression) + (subscript_expression) + ]@left + right: (_)@right)@assignment_expr { + + ; scope flows from LHS into pattern then back to assignment + edge @left.before_scope -> @assignment_expr.before_scope + + ; ensure the scope flows through the identifier + edge @assignment_expr.after_scope -> @right.after_scope + +} + ; assignment to direct fields on `this` (assignment_expression left: (member_expression @@ -3322,6 +3337,7 @@ inherit .return_or_yield ; scope flows from LHS into pattern then back to assignment edge @left.before_scope -> @right.after_scope edge @assignment_expr.after_scope -> @left.after_scope + } diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/array_assignment_interrupts_scope.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/array_assignment_interrupts_scope.js new file mode 100644 index 000000000..a71218475 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/array_assignment_interrupts_scope.js @@ -0,0 +1,10 @@ +let bar = {}; + +/**/ bar; +// ^ defined: 1 + +/**/ bar["one"] = 1; +// ^ defined: 1 + +/**/ bar; +// ^ defined: 1 From 1475444c7fad87ce56dfb5872316c688305ba5ff Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 16 Oct 2023 14:32:29 +0200 Subject: [PATCH 203/500] Add exponential blowup tests (but skipped) --- .../if_statement_path_blowup.js.skip | 37 +++++++++++++++++++ .../ternary_expression_path_blowup.js.skip | 37 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/if_statement_path_blowup.js.skip create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ternary_expression_path_blowup.js.skip diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/if_statement_path_blowup.js.skip b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/if_statement_path_blowup.js.skip new file mode 100644 index 000000000..98f54e4ab --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/if_statement_path_blowup.js.skip @@ -0,0 +1,37 @@ +let x = 42; + +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } +if (true) { 1 } else { -1 } + +/**/ x; +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ternary_expression_path_blowup.js.skip b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ternary_expression_path_blowup.js.skip new file mode 100644 index 000000000..b0185ce87 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ternary_expression_path_blowup.js.skip @@ -0,0 +1,37 @@ +let x = 42; + +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; +true ? 1 : -1; + +/**/ x; +// ^ defined: 1 From 88351419a8313ea1c56944a1ddd9d8b7a5f72d19 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 16 Oct 2023 20:28:24 +0200 Subject: [PATCH 204/500] Add reference for ES6/CommonJS interop. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index ed789146e..d3d4c05c8 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4262,6 +4262,11 @@ inherit .return_or_yield ;; - property default bound to the value of `export default`, and ;; - other properties bound to named exports (e.g., `foo` binds `export { foo }`). ;; - `require("es6_module")` is not supported. +;; +;; References: +;; +;; - https://nodejs.org/api/esm.html#interoperability-with-commonjs +;; From 2a22ad25dc3c160286dcd9f4875e66db6bb268a1 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 16 Oct 2023 20:51:27 +0200 Subject: [PATCH 205/500] Fix bug with string property keys --- .../src/stack-graphs.tsg | 10 +++++++++- .../string_property_interrupts_scope.js | 6 ++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/string_property_interrupts_scope.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index d3d4c05c8..254445369 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -2535,10 +2535,18 @@ inherit .return_or_yield } -(pair key:(string)@key) { +(pair + key:(string)@key + value:(_)@value)@pair +{ node @key.pop attr (@key.pop) pop_symbol = (replace (source-text @key) "\"" "") + + ; scopes flow into the value, then back to the pair + edge @value.before_scope -> @pair.before_scope + edge @pair.after_scope -> @value.after_scope + } (pair diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/string_property_interrupts_scope.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/string_property_interrupts_scope.js new file mode 100644 index 000000000..a64352e75 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/string_property_interrupts_scope.js @@ -0,0 +1,6 @@ +let x = 42; + +let foo = { "strict": true }; + +/**/ x; +// ^ defined: 1 From cfcd41a6eb48135bc2252d3ac72148cacb5ee143 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 17 Oct 2023 11:55:14 +0200 Subject: [PATCH 206/500] Enable similar path detection by default --- stack-graphs/src/stitching.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index b332389c1..1a84db5ca 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -775,7 +775,7 @@ impl ForwardPartialPathStitcher { initial_paths: next_iteration.0.len(), next_iteration, appended_paths, - similar_path_detector: None, + similar_path_detector: Some(SimilarPathDetector::new()), // By default, there's no artificial bound on the amount of work done per phase max_work_per_phase: usize::MAX, #[cfg(feature = "copious-debugging")] @@ -807,13 +807,13 @@ impl ForwardPartialPathStitcher { /// Sets whether similar path detection should be enabled during path stitching. Paths are similar /// if start and end node, and pre- and postconditions are the same. The presence of similar paths - /// can lead to exponential blow up during path stitching. Similar path detection is disabled by - /// default because of the associated preformance cost. + /// can lead to exponential blow up during path stitching. Similar path detection is enabled by + /// default. pub fn set_similar_path_detection(&mut self, detect_similar_paths: bool) { - if detect_similar_paths { - self.similar_path_detector = Some(SimilarPathDetector::new()); - } else { + if !detect_similar_paths { self.similar_path_detector = None; + } else if self.similar_path_detector.is_none() { + self.similar_path_detector = Some(SimilarPathDetector::new()); } } From a342c0d165444b390b396d26c01f0f4b1f2f9fd8 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 17 Oct 2023 17:30:28 +0200 Subject: [PATCH 207/500] Prefer higher-priority similar paths --- stack-graphs/src/cycles.rs | 12 +++++++----- stack-graphs/src/stitching.rs | 15 ++++++++++++++- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/stack-graphs/src/cycles.rs b/stack-graphs/src/cycles.rs index 51225a06a..eda31e171 100644 --- a/stack-graphs/src/cycles.rs +++ b/stack-graphs/src/cycles.rs @@ -31,6 +31,7 @@ use enumset::EnumSet; use smallvec::SmallVec; +use std::cmp::Ordering; use std::collections::HashMap; use crate::arena::Arena; @@ -97,22 +98,23 @@ where /// Determines whether we should process this path during the path-finding algorithm. If we have seen /// a path with the same start and end node, and the same pre- and postcondition, then we return false. /// Otherwise, we return true. - pub fn has_similar_path( + pub fn has_similar_path( &mut self, _graph: &StackGraph, arena: &mut P::Arena, path: &P, - eq: Eq, + cmp: Cmp, ) -> bool where - Eq: Fn(&mut P::Arena, &P, &P) -> bool, + Cmp: Fn(&mut P::Arena, &P, &P) -> Option, { let key = path.key(); let possibly_similar_paths = self.paths.entry(key).or_default(); for other_path in possibly_similar_paths.iter() { - if eq(arena, path, other_path) { - return true; + match cmp(arena, path, other_path) { + Some(ord) if ord != Ordering::Less => return true, + _ => continue, } } diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index 1a84db5ca..4872afe91 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -35,6 +35,7 @@ //! [`Database`]: struct.Database.html //! [`PathStitcher`]: struct.PathStitcher.html +use std::cmp::Ordering; use std::collections::HashMap; use std::collections::VecDeque; #[cfg(feature = "copious-debugging")] @@ -897,7 +898,19 @@ impl ForwardPartialPathStitcher { graph, partials, &new_partial_path, - |ps, left, right| left.equals(ps, right), + |ps, left, right| { + if !left.equals(ps, right) { + None + } else { + if left.shadows(ps, right) { + Some(Ordering::Less) + } else if right.shadows(ps, left) { + Some(Ordering::Greater) + } else { + Some(Ordering::Equal) + } + } + }, ) { copious_debugging!(" is rejected: too many similar"); continue; From 6fd2a98199ea14bf3cee2136a3ad49dc702dedc9 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 17 Oct 2023 17:32:31 +0200 Subject: [PATCH 208/500] Renable exponential blowup tests --- ..._statement_path_blowup.js.skip => if_statement_path_blowup.js} | 0 ...sion_path_blowup.js.skip => ternary_expression_path_blowup.js} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/{if_statement_path_blowup.js.skip => if_statement_path_blowup.js} (100%) rename languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/{ternary_expression_path_blowup.js.skip => ternary_expression_path_blowup.js} (100%) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/if_statement_path_blowup.js.skip b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/if_statement_path_blowup.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/if_statement_path_blowup.js.skip rename to languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/if_statement_path_blowup.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ternary_expression_path_blowup.js.skip b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ternary_expression_path_blowup.js similarity index 100% rename from languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ternary_expression_path_blowup.js.skip rename to languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/ternary_expression_path_blowup.js From d26ad134357546a1bfb215c35befb07ea7d1be16 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 17 Oct 2023 17:30:28 +0200 Subject: [PATCH 209/500] Prefer higher-priority similar paths --- stack-graphs/src/cycles.rs | 12 +++++++----- stack-graphs/src/stitching.rs | 15 ++++++++++++++- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/stack-graphs/src/cycles.rs b/stack-graphs/src/cycles.rs index 51225a06a..eda31e171 100644 --- a/stack-graphs/src/cycles.rs +++ b/stack-graphs/src/cycles.rs @@ -31,6 +31,7 @@ use enumset::EnumSet; use smallvec::SmallVec; +use std::cmp::Ordering; use std::collections::HashMap; use crate::arena::Arena; @@ -97,22 +98,23 @@ where /// Determines whether we should process this path during the path-finding algorithm. If we have seen /// a path with the same start and end node, and the same pre- and postcondition, then we return false. /// Otherwise, we return true. - pub fn has_similar_path( + pub fn has_similar_path( &mut self, _graph: &StackGraph, arena: &mut P::Arena, path: &P, - eq: Eq, + cmp: Cmp, ) -> bool where - Eq: Fn(&mut P::Arena, &P, &P) -> bool, + Cmp: Fn(&mut P::Arena, &P, &P) -> Option, { let key = path.key(); let possibly_similar_paths = self.paths.entry(key).or_default(); for other_path in possibly_similar_paths.iter() { - if eq(arena, path, other_path) { - return true; + match cmp(arena, path, other_path) { + Some(ord) if ord != Ordering::Less => return true, + _ => continue, } } diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index 1a84db5ca..4872afe91 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -35,6 +35,7 @@ //! [`Database`]: struct.Database.html //! [`PathStitcher`]: struct.PathStitcher.html +use std::cmp::Ordering; use std::collections::HashMap; use std::collections::VecDeque; #[cfg(feature = "copious-debugging")] @@ -897,7 +898,19 @@ impl ForwardPartialPathStitcher { graph, partials, &new_partial_path, - |ps, left, right| left.equals(ps, right), + |ps, left, right| { + if !left.equals(ps, right) { + None + } else { + if left.shadows(ps, right) { + Some(Ordering::Less) + } else if right.shadows(ps, left) { + Some(Ordering::Greater) + } else { + Some(Ordering::Equal) + } + } + }, ) { copious_debugging!(" is rejected: too many similar"); continue; From 7d2389d71cfa89aa9c91b48985b361e59fd8dd37 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 19 Oct 2023 17:15:14 +0200 Subject: [PATCH 210/500] Fix free cycle for index files --- .../src/stack-graphs.tsg | 21 +++++++++++++++++-- ...mport-reexports-from-subdirectory-index.ts | 12 +++++++++++ ...ort-reexports-from-superdirectory-index.ts | 12 +++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/modules/import-reexports-from-subdirectory-index.ts create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/modules/import-reexports-from-superdirectory-index.ts diff --git a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg index 0a2a0d0b5..499022284 100644 --- a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg @@ -687,8 +687,25 @@ if none @is_type { (export_statement "*" source:(_)@name )@export_stmt { - ; export everything from source module - edge @export_stmt.exports -> @name.mod_ref + node expr_pop + node expr_push + attr (expr_pop) pop_symbol = "%E" + attr (expr_push) push_symbol = "%E" + edge expr_pop -> expr_push + + node type_pop + node type_push + attr (type_pop) pop_symbol = "%E" + attr (type_push) push_symbol = "%E" + edge type_pop -> type_push + + ; export all expressions from source module + edge @export_stmt.exports -> expr_pop + edge expr_push -> @name.mod_ref + + ; export all types from source module + edge @export_stmt.exports -> type_pop + edge type_push -> @name.mod_ref } ; export CLAUSE from MODULE diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-reexports-from-subdirectory-index.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-reexports-from-subdirectory-index.ts new file mode 100644 index 000000000..e1871de89 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-reexports-from-subdirectory-index.ts @@ -0,0 +1,12 @@ +/* --- path: foo/index.ts --- */ + +export * from './bar' + +/* --- path: foo/bar.ts --- */ + +export let baz = 42 + +/* --- path: qux.ts --- */ + +import { baz } from './foo' +// ^ defined: 7 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-reexports-from-superdirectory-index.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-reexports-from-superdirectory-index.ts new file mode 100644 index 000000000..c37ae3cf7 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-reexports-from-superdirectory-index.ts @@ -0,0 +1,12 @@ +/* --- path: index.ts --- */ + +export * from './bar' + +/* --- path: bar.ts --- */ + +export let baz = 42 + +/* --- path: foo/qux.ts --- */ + +import { baz } from '..' +// ^ defined: 7 From 3bca8673f5f10459fe540bd06731baeb0be90f2b Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 20 Oct 2023 14:21:30 +0200 Subject: [PATCH 211/500] Add syntax types --- .../src/stack-graphs.tsg | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg index 499022284..d08f4805b 100644 --- a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg @@ -1276,7 +1276,7 @@ if none @is_type { attr (@name.expr_def__ns) pop_symbol = "%E" edge @name.expr_def__ns -> @name.expr_def ; - attr (@name.expr_def) node_definition = @name + attr (@name.expr_def) node_definition = @name, syntax_type = "function" ; function type edge @name.expr_def -> @name.expr_def__typeof @@ -1430,10 +1430,17 @@ if none @is_async { edge @class_decl.type_export -> @class_decl.generic_type } [ - (abstract_class_declaration name:(_)) - (class_declaration name:(_)) + (interface_declaration name:(_)@name) +] { + attr (@name.type_def) syntax_type = "interface" +} +[ + (abstract_class_declaration name:(_)@name) + (class_declaration name:(_)@name) ; NOTE not for interface_declaration as body is already a type with an endpoint of needed ]@class_decl { + attr (@name.type_def) syntax_type = "class" + ; mark type scope as endpoint attr (@class_decl.generic_inner_type) is_endpoint } @@ -1449,7 +1456,7 @@ if none @is_async { attr (@name.expr_def__ns) pop_symbol = "%E" edge @name.expr_def__ns -> @name.expr_def ; - attr (@name.expr_def) node_definition = @name + attr (@name.expr_def) node_definition = @name, syntax_type = "class" ; type of expression is .static_type edge @name.expr_def -> @name.expr_def__typeof @@ -2291,7 +2298,7 @@ if none @is_async { attr (@name.expr_def__ns) pop_symbol = "%E" edge @name.expr_def__ns -> @name.expr_def ; - attr (@name.expr_def) node_definition = @name + attr (@name.expr_def) node_definition = @name, syntax_type = "module" ; namespaces mimic objects with members to access exported expressions edge @name.expr_def -> @name.expr_def__typeof @@ -2311,7 +2318,7 @@ if none @is_async { attr (@name.type_def__ns) pop_symbol = "%T" edge @name.type_def__ns -> @name.type_def ; - attr (@name.type_def) node_definition = @name + attr (@name.type_def) node_definition = @name, syntax_type = "module" ; namespaces mimic types with member types to access exported expressions edge @name.type_def -> @mod.type_member @@ -2353,7 +2360,7 @@ if none @is_async { attr (@name.expr_def__ns) pop_symbol = "%E" edge @name.expr_def__ns -> @name.expr_def ; - attr (@name.expr_def) node_definition = @name + attr (@name.expr_def) node_definition = @name, syntax_type = "module" ; namespaces mimic objects with members to access exported expressions edge @name.expr_def -> @name.expr_def__typeof @@ -2373,7 +2380,7 @@ if none @is_async { attr (@name.type_def__ns) pop_symbol = "%T" edge @name.type_def__ns -> @name.type_def ; - attr (@name.type_def) node_definition = @name + attr (@name.type_def) node_definition = @name, syntax_type = "module" ; namespaces mimic types with member types to access exported expressions edge @name.type_def -> @mod.type_member @@ -2472,7 +2479,7 @@ if none @is_async { attr (@name.expr_def__ns) pop_symbol = "%E" edge @name.expr_def__ns -> @name.expr_def ; - attr (@name.expr_def) node_definition = @name + attr (@name.expr_def) node_definition = @name, syntax_type = "type" ; type of enum expression is members edge @name.expr_def -> @name.expr_def__typeof @@ -2494,7 +2501,7 @@ if none @is_async { attr (@name.type_def__ns) pop_symbol = "%T" edge @name.type_def__ns -> @name.type_def ; - attr (@name.type_def) node_definition = @name + attr (@name.type_def) node_definition = @name, syntax_type = "type" edge @name.type_def -> @enum_decl.type ; edge @enum_decl.type -> @body.type_members @@ -2584,7 +2591,7 @@ if none @is_async { attr (@name.type_def__ns) pop_symbol = "%T" edge @name.type_def__ns -> @name.type_def ; - attr (@name.type_def) node_definition = @name + attr (@name.type_def) node_definition = @name, syntax_type = "type" edge @name.type_def -> @decl.generic_type ; ; type parameters are handled by generics rules below @@ -4468,7 +4475,7 @@ if none @is_async { attr (@sig.member) pop_symbol = "." edge @sig.member -> @name.expr_def ; - attr (@name.expr_def) node_definition = @name + attr (@name.expr_def) node_definition = @name, syntax_type = "field" } (property_signature @@ -4506,7 +4513,7 @@ if none @is_async { attr (@def.member) pop_symbol = "." edge @def.member -> @name.expr_def ; - attr (@name.expr_def) node_definition = @name + attr (@name.expr_def) node_definition = @name, syntax_type = "field" } (public_field_definition @@ -4590,7 +4597,7 @@ if none @is_acc { attr (@mem.member) pop_symbol = "." edge @mem.member -> @name.expr_def ; - attr (@name.expr_def) node_definition = @name + attr (@name.expr_def) node_definition = @name, syntax_type = "method" ; type of method is callable generic type edge @name.expr_def -> @name.expr_def__typeof @@ -4675,7 +4682,7 @@ if none @is_acc { attr (@mem.member) pop_symbol = "." edge @mem.member -> @name.expr_def ; - attr (@name.expr_def) node_definition = @name + attr (@name.expr_def) node_definition = @name, syntax_type = "field" } [ From 7482452cf396d8151f663aafdb6c9edafe23333b Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 25 Oct 2023 14:58:21 +0100 Subject: [PATCH 212/500] Fix panic when error was already reported --- tree-sitter-stack-graphs/src/cli/util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tree-sitter-stack-graphs/src/cli/util.rs b/tree-sitter-stack-graphs/src/cli/util.rs index 66181a1fd..7d50c8a44 100644 --- a/tree-sitter-stack-graphs/src/cli/util.rs +++ b/tree-sitter-stack-graphs/src/cli/util.rs @@ -437,7 +437,7 @@ impl<'a> CLIFileReporter<'a> { status: &str, details: Option<&dyn std::fmt::Display>, ) { - if !self.path_logged { + if !self.path_logged || self.status_logged { return; } self.failure(status, details); From d30ec74c946e2dbe0d4c64aff2146295f8c071a0 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Sun, 22 Oct 2023 13:36:02 +0200 Subject: [PATCH 213/500] Reduce source span for async definitions --- .../tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg index d08f4805b..2d05f5891 100644 --- a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg @@ -6146,7 +6146,7 @@ if none @is_acc { attr (@async.async_type__type_app) push_scoped_symbol = "<>", scope = @async.async_type__type_args edge @async.async_type__type_app -> @async.async_type__promise_ref ; - attr (@async.async_type__promise_ref) symbol_reference = "Promise", source_node = @async + attr (@async.async_type__promise_ref) symbol_reference = "Promise", source_node = @async, empty_source_span edge @async.async_type__promise_ref -> @async.async_type__promise_ref__ns ; attr (@async.async_type__promise_ref__ns) push_symbol = "%T" From e2151cc8c2e5a7aed04ee291f6f1d60ab9b26d44 Mon Sep 17 00:00:00 2001 From: jdonszelmann Date: Mon, 30 Oct 2023 17:07:02 +0100 Subject: [PATCH 214/500] make tree-sitter feature optional Co-authored-by: Terts Diepraam --- stack-graphs/Cargo.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stack-graphs/Cargo.toml b/stack-graphs/Cargo.toml index 2e55e1768..bc08b1d82 100644 --- a/stack-graphs/Cargo.toml +++ b/stack-graphs/Cargo.toml @@ -13,11 +13,13 @@ authors = [ edition = "2018" [features] +default = ["tree-sitter"] bincode = ["dep:bincode", "lsp-positions/bincode"] copious-debugging = [] serde = ["dep:serde", "serde_with", "lsp-positions/serde"] storage = ["bincode", "rusqlite"] visualization = ["serde", "serde_json"] +tree-sitter = ["lsp-positions/tree-sitter"] [lib] # All of our tests are in the tests/it "integration" test executable. @@ -32,7 +34,7 @@ enumset = "1.1" fxhash = "0.2" itertools = "0.10" libc = "0.2" -lsp-positions = { version = "0.3", path = "../lsp-positions" } +lsp-positions = { version = "0.3", path = "../lsp-positions", default-features=false } rusqlite = { version = "0.28", optional = true, features = ["bundled", "functions"] } serde = { version = "1.0", optional = true, features = ["derive"] } serde_json = { version = "1.0", optional = true } From 2038d46d630faf389c864f07499caf409d008134 Mon Sep 17 00:00:00 2001 From: jdonszelmann Date: Mon, 30 Oct 2023 17:40:07 +0100 Subject: [PATCH 215/500] change to dep:tree-sitter Co-authored-by: Terts Diepraam --- lsp-positions/Cargo.toml | 2 +- tree-sitter-stack-graphs/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lsp-positions/Cargo.toml b/lsp-positions/Cargo.toml index 2b2d496b3..058b318f7 100644 --- a/lsp-positions/Cargo.toml +++ b/lsp-positions/Cargo.toml @@ -17,7 +17,7 @@ edition = "2018" test = false [features] -default = ["tree-sitter"] +default = ["dep:tree-sitter"] bincode = ["dep:bincode"] [dependencies] diff --git a/tree-sitter-stack-graphs/Cargo.toml b/tree-sitter-stack-graphs/Cargo.toml index 2d6dabbd1..2de26a86f 100644 --- a/tree-sitter-stack-graphs/Cargo.toml +++ b/tree-sitter-stack-graphs/Cargo.toml @@ -62,7 +62,7 @@ env_logger = { version = "0.9", optional = true } indoc = { version = "1.0", optional = true } itertools = "0.10" log = "0.4" -lsp-positions = { version="0.3", path="../lsp-positions" } +lsp-positions = { version="0.3", path="../lsp-positions", features=["tree-sitter"] } once_cell = "1" pathdiff = { version = "0.2.1", optional = true } regex = "1" From 0bbb98ab2fba6b3e97e1420d07e6384167c407b5 Mon Sep 17 00:00:00 2001 From: jdonszelmann Date: Mon, 30 Oct 2023 17:41:43 +0100 Subject: [PATCH 216/500] remove tree-sitter feature from stack-graphs Co-authored-by: Terts Diepraam --- stack-graphs/Cargo.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stack-graphs/Cargo.toml b/stack-graphs/Cargo.toml index bc08b1d82..e7acaac06 100644 --- a/stack-graphs/Cargo.toml +++ b/stack-graphs/Cargo.toml @@ -13,13 +13,12 @@ authors = [ edition = "2018" [features] -default = ["tree-sitter"] +default = [] bincode = ["dep:bincode", "lsp-positions/bincode"] copious-debugging = [] serde = ["dep:serde", "serde_with", "lsp-positions/serde"] storage = ["bincode", "rusqlite"] visualization = ["serde", "serde_json"] -tree-sitter = ["lsp-positions/tree-sitter"] [lib] # All of our tests are in the tests/it "integration" test executable. From 25b77e9ed173f131d8ca4f2bcabe1f329252f939 Mon Sep 17 00:00:00 2001 From: jdonszelmann Date: Mon, 30 Oct 2023 17:49:49 +0100 Subject: [PATCH 217/500] remove default feature Co-authored-by: Terts Diepraam terts.diepraam@gmail.com --- stack-graphs/Cargo.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stack-graphs/Cargo.toml b/stack-graphs/Cargo.toml index e7acaac06..d756a2c79 100644 --- a/stack-graphs/Cargo.toml +++ b/stack-graphs/Cargo.toml @@ -13,7 +13,6 @@ authors = [ edition = "2018" [features] -default = [] bincode = ["dep:bincode", "lsp-positions/bincode"] copious-debugging = [] serde = ["dep:serde", "serde_with", "lsp-positions/serde"] @@ -33,7 +32,7 @@ enumset = "1.1" fxhash = "0.2" itertools = "0.10" libc = "0.2" -lsp-positions = { version = "0.3", path = "../lsp-positions", default-features=false } +lsp-positions = { version = "0.3", path = "../lsp-positions"} rusqlite = { version = "0.28", optional = true, features = ["bundled", "functions"] } serde = { version = "1.0", optional = true, features = ["derive"] } serde_json = { version = "1.0", optional = true } From 76261f7c84bdb618511526ebd76bce4f93ac0004 Mon Sep 17 00:00:00 2001 From: jdonszelmann Date: Mon, 30 Oct 2023 17:59:34 +0100 Subject: [PATCH 218/500] final suggestions --- lsp-positions/Cargo.toml | 2 +- stack-graphs/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lsp-positions/Cargo.toml b/lsp-positions/Cargo.toml index 058b318f7..242a894ff 100644 --- a/lsp-positions/Cargo.toml +++ b/lsp-positions/Cargo.toml @@ -17,8 +17,8 @@ edition = "2018" test = false [features] -default = ["dep:tree-sitter"] bincode = ["dep:bincode"] +tree-sitter = ["dep:tree-sitter"] [dependencies] memchr = "2.4" diff --git a/stack-graphs/Cargo.toml b/stack-graphs/Cargo.toml index d756a2c79..2e55e1768 100644 --- a/stack-graphs/Cargo.toml +++ b/stack-graphs/Cargo.toml @@ -32,7 +32,7 @@ enumset = "1.1" fxhash = "0.2" itertools = "0.10" libc = "0.2" -lsp-positions = { version = "0.3", path = "../lsp-positions"} +lsp-positions = { version = "0.3", path = "../lsp-positions" } rusqlite = { version = "0.28", optional = true, features = ["bundled", "functions"] } serde = { version = "1.0", optional = true, features = ["derive"] } serde_json = { version = "1.0", optional = true } From 31c0523280bb8d7041b7b09ffce62bb4aa2c78dc Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 31 Oct 2023 15:28:42 -0400 Subject: [PATCH 219/500] Adds many jsx rules Co-Authored-By: Rob Rix --- .../src/stack-graphs.tsg | 249 ++++++++++++++++++ 1 file changed, 249 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 254445369..9d29db8b3 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3476,6 +3476,255 @@ inherit .return_or_yield edge @class.after_scope -> @name.after_scope } +(jsx_element + open_tag:(_)@open_tag + close_tag:(_)@close_tag)@jsx_element { + + node @jsx_element.before_scope + node @jsx_element.after_scope + node @jsx_element.value + + edge @open_tag.before_scope -> @jsx_element.before_scope + edge @jsx_element.after_scope -> @close_tag.after_scope + + ; LATER-TODO scope propagation through empty JSX children + ; currently unsupported by tree sitter queries + ; THIS IS A HUGE HACK AND MUST BE FIXED + edge @close_tag.before_scope -> @open_tag.after_scope + +} + +(jsx_element + open_tag:(_)@open_tag + . + [ + (jsx_text) + (jsx_element) + (jsx_self_closing_element) + (jsx_fragment) + (jsx_expression) + ]@first_child +) { + edge @first_child.before_scope -> @open_tag.after_scope +} + +(jsx_element + [ + (jsx_text) + (jsx_element) + (jsx_self_closing_element) + (jsx_fragment) + (jsx_expression) + ]@left_child + . + [ + (jsx_text) + (jsx_element) + (jsx_self_closing_element) + (jsx_fragment) + (jsx_expression) + ]@right_child +) { + edge @right_child.before_scope -> @left_child.after_scope +} + +(jsx_element + [ + (jsx_text) + (jsx_element) + (jsx_self_closing_element) + (jsx_fragment) + (jsx_expression) + ]@last_child + . + close_tag:(_)@close_tag +) { + edge @close_tag.before_scope -> @last_child.after_scope +} + +(jsx_text)@jsx_text { + node @jsx_text.before_scope + node @jsx_text.after_scope + + edge @jsx_text.after_scope -> @jsx_text.before_scope +} + +(jsx_opening_element + name:(_)@element_name)@jsx_opening_element { + + node @jsx_opening_element.before_scope + node @jsx_opening_element.after_scope + + edge @element_name.before_scope -> @jsx_opening_element.before_scope + +} + +(jsx_opening_element + name:(_)@element_name + !attribute)@jsx_opening_element +{ + + edge @jsx_opening_element.after_scope -> @element_name.after_scope + +} + +(jsx_opening_element + name:(_)@element_name + . + attribute:(_)@first_attr +) { + + edge @first_attr.before_scope -> @element_name.after_scope + +} + +(jsx_opening_element + attribute:(_)@left_attr + . + attribute:(_)@right_attr +) { + + edge @right_attr.before_scope -> @left_attr.after_scope + +} + +(jsx_opening_element + attribute:(_)@last_attr + .)@jsx_opening_element +{ + + edge @jsx_opening_element.after_scope -> @last_attr.after_scope + +} + +(jsx_opening_element name:(identifier)@name) { + + node @name.before_scope + node @name.after_scope + + edge @name.after_scope -> @name.before_scope + +} + +(jsx_attribute)@jsx_attribute { + + node @jsx_attribute.before_scope + node @jsx_attribute.after_scope + + ; LATER-TODO scope propagation through empty child lists + ; currently unsupported by tree sitter queries + ; THIS IS A HUGE HACK AND MUST BE FIXED + edge @jsx_attribute.after_scope -> @jsx_attribute.before_scope + +} + +(jsx_attribute (_) . (_)@attr_value)@jsx_attribute { + + edge @attr_value.before_scope -> @jsx_attribute.before_scope + edge @jsx_attribute.after_scope -> @attr_value.after_scope + +} + +(jsx_self_closing_element + name:(_)@element_name)@jsx_self_closing_element { + + node @jsx_self_closing_element.before_scope + node @jsx_self_closing_element.after_scope + + edge @element_name.before_scope -> @jsx_self_closing_element.before_scope + +} + +(jsx_self_closing_element + name:(_)@element_name + !attribute)@jsx_self_closing_element +{ + + edge @jsx_self_closing_element.after_scope -> @element_name.after_scope + +} + +(jsx_self_closing_element + name:(_)@element_name + . + attribute:(_)@first_attr +) { + + edge @first_attr.before_scope -> @element_name.after_scope + +} + +(jsx_self_closing_element + attribute:(_)@left_attr + . + attribute:(_)@right_attr +) { + + edge @right_attr.before_scope -> @left_attr.after_scope + +} + +(jsx_self_closing_element + attribute:(_)@last_attr + .)@jsx_self_closing_element +{ + + edge @jsx_self_closing_element.after_scope -> @last_attr.after_scope + +} + +(jsx_self_closing_element name:(identifier)@name) { + + node @name.before_scope + node @name.after_scope + + edge @name.after_scope -> @name.before_scope + +} + +(jsx_expression)@jsx_expression { + + node @jsx_expression.before_scope + node @jsx_expression.after_scope + + ; LATER-TODO scope propagation through empty child lists + ; currently unsupported by tree sitter queries + ; THIS IS A HUGE HACK AND MUST BE FIXED + edge @jsx_expression.after_scope -> @jsx_expression.before_scope + +} + +(jsx_expression (_)@child)@jsx_expression { + + edge @child.before_scope -> @jsx_expression.before_scope + edge @jsx_expression.after_scope -> @child.after_scope + +} + +(jsx_closing_element + name:(_)@element_name)@jsx_closing_element +{ + + node @jsx_closing_element.before_scope + node @jsx_closing_element.after_scope + + edge @element_name.before_scope -> @jsx_closing_element.before_scope + edge @jsx_closing_element.after_scope -> @element_name.after_scope + +} + +(jsx_closing_element + name:(_)@element_name) +{ + + node @element_name.before_scope + node @element_name.after_scope + + edge @element_name.after_scope -> @element_name.before_scope + +} + + From a9b8b05ee42ff8dba65b49e378f2e0764beb6972 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 31 Oct 2023 15:56:07 -0400 Subject: [PATCH 220/500] Adds missing self closing element value Co-Authored-By: Rob Rix --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 9d29db8b3..1731fcd59 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3630,6 +3630,7 @@ inherit .return_or_yield node @jsx_self_closing_element.before_scope node @jsx_self_closing_element.after_scope + node @jsx_self_closing_element.value edge @element_name.before_scope -> @jsx_self_closing_element.before_scope From 12ff224f4e73a6340bb99a1cbc032bc108f2abcb Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 31 Oct 2023 18:20:46 -0400 Subject: [PATCH 221/500] Adds jsx_fragment Co-Authored-By: Rob Rix --- .../src/stack-graphs.tsg | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 1731fcd59..812827e0c 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3725,6 +3725,37 @@ inherit .return_or_yield } +(jsx_fragment)@jsx_fragment { + node @jsx_fragment.before_scope + node @jsx_fragment.after_scope + + ; LATER-TODO scope propagation through empty child lists + ; currently unsupported by tree sitter queries + ; THIS IS A HUGE HACK AND MUST BE FIXED + edge @jsx_fragment.after_scope -> @jsx_fragment.before_scope +} + +(jsx_fragment + . + (_)@first_child)@jsx_fragment +{ + edge @first_child.before_scope -> @jsx_fragment.before_scope +} + +(jsx_fragment + (_)@left_child + . + (_)@right_child) +{ + edge @right_child.before_scope -> @left_child.after_scope +} + +(jsx_fragment + (_)@last_child + .)@jsx_fragment +{ + edge @jsx_fragment.after_scope -> @last_child.after_scope +} From 58ee031c8e4b1a1cf303253cee8571ed82ebecc2 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Wed, 1 Nov 2023 15:01:32 -0400 Subject: [PATCH 222/500] Removes hack notes and associated code --- .../src/stack-graphs.tsg | 57 ++++++++----------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 812827e0c..564fb0bb9 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3478,7 +3478,8 @@ inherit .return_or_yield (jsx_element open_tag:(_)@open_tag - close_tag:(_)@close_tag)@jsx_element { + close_tag:(_)@close_tag + (_)*@children)@jsx_element { node @jsx_element.before_scope node @jsx_element.after_scope @@ -3487,10 +3488,9 @@ inherit .return_or_yield edge @open_tag.before_scope -> @jsx_element.before_scope edge @jsx_element.after_scope -> @close_tag.after_scope - ; LATER-TODO scope propagation through empty JSX children - ; currently unsupported by tree sitter queries - ; THIS IS A HUGE HACK AND MUST BE FIXED - edge @close_tag.before_scope -> @open_tag.after_scope + if (is-empty @children) { + edge @close_tag.before_scope -> @open_tag.after_scope + } } @@ -3606,22 +3606,17 @@ inherit .return_or_yield } -(jsx_attribute)@jsx_attribute { +(jsx_attribute (_) . (_)?@attr_value)@jsx_attribute { node @jsx_attribute.before_scope node @jsx_attribute.after_scope - ; LATER-TODO scope propagation through empty child lists - ; currently unsupported by tree sitter queries - ; THIS IS A HUGE HACK AND MUST BE FIXED - edge @jsx_attribute.after_scope -> @jsx_attribute.before_scope - -} - -(jsx_attribute (_) . (_)@attr_value)@jsx_attribute { - - edge @attr_value.before_scope -> @jsx_attribute.before_scope - edge @jsx_attribute.after_scope -> @attr_value.after_scope + if none @attr_value { + edge @jsx_attribute.after_scope -> @jsx_attribute.before_scope + } else { + edge @attr_value.before_scope -> @jsx_attribute.before_scope + edge @jsx_attribute.after_scope -> @attr_value.after_scope + } } @@ -3683,22 +3678,17 @@ inherit .return_or_yield } -(jsx_expression)@jsx_expression { +(jsx_expression (_)?@child)@jsx_expression { node @jsx_expression.before_scope node @jsx_expression.after_scope - ; LATER-TODO scope propagation through empty child lists - ; currently unsupported by tree sitter queries - ; THIS IS A HUGE HACK AND MUST BE FIXED - edge @jsx_expression.after_scope -> @jsx_expression.before_scope - -} - -(jsx_expression (_)@child)@jsx_expression { - - edge @child.before_scope -> @jsx_expression.before_scope - edge @jsx_expression.after_scope -> @child.after_scope + if none @child { + edge @jsx_expression.after_scope -> @jsx_expression.before_scope + } else { + edge @child.before_scope -> @jsx_expression.before_scope + edge @jsx_expression.after_scope -> @child.after_scope + } } @@ -3725,14 +3715,13 @@ inherit .return_or_yield } -(jsx_fragment)@jsx_fragment { +(jsx_fragment (_)*@children)@jsx_fragment { node @jsx_fragment.before_scope node @jsx_fragment.after_scope - ; LATER-TODO scope propagation through empty child lists - ; currently unsupported by tree sitter queries - ; THIS IS A HUGE HACK AND MUST BE FIXED - edge @jsx_fragment.after_scope -> @jsx_fragment.before_scope + if (is-empty @children) { + edge @jsx_fragment.after_scope -> @jsx_fragment.before_scope + } } (jsx_fragment From fd6efe57c18594c105fc208affbf20bceac18864 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Wed, 1 Nov 2023 15:01:48 -0400 Subject: [PATCH 223/500] Removes remnant hack note --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 3 --- 1 file changed, 3 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 564fb0bb9..e23716717 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4034,9 +4034,6 @@ inherit .return_or_yield ;; #### Object Patterns -; LATER-TODO scope propagation through empty object patterns -; currently unsupported by tree sitter queries -; THIS IS A HUGE HACK AND MUST BE FIXED (object_pattern (_)* @entries)@object_pat { if (is-empty @entries) { edge @object_pat.after_scope -> @object_pat.before_scope From 1959db1855ec869928539ff5cfd4134b11341ee7 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 2 Nov 2023 10:16:06 -0700 Subject: [PATCH 224/500] Adds tests and makes them pass --- .../src/stack-graphs.tsg | 14 ++++++- .../test/base_syntax.js | 7 +++- .../test/jsx/jsx_core.js | 40 +++++++++++++++++++ .../test/jsx/jsx_fragment.js | 8 ++++ .../test/jsx/jsx_namespace_name.js | 8 ++++ .../test/jsx/jsx_text.js | 8 ++++ 6 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_core.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_fragment.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_namespace_name.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_text.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index e23716717..1a1bff821 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3597,7 +3597,7 @@ inherit .return_or_yield } -(jsx_opening_element name:(identifier)@name) { +(jsx_opening_element name:(_)@name) { node @name.before_scope node @name.after_scope @@ -3631,6 +3631,17 @@ inherit .return_or_yield } +(jsx_self_closing_element + name:(_)@element_name) +{ + + node @element_name.before_scope + node @element_name.after_scope + + edge @element_name.after_scope -> @element_name.before_scope + +} + (jsx_self_closing_element name:(_)@element_name !attribute)@jsx_self_closing_element @@ -3718,6 +3729,7 @@ inherit .return_or_yield (jsx_fragment (_)*@children)@jsx_fragment { node @jsx_fragment.before_scope node @jsx_fragment.after_scope + node @jsx_fragment.value if (is-empty @children) { edge @jsx_fragment.after_scope -> @jsx_fragment.before_scope diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index 858f854cd..e732ced2a 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -62,4 +62,9 @@ x++; x += 1; (1, 2); 1 ? 2 : 3; -class { }; \ No newline at end of file +class { }; + + + <>doo + {garply} + \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_core.js b/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_core.js new file mode 100644 index 000000000..64e5c3b3b --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_core.js @@ -0,0 +1,40 @@ +// The core of JSX tests here verify the behavior of the following node types: +// jsx_element +// jsx_identifier +// jsx_attribute +// jsx_expression +// jsx_opening_element +// jsx_closing_element +// There is no real way to avoid testing all of these at once, +// and so we don't even try to. + +let x = 1; + +// Flow In + +const el = {x}; +// ^ defined: 11 +// ^ defined: 11 + +// Flow Out + +const el = + {z = 3} +; + +/**/ y; +// ^ defined: 21 + +/**/ z; +// ^ defined: 22 + +// Flow Across + +const el = + {w}; +// ^ defined: 33 + +// Flow Around + +/**/ x; +// ^ defined: 11 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_fragment.js b/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_fragment.js new file mode 100644 index 000000000..02d5f5d68 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_fragment.js @@ -0,0 +1,8 @@ +let x = 1; + +// Flow Around + +const el = <>; + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_namespace_name.js b/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_namespace_name.js new file mode 100644 index 000000000..2c325ed51 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_namespace_name.js @@ -0,0 +1,8 @@ +let x = 1; + +// Flow Around + +const el = ; + +/**/ x; +// ^ defined: 1 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_text.js b/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_text.js new file mode 100644 index 000000000..0cc359765 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_text.js @@ -0,0 +1,8 @@ +let x = 1; + +// Flow Around + +const el = bar; + +/**/ x; +// ^ defined: 1 \ No newline at end of file From 073ed25e67089b7b956991192a18bfdd7b581df7 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 2 Nov 2023 17:05:21 -0700 Subject: [PATCH 225/500] Cleans up element names and makes them reference correctly --- .../src/stack-graphs.tsg | 95 +++++++++++++------ .../test/jsx/jsx_core.js | 14 ++- .../test/jsx/jsx_namespace_name.js | 15 ++- .../test/jsx/jsx_self_closing_element.js | 37 ++++++++ 4 files changed, 126 insertions(+), 35 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_self_closing_element.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 1a1bff821..b8a220f41 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3597,15 +3597,6 @@ inherit .return_or_yield } -(jsx_opening_element name:(_)@name) { - - node @name.before_scope - node @name.after_scope - - edge @name.after_scope -> @name.before_scope - -} - (jsx_attribute (_) . (_)?@attr_value)@jsx_attribute { node @jsx_attribute.before_scope @@ -3631,17 +3622,6 @@ inherit .return_or_yield } -(jsx_self_closing_element - name:(_)@element_name) -{ - - node @element_name.before_scope - node @element_name.after_scope - - edge @element_name.after_scope -> @element_name.before_scope - -} - (jsx_self_closing_element name:(_)@element_name !attribute)@jsx_self_closing_element @@ -3680,15 +3660,6 @@ inherit .return_or_yield } -(jsx_self_closing_element name:(identifier)@name) { - - node @name.before_scope - node @name.after_scope - - edge @name.after_scope -> @name.before_scope - -} - (jsx_expression (_)?@child)@jsx_expression { node @jsx_expression.before_scope @@ -3715,8 +3686,14 @@ inherit .return_or_yield } -(jsx_closing_element - name:(_)@element_name) +[ + (jsx_opening_element + name:(identifier)@element_name) + (jsx_self_closing_element + name:(identifier)@element_name) + (jsx_closing_element + name:(identifier)@element_name) +] { node @element_name.before_scope @@ -3724,6 +3701,62 @@ inherit .return_or_yield edge @element_name.after_scope -> @element_name.before_scope + scan (source-text @element_name) { + ; standard HTML elements + "^(a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdi|bdo|big|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|data|datalist|dd|del|details|dfn|dialog|dir|div|dl|dt|em|embed|fieldset|figcaption|figure|font|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|header|hgroup|hr|html|i|iframe|input|ins|kbd|label|legend|li|link|main|map|mark|menu|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|picture|pre|progress|q|rp|rt|ruby|s|samp|script|search|section|select|small|source|span|strike|strong|style|sub|summary|sup|svg|table|tbody|td|template|textarea|tfoot|th|thead|time|title|tr|track|tt|u|ul|var|video|wbr)$" { + ; do nothing! + } + + ; everything else + "^.+$" { + node element_name_pop + attr (element_name_pop) node_reference = @element_name + edge element_name_pop -> @element_name.before_scope + } + } + +} + +(nested_identifier)@nested_identifier { + node @nested_identifier.before_scope + node @nested_identifier.after_scope + node @nested_identifier.value + + edge @nested_identifier.after_scope -> @nested_identifier.before_scope +} + +(nested_identifier + (identifier)@first_part + (identifier)@second_part)@nested_identifier +{ + node @first_part.value + node @second_part.value + node guard_member + + attr (@first_part.value) node_reference = @first_part + attr (@second_part.value) node_reference = @second_part + attr (guard_member) symbol_reference = "GUARD:MEMBER" + + edge @first_part.value -> @nested_identifier.before_scope + edge guard_member -> @first_part.value + edge @second_part.value -> guard_member + edge @nested_identifier.value -> @second_part.value +} + +(nested_identifier + (nested_identifier)@first_part + (identifier)@second_part)@nested_identifier +{ + node @second_part.value + node guard_member + + attr (@second_part.value) node_reference = @second_part + attr (guard_member) symbol_reference = "GUARD:MEMBER" + + edge @first_part.before_scope -> @nested_identifier.before_scope + edge guard_member -> @first_part.value + edge @second_part.value -> guard_member + edge @nested_identifier.value -> @second_part.value } (jsx_fragment (_)*@children)@jsx_fragment { diff --git a/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_core.js b/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_core.js index 64e5c3b3b..fc0674833 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_core.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_core.js @@ -16,6 +16,10 @@ const el = {x}; // ^ defined: 11 // ^ defined: 11 +const el2 = +// ^ defined: 11 +// ^ defined: 11 + // Flow Out const el = @@ -23,16 +27,20 @@ const el = ; /**/ y; -// ^ defined: 21 +// ^ defined: 25 /**/ z; -// ^ defined: 22 +// ^ defined: 26 // Flow Across const el = {w}; -// ^ defined: 33 +// ^ defined: 37 + +const el = ; +// ^ defined: 41 // Flow Around diff --git a/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_namespace_name.js b/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_namespace_name.js index 2c325ed51..ec59c3dca 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_namespace_name.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_namespace_name.js @@ -5,4 +5,17 @@ let x = 1; const el = ; /**/ x; -// ^ defined: 1 \ No newline at end of file +// ^ defined: 1 + +// Flow In + +let foo = { + bar: { + baz: 1 + } +}; + +const el2 = ; +// ^ defined: 12 +// ^ defined: 13 +// ^ defined: 14 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_self_closing_element.js b/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_self_closing_element.js new file mode 100644 index 000000000..937ca0970 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/jsx/jsx_self_closing_element.js @@ -0,0 +1,37 @@ +// The core of JSX tests here verify the behavior of the following node types: +// jsx_element +// jsx_identifier +// jsx_attribute +// jsx_expression +// jsx_opening_element +// jsx_closing_element +// There is no real way to avoid testing all of these at once, +// and so we don't even try to. + +let x = 1; + +// Flow In + +const el = ; +// ^ defined: 11 + +const el2 = +// ^ defined: 11 + +// Flow Out + +const el = ; + +/**/ y; +// ^ defined: 23 + +// Flow Across + +const el = ; +// ^ defined: 30 + +// Flow Around + +/**/ x; +// ^ defined: 11 \ No newline at end of file From 9ffe369f72bfe7b9b30a0cf3b301e4e2573d8a95 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Fri, 3 Nov 2023 15:30:50 -0700 Subject: [PATCH 226/500] Adds definiens for module name --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index b8a220f41..6b644d02f 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -327,6 +327,7 @@ inherit .return_or_yield edge @prog.before_scope -> @prog.hoist_point attr (prog_module_scope) pop_symbol = "GUARD:MODULE" + attr (prog_module_pop_start) definiens = @prog edge @prog.pkg_pop -> prog_module_pop_start edge module_pop_end -> prog_module_scope edge prog_module_scope -> @prog.after_scope From b2fc0434435b2a9ec6e783a5dccea25130856abb Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Fri, 3 Nov 2023 15:40:13 -0700 Subject: [PATCH 227/500] Ibid. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 6b644d02f..bdc5d3f22 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -320,6 +320,7 @@ inherit .return_or_yield "([^/]+)$" { attr (module_pop_end) symbol_definition = $1, source_node = @prog attr (module_pop_end) empty_source_span + attr (module_pop_end) definiens = @prog } } @@ -327,7 +328,6 @@ inherit .return_or_yield edge @prog.before_scope -> @prog.hoist_point attr (prog_module_scope) pop_symbol = "GUARD:MODULE" - attr (prog_module_pop_start) definiens = @prog edge @prog.pkg_pop -> prog_module_pop_start edge module_pop_end -> prog_module_scope edge prog_module_scope -> @prog.after_scope From 67014222d1522e769508b6a3595f60ce895f9594 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Fri, 3 Nov 2023 17:07:28 -0700 Subject: [PATCH 228/500] Removes empty source span for prog node --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index bdc5d3f22..895099776 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -319,7 +319,7 @@ inherit .return_or_yield } "([^/]+)$" { attr (module_pop_end) symbol_definition = $1, source_node = @prog - attr (module_pop_end) empty_source_span + ;; attr (module_pop_end) empty_source_span attr (module_pop_end) definiens = @prog } } From 4a480e938f2457a789133b219b2c9722e3afce1b Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Fri, 3 Nov 2023 18:42:36 -0700 Subject: [PATCH 229/500] Revert "Removes empty source span for prog node" This reverts commit 67014222d1522e769508b6a3595f60ce895f9594. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 895099776..bdc5d3f22 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -319,7 +319,7 @@ inherit .return_or_yield } "([^/]+)$" { attr (module_pop_end) symbol_definition = $1, source_node = @prog - ;; attr (module_pop_end) empty_source_span + attr (module_pop_end) empty_source_span attr (module_pop_end) definiens = @prog } } From d4fae16c72e9920bfffac1e65a85ec4653c86d29 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Mon, 6 Nov 2023 12:24:31 -0800 Subject: [PATCH 230/500] Fixes definiens attr name Co-Authored-By: Rob Rix --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index bdc5d3f22..ecdc9bf30 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -320,7 +320,7 @@ inherit .return_or_yield "([^/]+)$" { attr (module_pop_end) symbol_definition = $1, source_node = @prog attr (module_pop_end) empty_source_span - attr (module_pop_end) definiens = @prog + attr (module_pop_end) definiens_node = @prog } } From 40e1c3def1c965cf6bd29e9faafd67153cfc5ede Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 7 Nov 2023 14:01:16 +0100 Subject: [PATCH 231/500] Fix rustc warnings --- tree-sitter-stack-graphs/src/loader.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tree-sitter-stack-graphs/src/loader.rs b/tree-sitter-stack-graphs/src/loader.rs index 1620334ce..0feb6a28c 100644 --- a/tree-sitter-stack-graphs/src/loader.rs +++ b/tree-sitter-stack-graphs/src/loader.rs @@ -700,11 +700,11 @@ impl PathLoader { graph: &mut StackGraph, cancellation_flag: &dyn CancellationFlag, ) -> Result<(), LoadError<'static>> { - let source = std::fs::read_to_string(builtins_path.clone())?; + let source = std::fs::read_to_string(builtins_path)?; let mut config_path = builtins_path.to_path_buf(); config_path.set_extension("cfg"); let config = if config_path.exists() { - std::fs::read_to_string(builtins_path.clone())? + std::fs::read_to_string(builtins_path)? } else { "".into() }; From df0b8c088f94c6df4372af7d9387181678a9a7a6 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 7 Nov 2023 18:47:09 +0100 Subject: [PATCH 232/500] Support main module configuration in `package.json` --- .../rust/npm_package.rs | 37 ++++++++++---- .../rust/tsconfig.rs | 12 ++--- .../can-access-package-non-main-explicilty.ts | 51 +++++++++++++++++++ .../package-does-not-export-non-main.ts | 44 ++++++++++++++++ .../packages/package-exports-explicit-main.ts | 51 +++++++++++++++++++ .../package-invisible-without-dependency.ts | 12 +++-- .../package-main-defaults-to-index.ts | 50 ++++++++++++++++++ 7 files changed, 237 insertions(+), 20 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/packages/can-access-package-non-main-explicilty.ts create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/packages/package-does-not-export-non-main.ts create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/packages/package-exports-explicit-main.ts rename languages/tree-sitter-stack-graphs-typescript/test/{projects => packages}/package-invisible-without-dependency.ts (98%) create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/packages/package-main-defaults-to-index.ts diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/npm_package.rs b/languages/tree-sitter-stack-graphs-typescript/rust/npm_package.rs index 9b67db598..b7351454a 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/npm_package.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/npm_package.rs @@ -8,6 +8,7 @@ use serde::Deserialize; use std::collections::HashMap; use std::path::Path; +use std::path::PathBuf; use stack_graphs::arena::Handle; use stack_graphs::graph::File; @@ -15,6 +16,7 @@ use stack_graphs::graph::StackGraph; use tree_sitter_stack_graphs::BuildError; use tree_sitter_stack_graphs::FileAnalyzer; +use crate::tsconfig::NormalizedRelativePath; use crate::util::*; pub struct NpmPackageAnalyzer {} @@ -74,16 +76,28 @@ impl FileAnalyzer for NpmPackageAnalyzer { }; // package definition - let pkg_def = add_module_pops( - graph, - file, - NON_REL_M_NS, - Path::new(&npm_pkg.name), - root, - "npm_package.pkg_def", - ); - let pkg_ref = add_push(graph, file, proj_scope, PKG_M_NS, "npm_package.pkg_ref"); - add_edge(graph, pkg_def, pkg_ref, 0); + if !npm_pkg.name.is_empty() { + let pkg_def = add_module_pops( + graph, + file, + NON_REL_M_NS, + Path::new(&npm_pkg.name), + root, + "npm_package.pkg_def", + ); + let pkg_ref = add_push(graph, file, proj_scope, PKG_M_NS, "npm_package.pkg_ref"); + add_edge(graph, pkg_def, pkg_ref, 0); + + let main = Some(npm_pkg.main) + .filter(|main| !main.is_empty()) + .and_then(|main| NormalizedRelativePath::from_str(&main)) + .map(|p| p.into_path_buf()) + .unwrap_or(PathBuf::from("index")) + .with_extension(""); + let main_ref = + add_module_pushes(graph, file, M_NS, &main, proj_scope, "npm_package.main_ref"); + add_edge(graph, pkg_def, main_ref, 0); + } // dependencies (package references) for (i, (pkg_name, _)) in npm_pkg.dependencies.iter().enumerate() { @@ -113,7 +127,10 @@ impl FileAnalyzer for NpmPackageAnalyzer { #[derive(Default, Debug, Clone, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct NpmPackage { + #[serde(default)] pub name: String, #[serde(default)] + pub main: String, + #[serde(default)] pub dependencies: HashMap, } diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/tsconfig.rs b/languages/tree-sitter-stack-graphs-typescript/rust/tsconfig.rs index c885c298f..5c9ecae28 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/tsconfig.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/tsconfig.rs @@ -498,15 +498,15 @@ fn longest_common_prefix(left: &Path, right: &Path) -> Option { Some(prefix) } -struct NormalizedRelativePath(PathBuf); +pub(crate) struct NormalizedRelativePath(PathBuf); impl NormalizedRelativePath { - pub(self) fn from_str(path: &str) -> Option { + pub(crate) fn from_str(path: &str) -> Option { Self::from_path(Path::new(path)) } /// Creates a new normalized, relative path from a path. - pub(self) fn from_path(path: &Path) -> Option { + pub(crate) fn from_path(path: &Path) -> Option { let mut np = PathBuf::new(); let mut normal_components = 0usize; for c in path.components() { @@ -538,18 +538,18 @@ impl NormalizedRelativePath { } /// Returns if the relative path escapes to the parent. - pub(self) fn escapes(&self) -> bool { + pub(crate) fn escapes(&self) -> bool { self.0 .components() .next() .map_or(false, |c| c == Component::ParentDir) } - pub(self) fn as_path(&self) -> &Path { + pub(crate) fn as_path(&self) -> &Path { &self.0 } - pub(self) fn into_path_buf(self) -> PathBuf { + pub(crate) fn into_path_buf(self) -> PathBuf { self.0 } } diff --git a/languages/tree-sitter-stack-graphs-typescript/test/packages/can-access-package-non-main-explicilty.ts b/languages/tree-sitter-stack-graphs-typescript/test/packages/can-access-package-non-main-explicilty.ts new file mode 100644 index 000000000..dda91f57b --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/packages/can-access-package-non-main-explicilty.ts @@ -0,0 +1,51 @@ +/* --- path: acme_foo/tsconfig.json --- */ +/* --- global: FILE_PATH=tsconfig.json --- */ +/* --- global: PROJECT_NAME=acme_foo --- */ + +{} + +/* --- path: acme_foo/package.json --- */ +/* --- global: FILE_PATH=package.json --- */ +/* --- global: PROJECT_NAME=acme_foo --- */ + +{ + "name": "@acme/foo", + "version": "1.0", + "main": "./api" +} + +/* --- path: acme_foo/api.ts --- */ +/* --- global: FILE_PATH=api.ts --- */ +/* --- global: PROJECT_NAME=acme_foo --- */ + +export let x; + +/* --- path: acme_foo/core.ts --- */ +/* --- global: FILE_PATH=core.ts --- */ +/* --- global: PROJECT_NAME=acme_foo --- */ + +export let x; + +/* --- path: bar/tsconfig.json --- */ +/* --- global: FILE_PATH=tsconfig.json --- */ +/* --- global: PROJECT_NAME=bar --- */ + +{} + +/* --- path: bar/package.json --- */ +/* --- global: FILE_PATH=package.json --- */ +/* --- global: PROJECT_NAME=bar --- */ + +{ + "name": "bar", + "dependencies": { + "@acme/foo": "1" + } +} + +/* --- path: bar/app.ts --- */ +/* --- global: FILE_PATH=app.ts --- */ +/* --- global: PROJECT_NAME=bar --- */ + +import { x } from "@acme/foo/core" +// ^ defined: 27 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/packages/package-does-not-export-non-main.ts b/languages/tree-sitter-stack-graphs-typescript/test/packages/package-does-not-export-non-main.ts new file mode 100644 index 000000000..d39b0d79f --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/packages/package-does-not-export-non-main.ts @@ -0,0 +1,44 @@ +/* --- path: foo/tsconfig.json --- */ +/* --- global: FILE_PATH=tsconfig.json --- */ +/* --- global: PROJECT_NAME=foo --- */ + +{} + +/* --- path: foo/package.json --- */ +/* --- global: FILE_PATH=package.json --- */ +/* --- global: PROJECT_NAME=foo --- */ + +{ + "name": "foo", + "version": "1.0" +} + +/* --- path: foo/impl.ts --- */ +/* --- global: FILE_PATH=impl.ts --- */ +/* --- global: PROJECT_NAME=foo --- */ + +export let x; + +/* --- path: bar/tsconfig.json --- */ +/* --- global: FILE_PATH=tsconfig.json --- */ +/* --- global: PROJECT_NAME=bar --- */ + +{} + +/* --- path: bar/package.json --- */ +/* --- global: FILE_PATH=package.json --- */ +/* --- global: PROJECT_NAME=bar --- */ + +{ + "name": "bar", + "dependencies": { + "foo": "1" + } +} + +/* --- path: bar/app.ts --- */ +/* --- global: FILE_PATH=app.ts --- */ +/* --- global: PROJECT_NAME=bar --- */ + +import { x } from "foo" +// ^ defined: diff --git a/languages/tree-sitter-stack-graphs-typescript/test/packages/package-exports-explicit-main.ts b/languages/tree-sitter-stack-graphs-typescript/test/packages/package-exports-explicit-main.ts new file mode 100644 index 000000000..f6a4f5e45 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/packages/package-exports-explicit-main.ts @@ -0,0 +1,51 @@ +/* --- path: acme_foo/tsconfig.json --- */ +/* --- global: FILE_PATH=tsconfig.json --- */ +/* --- global: PROJECT_NAME=acme_foo --- */ + +{} + +/* --- path: acme_foo/package.json --- */ +/* --- global: FILE_PATH=package.json --- */ +/* --- global: PROJECT_NAME=acme_foo --- */ + +{ + "name": "@acme/foo", + "version": "1.0", + "main": "./api" +} + +/* --- path: acme_foo/api.ts --- */ +/* --- global: FILE_PATH=api.ts --- */ +/* --- global: PROJECT_NAME=acme_foo --- */ + +export let x; + +/* --- path: acme_foo/core.ts --- */ +/* --- global: FILE_PATH=core.ts --- */ +/* --- global: PROJECT_NAME=acme_foo --- */ + +export let x; + +/* --- path: bar/tsconfig.json --- */ +/* --- global: FILE_PATH=tsconfig.json --- */ +/* --- global: PROJECT_NAME=bar --- */ + +{} + +/* --- path: bar/package.json --- */ +/* --- global: FILE_PATH=package.json --- */ +/* --- global: PROJECT_NAME=bar --- */ + +{ + "name": "bar", + "dependencies": { + "@acme/foo": "1" + } +} + +/* --- path: bar/app.ts --- */ +/* --- global: FILE_PATH=app.ts --- */ +/* --- global: PROJECT_NAME=bar --- */ + +import { x } from "@acme/foo" +// ^ defined: 21 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/package-invisible-without-dependency.ts b/languages/tree-sitter-stack-graphs-typescript/test/packages/package-invisible-without-dependency.ts similarity index 98% rename from languages/tree-sitter-stack-graphs-typescript/test/projects/package-invisible-without-dependency.ts rename to languages/tree-sitter-stack-graphs-typescript/test/packages/package-invisible-without-dependency.ts index ca9852a68..c7c0458ff 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/package-invisible-without-dependency.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/packages/package-invisible-without-dependency.ts @@ -1,6 +1,7 @@ /* --- path: ./my_lib/package.json --- */ /* --- global: FILE_PATH=package.json --- */ /* --- global: PROJECT_NAME=my_lib --- */ + { "name": "@my/lib" } @@ -8,17 +9,19 @@ /* --- path: ./my_lib/tsconfig.json --- */ /* --- global: FILE_PATH=tsconfig.json --- */ /* --- global: PROJECT_NAME=my_lib --- */ -{ -} + +{} /* --- path: ./my_lib/src/foo.ts --- */ /* --- global: FILE_PATH=src/foo.ts --- */ /* --- global: PROJECT_NAME=my_lib --- */ + export const bar = 42; /* --- path: ./my_app/package.json --- */ /* --- global: FILE_PATH=package.json --- */ /* --- global: PROJECT_NAME=my_app --- */ + { "name": "@my/app" } @@ -26,11 +29,12 @@ export const bar = 42; /* --- path: ./my_app/tsconfig.json --- */ /* --- global: FILE_PATH=tsconfig.json --- */ /* --- global: PROJECT_NAME=my_app --- */ -{ -} + +{} /* --- path: ./my_app/src/index.ts --- */ /* --- global: FILE_PATH=src/index.ts --- */ /* --- global: PROJECT_NAME=my_app --- */ + import { bar } from "@my/lib/foo"; // ^ defined: diff --git a/languages/tree-sitter-stack-graphs-typescript/test/packages/package-main-defaults-to-index.ts b/languages/tree-sitter-stack-graphs-typescript/test/packages/package-main-defaults-to-index.ts new file mode 100644 index 000000000..b7983551d --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/packages/package-main-defaults-to-index.ts @@ -0,0 +1,50 @@ +/* --- path: foo/tsconfig.json --- */ +/* --- global: FILE_PATH=tsconfig.json --- */ +/* --- global: PROJECT_NAME=foo --- */ + +{} + +/* --- path: foo/package.json --- */ +/* --- global: FILE_PATH=package.json --- */ +/* --- global: PROJECT_NAME=foo --- */ + +{ + "name": "foo", + "version": "1.0" +} + +/* --- path: foo/index.ts --- */ +/* --- global: FILE_PATH=index.ts --- */ +/* --- global: PROJECT_NAME=foo --- */ + +export let x; + +/* --- path: foo/impl.ts --- */ +/* --- global: FILE_PATH=impl.ts --- */ +/* --- global: PROJECT_NAME=foo --- */ + +export let x; + +/* --- path: bar/tsconfig.json --- */ +/* --- global: FILE_PATH=tsconfig.json --- */ +/* --- global: PROJECT_NAME=bar --- */ + +{} + +/* --- path: bar/package.json --- */ +/* --- global: FILE_PATH=package.json --- */ +/* --- global: PROJECT_NAME=bar --- */ + +{ + "name": "bar", + "dependencies": { + "foo": "1" + } +} + +/* --- path: bar/app.ts --- */ +/* --- global: FILE_PATH=app.ts --- */ +/* --- global: PROJECT_NAME=bar --- */ + +import { x } from "foo" +// ^ defined: 20 From 8ab41844775d8803c602cefc2d4d477cdb28a2fb Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 9 Nov 2023 12:43:24 +0100 Subject: [PATCH 233/500] Color nodes by file --- .../src/visualization/visualization.css | 233 ++++++++++++++---- .../src/visualization/visualization.js | 45 +++- 2 files changed, 221 insertions(+), 57 deletions(-) diff --git a/stack-graphs/src/visualization/visualization.css b/stack-graphs/src/visualization/visualization.css index 360594182..c5cc80151 100644 --- a/stack-graphs/src/visualization/visualization.css +++ b/stack-graphs/src/visualization/visualization.css @@ -9,15 +9,33 @@ /* Paul Tol's Colorblind Friendly Color Scheme (vibrant) * Source: https://personal.sron.nl/~pault/ * + * In default order: + * + * orange #ee7733 * blue #0077bb * cyan #33bbee - * teal #009988 - * orange #ee7733 - * red #cc3311 * magenta #ee3377 + * red #cc3311 + * teal #009988 * grey #bbbbbb */ +/* Paul Tol's Colorblind Friendly Color Scheme (light) + * Source: https://personal.sron.nl/~pault/ + * + * In default order: + * + * light blue #77aadd + * orange #ee8866 + * light yellow #eedd88 + * pink #ffaabb + * light cyan #99ddff + * mint #44bb99 + * pear #bbcc33 + * olive #aaaa00 + * pale grey #dddddd + */ + .sg { width: 100%; height: 100%; @@ -50,52 +68,25 @@ /* --- drop scopes --- */ .sg .node.drop_scopes .background { - fill: #cc3311; r: 6px; } /* --- jump to scope --- */ .sg .node.jump_to_scope .background { - fill: #ee7733; r: 6px; - stroke: black; } /* --- pop symbol --- */ -.sg .node.pop_symbol .background, -.sg .node.pop_scoped_symbol .background { - fill: #009988; -} - -.sg .node.pop_symbol .arrow, -.sg .node.pop_scoped_symbol .arrow { - fill: #005b51; -} - .sg .node.pop_scoped_symbol .pop_scope { fill: #ee7733; r: 6px; stroke: black; } -.sg .node.definition .background { - stroke: black; -} - /* --- push symbol --- */ -.sg .node.push_symbol .background, -.sg .node.push_scoped_symbol .background { - fill: #33bbee; -} - -.sg .node.push_symbol .arrow, -.sg .node.push_scoped_symbol .arrow { - fill: #006e96; -} - .sg .node.push_scoped_symbol .push_scope { fill: #bbbbbb; r: 6px; @@ -111,16 +102,10 @@ fill: black; } -.sg .node.reference .background { - stroke: black; -} - /* --- root --- */ .sg .node.root .background { - fill: #0077bb; r: 6px; - stroke: black; } /* --- scope --- */ @@ -131,14 +116,9 @@ } .sg .node.scope .background { - fill: #bbbbbb; r: 6px; } -.sg .node.scope.exported .background { - stroke: black; -} - .sg .node.scope .focus-point { r: 3px; fill: none; @@ -156,7 +136,6 @@ } .sg .node.scope.plain_labeled_node .background { - fill: #bbbbbb; rx: 6px; } @@ -167,7 +146,6 @@ /* --- path highlight --- */ .sg .node.path-node .border { - stroke: #ee3377; stroke-width: 4px; stroke-dasharray: 5, 5; } @@ -185,30 +163,21 @@ } .sg .edge path { - stroke: black; stroke-width: 1px; fill: none; } .sg .edge text { font-size: 11pt; - stroke: black; stroke-width: 1px; dominant-baseline: central; } .sg .edge.path-edge path { - stroke: #ee3377; stroke-width: 3px; } -.sg .edge.path-edge text -{ - stroke: #ee3377; - fill: #ee3377; -} - /* ------------------------------------------------------------------------------------------------ * Jumps */ @@ -442,3 +411,163 @@ margin: 0px 6px; cursor: pointer; } + +/* ------------------------------------------------------------------------------------------------ + * Colors + */ + +.sg .node.global .background { + fill: #0077bb; /* blue */ +} +.sg .edge.global path, +.sg .edge.global text { + stroke: #0077bb; /* blue */ +} + +.sg .node.file-0 .background { + fill: #77aadd; /* light blue */ +} + +.sg .node.file-0 .arrow, +.sg .edge.file-0 text +{ + fill: #0e2236; /* light blue (darkened) */ +} +.sg .node.file-0.reference .background, +.sg .node.file-0.definition .background, +.sg .node.file-0.scope.exported .background, +.sg .edge.file-0 path, +.sg .edge.file-0 text +{ + stroke: #0e2236; /* light blue (darkened) */ +} + +.sg .node.file-1 .background, +.sg .edge.file-1 text +{ + fill: #ee8866; /* orange */ +} +.sg .node.file-1 .arrow { + fill: #3d1407; /* orange (darkened) */ +} +.sg .node.file-1.reference .background, +.sg .node.file-1.definition .background, +.sg .node.file-1.scope.exported .background, +.sg .edge.file-1 path, +.sg .edge.file-1 text +{ + stroke: #3d1407; /* orange (darkened) */ +} + +.sg .node.file-2 .background, +.sg .edge.file-2 text +{ + fill: #eedd88; /* light yellow */ +} +.sg .node.file-2 .arrow { + fill: #413809; /* light yellow (darkened) */ +} +.sg .node.file-2.reference .background, +.sg .node.file-2.definition .background, +.sg .node.file-2.scope.exported .background, +.sg .edge.file-2 path, +.sg .edge.file-2 text +{ + stroke: #413809; /* light yellow (darkened) */ +} + +.sg .node.file-3 .background, +.sg .edge.file-3 text +{ + fill: #ffaabb; /* pink */ +} +.sg .node.file-3 .arrow { + fill: #550011; /* pink (darkened) */ +} +.sg .node.file-3.reference .background, +.sg .node.file-3.definition .background, +.sg .node.file-3.scope.exported .background, +.sg .edge.file-3 path, +.sg .edge.file-3 text +{ + stroke: #550011; /* pink (darkened) */ +} + +.sg .node.file-4 .background, +.sg .edge.file-4 text +{ + fill: #99ddff; /* light cyan */ +} +.sg .node.file-4 .arrow { + fill: #003652; /* light cyan (darkened) */ +} +.sg .node.file-4.reference .background, +.sg .node.file-4.definition .background, +.sg .node.file-4.scope.exported .background, +.sg .edge.file-4 path, +.sg .edge.file-4 text +{ + stroke: #003652; /* light cyan (darkened) */ +} + +.sg .node.file-5 .background, +.sg .edge.file-5 text +{ + fill: #44bb99; /* mint */ +} +.sg .node.file-5 .arrow { + fill: #0e251f; /* mint (darkened) */ +} +.sg .node.file-5.reference .background, +.sg .node.file-5.definition .background, +.sg .node.file-5.scope.exported .background, +.sg .edge.file-5 path, +.sg .edge.file-5 text +{ + stroke: #0e251f; /* mint (darkened) */ +} + +.sg .node.file-6 .background, +.sg .edge.file-6 text +{ + fill: #bbcc33; /* pear */ +} +.sg .node.file-6 .arrow { + fill: #25290a; /* pear (darkened) */ +} +.sg .node.file-6.reference .background, +.sg .node.file-6.definition .background, +.sg .node.file-6.scope.exported .background, +.sg .edge.file-6 path, +.sg .edge.file-6 text +{ + stroke: #25290a; /* pear (darkened) */ +} + +.sg .node.file-7 .background, +.sg .edge.file-7 text +{ + fill: #aaaa00; /* olive */ +} +.sg .node.file-7 .arrow { + fill: #222200; /* olive (darkened) */ +} +.sg .node.file-7.reference .background, +.sg .node.file-7.definition .background, +.sg .node.file-7.scope.exported .background, +.sg .edge.file-7 path, +.sg .edge.file-7 text +{ + stroke: #222200; /* olive (darkened) */ +} + +.sg .node.path-node .border, +.sg .edge.path-edge path, +.sg .edge.path-edge text +{ + stroke: #ee7733; +} + +.sg .edge.path-edge text { + fill: #ee7733; +} diff --git a/stack-graphs/src/visualization/visualization.js b/stack-graphs/src/visualization/visualization.js index a1d9bbaac..7e5183973 100644 --- a/stack-graphs/src/visualization/visualization.js +++ b/stack-graphs/src/visualization/visualization.js @@ -17,6 +17,8 @@ class StackGraph { static arrow_head_w = 16; static arrow_head_h = 8; + static number_of_file_colors = 8; + constructor(container, graph, paths, metadata) { this.metadata = metadata; @@ -32,12 +34,22 @@ class StackGraph { } compute_data() { + this.F = {}; this.ID = {}; this.N = []; + this.compute_file_data(); this.compute_node_data(); this.compute_path_data(); } + compute_file_data() { + for (let i in graph.files) { + const file = graph.files[i]; + this.F[file] = i; + } + console.log(this.F); + } + compute_node_data() { for (let i in graph.nodes) { const node = graph.nodes[i]; @@ -225,7 +237,7 @@ class StackGraph { .data(dag.links()) .enter() .append("g") - .attr("class", (d) => d.data.is_jump ? "jump" : "edge") + .attr("class", (d) => `${d.data.is_jump ? "jump" : "edge"} ${this.edge_to_file_class(d.data)}`) .attr("id", (d) => this.edge_to_id_str(d.data)); edges.append("path") .attr("id", (d) => this.edge_to_id_str(d.data) + ":path") @@ -286,14 +298,14 @@ class StackGraph { render_node(node, g) { g.attr('id', this.node_to_id_str(node)); - g.attr('class', `node ${node.type}`); + g.attr('class', `node ${node.type} ${this.node_to_file_class(node)}`); switch (node.type) { case "drop_scopes": - this.render_scope(g); + this.render_symbol_node(g, "[drop]", null, ""); break; case "jump_to_scope": - this.render_scope(g); + this.render_symbol_node(g, "[jump]", null, ""); break; case "pop_symbol": this.render_symbol_node(g, node.symbol, null, "pop"); @@ -322,7 +334,7 @@ class StackGraph { } break; case "root": - this.render_scope(g); + this.render_symbol_node(g, "[root]", null, ""); break; case "scope": if (this.show_all_node_labels()) { @@ -347,6 +359,7 @@ class StackGraph { break; } } + render_symbol_node(g, text, scope, shape) { let content = g.append("g"); content.append('text').text(text); @@ -869,10 +882,24 @@ class StackGraph { return this.node_id_to_str(node.id); } + node_to_file_class(node) { + return this.node_id_to_file_class(node.id); + } + edge_to_id_str(edge) { return this.node_id_to_str(edge.source) + "->" + this.node_id_to_str(edge.sink); } + edge_to_file_class(edge) { + if (edge.source.hasOwnProperty('file')) { + return "file-" + (this.F[edge.source.file] % StackGraph.number_of_file_colors); + } else if (edge.sink.hasOwnProperty('file')) { + return "file-" + (this.F[edge.sink.file] % StackGraph.number_of_file_colors); + } else { + return "global"; + } + } + node_id_to_str(id) { if (id.hasOwnProperty('file')) { return id.file + "#" + id.local_id; @@ -881,6 +908,14 @@ class StackGraph { } } + node_id_to_file_class(id) { + if (id.hasOwnProperty('file')) { + return "file-" + (this.F[id.file] % StackGraph.number_of_file_colors); + } else { + return "global"; + } + } + id_selector(id) { const sel = "#" + id.replaceAll(/[^a-zA-Z0-9]/g, '\\$&'); return sel; From 13dce02b433660f94b892df0dbf805c290855335 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 9 Nov 2023 18:17:17 +0100 Subject: [PATCH 234/500] Add file legend --- .../src/visualization/visualization.css | 62 ++++++++++++++++++- .../src/visualization/visualization.js | 45 ++++++++++++-- 2 files changed, 102 insertions(+), 5 deletions(-) diff --git a/stack-graphs/src/visualization/visualization.css b/stack-graphs/src/visualization/visualization.css index c5cc80151..177b56cef 100644 --- a/stack-graphs/src/visualization/visualization.css +++ b/stack-graphs/src/visualization/visualization.css @@ -314,6 +314,40 @@ margin: 0px 1px; } +/* ------------------------------------------------------------------------------------------------ + * Legend + */ + +#sg-legend { + position: absolute; + left: 10px; + top: 10px; + background-color: #bbbbbb; + padding: 6px; + border-radius: 6px; + z-index: 1; +} + +#sg-legend h1 { + font-variant: small-caps; + font-weight: bold; + font-size: inherit; + border-bottom: solid 1px #777777; + margin: 0px; +} + +#sg-legend ul { + list-style: none; + padding: 0px; + margin: 0px; +} + +#sg-legend li { + padding: 3px 6px; + margin: 3px 0px; + border: 1px solid white; +} + /* ------------------------------------------------------------------------------------------------ * Help */ @@ -419,6 +453,9 @@ .sg .node.global .background { fill: #0077bb; /* blue */ } +#sg-legend .global { + background-color: #0077bb; /* blue */ +} .sg .edge.global path, .sg .edge.global text { stroke: #0077bb; /* blue */ @@ -427,7 +464,9 @@ .sg .node.file-0 .background { fill: #77aadd; /* light blue */ } - +#sg-legend .file-0 { + background-color: #77aadd; /* light blue */ +} .sg .node.file-0 .arrow, .sg .edge.file-0 text { @@ -447,6 +486,9 @@ { fill: #ee8866; /* orange */ } +#sg-legend .file-1 { + background-color: #ee8866; /* orange */ +} .sg .node.file-1 .arrow { fill: #3d1407; /* orange (darkened) */ } @@ -464,6 +506,9 @@ { fill: #eedd88; /* light yellow */ } +#sg-legend .file-2 { + background-color: #eedd88; /* light yellow */ +} .sg .node.file-2 .arrow { fill: #413809; /* light yellow (darkened) */ } @@ -481,6 +526,9 @@ { fill: #ffaabb; /* pink */ } +#sg-legend .file-3 { + background-color: #ffaabb; /* pink */ +} .sg .node.file-3 .arrow { fill: #550011; /* pink (darkened) */ } @@ -498,6 +546,9 @@ { fill: #99ddff; /* light cyan */ } +#sg-legend .file-4 { + background-color: #99ddff; /* light cyan */ +} .sg .node.file-4 .arrow { fill: #003652; /* light cyan (darkened) */ } @@ -515,6 +566,9 @@ { fill: #44bb99; /* mint */ } +#sg-legend .file-5 { + background-color: #44bb99; /* mint */ +} .sg .node.file-5 .arrow { fill: #0e251f; /* mint (darkened) */ } @@ -532,6 +586,9 @@ { fill: #bbcc33; /* pear */ } +#sg-legend .file-6 { + background-color: #bbcc33; /* pear */ +} .sg .node.file-6 .arrow { fill: #25290a; /* pear (darkened) */ } @@ -549,6 +606,9 @@ { fill: #aaaa00; /* olive */ } +#sg-legend .file-7 { + background-color: #aaaa00; /* olive */ +} .sg .node.file-7 .arrow { fill: #222200; /* olive (darkened) */ } diff --git a/stack-graphs/src/visualization/visualization.js b/stack-graphs/src/visualization/visualization.js index 7e5183973..116850791 100644 --- a/stack-graphs/src/visualization/visualization.js +++ b/stack-graphs/src/visualization/visualization.js @@ -163,7 +163,8 @@ class StackGraph { // render UI this.render_help(); this.render_tooltip(); - this.render_graph() + this.render_legend(); + this.render_graph(); // pan & zoom let zoom = d3.zoom() @@ -471,9 +472,9 @@ class StackGraph { } } - /* ------------------------------------------------------------------------------------------------ - * Path Highlighting - */ + // ------------------------------------------------------------------------------------------------ + // Path Highlighting + // paths_mouseover(e, node) { if (this.paths_lock !== null) { @@ -781,6 +782,30 @@ class StackGraph { || (this.current_edge !== null && path.derived.edges.hasOwnProperty(this.edge_to_id_str(this.current_edge))); } + // ------------------------------------------------------------------------------------------------ + // Legend + // + + render_legend() { + const legend = d3.select('body').append('div') + .attr('id', 'sg-legend') + legend.append("h1").text("Files"); + const items = legend.append("ul"); + items.append("li") + .classed("global", true) + .text("[global]"); + for (const file in this.F) { + items.append("li") + .classed('file-' + this.F[file], true) + .text(file); + } + } + + legend_update() { + const legend = d3.select('#sg-legend'); + legend.style('visibility', this.show_file_legend() ? null : 'hidden'); + } + // ------------------------------------------------------------------------------------------------ // Help // @@ -802,6 +827,10 @@ class StackGraph { Pan by dragging the background with the mouse. Zoom using the scroll wheel. `); + this.show_files_legend_toggle = this.new_setting(help_content, "sg-files-legend", "Show files legend (f)", true); + this.show_files_legend_toggle.on("change", (e => { + this.legend_update(); + })); this.show_all_node_labels_toggle = this.new_setting(help_content, "sg-scope-labels", "Show all node labels (l)", false); this.show_all_node_labels_toggle.on("change", (e => { this.render_graph(); @@ -838,6 +867,10 @@ class StackGraph { help_keypress(e) { switch (e.keyCode) { + case 70: // f + this.show_files_legend_toggle.property("checked", !this.show_files_legend_toggle.property("checked")); + this.legend_update(); + break; case 72: // h this.help_toggle.property("checked", !this.help_toggle.property("checked")); break; @@ -860,6 +893,10 @@ class StackGraph { return this.show_all_node_labels_toggle.property("checked"); } + show_file_legend() { + return this.show_files_legend_toggle.property("checked"); + } + new_setting(element, id, html, initial) { const toggle = element.append("div"); const toggle_input = toggle.append('input') From 1acebc7a89c312e8119e3f8e6bd15e7c622ed6ab Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 9 Nov 2023 18:36:59 +0100 Subject: [PATCH 235/500] Make border of clickable nodes heavier --- stack-graphs/src/visualization/visualization.css | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/stack-graphs/src/visualization/visualization.css b/stack-graphs/src/visualization/visualization.css index 177b56cef..c3dfc091b 100644 --- a/stack-graphs/src/visualization/visualization.css +++ b/stack-graphs/src/visualization/visualization.css @@ -85,6 +85,10 @@ stroke: black; } +.sg .node.definition .background { + stroke-width: 2px; +} + /* --- push symbol --- */ .sg .node.push_scoped_symbol .push_scope { @@ -102,6 +106,10 @@ fill: black; } +.sg .node.reference .background { + stroke-width: 2px; +} + /* --- root --- */ .sg .node.root .background { @@ -128,6 +136,10 @@ fill: black; } +.sg .node.scope.exported .background { + stroke-width: 2px; +} + /* --- plain labeled node --- */ .sg .node.scope.plain_labeled_node .border { @@ -139,10 +151,6 @@ rx: 6px; } -.sg .node.scope.plain_labeled_node.exported .background { - stroke: black; -} - /* --- path highlight --- */ .sg .node.path-node .border { From 11c42030b7396644c878a71fb1e449b43c672137 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 9 Nov 2023 10:21:53 -0800 Subject: [PATCH 236/500] Adds closure points and tests --- .../src/stack-graphs.tsg | 26 ++++++++++--- .../function_closure_mutation.js | 38 +++++++++++++++++++ 2 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_closure_mutation.js diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index b8a220f41..253ea216c 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -252,6 +252,7 @@ inherit .constructor inherit .export_statement inherit .exports inherit .hoist_point +inherit .closure_point inherit .import_statement inherit .pkg_pop inherit .pkg_push @@ -280,6 +281,7 @@ inherit .return_or_yield (program)@prog { node @prog.after_scope node @prog.before_scope + let @prog.closure_point = @prog.after_scope } ;; ### Program Queries @@ -1267,6 +1269,7 @@ inherit .return_or_yield node fun_decl_value_return node fun_decl_value_this node fun_decl_value_this_guard + let @body.closure_point = @body.after_scope attr (@name.pop) syntax_type = "function" @@ -1281,7 +1284,7 @@ inherit .return_or_yield ; function values have drop nodes that handle closures, that points to the ; before scope for the function attr (fun_decl_value_drop) type = "drop_scopes" - edge fun_decl_value_drop -> @fun_decl.before_scope + edge fun_decl_value_drop -> @fun_decl.closure_point ; the call sig's before scope comes from the drop node then flows into the body edge @call_sig.before_scope -> fun_decl_value_drop @@ -1351,6 +1354,7 @@ inherit .return_or_yield node fun_decl_value_return node fun_decl_value_this node fun_decl_value_this_guard + let @body.closure_point = @body.after_scope attr (@name.pop) syntax_type = "function" @@ -1365,7 +1369,7 @@ inherit .return_or_yield ; function values have drop nodes that handle closures, that points to the ; before scope of the declaration attr (fun_decl_value_drop) type = "drop_scopes" - edge fun_decl_value_drop -> @fun_decl.before_scope + edge fun_decl_value_drop -> @fun_decl.closure_point ; the call sig's before scope comes from the drop node then flows into the body @@ -1549,7 +1553,7 @@ inherit .return_or_yield ; method values have drop nodes that handle closures, that points to the ; before scope from method def attr (method_def_method_value_drop) type = "drop_scopes" - edge method_def_method_value_drop -> @method_def.before_scope + edge method_def_method_value_drop -> @method_def.closure_point ; the call sig's before scope comes from the drop node then flows into the body edge @call_sig.before_scope -> method_def_method_value_drop @@ -2246,6 +2250,16 @@ inherit .return_or_yield } +[ + (function body:(_)@body) + (arrow_function body:(_)@body) + (generator_function body:(_)@body) +] { + + let @body.closure_point = @body.after_scope + +} + ;; ### Expression Queries @@ -2713,7 +2727,7 @@ inherit .return_or_yield ; function values have drop nodes that handle closures, that points to the ; before scope from the function attr (fun_value_drop) type = "drop_scopes" - edge fun_value_drop -> @fun.before_scope + edge fun_value_drop -> @fun.closure_point ; the call sig's before scope comes from the drop node, ; then flows into the body, and includes a variable binding for "this" @@ -2791,7 +2805,7 @@ inherit .return_or_yield ; function values have drop nodes that handle closures, that points to the ; before scope from the function attr (fun_value_drop) type = "drop_scopes" - edge fun_value_drop -> @fun.before_scope + edge fun_value_drop -> @fun.closure_point ; the call sig's before scope comes from the drop node then flows into the body edge @call_sig.before_scope -> fun_value_drop @@ -2900,7 +2914,7 @@ inherit .return_or_yield ; function values have drop nodes that handle closures, that points to the ; before scope from the function attr (fun_value_drop) type = "drop_scopes" - edge fun_value_drop -> @fun.before_scope + edge fun_value_drop -> @fun.closure_point ; the call sig's before scope comes from the drop node, ; then flows into the body, and includes a variable binding for "this" diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_closure_mutation.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_closure_mutation.js new file mode 100644 index 000000000..68cd9117b --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_closure_mutation.js @@ -0,0 +1,38 @@ +let x = 1; + +function foo() { + /**/ x; + // ^ defined: 1, 38 +} + +function* foo() { + /**/ x; + // ^ defined: 1, 38 +} + +function () { + /**/ x; + // ^ defined: 1, 38 +}; + +function* () { + /**/ x; + // ^ defined: 1, 38 +}; + +() => x; +// ^ defined: 1, 38 + +() => { + /**/ x; + // ^ defined: 1, 38 +}; + +class C { + foo() { + /**/ x; + // ^ defined: 1, 38 + } +} + +x = 2; \ No newline at end of file From 5ac451d5d101766c9dfe246fea98114e1412bc5b Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 9 Nov 2023 11:52:40 -0800 Subject: [PATCH 237/500] Fixes minore bugs around method closure scopes --- .../src/stack-graphs.tsg | 6 +++--- .../test/computation_flow/function_closure_mutation.js | 7 ++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 253ea216c..b864404a9 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -1441,7 +1441,7 @@ inherit .return_or_yield edge @class_decl.class_value -> guard_prototype edge guard_prototype -> @class_decl.prototype - edge @body.before_scope -> @class_decl.before_scope + edge @body.before_scope -> @class_decl.closure_point edge @class_decl.prototype -> @body.after_scope edge @class_decl.after_scope -> @class_decl.before_scope } @@ -1553,7 +1553,7 @@ inherit .return_or_yield ; method values have drop nodes that handle closures, that points to the ; before scope from method def attr (method_def_method_value_drop) type = "drop_scopes" - edge method_def_method_value_drop -> @method_def.closure_point + edge method_def_method_value_drop -> @method_def.before_scope ; the call sig's before scope comes from the drop node then flows into the body edge @call_sig.before_scope -> method_def_method_value_drop @@ -3454,7 +3454,7 @@ inherit .return_or_yield node @class.constructor attr (guard_prototype) pop_symbol = "GUARD:PROTOTYPE" - edge @body.before_scope -> @class.before_scope + edge @body.before_scope -> @class.closure_point edge @class.value -> @class.class_value edge @class.class_value -> guard_prototype edge guard_prototype -> @class.prototype diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_closure_mutation.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_closure_mutation.js index 68cd9117b..4b8c1a200 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_closure_mutation.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/function_closure_mutation.js @@ -35,4 +35,9 @@ class C { } } -x = 2; \ No newline at end of file +x = 2; + +(function bar() { + /**/ bar; + // ^ defined: 40 +}); \ No newline at end of file From 81c9cf8d4cef4b1f585f09f0e837819db816827f Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 9 Nov 2023 12:50:31 -0800 Subject: [PATCH 238/500] Improves definiens --- .../src/stack-graphs.tsg | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index b864404a9..3aa12eabd 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4699,12 +4699,7 @@ inherit .return_or_yield (assignment_expression left: (identifier)@left - right: [ - (function) - (generator_function) - (arrow_function) - (class) - ])@assignment_expr { + right: (_))@assignment_expr { attr (@left.pop) definiens_node = @assignment_expr @@ -4716,7 +4711,7 @@ inherit .return_or_yield object:(identifier)@_object property:(_)@left ) - right: (_)@right)@assignment_expr + right: (_))@assignment_expr (#not-eq @_object "module") (#not-eq @left "exports") ) { @@ -4726,7 +4721,7 @@ inherit .return_or_yield attr (left_ignore_guard) pop_symbol = "GUARD:GANDALF" attr (left_definiens_hook) node_definition = @left - attr (left_definiens_hook) definiens_node = @right + attr (left_definiens_hook) definiens_node = @assignment_expr edge @assignment_expr.pkg_pop -> left_ignore_guard edge left_ignore_guard -> left_definiens_hook } @@ -4737,7 +4732,7 @@ inherit .return_or_yield object:(identifier)@_object property:(_)@left ) - right: (_)@right)@assignment_expr + right: (_))@assignment_expr (#eq @_object "module") (#eq @left "exports") ) { @@ -4747,7 +4742,7 @@ inherit .return_or_yield attr (left_ignore_guard) pop_symbol = "GUARD:GANDALF" attr (left_definiens_hook) node_definition = @left - attr (left_definiens_hook) definiens_node = @right + attr (left_definiens_hook) definiens_node = @assignment_expr edge @assignment_expr.pkg_pop -> left_ignore_guard edge left_ignore_guard -> left_definiens_hook @@ -4846,12 +4841,7 @@ inherit .return_or_yield (pair key: (_)@name - value: [ - (function) - (generator_function) - (arrow_function) - (class) - ])@pair_expr { + value: (_))@pair_expr { node @name.definiens_hook node name_ignore_guard From c41dc0e657231df026c79724a135576a43ebb0ed Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 9 Nov 2023 20:52:28 +0100 Subject: [PATCH 239/500] Only keep the best path in similar path detection --- stack-graphs/src/cycles.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/stack-graphs/src/cycles.rs b/stack-graphs/src/cycles.rs index eda31e171..4ffe3148b 100644 --- a/stack-graphs/src/cycles.rs +++ b/stack-graphs/src/cycles.rs @@ -111,10 +111,22 @@ where let key = path.key(); let possibly_similar_paths = self.paths.entry(key).or_default(); - for other_path in possibly_similar_paths.iter() { - match cmp(arena, path, other_path) { - Some(ord) if ord != Ordering::Less => return true, - _ => continue, + let mut idx = 0; + while idx < possibly_similar_paths.len() { + match cmp(arena, path, &possibly_similar_paths[idx]) { + Some(Ordering::Less) => { + // the new path is betetr, remove the old one + possibly_similar_paths.remove(idx); + // keep `idx` which now points to the next element + continue; + } + Some(_) => { + // the new path is equal or worse, and ignored + return true; + } + None => { + idx += 1; + } } } From 397942bdc42cbadef99f4ae6622d716c0c86435a Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 10 Nov 2023 11:09:59 +0100 Subject: [PATCH 240/500] Use much smaller buckets --- stack-graphs/src/cycles.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack-graphs/src/cycles.rs b/stack-graphs/src/cycles.rs index 4ffe3148b..2fc125b6c 100644 --- a/stack-graphs/src/cycles.rs +++ b/stack-graphs/src/cycles.rs @@ -49,7 +49,7 @@ use crate::stitching::ToAppendable; /// Helps detect similar paths in the path-finding algorithm. pub struct SimilarPathDetector

{ - paths: HashMap>, + paths: HashMap>, } #[doc(hidden)] From 84694154d7d099c6113a401db67e1f1e0bc2e24b Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Sat, 11 Nov 2023 18:17:45 +0100 Subject: [PATCH 241/500] Restrict similar path detection to split paths --- stack-graphs/src/stitching.rs | 79 +++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 26 deletions(-) diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index 4872afe91..5bea52134 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -41,6 +41,9 @@ use std::collections::VecDeque; #[cfg(feature = "copious-debugging")] use std::fmt::Display; +use itertools::izip; +use itertools::Itertools; + use crate::arena::Arena; use crate::arena::Handle; use crate::arena::HandleSet; @@ -60,6 +63,7 @@ use crate::partial::Cyclicity; use crate::partial::PartialPath; use crate::partial::PartialPaths; use crate::partial::PartialSymbolStack; +use crate::paths::Extend; use crate::paths::PathResolutionError; use crate::CancellationError; use crate::CancellationFlag; @@ -736,13 +740,18 @@ impl<'a> Display for DisplaySymbolStackKey<'a> { /// [`find_all_complete_partial_paths`]: #method.find_all_complete_partial_paths pub struct ForwardPartialPathStitcher { candidates: Vec, - queue: VecDeque<(PartialPath, AppendingCycleDetector)>, + extensions: Vec<(PartialPath, AppendingCycleDetector)>, + queue: VecDeque<(PartialPath, AppendingCycleDetector, bool)>, // tracks the number of initial paths in the queue because we do not want call // extend_until on those initial_paths: usize, // next_iteration is a tuple of queues instead of an queue of tuples so that the path queue // can be cheaply exposed through the C API as a continuous memory block - next_iteration: (VecDeque, VecDeque>), + next_iteration: ( + VecDeque, + VecDeque>, + VecDeque, + ), appended_paths: Appendables, similar_path_detector: Option>, max_work_per_phase: usize, @@ -763,15 +772,16 @@ impl ForwardPartialPathStitcher { I: IntoIterator, { let mut appended_paths = Appendables::new(); - let next_iteration: (VecDeque<_>, VecDeque<_>) = initial_partial_paths + let next_iteration: (VecDeque<_>, VecDeque<_>, VecDeque<_>) = initial_partial_paths .into_iter() .map(|p| { let c = AppendingCycleDetector::from(&mut appended_paths, p.clone().into()); - (p, c) + (p, c, false) }) - .unzip(); + .multiunzip(); Self { candidates: Vec::new(), + extensions: Vec::new(), queue: VecDeque::new(), initial_paths: next_iteration.0.len(), next_iteration, @@ -835,6 +845,7 @@ impl ForwardPartialPathStitcher { candidates: &mut C, partial_path: &PartialPath, cycle_detector: AppendingCycleDetector, + has_split: bool, ) -> usize where A: Appendable, @@ -871,15 +882,15 @@ impl ForwardPartialPathStitcher { // find candidates to append self.candidates.clear(); candidates.get_forward_candidates(partial_path, &mut self.candidates); + let (graph, partials, db) = candidates.get_graph_partials_and_db(); // try to extend path with candidates - let extension_count = self.candidates.len(); - self.next_iteration.0.reserve(extension_count); - self.next_iteration.1.reserve(extension_count); - for extension in &self.candidates { - let (graph, partials, db) = candidates.get_graph_partials_and_db(); - let extension_path = db.get_appendable(extension); - copious_debugging!(" with {}", extension_path.display(graph, partials)); + let candidate_count = self.candidates.len(); + self.extensions.clear(); + self.extensions.reserve(candidate_count); + for candidate in &self.candidates { + let appendable = db.get_appendable(candidate); + copious_debugging!(" with {}", appendable.display(graph, partials)); let mut new_partial_path = partial_path.clone(); let mut new_cycle_detector = cycle_detector.clone(); @@ -887,12 +898,23 @@ impl ForwardPartialPathStitcher { // partial path, just skip the extension — it's not a fatal error. #[cfg_attr(not(feature = "copious-debugging"), allow(unused_variables))] { - if let Err(err) = extension_path.append_to(graph, partials, &mut new_partial_path) { + if let Err(err) = appendable.append_to(graph, partials, &mut new_partial_path) { copious_debugging!(" is invalid: {:?}", err); continue; } - copious_debugging!(" is {}", new_partial_path.display(graph, partials)); - new_cycle_detector.append(&mut self.appended_paths, extension.clone()); + } + new_cycle_detector.append(&mut self.appended_paths, candidate.clone()); + copious_debugging!(" is {}", new_partial_path.display(graph, partials)); + self.extensions.push((new_partial_path, new_cycle_detector)); + } + + let extension_count = self.extensions.len(); + let new_has_split = has_split || self.extensions.len() > 1; + self.next_iteration.0.reserve(extension_count); + self.next_iteration.1.reserve(extension_count); + self.next_iteration.2.reserve(extension_count); + for (new_partial_path, new_cycle_detector) in self.extensions.drain(..) { + if new_has_split { if let Some(similar_path_detector) = &mut self.similar_path_detector { if similar_path_detector.has_similar_path( graph, @@ -912,16 +934,22 @@ impl ForwardPartialPathStitcher { } }, ) { + copious_debugging!( + " extension {}", + new_partial_path.display(graph, partials) + ); copious_debugging!(" is rejected: too many similar"); continue; } } } - self.next_iteration.0.push_back(new_partial_path); - self.next_iteration.1.push_back(new_cycle_detector); + + self.next_iteration.0.push(new_partial_path); + self.next_iteration.1.push(new_cycle_detector); + self.next_iteration.2.push(new_has_split); } - extension_count + candidate_count } /// Returns whether the algorithm has completed. @@ -949,14 +977,13 @@ impl ForwardPartialPathStitcher { E: Fn(&StackGraph, &mut PartialPaths, &PartialPath) -> bool, { copious_debugging!("==> Start phase {}", self.phase_number); - self.queue.extend( - self.next_iteration - .0 - .drain(..) - .zip(self.next_iteration.1.drain(..)), - ); + self.queue.extend(izip!( + self.next_iteration.0.drain(..), + self.next_iteration.1.drain(..), + self.next_iteration.2.drain(..), + )); let mut work_performed = 0; - while let Some((partial_path, cycle_detector)) = self.queue.pop_front() { + while let Some((partial_path, cycle_detector, has_split)) = self.queue.pop_front() { let (graph, partials, _) = candidates.get_graph_partials_and_db(); copious_debugging!( "--> Candidate partial path {}", @@ -971,7 +998,7 @@ impl ForwardPartialPathStitcher { ); continue; } - work_performed += self.extend(candidates, &partial_path, cycle_detector); + work_performed += self.extend(candidates, &partial_path, cycle_detector, has_split); if work_performed >= self.max_work_per_phase { break; } From 52d7bd55b38302ee2f5bb9bffea687d2678b71d5 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Sat, 11 Nov 2023 18:23:25 +0100 Subject: [PATCH 242/500] Restrict similar path detection to paths that can converge --- stack-graphs/src/graph.rs | 9 +++++++++ stack-graphs/src/stitching.rs | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/stack-graphs/src/graph.rs b/stack-graphs/src/graph.rs index ae2b9aa62..8c0de1f74 100644 --- a/stack-graphs/src/graph.rs +++ b/stack-graphs/src/graph.rs @@ -1303,6 +1303,7 @@ impl StackGraph { let edges = &mut self.outgoing_edges[source]; if let Err(index) = edges.binary_search_by_key(&sink, |o| o.sink) { edges.insert(index, OutgoingEdge { sink, precedence }); + self.incoming_edges[sink] += 1; } } @@ -1311,6 +1312,7 @@ impl StackGraph { let edges = &mut self.outgoing_edges[source]; if let Ok(index) = edges.binary_search_by_key(&sink, |o| o.sink) { edges.remove(index); + self.incoming_edges[sink] -= 1; } } @@ -1325,6 +1327,11 @@ impl StackGraph { None => Either::Left(std::iter::empty()), } } + + /// Returns the number of edges that end at a particular sink node. + pub fn incoming_edge_count(&self, sink: Handle) -> u32 { + self.incoming_edges[sink] + } } //------------------------------------------------------------------------------------------------- @@ -1443,6 +1450,7 @@ pub struct StackGraph { pub(crate) source_info: SupplementalArena, node_id_handles: NodeIDHandles, outgoing_edges: SupplementalArena>, + incoming_edges: SupplementalArena, pub(crate) node_debug_info: SupplementalArena, pub(crate) edge_debug_info: SupplementalArena, DebugInfo); 8]>>, } @@ -1625,6 +1633,7 @@ impl Default for StackGraph { source_info: SupplementalArena::new(), node_id_handles: NodeIDHandles::new(), outgoing_edges: SupplementalArena::new(), + incoming_edges: SupplementalArena::new(), node_debug_info: SupplementalArena::new(), edge_debug_info: SupplementalArena::new(), } diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index 5bea52134..1c0a29f27 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -914,7 +914,8 @@ impl ForwardPartialPathStitcher { self.next_iteration.1.reserve(extension_count); self.next_iteration.2.reserve(extension_count); for (new_partial_path, new_cycle_detector) in self.extensions.drain(..) { - if new_has_split { + let can_converge = graph.incoming_edge_count(new_partial_path.end_node) > 1; + if new_has_split && can_converge { if let Some(similar_path_detector) = &mut self.similar_path_detector { if similar_path_detector.has_similar_path( graph, From 2596ad29c4dd87bca73d132d8701c17f078594fa Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Sun, 12 Nov 2023 21:41:50 +0100 Subject: [PATCH 243/500] Only check for cycles if loops can actually occur --- stack-graphs/src/stitching.rs | 66 +++++++++++++++++++++++------------ stack-graphs/src/storage.rs | 4 +++ 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index 1c0a29f27..d348dac9b 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -202,6 +202,9 @@ where where R: std::iter::Extend; + /// Get the number of available candidates that share the given path's end node. + fn get_joining_candidate_count(&self, path: &PartialPath) -> u32; + /// Get the graph, partial path arena, and database backing this candidates instance. fn get_graph_partials_and_db(&mut self) -> (&StackGraph, &mut PartialPaths, &Db); } @@ -243,6 +246,10 @@ impl ForwardCandidates for GraphEdgeC })); } + fn get_joining_candidate_count(&self, path: &PartialPath) -> u32 { + self.graph.incoming_edge_count(path.end_node) + } + fn get_graph_partials_and_db(&mut self) -> (&StackGraph, &mut PartialPaths, &GraphEdges) { (self.graph, self.partials, &self.edges) } @@ -277,6 +284,7 @@ pub struct Database { symbol_stack_key_cache: HashMap, paths_by_start_node: SupplementalArena>>, root_paths_by_precondition: SupplementalArena>>, + incoming_paths: SupplementalArena, } impl Database { @@ -289,6 +297,7 @@ impl Database { symbol_stack_key_cache: HashMap::new(), paths_by_start_node: SupplementalArena::new(), root_paths_by_precondition: SupplementalArena::new(), + incoming_paths: SupplementalArena::new(), } } @@ -302,6 +311,7 @@ impl Database { self.symbol_stack_key_cache.clear(); self.paths_by_start_node.clear(); self.root_paths_by_precondition.clear(); + self.incoming_paths.clear(); } /// Adds a partial path to this database. We do not deduplicate partial paths in any way; it's @@ -313,6 +323,7 @@ impl Database { path: PartialPath, ) -> Handle { let start_node = path.start_node; + let end_node = path.end_node; copious_debugging!( " Add {} path to database {}", if graph[start_node].is_root() { @@ -343,6 +354,7 @@ impl Database { self.paths_by_start_node[start_node].push(handle); } + self.incoming_paths[end_node] += 1; handle } @@ -600,6 +612,10 @@ impl ForwardCandidates, PartialPath, Database, CancellationE .find_candidate_partial_paths(self.graph, self.partials, path, result); } + fn get_joining_candidate_count(&self, path: &PartialPath) -> u32 { + self.database.incoming_paths[path.end_node] + } + fn get_graph_partials_and_db(&mut self) -> (&StackGraph, &mut PartialPaths, &Database) { (self.graph, self.partials, self.database) } @@ -852,31 +868,37 @@ impl ForwardPartialPathStitcher { Db: ToAppendable, C: ForwardCandidates, { + let check_cycle = partial_path.start_node == partial_path.end_node + || candidates.get_joining_candidate_count(partial_path) > 1; + let (graph, partials, db) = candidates.get_graph_partials_and_db(); copious_debugging!(" Extend {}", partial_path.display(graph, partials)); - // check is path is cyclic, in which case we do not extend it - let has_precondition_variables = partial_path.symbol_stack_precondition.has_variable() - || partial_path.scope_stack_precondition.has_variable(); - let cycles = cycle_detector - .is_cyclic(graph, partials, db, &mut self.appended_paths) - .expect("cyclic test failed when stitching partial paths"); - let cyclic = match has_precondition_variables { - // If the precondition has no variables, we allow cycles that strengthen the - // precondition, because we know they cannot strengthen the precondition of - // the overall path. - false => !cycles - .into_iter() - .all(|c| c == Cyclicity::StrengthensPrecondition), - // If the precondition has variables, do not allow any cycles, not even those - // that strengthen the precondition. This is more strict than necessary. Better - // might be to disallow precondition strengthening cycles only if they would - // strengthen the overall path precondition. - true => !cycles.is_empty(), - }; - if cyclic { - copious_debugging!(" is discontinued: cyclic"); - return 0; + if check_cycle { + // Check is path is cyclic, in which case we do not extend it. We only do this if the start and end nodes are the same, + // or the current end node has multiple incoming edges. If neither of these hold, the path cannot end in a cycle. + let has_precondition_variables = partial_path.symbol_stack_precondition.has_variable() + || partial_path.scope_stack_precondition.has_variable(); + let cycles = cycle_detector + .is_cyclic(graph, partials, db, &mut self.appended_paths) + .expect("cyclic test failed when stitching partial paths"); + let cyclic = match has_precondition_variables { + // If the precondition has no variables, we allow cycles that strengthen the + // precondition, because we know they cannot strengthen the precondition of + // the overall path. + false => !cycles + .into_iter() + .all(|c| c == Cyclicity::StrengthensPrecondition), + // If the precondition has variables, do not allow any cycles, not even those + // that strengthen the precondition. This is more strict than necessary. Better + // might be to disallow precondition strengthening cycles only if they would + // strengthen the overall path precondition. + true => !cycles.is_empty(), + }; + if cyclic { + copious_debugging!(" is discontinued: cyclic"); + return 0; + } } // find candidates to append diff --git a/stack-graphs/src/storage.rs b/stack-graphs/src/storage.rs index 3cd89d797..42e7234a5 100644 --- a/stack-graphs/src/storage.rs +++ b/stack-graphs/src/storage.rs @@ -736,6 +736,10 @@ impl ForwardCandidates, PartialPath, Database, StorageError> .find_candidate_partial_paths(&self.graph, &mut self.partials, path, result); } + fn get_joining_candidate_count(&self, _path: &PartialPath) -> u32 { + u32::MAX // err on the safe side + } + fn get_graph_partials_and_db(&mut self) -> (&StackGraph, &mut PartialPaths, &Database) { (&self.graph, &mut self.partials, &self.db) } From d7bb4ad92f07bb301e06afddca8510b7eaa9336b Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 13 Nov 2023 11:16:47 +0100 Subject: [PATCH 244/500] Only apply join count optimization if explicitly enabled --- stack-graphs/src/stitching.rs | 30 ++++++++++++++++++++++++++---- stack-graphs/src/storage.rs | 4 ++-- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index d348dac9b..169f1e00a 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -469,6 +469,11 @@ impl Database { } } + /// Returns the number of paths in this database that share the given end node. + pub fn get_incoming_path_count(&self, end_node: Handle) -> u32 { + self.incoming_paths[end_node] + } + /// Determines which nodes in the stack graph are “local”, taking into account the partial /// paths in this database. /// @@ -613,7 +618,7 @@ impl ForwardCandidates, PartialPath, Database, CancellationE } fn get_joining_candidate_count(&self, path: &PartialPath) -> u32 { - self.database.incoming_paths[path.end_node] + self.database.get_incoming_path_count(path.end_node) } fn get_graph_partials_and_db(&mut self) -> (&StackGraph, &mut PartialPaths, &Database) { @@ -770,6 +775,7 @@ pub struct ForwardPartialPathStitcher { ), appended_paths: Appendables, similar_path_detector: Option>, + check_only_join_nodes: bool, max_work_per_phase: usize, #[cfg(feature = "copious-debugging")] phase_number: usize, @@ -803,6 +809,8 @@ impl ForwardPartialPathStitcher { next_iteration, appended_paths, similar_path_detector: Some(SimilarPathDetector::new()), + // By default, all nodes are checked for cycles and (if enabled) similarity + check_only_join_nodes: false, // By default, there's no artificial bound on the amount of work done per phase max_work_per_phase: usize::MAX, #[cfg(feature = "copious-debugging")] @@ -844,6 +852,14 @@ impl ForwardPartialPathStitcher { } } + /// Sets whether all nodes are checked for cycles and (if enabled) similar paths, or only nodes with multiple + /// incoming candidates. Checking only join nodes is **unsafe** unless the database of candidates is stable + /// between all stitching phases. If paths are added to the database from one phase to another, for example if + /// paths are dynamically loaded from storage, setting this to true is incorrect and might lead to non-termination! + pub fn set_check_only_join_nodes(&mut self, check_only_join_nodes: bool) { + self.check_only_join_nodes = check_only_join_nodes; + } + /// Sets the maximum amount of work that can be performed during each phase of the algorithm. /// By bounding our work this way, you can ensure that it's not possible for our CPU-bound /// algorithm to starve any worker threads or processes that you might be using. If you don't @@ -868,7 +884,8 @@ impl ForwardPartialPathStitcher { Db: ToAppendable, C: ForwardCandidates, { - let check_cycle = partial_path.start_node == partial_path.end_node + let check_cycle = !self.check_only_join_nodes + || partial_path.start_node == partial_path.end_node || candidates.get_joining_candidate_count(partial_path) > 1; let (graph, partials, db) = candidates.get_graph_partials_and_db(); @@ -936,8 +953,11 @@ impl ForwardPartialPathStitcher { self.next_iteration.1.reserve(extension_count); self.next_iteration.2.reserve(extension_count); for (new_partial_path, new_cycle_detector) in self.extensions.drain(..) { - let can_converge = graph.incoming_edge_count(new_partial_path.end_node) > 1; - if new_has_split && can_converge { + let check_similar_path = new_has_split + && (!self.check_only_join_nodes + || candidates.get_joining_candidate_count(&new_partial_path) > 1); + let (graph, partials, _) = candidates.get_graph_partials_and_db(); + if check_similar_path { if let Some(similar_path_detector) = &mut self.similar_path_detector { if similar_path_detector.has_similar_path( graph, @@ -1081,6 +1101,7 @@ impl ForwardPartialPathStitcher { .collect::>(); let mut stitcher = ForwardPartialPathStitcher::from_partial_paths(graph, partials, initial_paths); + stitcher.set_check_only_join_nodes(true); while !stitcher.is_complete() { cancellation_flag.check("finding complete partial paths")?; stitcher.process_next_phase( @@ -1136,6 +1157,7 @@ impl ForwardPartialPathStitcher { .collect::>(); ForwardPartialPathStitcher::from_partial_paths(graph, partials, initial_paths) }; + stitcher.set_check_only_join_nodes(true); while !stitcher.is_complete() { cancellation_flag.check("finding complete partial paths")?; for path in stitcher.previous_phase_partial_paths() { diff --git a/stack-graphs/src/storage.rs b/stack-graphs/src/storage.rs index 42e7234a5..78481dc71 100644 --- a/stack-graphs/src/storage.rs +++ b/stack-graphs/src/storage.rs @@ -736,8 +736,8 @@ impl ForwardCandidates, PartialPath, Database, StorageError> .find_candidate_partial_paths(&self.graph, &mut self.partials, path, result); } - fn get_joining_candidate_count(&self, _path: &PartialPath) -> u32 { - u32::MAX // err on the safe side + fn get_joining_candidate_count(&self, path: &PartialPath) -> u32 { + self.db.get_incoming_path_count(path.end_node) } fn get_graph_partials_and_db(&mut self) -> (&StackGraph, &mut PartialPaths, &Database) { From e535492484356f599ca751873b2ee9615cf7c2bb Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 13 Nov 2023 14:20:58 +0100 Subject: [PATCH 245/500] Reduce preallocated buffers --- stack-graphs/src/cycles.rs | 2 +- stack-graphs/src/graph.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/stack-graphs/src/cycles.rs b/stack-graphs/src/cycles.rs index 2fc125b6c..6038770fd 100644 --- a/stack-graphs/src/cycles.rs +++ b/stack-graphs/src/cycles.rs @@ -49,7 +49,7 @@ use crate::stitching::ToAppendable; /// Helps detect similar paths in the path-finding algorithm. pub struct SimilarPathDetector

{ - paths: HashMap>, + paths: HashMap>, } #[doc(hidden)] diff --git a/stack-graphs/src/graph.rs b/stack-graphs/src/graph.rs index 8c0de1f74..50eb1ab03 100644 --- a/stack-graphs/src/graph.rs +++ b/stack-graphs/src/graph.rs @@ -1449,10 +1449,10 @@ pub struct StackGraph { pub(crate) nodes: Arena, pub(crate) source_info: SupplementalArena, node_id_handles: NodeIDHandles, - outgoing_edges: SupplementalArena>, + outgoing_edges: SupplementalArena>, incoming_edges: SupplementalArena, pub(crate) node_debug_info: SupplementalArena, - pub(crate) edge_debug_info: SupplementalArena, DebugInfo); 8]>>, + pub(crate) edge_debug_info: SupplementalArena, DebugInfo); 4]>>, } impl StackGraph { From 07ca85d6bd593c26a03f34d577618e1b5d342337 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 13 Nov 2023 17:01:09 +0100 Subject: [PATCH 246/500] Add comment warning for in-loop modification --- stack-graphs/src/cycles.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/stack-graphs/src/cycles.rs b/stack-graphs/src/cycles.rs index 6038770fd..d10679385 100644 --- a/stack-graphs/src/cycles.rs +++ b/stack-graphs/src/cycles.rs @@ -110,12 +110,15 @@ where { let key = path.key(); + // Iterate through the bucket to determine if this paths is better than any already known + // path. Note that the bucket might be modified during the loop if a path is removed which + // is shadowed by the new path! let possibly_similar_paths = self.paths.entry(key).or_default(); let mut idx = 0; while idx < possibly_similar_paths.len() { match cmp(arena, path, &possibly_similar_paths[idx]) { Some(Ordering::Less) => { - // the new path is betetr, remove the old one + // the new path is better, remove the old one possibly_similar_paths.remove(idx); // keep `idx` which now points to the next element continue; From cd58abbff3d128fc480f7f016c3ac1ed9d01bf04 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 13 Nov 2023 17:27:12 +0100 Subject: [PATCH 247/500] Replace incoming count with degree --- .../rust/npm_package.rs | 2 +- .../rust/util.rs | 10 ++-- stack-graphs/src/graph.rs | 46 ++++++++++++++++--- stack-graphs/src/stitching.rs | 22 +++++---- stack-graphs/src/storage.rs | 5 +- stack-graphs/tests/it/graph.rs | 8 ---- 6 files changed, 63 insertions(+), 30 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs index 5a46d6ee1..e0ab0c951 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs @@ -115,7 +115,7 @@ impl FileAnalyzer for NpmPackageAnalyzer { EXPORTS_GUARD, "exports_guard_pop", ); - replace_edge(graph, pkg_name_pop, exports_guard_pop, 1); + set_edge_precedence(graph, pkg_name_pop, exports_guard_pop, 1); let main = Some(npm_pkg.main) .filter(|main| !main.is_empty()) .and_then(|main| NormalizedRelativePath::from_str(&main)) diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/util.rs b/languages/tree-sitter-stack-graphs-javascript/rust/util.rs index 1bed520cd..a53f2e7dd 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/util.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/util.rs @@ -61,12 +61,16 @@ pub fn add_edge(graph: &mut StackGraph, from: Handle, to: Handle, pr graph.add_edge(from, to, precedence); } -pub fn replace_edge(graph: &mut StackGraph, from: Handle, to: Handle, precedence: i32) { +pub fn set_edge_precedence( + graph: &mut StackGraph, + from: Handle, + to: Handle, + precedence: i32, +) { if from == to { return; } - graph.remove_edge(from, to); - graph.add_edge(from, to, precedence); + graph.set_edge_precedence(from, to, precedence); } pub fn add_module_pops( diff --git a/stack-graphs/src/graph.rs b/stack-graphs/src/graph.rs index 50eb1ab03..53dd392da 100644 --- a/stack-graphs/src/graph.rs +++ b/stack-graphs/src/graph.rs @@ -1303,16 +1303,20 @@ impl StackGraph { let edges = &mut self.outgoing_edges[source]; if let Err(index) = edges.binary_search_by_key(&sink, |o| o.sink) { edges.insert(index, OutgoingEdge { sink, precedence }); - self.incoming_edges[sink] += 1; + self.incoming_edges[sink] += Degree::One; } } /// Removes an edge from the stack graph. - pub fn remove_edge(&mut self, source: Handle, sink: Handle) { + pub fn set_edge_precedence( + &mut self, + source: Handle, + sink: Handle, + precedence: i32, + ) { let edges = &mut self.outgoing_edges[source]; if let Ok(index) = edges.binary_search_by_key(&sink, |o| o.sink) { - edges.remove(index); - self.incoming_edges[sink] -= 1; + edges[index].precedence = precedence; } } @@ -1329,7 +1333,7 @@ impl StackGraph { } /// Returns the number of edges that end at a particular sink node. - pub fn incoming_edge_count(&self, sink: Handle) -> u32 { + pub fn incoming_edge_degree(&self, sink: Handle) -> Degree { self.incoming_edges[sink] } } @@ -1437,6 +1441,36 @@ impl StackGraph { //------------------------------------------------------------------------------------------------- // Stack graphs +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[repr(u8)] +pub enum Degree { + Zero, + One, + Multiple, +} + +impl Default for Degree { + fn default() -> Self { + Self::Zero + } +} + +impl std::ops::Add for Degree { + type Output = Self; + fn add(self, rhs: Self) -> Self::Output { + match (self, rhs) { + (Self::Zero, result) | (result, Self::Zero) => result, + _ => Self::Multiple, + } + } +} + +impl std::ops::AddAssign for Degree { + fn add_assign(&mut self, rhs: Self) { + *self = *self + rhs; + } +} + /// Contains all of the nodes and edges that make up a stack graph. pub struct StackGraph { interned_strings: InternedStringArena, @@ -1450,7 +1484,7 @@ pub struct StackGraph { pub(crate) source_info: SupplementalArena, node_id_handles: NodeIDHandles, outgoing_edges: SupplementalArena>, - incoming_edges: SupplementalArena, + incoming_edges: SupplementalArena, pub(crate) node_debug_info: SupplementalArena, pub(crate) edge_debug_info: SupplementalArena, DebugInfo); 4]>>, } diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index 169f1e00a..3d02a14be 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -54,6 +54,7 @@ use crate::arena::SupplementalArena; use crate::cycles::Appendables; use crate::cycles::AppendingCycleDetector; use crate::cycles::SimilarPathDetector; +use crate::graph::Degree; use crate::graph::Edge; use crate::graph::File; use crate::graph::Node; @@ -203,7 +204,7 @@ where R: std::iter::Extend; /// Get the number of available candidates that share the given path's end node. - fn get_joining_candidate_count(&self, path: &PartialPath) -> u32; + fn get_joining_candidate_degree(&self, path: &PartialPath) -> Degree; /// Get the graph, partial path arena, and database backing this candidates instance. fn get_graph_partials_and_db(&mut self) -> (&StackGraph, &mut PartialPaths, &Db); @@ -246,8 +247,8 @@ impl ForwardCandidates for GraphEdgeC })); } - fn get_joining_candidate_count(&self, path: &PartialPath) -> u32 { - self.graph.incoming_edge_count(path.end_node) + fn get_joining_candidate_degree(&self, path: &PartialPath) -> Degree { + self.graph.incoming_edge_degree(path.end_node) } fn get_graph_partials_and_db(&mut self) -> (&StackGraph, &mut PartialPaths, &GraphEdges) { @@ -284,7 +285,7 @@ pub struct Database { symbol_stack_key_cache: HashMap, paths_by_start_node: SupplementalArena>>, root_paths_by_precondition: SupplementalArena>>, - incoming_paths: SupplementalArena, + incoming_paths: SupplementalArena, } impl Database { @@ -354,7 +355,7 @@ impl Database { self.paths_by_start_node[start_node].push(handle); } - self.incoming_paths[end_node] += 1; + self.incoming_paths[end_node] += Degree::One; handle } @@ -470,7 +471,7 @@ impl Database { } /// Returns the number of paths in this database that share the given end node. - pub fn get_incoming_path_count(&self, end_node: Handle) -> u32 { + pub fn get_incoming_path_degree(&self, end_node: Handle) -> Degree { self.incoming_paths[end_node] } @@ -617,8 +618,8 @@ impl ForwardCandidates, PartialPath, Database, CancellationE .find_candidate_partial_paths(self.graph, self.partials, path, result); } - fn get_joining_candidate_count(&self, path: &PartialPath) -> u32 { - self.database.get_incoming_path_count(path.end_node) + fn get_joining_candidate_degree(&self, path: &PartialPath) -> Degree { + self.database.get_incoming_path_degree(path.end_node) } fn get_graph_partials_and_db(&mut self) -> (&StackGraph, &mut PartialPaths, &Database) { @@ -886,7 +887,7 @@ impl ForwardPartialPathStitcher { { let check_cycle = !self.check_only_join_nodes || partial_path.start_node == partial_path.end_node - || candidates.get_joining_candidate_count(partial_path) > 1; + || candidates.get_joining_candidate_degree(partial_path) == Degree::Multiple; let (graph, partials, db) = candidates.get_graph_partials_and_db(); copious_debugging!(" Extend {}", partial_path.display(graph, partials)); @@ -955,7 +956,8 @@ impl ForwardPartialPathStitcher { for (new_partial_path, new_cycle_detector) in self.extensions.drain(..) { let check_similar_path = new_has_split && (!self.check_only_join_nodes - || candidates.get_joining_candidate_count(&new_partial_path) > 1); + || candidates.get_joining_candidate_degree(&new_partial_path) + == Degree::Multiple); let (graph, partials, _) = candidates.get_graph_partials_and_db(); if check_similar_path { if let Some(similar_path_detector) = &mut self.similar_path_detector { diff --git a/stack-graphs/src/storage.rs b/stack-graphs/src/storage.rs index 78481dc71..7664ea88f 100644 --- a/stack-graphs/src/storage.rs +++ b/stack-graphs/src/storage.rs @@ -19,6 +19,7 @@ use std::path::PathBuf; use thiserror::Error; use crate::arena::Handle; +use crate::graph::Degree; use crate::graph::File; use crate::graph::Node; use crate::graph::StackGraph; @@ -736,8 +737,8 @@ impl ForwardCandidates, PartialPath, Database, StorageError> .find_candidate_partial_paths(&self.graph, &mut self.partials, path, result); } - fn get_joining_candidate_count(&self, path: &PartialPath) -> u32 { - self.db.get_incoming_path_count(path.end_node) + fn get_joining_candidate_degree(&self, path: &PartialPath) -> Degree { + self.db.get_incoming_path_degree(path.end_node) } fn get_graph_partials_and_db(&mut self) -> (&StackGraph, &mut PartialPaths, &Database) { diff --git a/stack-graphs/tests/it/graph.rs b/stack-graphs/tests/it/graph.rs index 353850c6f..f19bb2c30 100644 --- a/stack-graphs/tests/it/graph.rs +++ b/stack-graphs/tests/it/graph.rs @@ -157,14 +157,6 @@ fn can_add_and_remove_edges() { .collect::>(), hashset! { (h2, 0), (h3, 0), (h4, 0) } ); - graph.remove_edge(h1, h3); - assert_eq!( - graph - .outgoing_edges(h1) - .map(|edge| edge.sink) - .collect::>(), - hashset! { h2, h4 } - ); } #[test] From a2dc6158488db02a3fe0cf4730412d3f17e8d868 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 7 Nov 2023 13:48:52 +0100 Subject: [PATCH 248/500] Only export main module from package --- .../rust/npm_package.rs | 1 - .../rust/util.rs | 12 ------ .../src/stack-graphs.tsg | 4 -- ...can-access-package-non-main-explicilty.js} | 32 +++------------ .../package-does-not-export-non-main.js | 32 +++++++++++++++ .../packages/package-exports-explicit-main.js | 39 +++++++++++++++++++ .../package-main-defaults-to-index.js | 38 ++++++++++++++++++ 7 files changed, 114 insertions(+), 44 deletions(-) rename languages/tree-sitter-stack-graphs-javascript/test/old/packages/{package_dependencies.js => can-access-package-non-main-explicilty.js} (64%) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/packages/package-does-not-export-non-main.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/packages/package-exports-explicit-main.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/packages/package-main-defaults-to-index.js diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs index e0ab0c951..ddaa952cc 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs @@ -115,7 +115,6 @@ impl FileAnalyzer for NpmPackageAnalyzer { EXPORTS_GUARD, "exports_guard_pop", ); - set_edge_precedence(graph, pkg_name_pop, exports_guard_pop, 1); let main = Some(npm_pkg.main) .filter(|main| !main.is_empty()) .and_then(|main| NormalizedRelativePath::from_str(&main)) diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/util.rs b/languages/tree-sitter-stack-graphs-javascript/rust/util.rs index a53f2e7dd..17ab8d779 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/util.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/util.rs @@ -61,18 +61,6 @@ pub fn add_edge(graph: &mut StackGraph, from: Handle, to: Handle, pr graph.add_edge(from, to, precedence); } -pub fn set_edge_precedence( - graph: &mut StackGraph, - from: Handle, - to: Handle, - precedence: i32, -) { - if from == to { - return; - } - graph.set_edge_precedence(from, to, precedence); -} - pub fn add_module_pops( graph: &mut StackGraph, file: Handle, diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 3aa12eabd..640ec0976 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -348,10 +348,6 @@ inherit .return_or_yield edge module_pop_end -> prog_exports_pop edge prog_exports_pop -> @prog.exports - ; allow direct access from the package to the modules exports - ; this is used from package.json - edge @prog.pkg_pop -> prog_exports_pop - ;; builtin types node @prog.builtins_number node @prog.builtins_string diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/packages/package_dependencies.js b/languages/tree-sitter-stack-graphs-javascript/test/old/packages/can-access-package-non-main-explicilty.js similarity index 64% rename from languages/tree-sitter-stack-graphs-javascript/test/old/packages/package_dependencies.js rename to languages/tree-sitter-stack-graphs-javascript/test/old/packages/can-access-package-non-main-explicilty.js index 7a67a873a..820c0368e 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/old/packages/package_dependencies.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/packages/can-access-package-non-main-explicilty.js @@ -1,18 +1,3 @@ -/* --- path: foo/package.json --- */ -/* --- global: FILE_PATH=package.json --- */ -/* --- global: PROJECT_NAME=foo --- */ - -{ - "name": "foo", - "version": "1.0" -} - -/* --- path: foo/src/index.js --- */ -/* --- global: FILE_PATH=src/index.js --- */ -/* --- global: PROJECT_NAME=foo --- */ - -export let x; - /* --- path: acme_foo/package.json --- */ /* --- global: FILE_PATH=package.json --- */ /* --- global: PROJECT_NAME=acme_foo --- */ @@ -23,14 +8,14 @@ export let x; "main": "./api" } -/* --- path: acme_foo/core.js --- */ -/* --- global: FILE_PATH=core.js --- */ +/* --- path: acme_foo/api.js --- */ +/* --- global: FILE_PATH=api.js --- */ /* --- global: PROJECT_NAME=acme_foo --- */ export let x; -/* --- path: acme_foo/api.js --- */ -/* --- global: FILE_PATH=api.js --- */ +/* --- path: acme_foo/core.js --- */ +/* --- global: FILE_PATH=core.js --- */ /* --- global: PROJECT_NAME=acme_foo --- */ export let x; @@ -42,7 +27,6 @@ export let x; { "name": "bar", "dependencies": { - "foo": "1", "@acme/foo": "1" } } @@ -51,11 +35,5 @@ export let x; /* --- global: FILE_PATH=app.js --- */ /* --- global: PROJECT_NAME=bar --- */ -import { x } from "@acme/foo" -// ^ defined: 36 - -import { x } from "foo" -// ^ defined: 14 - import { x } from "@acme/foo/core" -// ^ defined: 30 +// ^ defined: 21 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/packages/package-does-not-export-non-main.js b/languages/tree-sitter-stack-graphs-javascript/test/old/packages/package-does-not-export-non-main.js new file mode 100644 index 000000000..cea744788 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/packages/package-does-not-export-non-main.js @@ -0,0 +1,32 @@ +/* --- path: foo/package.json --- */ +/* --- global: FILE_PATH=package.json --- */ +/* --- global: PROJECT_NAME=foo --- */ + +{ + "name": "foo", + "version": "1.0" +} + +/* --- path: foo/impl.js --- */ +/* --- global: FILE_PATH=impl.js --- */ +/* --- global: PROJECT_NAME=foo --- */ + +export let x; + +/* --- path: bar/package.json --- */ +/* --- global: FILE_PATH=package.json --- */ +/* --- global: PROJECT_NAME=bar --- */ + +{ + "name": "bar", + "dependencies": { + "foo": "1" + } +} + +/* --- path: bar/app.js --- */ +/* --- global: FILE_PATH=app.js --- */ +/* --- global: PROJECT_NAME=bar --- */ + +import { x } from "foo" +// ^ defined: diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/packages/package-exports-explicit-main.js b/languages/tree-sitter-stack-graphs-javascript/test/old/packages/package-exports-explicit-main.js new file mode 100644 index 000000000..14ec28812 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/packages/package-exports-explicit-main.js @@ -0,0 +1,39 @@ +/* --- path: acme_foo/package.json --- */ +/* --- global: FILE_PATH=package.json --- */ +/* --- global: PROJECT_NAME=acme_foo --- */ + +{ + "name": "@acme/foo", + "version": "1.0", + "main": "./api" +} + +/* --- path: acme_foo/api.js --- */ +/* --- global: FILE_PATH=api.js --- */ +/* --- global: PROJECT_NAME=acme_foo --- */ + +export let x; + +/* --- path: acme_foo/core.js --- */ +/* --- global: FILE_PATH=core.js --- */ +/* --- global: PROJECT_NAME=acme_foo --- */ + +export let x; + +/* --- path: bar/package.json --- */ +/* --- global: FILE_PATH=package.json --- */ +/* --- global: PROJECT_NAME=bar --- */ + +{ + "name": "bar", + "dependencies": { + "@acme/foo": "1" + } +} + +/* --- path: bar/app.js --- */ +/* --- global: FILE_PATH=app.js --- */ +/* --- global: PROJECT_NAME=bar --- */ + +import { x } from "@acme/foo" +// ^ defined: 15 diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/packages/package-main-defaults-to-index.js b/languages/tree-sitter-stack-graphs-javascript/test/old/packages/package-main-defaults-to-index.js new file mode 100644 index 000000000..c06d0d625 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/packages/package-main-defaults-to-index.js @@ -0,0 +1,38 @@ +/* --- path: foo/package.json --- */ +/* --- global: FILE_PATH=package.json --- */ +/* --- global: PROJECT_NAME=foo --- */ + +{ + "name": "foo", + "version": "1.0" +} + +/* --- path: foo/index.js --- */ +/* --- global: FILE_PATH=index.js --- */ +/* --- global: PROJECT_NAME=foo --- */ + +export let x; + +/* --- path: foo/impl.js --- */ +/* --- global: FILE_PATH=impl.js --- */ +/* --- global: PROJECT_NAME=foo --- */ + +export let x; + +/* --- path: bar/package.json --- */ +/* --- global: FILE_PATH=package.json --- */ +/* --- global: PROJECT_NAME=bar --- */ + +{ + "name": "bar", + "dependencies": { + "foo": "1" + } +} + +/* --- path: bar/app.js --- */ +/* --- global: FILE_PATH=app.js --- */ +/* --- global: PROJECT_NAME=bar --- */ + +import { x } from "foo" +// ^ defined: 14 From d8b454025cd9d219fdd22ba70443fa6359eaffb3 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 9 Nov 2023 20:04:36 +0100 Subject: [PATCH 249/500] Add a place to document package structure --- .../docs/package-structure.md | 11 +++++++ .../docs/package-structure/example.js | 31 ++++++++++++++++++ .../docs/package-structure/example.png | Bin 0 -> 227817 bytes 3 files changed, 42 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-javascript/docs/package-structure.md create mode 100644 languages/tree-sitter-stack-graphs-javascript/docs/package-structure/example.js create mode 100644 languages/tree-sitter-stack-graphs-javascript/docs/package-structure/example.png diff --git a/languages/tree-sitter-stack-graphs-javascript/docs/package-structure.md b/languages/tree-sitter-stack-graphs-javascript/docs/package-structure.md new file mode 100644 index 000000000..30b96945a --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/docs/package-structure.md @@ -0,0 +1,11 @@ +# How package structure is modeled + +_This is WIP and only contains links to the example, no explanation yet._ + +An [example](package-structure/example.js) test shows a basic setup with a package `foo` exporting a function `foo`, and a package `bar` depending on `foo` and importing the function. + +The stack graph for this example looks as follows: + +![stack graph for example](package-structure/example.png) + +_Generate this yourself by running `cargo run --features cli -- test --save-graph='%d/%n.html' --output-mode=always docs/package-structure/example.js`._ diff --git a/languages/tree-sitter-stack-graphs-javascript/docs/package-structure/example.js b/languages/tree-sitter-stack-graphs-javascript/docs/package-structure/example.js new file mode 100644 index 000000000..ba8165fa7 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/docs/package-structure/example.js @@ -0,0 +1,31 @@ +/* --- path: foo/package.json --- */ +/* --- global: FILE_PATH=package.json --- */ +/* --- global: PROJECT_NAME=54EA007B --- */ + +{ + "name": "foo" +} + +/* --- path: foo/index.js --- */ +/* --- global: FILE_PATH=index.js --- */ +/* --- global: PROJECT_NAME=54EA007B --- */ + +export function foo() {} + +/* --- path: bar/package.json --- */ +/* --- global: FILE_PATH=package.json --- */ +/* --- global: PROJECT_NAME=202D9AA4 --- */ + +{ + "name": "bar", + "dependencies": { + "foo": "" + } +} + +/* --- path: bar/index.js --- */ +/* --- global: FILE_PATH=index.js --- */ +/* --- global: PROJECT_NAME=202D9AA4 --- */ + +import { foo } from "foo" +// ^ defined: 13 diff --git a/languages/tree-sitter-stack-graphs-javascript/docs/package-structure/example.png b/languages/tree-sitter-stack-graphs-javascript/docs/package-structure/example.png new file mode 100644 index 0000000000000000000000000000000000000000..83889ee42815f7a49bb64b02efc3ce44dcb18dd3 GIT binary patch literal 227817 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�fJW8btGfc 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�&{n-7pInSt_SLjc)rH)F1{n~k(B4u^ahckyPZ3H(D8CHB=j5#qMI22077 zOhvDpS{$c*{)}d?{@}=)^vs-q9KDrpv{B}mv*X@;lLE0lEyI(rFiEcvR3etOk~~1_ z4e4Ow`QMw4sx6DCCTGFsMiy*szT$vWLZCb34_)EB4Yk$QLkVGOqW*F-dam}x-n`3P zION=!gRs@m4?~OnW9Z|Iq-Xkn4Sf-bW-v?Boce13=t9Z>!Zcj81FoJ^#MUhP!#N^M z7)hDLr&uFvCM>73FJETy@JNbDoBZR_e!e7wTD1VUxLzk2qAu`f4rZi?SyyEhTn>hiJ^UPHnydT;;y-gWT4lQk@ zZ9eR{9N@stGi5Oq{KG>_F(L{HbHjI(jxuRXZq$2hz;K|$%Z*2scJt@_o8sk!4+D=x zPc29EPyOkSo|M5%5X36Cr>piOm&?1=aWlGHUA9;T-zgPFS~}P^pYwg{uvxx<4MnyI z^gWLjZ`MEmxG>~xS|l*EPuw_M#2999nCXP+LwSC2I5=N=rTROy5pk*^A4=p*AF!r> z|NA$vZ>1qaW_*@Oy0gX{^=z=9JlDXRpK{K*ZZH`Nd&|@!n11}r7Da}`+TAsIX%CA1 zZCMn@nwRlQ757wmsvd9k9Iu`@UWffDj6m)!*|!H+l8`{ApE&pjz2o&9sqxgT7<~5! z86#cpTy50T6wTyh7Zqsnqq!O(9jib7P1rrw!T!68rTWeCV@l)+QVLuc zBAj+xM_r;z*Uv1VX~eeTq(HQ~@>3YrOik^04ATVy8hXQ74h#gXNf~`~Vqpq1Hd1*I zP~-traJx*;yJch+5Q*ulg)XDRi)68Z`y5L+812e`v7W8PL`nHEC>u87ue!O+e0NNt zt^L6VbPrseJV!T+UFt)n50**?ehI~LiEE31k-lH#Grk14L0^&)4s7`?(-|&3C`>1^ z)qe54C%>ua^nH-o@ku!rc$FyB$lcO>UDWkvt78ojUkEcV8Bb;uIFke^V$*3lKB&3Y z_Sha<9E%j<5RC6F8tB?Ud)H+5Bs1Gy?wm_pJO`HVijJytElt*(WM#b*$aKFUUG6Iw zDW!=+hW>FtMN5nK@5Fz{dh=ZBC^dTx4fOYRau^f13LY?dSVtPT-^F>KnYRWX?Y4YP zqOgX}kk?UZ_|>Pr#x0807S6ni+&d8QlTv>zny@60!Zb76eO9}|RSoLg?Z zpB96p#--|6qDSrIuDk3=li?V<$tW>Dm{N*Jk`3S}=M{AtTaAMq1Mn+20yir&qp%{s zw-V1Re`UU^ASODx!1}F2b_a`A9cshOGx^vv1S6&Cxmbjo`G38QJ9Gq{=`}xt@tU!S=i6Q;|R8scQ zN-Kl-s&EeTVCuY~$aFUI@nER}=H}J~jhGnL2@(GWm#L&Ei$3jE5Qwo}$lGMJ_HsTw zJ`EX!-$p%bD5p(3f0*-ld+ygY{ieH3Rc8bjB4NHi)(49kBH1kwEDxebMNdQ%iM?Yb z5>!97D^>nGcCc0qrOo!EW}va*-QvEH z60EICIaTgLawRWl{&oG(0mJ*J&RCcXUnTxeow0}mfx>>idrJOg-f$=(H|@ZmHyq?t z>(7d9?|n)E4hxPzyO2f5NMbcuK(BLl3C)l}R(@r8t?@&I_4dz^(=nRP>_)>RLRl0? z-n?_gZm?b>5Z_&8;gph-Ru*TLAsJ35n5KIv5qycIfdejtj^)8=^}zxjNsWvouY^G( zz^hsVNie2e8rJm8LO|?fWmY=p*=nx7=NW(iOL1*Ph|7nagCnq6gYb%11(oRAq={ou zz^6zKS6(Vi>*mwGwM`~I^16|LzNy7L>k9FbphIoU&L3G8oI9r1*dT#Dh{t# zN;l_H^3K-gmah)@x2x3vfCKXJTTWQOxjgj`vvFJgTITyrw_6a5_q1NL;mHNcgL!{$ z5xg@dGM<|l*;T2Dk(JuFVU4+1%7H-yKmNBgMn%vM>u_Xb5kBsR^YbleUQs2nq@AQ*jfhz;7Z-~ z8jhT(U&_Vf)ody>2k>fjVFO~S+fg9~^=GZ@J8W|cRT1)WM$WLC_%n%rt_(fF|aZ^QoWK5w^ zGLj@g^0?a7!2c0m0XWs>MhM2nKh2Y_pl9^$`15I#J*TK_2x2ln5iF_t9YA?Q){ z93R%5%h{~gq6&jqt`L(8NkVL>S8y!hxp`CC{1E4TQ^QV&iB-<>D3G@@?-=uqif%n7zlVx;?z%{Qo{^WG>JLi+dqBRHeZ9{v(nxk#_a^y z^P+p9yhaFO{~B7{pbtoM3qwB^)vDlPV1eXh$S#!BO&bxuR^yYE3XN)qUFAD2w5@4g z?icv+lnn-N%AFvB(S}%sU%sA99Dz)%EwZF=+a%qh=NxG-)V5h)ul; zBm>Pu5=X755;(R@9O*=gX0L_9&a6-Th9k)=rZWlYSbL4lZ9}ZuwDyL%pN9Y#{8l{1 zPsz3Jk^{@FG8zusH)6stwc=Ad!wSK<4XJAz0UM)h+)>>(0@l~T>+oP*)gt>ALLz5u z%iX*`L%o0|dG-;$8U~&_KUkD+jbE+n&OUUu5kLArAG&ytDr5fR|EIu*NdPgLhQ?#Y z*k7cG^ynLbf*@|PX{*cY4$XYy!g{(Ts#+RROAU}J*~M8(p75C%Vg3mZ5EZ+moijcH z-Q+xq-N|F_5M?!I@GM1&V8(GcL5CR8O=LAg?hJ`qc#vRM9jtcM*5MKq3b+0{!(yH-$} zky15Dd_&N;gazChP8D!=doOLcfi#xkfpt7Lu>_$Lc|9`+;cS7Vd0l)lndQc7{b8N| zwxJ_%dmH$f6o+wP8ZH)jaBH@!MS`)xP4pcWRbeK+@|!+I{_M;T={F;N5NcFqebueg z?Y0uq!x6n{3g@@A{=rJa7H4{-GZ*}=>%&>ac6mh8x8o*&Fdi{M#P~Zx$loqsWN*P8 zIJs{*`UgA*dNa^U=}r}~f7TmQj~J9yl+kd-@4YF4L`3cP^h0Z^xXA3^hHHgIx4aF7?h>1dQ z4sHrl?~i+bJ0+9igGXdo`t4c--1b(}?$7w|z4t5YYg*}xicEnK8*4N{>Wz_EtPa72RWkD`MH8ApVEf_9os!Uy&2SSquWv1)1~dFSu<5c(ch@X1R$1*oEx z0uL`bx(-|0X2KK{6X-uuM6eX_YAij0H4;`V1JCkE%|Vi96T03IkT_j`x0hRhOPzLS%V>DYynsNO5HgCaag=-Rx~@5KX>K3G#0#$-cLZ1>;}O z#AIOu@lM4Xr6-ku080Qj;xr)HMQruwN!oO2_D6dGA0* zi(SqSPpEytHJJqGEul38(%xF#8tp&)Y&4|XilpovOmZ-H&l6g3l+AUcWwI23h5=HaPEI(%aa1QgU6#RI=KQ=~0!sZR2Zb2nw1( zUz;v4+&{@>+}63nNZGQH#9ZM%pm78&spK#Wq+>v!q*@bY zzL_g%3e<3>S+i3{$H2+4NMCxVsu)uo7C*Q0mr77DEDkiSKn1Z;^M?Fhl%@#q`40N* z!z9QUgcC?*c|h)5m9N;aVtbqHA@!N@R;7gf{TgdFo#@STBF9fE4(AQljz8wr%Pp^^ zCka{$Fr=Ur8TCWw6YOxTT-MsU!SLxulqT77y&o~bcfE919~^PHj9A+94&vA!dplYS z+H~?cd=b!HlJOT+pis+*npiYG^n#Spb2)|3b?NZb5577WX1-b`DTV|aPjL1jcx$Yt z<{mXRKS$WTbA@L2z}vplMBKc!EQU?O;E9SkEy}Lu$%3UuO+6O8yfzL?58U*&=3RRnRkL>g0rN?o^2A%9dw$=c>q*l%(wjHD+zhRa4f2CVkwI*988)vu*#M0!qJb+$W%*fP;Mt_=f zN#u2-_76d#jZO8(2fQ6=&Ia(?m@QxZskInof7pO!-2Rb;y;Cs$tz`N#`&(4spLY*g zQ*CY6$6x7uKGYrFknO)TLk<#{eu#olLD4d@-lD)zAyGN75*7L+B)|SHkHE_9NX;e-+*+Yqg{Vw6nI@6Z(*B& z)rjQ`p0?%53|01gTWx=VbboqC+`TkjQvXEpOXriF=gk8Q=Ucl$tnr-BKM|1`_mSB$ z<5JdD{>^I^&~4O^iB@`6J>esQ(TbAs1Og-bDl@qX#fn{gIACI-95gZz7!;HooD5&P zJJQ@GpL~VLyt{pjEYWpoOXGcnO37M?H5Nui72hT0=WRewGcj1nxEcma>;v^VFeqLW z$&PA*JrR`Xd|vW@`rR?xt+I^}IkPcEuOQF)7t zp{O<9;ebg=aEDQbDYq%j+@61X5tF4YuR-E`!vPn^Qw58ZVWKmVD&gG*8<`r139j8x zvCLpxj>0k;&PT@CUtZ||INViBkvCRWV0`FTI2x`qx;MfT3QG;tITg9S7a`cc$5!7Q zFGqYF(~_O__cv&!DBtvD#o&Z!#6z`w$Q`Ax$XPaVm;oyXaN9SV4$Su?i+;W=w z^m=#7S`M`Vw=#cJ&9R@EEtstBa%SF;F%^ShR0{LHY-mk|xv@~Aq*5++3jJ1I+iJ$@ zr$6ST<-QNEHbr2^&uOVx5p{vJ?88msS<)$(8_fF6QXD1{bEpC!3eb&~(u?wmac*FV zfll}v%QwTbw4dD8-w}*Z&j!qiI}xn$b?9__VZFVBCQFvp33b%fKUQ;HVXtufUDrut z>3ppY$78Ry#XH$lAJF6utsuHQ;RffX?~+MaOcDgd8}`@UtQ<4D?`qb+Ptq_@s~r(4 zU4%PQW`vGgZuj;xEg~ce=71cL-gt?^2?(SWO3EWQFY_Fyb!E(?(d(2|RDa3Kgy2*U z4-{PW&h zU~R{?xOL?F5Bi__|AYPzs%u66MgJQDXu1sgK^8tt{VHTE(y*%s*Vb@UVsvr!^o)q~ zn5@G_(MDN$29?(Ro`r-WST$x5XE<&UC?Q@n^aw)7^E_RJTS}yoJUC@KY=jsPgHl+P z=T8JyMU_g=P(=qvcohKTJ}Z$rpeIU7Qeqj2V61DEx~YOQTOG>` z8Vh*lM_kX}=JlAVEhRJV)RzJyP-zjF5*$(DS^3L)JX1B2yuwAh2qs_TW$5p0_UII)Q{81D+VcN(a8_k#7^5(RMQ zKbvK+j-&oKOBT<=08H&FPzKg0RDS^fKUlv;3_%*^-Pf;bYt!)A+aLk+>@z4FAzhC= zjTBy@>0AT?9*s2I^Y-X7qKr%u%aD+_B58jZzVSmcni%1JwNvJY#!G^0-QFVK$GhuU-vu%v+I`WcR|#+0SQ6 z;rLbT9--SD#r!`l04=)8A`^};%;_-^ycNkJ4yuT@D@_>iZ0TRFmxRRNJ}Xl14o4fy ziV9Lqxof6n$Kr8fC@)sM5!}C+!k5T?4VS6us2q>}Yq9Ff_r7cUu&5)*T%VGnbh*mqk*Lz7`e8vGIhfj^Fs zW5i`bP4%|rro%EEoNnlZ%J{U~3P6+0E0S%f0;+20%3%Iy95V{8zxnZ?1i}akEPV?1 z2-F0sAJO_?@AzcvnP$H~Pd#i4`$G$eqpWN;@fD5tqkHTcmIt^z%^uI+yk8!hB|(Nb zk|~Nz{X-z+&M~f`DP|`%?l~fb(??t!D15Sfp4~_Zt;$Qo)ObxSv zhGEt8I(}bc&bvHe-+k{F7dWPW44W#-q1QWQT^(}|G#n2#(cg#&bzkB znN-24bY2wyp|en%HJ159xyZb??)?*10XYqkpq-oSccx4g1=Bj4Zvt9Zom5ueJ5K0K zSi!Vek%Yx7q^(Kg=QfvuP9?Zqh_l6rqdOvr=DWL=Ag_+CvmIDiU%O`Wg!82ES`5`e zWIv@+X+F%th}=79z2<5F6YB>k8Jl5)-6Z}?4A>xV0ce5**m%$~wiU^e?#Wa}lCGG_ zSY+!w@a+Wvl_y?DNtBU(2~#cZlWYP*89zdH@<+qrFcf(DdM6BEa4-Oisvy&nuHksD zJSpazb%h^cZMDM3rq9c3wZ`)6a<+SsG5}=;_Vw9~r~?&6=;x{eAbMkpG9ZBqBP6A> zvaDJciy35SmN+e&tVgJ~igQPy#)3T0P#d4*s-k!^qGspeyUE9Umiy#@@4Gy;a3@vD{ALO~sO%(Jwx+SizHwTjMdbfh6<2FPmiS)y9*uVThns&UtQ!MOPzEYH3?86}(vnm~Kt7ZtBbWDWU zXsCB_H1#B{5WJ62RYt|?!YI6c&_HlAHawX`F&)qJGbW7cofyn0`sH}mFI*m$r(xV#IvqIj~fQH&2d!%<)cwM)f4m9+0!E zl6ecZ6Dp$qg?%RTe$yjI|9NB7g~wK0d*$bFaeGwwe05Y zH(CH4Q9M6hhR}6%BlUrwvEDQhk>w=PQN>qAuM|o7_snM4EWtb6l{RJ~>D*`-SXSbJ zk|RKPR_nO!K4w`wev$c=QyGLOQ3>?)NC7~uZ?iN&L`_YNohF|IU1Xjn|Ls+W7+vi- zyZXDEy>tIBH@=vnV9k;+KitYLW6y_iJJG4U{A$~}Nr%+bg#)|kI@Q07{64%QeWA@> zlG@*6)fopOE5dyFYh~MgA9@5@SZ%1BmzZQTn?L!z9dG=hkCsq1fmcN_Tu*Pk0iyG+pN3kSZx{Uj2j_3-pn2}ITFecr zB`W_L40r(yA^u8Is@=29ux=#ph0=T%yU$ihWf34-FZfOikWED}stP$M^6Jq(9nq__DWAopDIcL{C`YXXNmyk7Edr?Xbg|UJMI9&^P6jV_9R0K6X~)(|%hb#G zAWedQQ0~-NK3+9}?f&!O#Klm#J4ZzM{q%P)q>Kq@PIQ|)g7)besYkT(3*ON;3Iw1i z3>Un$brkS$w|IdeM2uV&9v7+Po`^5FM&q?_s@9~1byaR=3RRgVUx*0%)7SGm(n_oQ z(zgyj1DrFz-R|)9PJmta8`m#iABWKtx1Pb<6HII@EK|1GQ@wZR7>4)T92v|*R^RPa z@q5ckWRaE+?v&yJiz0EZG)D9;9Aq)YN8mL1HS|x8J5ef9mQ|(W$&!Ppd+N(6LaS(j z1dBzn%46y;MM zq6J|Cv1mMxt=!pry$kCQP+>@FxKLt^JG?4jlnp2Ni}ex>wJg@69T#`dB=SoFl> z(LvWgociCgzXu6Ww%hOc{>H9PP(ZcMhrW3>+_PCH^AWN^ZFr?y5PBZDA1gIlXPwAwQVa?vl8myxE-=w>kH(Xk9yn9SB8m4D0P#kH{7Rw(&&)TqQfG>g zxw4<|Xvc9nv>qJ&RQdkXhWQ2IL@v6Ql5<_eMI0>@B{#au=VR>iG-@(HtlQ|M`e_Sw zzr1rBy5HCL<&01^y$PohL%xoq)9=*S`nS%_aS&`OyDWj)wBJF`9lh!u)9F(eKN5Fj zFG=E;eA)Ici^q8!94(U!Fv={1Usu?NQvMi^ch$<}{Rx>mS?~NKTwS5BMxkpT8S2?(7-#B;A6f z3cr`OUZp#TB9`tTg?+Ofx)fM67zS|o72!T}EJRhXBnpPc6wB5#WVE21p*!vIk4Q=l z<>mL|46zfWt-9m)6&z)HaxR#>-a7h#_}feZl9;M7J zjjgN{Wd77Mon;)>=fI=vKwWe>kjoW!O80q11ws)y1x=$o;B{!%$wo}omFO* z-O-_Hdj=l@LjRngN*YCzzEuV8h>}DzrKHI32nPYIJsjZsr!=`6H$AFOY}Bv{t!dFE zl&f)b%;X$L#!`b5tH=yZfbrTwd2G$+<|_&!TSXkEM|#4LRsPG#1Eo@R8CX{VUsct_ zx~nygNR_?Y7stg{=LI=xTeCQ5LKx+i2LAwsy;=?%c) z7|2_2D1`k|*=k;7ZH?sO^`C#d^Plq5i>&I;;{W18h*MOE&-di?`-H1%fmOnhypp6- z6b@$^ycSqYiMunxM4N(0EM#y*PF{V>vT?K^GEw>OSCFA*st8g7S6zv6uQD8nGy*fg zWZa(3{HD2y15HMiRBMc*!uW|b#@h=^CP$}2LsRl&Q1VtiKR7*sPLb4X;wd#LJ-Vfu zH(ALA;1do`G5Y-$W!WrRjmGNbS;ECc-W)^~QASW+oq1L22|il2#E{!hWhzYP%9NQk zc#;%h@zr~8SBBTp(JGHNhWaScsHPM`Vlq&U_E^^gpqQUuqPDQn7j`Adb+XW`jDA${ zxl3LYC9DDh!x9wOG%0%fk2m{|nK)RQ?*aD|aG%BFm@MG52)q} zJ5mqOz~r)Lx+W6Nr{B!iLHdH3AASE=ZmW-kfg>_=lAUhf!oF+0-UJ++% zEI?=Y2mU|&R1gut1mCfcGXuo_M$D~{r#ytGDH5>8RxkhjZ0Ga9%~E&xhxKQx;nzl; zW07mNv>dlf(-M?@rXpr$_Fs9Mr0XI#k`>NU3F|d>UxNa}OtMgY+y@MnbB_p_wOqH& z^NYpc_?bn%pqEy)pgkrI)`UaHmN}J8P;Z%Qgnu_WgVp!bxtuT1s{48&^mG!xNs3D~ zFu$pEvrL*nRzWC{$O|QTb5QVKzO)zf4=_JJ9jyOk8u=}}v`JNetYPjvl8HL3 ztY_)Hn&_Bq$c?qF0!}Q;MqOdSx{~yc3g$|juna*`s{|>5XbKVV=ny?rd$qOnhnU#W zMO6urNj%tu<|NoWzOalY1V=s4ApcBpY05?@Hwl7>R7Kw&VcH=0n}8-O55g<@r%fpt z&X6)HD+x4X55 zO4^`SJ(2zmcp)+aA)zF}r=)+*1OMluQD{_jBLPuSC>s_4i(A(-bHe~%dZw-)Zd~xB ziDIA-nh+-RZOK$A0{C*1kvw&O0z4)}!y-%xP{JJFYurHY-`xldP;3>Z$F8i{Xn9g8 z(l{vLsq%KUWG_T_yMsQ0O#a#FJ216O{zzd)>O(aW>U<>sw%tC%(BJs?_B^v_oPr$2X`)Evk~wHf`^y}h_i;@?qk z8ZB%T8hy_iMkjLq_M&mysf4m!8qxsjcOVnFLzXAZT*Jpf_K_J7artVc9x*J+DmZ~+ zB4LYd$r-IrI$C`Tu}1`<=qrhQ7)HaX`5KdFvfV^H(5~pA#T_o`xUn#!D-xxn;{}}m zRIhje-~Ms9w%fn+LH|b~g#M7lEBuWsj57bjS*2sc0r}xQCAL;~%#Ch*9xq&@KqV|C zOAs_b3IwHOqKKykF9jAU_s^GLsYw+J0dJQ@E*HqFbSh_SPQr?;`^=Vx<}AIkd^yK7>{hpfp=B5-MG znT($ru#mlyFpyx1FCQ{hYq*q>_7%;?NtelNkD$VJfG$H{_G3cRGFPTrXZ~MzSp$4j z@y^4Q6~jgUbD#iMuuz9^cJ|uJB~shrop>H<|4$nW1iD+B$d3hR+mhjhH0qbE6*LJ` zY>5(9dejjGvs7j{I#{!@hz`!tjnYlCikgz-%(i|bH0?JqWM z>sQ8ciS{d3%=YuVetaA@6q^UuBz|xIkEyQ;h-(S9O^^V=-Q9z`dvKQ^!97558FUE2 zgF|q4cXtgAgS)#A?(!z*oO|#4n!nk*dv{l_wQ5y$(+#SPltPk1J<5e;JQ^dRfV8&i zm;8S@@85;Jga~=hI^3F;RZYr?R%QDRHlm56?HfOW_s$Yszl_m+zMU6`No5I;si>+J z)I4bGEV>169@(_#DY%; zqEy`;c+op@d+1{$<9W}k1KY%UUDjD|+*-ymwCVWp4qKg0hNG-;XT9r3LMpR=CtMsZ zV}+Mp`~OUvKEZq0jfvE^@dBBK&ljgQl{rJ1x8j(t-fB>s{(o zLn(pTf?(%~w-+kvIjo9=HvzO79&?^)(IO7)(pkNh)1Dh>WIeGaL3=S(Ossr^Ip}3H z5fO$ZTGgoqUe1c{GzaaP1br{}4&Q;?fI|OL+@s?_y217PSO&fv=tpk&y|V=CKI2I? zGzk^S&?IU8&E{XOBN`ftVXV+wTS2HSf2j!16$`4z#cIkfiI@f3$m+GNxf-WvDQ+UgWQM4xpXVo4j&qs@puuwtrQlzHUmE*CRs%F~i z!>8Hx?1g;p_;XqgJ~rMy;rmwKhFLd!*n-iqHZ0|?)+X#c)Bkr=OBjFGEps5};BfZ(WL0ilF)vDV#M1|P!nyc#Ey1>D~5aB7wzR?FRQNlX0i9%hft zBCG_WIB-2K?{) zTBAYmBQlPs(*J@R0zVqG!67AS(oc&-#I7lKG)6~`sWr*{LZP3ftfgo^55*=aSiqQ0NVdob``@Sb>q)b$25s^oP8*_`P4jiuKRDpr- zhM8?j%H#LlJq1xIhoL6AA{hKgDrR}TH>CGkV$=Std=Jx$qlO6u+ZW| zjS@48!39ZFjr1bl+&WgK!(IN@CS}e?mFCX2075_tVfL-@!-upNy z?^iu?d^X)f%>pRN(56MNUCOU(gObLKLubiDtA4XO{gCJIX(y#MwU#0XDK8pTmfSEX z`k`y61KVofCQ}3SKYP4U3W5h#A1{x({|*MBkF55BtxY(tvRI2IlLzJ%qhqExsV#er#vMTQGO(heI2$KXt6i~uBYZn)NKOmA_ z#HimvId2oh@%HDWXLG@4P=pVm%2vvG=;?m3+E~fRg5&Cwy86$m;5S#G(9{xs=BGu z?sfMwnD7f7MuwysZERm}&!T!U>xIVVSKHYq|EEUsAT#BYZhb2695y-^I`Q6M)1kn5 ztvRS<$=2CvD}t`XK5cUargdcqmFA_C|NW$Y ztwIo>^2RksIrF~=FO|%J>Wr-C1IL#JW{Xf!NptF0HFmrd>Q@0OK+%Tm2>T;=r|Zv9 zO#kp!`*t>bx{f+cQcvy4X$obd)kBpj>RDH}&ocHR<#0xp-{!9qKENRt9s%DgYKF)d zzyJM7UB6ACPDGgW zJb-3Ik%mZAZ;5hhqz5y)vQz?87HiMj7>ZBuE60A7zV|*ak>4Q13Lm<{F}nQu$MWY* zSwont*EfeBB{ziD#hcezqMaxYM6=*RgSr0}O06_x-&jUv+ll=vFolX5hu%J0VUV>~ z%ab{YilAA<%=s;Zh->Iajv7^1uEb=R-oR@N_~yUZ@mhPSb+XokLa15Z zr3(`DyWp@i{V1E&o!jqn0IzG!%aoy#p&-GMJV>RhOEx_fc2O4)ZPj~-((dwT_U|q zZ?1uBlQ{`D!;5kU-%r;5aS}xovRi6;bFB7qFj{XoVy*ag4~wK>2IAW{2=aP+WVt?E zUeeIFU72K_SP79;C;tN9x!&;tmDzs5f+d*jAL_ivKrz@m-#INc`Fryk(xo&$#h@+l z_9W^LK%_#<+LPZiZU&>*%9lXtX*!NBq+nX?8YkA}=Kt9B-!(Jd`Jn~wKYEje&gun2 z6(BA6)y0Yg%1YyqYEoNgDyMKlTc-eD=YzAkRd?^$mtp{wv*zao(a}sk$ru4)J?=uM zoe2Yr?WIUO3r_(B^QcC9GM`K-qq81)hkfYEuAZEmgprhbm*f(i;vwz3 z7asSc2ExsQt)H?;h^Zal=pU~+NY$7^tVxTL1S?R!H^TI#~0P2Q`EIHE> z&L!B=P_RrO=Z?b<`@*F7M(PTG=q7R`<={@tG&Iipd4uvE;2uLCK2p5%b*+&J_}>fIvR8)-3*;3W+A^Et7m&m-HK`w=*a*M_;b zXFSkQM%xlOTXO$&zLKTqgDPA9*G>q{qSYDP!WVbj`Nj@ht%9XjP&RZuN%}~RX`e0n zDg-NI?dc1V5fE>VW=nw_o;v@5qZB_#WKMY>yC(U+Xh{hF{l!!BV+&j>F-)OSx;VQ; zZNLh8EN%LlKrDqme1?MX?_Zsf(E>ReF%D(bs^}WviGzd=nsnoe6&&1+Z!53XAQFV_ zB{)&FybY1kcmOa?Nh^SFZ zK6?fQwm%N~A4p3c<~1X-o~}?=<@_vQz+riKGD+v;E>XIZmm6{X9S~gq|Dnywy+VA@8`)yogr8W!q$n5L)f_v%s$oX1i62+#pKopPk2>>sc`*LJNGi)2 zosOAV)IbU6r^Hc^Q<`n%&gS@B|IznUzU_-Y)cGHr3YYYB2Gi>l9>HdNWV9@qYXZ!l zyb_|!CMdc&1Wj0<+XQEO^P2@1zG(dJo|<|LH?{p196$+IBIM;pS2HlXs_t>Ckm)0A z*L=JP;ZYOK{GR%%n%oB3Zd|V&XTg!eu7&BK$ywyE%GcTwX_OO6^lL6Vp*NxcDWu+= zhcH&Vxi*WN@-!W~PTxCZJ(uIvv8B#jKrA?DkQ{h|%sJs=B3IX7-Za^vUOP-2h z$!VX%SEK^yzC;;(rKggrnn&BT(@QJvb4a;dPRSjNfzQ!qt*sJi7sKR%?NH-s?tKt@HV_q}CScvF7ah zjA;TKO6ZRno3kgvhDx0XSCO)=RFL3!RTUrA&+$K5#=V4pw(xpOIz0AW%?hbD67~&j zTtu8#$Uc!4-yjz{Uw-`km5!VqTh{7up~X2$4G|j)Cl>26XFZ{CNO!OZhk!N9HE0*Z zo!fX+X2o+o_x@tu)%~^_uF9-lqu9p}`Yy`3 zg~|#c-G1L>+wI`Dog5uGqJ^e$xA&Ga1I%%0z1X+6s&}s{9oPK1KE`7Jff=nve6Q87 z15%EMR)kWZBW$}{fg63X2h)IFBOr6T?M)sD{@uczMa!fm8 z3T7DMd-G*gHnRP5-=zy%aJ3M9mi#!4X#?8XTTkNf)<*rx-y7q+8KDol{jmqzP1!*Jz!QbTBdUd z!Md=@Iy%W}VD||loi@NT-Z-11!tak`v1m+ezfYCSNBY0GAJ+#vY=4P6-;<`t^%{;JP93CQGEP5?-I*oY zl=&^c9L2}E(AgQN_8fXt2}G~Y!c!tOw|?w}BxpQV!JiP5CmohR zsR7ZIkl)~-XSBR4l@9vK)pNT%sm2N0@yd*z-i^`%)Y6;sb2-yUOW8Wr?XQ-}XyO z|7P|f;-L(#EMMOsp5{*+TJ{)%xzb4ao|ZT-06`g?`m^WqBNtlI>;BTaTvi*F3@;aY zQn^}V%l&|ILSL%I+OWl@+n%+_(BTa9Bwq9P6|E0!3rqYiPEpI?>q4cBz6P+bsF^$O z7I6I|xZBwMu}%J>PfGEb6V7#g15MBKSij_KwGEw6la29Ykrv6=cob)klnduV1Q>)E z9Nbf(%(5bAN@Sp0o6n~RNc9O&NZ>brF5)-EsI1CGBE?jr^SgPP?JP#CnF&`o14XNn zD&NNi;9LQeW2cglBz}W=F3`Q+wm}zT!e)rT?KDONzfp?XzJf1m>e3 zpu_XBpX9OB*8C;X*6=cPlLyrtDXX?@j!FgdL1q)4si>la4>Wqeg)f6v4o;>k?McH4 zNZ!*1StAo-Nc|j;z^_}6?zyi?G`EaokJ`Jz~^#>n9gzgvZAp z!V|F~sc62ir}8ISE{5BiKWPDo^z01MY2Va$`PCDizqb4KVy0@Q8cMf{Mo|nX|C~uB z6^N)`2l`d60g0=Z8#a!N#Y*npkKekJm53xnk%aq}uNBGkGqaYt9p|K%BL|@(tJlBE zMpDr*n9#-SOc0X#1f{L4@V9DADHq4~-DTSQqJi2jKQz2v>!hE0{>v6zaG+A24;goE zJRt6AKN5dYF?1o{NE=WliF0@Bq-dl4EA~ibF=0ovQWP;cfJ#r?d|YjBSRrEk`hd1* zCc1H>(|*-&Ys-YlQZ8+c3TT~Z%4xJ#XHNV2GD=ymb+_>Fdx!G=GES??{_g9_Q{sbz zbMXb;SGP5HA|-AA(${B|s6NYSxXdj`-8Xq>5t{Pb9daAmi&s=%HWM7v=acI{xEuSZ z>-~THU)Z`qt21r6v+vsY0i0(UBCx2w=djP>JqpX$3dm3xkJLAr_C5hFj~~(nUBA*3 zM0mkFy2P#rY9?sX?N|b~eui!Ko@)$=?-`ylVQJWYWg@rw7rXmKibK#YabTS=L}dIA z4z;|4GKu`OHypfe;z-7glUcs>a|Y0v{}=#+DnWQsY<87XToWzWVSvHR_SJkch7~@y z`SNvvazS(!G@LoVDLP7iWAuBZs&abvV-}>h7h~%giudE5y#BkGhEo%3IYEKY$61Xzw^=?L2PuHN1|ff*)bqY{L1 zE>P?_H}+@qTtLGMC1xv2yuQW|rU{z1;j!(7GvQT?&r6ye0TkjXK5BQE3;##Vc+VkC)|eHIN;11Qd|f3Y3(9GBN?_MwHf|szcVmn}wSi-C z=U}vXKG;+U8|Rt#_Odm0+(YZnHijm@=`UqgmHEEdj4N<^GJx7yCULS!`3vbW8TIb& zWgAxT>U=R-HkEHiMv?E=f_05FQVN{5PVsj=RnvmaUp8O~r!De&Wlbrl$j<|mJOb#8 zi^-$nX2_PbHW=18AxO0Y@wnk#sc*~T&$@{zODm2g>zxtc7u0D=8*lABh4lBuaChL| z60Xk8!aL!f<-_1((t^ZP@gG24!;V*$fPg?#dlAHIfo|(b+?O)m(}7~dvFV4q^o-vy zty2c>Aq6M3iF!YZ5piv>Rhaa`*Xu*)Jvhj{<&{y>@SFjnPM_KVRGeYtU+Jmbr+72FCm3ZT?8Hz% z_hh*en21Q9 z?R#Gy|FIdl00Xwp_2ba6f*7}r%)On(-BKU~HoY0IpEXeM@WCdtIl?D5PjJ>HK|h@@ zXQa~!s|JSh7>2bbuyEK;bBuldarC>@;1R$9`0(q}soL$&{QZ0`>LpKEd?cWbp>U2b{=m$3WkA~$|aCC^x{PN9iQ`t8RsIqMm5`onvRS(af3{s^jeKP+~< zf2Q>E>WekGE@3IZ?E&mRVz&w@1R&2ye`fhdn)Ks_$nU;N88aCown#Qn_7!D081&w{ zX`eyq8lM0VwHwY~Ayy!kWOa2m@FR(qr=mNne*z&zkNAv45UB)W%2jmLW@CKQQ48EM z(LO{4GMzd=FKO`DPMO6hZ!mY1*BRLUX6<&{5slNe}1g@acltw4z2hrgZ?f?yb@a zb*|S9;j*_^!WGX~sK2}-&jXPSc|39EFjUssH}~?z!@N98`Ts?H@E0o5vZHf{u#;+^tk*2^$O}9Fj`V z405ts7|)98-(~!`vFV;tT&YEFR;ZM@1&&S>W1?Cd{Ki`zLXPqIp95bX_b>ZhwJG$f zfP7vTbeNA}@(z$*Ip;?Q6p49bt;tg2w4o6Bxixn*o)3GS7*g@EwYgU^l`Fqj25-@w zBI5ipU?s+Z$(aEzr?E!9-Nuy>ID&l988KdHZO<*VMc-FR zo3%Xmq1NFMJ;I4 zzvDRUB|RGdr>T}9K7D!42xjb8tIg1uY@sDc(|m%_STEK`VKC#IoYL|24-cf$_>AAp znP`4!d%%&DW4OJ_E0@nr`K}ln9x0O-R*kyMbroQ^HPZMR!ISBUg}FaE@EbO4bMtup zm*x#Qap(`s+TZ-DfuH1NmLw~R@swz(@?-Gix*^w7JU=gg`Gr?gQ=>*c^eRjhc)(z$ z^3h}3Vd>exX@(>&V;=sR>TkVYTtx#(>3?{Q^OvZSf#1h5Ir3^#m2(+u7YWa6_LK=v zwRTE~cqKFvWiLn@L2Pv{w~-1uGYfCC8ITgZUpS7~nwjO^F)M^9b(6LGJ42YmwGc`E zin$GiB;!%6uC}7sjHNY^L?q?@u#91%V?Q4J2Vb69jf;T`|2T>1qwu%J88gp3tDp6Rur;No~*0^Mi((7Nz9Tk2S%{A_3L-` z%w`a_`8_V1)NYYT_pkP_#3~f|V`GNY`Bk!*nV&e91XgOt@W%}2|!VjOu3xq0sP)@v+ z&dRGx+lkDROf1t$(~N`2jY15xS{`7!8x)8UH*N!;n+oX_Qgo=&p8N9ghi$5+giLIO z#>dMVNWW#xzO(gE35e!@vcMKA)T@CvzlB(lT|=A2fLthj{Uv0fHHT(9zrFJ=|8ICeHtf1?(pkxZ3#iskaV7erzd$}Qp(zTbjI4c7U9|afC>aGeEkWLioX6# zSkwBCNAMHBk4d1Vzd`Wyp7N-lvCkFn8S+m znH4FkOrQ8y+(1`~;F%#^M8q0Lqjl~+l7*q`<5tz~XhG;j%s|+EeOO2vYo)VnVIOt) zkb$XH)i}?Jzc3)a(z9=JqKB!qefEo(RfOzX4akv zlGA@Ba8|OcOsQ+ye<^Vt2NbMAvgc2l+LjqIGW#2~gHFo5;o|Fc^jK+c0F_{AUS7aa zx;2=XfKlG_`XV=Y`rD%V16W)8oBsp>)v}%4NKobmF61@|TlhtF z0|RRcuRW%=m6O3@O_W+`5;x18&uv)c678Nlf9$)n;E*E%{uMi)FDbdpzWVWGdJth+ zjQ9TzlxKC2`Hc8=y48&qCIvzXV9zIaIL&#}`wk!18|kAuojO?0&G!^l-#)0AV{IJE zn+)m_Dgg>ngGl6S{{pt!>?wi28*lGtS3RmAoV>KM^WixDQ%o9w;LrwjV_>z|a-}iX zt?A)sF+A#}?ff)#VF9I%LVVy(%mgEbz#*hun6M7$^VH+t7n%1X{=6(EMxtmdIeRd@ z;xU1l@&>-+=^DSuQBS`*kA^5HF;S%B^*$Trv;*%gA!dV~g+UT1Mn2S~77!#&@m&UM zkFg1>0|+gUCjwq`fb;ermA{!GhX!ZG5iQokAu@MjbqYRJqVVT>r1ksEuzns*n%Yc% zIIG81^)M4*gmZaONm99d@s~mpLm#;6r6hECyry3e;O*%iLh!lQ&5<7`GkWK2 zzXe%g2JPMnBEvQA(NI>2`9`TAnZ&D150`wRO4QmM>_E~um4VdvP#?2hn>I8>%W`gQf#fCpL(eFN4f z9PxZN%WWskS{pa_Nb<*37tbuMUlAe;EYi6i)J-eCtAHUc-x#E?_}4o_qvLEz4C;1F z{ljZipCL5i;WlDTz#H1q#&q_1+|5sjV>)W9z{WB=uMSFC(EYvm2RCA;DHw2(%=GsG z&_a=VKP|S=Od2l#^);l_vp3h&Vnfu0(XMsNNg;F1*$zqo<3Q&Mn*Y+p!nuO0+EElP zPDK2tWiTxq+laDyx*zhze*% zH1yP1wCREkRa9!ivNt@0G{zoai9Z@Y&0ZV*=Vl<1v@(uBh>G_e2W=E>^Y$bJUIpGa zZOFE99 zeEHk1;fPEn^`6ac0wx+gbWS;nSU|}s*jQ&YBR;JkVj7t?88iEq5Ma5;KK+Y!RsfQs z1t<^*Oqo@jY#mHIVglkQYuPc5(L~tGe*M~p{Ktc#5jl{AgbN$)j<{r6NAcaPp9G5w zIZVL4$L6FoSzlB&7549qNc*|X{Ik4w>?lggtz1wyp`_bJT<^_3iz{?rjQrc45jpc8csmeOSMs5K_~1OvGQ1r@}}m zx57Y0po{d6+dvJ51V9QRzXtt1w1N`X{*gnCAaAd8byY$GDnZDi*|c)lu0t?&=x&o8 zc4+PY;1jjQhT2-50NG zL8b)4qEi{5#GgNpvb#TX&Pqc@78to!fc_2d{YB^0zxl@`YAE?i-}7+DTW^cMvweNe z?3WZ0f`;n$1E$>bK}$v0;%x1=jL@oHO!Hot3eL&ABNmP|*2^zU5BY&6f*O%@8LU#- z-$Dg5Vc+>OwP4Y1Ksj*;4}WpBVn|wsc{HnC7!IQ%YyQQw_27oUPf1cVB-5A*7`uha zQ%WlS?vMTa`s5gtJU9=X4C?DcuE>YKL~oJeeD+wm#$FAXT9}Wxw=m6Audim{)iR}0 z$hoWy?;^EB3^;6zROKkTu>k9Ei7E}863dgSl<4aroG8^|ag|wlWHGV=f6N>#E})r0 z{Vs0zYycA>g3DdOWhIIFe9x>zQmXRA_ZZaUJP31LU!^gE4Z9e!d=9(7T1K?8d4LJE z-<4g!4dPT!B8l1|7Aao!yg5T`oQQEiC3(+UUh?~eVLd?lUb_hfS$(8XiAZ`BL|OwL zhfk@}E*}YB{8jftsQTqA{QeJeJl+ez>*|9?E8y(L=z)kKmXGT`QCqe9)@r!ES7%k%}QB<9%d2s4J}IC}}6@RVMQm zzcn;BrVu!gTG?G+wi!eQBq;|d`JUd5-EiObI z7X%{pFKjqWufIgzYd^aip_=Jtg%Q%g1ojNf_Rj1jTL9M@p>;7Mi&nos>29qUQ=%VO z-7AeSjSl$ESN4xh@AXWMpL+}rk94P|0{?_hWG8ifGM5-Nc&_qAb&?Nb<0r%OP2t6C zXBtlvlIu@3(8yY1eWl$dJlYKgaF_cf`eQPah>SHMklI1WGc|9`AHkn#Q7~TJknFmSgXs zUi+20j)5nfQ}4F>hSVL5KGdLD3MlOIJ>FWawH`PG@Mwvr#<}k zIT-^D25!DD@DX10#VV%WZ89A-a?R)&HofP4q|2#A+%TCX#YIL@G36qj7z}r8yWue; zKo3~Oe~_X3^k<4yaU(JHIZ8LDV^xiU_ai)H$DY{;^Bdjfu9TV03FZPz!eRu5ZAJ$<^V<@a%aHUw`b z?;CQLZI>_CNE3G4F${-DPesns4JrARr?PxdYJR8L*2%H&)mi657@b(998qrXYvYcZ zisS_%tN-3sNyK?7uD#S;;%e@J-`4p;aF(6>B|g5q{f=YpxFo3bt=8@K^LZb2Tj%q; z!h2nA_gkmyBh&k**efgxqCn+7GosaJ{nK8BtM+?BhP#FO0rRE7(L2`Ck9aE505oWSk*s*RU6NUPui*Z$Y}PAyR6a$p*z7pvJTSAowB zB&8Bms#9C`Z;L6>L@7}qo|XszSt(N(mL--0*2bgn?K8V4qfj;K2QyaWbaQaZnZ%?>rdFcK5z4G%pq+Pxzp61L`p%rjCDM36+UAe0w*7nSz;XEDZd zhdb;oGf9#csI|)Vu6GV(*xwWe*4zOVtJ79*MtH^GH)39$`DoQQfS=wjleEyWxQL@bL!o`rWixYqTDRaR=Hx7^06-h0jh^DMDb2Qxp# ziYRwJBGwl0r3_}~Y<*g}Xsn!N+s=7r^U(W|0vcpieTpPO&w|gUHTa6Gh3n;gbL)hJ z;5q;nh?~8&!jw2SRwId3zd9dWy*fhUF3Fa9eFDSjI;5fMi(8+D4RxKO`bMNyqy!9r zGfS6%yXCG04Grgdh|Ip2^9K9|=pwWa(SRZ3Od~HBj6FqEOMya%hcQy)tGh-Dm#j^T zhM4J;*&{AU%bh*vC?gjKc!X%bd+&Xm&xJJGZ+30CZ_5qn^svn|m-~I8rtbHpQRpW} zb`-v!7=|5ATR;4?8qVrY!m@D3Q)Z!4c~T;yH<@f?IeUACZsOxNdC~WkE>eCsN5Y@g z01CzP>s`c`86EDs8mZ{lze?mr%&Y|1_tNU}7&#pnQSI$*+$yj2d>*%N+ee_<-!EwZ z5p&DMh=_+PcxqE1ZKm_LzV^LHbwydGK1Rw@SqsYB`tR&yz*;9 z7!^nq^WjR@geGHy-y_ONtf`a2NU0VxlUSiAC_p3p>aHi4O2_WejF>vBWlcmqpj6~6_1M(?$LXEHat)~@_Q3fo>~wX2 z&;5D_42E;N;tr^ks+#24ieatUD1`zTE8E5Re2<%EByI7*!^GE(TzIkbgS35nR`GO+ z?Lf#RxVV|OA2d-A;PSa@otdhBFJ|SDm7hd}SguE`;chPn!TQZ7?QQwUHc7(i6MyNC zfFv>cM_oO3LE=-iJrkKEw1aP9VpQEQ@}{Z%;|tTymGla4vI-yz5ybYCXkUN1PT zKe4Fnl4!|Yo*710z0fvYQs)uT=C{!)uYw;@@a4DS?`Fkc9oilBrYue|xR0ISi_O~% z6P`?)*Xtc!`d3=ldSp8mRxS?_kI?2fHh=ZS1wxmK1hfbH5?>Z(A5%YB5HCfxi*!^D zk-pFMgVe`-5S=XL$MswD@#^mHu5cE}2CbQ+FFdVwK5RQ8g^|2qygcMmQ{R1asU1)s zC)FYc?gTTsg6xYFUu7u8w#U1xob7uK<7lfcNk^&xe|!~1!fSj+^HJ$$BcAWQ-)6pe zb8vh#=CIKqyVTrv_dq}(u+-Lmxo~DSQ}wm+!n!ye#zkcmAFU*<84J#{`tlj$4Ye^ZMq?Q$uxs)gGXobzr zj*JR3cDPS9h9L&5(7stF$9ymqytN06_w-G^%2=jK6bc2;uPulBinwMhF%BT$ zQ%TAc4P?Bb=XBu{Sh&}+$mQnEK;`3nyacE{&A!^7)u{+x%|HA?Yu|jeKL_7&Z;c<* z&ac6?-W6`grV97`k(b(94Bjub%`9ICHstOzxhb4C#ln_WBe@^ppN>u46Q+0~!JB3MjPqQB#Abu3u& zeOUHGgqK&oS_S-rdTU$zeh3B7KmZU+;hzUmwp|F8drkk|VevjZZ}8T7SN+tKFa`I| z^sg{WI&9VZk<86*S#)izqtgCwD{pVNME$+$6q}ZYcTcCyi@7t*&ky|}Jeo!pS#SnP z982zaHN&57Z;j#p#BqHzAHenDu=7zY57WKFpX+=Abd8A1BLcOYFDuJigbb7I7z{ab!B2=omvia6Y&{&?o9g;Enu|EFLRC7A~D5n^{qD* z&o_Rv5mZ;>xuG%U|maLAFZf%;2YmaRI zmNN0WZgI*XroM^Jd{*~VN0kr_iAi!bya=|A3B5;$56@N`^OJxlB{!tN)sHIc)5i17 zJ0fLZ*Ou;d_??(Av!0hA8B2)9hkw!Ot7Z8#uADirf5-B9rG@3Ftg@4=#!&V3_l06~ zv4i)r@FN@spmJbEz)(H=dkvHEF{*W96@Frp+bK_%6uLwKwr7Dl`u%0_%hB_^!B^*A zd&}ug$)iNlxjyzZ1~liwzzy11kqB%SRDn-HX{zE*#o12B^_bY9*AI7-1!Kkdl6V|% z*x@Npu~zyL92neORxUr5ekZ723Hh8ma3>f%krYG{hG>zBXazwth}1Ci zcHyJkj(H9Kei3LrkqMFTw%|WYsW005ki-iwJGpW>dsZ&zLrFCV*~vVfNu~a^YC~8t zW>!UltYB|RigwUM?vnW^2P(z+D`6E6b@lC$$S4Sfhb}S}Z_S+XkKp_@E~&ZpAVOK| z6Pxze#Ue#g`{k^H#xYhjj~XMfS*5DN%CEi+Z>xiD>)KCo6m8=TLwf5l%gnt-8i6!^9boJS5EC z@n(8If6BnUwdk?!D4Dkj)_8p0tkBlu=N$a}JowuGI`q8wo6Zn`luL1#&jbf5Nai3} zMk}!72RK*G<15=02!zzoiZH-#)-sn~5i?OqI?Kzs+_bOvi17G;r2`9E?kJ7dR4!ER zfN^M@9)VW1MZrMtJvr}jTu<0K%5Np^0TJq{BbV%ot?5OK-7G8ys0eqNu6L;gxWNd^ zn)Ic9w=H*wscm>3hX^uDH?_qqr);LXGNmv8(vm%S#WB=mM|6~mmzv4Mq_K7_9*c@bu>Goyb-2E>kEwD-{wXz9*4{kcmL4o3cV!d9E~eF-jym_-DZIRMQk6!@`|GM?=Gpdfxk8a>pZ;Pl5FVfXZ`QQ~1A z2^vx(Myk9WwsN#D=Da8Oq@Crbtfn)`qliT*q@J~+iRTFqR>O?1krr=d4q+F3H?t^< zbH9P!CGn9C@KOgaV-NSuJ5BYG0g|h&Hl;kf*X8uY&m_*t*J-H zR012by$VN(^SK7-!GhSre94K{-KPln$9>#_NA%vI@Lh!@Zr3voeU@#$mZLf<9!1yH zHOi_l5@=2|u6Ii*UY&22V8M+X{tVt%br`YeHLpfv@PgMoo)-@RrsActx+$lkB3med zx?&D}$~TjfPy(Bi_Auhlo^Xf6J0h(E!~l5B0B8&0%+^MGz zB&R;vvk=w{mTC@I95}~xWR5C_=o_I0c$51`T=V_=n!aj!zuQhB0L|y=(~`1x;I7o z8mZXY^GlCiZ@FG>n_zdyf9`15)4MHEwA`zfHyDBSJ&g(<}7%pn=)o<9T?sU`MIe5xlWg#vOjn381xX#RVa}Ja`>DJYNJ2_jm zr2PWyWr|7n4NiAg0y&_6ntYpGukK483%Rk+&TIwC$`Z21EaouTz=v`N^L2iA05R-E z-Dep)O@2N%=10GVJ@Y`&```~ulc(|a8uQLMTkv`L`(0gGgLiSd%gQ@O-nz}Er+{2i z-YU!;d1*Q=PnYZH4wpV|=IR^yRs8EZ9pB<5kJCVAJfY9VyV=7U^6<3NL&cIJDko(T z7k4GaJL-~xS{+)N6?~C5%glpp_nZ!0J&WzTIBe#M088gzz=Uw>5me*u6NBOJdFDG= zk$&Qv)I`Ej?wdS1w|imw7oGIKK*c3B2{f@ohEZs_OCN3Wv)6$?{pVREq8j}A7}ZDj zff6EHzOb@~RtMl|BBccGDJRR3KhsIMdq`iu+o}z>`BAbK`0(r=3Jvh@eCMlnP#ErE znzoGFRbnPs;-jn8kj|!J^YREM^7qfj7AE0V;*W?_{Gx4#U^yi|#9=cH=HBZ(n~DxXEM`>yp&E5 zIs9`#nKkbx-|ms0;tLP94g(fDgiEfpo!S^LQPw}k&B^u{*P!L^#;9gHADHj(dLG7v z)qEdGT2uc1p6b;Z<-+Y}a6N1XpEEJjpw3n9uyZ*p3K*m*`E-T z)48xsCl0FKQ~orLK|Xw-%Ko9eiYPNe`02{;#S&A!LB$Z))N@LD#tvPPry3;gSV=pm zfDpFiW!}w|g31ZN8Tfj&^q#a_`-#3Iv9Hb7H{ZVuEPC8$XY!j;k(rQc(Dr^d+kcENC%Gnr~3sPvOjH)Pq>X}&i@Wzy>=v97o5L~{6SbL8Z*ege_ zsueYo8?Gj5C~7kD#bx4))vr$tst8tW?gRwa83A3nx{gk(7@y zlQTNaNZucyS5D=P)I|+dXTmb-5tL9c(j7MtUFNu4HtweT@pc^fEZx22GGbgs<~Y*j z&)XQv2ZKEFzZ0v@ZJRzo{97FTlN{Y8DD&O|C?i0@pDt>V@RO6XoPGJOX;{0K&I28U zm(RzU*qN$AkJ+uxZ;GQDSCB51f2iEOv`sc^UbJuKt=a^Og&3KTu#vI7qLgK%eWG$m z@gE=S&o0RGfI~kFgxwv*1)BJhd%7zI`9JGeVm@Ggt={9rVO|Y<#X>H#MWof)k#WVO zt4T()KLX#`_ZuIj{y*a0F}$uW+yZUT7!4cSXlypxX>41KoyN9pH@0m%X>2ErZQq^t z>pAy1&;5UYCVS1f=A5tJG1gkxQR$kseS+ww7pb95KJw;bj2b55GX)c2eWuHT26;8I z5o#3DGr}q)P=t5AmyN;oZqTx7t5A8-3a@Y&gjapbYspuXFbS~=oiu!vC|1!uhOy0e zw&)J}gA6r=C11*TunRLybNyosPU7YbNN8{N^@qheq9<^{c;MJ8_x{YkYrXoM8pEY5Br4=cc1pea_}DBf_T@uJ;Uzf-mDV0 zYG|jH{SmVS36WS1lmNJ z8ok=Ht(LTdm~~|e5g7AI6tifa4qp4NPf2)Aw-ql=2kR*8Z{0dg>0?#D9A$8X6;X-O z6u4wE<=OD!U}%yb{H(eUFUD@+8LTEK8*j|7M9YGm>qz{go6krly&hXbm^8EcYiHVv zyr)i;6=h#3<~>v?p>4$#uD-tl#=RXk1hV^v!R9^Yd+$uWi3H+pPXN5uy{sfWA)TbT z#wQK_a~|3&-%pgiV&**NGKA-rs=wB;Ws@Ax?-FB<4Ucw-m-)q91NOu{tnBR_E+zmd z*6DbrtcP!{6j?WAxI|VN@i+cH2PUO2aJ0vS^`4p!cjQSN&SnuOAm52xl3nb}w`ThU zRpng~)7Gy^%W)U@kCub66g8HweIMq|40af9d;(QVO6K=!$w0N7!Ku(d zHa|#HsQ)a_h}uRcq^4a>E&fd)q2j-iM;|LTG%_M*kqDDVtGy+zqB0W%1)h)rGXk9r zCl`Xiafo8n5dO$ZPHdL0)eZKlZbosv@1Ur8<5#B) zdypfFsV3hhF`regv2ZWtginZC&bjdmLe>1YhPE0;u=Rz29~e(IzuqJsC@=hRuHk4n z(9UJLfv=o4jMnRq!6DfDHTNZNCx%#_FucFS=Wm^kQ1StobVPa(@bQwel|P-ZZrbpD^Jz8tga4ue#l9{TR5* zzasOHQTe)IiV$vIIw((yB*|N^Z_y15eh*W-Q!FJxJ$?D<0gVs%2@fX6tVm|^d!H(> zzJw+rH7 zNjSL4kp63z%&w$1541S-DK+*M;)I{kt08b`v$=w%Tp{<0`2sKxO{h)BNA6rvDVjgT zNE!Me8ENy*0-LlAhqGF-iD?D(&FpaCf<<^$PoQ?ckzXq3NM}ms1&OM4dpFA2!cGSm zu%M*H1e8SEObG}_#tChax{V)`m=WYb?M4SFkP>Oq{-lr_8SEA@2c!NXP*t_}gQRqj zQFHg&@Mihx_KV1LdtE&ZXinFv7#iFH1z^%TUH){F_K;#U%!xp?-t#E9?`EvHhN{j7;4F;vZSd5Y28+rQX$IO*-Dya~d+)s&b zo1MyZg2%d+jKf!f@mO-QoQ-aZ2P$ z?gV?OvC(qHv8{o}J|*!C-r4ThV&tP0ZFh*zRs+P89I&zsMa5c&@(Wk6iGo#U=d`M~ zJpRg`ry8@%uD6NZ?ptr6;#@trItg zOszZD?(NMZVkUx4R)yIe%&FIwy|JJuo?%}vck*23#A(|MkM ze86F3no>}rDHC-jdcKFk=Y@rg>`v6zj;ffA)lQg)Dd_GKPOPULJ>o*;!(AfIu?V)U zGCY2^@O*aO`ta!XQe_XtQ>HH+F1{CYGdg0XB*T8E68;R}P<=jjTD(olYzH+tqAzv; zIP;p!IzolOB-+8!)ra4BoWPRCU^t>%07Av2;!KdnN*g6kerZy*f)@ay!_v$b^Y;ZG zkni#vjp=FUJTKbuZ#_s2jS3$XZqqa6Ys0JWF=`JqC`4Z8>p^;N3+M0BqGjuZW@z)K zR!(c`OjuU45@4 zSIjLvCQH#AZ?QjH9IU*=+_^glcvFX?F_*t4)&lY0+>E!Njugueg-xcq5Jxy#R zC)~07wpfw&y;d({xW4Ye*w_TpYWyjIs(QuMVRjIGma?kb*#TbBQjF z$fPfDRjKr4zf0(%PMa&F(scJ&(yYmK-lMx)M95n*2+GIw1n?o=tm8$y!>4xvD!eXp zA;v-XsDZuyR(^~CFA}Qm;g_@gZ^2!>~t}|!QM}^_1I(Yfg`zEax(Ce^ig zi<=ltP>+Y!{}my0y&`7ru$!--T6$MjXxWf(-W$&QPk|W^<>Y_~vdMflSOL2uK021; zAe|ItQgog(?J=s(ezCWQiWlp#5jAtht?)P-+~O{)Ho<;>KkT-fD!7f%D1`*cIr%vP z)#R>RG=*clV0fYPE~BV$M3%W%aVYxt`_7NHkbZqRq#5~ z;!1&{qT9t}`kxZWXL^c<+6cp@TY8UdkQA^6BgTicbVJG!j^ zu}ar8)!6vmQZ3(${!G60>C%``+puAnEe#TIGH@bPqK< zb?opnoE<5{9vtc5bN;xMhbj*v^@-Q6^ip9YlI54j6l5-VGF?w8H6-=(AQaM9{-wxd zNwbc=yYd%MIvKxBE*b47=#P;aPq<5dKFD((zim(EgXcW>vbSdtivmH7OJ9Chc<$F_ zKDx*I(r!ws0#u;t$f=V(KTGF)I;Q^C#q2xhL2YuvrfzZa{hL`w6KSoj)m$A<$zb3v zmSWdB>;V6L^)Z)YxCUJb48^2VC-Z}jB9C-#yuLhM{O;DXls$z|>LKIK3!h=5OESPA zZfn+={mY4pxB8CUS54EHI`{RoB~r|sNBe46%G;1_iHY&6Dc%LWAk(XJ zG|_c)C)lpq|51xorP^Afs0_LUf75(%u}i4VT22Yw@WOG50xOZybl!t~H|$c)f-e9- zCYbqKAqAg^;k7eLsP?d}R-@o@Anie=<6d1cQ{7WDPwcZa>dtS1YbhL!K}vFemT3xf zB|e63x~M!B9yRJm-BQ`2m<)qoD=|z{x&Za*eL?ka-(?wk)-v&YPw6CS=f?qac0vp3 z28(;f)veC$nz3?Eh{PrM?vFI;n1}1~?EyT6OWG=NVISkF99&3o9oJCZ{<(Bht6qz;<#!I!$p ziSpAOawl}~ybd`>i5YH&?VTUbeBPXHe$lTZpJ8NrbR78ZY3>u8{GeZVkrjH+x8@6F z!||T1#eR6eDKwKepv>ll#?^F(={v~JP&Ax!LH()Fs#2TiRTRwITSC&Lt@`bTT0SG^ z#W%Cu?8(iqFFZ87d#dcTciyN$RD>i?OM(U+>wg!o*fB zI?AVz^eLfLL}?QTD*bjD1LvSmSN^u-)R5z$;>r})C1)Y<#LZMCSF)kdgE#5n;=#nF zQf3`Bp0xdW=_O)21dNa!4d_aE!s;F3WrH6TBR)`j7O&9mLjS4Yl0E>pA+d3QbZ^oP zmm7yHS!o3SgZ$xo&~8N9*NcIp`ZZBtB$15NKaH;J%N`Sm1%XV(5d}NTiN>LfpBZSv z;Ww{%zS*nxtJ35@GkLuSwsRHml*UWMzyZ*K&nBeaYCEOvHKE;B(MkwWkbU5I(O#8q zbYqV%NU2+gieVr4GK%!r;tG1e|E}fF44wb4KO8_ypJfZWOn~*~|K}A744|ziB_XRa z83^xt`7>UI(ffHtLueI_pQP<4s3q~^oQ0oOhpMgNxZ!_S04L)|BLe2#RQ62HRDVYS z|L5hyU+YOg^a4f@G3niaR_4zI-c8CX@F7nap~_vcC3H<7X)+ee_cy;lYtHS{j?h{@*sK zTSp;CP|)W9QT`8{cla`;xh`pQg+;#gyWF#~V6H^8JmRy|6)y@DcvR7enUQEEZ@uF3 z{d@{9he}0SSFE$9!==wfN)4&xBj8kg-qL%hl%7;?=1vfb{`@8NZG>7h(vkdP<{Fa; zv`gh^l42SAS)XQDm`Kg=vUhBRd&Y5p=`WEi%-)HNr6BIj{pu?K=?(RVRzL&w&F|1s z%>U_dWvnja#Rh=$p{BesPuHlmbW^n9*D8Db;8KMS*a1e-^nPrV<1y zoZ@e#OQCkNv7g5g)VA+x`~KS--yk7sFZ zF$dnBlMyeLu>=8OILF4;`>s)q_}*A7rdjKSHVe1Q6G^w@-A{_UjPKg!HHQT3JM+DXDb7KN&oQ2xcOPDMsv1fA1RP!TOAhrMKFNGOsTR>z#tb2>jN=Z?ne1oMb+r-HqTg<=$QF`TOsa>J} zcemni8^;MJDsQKNLaQ^sd`&JM>zHV^XOj_h)k|=2qL5POpQ1ytG1idvxjR+y z9fIl$b5}me=_g>z+c58H?HxiyQ06HL0)*`NbVo<56lUlfwcmHwNsOYiJ3&mm4g2pT z6{JBOiE=7WZya^fVk0Nk-LONI%Y-T}h!yC!d<1i2$V1||iNcz%-?wV6k(PU92u!+X zjrIu++!lx9UknR7ZG3j(nOl+Izaqq^h*MXoNL z1?u0gQ+Pk#?zkoU|CdJZ&z6UmgF)yHq$pz0dob#C3smmiY3rEkE63*#*%jr2|J2{o zG1FJv+Mi~sk>QUR2|ujtXhjB5ypT|ORk*+&od$N7|GKV5@F^4&8`JIeg{v_!d*cO+ zD{W`_*_kT4?>fuBuuscUvbPtIcH9(P-~AB?^5aZ{p$Q7@eoig)*PcPL=jS2(NZS$ghuv=>5npj0dbc>9QN?lZxN%T<;m|`u5OY#s6a{|^p+5wk()ctyJl9i< zHXfbEn(K$I0y>@5=oiuTdg$?61nZj0fYeynm9+GWuCRIfmU$)>w;P4LBtFELKS6{9 z{15}{r(mMxV4DkqsA70XhSV~f zZX92TeA4J*rSTk<7hw6%&GUB)szKoNyF4#O%1SLjY=aTrP-3bonQ7?G@1{H9$ z^3B$=a9ZNf`>}ni;`SgEY++6IZo65-pR(}hDrht#ZnWvTPI6ip^0Na?O`ADcyg>>0 z*gkVMHy67}(R*K#ov-X?-)|4;q2+!+5DsOBg=%X%-Y1 zr6+w-I|cuR;Bx}dq6=t)J`{cr=fMYj=6WRprL%_a_9leY($Tu}7RG^_ zspKNJ>hC_|{pwpi_$?kSd5+g6a3m0x&Mz4RlK*g?}F_rTP=;LyJZ8iTpybMNf z3AI9KQt9h4exWrOA&D%g96Tbynx*FE&V)Gb2>8RC8zwLV3~g!8ON@4*1+He zJppW%a3)>n%9pWh0AF*>^z?`)!3r@7g$U4o5*SxpZDA~)h%BN!PL?ouYCWse+<+ho zFe_+YwaK9S>(PyY*0STqaQP^CIU+d64Pr1vTnY>xwnl24=AuLTd)enB(~W@72Z;sc z@p(#NsgPZN7a$Do1_|e%olLssWC$}Fc0?3PGLcwwv$mdL!ruh?62d zjTJp+LS_&GSE(4vFTXCePyYkv^>r7pBY*FRPL>4^E`o3nDy;1hnVV}Mfz2m}9nh;^ zr~?#v(FS(sD$`$4%@TgX$I1^XN8=a6(;c!)eZKVb>+Bv!s23O#e6>-#KBMg^gvIBf z`6~(;7AT3d2iDuSnva(7?#2CnPU!I&UeKyPS**5v1qY;l%JNKz@!@B5#=eKCSf(BH zzhNpX1xYkGJl4Z`CxJFECXmP+GX(=!^y`f%`9_>fS{#D2&)kVf;-;I51Qm?DA77ys zxDdq&i2lI#nIbj4?PJNT*(JAn8R_}-XZ)Y*`zC5!ym%@PK$KDX;qv#|e>Xu!8Wfch znF&`%6?s8_*pX$|jvyk9M4+@YUqu~H)J$dh`V=jgceT6ZaH#Ne@j~XWPsyTzhRe9; z*20^Kjps9jj$d{m0(CgV_ytBGTzE%r8bmio@CgMkB^TKUB543kb53Z)KovRq8CKg!1$!KcM{j0SZhyLZ2_8 z_C~%EibjMMK&g-KBo4s;$gn)OoX4uaY16T^DmaG2n2UXrRvEmYoLgnC_s0%OP-RxH8$!|{;o9(Liq|($vE4$AwpYqaA;wV z&3c%fLU|@u`b=rHwSxaw3UQR)y@kd?>u?mn#AmtAaym4QyC3~`C2rE6gnK~$Y%x4-UcSih0=Lh36BRX+AiIp|>kkE;$)dOd1^^`f9h(OFf9NgS-2oI-|W^;WFsg z!GCE;We%-6QRbf{=-pL1qnzhjpF!-r4V>*TFq_P0x3=uP0_8^m2};zh-H_c=^|s=1 zZMN~nl^X@w|FLYjYhk7oN92586ByJdlP}PK2d-cTioHkYqpN{@jDu6c5j<6pnUWbO zb=D^9;{Oz9@ZCtxkM?q88(&l`qnlQJCy|_wPI@yjFpm57rghR(##8Rn>1Rankh|J8 z(SNdd1c#|~IW_wQ-wZ-7equeiUPOS%K+V?|%>tq3%h#6w<HxXO!Eej9=MIFNrY5jlkZ>f4NH1f(l=yWceTE*8!c4>`X!Yz0ojh_94W$%}EC^ zQ&Uyw@d;0_Kiec3Q8u)Mo5uU2c3Jl&zS7{KCRqm3Ks9NUxr*;+UQKdjBOv= z5q}5RD6Xb83n!jZ07TGOQ)qsBI+ce`UKlXC=Xq_Kzn>Pr4XD6Hjm?Gfpy*hPuw4Qz z1hrR)Jk?LK%$<;(pRN{?ZRr4+zjD87wtx!g1E^66*D% z78c)zwn5bq9hpz2!CqS1bdJi>r3b|_kp5ecS3T1Gc8@bw2tGr5Seiy9sOa*k!YtOr zz=-F(%yZBpH0dX5ui`m(kA=mcLXQrQ`!A~HA=0oBtx0M z*e3_{MLsU5g5*jGGM%ipvouTLQ8$<$>>rwS%KF>Gb;VnQLrP7C@ z=?!~TWZ>rWv^@%{?`5rk`#xkYmR4i;IAu1b00tt=#{h>~mo1h$7kh5@KLYvqepol5 z3B~m;@ys}RpcFI|mAPA{$;vfGlC_wu;1Rs=T_KsK4@eu|{sh4cEbk89bnW6Tz+#ac zh&>b8*W^9`*|`unuXa3CYt+E?_84?q`H zNCC-@b7#5Nu;1n(Wks8p~%H&um8N(rJ1`=RQ6l~OJX46o4bNV+IfeMg~#5f*qE>kcr1OD ztNLHl%1Kcf@U7mO%5(zC07%P(xpRjKNC36^Y#ose2g#?7bZ)=6Q8@bx%b=?ERhHrC z#L&psRq)St;u8B#XYD&1`%tAE?%_s z|HpkMqZn^2e=Mm0FIl1`2=5<+7>AM;jd5;kO+RT zz;fO)xGRH7iNF#KQmwEUp`~Sgv}IWK|%VBa*Jn%Lm{=nvnw14(q#Jkpqfb*_YL6=D5@w3V8-wz0FZ(AH)xFxQsJgmI!*!$b& z^#N*RC)SWy9V9oNhK!z{9$WV3OKC5wnGW2(xP80WGO-AqpMMKUoGa~IbmR*ROh-Xj zYYn+$tq?xzAKS#o_SZ4>94g$SuUW6DJ}JD%V1C$eV79mYs_*(eOuY*3yP)NED8odF z%vqbqw|YXx{<;Id6qgif0Z;B~#LUx$pmO-s4gPP#nJo_(b(i94h%jEs-nvD@_=LFpy~(i>ij>@M7HzH~XbCY9x}K+KNZSliaiRhb#HEG_nN7j=A!JJH zQwk2@`m03ic->h>b=m~&+%C}RE4a*Ye2dPGlU66ZKzvoS@7Gl-;-;86GVkG>Mtz+( zs>p-|chFb(Rix;Yh|Dkd+nu@X)(i{+2Br{{j$4ZEzkly-FPuQREwsS9#9V&2l8HO6 zv2s^l85-?(b(PBD8oS7x?8AF5RND}8Mivc*?oJ+C@5-yHC|2hI^VgG({~8?TM{%si ziJQygEq{e4_aN`f>ok8?{#8qgOyXokarP+5j0zo0w8_q9fX>={0m6MIj?eKxcRgbw zQ&7q%MF9@?UKatm$MWZHP;xbGHuKW$q*KyzOJ`R3$9hjj=r-*)bg8jsLON>SIIhnM z?jb^hyW7@glZsTHMCCZ~?jcvlwFYU=W<_cG6Uo#p<(nuc#GS+VCoSZ&9zvYWob(KI zkG5sE{22UsMCWb;rz*_$aQ4@z(y-c^PsHtuEx7BE?s#>k*c&4+Tso!(ekfM%G?`Hg zqZuI|bIp;4Gu7&@t)06Psl>B;7 zv-_Whr|9yjV&oMRbpMjEi@rn~>l4*xV7obDANyO(N${saLzN`b5;y-$kQze{q(o)6 zI_2>Fk|D+JMtz*Y>H7_{w$|~;_0kYRvvrjZC!Gh!hJ+p`I5&uaNrqeF;ZBLYT&RC* zG%ULiu-q3b3Vn@68EjN%1)lAtX8TMPz;@eP{GD@4Zxq*F;{uV=3-nxf{3Os~54O$&{e z(x_p4eeBPL)V7SLLc}{`c<1N1rC5Q%d9=+PkLlcztuAm}pF6yIe;rMMiYgXylJ4`S zs;W+hiNC&G(o^_NEspoauZh>MxF)gUDePSU?y?e^(xAD?fM9?d$@({!(UJ#7GMOsy zR$L7QU?zf$?@G>*#SP>B#o)|=@7inzhsFM;(s}@*S59S69)vA-7SWh1@e!SYNuTMG z(jcJ4u`lLYD|y)w!;jIJ#o`LNImgBT%rkM%`C`qsK|PQ!ISE~r^ftj+igD-T!dmdRaP)#U<^y@8dWobl>{X(y zf-h+_Z^H92Gl*u2jbn_Y0x?iU#YpwK<6?_XJcSF30$iN9dp%y&))SNvqTnC|_m3ZS zRUZqf&}3NbV|Z#N8}9yOOVaGJzrYSt>A^H8v=@-MZE)QiLs6Vud2h3yWg?l5y|*d_y68kBf{f`ReO;AI+B)bk7cF zzT$%_=6JD~QKmu}Cx@CW9#r{=G@P%rBVMRIt@KGrK!3?G)^N*W*lJy0F3_@YZ@+kW z`@aI6-g}sz|2ZwC`Q}p$qn(avR^YBLr=B&>cMkh(xRkm(xc1{|2nW-HIQDdWY0bU_ zY{KGd5CiCINp1hg_!EOwec|O=KfcV2wef`meD5mW(`ri%7j&GkBZ5#o%l7&sINpNNTSGVH1#&b9b7v_6dT$U4TBzAeri>=(;{ z=eTT;1M?mMqa=MP3^!8TD@7XjFB~m~982LD{;@|1GS1wGOBAnP49IJxS{;t9oE$NN zfS*xO+!l?9?C)3QiHc9A+?zAHFPWV`1PBX1p#ZDkSJz%*VDCFC2HEMRA`=Pcv#;ix zD}co}_nLWTZn7_Ky<-6Qz`(}QChf@7;6qI_6m?orNqdj^<=*sgPP8(5qz>w9rC`MGy&K-glKZ==M5gaEbp7K_$U*FhHenv54_Aex&II$M6?#Z!P z1eT#orTZ;a`+aWPeOIN#`Xs}h-;;M9k~F+FAC(+T^+m+3ik^o?hhhzXhAW6otlGhp zWSoRBMMDn`DpB|gC4ZV6Ftx>?MU?<+!!gXb980-uCnb%mBw7;LzQ0(Jgd@yLsASeF zQUUFTzTD4y(lOQry#6TPzAt`YzaDwonP~wtJ;2;}?l-K=;uOF{bv$wl_C@n>Xyrsy zj>k+{9IRcqB&Bi3!JYyWa0%Mm*bc4neB&R^&|oB~5N`LW&JsKYf3AOndTGu#{-xil z@Ct=5AmGPXoF9QF_4-Pfg6M{qfCoc<;LMSdz!yC)O~62gqsavqKTo+XG*fdM`zV+2%@hK`pb~+-A-#Qelz1;1<$fb}}VwV7`A{0^e@z?WoiOf5^!i(;dq!}U?4 zsiW#OUaaORo5sXdHgJB@Y6;MYZrXYO415tK-0L`)N5^!2U|gT7WaWq}r+sqKzcabM z`5}xbhm&Wt*B#4ed{_ZYc=K-Ya3u$=WTI8jGHt+2NHoWzsLK zGDbr=2t0%K#w*Zxxu}PX?v%FQyfJ@xbco>cPV&CP3+=Am#J~nwRt(C$&09xO%Z1}{ z@&m|{6J>jDy!>T#eXMM=lB9PA zYI71FQAC~$evhJXY^aS^?~EJHcBx0Gl^O4(8@L@wY}{9{{s3g45moH5{q1}K=^_67 zoEBZkawSIaD|z@U78=LaA>G9lZEotElIVurvNcfauLO(VZv1L%8@%u+_55N)Rrbw^ zA%6+1NQQqBCtUkpdlNm!o~VZcdv(-3E>pG26lp;+j_5|Bc}LsKB8brJL+r z-H!xxp7z*1@eV#mfr@V(yb%7nzlB$6XdFtAs^0tLm#Gd;vMuKtqg@1M;uzJ8mCVs^MsgZnk~{1CF@fiM-_Wz%L- zMT*xupyATr`c@+<)wf)Hk2nLBpD#v!_bRs(Nl(`p>N7TEGWs0*&#_bnq@)fDFbxZH z1|U0El}w-yHZ*fQ*SZ-AH{!rdS%<%dwUS(T>e7ALAiYlh6;jjPzvyv&FJe2{3Z0Od z3|ak4hKPE_8FMY|LPV0(U6k}-QKLDvVrt@q^ z8bF~SRCtTBS*7Cf$eBhfF&Q;3d|mN^@>JMQTkn4J=m6<~wG-MuXT&(uLJ{_Dq#IN2 z6Qytn5|M^sx+!i1x#c9&X91nX%tdAz#a3B^H4yV*ZKg4LG0*r(eMieeL>z9>}ah;%|t zLkJDq%tEadK0)opzcEQmUtJqm)dsm`rP*8OZl+^&@&( z#LP@_^+n6Udg3qm@gceBJzB9h50b7xR2krU1|JD*pL>gm>I@k6Wt>dBt-@W%h2Z;J zTODtC?+r2TS$DErYg~HMAj2fmiAcm8sMwCWwbL^y7f7$mYK45IUE0W0UXRV*6gC?1 zXWG;?i@<(-1oVv^7ue(c`z;nUp8C1C%<}) zZ0WJ?Vbo^S(T}r^%<2^o!->@q_XrYBu0-{kE#VC<%*sY1CB3(0 zXgdUIn6@uh?I#y=?Gu)sx*Pa5Yc3c84>}<@(hz@?K z-tQkgqzGV=9J)AQK_ESt?ZtfVqoj;U$pV)2jAd>u4sO)k%hw_n#QvmBjM{zypC`Lm zJJ=+Qk{8*hRPuZ3Bs~q$cugrmF42VRBWNV}L!thc!q}QF6lw{Jm>1PKVxWbMgiJai za(fmEY!>pNr%EiTr%OFu(n_N7g5i}!$9(xo&i-}BV98s;^9F|2O|1B~_KJuSH2Eb} zKH~@53h#d?nH}g>!RULtjy&`;VNR;+_QMaDBM1lPZZ>Iq7cv@n(?kp^&9>8N(eJSp z_}PO<=%R;w=kf0T1qPjs_2q7qSHq7OVlQm>dYYa@!!nJsgITAh-7eYX#fxRBW< zbYp?WpkbBGL!uF}QiF&MpP7M{M$CX7P)l2yJCPp5o*<3T4?kL(xfEr~D1Whh zT`yhcUS^!ciwOIjJMeo!J5=V}9hE7*QP>s}OOB_b+wA~Z(l5?e6DajpZusJrKeT}j z5OBCdj4uAFr$Z1H{Hi3khsNkgeDr@BCy^E8W!*}ng+|(qA4&c2Mk$E{n-dtXH2x4D z>s6UTX~`j+^xjtsK1}nSAKK=EMJ?*C{B!gSh368GHY_ z6aV)D*!K(mf1d&8uuW~nD1!tjazo*bMaT8-^mC}iw4yTj@sxu&#c9JiDI-%VgtsaX zcdaxzBMV+r!RA}bO3#_l#{blW-Wxz7lOqBzk--6Zu}OF-W(O;-QD5cUtCZn!WB+Km zR_6>BAX(gaX2jz=B{;_C4ysrJdC`>m(rv8KxFjbvIyD8#YE-4hHq`p;R;uzsu9d>r z-rcV>5^^F*1?N!}q52>X2bK8;e>nwY4a`8_QO|``1EIs?rvtWHtQBeM{vO|dy~1;5 zXt<=?;c4@Bi6yC^klqA~>?-79Ee*lCzBe3?|VAC!)QtLjU}vzu>(p{ z;41LSQdv#d|DzHAS6JZh>>+T6)7bxT$p7VJ{s(653IXw^UGS6^-T&xC|NZ}8bW7qF z1~Mk3g=O}5|8*w*kO=;jKJQT+xQqw+f6M5cCW^{Tg?-yD5VPRD9%jkyA4pUi|ML7;p06O_@a{+z|JeI6QkZ~^4Uv38lj>%vgw2YOm#}EY_DkW?``mSB zbQ3_t$=j5F<2L!~-gJezG~<;_D9O=b@%$Fljn$aB{FtvaW9)w^p&OLQjW(}v=n}Yr zblRRsn0@W3o{u^Rzr!%X>;e(F`;e@sXQMll#g*yxhTrHf;v1q<60*HF!teNm&vavL z_Ipjj-FS<5f!qPto2GegdEfyTQ-IK|*IQfv2oPtj{MA6m8HO7W$K^<0;$a4NumUe4 zB4W&Uxk$z7nt}cw;skO+{Hs#Zm7RmVllPfZ>tGVSO+;DK3V zYz~A=m?y#zhvS9hdi@}KE12Ys_wLKml%w63W?rUJPMr;o1SSxmp7T26n9k1$YCPk* zJ@?uA`2&c)Y$7n$)G!3h`|Y{`YD>6)K=%C0#^fJ;zzgLMyvVUW4$+Ie%W4Osx7kt2 zGLpn;@xW|X=>N9>FX%Wr?~I;-4ddMIiiv%)jHI=826vWeM>{u8mk2EFcHhmlVt8)` z!Kduy6+waiG55F>d0#t2}=maaKV^BpFZh=5tfG z`$}yi90HtIbQ`=m_X^djn^WgMt)t=saR+m+Jzc{FSO$(1&5)FY9Zg=)J6H$!rUDEz z@glXwp@Swg*Vk5=MU-V^K3J(Cx-_zz>|A}jd8Y&)I&?VK1LsoE1=Ty6kEZr0#>8u~ zMrcP7DH-SZkCFrYIgZ>L%V3iU1fUn{!+?Vj3W&6sh~Fb->R52T|(8Cf0AC>bcFE##| zn*tT+jaschc{@@!vV2r@Z0OMt=Kg|}OkN5YV*MqO@nSAv8ZPdK>U$(5J~A>gjD-@j z-BhT^Mu~SivV@JT{`-k|hmijIacqtA^SnAxIz#Abv$di{?+oH@{BKB@P4}|yT(-C- z!GQ|z^H$H^??!4beggbl`Te$Kr%zFw)_pg@u7#3-?Pzft6wkNh=ICVpXIcQsui$!T z+%|iVH#{Cc1eArzE8?x~!}s6bLFnN${t2WU8xm#+F3SMf!8>TfHD0zsa4{nKANwCd z9u={h>r8boDLe>NkaG?bfDrHDj{)a);AjOCP!d&9B+2%0jO zP(k?X@anZ9Y91g!wlGyslyjJ(msb$Ye3QG`{=vZ%I{gzBJ#j{NERfPO5sSQY^v98@ ziRg@e#+UV@bEL&aL;UlCk9Un?A>~)^FmkKK_@Q-EO!*<>hcJ@LH!}f5HYIi?R8Nbe zMBs*h0Gzo0ZR($3{y9YoL11{K6iiw{{pSS!uWzmm2MWFRB;wrZ|Bn3^3uFS`on8Qa z6XpLM`)`CXHqfsdFXL`r{JZbJvH#q6798{pRZo56e^XG15YQ4Ld3x5Ds+>;qj7d%K zD~M9ewcmIo1Ha~WDx2;8b+Ve89Zf^ z8;1U%yf^Pmw!>BV3?$$_)dct{Jl0MZU^m%(W%>1sWyiOdDh-^I?*{(|7Jffl4rEcO zpaIyIW-mG8ByTAGbqod)<35g-yi zYyoGuIEjBWulq8tX}Czz(D!eD8qgG|e40qes6xPR5OmLuVvJ-Q_%uJ(jX2;K&Mpq4 zc&K<%W|gLF|G?wl2xL*e=o$!(PK|}+^uFYAH;R?vc5_UoLG*YA==8$bK zKDEujaU6KRLm?Ds9~z$?T$k=-(#s-XP*S=ih|nhUpS~2ccyEQ^gAlVbe6%v>@tY|< zHXREff71aHJ(#REiHh!#>Lx7TK6-z@<+&Fq?*gw4de@eHqjQ<}xu3zsF0KAv zmZ_h?MTWkYWy1VL_rVm`7j_+8HK6+*_Kp9zPW+3XfFuc%mk_t-l?p|r537+ns;Z3D$_n$K|nH7m6 zrT?iskiS6=#3-S7=zD%10X2_e#?j$yKvi9AG0py#F0iN7)!ii+KLAaZWdSs{91BOk0pJ5C zz<^?HGT~{wTEW)F9N2DiaEFDNIr_xEt?{z656>s@ass*XymQf0vknC-GEsrP_4rID zJ3pw><}CG>^9YoY68JdYGa|0*T{PWI@LT&c*Q^P=nEREv>h`$sT#2Ez|DhYI6`dWbxWR0@-;iy+~2kiR47z41ANQsO@TX2ecEoFF(|9-+885SvsFtnYA%NzCz}2-4bX8eX$ouq0?7bz8 zsLHRXbjp15^RvD=$^I^L#07T7NJvQdfo_kWM*nhBnRMuD3|5$}yf0gjt<9H!w$j|% z_6UUIBdj=u>tD`IK=evjw(qjYDxp|<&^1;5z|?(%<7rW*(wf;*?}Cs z_P3H;UMA&XGqA`vU%y{R^mSMKQyGevDN+-3KJGaPj4xRYN3Qc5mL6XuaJg;B?NJck zE>3-lKLhW|y1`xV$&JL@)-T#OvD)&$em*-A)VvGXfUar7M)%pZ z-R)z~=NB*(EX2^;|A(!w42o;%+6@*UBoN%)J-E9|a33T<2=49>g1fuBySo!K*x>H2 z1B2f=?>X=JzFYTJbxrLbd!~EOUh=H9o?Z>n*yy`eBqAA7D1lC$FDzUpMDjTvpGhRX zeivmpjr>}>->S)eAa774!lG=~*dQrvg;D3=I6W}0TCbo_qyYaQR$LVIqw6|ixdjU~ zY@~qCZ0q#BBYL2_r@jkS-#JCk#4>WuU}a211p5F5b?-z{*5+kA9;L`XCPkQo-0t26 zs!wIc(DJ+A9?Y`&xIX_kM0xpu`cP6r)!5ABXe^gB6k7*KMw*kAsBwfYpCU2ZY{x>E zHE))6dSFQYj+|F!?6(+%g8)ffD#=M1PRAxB1}xq(xTP+b(0_>J%k`!{` zK^hCt${}*E*)1Vhd4>GKjRe`fOe}_d76TN{`&q*-8;O)Z6^nel%spl~w?UBZB9dNv zQ-C=&oqe!1GdXX@zX=DTlSb&G!{h_;35Ypw#G3R{HBP(QlADMAP>vF=~9-Qgac zF_Xmb{%Xk8#`Qx3$j&#oake9`x+uNW+A{MrTc2dKH?^~h+qGYcHj>NSwaX`?*ob12 zfoO*0|9zQn{W-olCO$qKQmMkIST4fT@seeQY!CLUb`>MI@20xp<1&j7a}cagi=gdnX zyYC8Vj$3urX~N6FhYj<(8hm3IM*Mu9lqTdCNM?FlBzCQ%3L`*ay1$vcrN@%zPtSVf zAJyXG27}FTJdKvx>V8=7!n`Vt+hC)GJ&(hkn+f~NB-+hQqx%VG{+%-@a^!I^WKvEA zrmPH;O8Q9p1M!o`grUsJAhe>DR5^=dm}cBT&=1Zp_4WxXBVn3~I~BOt6X?Y8^2Y_(_IwC<0z z8&!ev?y;((%3B~%H`%TN!B3$ls8ECI-u3_~!*z{8AA4hR^or~|s-)A^pPk85+Z<)- zvZDo!s`~0Dsqz2f0AeUhG4E9$XYMZI)mF%9Q#f;yyMUbw zrLP>p4RDDwjOM?+yxb^MG!8qjdk;V8kam24LCOl=3ztjo|UuYq8~0D*@wh@Jk$ zH=V1pm1hwkDBKrDL%T}s!{;MzBoF(re^f=Mp@_56HagqjHkhW|c`9-QVS=slwy94J zj@M>YWMyVW2*?$Q5_tcfDJe=Dbhpsue!z9`RI1mlf`eVWmO`?DM)^;B13Mw;_!ZZH zEFVIrvIU&Jp9kQxbi2YzZN6%K@nDZn>VRI!CadUx1&pXWaZkWh_Rsi0%&z6`_$*Qk z5=u7o*H}Yt-xXrU)y^%z6nuD)qVPo_()as=b%QWo=Yd(;|CJVFhc;3jG9%W+SpZ5< zQ(LCQz)hJi@9&u#M!bk9n;lqGFMr@{$zqFIV|s>C5L$O#{}>dIis-|Cz?^-7B$o@Q zMdU_DjRqno9iCbRxVAM9)Ck>=P7ps8fBaS2rEe~_<;6%wlEH&CJSl2{@TO8t^L)n5 zZWd@$?FH(I9Rg>IaXvhwPR5<+Eatlq8vioj&bfxCU=Y3YeM>6K+=s~ymU`+<@UAWl zvB`y|V`lrR-W`>S`M&D~=~LDBr|22O~uf$UK+^)$jyO^zh2I0gnf>lwT0tZc?_?U=`w zfq!BxL=;*Zh~n|K<^&?~?ZtlqNB)ya>VZLMNyi<-GDV*dxoK$=45uAZL295G0?bm;9~1*FE}lg3!^CfXnRN(53*wTv#POGuBbgEWlgCB z6SVI#A}tdG!;o`k(5e4~*OV0*o192`V{weJW*kdO5Q9{ze7Hk-yX{jt(%N={ouT`L z>hv4MVzDrwE^52-{o~{_RDSZgfAhsVUA`75?b5KV!Xaloz5caKg4e)6}~1MP~Dx^ zePX$5cV8;w&G>`-7l?^^>dF64yv5Jzk4yxzqa>4eUMsBmrjCb!*tb0Xu~K)H#dVV= zGC4RiK97htBVFv_npituF7mn5ymnT)1zeo(K+G8=;z-}j9<6p%9^-y*I>spPDll4A!ii& zJLGV#Ga7!YaC)yV7Njs$9HJvjJ2Dn4qgR)Pnk2fFj9i-M9tt_NnCPnsEF0B(OTk;vCp({=$6}9=4*RgY&I2(pH=6aKiXPT~S$h0`@&3!u z{hz%Mh9}74l0U~{F+aZdCJF3{OxyBOddHc;8-ZT{)^^^`8R9@+aUM*5JL@T$m9pca z#*ek11|JeX_Az_S+#VZrlTdLWrWa2Q8BBHiPq|q2oy(cBFK?p%H%Ok36ef~5L5pp6 zIONj_kq%D|fp!r>UFmIWUEWf0`v^2Z3No-Fdu>Bgb3#&}RI_aIsb(B`Y z!y*L5YmnrDT6fWDqB2C^I19)%J|6p3N9p%X`d#L6h86w-jqFxgUp=HV8y*mMle29%`{dt? z21o@+(OLt;a)WJB=#!BAb@pbET>tTSlxS{yQ?*U%r6>TB&r|YNbqj|1zWK6oqNN{Wup0&z{m%otVF?=WsBd z+_&$X{xhn!kL~+YKcMLW;YeE0?>*ObPr_Gt%!6~}YnpZONcYS%5kSe#s@-O=cBp{gtJCG+4>Q@z{fGz(2cS)7e3XKd)^uKOQM_Jg?OmYIC#tT zk^9a@KiaFV=hA%XL*&Y1UaGC>;X>;@ugQiN10OWUh)yxKbtLcej+IpgpERe{_aC7y z#s{Mfro*|ck4ZDsQDAYWj9aD%20}acrwZqNqQ-as-C4_u2ymg*iO4V>@1W4Mgk}h%)v?jO8Zje$x1Zx% zg`eD*{>)7AMg_5bMuNWPeRZ;W;1tPl(b^pIP6O6w5~TV*sUDp#I7HCspJAh3TZzgK z7zajk=s*5KRI`AdnroQDc>@|~nr9@>%c#hrIgK3nDQzcE^c_=EkRo$Z6-A%@d58v` z)c71QS#<);Jakp0GX9gQfY>nMaKw;ofi9rLM&dU0**b22_GpNNv@7A`G(!S6WhlZ9 zQBoWfs`jZpA#XMRRxl_T+KyiX)m(l_(Mb#8S%D~cqjaamWs4wVRp3vF2|l~!2I~6P zbo%nED^!G#DTU#!*)7-egpSd^tGClkcr7(4>>#1RAgy=G;)RPMWm>58ck7nyECNN; zR4knb(MJMBX(>iwGVIF67Xq9Zp82IAVF=Qw60dBoOC};Q+t7fntEDy1iw3rf@xe~h zsf<}@?{lBVKUfJSia&J1tfno#BZO8lS6s6WP)Dmgs#O{3O?IfFZx0+fbIg_Kfulo8 z?WL~9X8S?h6+5cH;qqCV;S#=!K!e~Il}MS&TJwOuOW>-I@uz3tryRk`QOi+Q4uArI}H`T;$GFy4;`HRg*yEjIIdf;ipGW+2!t!GxcQ&ez5wOe+;u zx(A3ru+j#@ht1e~j%oRapXOa}z~fdEis>@m`>22C>lsC)k;^9Pmo#VQm_vuZCl$>L zc@a1ObllGwUz+1Hy#7p3SJIsD7#X#frx&T<>M8#(hcjq-q60gIesBAt3)kx+NTtzk;& zv-P+*@(OyuDDg_VV^j*Pbk1k!BeYki;h(;P(NnAxSpvbEK87jRcjacgYh^KbTwTxm zKy@xACCS!Md(+FUg7(W%Jl+f@@&T))zqJ_}u>>A$n^ax>`8WEu!cO6n&2X_Vb9v0` zSljIT$h4e`L&Rk{kTbVevKE|mA9J>E$l?h4B_>>q@9<~XpkIBBp;D!Tt)G1*GqyPy zoV_(Dpa4|Dd(n(jg2M{X8uBFC30%&27|e8oQE=guDhm$c=WD?^f&whyY4|@Ks(kcC z{kgIK>b&q0su>~1M-ViTsH6^_i>*$u_nUR^wt zKpv-B4H)g3l@dzT=Loob(Dz;-Wq%X**#A)y=^Q6mi@A!>m@b&cWQ#4QImA%1CPYiD ziQ(dE{^)%{!Ar{xL?}|d>Ar=xpiFiYgubmo-)$hW^<`hP*YLr&p& z(f=i%5|--q(b{(ln0Rn;en;lxbdXq;ll@r`Eowy4V%iL;*O2^bs)ODnM~Qev!=IlHDFp_8HEHd4qfz@Xq1N5 z2|(8Mf%Nhuf2!xoh?fePFw$f!nT+w|!#b`zQkASzP3~zn=A*CF!aThZwrh2K3GUyttkQ*aYKk>++;<=dnsS&JLR`Xm;~;=!q3D zW{Pb&_6av{?n;i~vK&hYuh(bKLHpah?1RnBVj_w3rtSFYTx11mJ>juOg_Ol1q!nX@ zov!nawIu96j}`?bhcs#(${MBK|g)(22$d<&Rq`6 zg}#A>tbVp|AE`I^i&~w*Xgs@_rJIzu<#spU5!j4X*PbtD*btO}WO#Ej%S^sChuiN= z^smQDVDv{im@=9i*SuV9A?3EW%g(L8u`j;tF5S7BM^fDG5PxUf#sXCh6vS~^(Q`Ym zx4oPl$~0TbqpT7ql8nY`6*_djwCfMg1Z=IX41Jro6~7{D-(37J6sSOGFx!d#0ojH<$3$qbDuj7{#=En<#NEN|@>$ZY zb-N&*jTdxos==Dx{ssT-0Y>We1)cd`MR~w4{0LWC`s;8Y`$Iyq;@L6yt}*$u=Qekd z;7y%IkS)Xv#M1EpG}{&P(94>Ha{8Y$>tplx5##%te@`_0vMCrYpC zoew!ZQceA=jB??Jb+=Pdsa3!N()UBwQ_yJ z`O~r-oy5@+{YqY}ju%uq^{R+JrSapgc2qG8-=AroAFk6=zI=ymb2>IMv!7kJllMJv z@8?1J=Vd~CZm@7QsxiwG2%CkYhUbypw!%4$@d96wa&saS?g^TX_%}m!a>ICe%UL0p za&<1g?kZkyp&>cM7=xn+kK4D_Cr)ZLeLe$tFR-n9AZk_b#>|gKFxWQ795QH!6D3f;BbCk`ZY@$Mpo)pLTlNdI2tj{^_Es(y z@dn@s4om+B6$nHBkjRPCdb`Erz$(A95*M;%{@SEhYx;+whB4!q>kGa1gdWZwY#W6P ztt;;@(5!yhdg`LtFWdEyPjXn>V_f<{?c6KKhktOPGR3A@NlGZb)-xb#F+gA@gUc}u zH=-6b)L!|I;f?TGxjapi5NPTa1Dx|zkRTpAh|Zzs7@GuCH~-~4H-30)xSfcD#+UPS zDUwN1K#772>u;0*`J};z_8yk+3#LyFyOvsbeVh%&xm{H?nZ*S#CJ2kUDt^SN)^8gr zfp@i$0s|vcZh8SBLf*3BWLS%|5Fen&F_tHaZ}c8f>&suOa=WJCMbtuqGO4YHpwd(Q zIy8G~vgsxR+X(kpTDSKPfU(bGCIpckfZnbyHY4)r{-xiD_P?>W7TTp+ZzmM~m4+(n z&FNA6Mw9TFt$J*wsa_(}Iy%x8&*~GTYuQ$`OY;S&<3be+hq%9;0VDY2$<~m$3-G*L z&S;cdCsDyi7yk5)3a#cnwA!myKZC~uM@D=AcH|zRx zVDVObz-+(St<`#ZAucgCfXN(=tWeTk)IFA>9bJk4nSQCY| zLfMt5V&}pHnK4rWPN(}9$yW}OL#uO8vb>?!>lnwYy`^A-oC1?w@g32#uVaL3|MG=a zY77w3`1S!>iqm>9Dp0P*b5F<3)hgIU?EPkx;s%Grtd$so6Gpd?Z;05ySn|wekk|Bg zvi~5uzd)T9^jdHf#_$yLri1KT#i6UlLL6e^mwt5?%2W{Y*&si5CM|ARUpz$1qYf!%fo5(By) zc#pI>z_oK#4zF9M*Ibth*?}ymo|m05hNnppJ{-M&(rKg<6~B{#{!8L;lrI1JGCORQ ziAiXmX)L#me$-;W)O3?Ab41D&LRyn0AZ=eO_M65i-MT0Up?!4irVNuo+zo53d;zOx#t<}1vF?pp{1Iwumh)5PIYSEGya7B%wIxW zAF(eo3L#*!F>=Smzy6}xd~H7|h*0N)U(RqE*Fg*1wNJE%g4qcIu{ z3;F#MAw<)aI{C3g_jlEtXt;q}OB+394liB0_@3gDok=;D$mVe(0|hnJnmAI0g)DS2 zGC^OIuUbKsx}A$<$fp0xm*=BlrGTfTuc4{d|AXb3M2P+Px{FymFS1 z=t?e~Wi&mwXWE+Y>gh#svy|^bLLJ`Y&lJo7l|n|LO}CECA(w}P4L!ZfK2iGR;Y>|c z$=(PAdcs=by2cmB)n8MF0!QIm9B zT6ha**rmd-J#sOzAAVom2a>PoZ-Kt$N3@xiKIanqxu z^Q#i;L;4{J(P6gq&tZ5*#i^t}RHOct!rL{QHs3?UEP(swiQo5ehTWr+w(16eVpg=u}(iP)EG=F59T z9b!?g17m9^P9$i3Zq-_BZYjVr|G*OyImnG!ScB0%<(h__%1~-Jxcbbl(6U!-hBP1Q zz`vQ1FohxOS=B}OvYgyH4!cJa*Hgx9+FxmcbXJI&B-F>ZaB$v8$Ymy+#p!YpERxpY)#+@!Z|ChFqIU<`J4 zToDgb^U#QMkjVP3zu;$qfYuF)5j3^p>tfg%tp+2+)rX~acUW$G%mB|cIQ*)wcznHf zR$g}eOjzA#i@)+sr*cdJf?BFQg}4`-CB<*;8CKf~r;u?`)Mj3m9(-OLTIQWa-+GXP zs5CA%0w;!}zgb8tvX^fBv3m(9yopUK4VOgSJrDHn5~(RKf_9hvG8B$|8Q7q%oo2nQ zh2sCUR_f8imi|8?bQ2*NtV9DIshP{fI zt4jP94v|A!`1tHBI7Y+A&&wa+Y=`o?-1*5Rk)FIjn_m9(&!-X<7GIn5G>|@#xgrto z&ogVtnSk13ZOSLl7nf(tUM@F?b3@H9iy~Is9-m*9Vf&`)TV2jBGSh3Ve7OlMc{h`y z);3S3<=eY+80Q!*0IbiM=5iZ^1}-I51_%D9N_ozp)Byl zA(R!r3qmvsLE+fc{p)<1uRSLv&(!?;#*@t~{eWxT9mK!&FcCfGLO0syK{ZQ6@@y%z z(%ZvgVUDY=ofm%h_d+%SZ}u;^U?V$z7PyH_3u6l1lou7O;=F4?uuaWBO7LYLS6i$ zU0yZRKu3oh#ZhKh5lszU&>_20aB9(7)ureTbQUfi0^N+fOl{#5eAgdjd~JIhtNx+a z&j+|O)UreY16>DxD5qJ+UkL(BBZ2y_&DAc1BBDBySz{mzV2?nrd!nuThs8sg`X<85 z-mx#DsoHV`(+Yq$sd8WhZvqT*Frf}3HbZ-qr2mo*bfk(w}gmXY)E)>m5 zy~ZlvK|J#l~2Du|afx`gUp|fH!5uLwmZstwKhzC>W}g3gNOgB*@G=L5TU zhAU5Mm5I`dy>3v;R@ty*dGb^uXr$FL2T|Lv&cgx`JofA(o}L*u%g)0CH4fj~dMZd- zf))tYnNcp_KUUY%%Gg!yP@o*Ov+T7iio0Y^J{M1vUxBOZw~llTi2krOwB5MA75{cQ zX(sMJ&tggG_Ra?yj~0G+a&vsYZ>3$GIR)O4k_Xdiia6xkpG8Hoj^qs$W9WK37%@?p zojE^msHWVW1xuq3YV{RjtiH`^hVZ-Yzt89BW{}h6;xktG_Gr7YW$1o1tLpnwptnLI zOOlviWII4@OQxN`ePW{b&xt?2Ded7$9 zu}|H4KAxAa>^RmeoDaU=YLvM7`0#+T4ydJ>@=!kc;W>BpJm{wIj~jqP(;^K^zpLNh z*)XPVgkSDP88#Xk&D2>Uye4@bTFz`qy6Kem_Ue2>c;#`J`IFRkcl;>eW<0_4+`x7J zM(q5u_G#<7h9I(%ddhgY?~`5T1G>*REqZ!J(Y!X(i*M7;7Z0!c&#JG>e)7r<7>Rv5 z%$tFGZ(FJA?G1S|nELwIQP_LSKa@{PZvAPpsHOmnvKjP?Xr9Qq1}_16tVD^N8T{p- zPSSk_eeGuW*X-w9T4=Q_ixWlno)`TD-Nyu`u%Boejbp9Cc?6(4O9Ei--|BmFa@0~~LrZ|y3aQoEmZh;C&R;wQCPV6^3dvcsR$jI8 zeHnVmTBU?G+7yAcBUGbl$k}g!T|!J;t85k%im@ENGQejI?HfIl3HrilS=p^rU)?pw zA!pK;I>St+m?wio)%zfw_TzPB^Q-Cj%LlWp)u-C!jnKk85>L}vLB?p?YXCoKj9)8i zO}PqgBY`8wLSfQ{4%Yd@mE6Zq=OMmCUdS;9UrBs_-S6{PU=^<+$za#$RrvHl8rX<{ zecj9l3i#)XoX(>Tfii(ECTYt$vw%oGRMF&~4|_iK*$;3BC5LBo{=E zvO}NFFBt3xFh~Ym#U>MyLz&`hX&k6T-jF`JJSVci!*P?FE9vgsHlBFLjb!3pfDy~x zO{bz6Tiz&B`fHiX^M2mO9esyN4T~>VW zJv_IXrv-ND^(Y@?lRp*e(%OW{eI2e^baS#@hlOm`2s~&%srU{84L^Bor&d9Yba;Fc z*k>3Vk3@Yhhh*|{X|r*MfE7+$sD#UJir5xHIoNPl37WU(Yq(h)m!Ju;-0W zD-s}CDAUJ$+Mdj<>SQtifkOEaHdcOPUw}?>K!mKGEC~`Lr(1fBR0Nh9{e6gr%U9!H zQQgc3U1&~Fg=&RaCGdcwdM7Iw*0qrxus$oqfr(NBeS1-)hkvx1DNkE%pzKgj%C;#A z2ecW&5~8wf7KsRh)$?fZX39cy%UB(rjI9*UbhX#zG2zC4icPmr4vW$(PDqStYFMjc zSq;3r*+>j{_wRYOPA(g)X;KfQNv!{%=_f?sZJ z-)|+x&oup>@PsH*$BZu5SGWnF}v zFY`0g%f{7#&NF`8bNGCc(u07@P*=H}h$1PKRF2Rz3Do9`%{CYEJ zBrWi{o7IV-Z%~$0P^4JBtE$T?5i#kE4Vzi7jY&@LaAp|=2GaAreZum3SLk`girxEB za6Hahmr}+eePT9Xcr#SUw@1wAD!(Faoq(sdhicBHnrQ++&M9?=34fm_SI(KXEv1fw zTd=a-q{1LrB_|O<@B46Lbd;|$Kic-DHfR4;*#g&=M|EMGNBgl2cdd!dXT3|Le(s1~ zRu10N^V9vS>NIzHN(kyBV_{tekb>8u27D3c|0 zcR^*(7B!SIx>Ci$2wEEzl&q*cCuNi>)Z!^o>rb>a>WRdpFuIvB3Hp~X`OA5;#fk7f z9Lqj=M7-Jhjp)5bTbG$usAJjh!+-9fxNBwllHduXxAu1hoo~JQfx~%{oe%>Ynx;y+ zJj0Dlt(~ekLhJ$2p>fi*Q3)#kzdI01ICA$(>ov&(wxwiN`&uWRM|=Au;}}0o78-pacp|1RIQE7!Ye%cJTh@iq-J@%E7Io%%U=q*$3+U#y6DkyrU4d{$q? zqzuC;c0sxa4}m}kyZTfAFr%iJ{)~NTrRp(Mo28t=nTT7L*4yfWXH9M@QfcyMLf;SR zQN%+Ae9hnFpL7jagG71YEAct|Cf^(;B5n?_oz_nu;IDOGFOImjj>_sM-K`h7pIfX6 zyHE$G%cu=l!1$x8BCk4c)Bqo>Ff>bXJ8DLH{iY}m7bi}Pat*P2_$zsbye%D>A(Ijc z`23%|78(4etKoq5AVY^@o5Pch^_Gw&V!&ft>Rc`T`O5?S!_N~x>Zecr`{=_9g19q)}1w+4~v^H7Q~eYoCo8n z0~<9yWyp0EXmgsUO4`oviY%@DMx~DbprMP4$#}PwymDvUr4@b{ucGG7Dtw=*>>HU~ zNJ0|Mq~mq|Yae_=D}l7gm}G4#ZaCZQPF^yhn;n*zQs*{HFFgOsv4?DeEzil zjeLw`M-Tuk&(D-RQ1v)gD;=VAjJ9pyd>=xbook)8<-NrE;MPn6#{L#slpu*%r!HrG zqw?}Gw$WMboF(zrQlF43fukBj)WYgfZPos0tX$Cqkz=}>Rv*v^gL<$FKLtE*;i!Sb zOAfx4daTm#C&CS+iHzK<7%`^vrHd1MVp4^cIcj^uu~c7pX=A;feKS1kMNmU8HoGEz zR{Fl7$y{t)OXJzqzC${J>!6kXZX9JJN$TOIx2}6|`g%hLkXyO3c|v=Sxm*>%9RMV1 zh?MPM|IToJ1cYZiX~)%@5O{Wb&Mb+)If-ersAy=VLpjx~b6WP^5lVVo9&HX61jU|d zGb7{WXBO#od986Wn5-ovrIs>RMV7Ygu&Tuc(9NHra@-(wTwNG!U%J!#EVkegrZxA4 zNg0T*Ef+rZ{aE#JCxD3A5uHNwRJcJgOzkwz-9Wk9<$^7TRWj2_*EbEW<)4}owz-sm zwGXnRc?>KEf^;<91q*XntIe~|NbSkV5quF z`=FrtiJA!L-A&t2_gy#caSTOjCq7p%x5BcGBeBxJNZGLBIh9gSc22JFb1e{D(>=+m z(;jm%A;LhM@KZ8-F5pbnNc*qqQriB8AbF}@I=isZkO=`#x*rs}hjEY=Vrc^1tF~Gh zlPsZkSz7&`*h6?LlMLWa{mf3eDLIwyQ%t3k>K>GKHr@g)JUybfsm81O(I}=pK~;T_ zCUUmaOJ4o0uV?~gw3C%%|1>>Eh>B7h&%A#$w}ZyX7UdOYAwiO>g^EFW`6xJ)m?m)! z@7Y_F*e%5PQWrBUsjzcCj-x#8nz2wZQk=F941{`5ee`(pIF$#Kl#F6l?W|_>767#x zU}T(MOkg6l$y= z?|NeR0W)D1`A!dsO8s3_GqWF>a2WK`i>f8|qK{JRB-luEGKkBaIC&8D>p*5j;FHu@ zJHmC{f+uoq%50e&eJk&T5K6QM>B2x%zN>8R!N|A~t@iKq+CL=mZh@>*DEQ1kOtGs< z8lHsyz4>7B0U@QDu2TN&QEf-Z+E*5ZQRb+1uBa>Lm#fcjo6z2`CC|eL6R{)m>g-7A zPXjYMiznG(ca#gwla~25{$V}y3QhS(d+MMB-`s**C+8Bmyrga#EP0USkq@d8wj66! zhQ>!?+21#J;FZSY^@V9jz_WYh{GG-s2p+53=DS`uyIaNn+>%?no>;1DVnV&Cw=61L z@jm*9+1laFoN0#^(gVlLgN=%EPego}LvCD{kIL%Y_#h@s0NB#V-o2LKZ~GP{9G_uu zJ{4LRab0{P+ARD`mGqI=W;GwPW-RnFF+2ISE{v|=bwS7FnOzMd4@Y_RRKQt-;8LGO zTwMia7ZQUHMWa%)2an?qG)IT!s44MME61b(#~KUNP1Fh~cg*C5K&RrZH{U~q;`V|$ z8%-p$6MRV$BZx;5`-H8}%CdHnB@8s45=1hv-wR&bmB;B#VsW2|uiv7)48CRK>R_-K z3$Z>nf!%Ll)qYip*Lo?-R7SS$co-l5{G^21p{Am|8WF#KDFJ9^OcPMZx*vY8Dl zHQtlgu6|bDQxI|v7YDWd^2D~rGTnsFVQ^qa$Jq(m;})bYORvR@xPF<{%bUbZQv21~ z2OPREdT0`T#uZrRP-;g}AK)o0n4ymL$n(QRgEqYy&L^8XQZ=;HxBktpe`C*PBT^7? zVuQQj$+I&flz+5BcdGikLLXaP=COrle0_<46!la`f4IHov9Pm>!Ivq$bx&~}Q*$}C zjtDV@)IWzxKTT~6`LGM8q~=hN2RTwbNabgV6G-;Fni?0acO0{pV_1@mH(zxYG zZkm-pqIIt0aWjokvW8-(dh&_0#r&W#jHFSDRe9Ro4Od;Dni^` zZ4?Il+JfWFLJ}cu=4rTlafh`*<ChtJFArA6EbC0;w{x|k zc)OPw3PW#GS}Id;u0>FZaw9&Qdk^E)F%WvD@E!A;cRVGs#X=Z?_00pm4km7}HX5n9 zVw6dMKJv>!19Ii3+!D~jTz{kN)0EzvU}6RQBvq~qslVb}67Jp;O-*i8a2%H^H1}b= zAarV-yiwUV=)9CG+s%pxTa}ZNDDJ0oDur0fk@^6^*2RO&Zh9Wa(tT!GjD%5-qWB8+ z#vk+aTF1;RVc&|El?~Sec3)FCxM2bL3YLa@pfh}5Cd|QNS$`hV`T1HEpRyADQQ0C$ zL0mlxi+ak{$t+;Ovr)oqRx+i_%QK70qWo$!iOYB}nr>5D6FWq_dw;(1rEWhlz-*^r zsL;#STX~=*;$&CI1xw;et2H^%ppqQh$w%fUnPtyi@1Wy@p=y(LSrerGi7C@$>;kL1 zmwT7QBtQwhP`yZ_U_H-SMQ%EUvwLe^aszj}J}OZs#D*#NT`qZm&5r7&z%6&tYnlBcCjv6B7X`?d|s@FX$U zop{7F9Oe+70^{+T08agtvpIZlx(Z$DW3~8RvJ_E|?c0{)Es9mJGMRz3JB_ai7#6Wz z0Gm1-RmD3Dyrn$d)unU89LG$#73k|TTOkw#ZXVm{bkYCQ@_~T{Tk~us&~$+8s3igr zn2=3RdZ>O|-9wcXsLs-U0+GoNKbM7@w4Cp+hWW*QNqKMg>KotR3 zm;u0?w_#he(W!RFyaig5ytJ`IBgAAT)YWypt7whtPOYS)_^z(2w0Ws)RTBjRc}V(I zU6S~RzCm{OKin0i&rq(lIXH}f`1R!m?2|#3in;_I!`m+lIuC596Tc7mkV$3w%$d>N z1f{mo|4dG3`}np8CFbqot_`U=s+1GVcQIFUUMp3O?kSF1?8Ak^y2v+~y|f99#&|<& zHAs{lw~InR+0T*TZYoX55WKhi%z!1P$hh`%K9IX=KAGcHEs0cbxA&p`ESMdB&ce#~ zLMW=XOFzg+#yoYA2@td&7I0+mTQQrU)hs(lPFY+>rHneBG#1e5LGq@%tV~;zTYp!& zehX5^e}uS{n9=C&1jCl9Ymni-I+5xTV#$MhNqqGF*uJuI1Wh;pXm8!?FdK)zAn3%x zQZ~>n8aup-$1`dyxnidTZ|VUcxIgGZLb9c*aP{**0~o0 zmkR_mIIul63_tEr@A-r>)DZ53fBg5j9~U(h!wI2;KYP)y*PpVo?gL!TqRzcpM2Lc1L*jM! zvQ1+Q0B3El)-hK7j}B+70Rg(kmHK7l(y>okSUfuIM2q&=xhyq^H5d z=h4R!ZW&wP;z=g<4Ti7js@g+9Rv~R^l3)T~Q81;~vnkmE3~Lgx4K}ev9Nmd^=1s#p zryIn9@c!YQb)Nc$O&!}sO_QrR?y7~#8F6faX0xQ~)cM7ESaMvqqFz)b zNfiY|NCwym!d6=LV%FYnqn*4fCoUEY>ByDEJv#T*k2PyY_d1#kEEPN2-MgEdB?Q#g*?c?q z+Y2JCT6KKyzaTcAmw+7exnABX0~3{Z9_1PEhn~Bz1c@hR!y<33qu`f4Er;n0Kx>wF zWbEjLe#_@Kl3F#SYWE3#KhQj0KT1yM+0eYLZ!*0<`QWT~fgNnp6n_ipa?_d~>|Lt2T^`w2% z*de*SAr;7{>DaUjrd5t(=d_YjgY$6bm>Z=%*h{<#gwZ?`m>$Fy=+;KSywelNx5ARk z5xKs0E{}fVecUcp@~!N;0+2={m5_nn1nqP^agz;PR!E*(PCj?xO|N}!l&3YL`u%cO z0j|TFnb8BLT&;cA1-Moi+;r9L&udBTYTsB;xX;G3R-Lm}xwA4kE0z}|^SucaVHlwM z8km^nNFlj;vFC_Y#aoF*9ibf0+xm6BVOB`9dD|9R*2aOYmBv%0d#n(wp7&hG-S5=B z2umH?G*iBr<{Q~5*6Y6UB6U4=)#QyNRqC-|Pxj7AyqfLb>yf!nqrLBp%~vJb;11;c zL5Umo`}Y8B%K|plV|NY}UV5F9EavdcSG5(10=a%j`*HCqnrf%(KdAhRMd7)809~%D zy7d!j1UJvCK=qk|3ZLynV#eh6?q2eV4VihPwq;5Fe?pDJ=!U%h7B6~|&y7+Ql~1>G zl6gcg8uIkd7rsGYIc3uP&hJklkA}V6r5#$KzxH&-^jCfuXPBN3)7^F~ALn`DC9>1P z{~0BYbGWlSW+8YIe)!^z4uTQqGmw?(69Beg9i{+dz9US+HbIzlU>ugMp^}}36_VtzZf`}=I zP$u(vD6v@v6p6(ZepZa7_U&9>9x=y%y~{Y}?tOOc#1i;ssmEnu2{4aW!J&me{);~U z*HA)*O^9E{3bfi%a(|2gVv?>*+?EnO%cUpum9Wd^&)f}rP*U6FKUmX@$^zuMj2zhb z6I4Ncuac|s?Gp3ONyL)OR2j@=T7mlq>dBfVG^ZJ`POx;LnMNG;enaB_6iWV?>pwH@ zE96wQJW6*vA!?)5RyUNo=t(Wb*uMaqXPT0`i4uh%b@Prs#P4z${o}V0ACd#0|0Og1 z&xNo(!knw+uX_7dW!P}l;TCz>8Ht2KO(Htq2=f~V!ydw=`G1D2u<+6e_k49U8_P6h ziF%g=WKV{{`f23<=T_;SG=vcsMhLr8;sM>bDL?Oe*s3__=l|x({JRz{XsCsub8gSa zf~7Foz33%{PjC>f@xL^|e=llaq0_DpSPy*- zVN-@&Esnb!xtZvyd56=+8Tj_Xq_ETm%h@9(5M!V8SJ=qy`s3O@X#}p!)gb*;uDUQu zpJdb+d7^`nZjy4vwUfrrcv4ClKt|pt0Rel)6CL|74QX7RS2Y9|7uo;MTLg-I8y7(N z_L^aP^U>@zIeYVWZIMR(?opqWg03$9mfZkReJpi1iQ4Nfb)O?z%@^oYTwE+FmcdE{ zXkBVdkxcKnzc&yFZ^1I%@ab;Zr5MM;>QcJLW%c3++s1t6{CZVH~j^_(e!idpP6sE*{*tq z`ZX4i=`;j73H}LA;m{WA%>{-UK|@27NY(NBdtZ+T{3hUb^)yqkrF&EmMu1F-381N; zJoQjKZ?~nvcIDCVaT98|MivcptDc?jtGGSsfOB8d3j`jYSr8>TMWIc^dfGi{$}}p& zyf?-Nld^rpMiQ=CJoY|xwVxR33c9~nF9dXdIqzY@e@vRScy(s|_82fS+BWKJ#G@)L z^Edyg0 z-L)v7Af@Bep>hjWj+`#f{!PJCwWow)(-w=LYZ>*Fv= zy|upcI}Q03Blsco=q}qkou)%wcu0=;`qsNXs+lt|mobL$mUFoL_@BaeGu7`ZtE^t9 zUFWQB1lniGre^4-Oaw=E5tYTGA-?a5lQEdMjc9i{(~n&eaWH$NZK_r)oj1?Dg^{jwOXm4-u{i+<6+!L z&-eU}%;)EVB$J~>{t{0&(~RwjMhaFHU_O^f-kp?v+u6x+yqmn2z3F2ds~YC;0`b%t zVSp=-zTZh4VReB{g=sXArX}4dPeGFlTBxbIM|GK6Dn5Op%%(N5(Th?Y72M-+Q8Gxn z#pMcOBm5vRj77iy?Oo_nA`U|{12O#O>5fRWX2)jG{%||Ov!XAnyWSYP{FlsQAA^e! zkdpt=@Du}tBLerwYzcMm*`8`MmZ@rbu%*Fqxz*}>YLU3f))yG~8Sawl8Gx*B8d0pY zFNyOs9H%E+u#x>9;gWc8{s_J7#72{vPIqNfZ7W3V>u8IVsKz)C*FEWu%(b$mkv~_& zm!J~@VTz^b=dIY7su9U|gsy+hR)D2OK;VdWLby9xnDS<8G6CKuF=p684(peVcrdM5 zE;u71ZNsQ@I-n_CS)WiB;s4%(yL`LL@=}X*RCK;?Y|c-yNj|1xQ!J?kT3TdPDHC=G zZ{~{*S28P(DLS?i1H@$=>Zwv>VW9#)e%g*dYaF(5ybiHk<8k`BkN`)P0=&|O;FrY$ zFshtp6NPl!#kl>W)KQW4)YUZve|y3(p9<7xwx{pb98S~E<|^O$r$P&9_;rAwB|-D> zRRNcy?YcssI#M_wMhRGm!XQ_Kaw1Ofr2&a8J*js0c)2&SVAes9kd6e;64wImZ?ktu zGT=DCxFsniTnpZki|1r(*B0QnI%h5tPkTv0IbeCFCKY>*L#W$GFh;f!-C98#*H8P! z`Hlb6Q74DjW)h`15|0KJ%G6~Z`;kC45#E1TT0PdRN=f>HuHok(DBb&f{CL@=trEc| zas1@U{^(zWxFRgT>9xaZhOc6+i4+}ovbQ~?o%WnMt5AweZw6dHRoQxrmESy)lsHiI zRtQ1EzNHo}fu(jbq%WJ!%e#kZ@ZYmw;Q}yVLGqr5X}`^XFz7M>l28v5AXuk4Nj7SBk{s7%=6t8 zzm7|zgeSp#1Tk)1!k9$Nf;HxTx(mz8jUZj+qqH_f!jYq~>u{|7F{!uQYh_rG;7Wa?#{%Xz<+8ueMJ{@SO7)l0qR_!G{SmG5`vkp44wZu zYifF~cxNS~QGV3AJ*CF}VwDD~LjM1GU`A|^%rRby<%eU<+XQY$G}bKwiBG(mW(mBQ zw7VPG7HGibm#vWnzr50);Q4wx?PL$mAQrQZ}c*6jDXMO z0fHuK*)G2B>1AuXAk!NJM;y!AM9a}#dKNnITj(@R07rMs)l~<74+N|e1oO0BO%mn3g?;m+%|A5Kw|E%xZmi&olXBUBg(e5dNpiV97e3eT?OJ|_ za!~YhQz-i$Mq8-uhRrd)){3|9p0;~10{{^%e0>x?0Mr5v+GoJD;Ua6S9#7kX~dE;e9 zEP`-Pm>#}G#Da7s`_}ByAjH5z5;c)u@m9}KIrjABu{O!8uc%YPRLtbbLnYYp6G|VX z6=ma*7*PD0X3VGNOvm^Ib?PPmZO3XiECd8>Yc>B^GCgTt|DrA%@4h}5X=VS$7b_WWKM$&0XiP7b)(C5u;*agj=iIR5XB4@B7K)T<){V-Vp zH|T!y+;|QqK_btWudBr#HAh*pibR4j{x=QH7~q6>HaMAl>QZWJ{yCEFV&KF&E=<5= z1-;piDOCnhGc!bxU~QC!)kn0@;X(NyeT^y`Y=OCA%d+zCV`T5Vv$Bok$8m=pf3*A> z6@msUHQ(4M8Dgi~SFd+N1~7P;>=K@NV-e04%rC6ILu!Rfx2CoJTKKeS0jniZl_s5l zv{n5=A?4~9@)m5KDtd~hsscICS5TX@QYGTu(DTHC_K z!bD);=Ek$<^T00hx_&p&j~&Tx%rA^F5QXsa*rvS{S7t3)zL;Fe3~L@LD%ixL{uJ^! zYYDh`7m|&imozRUDmT}Fz~j*{SZ?{iO(yZZNZMIvvI-$*5Z^v5H=OF`R}J{q&J~k( z`(LPniWYSI-LD1h_GYco+7_ZsW~>TX8t8;w*(X6zV}VrnkWSi4`A(`Oz22|oKH$*-KZAB<^wFFok6Wr*VL;wg}D>jmtP| zMd~LbmTMZ{REii1)4X%OJKFK$={*0}oj?MKiwy=9=n~nn6$xE^C6WVU9-O?50*}7X z4L+aq^s_zX1y_*wd{$6V!Lr(&z~Q$Tw?Zq4)G+=Nw$sEDoxVLc{G4MzN+x##PWY}X znT52-6V^!rPZnrEsgduNcDf^)&tVi2wXOLg7_UXK(%Ka^XIrxhquR3@0r#}b zpl^VCiy?*de0uUaZ%s38?PK`1=AZ#I{j*8@=-%F`@a^TUuZazDE;L&|WKoggzfmm2 z0QEG z0BUcBVqIS6Zfm-eyty2G^&Out&@F9Tez1xMbT#1F1%8PI*ZVt_@oz#y05mE&AEcTr z^suV^8RHFB5I$KXKNhDYMjTLELxT0bGlI(tA66Q zQTzFT5-Z^QBu7_;6H| znEHk;?aigiCyTj26&2pJGx@2iX`}8ag_HL(xR0H6i8k>#ME@tFB1Z$#ZQ3W%ig(c) zw{(uoZRAu2k`)QY?@EC=#Jq2g?2-D|m@(CeNnrb+WHE(v(=4jevs*FE`nYZviT*;x z(cS&aQOB>tcz@7aeo!;}tvdoCeZ!#lG+ExWXOa9WOu_hIgmE?q2QY2S7XW!{0C|h) zhUMFuNd|+%PI|glbEVtMErVbFs5LMU*hhF{vUJW(p+E4RdTq#CZhte@RUCj%9==qB zfLny{CwmiI6DImkzBrb6`Tb|vD)2m-i>Q?dbqxNHW9@lr%}So{xs(pyOkbjAAfx}b z7{A{U@m@ef0+Eo2AAi`SF*FM16?u-?iBZlK(;A^P|oF zIUAe1#tssd*1|b!nq9e~Y1VJ2syx0^mr=Q0OtWAny}HSMjx-+ghZVmDDdpfaq@50P zZ$6f^0~Mzcj>-Mh zJTQqRd~h#fO>@Vf6Meji-M`=ENuM;XwrVK$|M8|#x|o0hbCrcDOgzb{_Y-5lTeh-3 zfIj;yqjOX`!maS^fgc4pv{iqsS`12V6zT}r`8K<3jzX(Hntu9GIh4bwkXEyq2QU~1 zlnJDNkO|di0l+S8ZEXe8bpWN5l3<#}#n47kArU!{ZA;2icR)0*+~Bntol5+-Kw7L>5CK5qZ66yJT#R4q9wj;8eG`!u zsN^wy5qrq$b^i0=xRHtekRc15g9Ao9SVA;Ke%P1;HQZhINu%=Vr<5j!TrJwBOOllz z&wIR9y`S0lzdUnCEj6YnyR}e)+Jk}#_Xj4U1tWzuHPtEMioDtVodzpcf|oijmL0fLzCQ;4 zgh^`rFeMI1c;1h(>aQ@8)_w--=-^bxL_soNgq%5z$xj^I6d$w9!;7ap0O>DLc6;uB z-DwPSUo_A#+-{6%*!(b!9f~2>S{}{kY5OQwwJ4-&^~Pw@pFV{ZD2mqmOhtmAgaJ8Q z3jZ+M04Gm#F?#dv12-zd>1e^ib1%26RyVyLM{o;^3tovXUCy!{gRO^Jva;eWZ%YsZ zxjnQlr#;W83bh)18FpPBoc7(&$*L#)6;q!KbojMt%(60CQa*Cb!U}?UrLsqbT6O*e zCNJg}!k6egT_Tdf62ioCpyr=V45dFC&lq+9}%)4^8Pdm`q)LJ zncx@_3q~Zip?)r(wFWo@CeFbsGj8tI^k6FYE6+jk2+kyk7wib#EO`cs*=%a!33Fj8 zUBEpv(>w`J#UG&mCDWkSmx%FsiXU4&RMcR=aE;L%kETNi=q(g>+o(o;D%`K{>do;& z{+%#}&i-nV8qX;l&*1{LjpHd*TKTatpu!FI-QnQ^so=toPP}(^EY=lu+(c)fVZBL*;vi#Eiz$%exSF%O8#o@#o zo~sL`vd`h)!USB=*SOt4ggrG3N^|i`U%J*B?{I-sK*JgS^oQ z9_F@BlIFZETt3-I?&W5HL?|L%GQWRx>|aOa&J}`>*iYZz()XH^~bF>it*ruIwyNP zgFH`lIay-pmUHX208&WZ3G5P<>EJ$L;UL8oc)-b*ZG7Z)z}T6kZ=)___o(&PYkudP z{;DjKO(LL`;%`3WkTeCK|FmY=>FWG=b%he2oCJbM#;CW^aCUPYOA)Sjy$E||G@9k& zvEpvJj&1sxt)Kvv#yj6qgp)Aux!!nV#??{wnkE`WgTIipOJG_@Ytz%orvyHkEw5Bq zbdcWvj?{d>`H=$b`<$f*yG{9yF8J685rG2z`lS0~3Dy$Is=Di?uaR!_+S5%Jq4;H3 z1tYpECNMyKJ@o@bhH&6Mmw`%aYJT2QPui8{=dA#$(j@|FaNl*dKmd0K&mp7n7E0KY?~jP8Y_jvb-jo4xIpiT!2pE$9XGW$!Y%rWdIM4 z8Ye8VJ_fC(8={a;Ri!~s=rPT%_fTKHg$gDxU#2)lhpgQ;Yfm>CVX+85|Bsh$t^|s2 z`#s;eEqyN`&3@lS5wO2^Hb`#8lH%!p_Nc1W*}O8Uy0Ab6c!`Qh($Wid&|7iw#Viws zv~Q7Vl+Kq?c3t_E*09Jsa10ZT87J>p{x><~Q-d;q!T+$;X7Nm3Dd$Z89sDy|uZT8T6(=?};f{qwpf%EDg^r)iB#yg?;!SmpyOP*#)HHP@ ze-w{ILOfFT9T7=L%yJ0T2H7((ep_SIk zg%%f{#cZDvg(&|D?p>GxG?J0nw=c3d4vZ+!fjvJ<1!dz?w!YVvKQ|PNvB+ISu$c0~ zS3M;ZGL58-V+{C7+9=F&v^J6X{TmQN4Qd?GBUE_JGb+5$8lZL?IVsprXUwrAHiO#J z*w*F$7Nt9&u7?LkLwjM+z15Erf$vuZ!dqw#LY`M!dhk93C)DluSsRp11!5Fj3e;eG zy;ORzF0R%`32=%s*$n0z+uGnji)i0C4k+`Pe=h2o?+C#WemRTUu|8rX;z-AyUd|wT0@)(fAyZ(Jc+HF-a6e2NKo!+Cdn# z{7VrxMp8L}ra|R*xR;VkFwMI2q+sLZWDi9+G$0w-_tDA1Nr5lZ0nJ}T0yN)%f3vjs zjc8DT+6z&vaY9_}u-D`n^HL4S&h;ah#=kjVHOWsXk!#Om#Z%$!*?@$-kt3y`R2IZ8U6k zwVQzhNCfH*kbVIyr(k}>_6*^T4U{ohsMccRwp2LFCHP#_@xkR4yHXvC1c z$AkhQf*pcGs^g)9o zKPqe^jg*iu(3j(SM!@PkT#UnQBCnlF0+4AJ4W9JqK=uNxR!rwE# zwq|*0SC4h(J?pBD^V?&=wo&JMh{x4hBEot|V1px;>EzGFH71lH!Rh|GI|Z4>yXyf> zd_5;Ky(sw69XM%$QI($`A&P(HZm<-)w&EUHabekDa*esa@Q(MB27c ziKea45e)uAilbNGSQKr%Kkz4MH$J8O;>ds2)ab=9R90GSI4Sm;j}OMn>Ue*=bX!Ba zF*f8uB!8x1XB17CKr&1VM}&IygB*1q)m^O)Bfsc3NcW`p0m3vs#JHEIWN2d7Klr;N zp;xPi@n@e3lyQ7_pgA%=Q?U`cQgnfyGq_^FzjCR(k72a(%j$q)zDK?GMp`4)XOVN4 zMH>$g+RzKl$Dp!jZ~(YrdW!K41FY5dvX~e)OyMeF4dZ<#VPEE&zvW+uc^ChNgZ=rr z2+Z*vkZaB#7oFmLntgY<+SCJViA#W1hgk-uYeMub=o1{KNcuC4Ovhe)%}n#N-%;sQ z;WX-B{)tC(FrNuOu-Y%ZU}$7dGXGNzUB(%?rM3dj#_3l6jhL8oRSKKw*aY6q=Z^no z2A0JI{OpkDDzH1)@`Xl9giL1&(LL%;zYAEM()7R8)5VlZ(WiH(<3lqKGic)QQt9k% z(YbWU(Z+-8BY)emK~JKydf8D>`C=}t{8hXdx*rmx%ZTL*HghWcfNr9hYYav;z6+J$@$$D21(ufCIIEH)He zrY3MX+ghh|LhIfN<#S=ZBNvr52z`BZ@pcZO+}Zj=E!2{BQB_?Qjo!N}j&bULJi$M@ zh)2#?9?8A4{xitrduN#&bz8saySfw|X>EZdle$Oq^XFurt{pQ(vSWkL8wm)^(#yN7 z#+7b*c|s0;_X3C@(5#gDKaMxBy%JDA&~nq?a5OAX%0Zjm9fK)4u?RXFac~*66~L^U zmKKvhINJTn$HBnoHB@BWqJ0o6b=O;Fn8hgQFF)@26cMnQa-OdS)Q*4~&**Ky3s&== zP2cU&(S9gb#TLu63I88N+&xE+@UH7nsA~$w|M^rhxx21J)adyZ|Ls}x#~t^)1Jq=N z2|41=PSNizx_`gY^&a@#$Tu?hPe}J4`So!{(JKe`OW-8#LFPY{7)ukg9wIs=@hIvu z6LLo@>3eFrbpV~CE}kfO{jrvR2f)Qs6V;g&gkNIb<2+`M(wDWU%?CORDXP4gc<~=~ z{g(uwHCFOG(%ITrQ`Z}CG|LdvW<~Vg8lH7@^>w>+d~|h4f$ANMQ+?1O`+qPG7A1S> z=O>wlOYAWF!{{M}&kJ&^4b0}ZE9B*cSZjL|wJXEMqV{|gSl#?rX#@L3$t>96b>IHk zt+~&Em_UK6&SzJwo9Tk_n#`x7__Jks10KdWo&K9Vzx~HQ9D$UQgxRj6t$3c}WFkLpZAqM} zuqs{VJvq~_e`(9H(s+%i@a24_JpZgr`;aUwDK58;!T*SP8e3v$d`Z;dv`v%Yu#u`Y zXQ{G?`F(e0cc=hq^5~w~Qm_>v{oXE1(L(7vUSx+UDWI>e1&AkbQY0Mx-;?T{)Be8D%tO0nNP#!6^L49+$QOWkfzxXT$bw? zHqI-AG`_jkFi@DDwz(wpYpvQ zKXY*)WH03r*4O$IkIEKu{brjt*3XxRr^jen!6Ji-13DF{;Sy(Jm zhgB>1)9&M4`wqq*=}8NX@OUgO{+$um1Hj=e_x7#S1b7F07LdCPJ}ff}>U1ILh5s?s zZ59JHq)?GE>I=q}|KE57kar)Tt?lzG55yO`y@FN7(u_k*3|@x z8xoP{jAtr`1&3?WsW1)$Jm7zyF~&3Kf)a20XFZ!$mFI4Wyyu>v!9Pa;!@HBZcg|{} zpumxUXjCkZ=QfH8Ce5-cT3>8hR1}njjQWwJZ1D=8pu8!1@I2@}qu}Su+oZ?r@3(CG zrFR;NmPl(>lMWO6cZ0XD&#t}tzs8pv%*0JgI9p7msWiAzkx+1*;!?sB`#b>s`)8bf zp0Ui^e}-9H@`SLjz^ruv-E1tc$V|B7r_K@>B7pwm)_Fhjyw0?L&TpIOp)Y?Wx*~)f z_CmHvD6eTENpqP7{c7Ereb~(Y700UwFklpcyFYtz%|AMa%QucDrY}^Iqz2)QuYbDP zpv8blcVoP^=h{BL369|+Wn`)!H)r!WAz@RVV32E4ek{xuINajtj)|wJ`4O9W#A@%s zC2i)TU(dXI@BzY0vq6apJoe$fFCTNw3B^9=qd0E!Q|Z#olAx%8&Tn6QJ_9=2!uiDV z>*!~qStA~?lzB&aH|R)?7OBj=t#U6j+YtOirNDfyPsRRWxqHQxnD5FiXRf~D_~t4N zk_m*)=6HAU!vwyk2(h9|!7kXlUPM}W7OmQAG1z!%)l=gD%Jnpct5XxIfc%S(cN~QU zKl+4Ilt_)EQGJ^&vi~w2#HR%>1%Vh+uEn#gR_M*4-n^(kLM1+1A~((5FBIsu(#DWy zSAm*C53Jfo{C_VAv5x>DjQP^)Y86|K%HQ}vrhUPr|&3}OuMhJJ~Eh*G`G_6=uONdwxHuL%n0ctf)rFXfz z9fE$fU&(R&{Erm;kp~?NfI4A|+$otHPVwdC~{(1lJ zAEE43K4>Ab4pJn#$ERQ7H!lq1%dhi2ljhz6|0_NM%~K$N=kzk3m55)zCJld6-^5Hn z%f$+=GiwpebKDavEpSxexc5Y11dsED4vq5@bKI%I$d#+*Q;h}>M|ts@5P@cRHE*~e zU03-khuxkzzi1KO?~=!IPeGNBE#_RMD#ok^v*i?(pVAhpOLIl1eG)b=&(;?T#vg7y zVUvTo_lhV11%=$o+iPUp1jh?zu^3nJIZFE3EKXhe;j<2JuXC;@RCq?ndDCsiBOM;6 znz1Ww7t5pA^Cea@no`B)xP3!dFI;spscW2%EQdBoO*Je^w9|!z5FFCLlik~ACb3k}w+b>@3 zeW{WUz_RYSjIzJSObb*FoB3i9ie0M8t({9%EcfJi__KH)R=mQmO+iWf9wuex(+D@? zmWeia<{@{D|K}l(Tp1n?zj-)+2gFe18GA0BJe-_ldL%=P$6?p92 z(x^tx97zk)l5AHJ-l+m14iFUV)hJ-bhuYamNNtCeeSb;zk45ha)N7+Jd=No5l_JWk7&XZ>y-(-8?}_o zf8K_ZX2n|@@h>d`?AAOn-$}J|8^1k6>PZbDPaOcQS-?Vy_ z_}P@n0mAB6YBM+nHb^sH6G*lae&mA%wa(^i&^XtqGG+K9Dn7D^93$s&{9`hr1%jGQ zFViZlyw+L-cWqH&ys_5K=hKC6wAEmSAr7KDXlkF|NdK>sxC#l4nS=|@H=S(}d`jrm{*!+x=6y07EESIn6 z?th_-j7YqMKg;krc9vgdXD~g{yp{jCu-)~8ac+vlY{TP{54U^HufR}duR}!#@w8GP zD6;};aA8w$K1VrOYZRY(v(G+j1-fq?=Fy59*JNUBt3Jzo-yB1p&5Jg6Z){0H4vUh+6&UqZBn56PvINRtq%? zTq_d5usI>3T$LzBmv)n*;G=zw8=3=7S#5j$Z zkBcD%cs|Fylqe+m@Urz3Tv}%5z;^s;mo)*4^ndK7oCr*ocruE&mW+uEj(rp#XG`*s zW;ojYxuZ~(`Lxnq27U~tx94NNljS5dz`|0Ccl~vichf>dwTUy*rT+NQZ+Za@5T$tn zK-^|+GqLVb{L40`D1hN_ln}Wi?`HX1Qw37se}ZAD*$Q8!I7EAq0J8xMxgso_AH{tm z?{fGX#$HI|9qK(L{Z~OCL%=#wH(*ldRX2a+bq})8@A~+K zD>+H$r>E6@os9M&rBXY_W39|{=@M=>0f+3&D8AAB(z8`)5sOP+s|TOod>ht?+a@$Z=ca{@3)Pv>aPQpZ-I{{bo>3z}nv zL!s6U@W{wbT=|CDN7JtEv0Y?Le>nILFMUkFwI_Jl)fdMY zjrNHVMlg%&_GIUSg=KTmGev0G$MfS9SB-lBw zXFmYBYrQ8&jHzvf{7jJ!ncY)duep4x!mR_V^9p(MXew*1rEW)A?G1gwWR3LoEP;YcH$ zp4ms`$Vo<5_n;-YG(J2%5b^bE(LCuUzR5<%!)2^E?^Jw#53yAFiji!gI+{tdIKRKr z35>x00=?O$jvM@9o5*c-To$m9lO!2=wL~|w*+L;bVkHFzgc~I^9_S?Lz-?itM#;6r zUWZbN$MD#ObN?H6nslZADguNV;ZuTLbX2lbZ*SR_n6Jp}apLr8!Z<157YS7*3dkUp z4=*;Pj58I`(8$Ve`=c7_psOdEG&!tFL4WD;`N=qiwwLY9hXAjIwKkpAG=vXzSnN?Z zidzngM^|8VSR`|?z=AKS@dy-c-UNAO$qpU(^i%=|AJq@GY1%XDRYdTiGZaQRmVr?St zOz9r@10ESc%y@BCUQA$zG-j|}seMFvln#!vBIUi;{qq|g zOq;mL&$5XMPBI~u#|PyMQ>N6((ju5Z3OIFF%Cm;)vk>V=S<3;%?)Tqv8zQd6j&8vS9O@ z`=^iN?Sm>vA4F(!P*&dgjL7J3|7#8Rcp-Cf&HdP}Aby7Y@x=`=4DlSEWM13W`BMCn zNZ$RgH;aPtTUr9mhrWwyNV1@Y9l&`_Q>Z*JJ?Zn@sj9yS18fx$E?t}k7i60|blt_S zxYTfRE$`{2Wb{X+dz>66oA2ox?MxT7q)9YD-OCq{hY&f_gMFsa8jrh58Rl>qG&Da6 zNNjL!U%bh9^j=G075;EA2NnDio!? zR0F9*NI@H9_OdoYp3>8%H$y_B-wK$vh%Qw;j$|ISmX}DM4E$Iq->x7Ya!<_Lz;^hr zj3-ow12F}yz!q5JjTWh&`;D`$qfcsBw`bi2a#k5?XRC^IHMQ~DS7x~*y=2z0U(hh~ z^f+3st}7LAI7lEL*S=s6c4YRRvsIT}jk8Hyjp9>ze3C3IC6lGd-*7ELp3LDD9G^9Z zawxgf6l*6?RSHSIymabxzl=N7rJMNbR3bm7RW=KTi5l6-3PnAsnqyq;z0f$}i~MPqv9IkiyV`!ZL>@(v^Jd9dfNV{wQ`I z+X6PVi>i42^=B+E_t(fL^-iOq$~`}@o+>q|eASt$&ibxkZklU z+FAEJS|UCGu*GG0lNWa|Gbc_MN;g0f(3*;)t+@#;a>lM+ZM5My&iCT64t`Y6q{&b; zoBiCnZ*Vut+HUS-O4Yn`tTdL$tQsL~X1p**rS~e?(sOyU_zsEdK(_MnGqN(HsND_T zw5w;XR8>?-~7=}5-9lekbp zC=Hv)L{8^qlX)He%;HoreLlv9C8YAY&`Lr@X@)v@DX_N9@qe6w9sHa4`IWx2VKW?b z^*1{z6%2Dzi7wmTKV=)ja&XF2Oc$gJMoMIkr>|Ir-n}ezE%zEH7n!^E5Z-ZY;$kZE z!fLwof5e^>KUMJDR$k+5R%=yo;lm4VNnhGbh(8s)9tAy?*LbzIL7VF)ry;)B0&(TF&pp$m%z zkVWU1$a_h}Y|Lr(+58NrH(FiNgx;Mw=L<}@PP-L#qpKA2;QuJRK*}^oULUH|zjbUs zK(|S=!4VU;QwyziDlq?SAt|O1q#+C!od4aH)whCj?o+Bc;{G6e5TA$a!%dx8()Gk` zxTA$p>t#mIb!%e~{n=U*;VxziQRo*1JtM^O9HRW1L%y&boT7-2t(-IYygUNE>h<1j_;ZzSHCemYbA!EkWF#P%m^NTe3|uVWW+%4Z z*dnX+fVzYBnBX#wUl{o}zS+WjHdqQ#A>?}-MXRmT7|~Se2Pb2y*DZpGT=I=qHS|%1 znVIHLO&&HP=Tw}Bj%Ba$j~fTN>n+kmZg&;RsiOhlnud{qsU0OH3s2tjk!r)@dCpp4I@XfzNq)8@FN2sT1rds`$`vUPYhyFl zi0w`JZ;(Ws0w(EA?;_fokuS2CR!o_*wwTG9?Zq`UJ@l2;-GNf6C~{RnPooH^!x$E( z$vv&lnHn4q2Y{=Qt_2(XgB`WUc7&bMJLdHf^SqANO@t}vT7ws{$0AdSKa7lpjgN*+L9wL7k0*lXBVl_)W~U;c!5;<-lR=J^;Of7^uXl1^v(e6Wff9LN=1DqYS& zzbutROP;)=UH8fnmsL(l>-sbLm;VI3fY_7o^|n9NU~|tLrPIlVq_>-1kcO_;TJdU~ z&Yrg_>L}*EP1=AqiSrggu}v{iuMo;nPls=;ZVVc0=NN}%-9@YZ3bKcKGYJ|AVqPOSR_82$>8L3NFLqf8=OC}9Ri92fXykmu`x=4qi+HfsIb#JK0 z@<5tc3}e-z-t$ndoF{)J5;6qO0RXbkF10Vk#ozf9fbgQ|MoMdv-_G?V;=VLaAiO@b zHycTd1QKm7ogkSnWSk2T2`fZ(NWT0|oeEYpu=vLP$=O^Px^w5f2g+u4+IYgRMWgFv znD0lW4?s6mDBf#6QE|QTs(tZ!QQK4I<7e^5XJy`}9fd<#20$c>@vgO?3y6Msz5B>A zB5DtMb?KCrtMp~t6I!%ZZ2 zkAi76nnN8geN#hmy&^vMmXZD*KmbgF1#mZ>VO~`4#rK|ra|O?U(1D-3Hv$B1Coi0( ziFWujcIwHEc%qXsMXm6%#<23~sNX^^QDF;hQpo`1O^#sOB=OinvslTpXt&U8VL`bz z@g>qdQhp~tppsG+a&DDl3=rjC(sLSpGA?$Y?{iqIi z+c$T8+OtB7F@BtA2cQSl)PevW**nI3r z!1lvrQc~!?aen|w10#8sDSEr=#if}8cSIv>{p3}NCD-m=?HTG^64eeh_1=K8V*
Uzgdwkx?;mtjfU&* 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 e{?Xh4Zmr+1Sv? Date: Tue, 14 Nov 2023 11:27:08 +0100 Subject: [PATCH 250/500] Fix arena clear methods --- stack-graphs/src/arena.rs | 8 ++++---- stack-graphs/tests/it/arena.rs | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/stack-graphs/src/arena.rs b/stack-graphs/src/arena.rs index 6e4747267..18009db02 100644 --- a/stack-graphs/src/arena.rs +++ b/stack-graphs/src/arena.rs @@ -183,10 +183,10 @@ impl Arena { /// Clear the arena, keeping underlying allocated capacity. After this, all previous handles into /// the arena are invalid. - #[cfg_attr(not(feature = "storage"), allow(dead_code))] #[inline(always)] - pub(crate) fn clear(&mut self) { + pub fn clear(&mut self) { self.items.clear(); + self.items.push(MaybeUninit::uninit()); } /// Adds a new instance to this arena, returning a stable handle to it. @@ -290,10 +290,10 @@ impl SupplementalArena { /// Clear the supplemantal arena, keeping underlying allocated capacity. After this, /// all previous handles into the arena are invalid. - #[cfg_attr(not(feature = "storage"), allow(dead_code))] #[inline(always)] - pub(crate) fn clear(&mut self) { + pub fn clear(&mut self) { self.items.clear(); + self.items.push(MaybeUninit::uninit()); } /// Creates a new, empty supplemental arena, preallocating enough space to store supplemental diff --git a/stack-graphs/tests/it/arena.rs b/stack-graphs/tests/it/arena.rs index 5af25d66e..6963dae29 100644 --- a/stack-graphs/tests/it/arena.rs +++ b/stack-graphs/tests/it/arena.rs @@ -229,3 +229,28 @@ fn can_compare_deques() { deque10.ensure_backwards(&mut arena); assert_eq!(deque1.cmp(&mut arena, deque10), Ordering::Less); } + +#[test] +fn can_use_arena_after_clear() { + let mut a = Arena::new(); + let h = a.add(12 as u8); + assert_eq!(12, *a.get(h)); + + a.clear(); + let h = a.add(7); + assert_eq!(7, *a.get(h)); +} + +#[test] +fn can_use_supplemental_arena_after_clear() { + let mut a = Arena::new(); + let h = a.add(()); + + let mut x = SupplementalArena::new(); + x[h] = 12; + assert_eq!(Some(12), x.get(h).cloned()); + + x.clear(); + x[h] = 7; + assert_eq!(Some(7), x.get(h).cloned()); +} From 3696992ed06c7a40ca4eff849eda7b290dbf8950 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 14 Nov 2023 17:29:36 +0100 Subject: [PATCH 251/500] Use truncate instead --- stack-graphs/src/arena.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/stack-graphs/src/arena.rs b/stack-graphs/src/arena.rs index 18009db02..134a90d14 100644 --- a/stack-graphs/src/arena.rs +++ b/stack-graphs/src/arena.rs @@ -185,8 +185,7 @@ impl Arena { /// the arena are invalid. #[inline(always)] pub fn clear(&mut self) { - self.items.clear(); - self.items.push(MaybeUninit::uninit()); + self.items.truncate(1); } /// Adds a new instance to this arena, returning a stable handle to it. @@ -292,8 +291,7 @@ impl SupplementalArena { /// all previous handles into the arena are invalid. #[inline(always)] pub fn clear(&mut self) { - self.items.clear(); - self.items.push(MaybeUninit::uninit()); + self.items.truncate(1); } /// Creates a new, empty supplemental arena, preallocating enough space to store supplemental From 64739d3889f84a464e898f42c26a860753f16586 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 14 Nov 2023 13:15:40 -0800 Subject: [PATCH 252/500] Add definiens to guard exports Co-Authored-By: Rob Rix --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 0d2a73c18..87ae4e8db 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -346,6 +346,7 @@ inherit .return_or_yield attr (@prog.after_scope) empty_source_span attr (prog_exports_pop) pop_symbol = "GUARD:EXPORTS" + attr (prog_exports_pop) definiens_node = @prog edge module_pop_end -> prog_exports_pop edge prog_exports_pop -> @prog.exports From 16e008e51bf6596df0ac8a19770c274707c5c7f2 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 14 Nov 2023 13:32:00 -0800 Subject: [PATCH 253/500] Try modifying the package processor instead? Co-Authored-By: Rob Rix --- .../rust/npm_package.rs | 33 ++++++++++++++----- .../rust/util.rs | 1 + .../src/stack-graphs.tsg | 1 - 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs index ddaa952cc..3ce18aa07 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs @@ -104,6 +104,16 @@ impl FileAnalyzer for NpmPackageAnalyzer { ); add_edge(graph, pkg_name_pop, pkg_internal_name_push, 0); + // Common main + let main = Some(npm_pkg.main) + .filter(|main| !main.is_empty()) + .and_then(|main| NormalizedRelativePath::from_str(&main)) + .map(|p| p.into_path_buf()) + .unwrap_or(PathBuf::from("index")) + .with_extension(""); + let main_push = + add_module_pushes(graph, file, &main, pkg_internal_name_push, "main_push"); + // reach main exports directly via package name (with precedence) // // [pop pkg_name] -1-> [pop "GUARD:EXPORTS"] -> [push "GUARD:EXPORTS"] -> [push main]* -> [push pkg_internal_name] @@ -115,17 +125,24 @@ impl FileAnalyzer for NpmPackageAnalyzer { EXPORTS_GUARD, "exports_guard_pop", ); - let main = Some(npm_pkg.main) - .filter(|main| !main.is_empty()) - .and_then(|main| NormalizedRelativePath::from_str(&main)) - .map(|p| p.into_path_buf()) - .unwrap_or(PathBuf::from("index")) - .with_extension(""); - let main_push = - add_module_pushes(graph, file, &main, pkg_internal_name_push, "main_push"); let exports_guard_push = add_push(graph, file, main_push, EXPORTS_GUARD, "exports_guard_push"); add_edge(graph, exports_guard_pop, exports_guard_push, 0); + + // reach main exports directly via package name (with precedence) + // + // [pop pkg_name] -1-> [pop "GUARD:DEFAULT"] -> [push "GUARD:DEFAULT"] -> [push main]* -> [push pkg_internal_name] + // + let default_guard_pop = add_pop( + graph, + file, + pkg_name_pop, + DEFAULT_GUARD, + "default_guard_pop", + ); + let default_guard_push = + add_push(graph, file, main_push, DEFAULT_GUARD, "default_guard_push"); + add_edge(graph, default_guard_pop, default_guard_push, 0); } // reach dependencies via package internal name diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/util.rs b/languages/tree-sitter-stack-graphs-javascript/rust/util.rs index 17ab8d779..1e0c14019 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/util.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/util.rs @@ -15,6 +15,7 @@ use stack_graphs::graph::File; use stack_graphs::graph::StackGraph; pub const EXPORTS_GUARD: &str = "GUARD:EXPORTS"; +pub const DEFAULT_GUARD: &str = "GUARD:DEFAULT"; pub const PKG_GUARD: &str = "GUARD:PKG"; pub const PKG_INTERNAL_GUARD: &str = "GUARD:PKG_INTERNAL"; diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 87ae4e8db..0d2a73c18 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -346,7 +346,6 @@ inherit .return_or_yield attr (@prog.after_scope) empty_source_span attr (prog_exports_pop) pop_symbol = "GUARD:EXPORTS" - attr (prog_exports_pop) definiens_node = @prog edge module_pop_end -> prog_exports_pop edge prog_exports_pop -> @prog.exports From 188090be872b76b4ced85cce69f3f94bbe4544b7 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 14 Nov 2023 13:40:55 -0800 Subject: [PATCH 254/500] Add default pop Co-Authored-By: Rob Rix --- .../tree-sitter-stack-graphs-javascript/rust/npm_package.rs | 2 +- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs index 3ce18aa07..01095022e 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs @@ -129,7 +129,7 @@ impl FileAnalyzer for NpmPackageAnalyzer { add_push(graph, file, main_push, EXPORTS_GUARD, "exports_guard_push"); add_edge(graph, exports_guard_pop, exports_guard_push, 0); - // reach main exports directly via package name (with precedence) + // reach main default directly via package name (with precedence) // // [pop pkg_name] -1-> [pop "GUARD:DEFAULT"] -> [push "GUARD:DEFAULT"] -> [push main]* -> [push pkg_internal_name] // diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 0d2a73c18..61e17ad4e 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -349,6 +349,10 @@ inherit .return_or_yield edge module_pop_end -> prog_exports_pop edge prog_exports_pop -> @prog.exports + node prog_default_pop + attr (prog_default_pop) pop_symbol = "GUARD:DEFAULT", definiens_node = @prog + edge module_pop_end -> prog_default_pop + ;; builtin types node @prog.builtins_number node @prog.builtins_string From e884c34d98156eb35c3ae31864e8ce14fd53997b Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 14 Nov 2023 14:05:50 -0800 Subject: [PATCH 255/500] Restructure graph? Co-Authored-By: Rob Rix --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 61e17ad4e..240725978 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -351,7 +351,7 @@ inherit .return_or_yield node prog_default_pop attr (prog_default_pop) pop_symbol = "GUARD:DEFAULT", definiens_node = @prog - edge module_pop_end -> prog_default_pop + edge prog_exports_pop -> prog_default_pop ;; builtin types node @prog.builtins_number From e98eb0da4c2834528d85f71ede09776be50185d9 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 14 Nov 2023 14:24:43 -0800 Subject: [PATCH 256/500] Remove unnecessary default?? Co-Authored-By: Rob Rix --- .../rust/npm_package.rs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs index 01095022e..236d23f96 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs @@ -128,21 +128,6 @@ impl FileAnalyzer for NpmPackageAnalyzer { let exports_guard_push = add_push(graph, file, main_push, EXPORTS_GUARD, "exports_guard_push"); add_edge(graph, exports_guard_pop, exports_guard_push, 0); - - // reach main default directly via package name (with precedence) - // - // [pop pkg_name] -1-> [pop "GUARD:DEFAULT"] -> [push "GUARD:DEFAULT"] -> [push main]* -> [push pkg_internal_name] - // - let default_guard_pop = add_pop( - graph, - file, - pkg_name_pop, - DEFAULT_GUARD, - "default_guard_pop", - ); - let default_guard_push = - add_push(graph, file, main_push, DEFAULT_GUARD, "default_guard_push"); - add_edge(graph, default_guard_pop, default_guard_push, 0); } // reach dependencies via package internal name From eb6657eb4c53ad085aa555332e22a5c614536083 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Wed, 15 Nov 2023 10:21:24 -0800 Subject: [PATCH 257/500] Remove no-longer-needed DEFAULT_GUARD var Co-Authored-By: Rob Rix --- languages/tree-sitter-stack-graphs-javascript/rust/util.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/util.rs b/languages/tree-sitter-stack-graphs-javascript/rust/util.rs index 1e0c14019..17ab8d779 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/util.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/util.rs @@ -15,7 +15,6 @@ use stack_graphs::graph::File; use stack_graphs::graph::StackGraph; pub const EXPORTS_GUARD: &str = "GUARD:EXPORTS"; -pub const DEFAULT_GUARD: &str = "GUARD:DEFAULT"; pub const PKG_GUARD: &str = "GUARD:PKG"; pub const PKG_INTERNAL_GUARD: &str = "GUARD:PKG_INTERNAL"; From fb9dc1c4bdc0cc88f219ccbe73ff658cac12d7ff Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Wed, 15 Nov 2023 11:20:59 -0800 Subject: [PATCH 258/500] More debugging! Co-Authored-By: Rob Rix --- .../tree-sitter-stack-graphs-javascript/rust/npm_package.rs | 6 ++++++ .../src/stack-graphs.tsg | 4 ---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs index 236d23f96..6adbd753a 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs @@ -128,6 +128,12 @@ impl FileAnalyzer for NpmPackageAnalyzer { let exports_guard_push = add_push(graph, file, main_push, EXPORTS_GUARD, "exports_guard_push"); add_edge(graph, exports_guard_pop, exports_guard_push, 0); + + // reach main directly via package name (with precedence) + // + // [pop pkg_name] -1-> [push main]* -> [push pkg_internal_name] + // + add_edge(graph, pkg_name_pop, main_push, 0); } // reach dependencies via package internal name diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 240725978..0d2a73c18 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -349,10 +349,6 @@ inherit .return_or_yield edge module_pop_end -> prog_exports_pop edge prog_exports_pop -> @prog.exports - node prog_default_pop - attr (prog_default_pop) pop_symbol = "GUARD:DEFAULT", definiens_node = @prog - edge prog_exports_pop -> prog_default_pop - ;; builtin types node @prog.builtins_number node @prog.builtins_string From 7d71397c7dd98607349482b5c4b28e1dff25fc8e Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Wed, 15 Nov 2023 11:35:05 -0800 Subject: [PATCH 259/500] Removes unneeded guard exports in package.json Co-Authored-By: Rob Rix --- .../rust/npm_package.rs | 15 --------------- .../rust/util.rs | 1 - 2 files changed, 16 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs index 6adbd753a..6c346ccd4 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs @@ -114,21 +114,6 @@ impl FileAnalyzer for NpmPackageAnalyzer { let main_push = add_module_pushes(graph, file, &main, pkg_internal_name_push, "main_push"); - // reach main exports directly via package name (with precedence) - // - // [pop pkg_name] -1-> [pop "GUARD:EXPORTS"] -> [push "GUARD:EXPORTS"] -> [push main]* -> [push pkg_internal_name] - // - let exports_guard_pop = add_pop( - graph, - file, - pkg_name_pop, - EXPORTS_GUARD, - "exports_guard_pop", - ); - let exports_guard_push = - add_push(graph, file, main_push, EXPORTS_GUARD, "exports_guard_push"); - add_edge(graph, exports_guard_pop, exports_guard_push, 0); - // reach main directly via package name (with precedence) // // [pop pkg_name] -1-> [push main]* -> [push pkg_internal_name] diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/util.rs b/languages/tree-sitter-stack-graphs-javascript/rust/util.rs index 17ab8d779..c57c409b3 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/util.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/util.rs @@ -14,7 +14,6 @@ use stack_graphs::arena::Handle; use stack_graphs::graph::File; use stack_graphs::graph::StackGraph; -pub const EXPORTS_GUARD: &str = "GUARD:EXPORTS"; pub const PKG_GUARD: &str = "GUARD:PKG"; pub const PKG_INTERNAL_GUARD: &str = "GUARD:PKG_INTERNAL"; From 33883c4637b5c75cf49531c61c0569c35886f95e Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Sat, 11 Nov 2023 14:36:57 +0100 Subject: [PATCH 260/500] Remove unused module guard --- .../src/stack-graphs.tsg | 6 ------ 1 file changed, 6 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 640ec0976..e88db9778 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -230,7 +230,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; a connected subgraph that is never the less never traversed. ;; - `GUARD:LABEL` - used for the names of labels ;; - `GUARD:MEMBER` - used for the members/fields/properties of objects -;; - `GUARD:MODULE` - used for the final scope of the module ;; - `GUARD:RETURN` - used for the AST nodes for values returned by a function ;; in the function body ;; - `GUARD:THIS` - used for the implicit `this` argument of a function inside @@ -289,7 +288,6 @@ inherit .return_or_yield (program)@prog { node prog_module_pop - node prog_module_scope node prog_exports_pop node prog_pkg_pop_guard node prog_pkg_push_guard @@ -328,17 +326,13 @@ inherit .return_or_yield edge @prog.before_scope -> @prog.pkg_push edge @prog.before_scope -> @prog.hoist_point - attr (prog_module_scope) pop_symbol = "GUARD:MODULE" edge @prog.pkg_pop -> prog_module_pop_start - edge module_pop_end -> prog_module_scope - edge prog_module_scope -> @prog.after_scope attr (prog_legacy_qname_guard) push_symbol = "GUARD:LEGACY_QNAME" edge @prog.before_scope -> prog_legacy_qname_guard edge prog_legacy_qname_guard -> ROOT_NODE attr (prog_module_pop) empty_source_span - attr (prog_module_scope) empty_source_span attr (@prog.exports) empty_source_span attr (prog_exports_pop) empty_source_span attr (@prog.before_scope) empty_source_span From 80b5d61e270e0176fdcff14089e1afcefd5137ad Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Sat, 11 Nov 2023 17:25:02 +0100 Subject: [PATCH 261/500] Guard module names --- .../rust/npm_package.rs | 18 ++++++++++++------ .../rust/util.rs | 4 ++++ .../src/stack-graphs.tsg | 13 +++++++++++-- .../variable_resolves_to_module.js | 4 ++++ 4 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/variable_resolves_to_module.js diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs index ddaa952cc..e3fb50411 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/npm_package.rs @@ -61,7 +61,6 @@ impl FileAnalyzer for NpmPackageAnalyzer { pkg_internal_name, "pkg_internal_name_pop", ); - // reach package internals via root // // [push pkg_internal_name] -> [push "GUARD:PKG_INTERNAL"] -> [root] @@ -83,13 +82,21 @@ impl FileAnalyzer for NpmPackageAnalyzer { // reach exports via package name // - // [root] -> [pop "GUARD:PKG"] -> [pop PKG_NAME]* -> [push PKG_INTERNAL_NAME] -> [push "GUARD:PKG_INTERNAL"] -> [root] + // [root] -> [pop "GUARD:PKG"] -> [pop PKG_NAME]* -> [push "GUARD:MODULE"] -> [push PKG_INTERNAL_NAME] -> [push "GUARD:PKG_INTERNAL"] -> [root] // if !npm_pkg.name.is_empty() { // NOTE Because all modules expose their exports at the top-level, both paths created below are equivalent for // exports of the main module. This means multiple equivalent paths to those exports, which is bad for // performance. At the moment, we have no mechanism to prevent this from happening. + let module_guard = add_push( + graph, + file, + pkg_internal_name_push, + MODULE_GUARD, + "main_guard", + ); + // reach package internals via package name // // [root] -> [pop "GUARD:PKG"] -> [pop pkg_name]* -> [push pkg_internal_name] @@ -102,11 +109,11 @@ impl FileAnalyzer for NpmPackageAnalyzer { pkg_guard_pop, "pkg_name_pop", ); - add_edge(graph, pkg_name_pop, pkg_internal_name_push, 0); + add_edge(graph, pkg_name_pop, module_guard, 0); // reach main exports directly via package name (with precedence) // - // [pop pkg_name] -1-> [pop "GUARD:EXPORTS"] -> [push "GUARD:EXPORTS"] -> [push main]* -> [push pkg_internal_name] + // [pop pkg_name] -1-> [pop "GUARD:EXPORTS"] -> [push "GUARD:EXPORTS"] -> [push main]* -> [push "GUARD:MODULE"] -> [push pkg_internal_name] // let exports_guard_pop = add_pop( graph, @@ -121,8 +128,7 @@ impl FileAnalyzer for NpmPackageAnalyzer { .map(|p| p.into_path_buf()) .unwrap_or(PathBuf::from("index")) .with_extension(""); - let main_push = - add_module_pushes(graph, file, &main, pkg_internal_name_push, "main_push"); + let main_push = add_module_pushes(graph, file, &main, module_guard, "main_push"); let exports_guard_push = add_push(graph, file, main_push, EXPORTS_GUARD, "exports_guard_push"); add_edge(graph, exports_guard_pop, exports_guard_push, 0); diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/util.rs b/languages/tree-sitter-stack-graphs-javascript/rust/util.rs index 17ab8d779..02b094005 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/util.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/util.rs @@ -15,10 +15,14 @@ use stack_graphs::graph::File; use stack_graphs::graph::StackGraph; pub const EXPORTS_GUARD: &str = "GUARD:EXPORTS"; +pub const MODULE_GUARD: &str = "GUARD:MODULE"; pub const PKG_GUARD: &str = "GUARD:PKG"; pub const PKG_INTERNAL_GUARD: &str = "GUARD:PKG_INTERNAL"; pub fn add_debug_name(graph: &mut StackGraph, node: Handle, name: &str) { + if name.is_empty() { + return; + } let key = graph.add_string("name"); let value = graph.add_string(name); graph.node_debug_info_mut(node).add(key, value); diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index e88db9778..4ab571db9 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -230,6 +230,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; a connected subgraph that is never the less never traversed. ;; - `GUARD:LABEL` - used for the names of labels ;; - `GUARD:MEMBER` - used for the members/fields/properties of objects +;; - `GUARD:MODULE` - used for module names ;; - `GUARD:RETURN` - used for the AST nodes for values returned by a function ;; in the function body ;; - `GUARD:THIS` - used for the implicit `this` argument of a function inside @@ -307,7 +308,12 @@ inherit .return_or_yield edge @prog.pkg_push -> prog_pkg_push_guard edge prog_pkg_push_guard -> ROOT_NODE + node module_guard_pop + attr (module_guard_pop) pop_symbol = "GUARD:MODULE" + edge @prog.pkg_pop -> module_guard_pop + node prog_module_pop_start + edge module_guard_pop -> prog_module_pop_start var module_pop_end = prog_module_pop_start let module_name = (replace FILE_PATH "\.js$" "") scan module_name { @@ -326,7 +332,6 @@ inherit .return_or_yield edge @prog.before_scope -> @prog.pkg_push edge @prog.before_scope -> @prog.hoist_point - edge @prog.pkg_pop -> prog_module_pop_start attr (prog_legacy_qname_guard) push_symbol = "GUARD:LEGACY_QNAME" edge @prog.before_scope -> prog_legacy_qname_guard @@ -826,7 +831,12 @@ inherit .return_or_yield ; relative import let name = (replace (path-normalize (path-join (path-dir FILE_PATH) $1)) "\.js$" "") + node module_guard_push + attr (module_guard_push) push_symbol = "GUARD:MODULE" + edge module_guard_push -> @source.pkg_push + node source_push_end + edge source_push_end -> module_guard_push var push_start = source_push_end scan name { "([^/]+)/" { @@ -850,7 +860,6 @@ inherit .return_or_yield attr (push_start) is_reference, source_node = @source edge source_push_guard_exports -> push_start - edge source_push_end -> @source.pkg_push } "^[\"']([^\./].*)[\"']$" { ; package import diff --git a/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/variable_resolves_to_module.js b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/variable_resolves_to_module.js new file mode 100644 index 000000000..e829ab7ff --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/old/bug_regressions/variable_resolves_to_module.js @@ -0,0 +1,4 @@ +/* --- path: debug.js --- */ + +/**/ debug(42); +// ^ defined: From 6784290074ea32a71ce964eea10b0b31519fa4a0 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 20 Nov 2023 13:29:31 +0100 Subject: [PATCH 262/500] Cleanup TypeScript tests and add two missing cases --- .../modules/import-directly-exported-variable.ts | 4 ++-- .../import-from-ambient-module-declaration.ts | 4 ++-- .../modules/import-from-own-direcotry-in-index.ts | 8 ++++++++ .../import-from-own-project-subdirectory.ts | 4 ++-- .../test/modules/import-from-subdirectory.ts | 4 ++-- .../test/modules/import-from-superdirectory.ts | 4 ++-- .../import-indirectly-exported-variable.ts | 4 ++-- ...ug => import-relative-to-project-root.ts.skip} | 4 ++-- .../test/modules/import-via-index.ts | 4 ++-- .../test/modules/import-via-superdirectory.ts | 4 ++-- .../test/modules/import-via-two-reexports.ts | 15 +++++++++++++++ .../rename-imported-directly-exported-variable.ts | 4 ++-- ...ename-imported-indirectly-exported-variable.ts | 4 ++-- .../package-invisible-without-dependency.ts | 12 ++++++------ .../test/projects/baseurl-to-subdir.ts | 6 +++--- .../test/projects/composite-project.ts | 6 +++--- .../test/projects/declarations-are-ignored.ts | 8 ++++---- .../test/projects/exclude-second-subdir.ts | 8 ++++---- .../test/projects/explicit-root-dir.ts | 6 +++--- .../test/projects/import-from-rootdirs-subdir.ts | 10 +++++----- .../test/projects/import-from-rootdirs.ts | 10 +++++----- .../projects/import-with-own-project-baseurl.ts | 6 +++--- .../test/projects/include-one-subdir.ts | 8 ++++---- .../test/projects/invalid-paths-mappings.ts | 2 +- .../test/projects/js-sources-are-ignored.ts.skip | 8 ++++---- .../projects/js-sources-can-be-allowed.ts.skip | 8 ++++---- .../projects/non-relative-single-module-remap.ts | 6 +++--- .../test/projects/non-relative-star-remap.ts | 6 +++--- .../test/projects/non-relative-star-remaps.ts | 6 +++--- .../test/projects/one-file-in-subdir.ts | 8 ++++---- .../package-dependency-with-nested-source-root.ts | 12 ++++++------ .../test/projects/relative-import.ts | 6 +++--- .../test/projects/relative-single-module-remap.ts | 6 +++--- .../test/projects/relative-star-remap.ts | 6 +++--- .../test/projects/remap-with-baseurl.ts | 6 +++--- .../test/projects/sources-in-multiple-subdirs.ts | 8 ++++---- .../test/projects/sources-in-one-subdir.ts | 6 +++--- 37 files changed, 132 insertions(+), 109 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-own-direcotry-in-index.ts rename languages/tree-sitter-stack-graphs-typescript/test/modules/{import-relative-to-project-root.ts.bug => import-relative-to-project-root.ts.skip} (55%) create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/modules/import-via-two-reexports.ts diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-directly-exported-variable.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-directly-exported-variable.ts index bd6a1126b..91e5da6c7 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-directly-exported-variable.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-directly-exported-variable.ts @@ -1,10 +1,10 @@ -/*--- path: ./ModA.ts ---*/ +/*--- path: ModA.ts ---*/ export let a = { v: 42 }; -/*--- path: ./ModB.ts ---*/ +/*--- path: ModB.ts ---*/ import { a } from "./ModA"; // ^ defined: 3 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-ambient-module-declaration.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-ambient-module-declaration.ts index 75aff4238..abef61e5e 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-ambient-module-declaration.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-ambient-module-declaration.ts @@ -1,8 +1,8 @@ -/* --- path: ./index.ts --- */ +/* --- path: index.ts --- */ import { foo } from "@my/lib"; // ^ defined: 8 -/* --- path: ./mod.ts --- */ +/* --- path: mod.ts --- */ declare module "@my/lib" { export const foo = 42; diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-own-direcotry-in-index.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-own-direcotry-in-index.ts new file mode 100644 index 000000000..b62a2fe45 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-own-direcotry-in-index.ts @@ -0,0 +1,8 @@ +/*--- path: foo/index.ts ---*/ + +import { FOO } from "./bar"; +// ^ defined: 8 + +/*--- path: foo/bar.ts ---*/ + +export const FOO = 42; diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-own-project-subdirectory.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-own-project-subdirectory.ts index 2d399830c..743efa90a 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-own-project-subdirectory.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-own-project-subdirectory.ts @@ -1,11 +1,11 @@ -/*--- path: ./A/ModA.ts ---*/ +/*--- path: A/ModA.ts ---*/ /*--- global: PROJECT_NAME=foo/bar ---*/ export let a = { v: 42 }; -/*--- path: ./ModB.ts ---*/ +/*--- path: ModB.ts ---*/ /*--- global: PROJECT_NAME=foo/bar ---*/ import { a } from "./A/ModA"; diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-subdirectory.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-subdirectory.ts index 19e6c03b2..11292dff4 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-subdirectory.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-subdirectory.ts @@ -1,10 +1,10 @@ -/*--- path: ./A/ModA.ts ---*/ +/*--- path: A/ModA.ts ---*/ export let a = { v: 42 }; -/*--- path: ./ModB.ts ---*/ +/*--- path: ModB.ts ---*/ import { a } from "./A/ModA"; // ^ defined: 3 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-superdirectory.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-superdirectory.ts index bf7865e08..8f728d91c 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-superdirectory.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-from-superdirectory.ts @@ -1,10 +1,10 @@ -/*--- path: ./ModA.ts ---*/ +/*--- path: ModA.ts ---*/ export let a = { v: 42 }; -/*--- path: ./B/ModB.ts ---*/ +/*--- path: B/ModB.ts ---*/ import { a } from "../ModA"; // ^ defined: 3 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-indirectly-exported-variable.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-indirectly-exported-variable.ts index 3676bf85c..e2906595e 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-indirectly-exported-variable.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-indirectly-exported-variable.ts @@ -1,4 +1,4 @@ -/*--- path: ./ModA.ts ---*/ +/*--- path: ModA.ts ---*/ let a = { v: 42 @@ -7,7 +7,7 @@ let a = { export { a }; // ^ defined: 3 -/*--- path: ./ModB.ts ---*/ +/*--- path: ModB.ts ---*/ import { a } from "./ModA"; // ^ defined: 7, 3 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-relative-to-project-root.ts.bug b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-relative-to-project-root.ts.skip similarity index 55% rename from languages/tree-sitter-stack-graphs-typescript/test/modules/import-relative-to-project-root.ts.bug rename to languages/tree-sitter-stack-graphs-typescript/test/modules/import-relative-to-project-root.ts.skip index c3a2589da..eed68b4ee 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-relative-to-project-root.ts.bug +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-relative-to-project-root.ts.skip @@ -1,8 +1,8 @@ -/*--- path: ./ModA.ts ---*/ +/*--- path: ModA.ts ---*/ export const a = 42; -/*--- path: ./B/ModB.ts ---*/ +/*--- path: B/ModB.ts ---*/ import { a } from "./ModA"; // ^ defined: \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-via-index.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-via-index.ts index ef0504741..3730b1b73 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-via-index.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-via-index.ts @@ -1,10 +1,10 @@ -/*--- path: ./A/index.ts ---*/ +/*--- path: A/index.ts ---*/ export let a = { v: 42 }; -/*--- path: ./B/ModB.ts ---*/ +/*--- path: B/ModB.ts ---*/ import { a } from "../A"; // ^ defined: 3 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-via-superdirectory.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-via-superdirectory.ts index 332d6474d..a67e79311 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-via-superdirectory.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-via-superdirectory.ts @@ -1,10 +1,10 @@ -/*--- path: ./A/ModA.ts ---*/ +/*--- path: A/ModA.ts ---*/ export let a = { v: 42 }; -/*--- path: ./B/ModB.ts ---*/ +/*--- path: B/ModB.ts ---*/ import { a } from "../A/ModA"; // ^ defined: 3 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-via-two-reexports.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-via-two-reexports.ts new file mode 100644 index 000000000..981e3d15d --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-via-two-reexports.ts @@ -0,0 +1,15 @@ +/* --- path: src/foo/index.ts --- */ + +export * from "../bar"; + +/* --- path: src/bar/index.ts --- */ + +export * from "./quz"; + +/* --- path: src/bar/quz.ts --- */ + +export const QUZ = 42; + +/* --- path: src/test.ts --- */ + +import { QUZ } from "./foo"; diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/rename-imported-directly-exported-variable.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/rename-imported-directly-exported-variable.ts index f3b403494..ecfdc2d2c 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/modules/rename-imported-directly-exported-variable.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/rename-imported-directly-exported-variable.ts @@ -1,10 +1,10 @@ -/*--- path: ./ModA.ts ---*/ +/*--- path: ModA.ts ---*/ export let a = { v: 42 }; -/*--- path: ./ModB.ts ---*/ +/*--- path: ModB.ts ---*/ import { a as b } from "./ModA"; // ^ defined: 3 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/rename-imported-indirectly-exported-variable.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/rename-imported-indirectly-exported-variable.ts index 48f62099e..e1e99db34 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/modules/rename-imported-indirectly-exported-variable.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/rename-imported-indirectly-exported-variable.ts @@ -1,4 +1,4 @@ -/*--- path: ./ModA.ts ---*/ +/*--- path: ModA.ts ---*/ let a = { v: 42 @@ -7,7 +7,7 @@ let a = { export { a }; // ^ defined: 3 -/*--- path: ./ModB.ts ---*/ +/*--- path: ModB.ts ---*/ import { a as b } from "./ModA"; // ^ defined: 7, 3 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/packages/package-invisible-without-dependency.ts b/languages/tree-sitter-stack-graphs-typescript/test/packages/package-invisible-without-dependency.ts index c7c0458ff..87248abe2 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/packages/package-invisible-without-dependency.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/packages/package-invisible-without-dependency.ts @@ -1,4 +1,4 @@ -/* --- path: ./my_lib/package.json --- */ +/* --- path: my_lib/package.json --- */ /* --- global: FILE_PATH=package.json --- */ /* --- global: PROJECT_NAME=my_lib --- */ @@ -6,19 +6,19 @@ "name": "@my/lib" } -/* --- path: ./my_lib/tsconfig.json --- */ +/* --- path: my_lib/tsconfig.json --- */ /* --- global: FILE_PATH=tsconfig.json --- */ /* --- global: PROJECT_NAME=my_lib --- */ {} -/* --- path: ./my_lib/src/foo.ts --- */ +/* --- path: my_lib/src/foo.ts --- */ /* --- global: FILE_PATH=src/foo.ts --- */ /* --- global: PROJECT_NAME=my_lib --- */ export const bar = 42; -/* --- path: ./my_app/package.json --- */ +/* --- path: my_app/package.json --- */ /* --- global: FILE_PATH=package.json --- */ /* --- global: PROJECT_NAME=my_app --- */ @@ -26,13 +26,13 @@ export const bar = 42; "name": "@my/app" } -/* --- path: ./my_app/tsconfig.json --- */ +/* --- path: my_app/tsconfig.json --- */ /* --- global: FILE_PATH=tsconfig.json --- */ /* --- global: PROJECT_NAME=my_app --- */ {} -/* --- path: ./my_app/src/index.ts --- */ +/* --- path: my_app/src/index.ts --- */ /* --- global: FILE_PATH=src/index.ts --- */ /* --- global: PROJECT_NAME=my_app --- */ diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/baseurl-to-subdir.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/baseurl-to-subdir.ts index a867d24b1..80f5a00d4 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/baseurl-to-subdir.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/baseurl-to-subdir.ts @@ -1,4 +1,4 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { "compilerOptions": { "composite": true, @@ -6,9 +6,9 @@ } } -/* --- path: ./src/foo.ts --- */ +/* --- path: src/foo.ts --- */ export const bar = 42; -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ import { bar } from "foo"; // ^ defined: 10 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/composite-project.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/composite-project.ts index 732536dbf..e7fd1b57d 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/composite-project.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/composite-project.ts @@ -1,13 +1,13 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { "compilerOptions": { "composite": true, } } -/* --- path: ./src/foo.ts --- */ +/* --- path: src/foo.ts --- */ export const bar = 42; -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ import { bar } from "./foo"; // ^ defined: 9 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/declarations-are-ignored.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/declarations-are-ignored.ts index 27cf54427..8c3d2a6b5 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/declarations-are-ignored.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/declarations-are-ignored.ts @@ -1,12 +1,12 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { } -/* --- path: ./src/foo.ts --- */ +/* --- path: src/foo.ts --- */ export const bar = 42; -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ import { bar } from "./foo"; // ^ defined: 6 -/* --- path: ./types/index.d.ts --- */ +/* --- path: types/index.d.ts --- */ diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/exclude-second-subdir.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/exclude-second-subdir.ts index 083f0293b..326557cc7 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/exclude-second-subdir.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/exclude-second-subdir.ts @@ -1,13 +1,13 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { "exclude": ["test/**/*"] } -/* --- path: ./src/foo.ts --- */ +/* --- path: src/foo.ts --- */ export const bar = 42; -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ import { bar } from "./foo"; // ^ defined: 7 -/* --- path: ./test/index.ts --- */ +/* --- path: test/index.ts --- */ diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/explicit-root-dir.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/explicit-root-dir.ts index c51108621..37dbade29 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/explicit-root-dir.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/explicit-root-dir.ts @@ -1,13 +1,13 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { "compilerOptions": { "rootDir": "." } } -/* --- path: ./core/foo.ts --- */ +/* --- path: core/foo.ts --- */ export const bar = 42; -/* --- path: ./core/index.ts --- */ +/* --- path: core/index.ts --- */ import { bar } from "./foo"; // ^ defined: 9 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/import-from-rootdirs-subdir.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/import-from-rootdirs-subdir.ts index 6c8715cec..5c9d2c896 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/import-from-rootdirs-subdir.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/import-from-rootdirs-subdir.ts @@ -1,4 +1,4 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { "compilerOptions": { "rootDirs": [ @@ -8,13 +8,13 @@ } } -/* --- path: ./src/core/index.ts --- */ +/* --- path: src/core/index.ts --- */ import { bar } from "./foo/baz"; // ^ defined: 16 -/* --- path: ./src/util/foo/baz.ts --- */ +/* --- path: src/util/foo/baz.ts --- */ export const bar = 42; -/* --- path: ./src/util/index.ts --- */ +/* --- path: src/util/index.ts --- */ -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/import-from-rootdirs.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/import-from-rootdirs.ts index d7720e510..7603a8f91 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/import-from-rootdirs.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/import-from-rootdirs.ts @@ -1,4 +1,4 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { "compilerOptions": { "rootDirs": [ @@ -8,13 +8,13 @@ } } -/* --- path: ./src/core/index.ts --- */ +/* --- path: src/core/index.ts --- */ import { bar } from "./foo"; // ^ defined: 16 -/* --- path: ./src/util/foo.ts --- */ +/* --- path: src/util/foo.ts --- */ export const bar = 42; -/* --- path: ./src/util/index.ts --- */ +/* --- path: src/util/index.ts --- */ -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/import-with-own-project-baseurl.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/import-with-own-project-baseurl.ts index 29c2892d8..1e40e23db 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/import-with-own-project-baseurl.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/import-with-own-project-baseurl.ts @@ -1,4 +1,4 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ /* --- global: PROJECT_NAME=a --- */ { "compilerOptions": { @@ -7,11 +7,11 @@ } } -/* --- path: ./src/foo.ts --- */ +/* --- path: src/foo.ts --- */ /* --- global: PROJECT_NAME=a --- */ export const bar = 42; -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ /* --- global: PROJECT_NAME=a --- */ import { bar } from "foo"; // ^ defined: 12 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/include-one-subdir.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/include-one-subdir.ts index 42f991b95..8aed79105 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/include-one-subdir.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/include-one-subdir.ts @@ -1,13 +1,13 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { "include": ["src/**/*"] } -/* --- path: ./src/foo.ts --- */ +/* --- path: src/foo.ts --- */ export const bar = 42; -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ import { bar } from "./foo"; // ^ defined: 7 -/* --- path: ./test/index.ts --- */ +/* --- path: test/index.ts --- */ diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/invalid-paths-mappings.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/invalid-paths-mappings.ts index 6e422f928..926f28e97 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/invalid-paths-mappings.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/invalid-paths-mappings.ts @@ -1,4 +1,4 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { "compilerOptions": { "paths": { diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/js-sources-are-ignored.ts.skip b/languages/tree-sitter-stack-graphs-typescript/test/projects/js-sources-are-ignored.ts.skip index 3ad81a358..21f8fae85 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/js-sources-are-ignored.ts.skip +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/js-sources-are-ignored.ts.skip @@ -1,12 +1,12 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { } -/* --- path: ./lib/index.js --- */ +/* --- path: lib/index.js --- */ -/* --- path: ./src/foo.ts --- */ +/* --- path: src/foo.ts --- */ export const bar = 42; -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ import { bar } from "./foo"; // ^ defined: 8 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/js-sources-can-be-allowed.ts.skip b/languages/tree-sitter-stack-graphs-typescript/test/projects/js-sources-can-be-allowed.ts.skip index 1b4bd4619..ed304a1b9 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/js-sources-can-be-allowed.ts.skip +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/js-sources-can-be-allowed.ts.skip @@ -1,15 +1,15 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { "compilerOptions": { "allowJs": true } } -/* --- path: ./lib/index.js --- */ +/* --- path: lib/index.js --- */ -/* --- path: ./src/foo.ts --- */ +/* --- path: src/foo.ts --- */ export const bar = 42; -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ import { bar } from "./foo"; // ^ defined: 11 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/non-relative-single-module-remap.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/non-relative-single-module-remap.ts index c948f40ee..64036fc0d 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/non-relative-single-module-remap.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/non-relative-single-module-remap.ts @@ -1,4 +1,4 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { "compilerOptions": { "composite": true, @@ -9,9 +9,9 @@ } } -/* --- path: ./lib/the_foo.ts --- */ +/* --- path: lib/the_foo.ts --- */ export const bar = 42; -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ import { bar } from "foo"; // ^ defined: 13 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/non-relative-star-remap.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/non-relative-star-remap.ts index 2d0c07608..5961eeffa 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/non-relative-star-remap.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/non-relative-star-remap.ts @@ -1,4 +1,4 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { "compilerOptions": { "composite": true, @@ -9,9 +9,9 @@ } } -/* --- path: ./lib/foo.ts --- */ +/* --- path: lib/foo.ts --- */ export const bar = 42; -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ import { bar } from "foo"; // ^ defined: 13 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/non-relative-star-remaps.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/non-relative-star-remaps.ts index f8146cf96..6d3e26955 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/non-relative-star-remaps.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/non-relative-star-remaps.ts @@ -1,4 +1,4 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { "compilerOptions": { "composite": true, @@ -9,9 +9,9 @@ } } -/* --- path: ./ext/foo.ts --- */ +/* --- path: ext/foo.ts --- */ export const bar = 42; -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ import { bar } from "foo"; // ^ defined: 13 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/one-file-in-subdir.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/one-file-in-subdir.ts index 5b399e022..9aed45a39 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/one-file-in-subdir.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/one-file-in-subdir.ts @@ -1,13 +1,13 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { "files": ["src/index.ts"] } -/* --- path: ./src/foo.ts --- */ +/* --- path: src/foo.ts --- */ export const bar = 42; -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ import { bar } from "./foo"; // ^ defined: 7 -/* --- path: ./test/index.ts --- */ +/* --- path: test/index.ts --- */ diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/package-dependency-with-nested-source-root.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/package-dependency-with-nested-source-root.ts index f8b2a69fb..16215e31c 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/package-dependency-with-nested-source-root.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/package-dependency-with-nested-source-root.ts @@ -1,22 +1,22 @@ -/* --- path: ./my_lib/package.json --- */ +/* --- path: my_lib/package.json --- */ /* --- global: FILE_PATH=package.json --- */ /* --- global: PROJECT_NAME=my_lib --- */ { "name": "@my/lib" } -/* --- path: ./my_lib/tsconfig.json --- */ +/* --- path: my_lib/tsconfig.json --- */ /* --- global: FILE_PATH=tsconfig.json --- */ /* --- global: PROJECT_NAME=my_lib --- */ { } -/* --- path: ./my_lib/src/foo.ts --- */ +/* --- path: my_lib/src/foo.ts --- */ /* --- global: FILE_PATH=src/foo.ts --- */ /* --- global: PROJECT_NAME=my_lib --- */ export const bar = 42; -/* --- path: ./my_app/package.json --- */ +/* --- path: my_app/package.json --- */ /* --- global: FILE_PATH=package.json --- */ /* --- global: PROJECT_NAME=my_app --- */ { @@ -26,13 +26,13 @@ export const bar = 42; } } -/* --- path: ./my_app/tsconfig.json --- */ +/* --- path: my_app/tsconfig.json --- */ /* --- global: FILE_PATH=tsconfig.json --- */ /* --- global: PROJECT_NAME=my_app --- */ { } -/* --- path: ./my_app/src/index.ts --- */ +/* --- path: my_app/src/index.ts --- */ /* --- global: FILE_PATH=src/index.ts --- */ /* --- global: PROJECT_NAME=my_app --- */ import { bar } from "@my/lib/foo"; diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/relative-import.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/relative-import.ts index 1c2670335..e1951f3af 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/relative-import.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/relative-import.ts @@ -1,13 +1,13 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { "compilerOptions": { "composite": true } } -/* --- path: ./src/foo.ts --- */ +/* --- path: src/foo.ts --- */ export const bar = 42; -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ import { bar } from "./foo"; // ^ defined: 9 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/relative-single-module-remap.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/relative-single-module-remap.ts index 03ee84488..71b6ce834 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/relative-single-module-remap.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/relative-single-module-remap.ts @@ -1,4 +1,4 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { "compilerOptions": { "composite": true, @@ -8,9 +8,9 @@ } } -/* --- path: ./lib/the_foo.ts --- */ +/* --- path: lib/the_foo.ts --- */ export const bar = 42; -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ import { bar } from "foo"; // ^ defined: 12 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/relative-star-remap.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/relative-star-remap.ts index a116cfbbd..4a169c524 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/relative-star-remap.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/relative-star-remap.ts @@ -1,4 +1,4 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { "compilerOptions": { "composite": true, @@ -8,9 +8,9 @@ } } -/* --- path: ./lib/foo.ts --- */ +/* --- path: lib/foo.ts --- */ export const bar = 42; -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ import { bar } from "foo"; // ^ defined: 12 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/remap-with-baseurl.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/remap-with-baseurl.ts index 53d47534d..cf2788ba0 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/remap-with-baseurl.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/remap-with-baseurl.ts @@ -1,4 +1,4 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { "compilerOptions": { "composite": true, @@ -9,9 +9,9 @@ } } -/* --- path: ./src/util_impl/foo.ts --- */ +/* --- path: src/util_impl/foo.ts --- */ export const bar = 42; -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ import { bar } from "util/foo"; // ^ defined: 13 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/sources-in-multiple-subdirs.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/sources-in-multiple-subdirs.ts index e4248c32f..76d763b33 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/sources-in-multiple-subdirs.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/sources-in-multiple-subdirs.ts @@ -1,12 +1,12 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { } -/* --- path: ./src/foo.ts --- */ +/* --- path: src/foo.ts --- */ export const bar = 42; -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ import { bar } from "./foo"; // ^ defined: 6 -/* --- path: ./test/index.ts --- */ +/* --- path: test/index.ts --- */ diff --git a/languages/tree-sitter-stack-graphs-typescript/test/projects/sources-in-one-subdir.ts b/languages/tree-sitter-stack-graphs-typescript/test/projects/sources-in-one-subdir.ts index e97ea71ed..24a9a62ca 100644 --- a/languages/tree-sitter-stack-graphs-typescript/test/projects/sources-in-one-subdir.ts +++ b/languages/tree-sitter-stack-graphs-typescript/test/projects/sources-in-one-subdir.ts @@ -1,10 +1,10 @@ -/* --- path: ./tsconfig.json --- */ +/* --- path: tsconfig.json --- */ { } -/* --- path: ./src/foo.ts --- */ +/* --- path: src/foo.ts --- */ export const bar = 42; -/* --- path: ./src/index.ts --- */ +/* --- path: src/index.ts --- */ import { bar } from "./foo"; // ^ defined: 6 From 94ab2f9936ebb10df2504b92805dddd85a1c0970 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 27 Oct 2023 11:58:04 +0100 Subject: [PATCH 263/500] Ensure all viable root paths are loaded from database --- stack-graphs/src/stitching.rs | 101 +++++++++++++---- ...can_find_root_partial_paths_in_database.rs | 9 +- stack-graphs/tests/it/main.rs | 1 + stack-graphs/tests/it/stitching.rs | 104 ++++++++++++++++++ 4 files changed, 192 insertions(+), 23 deletions(-) create mode 100644 stack-graphs/tests/it/stitching.rs diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index 3d02a14be..6aade970d 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -284,7 +284,12 @@ pub struct Database { symbol_stack_keys: ListArena>, symbol_stack_key_cache: HashMap, paths_by_start_node: SupplementalArena>>, - root_paths_by_precondition: SupplementalArena>>, + root_paths_by_precondition_prefix: + SupplementalArena>>, + root_paths_by_precondition_with_variable: + SupplementalArena>>, + root_paths_by_precondition_without_variable: + SupplementalArena>>, incoming_paths: SupplementalArena, } @@ -297,7 +302,9 @@ impl Database { symbol_stack_keys: List::new_arena(), symbol_stack_key_cache: HashMap::new(), paths_by_start_node: SupplementalArena::new(), - root_paths_by_precondition: SupplementalArena::new(), + root_paths_by_precondition_prefix: SupplementalArena::new(), + root_paths_by_precondition_with_variable: SupplementalArena::new(), + root_paths_by_precondition_without_variable: SupplementalArena::new(), incoming_paths: SupplementalArena::new(), } } @@ -311,7 +318,9 @@ impl Database { self.symbol_stack_keys.clear(); self.symbol_stack_key_cache.clear(); self.paths_by_start_node.clear(); - self.root_paths_by_precondition.clear(); + self.root_paths_by_precondition_prefix.clear(); + self.root_paths_by_precondition_with_variable.clear(); + self.root_paths_by_precondition_without_variable.clear(); self.incoming_paths.clear(); } @@ -341,14 +350,21 @@ impl Database { if graph[start_node].is_root() { // The join node is root, so there's no need to use half-open symbol stacks here, as we // do for [`PartialPath::concatenate`][]. - let key = SymbolStackKey::from_partial_symbol_stack( + let mut key = SymbolStackKey::from_partial_symbol_stack( partials, self, symbol_stack_precondition, ); if !key.is_empty() { - let key_handle = key.back_handle(); - self.root_paths_by_precondition[key_handle].push(handle); + match symbol_stack_precondition.has_variable() { + true => self.root_paths_by_precondition_with_variable[key.back_handle()] + .push(handle), + false => self.root_paths_by_precondition_without_variable[key.back_handle()] + .push(handle), + } + } + while key.pop_back(self).is_some() && !key.is_empty() { + self.root_paths_by_precondition_prefix[key.back_handle()].push(handle); } } else { // Otherwise index it by its source node. @@ -374,12 +390,12 @@ impl Database { if graph[path.end_node].is_root() { // The join node is root, so there's no need to use half-open symbol stacks here, as we // do for [`PartialPath::concatenate`][]. - let key = SymbolStackKey::from_partial_symbol_stack( + self.find_candidate_partial_paths_from_root( + graph, partials, - self, - path.symbol_stack_postcondition, + Some(path.symbol_stack_postcondition), + result, ); - self.find_candidate_partial_paths_from_root(graph, partials, Some(key), result); } else { self.find_candidate_partial_paths_from_node(graph, partials, path.end_node, result); } @@ -392,7 +408,7 @@ impl Database { &mut self, graph: &StackGraph, partials: &mut PartialPaths, - symbol_stack: Option, + symbol_stack: Option, result: &mut R, ) where R: std::iter::Extend>, @@ -400,31 +416,76 @@ impl Database { // If the path currently ends at the root node, then we need to look up partial paths whose // symbol stack precondition is compatible with the path. match symbol_stack { - Some(mut symbol_stack) => loop { + Some(symbol_stack) => { + let mut key = + SymbolStackKey::from_partial_symbol_stack(partials, self, symbol_stack); copious_debugging!( " Search for symbol stack <{}>", - symbol_stack.display(graph, self) + key.display(graph, self) ); - let key_handle = symbol_stack.back_handle(); - if let Some(paths) = self.root_paths_by_precondition.get(key_handle) { + // paths that have exactly this symbol stack + if let Some(paths) = self + .root_paths_by_precondition_without_variable + .get(key.back_handle()) + { #[cfg(feature = "copious-debugging")] { for path in paths { copious_debugging!( - " Found path {}", + " Found path with exact stack {}", self[*path].display(graph, partials) ); } } result.extend(paths.iter().copied()); } - if symbol_stack.pop_back(self).is_none() { - break; + // paths that have an extension of this symbol stack + if symbol_stack.has_variable() { + if let Some(paths) = self + .root_paths_by_precondition_prefix + .get(key.back_handle()) + { + #[cfg(feature = "copious-debugging")] + { + for path in paths { + copious_debugging!( + " Found path with smaller stack {}", + self[*path].display(graph, partials) + ); + } + } + result.extend(paths.iter().copied()); + } + } + loop { + // paths that have a prefix of this symbol stack + if let Some(paths) = self + .root_paths_by_precondition_with_variable + .get(key.back_handle()) + { + #[cfg(feature = "copious-debugging")] + { + for path in paths { + copious_debugging!( + " Found path with smaller stack {}", + self[*path].display(graph, partials) + ); + } + } + result.extend(paths.iter().copied()); + } + if key.pop_back(self).is_none() { + break; + } } - }, + } None => { copious_debugging!(" Search for all root paths"); - for (_, paths) in self.root_paths_by_precondition.iter() { + for (_, paths) in self + .root_paths_by_precondition_with_variable + .iter() + .chain(self.root_paths_by_precondition_without_variable.iter()) + { #[cfg(feature = "copious-debugging")] { for path in paths { diff --git a/stack-graphs/tests/it/can_find_root_partial_paths_in_database.rs b/stack-graphs/tests/it/can_find_root_partial_paths_in_database.rs index 97dca4788..a70336333 100644 --- a/stack-graphs/tests/it/can_find_root_partial_paths_in_database.rs +++ b/stack-graphs/tests/it/can_find_root_partial_paths_in_database.rs @@ -17,7 +17,6 @@ use stack_graphs::partial::PartialScopedSymbol; use stack_graphs::partial::PartialSymbolStack; use stack_graphs::stitching::Database; use stack_graphs::stitching::ForwardPartialPathStitcher; -use stack_graphs::stitching::SymbolStackKey; use stack_graphs::NoCancellation; use crate::test_graphs; @@ -53,8 +52,12 @@ fn check_root_partial_paths( } let mut results = Vec::>::new(); - let key = SymbolStackKey::from_partial_symbol_stack(&mut partials, &mut db, symbol_stack); - db.find_candidate_partial_paths_from_root(graph, &mut partials, Some(key), &mut results); + db.find_candidate_partial_paths_from_root( + graph, + &mut partials, + Some(symbol_stack), + &mut results, + ); let actual_partial_paths = results .into_iter() diff --git a/stack-graphs/tests/it/main.rs b/stack-graphs/tests/it/main.rs index bea8a6030..75818b076 100644 --- a/stack-graphs/tests/it/main.rs +++ b/stack-graphs/tests/it/main.rs @@ -24,4 +24,5 @@ mod graph; mod partial; #[cfg(feature = "serde")] mod serde; +mod stitching; mod util; diff --git a/stack-graphs/tests/it/stitching.rs b/stack-graphs/tests/it/stitching.rs new file mode 100644 index 000000000..ddb878606 --- /dev/null +++ b/stack-graphs/tests/it/stitching.rs @@ -0,0 +1,104 @@ +// -*- coding: utf-8 -*- +// ------------------------------------------------------------------------------------------------ +// Copyright © 2023, stack-graphs authors. +// Licensed under either of Apache License, Version 2.0, or MIT license, at your option. +// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. +// ------------------------------------------------------------------------------------------------ + +use itertools::Itertools; +use stack_graphs::graph::StackGraph; +use stack_graphs::partial::PartialPaths; +use stack_graphs::stitching::Database; + +use crate::util::create_partial_path_and_edges; +use crate::util::create_pop_symbol_node; +use crate::util::create_push_symbol_node; + +fn test_foo_bar_root_candidate_paths(symbols: &[&str], variable: bool) -> usize { + let mut graph = StackGraph::new(); + let file = graph.add_file("test").unwrap(); + let mut partials = PartialPaths::new(); + + let r = StackGraph::root_node(); + let foo = create_pop_symbol_node(&mut graph, file, "foo", true); + let bar = create_pop_symbol_node(&mut graph, file, "bar", true); + + let path_with_variable = + create_partial_path_and_edges(&mut graph, &mut partials, &[r, foo, bar]).unwrap(); + + let mut path_without_variable = path_with_variable.clone(); + path_without_variable.eliminate_precondition_stack_variables(&mut partials); + + let mut db = Database::new(); + db.add_partial_path(&graph, &mut partials, path_with_variable); + db.add_partial_path(&graph, &mut partials, path_without_variable); + + let r = StackGraph::root_node(); + let refs = symbols + .into_iter() + .map(|r| create_push_symbol_node(&mut graph, file, *r, true)) + .chain(std::iter::once(r)) + .collect_vec(); + let mut path = create_partial_path_and_edges(&mut graph, &mut partials, &refs).unwrap(); + if !variable { + path.eliminate_precondition_stack_variables(&mut partials); + } + + let mut results = Vec::new(); + db.find_candidate_partial_paths_from_root( + &mut graph, + &mut partials, + Some(path.symbol_stack_postcondition), + &mut results, + ); + + results.len() +} + +#[test] +fn find_candidates_for_exact_symbol_stack_with_variable() { + // <"foo","bar",%2> ~ <"foo","bar",%1> | yes, %2 = %1 + // <"foo","bar",%2> ~ <"foo","bar"> | yes, %2 = <> + let results = test_foo_bar_root_candidate_paths(&["bar", "foo"], true); + assert_eq!(2, results); +} + +#[test] +fn find_candidates_for_exact_symbol_stack_without_variable() { + // <"foo","bar"> ~ <"foo","bar",%1> | yes, %1 = <> + // <"foo","bar"> ~ <"foo","bar"> | yes + let results = test_foo_bar_root_candidate_paths(&["bar", "foo"], false); + assert_eq!(2, results); +} + +#[test] +fn find_candidates_for_longer_symbol_stack_with_variable() { + // <"foo","bar","quz",%2> ~ <"foo","bar",%1> | yes, %1 = <"quz",%2> + // <"foo","bar","quz",%2> ~ <"foo","bar"> | no + let results = test_foo_bar_root_candidate_paths(&["quz", "bar", "foo"], true); + assert_eq!(1, results); +} + +#[test] +fn find_candidates_for_longer_symbol_stack_without_variable() { + // <"foo","bar","quz"> ~ <"foo","bar",%1> | yes, %1 = <"quz"> + // <"foo","bar","quz"> ~ <"foo","bar"> | no + let results = test_foo_bar_root_candidate_paths(&["quz", "bar", "foo"], false); + assert_eq!(1, results); +} + +#[test] +fn find_candidates_for_shorter_symbol_stack_with_variable() { + // <"foo",%2> ~ <"foo","bar",%1> | yes, %2 = <"bar",%1> + // <"foo",%2> ~ <"foo","bar"> | yes, %2 = <"bar"> + let results = test_foo_bar_root_candidate_paths(&["foo"], true); + assert_eq!(2, results); +} + +#[test] +fn find_candidates_for_shorter_symbol_stack_without_variable() { + // <"foo"> ~ <"foo","bar",%1> | no + // <"foo"> ~ <"foo","bar"> | no + let results = test_foo_bar_root_candidate_paths(&["foo"], false); + assert_eq!(0, results); +} From 5a6744b9672c6128bf938d34733ea52f07f36dee Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Sun, 22 Oct 2023 13:20:08 +0200 Subject: [PATCH 264/500] Ensure all viable root paths are loaded from storage --- stack-graphs/src/storage.rs | 69 +++++++++++------ stack-graphs/tests/it/main.rs | 2 + stack-graphs/tests/it/storage.rs | 127 +++++++++++++++++++++++++++++++ 3 files changed, 173 insertions(+), 25 deletions(-) create mode 100644 stack-graphs/tests/it/storage.rs diff --git a/stack-graphs/src/storage.rs b/stack-graphs/src/storage.rs index 7664ea88f..d3f1348dc 100644 --- a/stack-graphs/src/storage.rs +++ b/stack-graphs/src/storage.rs @@ -7,6 +7,7 @@ use bincode::error::DecodeError; use bincode::error::EncodeError; +use itertools::Itertools; use rusqlite::functions::FunctionFlags; use rusqlite::types::ValueRef; use rusqlite::Connection; @@ -33,7 +34,7 @@ use crate::stitching::ForwardCandidates; use crate::CancellationError; use crate::CancellationFlag; -const VERSION: usize = 5; +const VERSION: usize = 6; const SCHEMA: &str = r#" CREATE TABLE metadata ( @@ -616,9 +617,12 @@ impl SQLiteReader { " * Load extensions from root with symbol stack {}", symbol_stack.display(&self.graph, &mut self.partials) ); - let symbol_stack_prefixes = - symbol_stack.storage_key_prefixes(&self.graph, &mut self.partials); - for symbol_stack in symbol_stack_prefixes { + let mut stmt = self.conn.prepare_cached( + "SELECT file,value from root_paths WHERE symbol_stack LIKE ? ESCAPE ?", + )?; + let (symbol_stack_patterns, escape) = + symbol_stack.storage_key_patterns(&self.graph, &mut self.partials); + for symbol_stack in symbol_stack_patterns { copious_debugging!( " * Load extensions from root with prefix symbol stack {}", symbol_stack @@ -627,10 +631,7 @@ impl SQLiteReader { copious_debugging!(" > Already loaded"); continue; } - let mut stmt = self - .conn - .prepare_cached("SELECT file,value from root_paths WHERE symbol_stack = ?")?; - let paths = stmt.query_map([symbol_stack], |row| { + let paths = stmt.query_map([symbol_stack, escape.clone()], |row| { let file = row.get::<_, String>(0)?; let value = row.get::<_, Vec>(1)?; Ok((file, value)) @@ -682,41 +683,59 @@ impl SQLiteReader { } /// Get the stack graph, partial paths arena, and path database for the currently loaded data. - pub fn get(&mut self) -> (&StackGraph, &mut PartialPaths, &mut Database) { - (&self.graph, &mut self.partials, &mut self.db) + pub fn get(&mut self) -> (&mut StackGraph, &mut PartialPaths, &mut Database) { + (&mut self.graph, &mut self.partials, &mut self.db) } } +// Methods for computing keys and patterns for a symbol stack. The format of a storage key is: +// +// has-var GS ( symbol (US symbol)* )? +// +// where has-var is "V" if the symbol stack has a variable, "X" otherwise. impl PartialSymbolStack { /// Returns a string representation of this symbol stack for indexing in the database. - fn storage_key(mut self, graph: &StackGraph, partials: &mut PartialPaths) -> String { + fn storage_key(self, graph: &StackGraph, partials: &mut PartialPaths) -> String { let mut key = String::new(); - while let Some(symbol) = self.pop_front(partials) { - if !key.is_empty() { - key += "\u{241F}"; - } - key += &graph[symbol.symbol]; + match self.has_variable() { + true => key += "V\u{241E}", + false => key += "X\u{241E}", } + key += &self + .iter(partials) + .map(|s| &graph[s.symbol]) + .join("\u{241F}"); key } /// Returns string representations for all prefixes of this symbol stack for querying the /// index in the database. - fn storage_key_prefixes( + fn storage_key_patterns( mut self, graph: &StackGraph, partials: &mut PartialPaths, - ) -> Vec { - let mut key_prefixes = vec![String::new()]; + ) -> (Vec, String) { + let mut key_patterns = Vec::new(); + let mut symbols = String::new(); while let Some(symbol) = self.pop_front(partials) { - let mut key = key_prefixes.last().unwrap().to_string(); - if !key.is_empty() { - key += "\u{241F}"; + if !symbols.is_empty() { + symbols += "\u{241F}"; } - key += &graph[symbol.symbol]; - key_prefixes.push(key); + let symbol = graph[symbol.symbol] + .replace("%", "\\%") + .replace("_", "\\_") + .to_string(); + symbols += &symbol; + // patterns for paths matching a prefix of this stack + key_patterns.push("V\u{241E}".to_string() + &symbols); + } + // pattern for paths matching exactly this stack + key_patterns.push("X\u{241E}".to_string() + &symbols); + if self.has_variable() { + // patterns for paths for which this stack is a prefix + key_patterns.push("_\u{241E}".to_string() + &symbols + "\u{241F}%"); } - key_prefixes + (key_patterns, "\\".to_string()) } } diff --git a/stack-graphs/tests/it/main.rs b/stack-graphs/tests/it/main.rs index 75818b076..3f0162c3b 100644 --- a/stack-graphs/tests/it/main.rs +++ b/stack-graphs/tests/it/main.rs @@ -25,4 +25,6 @@ mod partial; #[cfg(feature = "serde")] mod serde; mod stitching; +#[cfg(feature = "storage")] +mod storage; mod util; diff --git a/stack-graphs/tests/it/storage.rs b/stack-graphs/tests/it/storage.rs new file mode 100644 index 000000000..464700414 --- /dev/null +++ b/stack-graphs/tests/it/storage.rs @@ -0,0 +1,127 @@ +// -*- coding: utf-8 -*- +// ------------------------------------------------------------------------------------------------ +// Copyright © 2023, stack-graphs authors. +// Licensed under either of Apache License, Version 2.0, or MIT license, at your option. +// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. +// ------------------------------------------------------------------------------------------------ + +use itertools::Itertools; +use stack_graphs::graph::StackGraph; +use stack_graphs::partial::PartialPaths; +use stack_graphs::storage::SQLiteWriter; +use stack_graphs::NoCancellation; + +use crate::util::create_partial_path_and_edges; +use crate::util::create_pop_symbol_node; +use crate::util::create_push_symbol_node; + +fn test_foo_bar_root_candidate_paths(symbols: &[&str], variable: bool) -> usize { + let mut reader = { + let mut writer = SQLiteWriter::open_in_memory().unwrap(); + + let mut graph = StackGraph::new(); + let file = graph.add_file("test1").unwrap(); + let mut partials = PartialPaths::new(); + + let r = StackGraph::root_node(); + let foo = create_pop_symbol_node(&mut graph, file, "foo", true); + let bar = create_pop_symbol_node(&mut graph, file, "bar", true); + + let path_with_variable = + create_partial_path_and_edges(&mut graph, &mut partials, &[r, foo, bar]).unwrap(); + + let mut path_without_variable = path_with_variable.clone(); + path_without_variable.eliminate_precondition_stack_variables(&mut partials); + + writer + .store_result_for_file( + &graph, + file, + "", + &mut partials, + vec![&path_with_variable, &path_without_variable], + ) + .unwrap(); + + writer.into_reader() + }; + + { + let (graph, partials, _) = reader.get(); + let file = graph.add_file("test2").unwrap(); + + let r = StackGraph::root_node(); + let refs = symbols + .into_iter() + .map(|r| create_push_symbol_node(graph, file, *r, true)) + .chain(std::iter::once(r)) + .collect_vec(); + let mut path = create_partial_path_and_edges(graph, partials, &refs).unwrap(); + if !variable { + path.eliminate_precondition_stack_variables(partials); + } + + reader + .load_partial_path_extensions(&path, &NoCancellation) + .unwrap(); + + let (graph, partials, db) = reader.get(); + let mut results = Vec::new(); + db.find_candidate_partial_paths_from_root( + graph, + partials, + Some(path.symbol_stack_postcondition), + &mut results, + ); + + results.len() + } +} + +#[test] +fn find_candidates_for_exact_symbol_stack_with_variable() { + // <"foo","bar",%2> ~ <"foo","bar",%1> | yes, %2 = %1 + // <"foo","bar",%2> ~ <"foo","bar"> | yes, %2 = <> + let results = test_foo_bar_root_candidate_paths(&["bar", "foo"], true); + assert_eq!(2, results); +} + +#[test] +fn find_candidates_for_exact_symbol_stack_without_variable() { + // <"foo","bar"> ~ <"foo","bar",%1> | yes, %1 = <> + // <"foo","bar"> ~ <"foo","bar"> | yes + let results = test_foo_bar_root_candidate_paths(&["bar", "foo"], false); + assert_eq!(2, results); +} + +#[test] +fn find_candidates_for_longer_symbol_stack_with_variable() { + // <"foo","bar","quz",%2> ~ <"foo","bar",%1> | yes, %1 = <"quz",%2> + // <"foo","bar","quz",%2> ~ <"foo","bar"> | no + let results = test_foo_bar_root_candidate_paths(&["quz", "bar", "foo"], true); + assert_eq!(1, results); +} + +#[test] +fn find_candidates_for_longer_symbol_stack_without_variable() { + // <"foo","bar","quz"> ~ <"foo","bar",%1> | yes, %1 = <"quz"> + // <"foo","bar","quz"> ~ <"foo","bar"> | no + let results = test_foo_bar_root_candidate_paths(&["quz", "bar", "foo"], false); + assert_eq!(1, results); +} + +#[test] +fn find_candidates_for_shorter_symbol_stack_with_variable() { + // <"foo",%2> ~ <"foo","bar",%1> | yes, %2 = <"bar",%1> + // <"foo",%2> ~ <"foo","bar"> | yes, %2 = <"bar"> + let results = test_foo_bar_root_candidate_paths(&["foo"], true); + assert_eq!(2, results); +} + +#[test] +fn find_candidates_for_shorter_symbol_stack_without_variable() { + // <"foo"> ~ <"foo","bar",%1> | no + // <"foo"> ~ <"foo","bar"> | no + let results = test_foo_bar_root_candidate_paths(&["foo"], false); + assert_eq!(0, results); +} From 87d312a1f585a9f77dada1d83c912091135fd443 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 16 Oct 2023 17:39:07 +0200 Subject: [PATCH 265/500] Add support for stitcher configuration --- .../tree-sitter-stack-graphs-java/Cargo.toml | 1 + .../tree-sitter-stack-graphs-java/rust/lib.rs | 4 +++ .../rust/lib.rs | 2 ++ stack-graphs/include/stack-graphs.h | 13 +++++++-- stack-graphs/src/assert.rs | 16 +++++++++-- stack-graphs/src/c.rs | 28 ++++++++++++++++++- stack-graphs/src/stitching.rs | 20 ++++++++++--- .../tests/it/c/can_find_local_nodes.rs | 5 ++++ .../it/c/can_find_partial_paths_in_file.rs | 5 ++++ ...ions_with_phased_partial_path_stitching.rs | 9 ++++++ .../tests/it/c/can_jump_to_definition.rs | 5 ++++ ...tion_with_phased_partial_path_stitching.rs | 9 ++++++ stack-graphs/tests/it/can_find_local_nodes.rs | 2 ++ ...can_find_node_partial_paths_in_database.rs | 2 ++ .../it/can_find_partial_paths_in_file.rs | 3 +- ...can_find_root_partial_paths_in_database.rs | 2 ++ .../tests/it/can_jump_to_definition.rs | 2 ++ ...ion_with_forward_partial_path_stitching.rs | 3 ++ stack-graphs/tests/it/cycles.rs | 4 +++ stack-graphs/tests/it/serde.rs | 3 +- tree-sitter-stack-graphs/src/cli/index.rs | 11 ++++++++ tree-sitter-stack-graphs/src/cli/init.rs | 2 ++ tree-sitter-stack-graphs/src/cli/query.rs | 8 ++++++ tree-sitter-stack-graphs/src/cli/test.rs | 22 +++++++++++++-- tree-sitter-stack-graphs/src/cli/visualize.rs | 8 ++++++ tree-sitter-stack-graphs/src/loader.rs | 6 ++++ tree-sitter-stack-graphs/src/test.rs | 10 ++++++- tree-sitter-stack-graphs/tests/it/loader.rs | 2 ++ tree-sitter-stack-graphs/tests/it/test.rs | 9 +++++- 29 files changed, 200 insertions(+), 16 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-java/Cargo.toml b/languages/tree-sitter-stack-graphs-java/Cargo.toml index 8bd3e5f93..72646a905 100644 --- a/languages/tree-sitter-stack-graphs-java/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-java/Cargo.toml @@ -36,5 +36,6 @@ harness = false # need to provide own main function to handle running tests [dependencies] anyhow = "1.0" clap = { version = "4", features = ["derive"] } +stack-graphs = { version = "0.12", path = "../../stack-graphs" } tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs", features=["cli"] } tree-sitter-java = { version = "=0.20.0" } diff --git a/languages/tree-sitter-stack-graphs-java/rust/lib.rs b/languages/tree-sitter-stack-graphs-java/rust/lib.rs index 09cb043a5..d1af5bb12 100644 --- a/languages/tree-sitter-stack-graphs-java/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-java/rust/lib.rs @@ -1,6 +1,7 @@ use tree_sitter_stack_graphs::loader::FileAnalyzers; use tree_sitter_stack_graphs::loader::LanguageConfiguration; use tree_sitter_stack_graphs::loader::LoadError; +use tree_sitter_stack_graphs::loader::StitcherConfig; use tree_sitter_stack_graphs::CancellationFlag; /// The stacks graphs tsg path for this language. @@ -40,6 +41,9 @@ pub fn try_language_configuration( )), Some(STACK_GRAPHS_BUILTINS_CONFIG), FileAnalyzers::new(), + StitcherConfig { + detect_similar_paths: true, + }, cancellation_flag, ) } diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs index 45ce6d255..9ef2f1805 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs @@ -8,6 +8,7 @@ use tree_sitter_stack_graphs::loader::FileAnalyzers; use tree_sitter_stack_graphs::loader::LanguageConfiguration; use tree_sitter_stack_graphs::loader::LoadError; +use tree_sitter_stack_graphs::loader::StitcherConfig; use tree_sitter_stack_graphs::CancellationFlag; use crate::npm_package::NpmPackageAnalyzer; @@ -56,6 +57,7 @@ pub fn try_language_configuration( FileAnalyzers::new() .add("tsconfig.json".to_string(), TsConfigAnalyzer {}) .add("package.json".to_string(), NpmPackageAnalyzer {}), + StitcherConfig::default(), cancellation_flag, ) } diff --git a/stack-graphs/include/stack-graphs.h b/stack-graphs/include/stack-graphs.h index 50b7062ed..a1afe93dd 100644 --- a/stack-graphs/include/stack-graphs.h +++ b/stack-graphs/include/stack-graphs.h @@ -437,6 +437,11 @@ struct sg_partial_path { struct sg_partial_path_edge_list edges; }; +struct sg_stitcher_config { + // Enables similar path detection during stiching. + bool detect_similar_paths; +}; + // An array of all of the partial paths in a partial path database. Partial path handles are // indices into this array. There will never be a valid partial path at index 0; a handle with // the value 0 represents a missing partial path. @@ -733,6 +738,7 @@ enum sg_result sg_partial_path_arena_find_partial_paths_in_file(const struct sg_ struct sg_partial_path_arena *partials, sg_file_handle file, struct sg_partial_path_list *partial_path_list, + struct sg_stitcher_config config, const size_t *cancellation_flag); // Finds all complete paths reachable from a set of starting nodes, placing the result into the @@ -748,6 +754,7 @@ enum sg_result sg_partial_path_arena_find_all_complete_paths(const struct sg_sta size_t starting_node_count, const sg_node_handle *starting_nodes, struct sg_partial_path_list *path_list, + struct sg_stitcher_config config, const size_t *cancellation_flag); // Returns a reference to the array of partial path data in this partial path database. The @@ -805,14 +812,16 @@ struct sg_node_handle_set sg_partial_path_database_local_nodes(const struct sg_p struct sg_forward_partial_path_stitcher *sg_forward_partial_path_stitcher_from_nodes(const struct sg_stack_graph *graph, struct sg_partial_path_arena *partials, size_t count, - const sg_node_handle *starting_nodes); + const sg_node_handle *starting_nodes, + struct sg_stitcher_config config); // Creates a new forward partial path stitcher that is "seeded" with a set of initial partial // paths. struct sg_forward_partial_path_stitcher *sg_forward_partial_path_stitcher_from_partial_paths(const struct sg_stack_graph *graph, struct sg_partial_path_arena *partials, size_t count, - const struct sg_partial_path *initial_partial_paths); + const struct sg_partial_path *initial_partial_paths, + struct sg_stitcher_config config); // Sets whether similar path detection should be enabled during path stitching. Paths are similar // if start and end node, and pre- and postconditions are the same. The presence of similar paths diff --git a/stack-graphs/src/assert.rs b/stack-graphs/src/assert.rs index 70237614c..278caabbc 100644 --- a/stack-graphs/src/assert.rs +++ b/stack-graphs/src/assert.rs @@ -20,6 +20,7 @@ use crate::partial::PartialPaths; use crate::stitching::Database; use crate::stitching::DatabaseCandidates; use crate::stitching::ForwardPartialPathStitcher; +use crate::stitching::StitcherConfig; use crate::CancellationError; use crate::CancellationFlag; @@ -149,12 +150,19 @@ impl Assertion { graph: &StackGraph, partials: &mut PartialPaths, db: &mut Database, + stitcher_config: &StitcherConfig, cancellation_flag: &dyn CancellationFlag, ) -> Result<(), AssertionError> { match self { - Self::Defined { source, targets } => { - self.run_defined(graph, partials, db, source, targets, cancellation_flag) - } + Self::Defined { source, targets } => self.run_defined( + graph, + partials, + db, + source, + targets, + stitcher_config, + cancellation_flag, + ), Self::Defines { source, symbols } => self.run_defines(graph, source, symbols), Self::Refers { source, symbols } => self.run_refers(graph, source, symbols), } @@ -167,6 +175,7 @@ impl Assertion { db: &mut Database, source: &AssertionSource, expected_targets: &Vec, + stitcher_config: &StitcherConfig, cancellation_flag: &dyn CancellationFlag, ) -> Result<(), AssertionError> { let references = source.iter_references(graph).collect::>(); @@ -182,6 +191,7 @@ impl Assertion { ForwardPartialPathStitcher::find_all_complete_partial_paths( &mut DatabaseCandidates::new(graph, partials, db), vec![*reference], + stitcher_config, cancellation_flag, |_, _, p| { reference_paths.push(p.clone()); diff --git a/stack-graphs/src/c.rs b/stack-graphs/src/c.rs index f4857c791..4f58caff2 100644 --- a/stack-graphs/src/c.rs +++ b/stack-graphs/src/c.rs @@ -32,6 +32,7 @@ use crate::stitching::Database; use crate::stitching::DatabaseCandidates; use crate::stitching::ForwardPartialPathStitcher; use crate::stitching::GraphEdgeCandidates; +use crate::stitching::StitcherConfig; use crate::CancellationError; use crate::CancellationFlag; @@ -1173,6 +1174,7 @@ pub extern "C" fn sg_partial_path_arena_find_partial_paths_in_file( partials: *mut sg_partial_path_arena, file: sg_file_handle, partial_path_list: *mut sg_partial_path_list, + config: sg_stitcher_config, cancellation_flag: *const usize, ) -> sg_result { let graph = unsafe { &(*graph).inner }; @@ -1185,6 +1187,7 @@ pub extern "C" fn sg_partial_path_arena_find_partial_paths_in_file( graph, partials, file, + &config.into(), &AtomicUsizeCancellationFlag(cancellation_flag), |_graph, partials, path| { let mut path = path.clone(); @@ -1210,6 +1213,7 @@ pub extern "C" fn sg_partial_path_arena_find_all_complete_paths( starting_node_count: usize, starting_nodes: *const sg_node_handle, path_list: *mut sg_partial_path_list, + config: sg_stitcher_config, cancellation_flag: *const usize, ) -> sg_result { let graph = unsafe { &(*graph).inner }; @@ -1221,6 +1225,7 @@ pub extern "C" fn sg_partial_path_arena_find_all_complete_paths( ForwardPartialPathStitcher::find_all_complete_partial_paths( &mut GraphEdgeCandidates::new(graph, partials, None), starting_nodes.iter().copied().map(sg_node_handle::into), + &config.into(), &AtomicUsizeCancellationFlag(cancellation_flag), |graph, _partials, path| { if path.is_complete(graph) { @@ -1391,6 +1396,19 @@ pub struct sg_forward_partial_path_stitcher { pub is_complete: bool, } +// Configuration for partial path stitchers. +#[repr(C)] +pub struct sg_stitcher_config { + /// Enables similar path detection during stiching. + pub detect_similar_paths: bool, +} + +impl Into for sg_stitcher_config { + fn into(self) -> StitcherConfig { + unsafe { std::mem::transmute(self) } + } +} + // This is the Rust equivalent of a common C trick, where you have two versions of a struct — a // publicly visible one and a private one containing internal implementation details. In our case, // `sg_forward_partial_path_stitcher` is the public struct, and @@ -1443,6 +1461,7 @@ pub extern "C" fn sg_forward_partial_path_stitcher_from_nodes( partials: *mut sg_partial_path_arena, count: usize, starting_nodes: *const sg_node_handle, + config: sg_stitcher_config, ) -> *mut sg_forward_partial_path_stitcher { let graph = unsafe { &(*graph).inner }; let partials = unsafe { &mut (*partials).inner }; @@ -1457,7 +1476,12 @@ pub extern "C" fn sg_forward_partial_path_stitcher_from_nodes( p }) .collect::>(); - let stitcher = ForwardPartialPathStitcher::from_partial_paths(graph, partials, initial_paths); + let stitcher = ForwardPartialPathStitcher::from_partial_paths( + graph, + partials, + initial_paths, + &config.into(), + ); Box::into_raw(Box::new(InternalForwardPartialPathStitcher::new( stitcher, partials, ))) as *mut _ @@ -1471,6 +1495,7 @@ pub extern "C" fn sg_forward_partial_path_stitcher_from_partial_paths( partials: *mut sg_partial_path_arena, count: usize, initial_partial_paths: *const sg_partial_path, + config: sg_stitcher_config, ) -> *mut sg_forward_partial_path_stitcher { let graph = unsafe { &(*graph).inner }; let partials = unsafe { &mut (*partials).inner }; @@ -1480,6 +1505,7 @@ pub extern "C" fn sg_forward_partial_path_stitcher_from_partial_paths( graph, partials, initial_partial_paths.to_vec(), + &config.into(), ); Box::into_raw(Box::new(InternalForwardPartialPathStitcher::new( stitcher, partials, diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index 6aade970d..dc7cb8c9b 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -795,6 +795,13 @@ impl<'a> Display for DisplaySymbolStackKey<'a> { //------------------------------------------------------------------------------------------------- // Stitching partial paths together +/// Configuration for partial path stitchers. +#[derive(Clone, Debug, Default)] +pub struct StitcherConfig { + /// Enables similar path detection during path stitching. + pub detect_similar_paths: bool, +} + /// Implements a phased forward partial path stitching algorithm. /// /// Our overall goal is to start with a set of _seed_ partial paths, and to repeatedly extend each @@ -851,6 +858,7 @@ impl ForwardPartialPathStitcher { _graph: &StackGraph, _partials: &mut PartialPaths, initial_partial_paths: I, + config: &StitcherConfig, ) -> Self where I: IntoIterator, @@ -863,14 +871,16 @@ impl ForwardPartialPathStitcher { (p, c, false) }) .multiunzip(); - Self { + let similar_path_detector = + Some(SimilarPathDetector::new()).filter(|_| config.detect_similar_paths); + ForwardPartialPathStitcher { candidates: Vec::new(), extensions: Vec::new(), queue: VecDeque::new(), initial_paths: next_iteration.0.len(), next_iteration, appended_paths, - similar_path_detector: Some(SimilarPathDetector::new()), + similar_path_detector, // By default, all nodes are checked for cycles and (if enabled) similarity check_only_join_nodes: false, // By default, there's no artificial bound on the amount of work done per phase @@ -1145,6 +1155,7 @@ impl ForwardPartialPathStitcher { graph: &StackGraph, partials: &mut PartialPaths, file: Handle, + config: &StitcherConfig, cancellation_flag: &dyn CancellationFlag, mut visit: F, ) -> Result<(), CancellationError> @@ -1163,7 +1174,7 @@ impl ForwardPartialPathStitcher { .map(|node| PartialPath::from_node(graph, partials, node)) .collect::>(); let mut stitcher = - ForwardPartialPathStitcher::from_partial_paths(graph, partials, initial_paths); + ForwardPartialPathStitcher::from_partial_paths(graph, partials, initial_paths, config); stitcher.set_check_only_join_nodes(true); while !stitcher.is_complete() { cancellation_flag.check("finding complete partial paths")?; @@ -1196,6 +1207,7 @@ impl ForwardPartialPathStitcher { pub fn find_all_complete_partial_paths( candidates: &mut C, starting_nodes: I, + config: &StitcherConfig, cancellation_flag: &dyn CancellationFlag, mut visit: F, ) -> Result<(), Err> @@ -1218,7 +1230,7 @@ impl ForwardPartialPathStitcher { p }) .collect::>(); - ForwardPartialPathStitcher::from_partial_paths(graph, partials, initial_paths) + ForwardPartialPathStitcher::from_partial_paths(graph, partials, initial_paths, config) }; stitcher.set_check_only_join_nodes(true); while !stitcher.is_complete() { diff --git a/stack-graphs/tests/it/c/can_find_local_nodes.rs b/stack-graphs/tests/it/c/can_find_local_nodes.rs index 0a5d3a402..2d2ecdee5 100644 --- a/stack-graphs/tests/it/c/can_find_local_nodes.rs +++ b/stack-graphs/tests/it/c/can_find_local_nodes.rs @@ -22,6 +22,7 @@ use stack_graphs::c::sg_partial_path_list_free; use stack_graphs::c::sg_partial_path_list_new; use stack_graphs::c::sg_partial_path_list_paths; use stack_graphs::c::sg_stack_graph_nodes; +use stack_graphs::c::sg_stitcher_config; use stack_graphs::graph::Node; use crate::c::test_graph::TestGraph; @@ -33,11 +34,15 @@ fn check_local_nodes(graph: &TestGraph, file: &str, expected_local_nodes: &[&str let partials = sg_partial_path_arena_new(); let path_list = sg_partial_path_list_new(); + let config = sg_stitcher_config { + detect_similar_paths: false, + }; sg_partial_path_arena_find_partial_paths_in_file( graph.graph, partials, file.as_u32(), path_list, + config, std::ptr::null(), ); diff --git a/stack-graphs/tests/it/c/can_find_partial_paths_in_file.rs b/stack-graphs/tests/it/c/can_find_partial_paths_in_file.rs index b39bc524a..65ab8e2c2 100644 --- a/stack-graphs/tests/it/c/can_find_partial_paths_in_file.rs +++ b/stack-graphs/tests/it/c/can_find_partial_paths_in_file.rs @@ -22,6 +22,7 @@ use stack_graphs::c::sg_partial_path_list_new; use stack_graphs::c::sg_partial_path_list_paths; use stack_graphs::c::sg_partial_scope_stack; use stack_graphs::c::sg_partial_symbol_stack; +use stack_graphs::c::sg_stitcher_config; use stack_graphs::c::SG_LIST_EMPTY_HANDLE; use stack_graphs::c::SG_NULL_HANDLE; use stack_graphs::partial::PartialPath; @@ -77,11 +78,15 @@ fn check_partial_paths_in_file(graph: &TestGraph, file: &str, expected_paths: &[ let partials = sg_partial_path_arena_new(); let path_list = sg_partial_path_list_new(); + let config = sg_stitcher_config { + detect_similar_paths: false, + }; sg_partial_path_arena_find_partial_paths_in_file( graph.graph, partials, file.as_u32(), path_list, + config, std::ptr::null(), ); diff --git a/stack-graphs/tests/it/c/can_find_qualified_definitions_with_phased_partial_path_stitching.rs b/stack-graphs/tests/it/c/can_find_qualified_definitions_with_phased_partial_path_stitching.rs index dcc276c86..fe8594dee 100644 --- a/stack-graphs/tests/it/c/can_find_qualified_definitions_with_phased_partial_path_stitching.rs +++ b/stack-graphs/tests/it/c/can_find_qualified_definitions_with_phased_partial_path_stitching.rs @@ -28,6 +28,7 @@ use stack_graphs::c::sg_partial_path_list_free; use stack_graphs::c::sg_partial_path_list_new; use stack_graphs::c::sg_partial_path_list_paths; use stack_graphs::c::sg_stack_graph; +use stack_graphs::c::sg_stitcher_config; use stack_graphs::copious_debugging; use stack_graphs::graph::StackGraph; use stack_graphs::partial::PartialPath; @@ -55,11 +56,15 @@ impl StorageLayer { let rust_graph = unsafe { &(*graph).inner }; let path_list = sg_partial_path_list_new(); for file in rust_graph.iter_files() { + let config = sg_stitcher_config { + detect_similar_paths: false, + }; sg_partial_path_arena_find_partial_paths_in_file( graph, partials, file.as_u32(), path_list, + config, std::ptr::null(), ); } @@ -117,6 +122,9 @@ fn check_find_qualified_definitions( let partials = sg_partial_path_arena_new(); let rust_partials = unsafe { &mut (*partials).inner }; let db = sg_partial_path_database_new(); + let config = sg_stitcher_config { + detect_similar_paths: false, + }; // Create a new external storage layer holding _all_ of the partial paths in the stack graph. let mut storage_layer = StorageLayer::new(graph.graph, partials); @@ -149,6 +157,7 @@ fn check_find_qualified_definitions( partials, 1, &initial_partial_path as *const PartialPath as *const _, + config, ); sg_forward_partial_path_stitcher_set_max_work_per_phase(stitcher, 1); let rust_stitcher = unsafe { &mut *stitcher }; diff --git a/stack-graphs/tests/it/c/can_jump_to_definition.rs b/stack-graphs/tests/it/c/can_jump_to_definition.rs index 800ce06e8..c00fe4cb1 100644 --- a/stack-graphs/tests/it/c/can_jump_to_definition.rs +++ b/stack-graphs/tests/it/c/can_jump_to_definition.rs @@ -15,6 +15,7 @@ use stack_graphs::c::sg_partial_path_list_count; use stack_graphs::c::sg_partial_path_list_free; use stack_graphs::c::sg_partial_path_list_new; use stack_graphs::c::sg_partial_path_list_paths; +use stack_graphs::c::sg_stitcher_config; use stack_graphs::partial::PartialPath; use crate::c::test_graph::TestGraph; @@ -28,12 +29,16 @@ fn check_jump_to_definition(graph: &TestGraph, expected_paths: &[&str]) { .iter_nodes() .filter(|handle| rust_graph[*handle].is_reference()) .collect::>(); + let config = sg_stitcher_config { + detect_similar_paths: false, + }; sg_partial_path_arena_find_all_complete_paths( graph.graph, paths, references.len(), references.as_ptr() as *const _, path_list, + config, std::ptr::null(), ); diff --git a/stack-graphs/tests/it/c/can_jump_to_definition_with_phased_partial_path_stitching.rs b/stack-graphs/tests/it/c/can_jump_to_definition_with_phased_partial_path_stitching.rs index 615ffedd5..3a23ab763 100644 --- a/stack-graphs/tests/it/c/can_jump_to_definition_with_phased_partial_path_stitching.rs +++ b/stack-graphs/tests/it/c/can_jump_to_definition_with_phased_partial_path_stitching.rs @@ -27,6 +27,7 @@ use stack_graphs::c::sg_partial_path_list_free; use stack_graphs::c::sg_partial_path_list_new; use stack_graphs::c::sg_partial_path_list_paths; use stack_graphs::c::sg_stack_graph; +use stack_graphs::c::sg_stitcher_config; use stack_graphs::copious_debugging; use stack_graphs::partial::PartialPath; use stack_graphs::partial::PartialScopeStackBindings; @@ -49,11 +50,15 @@ impl StorageLayer { let rust_graph = unsafe { &(*graph).inner }; let path_list = sg_partial_path_list_new(); for file in rust_graph.iter_files() { + let config = sg_stitcher_config { + detect_similar_paths: false, + }; sg_partial_path_arena_find_partial_paths_in_file( graph, partials, file.as_u32(), path_list, + config, std::ptr::null(), ); } @@ -129,11 +134,15 @@ fn check_jump_to_definition(graph: &TestGraph, file: &str, expected_partial_path }); // Create the forward partial path stitcher. + let config = sg_stitcher_config { + detect_similar_paths: false, + }; let stitcher = sg_forward_partial_path_stitcher_from_nodes( graph.graph, partials, references.len(), references.as_ptr() as *const _, + config, ); sg_forward_partial_path_stitcher_set_max_work_per_phase(stitcher, 1); let rust_stitcher = unsafe { &mut *stitcher }; diff --git a/stack-graphs/tests/it/can_find_local_nodes.rs b/stack-graphs/tests/it/can_find_local_nodes.rs index 105e5a795..6b763b0d7 100644 --- a/stack-graphs/tests/it/can_find_local_nodes.rs +++ b/stack-graphs/tests/it/can_find_local_nodes.rs @@ -12,6 +12,7 @@ use stack_graphs::graph::StackGraph; use stack_graphs::partial::PartialPaths; use stack_graphs::stitching::Database; use stack_graphs::stitching::ForwardPartialPathStitcher; +use stack_graphs::stitching::StitcherConfig; use stack_graphs::NoCancellation; use crate::test_graphs; @@ -24,6 +25,7 @@ fn check_local_nodes(graph: &StackGraph, file: &str, expected_local_nodes: &[&st graph, &mut partials, file, + &StitcherConfig::default(), &NoCancellation, |graph, partials, path| { database.add_partial_path(graph, partials, path.clone()); diff --git a/stack-graphs/tests/it/can_find_node_partial_paths_in_database.rs b/stack-graphs/tests/it/can_find_node_partial_paths_in_database.rs index 3ccea9548..22d311d34 100644 --- a/stack-graphs/tests/it/can_find_node_partial_paths_in_database.rs +++ b/stack-graphs/tests/it/can_find_node_partial_paths_in_database.rs @@ -15,6 +15,7 @@ use stack_graphs::partial::PartialPath; use stack_graphs::partial::PartialPaths; use stack_graphs::stitching::Database; use stack_graphs::stitching::ForwardPartialPathStitcher; +use stack_graphs::stitching::StitcherConfig; use stack_graphs::NoCancellation; use crate::test_graphs; @@ -33,6 +34,7 @@ fn check_node_partial_paths( graph, &mut partials, file, + &StitcherConfig::default(), &NoCancellation, |graph, partials, path| { db.add_partial_path(graph, partials, path.clone()); diff --git a/stack-graphs/tests/it/can_find_partial_paths_in_file.rs b/stack-graphs/tests/it/can_find_partial_paths_in_file.rs index abba6951b..d3e48e33f 100644 --- a/stack-graphs/tests/it/can_find_partial_paths_in_file.rs +++ b/stack-graphs/tests/it/can_find_partial_paths_in_file.rs @@ -10,7 +10,7 @@ use std::collections::BTreeSet; use pretty_assertions::assert_eq; use stack_graphs::graph::StackGraph; use stack_graphs::partial::PartialPaths; -use stack_graphs::stitching::ForwardPartialPathStitcher; +use stack_graphs::stitching::{ForwardPartialPathStitcher, StitcherConfig}; use stack_graphs::NoCancellation; use crate::test_graphs; @@ -23,6 +23,7 @@ fn check_partial_paths_in_file(graph: &StackGraph, file: &str, expected_paths: & graph, &mut partials, file, + &StitcherConfig::default(), &NoCancellation, |graph, partials, path| { results.insert(path.display(graph, partials).to_string()); diff --git a/stack-graphs/tests/it/can_find_root_partial_paths_in_database.rs b/stack-graphs/tests/it/can_find_root_partial_paths_in_database.rs index a70336333..616f9655c 100644 --- a/stack-graphs/tests/it/can_find_root_partial_paths_in_database.rs +++ b/stack-graphs/tests/it/can_find_root_partial_paths_in_database.rs @@ -17,6 +17,7 @@ use stack_graphs::partial::PartialScopedSymbol; use stack_graphs::partial::PartialSymbolStack; use stack_graphs::stitching::Database; use stack_graphs::stitching::ForwardPartialPathStitcher; +use stack_graphs::stitching::StitcherConfig; use stack_graphs::NoCancellation; use crate::test_graphs; @@ -34,6 +35,7 @@ fn check_root_partial_paths( graph, &mut partials, file, + &StitcherConfig::default(), &NoCancellation, |graph, partials, path| { db.add_partial_path(graph, partials, path.clone()); diff --git a/stack-graphs/tests/it/can_jump_to_definition.rs b/stack-graphs/tests/it/can_jump_to_definition.rs index 965207f4c..db288855c 100644 --- a/stack-graphs/tests/it/can_jump_to_definition.rs +++ b/stack-graphs/tests/it/can_jump_to_definition.rs @@ -12,6 +12,7 @@ use stack_graphs::graph::StackGraph; use stack_graphs::partial::PartialPaths; use stack_graphs::stitching::ForwardPartialPathStitcher; use stack_graphs::stitching::GraphEdgeCandidates; +use stack_graphs::stitching::StitcherConfig; use stack_graphs::NoCancellation; use crate::test_graphs; @@ -25,6 +26,7 @@ fn check_jump_to_definition(graph: &StackGraph, expected_paths: &[&str]) { ForwardPartialPathStitcher::find_all_complete_partial_paths( &mut GraphEdgeCandidates::new(graph, &mut paths, None), references, + &StitcherConfig::default(), &NoCancellation, |graph, paths, path| { results.insert(path.display(graph, paths).to_string()); diff --git a/stack-graphs/tests/it/can_jump_to_definition_with_forward_partial_path_stitching.rs b/stack-graphs/tests/it/can_jump_to_definition_with_forward_partial_path_stitching.rs index d45e96afc..32e225a9c 100644 --- a/stack-graphs/tests/it/can_jump_to_definition_with_forward_partial_path_stitching.rs +++ b/stack-graphs/tests/it/can_jump_to_definition_with_forward_partial_path_stitching.rs @@ -13,6 +13,7 @@ use stack_graphs::partial::PartialPaths; use stack_graphs::stitching::Database; use stack_graphs::stitching::DatabaseCandidates; use stack_graphs::stitching::ForwardPartialPathStitcher; +use stack_graphs::stitching::StitcherConfig; use stack_graphs::NoCancellation; use crate::test_graphs; @@ -27,6 +28,7 @@ fn check_jump_to_definition(graph: &StackGraph, expected_partial_paths: &[&str]) graph, &mut partials, file, + &StitcherConfig::default(), &NoCancellation, |graph, partials, path| { db.add_partial_path(graph, partials, path.clone()); @@ -42,6 +44,7 @@ fn check_jump_to_definition(graph: &StackGraph, expected_partial_paths: &[&str]) ForwardPartialPathStitcher::find_all_complete_partial_paths( &mut DatabaseCandidates::new(graph, &mut partials, &mut db), references, + &StitcherConfig::default(), &NoCancellation, |_, _, p| { complete_partial_paths.push(p.clone()); diff --git a/stack-graphs/tests/it/cycles.rs b/stack-graphs/tests/it/cycles.rs index 12c8b5672..abcd43048 100644 --- a/stack-graphs/tests/it/cycles.rs +++ b/stack-graphs/tests/it/cycles.rs @@ -16,6 +16,7 @@ use stack_graphs::partial::PartialPaths; use stack_graphs::stitching::Database; use stack_graphs::stitching::ForwardPartialPathStitcher; use stack_graphs::stitching::GraphEdges; +use stack_graphs::stitching::StitcherConfig; use stack_graphs::CancelAfterDuration; use std::time::Duration; @@ -199,6 +200,7 @@ fn finding_simple_identity_cycle_is_detected() { &graph, &mut partials, file, + &StitcherConfig::default(), &cancellation_flag, |_, _, _| path_count += 1, ); @@ -292,6 +294,7 @@ fn finding_composite_identity_cycle_is_detected() { &graph, &mut partials, file, + &StitcherConfig::default(), &cancellation_flag, |_, _, _| path_count += 1, ); @@ -353,6 +356,7 @@ fn appending_eliminating_cycle_terminates() { &graph, &mut partials, file, + &StitcherConfig::default(), &cancellation_flag, |_, _, _| path_count += 1, ); diff --git a/stack-graphs/tests/it/serde.rs b/stack-graphs/tests/it/serde.rs index 04679f353..c9c047d10 100644 --- a/stack-graphs/tests/it/serde.rs +++ b/stack-graphs/tests/it/serde.rs @@ -12,7 +12,7 @@ use stack_graphs::graph; use stack_graphs::graph::StackGraph; use stack_graphs::partial::PartialPaths; use stack_graphs::serde; -use stack_graphs::stitching::{Database, ForwardPartialPathStitcher}; +use stack_graphs::stitching::{Database, ForwardPartialPathStitcher, StitcherConfig}; use stack_graphs::NoCancellation; use crate::test_graphs; @@ -984,6 +984,7 @@ fn can_serialize_partial_paths() { &graph, &mut partials, file, + &StitcherConfig::default(), &NoCancellation, |g, ps, p| { db.add_partial_path(g, ps, p.clone()); diff --git a/tree-sitter-stack-graphs/src/cli/index.rs b/tree-sitter-stack-graphs/src/cli/index.rs index a90056f4b..882185108 100644 --- a/tree-sitter-stack-graphs/src/cli/index.rs +++ b/tree-sitter-stack-graphs/src/cli/index.rs @@ -316,6 +316,16 @@ impl<'a> Indexer<'a> { .add_file(&source_path.to_string_lossy()) .expect("file not present in empty graph"); + // FIXME We use the stitching config of the primary language here, which is not quite right. + // Ideally we'd use the primary language's stitcher config for computing the paths in + // the primary graph, and similarly for the secondary languages. However, that is not + // much use at the moment, since we use paths from all languages when reading from the + // database. Fixing this properly requires more isolation of graph and paths per language. + let stitcher_config = lcs + .primary + .map(|lc| lc.stitcher_config.clone()) + .unwrap_or_default(); + let result = Self::build_stack_graph( &mut graph, file, @@ -355,6 +365,7 @@ impl<'a> Indexer<'a> { &graph, &mut partials, file, + &stitcher_config, &(&cancellation_flag as &dyn CancellationFlag), |_g, _ps, p| { paths.push(p.clone()); diff --git a/tree-sitter-stack-graphs/src/cli/init.rs b/tree-sitter-stack-graphs/src/cli/init.rs index e87785477..c287909e6 100644 --- a/tree-sitter-stack-graphs/src/cli/init.rs +++ b/tree-sitter-stack-graphs/src/cli/init.rs @@ -721,6 +721,7 @@ impl ProjectSettings<'_> { use tree_sitter_stack_graphs::loader::FileAnalyzers; use tree_sitter_stack_graphs::loader::LanguageConfiguration; use tree_sitter_stack_graphs::loader::LoadError; + use tree_sitter_stack_graphs::loader::StitcherConfig; use tree_sitter_stack_graphs::CancellationFlag; /// The stack graphs tsg source for this language. @@ -758,6 +759,7 @@ impl ProjectSettings<'_> { )), Some(STACK_GRAPHS_BUILTINS_CONFIG), FileAnalyzers::new(), + StitcherConfig::default(), cancellation_flag, ) }} diff --git a/tree-sitter-stack-graphs/src/cli/query.rs b/tree-sitter-stack-graphs/src/cli/query.rs index 08ede0b93..3a9c4d47f 100644 --- a/tree-sitter-stack-graphs/src/cli/query.rs +++ b/tree-sitter-stack-graphs/src/cli/query.rs @@ -10,6 +10,7 @@ use clap::Parser; use clap::Subcommand; use clap::ValueHint; use stack_graphs::stitching::ForwardPartialPathStitcher; +use stack_graphs::stitching::StitcherConfig; use stack_graphs::storage::FileStatus; use stack_graphs::storage::SQLiteReader; use std::path::Path; @@ -185,9 +186,16 @@ impl<'a> Querier<'a> { }; let mut reference_paths = Vec::new(); + // FIXME We use the default stitcher config here, because we currently do not retrieve language + // configurations during querying. A first step to fixing this would be to lookup the language + // corresponding to the file that is queried. However, to solve this properly we would need to + // isolate graphs and paths per language so we don't accidently mix different languages that + // require different stitcher settings. + let config = StitcherConfig::default(); if let Err(err) = ForwardPartialPathStitcher::find_all_complete_partial_paths( self.db, std::iter::once(node), + &config, &cancellation_flag, |_g, _ps, p| { reference_paths.push(p.clone()); diff --git a/tree-sitter-stack-graphs/src/cli/test.rs b/tree-sitter-stack-graphs/src/cli/test.rs index 4bcb47171..e4bd690a5 100644 --- a/tree-sitter-stack-graphs/src/cli/test.rs +++ b/tree-sitter-stack-graphs/src/cli/test.rs @@ -18,6 +18,7 @@ use stack_graphs::serde::Filter; use stack_graphs::stitching::Database; use stack_graphs::stitching::DatabaseCandidates; use stack_graphs::stitching::ForwardPartialPathStitcher; +use stack_graphs::stitching::StitcherConfig; use std::path::Path; use std::path::PathBuf; use std::time::Duration; @@ -331,13 +332,19 @@ impl TestArgs { &test.graph, &mut partials, file, + &lc.stitcher_config, &cancellation_flag.as_ref(), |g, ps, p| { db.add_partial_path(g, ps, p.clone()); }, )?; } - let result = test.run(&mut partials, &mut db, cancellation_flag.as_ref())?; + let result = test.run( + &mut partials, + &mut db, + &lc.stitcher_config, + cancellation_flag.as_ref(), + )?; let success = result.failure_count() == 0; let outputs = if self.output_mode.test(!success) { let files = test.fragments.iter().map(|f| f.file).collect::>(); @@ -349,6 +356,7 @@ impl TestArgs { &mut db, &|_: &StackGraph, h: &Handle| files.contains(h), success, + &lc.stitcher_config, cancellation_flag.as_ref(), )? } else { @@ -397,6 +405,7 @@ impl TestArgs { db: &mut Database, filter: &dyn Filter, success: bool, + stitcher_config: &StitcherConfig, cancellation_flag: &dyn CancellationFlag, ) -> anyhow::Result> { let mut outputs = Vec::with_capacity(3); @@ -425,7 +434,14 @@ impl TestArgs { } let mut db = if save_paths.is_some() || save_visualization.is_some() { - self.compute_paths(graph, partials, db, filter, cancellation_flag)? + self.compute_paths( + graph, + partials, + db, + filter, + stitcher_config, + cancellation_flag, + )? } else { Database::new() }; @@ -474,6 +490,7 @@ impl TestArgs { partials: &mut PartialPaths, db: &mut Database, filter: &dyn Filter, + stitcher_config: &StitcherConfig, cancellation_flag: &dyn CancellationFlag, ) -> anyhow::Result { let references = graph @@ -484,6 +501,7 @@ impl TestArgs { ForwardPartialPathStitcher::find_all_complete_partial_paths( &mut DatabaseCandidates::new(graph, partials, db), references.clone(), + stitcher_config, &cancellation_flag, |_, _, p| { paths.push(p.clone()); diff --git a/tree-sitter-stack-graphs/src/cli/visualize.rs b/tree-sitter-stack-graphs/src/cli/visualize.rs index e0665c353..acffbc9ce 100644 --- a/tree-sitter-stack-graphs/src/cli/visualize.rs +++ b/tree-sitter-stack-graphs/src/cli/visualize.rs @@ -10,6 +10,7 @@ use clap::ValueHint; use stack_graphs::serde::NoFilter; use stack_graphs::stitching::Database; use stack_graphs::stitching::ForwardPartialPathStitcher; +use stack_graphs::stitching::StitcherConfig; use stack_graphs::storage::SQLiteReader; use stack_graphs::NoCancellation; use std::path::Path; @@ -54,9 +55,16 @@ impl VisualizeArgs { .filter(|n| graph[*n].is_reference()) .collect::>(); let mut complete_paths_db = Database::new(); + // FIXME We use the default stitcher config here, because we currently do not retrieve language + // configurations during querying. A first step to fixing this would be to lookup the language + // corresponding to the file that is queried. However, to solve this properly we would need to + // isolate graphs and paths per language so we don't accidently mix different languages that + // require different stitcher settings. + let config = StitcherConfig::default(); ForwardPartialPathStitcher::find_all_complete_partial_paths( &mut db, starting_nodes, + &config, cancellation_flag, |g, ps, p| { complete_paths_db.add_partial_path(g, ps, p.clone()); diff --git a/tree-sitter-stack-graphs/src/loader.rs b/tree-sitter-stack-graphs/src/loader.rs index 0feb6a28c..6464687fe 100644 --- a/tree-sitter-stack-graphs/src/loader.rs +++ b/tree-sitter-stack-graphs/src/loader.rs @@ -26,6 +26,8 @@ use tree_sitter_loader::Config as TsConfig; use tree_sitter_loader::LanguageConfiguration as TSLanguageConfiguration; use tree_sitter_loader::Loader as TsLoader; +pub use stack_graphs::stitching::StitcherConfig; + use crate::CancellationFlag; use crate::FileAnalyzer; use crate::StackGraphLanguage; @@ -44,6 +46,7 @@ pub struct LanguageConfiguration { pub sgl: StackGraphLanguage, pub builtins: StackGraph, pub special_files: FileAnalyzers, + pub stitcher_config: StitcherConfig, } impl LanguageConfiguration { @@ -59,6 +62,7 @@ impl LanguageConfiguration { builtins_source: Option<(PathBuf, &'a str)>, builtins_config: Option<&str>, special_files: FileAnalyzers, + stitcher_config: StitcherConfig, cancellation_flag: &dyn CancellationFlag, ) -> Result> { let sgl = StackGraphLanguage::from_source(language, tsg_path.clone(), tsg_source).map_err( @@ -98,6 +102,7 @@ impl LanguageConfiguration { sgl, builtins, special_files, + stitcher_config, }) } @@ -568,6 +573,7 @@ impl PathLoader { sgl, builtins, special_files: FileAnalyzers::new(), + stitcher_config: StitcherConfig::default(), // FIXME we do not have a place for this configuration }; self.cache.push((language.language, lc)); diff --git a/tree-sitter-stack-graphs/src/test.rs b/tree-sitter-stack-graphs/src/test.rs index 19abda61d..8f3c20c29 100644 --- a/tree-sitter-stack-graphs/src/test.rs +++ b/tree-sitter-stack-graphs/src/test.rs @@ -74,6 +74,7 @@ use stack_graphs::graph::SourceInfo; use stack_graphs::graph::StackGraph; use stack_graphs::partial::PartialPaths; use stack_graphs::stitching::Database; +use stack_graphs::stitching::StitcherConfig; use std::collections::HashMap; use std::path::Path; use std::path::PathBuf; @@ -623,13 +624,20 @@ impl Test { &mut self, partials: &mut PartialPaths, db: &mut Database, + stitcher_config: &StitcherConfig, cancellation_flag: &dyn CancellationFlag, ) -> Result { let mut result = TestResult::new(); for fragment in &self.fragments { for assertion in &fragment.assertions { match assertion - .run(&self.graph, partials, db, &cancellation_flag) + .run( + &self.graph, + partials, + db, + stitcher_config, + &cancellation_flag, + ) .map_or_else(|e| self.from_error(e), |v| Ok(v)) { Ok(_) => result.add_success(), diff --git a/tree-sitter-stack-graphs/tests/it/loader.rs b/tree-sitter-stack-graphs/tests/it/loader.rs index 8fcf0ccac..7525b6fcf 100644 --- a/tree-sitter-stack-graphs/tests/it/loader.rs +++ b/tree-sitter-stack-graphs/tests/it/loader.rs @@ -8,6 +8,7 @@ use once_cell::sync::Lazy; use pretty_assertions::assert_eq; use stack_graphs::graph::StackGraph; +use stack_graphs::stitching::StitcherConfig; use std::path::PathBuf; use tree_sitter_stack_graphs::loader::FileAnalyzers; use tree_sitter_stack_graphs::loader::LanguageConfiguration; @@ -35,6 +36,7 @@ fn can_load_from_provided_language_configuration() { sgl, builtins: StackGraph::new(), special_files: FileAnalyzers::new(), + stitcher_config: StitcherConfig::default(), }; let mut loader = Loader::from_language_configurations(vec![lc], None).expect("Expected loader to succeed"); diff --git a/tree-sitter-stack-graphs/tests/it/test.rs b/tree-sitter-stack-graphs/tests/it/test.rs index b281f283b..483ad011b 100644 --- a/tree-sitter-stack-graphs/tests/it/test.rs +++ b/tree-sitter-stack-graphs/tests/it/test.rs @@ -13,6 +13,7 @@ use stack_graphs::graph::StackGraph; use stack_graphs::partial::PartialPaths; use stack_graphs::stitching::Database; use stack_graphs::stitching::ForwardPartialPathStitcher; +use stack_graphs::stitching::StitcherConfig; use std::path::Path; use std::path::PathBuf; use tree_sitter_graph::Variables; @@ -113,6 +114,7 @@ fn check_test( &test.graph, &mut partials, fragment.file, + &StitcherConfig::default(), &stack_graphs::NoCancellation, |graph, partials, path| { db.add_partial_path(graph, partials, path.clone()); @@ -122,7 +124,12 @@ fn check_test( } let results = test - .run(&mut partials, &mut db, &NoCancellation) + .run( + &mut partials, + &mut db, + &StitcherConfig::default(), + &NoCancellation, + ) .expect("should never be cancelled"); assert_eq!( expected_successes, From 2216fda05fd72da4accca88df8edb4db1ffbc013 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 13 Nov 2023 11:59:07 +0100 Subject: [PATCH 266/500] Use stitcher config only for functions that wrap a stitcher, not for stitcher itself --- .../tree-sitter-stack-graphs-java/rust/lib.rs | 4 - .../rust/lib.rs | 2 - stack-graphs/include/stack-graphs.h | 10 +- stack-graphs/src/assert.rs | 4 +- stack-graphs/src/c.rs | 21 ++-- stack-graphs/src/stitching.rs | 113 ++++++++++-------- .../tests/it/c/can_find_local_nodes.rs | 4 +- .../it/c/can_find_partial_paths_in_file.rs | 4 +- ...ions_with_phased_partial_path_stitching.rs | 8 +- .../tests/it/c/can_jump_to_definition.rs | 4 +- ...tion_with_phased_partial_path_stitching.rs | 8 +- stack-graphs/tests/it/can_find_local_nodes.rs | 2 +- ...can_find_node_partial_paths_in_database.rs | 2 +- .../it/can_find_partial_paths_in_file.rs | 2 +- ...can_find_root_partial_paths_in_database.rs | 2 +- .../tests/it/can_jump_to_definition.rs | 2 +- ...ion_with_forward_partial_path_stitching.rs | 4 +- stack-graphs/tests/it/cycles.rs | 6 +- stack-graphs/tests/it/serde.rs | 2 +- tree-sitter-stack-graphs/src/cli/index.rs | 13 +- tree-sitter-stack-graphs/src/cli/query.rs | 8 +- tree-sitter-stack-graphs/src/cli/test.rs | 10 +- tree-sitter-stack-graphs/src/cli/visualize.rs | 8 +- tree-sitter-stack-graphs/src/loader.rs | 6 - tree-sitter-stack-graphs/src/test.rs | 2 +- tree-sitter-stack-graphs/tests/it/loader.rs | 2 - tree-sitter-stack-graphs/tests/it/test.rs | 4 +- 27 files changed, 110 insertions(+), 147 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-java/rust/lib.rs b/languages/tree-sitter-stack-graphs-java/rust/lib.rs index d1af5bb12..09cb043a5 100644 --- a/languages/tree-sitter-stack-graphs-java/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-java/rust/lib.rs @@ -1,7 +1,6 @@ use tree_sitter_stack_graphs::loader::FileAnalyzers; use tree_sitter_stack_graphs::loader::LanguageConfiguration; use tree_sitter_stack_graphs::loader::LoadError; -use tree_sitter_stack_graphs::loader::StitcherConfig; use tree_sitter_stack_graphs::CancellationFlag; /// The stacks graphs tsg path for this language. @@ -41,9 +40,6 @@ pub fn try_language_configuration( )), Some(STACK_GRAPHS_BUILTINS_CONFIG), FileAnalyzers::new(), - StitcherConfig { - detect_similar_paths: true, - }, cancellation_flag, ) } diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs index 9ef2f1805..45ce6d255 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs @@ -8,7 +8,6 @@ use tree_sitter_stack_graphs::loader::FileAnalyzers; use tree_sitter_stack_graphs::loader::LanguageConfiguration; use tree_sitter_stack_graphs::loader::LoadError; -use tree_sitter_stack_graphs::loader::StitcherConfig; use tree_sitter_stack_graphs::CancellationFlag; use crate::npm_package::NpmPackageAnalyzer; @@ -57,7 +56,6 @@ pub fn try_language_configuration( FileAnalyzers::new() .add("tsconfig.json".to_string(), TsConfigAnalyzer {}) .add("package.json".to_string(), NpmPackageAnalyzer {}), - StitcherConfig::default(), cancellation_flag, ) } diff --git a/stack-graphs/include/stack-graphs.h b/stack-graphs/include/stack-graphs.h index a1afe93dd..aeac9e636 100644 --- a/stack-graphs/include/stack-graphs.h +++ b/stack-graphs/include/stack-graphs.h @@ -738,7 +738,7 @@ enum sg_result sg_partial_path_arena_find_partial_paths_in_file(const struct sg_ struct sg_partial_path_arena *partials, sg_file_handle file, struct sg_partial_path_list *partial_path_list, - struct sg_stitcher_config config, + const struct sg_stitcher_config *stitcher_config, const size_t *cancellation_flag); // Finds all complete paths reachable from a set of starting nodes, placing the result into the @@ -754,7 +754,7 @@ enum sg_result sg_partial_path_arena_find_all_complete_paths(const struct sg_sta size_t starting_node_count, const sg_node_handle *starting_nodes, struct sg_partial_path_list *path_list, - struct sg_stitcher_config config, + const struct sg_stitcher_config *stitcher_config, const size_t *cancellation_flag); // Returns a reference to the array of partial path data in this partial path database. The @@ -812,16 +812,14 @@ struct sg_node_handle_set sg_partial_path_database_local_nodes(const struct sg_p struct sg_forward_partial_path_stitcher *sg_forward_partial_path_stitcher_from_nodes(const struct sg_stack_graph *graph, struct sg_partial_path_arena *partials, size_t count, - const sg_node_handle *starting_nodes, - struct sg_stitcher_config config); + const sg_node_handle *starting_nodes); // Creates a new forward partial path stitcher that is "seeded" with a set of initial partial // paths. struct sg_forward_partial_path_stitcher *sg_forward_partial_path_stitcher_from_partial_paths(const struct sg_stack_graph *graph, struct sg_partial_path_arena *partials, size_t count, - const struct sg_partial_path *initial_partial_paths, - struct sg_stitcher_config config); + const struct sg_partial_path *initial_partial_paths); // Sets whether similar path detection should be enabled during path stitching. Paths are similar // if start and end node, and pre- and postconditions are the same. The presence of similar paths diff --git a/stack-graphs/src/assert.rs b/stack-graphs/src/assert.rs index 278caabbc..6e1190673 100644 --- a/stack-graphs/src/assert.rs +++ b/stack-graphs/src/assert.rs @@ -150,7 +150,7 @@ impl Assertion { graph: &StackGraph, partials: &mut PartialPaths, db: &mut Database, - stitcher_config: &StitcherConfig, + stitcher_config: StitcherConfig, cancellation_flag: &dyn CancellationFlag, ) -> Result<(), AssertionError> { match self { @@ -175,7 +175,7 @@ impl Assertion { db: &mut Database, source: &AssertionSource, expected_targets: &Vec, - stitcher_config: &StitcherConfig, + stitcher_config: StitcherConfig, cancellation_flag: &dyn CancellationFlag, ) -> Result<(), AssertionError> { let references = source.iter_references(graph).collect::>(); diff --git a/stack-graphs/src/c.rs b/stack-graphs/src/c.rs index 4f58caff2..26a823eba 100644 --- a/stack-graphs/src/c.rs +++ b/stack-graphs/src/c.rs @@ -1174,20 +1174,21 @@ pub extern "C" fn sg_partial_path_arena_find_partial_paths_in_file( partials: *mut sg_partial_path_arena, file: sg_file_handle, partial_path_list: *mut sg_partial_path_list, - config: sg_stitcher_config, + stitcher_config: *const sg_stitcher_config, cancellation_flag: *const usize, ) -> sg_result { let graph = unsafe { &(*graph).inner }; let partials = unsafe { &mut (*partials).inner }; let file = file.into(); let partial_path_list = unsafe { &mut *partial_path_list }; + let stitcher_config = unsafe { *stitcher_config }; let cancellation_flag: Option<&AtomicUsize> = unsafe { std::mem::transmute(cancellation_flag.as_ref()) }; ForwardPartialPathStitcher::find_minimal_partial_path_set_in_file( graph, partials, file, - &config.into(), + stitcher_config.into(), &AtomicUsizeCancellationFlag(cancellation_flag), |_graph, partials, path| { let mut path = path.clone(); @@ -1213,19 +1214,20 @@ pub extern "C" fn sg_partial_path_arena_find_all_complete_paths( starting_node_count: usize, starting_nodes: *const sg_node_handle, path_list: *mut sg_partial_path_list, - config: sg_stitcher_config, + stitcher_config: *const sg_stitcher_config, cancellation_flag: *const usize, ) -> sg_result { let graph = unsafe { &(*graph).inner }; let partials = unsafe { &mut (*partials).inner }; let starting_nodes = unsafe { std::slice::from_raw_parts(starting_nodes, starting_node_count) }; + let stitcher_config = unsafe { *stitcher_config }; let path_list = unsafe { &mut *path_list }; let cancellation_flag: Option<&AtomicUsize> = unsafe { std::mem::transmute(cancellation_flag.as_ref()) }; ForwardPartialPathStitcher::find_all_complete_partial_paths( &mut GraphEdgeCandidates::new(graph, partials, None), starting_nodes.iter().copied().map(sg_node_handle::into), - &config.into(), + stitcher_config.into(), &AtomicUsizeCancellationFlag(cancellation_flag), |graph, _partials, path| { if path.is_complete(graph) { @@ -1398,6 +1400,7 @@ pub struct sg_forward_partial_path_stitcher { // Configuration for partial path stitchers. #[repr(C)] +#[derive(Clone, Copy)] pub struct sg_stitcher_config { /// Enables similar path detection during stiching. pub detect_similar_paths: bool, @@ -1461,7 +1464,6 @@ pub extern "C" fn sg_forward_partial_path_stitcher_from_nodes( partials: *mut sg_partial_path_arena, count: usize, starting_nodes: *const sg_node_handle, - config: sg_stitcher_config, ) -> *mut sg_forward_partial_path_stitcher { let graph = unsafe { &(*graph).inner }; let partials = unsafe { &mut (*partials).inner }; @@ -1476,12 +1478,7 @@ pub extern "C" fn sg_forward_partial_path_stitcher_from_nodes( p }) .collect::>(); - let stitcher = ForwardPartialPathStitcher::from_partial_paths( - graph, - partials, - initial_paths, - &config.into(), - ); + let stitcher = ForwardPartialPathStitcher::from_partial_paths(graph, partials, initial_paths); Box::into_raw(Box::new(InternalForwardPartialPathStitcher::new( stitcher, partials, ))) as *mut _ @@ -1495,7 +1492,6 @@ pub extern "C" fn sg_forward_partial_path_stitcher_from_partial_paths( partials: *mut sg_partial_path_arena, count: usize, initial_partial_paths: *const sg_partial_path, - config: sg_stitcher_config, ) -> *mut sg_forward_partial_path_stitcher { let graph = unsafe { &(*graph).inner }; let partials = unsafe { &mut (*partials).inner }; @@ -1505,7 +1501,6 @@ pub extern "C" fn sg_forward_partial_path_stitcher_from_partial_paths( graph, partials, initial_partial_paths.to_vec(), - &config.into(), ); Box::into_raw(Box::new(InternalForwardPartialPathStitcher::new( stitcher, partials, diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index dc7cb8c9b..1432669dd 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -795,13 +795,6 @@ impl<'a> Display for DisplaySymbolStackKey<'a> { //------------------------------------------------------------------------------------------------- // Stitching partial paths together -/// Configuration for partial path stitchers. -#[derive(Clone, Debug, Default)] -pub struct StitcherConfig { - /// Enables similar path detection during path stitching. - pub detect_similar_paths: bool, -} - /// Implements a phased forward partial path stitching algorithm. /// /// Our overall goal is to start with a set of _seed_ partial paths, and to repeatedly extend each @@ -858,7 +851,6 @@ impl ForwardPartialPathStitcher { _graph: &StackGraph, _partials: &mut PartialPaths, initial_partial_paths: I, - config: &StitcherConfig, ) -> Self where I: IntoIterator, @@ -871,16 +863,14 @@ impl ForwardPartialPathStitcher { (p, c, false) }) .multiunzip(); - let similar_path_detector = - Some(SimilarPathDetector::new()).filter(|_| config.detect_similar_paths); - ForwardPartialPathStitcher { + Self { candidates: Vec::new(), extensions: Vec::new(), queue: VecDeque::new(), initial_paths: next_iteration.0.len(), next_iteration, appended_paths, - similar_path_detector, + similar_path_detector: Some(SimilarPathDetector::new()), // By default, all nodes are checked for cycles and (if enabled) similarity check_only_join_nodes: false, // By default, there's no artificial bound on the amount of work done per phase @@ -889,28 +879,6 @@ impl ForwardPartialPathStitcher { phase_number: 1, } } -} - -impl ForwardPartialPathStitcher { - /// Returns an iterator of all of the (possibly incomplete) partial paths that were encountered - /// during the most recent phase of the algorithm. - pub fn previous_phase_partial_paths(&self) -> impl Iterator + '_ { - self.next_iteration.0.iter() - } - - /// Returns a slice of all of the (possibly incomplete) partial paths that were encountered - /// during the most recent phase of the algorithm. - pub fn previous_phase_partial_paths_slice(&mut self) -> &[PartialPath] { - self.next_iteration.0.make_contiguous(); - self.next_iteration.0.as_slices().0 - } - - /// Returns a mutable slice of all of the (possibly incomplete) partial paths that were - /// encountered during the most recent phase of the algorithm. - pub fn previous_phase_partial_paths_slice_mut(&mut self) -> &mut [PartialPath] { - self.next_iteration.0.make_contiguous(); - self.next_iteration.0.as_mut_slices().0 - } /// Sets whether similar path detection should be enabled during path stitching. Paths are similar /// if start and end node, and pre- and postconditions are the same. The presence of similar paths @@ -940,6 +908,28 @@ impl ForwardPartialPathStitcher { pub fn set_max_work_per_phase(&mut self, max_work_per_phase: usize) { self.max_work_per_phase = max_work_per_phase; } +} + +impl ForwardPartialPathStitcher { + /// Returns an iterator of all of the (possibly incomplete) partial paths that were encountered + /// during the most recent phase of the algorithm. + pub fn previous_phase_partial_paths(&self) -> impl Iterator + '_ { + self.next_iteration.0.iter() + } + + /// Returns a slice of all of the (possibly incomplete) partial paths that were encountered + /// during the most recent phase of the algorithm. + pub fn previous_phase_partial_paths_slice(&mut self) -> &[PartialPath] { + self.next_iteration.0.make_contiguous(); + self.next_iteration.0.as_slices().0 + } + + /// Returns a mutable slice of all of the (possibly incomplete) partial paths that were + /// encountered during the most recent phase of the algorithm. + pub fn previous_phase_partial_paths_slice_mut(&mut self) -> &mut [PartialPath] { + self.next_iteration.0.make_contiguous(); + self.next_iteration.0.as_mut_slices().0 + } /// Attempts to extend one partial path as part of the algorithm. When calling this function, /// you are responsible for ensuring that `db` already contains all of the possible appendables @@ -1155,7 +1145,7 @@ impl ForwardPartialPathStitcher { graph: &StackGraph, partials: &mut PartialPaths, file: Handle, - config: &StitcherConfig, + config: StitcherConfig, cancellation_flag: &dyn CancellationFlag, mut visit: F, ) -> Result<(), CancellationError> @@ -1174,7 +1164,8 @@ impl ForwardPartialPathStitcher { .map(|node| PartialPath::from_node(graph, partials, node)) .collect::>(); let mut stitcher = - ForwardPartialPathStitcher::from_partial_paths(graph, partials, initial_paths, config); + ForwardPartialPathStitcher::from_partial_paths(graph, partials, initial_paths); + config.apply(&mut stitcher); stitcher.set_check_only_join_nodes(true); while !stitcher.is_complete() { cancellation_flag.check("finding complete partial paths")?; @@ -1207,7 +1198,7 @@ impl ForwardPartialPathStitcher { pub fn find_all_complete_partial_paths( candidates: &mut C, starting_nodes: I, - config: &StitcherConfig, + config: StitcherConfig, cancellation_flag: &dyn CancellationFlag, mut visit: F, ) -> Result<(), Err> @@ -1219,19 +1210,19 @@ impl ForwardPartialPathStitcher { F: FnMut(&StackGraph, &mut PartialPaths, &PartialPath), Err: std::convert::From, { - let mut stitcher = { - let (graph, partials, _) = candidates.get_graph_partials_and_db(); - let initial_paths = starting_nodes - .into_iter() - .filter(|n| graph[*n].is_reference()) - .map(|n| { - let mut p = PartialPath::from_node(graph, partials, n); - p.eliminate_precondition_stack_variables(partials); - p - }) - .collect::>(); - ForwardPartialPathStitcher::from_partial_paths(graph, partials, initial_paths, config) - }; + let (graph, partials, _) = candidates.get_graph_partials_and_db(); + let initial_paths = starting_nodes + .into_iter() + .filter(|n| graph[*n].is_reference()) + .map(|n| { + let mut p = PartialPath::from_node(graph, partials, n); + p.eliminate_precondition_stack_variables(partials); + p + }) + .collect::>(); + let mut stitcher = + ForwardPartialPathStitcher::from_partial_paths(graph, partials, initial_paths); + config.apply(&mut stitcher); stitcher.set_check_only_join_nodes(true); while !stitcher.is_complete() { cancellation_flag.check("finding complete partial paths")?; @@ -1249,3 +1240,25 @@ impl ForwardPartialPathStitcher { Ok(()) } } + +/// Configuration for partial path stitchers. +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct StitcherConfig { + /// Enables similar path detection during path stitching. + pub detect_similar_paths: bool, +} + +impl StitcherConfig { + fn apply(&self, stitcher: &mut ForwardPartialPathStitcher) { + stitcher.set_similar_path_detection(self.detect_similar_paths); + } +} + +impl Default for StitcherConfig { + fn default() -> Self { + Self { + detect_similar_paths: true, + } + } +} diff --git a/stack-graphs/tests/it/c/can_find_local_nodes.rs b/stack-graphs/tests/it/c/can_find_local_nodes.rs index 2d2ecdee5..9fbf31859 100644 --- a/stack-graphs/tests/it/c/can_find_local_nodes.rs +++ b/stack-graphs/tests/it/c/can_find_local_nodes.rs @@ -34,7 +34,7 @@ fn check_local_nodes(graph: &TestGraph, file: &str, expected_local_nodes: &[&str let partials = sg_partial_path_arena_new(); let path_list = sg_partial_path_list_new(); - let config = sg_stitcher_config { + let stitcher_config = sg_stitcher_config { detect_similar_paths: false, }; sg_partial_path_arena_find_partial_paths_in_file( @@ -42,7 +42,7 @@ fn check_local_nodes(graph: &TestGraph, file: &str, expected_local_nodes: &[&str partials, file.as_u32(), path_list, - config, + &stitcher_config, std::ptr::null(), ); diff --git a/stack-graphs/tests/it/c/can_find_partial_paths_in_file.rs b/stack-graphs/tests/it/c/can_find_partial_paths_in_file.rs index 65ab8e2c2..ae93f84be 100644 --- a/stack-graphs/tests/it/c/can_find_partial_paths_in_file.rs +++ b/stack-graphs/tests/it/c/can_find_partial_paths_in_file.rs @@ -78,7 +78,7 @@ fn check_partial_paths_in_file(graph: &TestGraph, file: &str, expected_paths: &[ let partials = sg_partial_path_arena_new(); let path_list = sg_partial_path_list_new(); - let config = sg_stitcher_config { + let stitcher_config = sg_stitcher_config { detect_similar_paths: false, }; sg_partial_path_arena_find_partial_paths_in_file( @@ -86,7 +86,7 @@ fn check_partial_paths_in_file(graph: &TestGraph, file: &str, expected_paths: &[ partials, file.as_u32(), path_list, - config, + &stitcher_config, std::ptr::null(), ); diff --git a/stack-graphs/tests/it/c/can_find_qualified_definitions_with_phased_partial_path_stitching.rs b/stack-graphs/tests/it/c/can_find_qualified_definitions_with_phased_partial_path_stitching.rs index fe8594dee..613a54556 100644 --- a/stack-graphs/tests/it/c/can_find_qualified_definitions_with_phased_partial_path_stitching.rs +++ b/stack-graphs/tests/it/c/can_find_qualified_definitions_with_phased_partial_path_stitching.rs @@ -56,7 +56,7 @@ impl StorageLayer { let rust_graph = unsafe { &(*graph).inner }; let path_list = sg_partial_path_list_new(); for file in rust_graph.iter_files() { - let config = sg_stitcher_config { + let stitcher_config = sg_stitcher_config { detect_similar_paths: false, }; sg_partial_path_arena_find_partial_paths_in_file( @@ -64,7 +64,7 @@ impl StorageLayer { partials, file.as_u32(), path_list, - config, + &stitcher_config, std::ptr::null(), ); } @@ -122,9 +122,6 @@ fn check_find_qualified_definitions( let partials = sg_partial_path_arena_new(); let rust_partials = unsafe { &mut (*partials).inner }; let db = sg_partial_path_database_new(); - let config = sg_stitcher_config { - detect_similar_paths: false, - }; // Create a new external storage layer holding _all_ of the partial paths in the stack graph. let mut storage_layer = StorageLayer::new(graph.graph, partials); @@ -157,7 +154,6 @@ fn check_find_qualified_definitions( partials, 1, &initial_partial_path as *const PartialPath as *const _, - config, ); sg_forward_partial_path_stitcher_set_max_work_per_phase(stitcher, 1); let rust_stitcher = unsafe { &mut *stitcher }; diff --git a/stack-graphs/tests/it/c/can_jump_to_definition.rs b/stack-graphs/tests/it/c/can_jump_to_definition.rs index c00fe4cb1..aeea163f6 100644 --- a/stack-graphs/tests/it/c/can_jump_to_definition.rs +++ b/stack-graphs/tests/it/c/can_jump_to_definition.rs @@ -29,7 +29,7 @@ fn check_jump_to_definition(graph: &TestGraph, expected_paths: &[&str]) { .iter_nodes() .filter(|handle| rust_graph[*handle].is_reference()) .collect::>(); - let config = sg_stitcher_config { + let stitcher_config = sg_stitcher_config { detect_similar_paths: false, }; sg_partial_path_arena_find_all_complete_paths( @@ -38,7 +38,7 @@ fn check_jump_to_definition(graph: &TestGraph, expected_paths: &[&str]) { references.len(), references.as_ptr() as *const _, path_list, - config, + &stitcher_config, std::ptr::null(), ); diff --git a/stack-graphs/tests/it/c/can_jump_to_definition_with_phased_partial_path_stitching.rs b/stack-graphs/tests/it/c/can_jump_to_definition_with_phased_partial_path_stitching.rs index 3a23ab763..ce20ae378 100644 --- a/stack-graphs/tests/it/c/can_jump_to_definition_with_phased_partial_path_stitching.rs +++ b/stack-graphs/tests/it/c/can_jump_to_definition_with_phased_partial_path_stitching.rs @@ -50,7 +50,7 @@ impl StorageLayer { let rust_graph = unsafe { &(*graph).inner }; let path_list = sg_partial_path_list_new(); for file in rust_graph.iter_files() { - let config = sg_stitcher_config { + let stitcher_config = sg_stitcher_config { detect_similar_paths: false, }; sg_partial_path_arena_find_partial_paths_in_file( @@ -58,7 +58,7 @@ impl StorageLayer { partials, file.as_u32(), path_list, - config, + &stitcher_config, std::ptr::null(), ); } @@ -134,15 +134,11 @@ fn check_jump_to_definition(graph: &TestGraph, file: &str, expected_partial_path }); // Create the forward partial path stitcher. - let config = sg_stitcher_config { - detect_similar_paths: false, - }; let stitcher = sg_forward_partial_path_stitcher_from_nodes( graph.graph, partials, references.len(), references.as_ptr() as *const _, - config, ); sg_forward_partial_path_stitcher_set_max_work_per_phase(stitcher, 1); let rust_stitcher = unsafe { &mut *stitcher }; diff --git a/stack-graphs/tests/it/can_find_local_nodes.rs b/stack-graphs/tests/it/can_find_local_nodes.rs index 6b763b0d7..4f471d88f 100644 --- a/stack-graphs/tests/it/can_find_local_nodes.rs +++ b/stack-graphs/tests/it/can_find_local_nodes.rs @@ -25,7 +25,7 @@ fn check_local_nodes(graph: &StackGraph, file: &str, expected_local_nodes: &[&st graph, &mut partials, file, - &StitcherConfig::default(), + StitcherConfig::default(), &NoCancellation, |graph, partials, path| { database.add_partial_path(graph, partials, path.clone()); diff --git a/stack-graphs/tests/it/can_find_node_partial_paths_in_database.rs b/stack-graphs/tests/it/can_find_node_partial_paths_in_database.rs index 22d311d34..4e825c47e 100644 --- a/stack-graphs/tests/it/can_find_node_partial_paths_in_database.rs +++ b/stack-graphs/tests/it/can_find_node_partial_paths_in_database.rs @@ -34,7 +34,7 @@ fn check_node_partial_paths( graph, &mut partials, file, - &StitcherConfig::default(), + StitcherConfig::default(), &NoCancellation, |graph, partials, path| { db.add_partial_path(graph, partials, path.clone()); diff --git a/stack-graphs/tests/it/can_find_partial_paths_in_file.rs b/stack-graphs/tests/it/can_find_partial_paths_in_file.rs index d3e48e33f..adef36ae3 100644 --- a/stack-graphs/tests/it/can_find_partial_paths_in_file.rs +++ b/stack-graphs/tests/it/can_find_partial_paths_in_file.rs @@ -23,7 +23,7 @@ fn check_partial_paths_in_file(graph: &StackGraph, file: &str, expected_paths: & graph, &mut partials, file, - &StitcherConfig::default(), + StitcherConfig::default(), &NoCancellation, |graph, partials, path| { results.insert(path.display(graph, partials).to_string()); diff --git a/stack-graphs/tests/it/can_find_root_partial_paths_in_database.rs b/stack-graphs/tests/it/can_find_root_partial_paths_in_database.rs index 616f9655c..e8beff576 100644 --- a/stack-graphs/tests/it/can_find_root_partial_paths_in_database.rs +++ b/stack-graphs/tests/it/can_find_root_partial_paths_in_database.rs @@ -35,7 +35,7 @@ fn check_root_partial_paths( graph, &mut partials, file, - &StitcherConfig::default(), + StitcherConfig::default(), &NoCancellation, |graph, partials, path| { db.add_partial_path(graph, partials, path.clone()); diff --git a/stack-graphs/tests/it/can_jump_to_definition.rs b/stack-graphs/tests/it/can_jump_to_definition.rs index db288855c..70158f495 100644 --- a/stack-graphs/tests/it/can_jump_to_definition.rs +++ b/stack-graphs/tests/it/can_jump_to_definition.rs @@ -26,7 +26,7 @@ fn check_jump_to_definition(graph: &StackGraph, expected_paths: &[&str]) { ForwardPartialPathStitcher::find_all_complete_partial_paths( &mut GraphEdgeCandidates::new(graph, &mut paths, None), references, - &StitcherConfig::default(), + StitcherConfig::default(), &NoCancellation, |graph, paths, path| { results.insert(path.display(graph, paths).to_string()); diff --git a/stack-graphs/tests/it/can_jump_to_definition_with_forward_partial_path_stitching.rs b/stack-graphs/tests/it/can_jump_to_definition_with_forward_partial_path_stitching.rs index 32e225a9c..7f5996e3e 100644 --- a/stack-graphs/tests/it/can_jump_to_definition_with_forward_partial_path_stitching.rs +++ b/stack-graphs/tests/it/can_jump_to_definition_with_forward_partial_path_stitching.rs @@ -28,7 +28,7 @@ fn check_jump_to_definition(graph: &StackGraph, expected_partial_paths: &[&str]) graph, &mut partials, file, - &StitcherConfig::default(), + StitcherConfig::default(), &NoCancellation, |graph, partials, path| { db.add_partial_path(graph, partials, path.clone()); @@ -44,7 +44,7 @@ fn check_jump_to_definition(graph: &StackGraph, expected_partial_paths: &[&str]) ForwardPartialPathStitcher::find_all_complete_partial_paths( &mut DatabaseCandidates::new(graph, &mut partials, &mut db), references, - &StitcherConfig::default(), + StitcherConfig::default(), &NoCancellation, |_, _, p| { complete_partial_paths.push(p.clone()); diff --git a/stack-graphs/tests/it/cycles.rs b/stack-graphs/tests/it/cycles.rs index abcd43048..df840eba2 100644 --- a/stack-graphs/tests/it/cycles.rs +++ b/stack-graphs/tests/it/cycles.rs @@ -200,7 +200,7 @@ fn finding_simple_identity_cycle_is_detected() { &graph, &mut partials, file, - &StitcherConfig::default(), + StitcherConfig::default(), &cancellation_flag, |_, _, _| path_count += 1, ); @@ -294,7 +294,7 @@ fn finding_composite_identity_cycle_is_detected() { &graph, &mut partials, file, - &StitcherConfig::default(), + StitcherConfig::default(), &cancellation_flag, |_, _, _| path_count += 1, ); @@ -356,7 +356,7 @@ fn appending_eliminating_cycle_terminates() { &graph, &mut partials, file, - &StitcherConfig::default(), + StitcherConfig::default(), &cancellation_flag, |_, _, _| path_count += 1, ); diff --git a/stack-graphs/tests/it/serde.rs b/stack-graphs/tests/it/serde.rs index c9c047d10..3ecc1c48f 100644 --- a/stack-graphs/tests/it/serde.rs +++ b/stack-graphs/tests/it/serde.rs @@ -984,7 +984,7 @@ fn can_serialize_partial_paths() { &graph, &mut partials, file, - &StitcherConfig::default(), + StitcherConfig::default(), &NoCancellation, |g, ps, p| { db.add_partial_path(g, ps, p.clone()); diff --git a/tree-sitter-stack-graphs/src/cli/index.rs b/tree-sitter-stack-graphs/src/cli/index.rs index 882185108..436caca1a 100644 --- a/tree-sitter-stack-graphs/src/cli/index.rs +++ b/tree-sitter-stack-graphs/src/cli/index.rs @@ -12,6 +12,7 @@ use stack_graphs::graph::File; use stack_graphs::graph::StackGraph; use stack_graphs::partial::PartialPaths; use stack_graphs::stitching::ForwardPartialPathStitcher; +use stack_graphs::stitching::StitcherConfig; use stack_graphs::storage::FileStatus; use stack_graphs::storage::SQLiteWriter; use std::collections::HashMap; @@ -316,16 +317,6 @@ impl<'a> Indexer<'a> { .add_file(&source_path.to_string_lossy()) .expect("file not present in empty graph"); - // FIXME We use the stitching config of the primary language here, which is not quite right. - // Ideally we'd use the primary language's stitcher config for computing the paths in - // the primary graph, and similarly for the secondary languages. However, that is not - // much use at the moment, since we use paths from all languages when reading from the - // database. Fixing this properly requires more isolation of graph and paths per language. - let stitcher_config = lcs - .primary - .map(|lc| lc.stitcher_config.clone()) - .unwrap_or_default(); - let result = Self::build_stack_graph( &mut graph, file, @@ -365,7 +356,7 @@ impl<'a> Indexer<'a> { &graph, &mut partials, file, - &stitcher_config, + StitcherConfig::default(), &(&cancellation_flag as &dyn CancellationFlag), |_g, _ps, p| { paths.push(p.clone()); diff --git a/tree-sitter-stack-graphs/src/cli/query.rs b/tree-sitter-stack-graphs/src/cli/query.rs index 3a9c4d47f..1063e49e9 100644 --- a/tree-sitter-stack-graphs/src/cli/query.rs +++ b/tree-sitter-stack-graphs/src/cli/query.rs @@ -186,16 +186,10 @@ impl<'a> Querier<'a> { }; let mut reference_paths = Vec::new(); - // FIXME We use the default stitcher config here, because we currently do not retrieve language - // configurations during querying. A first step to fixing this would be to lookup the language - // corresponding to the file that is queried. However, to solve this properly we would need to - // isolate graphs and paths per language so we don't accidently mix different languages that - // require different stitcher settings. - let config = StitcherConfig::default(); if let Err(err) = ForwardPartialPathStitcher::find_all_complete_partial_paths( self.db, std::iter::once(node), - &config, + StitcherConfig::default(), &cancellation_flag, |_g, _ps, p| { reference_paths.push(p.clone()); diff --git a/tree-sitter-stack-graphs/src/cli/test.rs b/tree-sitter-stack-graphs/src/cli/test.rs index e4bd690a5..459573277 100644 --- a/tree-sitter-stack-graphs/src/cli/test.rs +++ b/tree-sitter-stack-graphs/src/cli/test.rs @@ -332,7 +332,7 @@ impl TestArgs { &test.graph, &mut partials, file, - &lc.stitcher_config, + StitcherConfig::default(), &cancellation_flag.as_ref(), |g, ps, p| { db.add_partial_path(g, ps, p.clone()); @@ -342,7 +342,7 @@ impl TestArgs { let result = test.run( &mut partials, &mut db, - &lc.stitcher_config, + StitcherConfig::default(), cancellation_flag.as_ref(), )?; let success = result.failure_count() == 0; @@ -356,7 +356,7 @@ impl TestArgs { &mut db, &|_: &StackGraph, h: &Handle| files.contains(h), success, - &lc.stitcher_config, + StitcherConfig::default(), cancellation_flag.as_ref(), )? } else { @@ -405,7 +405,7 @@ impl TestArgs { db: &mut Database, filter: &dyn Filter, success: bool, - stitcher_config: &StitcherConfig, + stitcher_config: StitcherConfig, cancellation_flag: &dyn CancellationFlag, ) -> anyhow::Result> { let mut outputs = Vec::with_capacity(3); @@ -490,7 +490,7 @@ impl TestArgs { partials: &mut PartialPaths, db: &mut Database, filter: &dyn Filter, - stitcher_config: &StitcherConfig, + stitcher_config: StitcherConfig, cancellation_flag: &dyn CancellationFlag, ) -> anyhow::Result { let references = graph diff --git a/tree-sitter-stack-graphs/src/cli/visualize.rs b/tree-sitter-stack-graphs/src/cli/visualize.rs index acffbc9ce..9f2d53c50 100644 --- a/tree-sitter-stack-graphs/src/cli/visualize.rs +++ b/tree-sitter-stack-graphs/src/cli/visualize.rs @@ -55,16 +55,10 @@ impl VisualizeArgs { .filter(|n| graph[*n].is_reference()) .collect::>(); let mut complete_paths_db = Database::new(); - // FIXME We use the default stitcher config here, because we currently do not retrieve language - // configurations during querying. A first step to fixing this would be to lookup the language - // corresponding to the file that is queried. However, to solve this properly we would need to - // isolate graphs and paths per language so we don't accidently mix different languages that - // require different stitcher settings. - let config = StitcherConfig::default(); ForwardPartialPathStitcher::find_all_complete_partial_paths( &mut db, starting_nodes, - &config, + StitcherConfig::default(), cancellation_flag, |g, ps, p| { complete_paths_db.add_partial_path(g, ps, p.clone()); diff --git a/tree-sitter-stack-graphs/src/loader.rs b/tree-sitter-stack-graphs/src/loader.rs index 6464687fe..0feb6a28c 100644 --- a/tree-sitter-stack-graphs/src/loader.rs +++ b/tree-sitter-stack-graphs/src/loader.rs @@ -26,8 +26,6 @@ use tree_sitter_loader::Config as TsConfig; use tree_sitter_loader::LanguageConfiguration as TSLanguageConfiguration; use tree_sitter_loader::Loader as TsLoader; -pub use stack_graphs::stitching::StitcherConfig; - use crate::CancellationFlag; use crate::FileAnalyzer; use crate::StackGraphLanguage; @@ -46,7 +44,6 @@ pub struct LanguageConfiguration { pub sgl: StackGraphLanguage, pub builtins: StackGraph, pub special_files: FileAnalyzers, - pub stitcher_config: StitcherConfig, } impl LanguageConfiguration { @@ -62,7 +59,6 @@ impl LanguageConfiguration { builtins_source: Option<(PathBuf, &'a str)>, builtins_config: Option<&str>, special_files: FileAnalyzers, - stitcher_config: StitcherConfig, cancellation_flag: &dyn CancellationFlag, ) -> Result> { let sgl = StackGraphLanguage::from_source(language, tsg_path.clone(), tsg_source).map_err( @@ -102,7 +98,6 @@ impl LanguageConfiguration { sgl, builtins, special_files, - stitcher_config, }) } @@ -573,7 +568,6 @@ impl PathLoader { sgl, builtins, special_files: FileAnalyzers::new(), - stitcher_config: StitcherConfig::default(), // FIXME we do not have a place for this configuration }; self.cache.push((language.language, lc)); diff --git a/tree-sitter-stack-graphs/src/test.rs b/tree-sitter-stack-graphs/src/test.rs index 8f3c20c29..236e254c5 100644 --- a/tree-sitter-stack-graphs/src/test.rs +++ b/tree-sitter-stack-graphs/src/test.rs @@ -624,7 +624,7 @@ impl Test { &mut self, partials: &mut PartialPaths, db: &mut Database, - stitcher_config: &StitcherConfig, + stitcher_config: StitcherConfig, cancellation_flag: &dyn CancellationFlag, ) -> Result { let mut result = TestResult::new(); diff --git a/tree-sitter-stack-graphs/tests/it/loader.rs b/tree-sitter-stack-graphs/tests/it/loader.rs index 7525b6fcf..8fcf0ccac 100644 --- a/tree-sitter-stack-graphs/tests/it/loader.rs +++ b/tree-sitter-stack-graphs/tests/it/loader.rs @@ -8,7 +8,6 @@ use once_cell::sync::Lazy; use pretty_assertions::assert_eq; use stack_graphs::graph::StackGraph; -use stack_graphs::stitching::StitcherConfig; use std::path::PathBuf; use tree_sitter_stack_graphs::loader::FileAnalyzers; use tree_sitter_stack_graphs::loader::LanguageConfiguration; @@ -36,7 +35,6 @@ fn can_load_from_provided_language_configuration() { sgl, builtins: StackGraph::new(), special_files: FileAnalyzers::new(), - stitcher_config: StitcherConfig::default(), }; let mut loader = Loader::from_language_configurations(vec![lc], None).expect("Expected loader to succeed"); diff --git a/tree-sitter-stack-graphs/tests/it/test.rs b/tree-sitter-stack-graphs/tests/it/test.rs index 483ad011b..98ec3ab96 100644 --- a/tree-sitter-stack-graphs/tests/it/test.rs +++ b/tree-sitter-stack-graphs/tests/it/test.rs @@ -114,7 +114,7 @@ fn check_test( &test.graph, &mut partials, fragment.file, - &StitcherConfig::default(), + StitcherConfig::default(), &stack_graphs::NoCancellation, |graph, partials, path| { db.add_partial_path(graph, partials, path.clone()); @@ -127,7 +127,7 @@ fn check_test( .run( &mut partials, &mut db, - &StitcherConfig::default(), + StitcherConfig::default(), &NoCancellation, ) .expect("should never be cancelled"); From 098e03a419831125836b26abd06fa08cb94ace2a Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 13 Nov 2023 14:48:29 +0100 Subject: [PATCH 267/500] Add similar path setting to language configuration --- .../tree-sitter-stack-graphs-java/rust/lib.rs | 2 -- .../rust/lib.rs | 9 ++--- .../rust/lib.rs | 13 +++---- stack-graphs/src/stitching.rs | 13 ++++++- tree-sitter-stack-graphs/src/cli/index.rs | 4 ++- tree-sitter-stack-graphs/src/cli/init.rs | 2 -- tree-sitter-stack-graphs/src/cli/query.rs | 5 ++- tree-sitter-stack-graphs/src/cli/test.rs | 8 +++-- tree-sitter-stack-graphs/src/cli/visualize.rs | 5 ++- tree-sitter-stack-graphs/src/loader.rs | 34 ++++++++++++++++--- tree-sitter-stack-graphs/tests/it/loader.rs | 1 + 11 files changed, 71 insertions(+), 25 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-java/rust/lib.rs b/languages/tree-sitter-stack-graphs-java/rust/lib.rs index 09cb043a5..942785044 100644 --- a/languages/tree-sitter-stack-graphs-java/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-java/rust/lib.rs @@ -1,4 +1,3 @@ -use tree_sitter_stack_graphs::loader::FileAnalyzers; use tree_sitter_stack_graphs::loader::LanguageConfiguration; use tree_sitter_stack_graphs::loader::LoadError; use tree_sitter_stack_graphs::CancellationFlag; @@ -39,7 +38,6 @@ pub fn try_language_configuration( STACK_GRAPHS_BUILTINS_SOURCE, )), Some(STACK_GRAPHS_BUILTINS_CONFIG), - FileAnalyzers::new(), cancellation_flag, ) } diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/lib.rs b/languages/tree-sitter-stack-graphs-javascript/rust/lib.rs index 508ba58b9..61f113149 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/lib.rs @@ -5,7 +5,6 @@ // Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. // ------------------------------------------------------------------------------------------------ -use tree_sitter_stack_graphs::loader::FileAnalyzers; use tree_sitter_stack_graphs::loader::LanguageConfiguration; use tree_sitter_stack_graphs::loader::LoadError; use tree_sitter_stack_graphs::CancellationFlag; @@ -38,7 +37,7 @@ pub fn language_configuration(cancellation_flag: &dyn CancellationFlag) -> Langu pub fn try_language_configuration( cancellation_flag: &dyn CancellationFlag, ) -> Result { - LanguageConfiguration::from_sources( + let mut lc = LanguageConfiguration::from_sources( tree_sitter_javascript::language(), Some(String::from("source.js")), None, @@ -50,7 +49,9 @@ pub fn try_language_configuration( STACK_GRAPHS_BUILTINS_SOURCE, )), Some(STACK_GRAPHS_BUILTINS_CONFIG), - FileAnalyzers::new().add("package.json".to_string(), NpmPackageAnalyzer {}), cancellation_flag, - ) + )?; + lc.special_files + .add("package.json".to_string(), NpmPackageAnalyzer {}); + Ok(lc) } diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs index 45ce6d255..0f84d64c1 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs @@ -5,7 +5,6 @@ // Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. // ------------------------------------------------------------------------------------------------ -use tree_sitter_stack_graphs::loader::FileAnalyzers; use tree_sitter_stack_graphs::loader::LanguageConfiguration; use tree_sitter_stack_graphs::loader::LoadError; use tree_sitter_stack_graphs::CancellationFlag; @@ -41,7 +40,7 @@ pub fn language_configuration(cancellation_flag: &dyn CancellationFlag) -> Langu pub fn try_language_configuration( cancellation_flag: &dyn CancellationFlag, ) -> Result { - LanguageConfiguration::from_sources( + let mut lc = LanguageConfiguration::from_sources( tree_sitter_typescript::language_typescript(), Some(String::from("source.ts")), None, @@ -53,9 +52,11 @@ pub fn try_language_configuration( STACK_GRAPHS_BUILTINS_SOURCE, )), Some(STACK_GRAPHS_BUILTINS_CONFIG), - FileAnalyzers::new() - .add("tsconfig.json".to_string(), TsConfigAnalyzer {}) - .add("package.json".to_string(), NpmPackageAnalyzer {}), cancellation_flag, - ) + )?; + lc.special_files + .add("tsconfig.json".to_string(), TsConfigAnalyzer {}) + .add("package.json".to_string(), NpmPackageAnalyzer {}); + lc.has_similar_paths = false; + Ok(lc) } diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index 1432669dd..64a7e5005 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -1246,7 +1246,18 @@ impl ForwardPartialPathStitcher { #[derive(Clone, Copy, Debug)] pub struct StitcherConfig { /// Enables similar path detection during path stitching. - pub detect_similar_paths: bool, + detect_similar_paths: bool, +} + +impl StitcherConfig { + pub fn detect_similar_paths(&self) -> bool { + self.detect_similar_paths + } + + pub fn with_detect_similar_paths(mut self, detect_similar_paths: bool) -> Self { + self.detect_similar_paths = detect_similar_paths; + self + } } impl StitcherConfig { diff --git a/tree-sitter-stack-graphs/src/cli/index.rs b/tree-sitter-stack-graphs/src/cli/index.rs index 436caca1a..a37806d45 100644 --- a/tree-sitter-stack-graphs/src/cli/index.rs +++ b/tree-sitter-stack-graphs/src/cli/index.rs @@ -280,6 +280,8 @@ impl<'a> Indexer<'a> { } Err(e) => return Err(IndexError::LoadError(e)), }; + let stitcher_config = + StitcherConfig::default().with_detect_similar_paths(lcs.has_similar_paths()); let source = file_reader.get(source_path)?; let tag = sha1(source); @@ -356,7 +358,7 @@ impl<'a> Indexer<'a> { &graph, &mut partials, file, - StitcherConfig::default(), + stitcher_config, &(&cancellation_flag as &dyn CancellationFlag), |_g, _ps, p| { paths.push(p.clone()); diff --git a/tree-sitter-stack-graphs/src/cli/init.rs b/tree-sitter-stack-graphs/src/cli/init.rs index c287909e6..d9fc0cd59 100644 --- a/tree-sitter-stack-graphs/src/cli/init.rs +++ b/tree-sitter-stack-graphs/src/cli/init.rs @@ -758,8 +758,6 @@ impl ProjectSettings<'_> { STACK_GRAPHS_BUILTINS_SOURCE, )), Some(STACK_GRAPHS_BUILTINS_CONFIG), - FileAnalyzers::new(), - StitcherConfig::default(), cancellation_flag, ) }} diff --git a/tree-sitter-stack-graphs/src/cli/query.rs b/tree-sitter-stack-graphs/src/cli/query.rs index 1063e49e9..6bbf46702 100644 --- a/tree-sitter-stack-graphs/src/cli/query.rs +++ b/tree-sitter-stack-graphs/src/cli/query.rs @@ -186,10 +186,13 @@ impl<'a> Querier<'a> { }; let mut reference_paths = Vec::new(); + let stitcher_config = StitcherConfig::default() + // always detect similar paths, we don't know the language configurations for the data in the database + .with_detect_similar_paths(true); if let Err(err) = ForwardPartialPathStitcher::find_all_complete_partial_paths( self.db, std::iter::once(node), - StitcherConfig::default(), + stitcher_config, &cancellation_flag, |_g, _ps, p| { reference_paths.push(p.clone()); diff --git a/tree-sitter-stack-graphs/src/cli/test.rs b/tree-sitter-stack-graphs/src/cli/test.rs index 459573277..3331a713b 100644 --- a/tree-sitter-stack-graphs/src/cli/test.rs +++ b/tree-sitter-stack-graphs/src/cli/test.rs @@ -325,6 +325,8 @@ impl TestArgs { Ok(_) => {} } } + let stitcher_config = + StitcherConfig::default().with_detect_similar_paths(lc.has_similar_paths); let mut partials = PartialPaths::new(); let mut db = Database::new(); for file in test.graph.iter_files() { @@ -332,7 +334,7 @@ impl TestArgs { &test.graph, &mut partials, file, - StitcherConfig::default(), + stitcher_config, &cancellation_flag.as_ref(), |g, ps, p| { db.add_partial_path(g, ps, p.clone()); @@ -342,7 +344,7 @@ impl TestArgs { let result = test.run( &mut partials, &mut db, - StitcherConfig::default(), + stitcher_config, cancellation_flag.as_ref(), )?; let success = result.failure_count() == 0; @@ -356,7 +358,7 @@ impl TestArgs { &mut db, &|_: &StackGraph, h: &Handle| files.contains(h), success, - StitcherConfig::default(), + stitcher_config, cancellation_flag.as_ref(), )? } else { diff --git a/tree-sitter-stack-graphs/src/cli/visualize.rs b/tree-sitter-stack-graphs/src/cli/visualize.rs index 9f2d53c50..f17f23b88 100644 --- a/tree-sitter-stack-graphs/src/cli/visualize.rs +++ b/tree-sitter-stack-graphs/src/cli/visualize.rs @@ -55,10 +55,13 @@ impl VisualizeArgs { .filter(|n| graph[*n].is_reference()) .collect::>(); let mut complete_paths_db = Database::new(); + let stitcher_config = StitcherConfig::default() + // always detect similar paths, we don't know the language configurations for the data in the database + .with_detect_similar_paths(true); ForwardPartialPathStitcher::find_all_complete_partial_paths( &mut db, starting_nodes, - StitcherConfig::default(), + stitcher_config, cancellation_flag, |g, ps, p| { complete_paths_db.add_partial_path(g, ps, p.clone()); diff --git a/tree-sitter-stack-graphs/src/loader.rs b/tree-sitter-stack-graphs/src/loader.rs index 0feb6a28c..b44996ffe 100644 --- a/tree-sitter-stack-graphs/src/loader.rs +++ b/tree-sitter-stack-graphs/src/loader.rs @@ -44,11 +44,12 @@ pub struct LanguageConfiguration { pub sgl: StackGraphLanguage, pub builtins: StackGraph, pub special_files: FileAnalyzers, + pub has_similar_paths: bool, } impl LanguageConfiguration { /// Build a language configuration from tsg and builtins sources. The tsg path - /// is kept for informational only, see [`StackGraphLanguage::from_source`][]. + /// is kept for informational use only, see [`StackGraphLanguage::from_source`][]. pub fn from_sources<'a>( language: Language, scope: Option, @@ -58,7 +59,6 @@ impl LanguageConfiguration { tsg_source: &'a str, builtins_source: Option<(PathBuf, &'a str)>, builtins_config: Option<&str>, - special_files: FileAnalyzers, cancellation_flag: &dyn CancellationFlag, ) -> Result> { let sgl = StackGraphLanguage::from_source(language, tsg_path.clone(), tsg_source).map_err( @@ -97,7 +97,8 @@ impl LanguageConfiguration { file_types, sgl, builtins, - special_files, + special_files: FileAnalyzers::new(), + has_similar_paths: true, }) } @@ -143,7 +144,7 @@ impl FileAnalyzers { } } - pub fn add( + pub fn with( mut self, file_name: String, analyzer: impl FileAnalyzer + Send + Sync + 'static, @@ -152,6 +153,15 @@ impl FileAnalyzers { self } + pub fn add( + &mut self, + file_name: String, + analyzer: impl FileAnalyzer + Send + Sync + 'static, + ) -> &mut Self { + self.file_analyzers.insert(file_name, Arc::new(analyzer)); + self + } + pub fn get(&self, file_name: &str) -> Option> { self.file_analyzers.get(file_name).cloned() } @@ -358,6 +368,20 @@ impl FileLanguageConfigurations<'_> { pub fn has_some(&self) -> bool { self.primary.is_some() || !self.secondary.is_empty() } + + pub fn has_similar_paths(&self) -> bool { + if let Some(lc) = &self.primary { + if lc.has_similar_paths { + return true; + } + } + for (lc, _) in &self.secondary { + if lc.has_similar_paths { + return true; + } + } + return false; + } } #[derive(Debug, Error)] @@ -568,6 +592,8 @@ impl PathLoader { sgl, builtins, special_files: FileAnalyzers::new(), + // always detect similar paths, we don't know the language configuration when loading from the file system + has_similar_paths: true, }; self.cache.push((language.language, lc)); diff --git a/tree-sitter-stack-graphs/tests/it/loader.rs b/tree-sitter-stack-graphs/tests/it/loader.rs index 8fcf0ccac..176600435 100644 --- a/tree-sitter-stack-graphs/tests/it/loader.rs +++ b/tree-sitter-stack-graphs/tests/it/loader.rs @@ -35,6 +35,7 @@ fn can_load_from_provided_language_configuration() { sgl, builtins: StackGraph::new(), special_files: FileAnalyzers::new(), + has_similar_paths: true, }; let mut loader = Loader::from_language_configurations(vec![lc], None).expect("Expected loader to succeed"); From 966f613175808942015fde20dc45a2295e8788ae Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 13 Nov 2023 14:50:24 +0100 Subject: [PATCH 268/500] Update project init --- tree-sitter-stack-graphs/src/cli/init.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tree-sitter-stack-graphs/src/cli/init.rs b/tree-sitter-stack-graphs/src/cli/init.rs index d9fc0cd59..e381786b9 100644 --- a/tree-sitter-stack-graphs/src/cli/init.rs +++ b/tree-sitter-stack-graphs/src/cli/init.rs @@ -718,10 +718,8 @@ impl ProjectSettings<'_> { let mut file = File::create(project_path.join("rust/lib.rs"))?; self.write_license_header(&mut file, "// ")?; writedoc! {file, r#" - use tree_sitter_stack_graphs::loader::FileAnalyzers; use tree_sitter_stack_graphs::loader::LanguageConfiguration; use tree_sitter_stack_graphs::loader::LoadError; - use tree_sitter_stack_graphs::loader::StitcherConfig; use tree_sitter_stack_graphs::CancellationFlag; /// The stack graphs tsg source for this language. From 3d32fbb2cb70fb70995536ff83087f2066bf013f Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 20 Nov 2023 13:42:04 +0100 Subject: [PATCH 269/500] Do not use transmute for stitcher config --- stack-graphs/src/c.rs | 2 +- stack-graphs/src/stitching.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/stack-graphs/src/c.rs b/stack-graphs/src/c.rs index 26a823eba..9b50349ec 100644 --- a/stack-graphs/src/c.rs +++ b/stack-graphs/src/c.rs @@ -1408,7 +1408,7 @@ pub struct sg_stitcher_config { impl Into for sg_stitcher_config { fn into(self) -> StitcherConfig { - unsafe { std::mem::transmute(self) } + StitcherConfig::default().with_detect_similar_paths(self.detect_similar_paths) } } diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index 64a7e5005..328dc63a9 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -1242,7 +1242,6 @@ impl ForwardPartialPathStitcher { } /// Configuration for partial path stitchers. -#[repr(C)] #[derive(Clone, Copy, Debug)] pub struct StitcherConfig { /// Enables similar path detection during path stitching. From 294596aed849e1873e1693da6f2dcdcb243fac83 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 20 Nov 2023 14:57:58 +0100 Subject: [PATCH 270/500] Change setting name and add comment explaining the consequences --- .../rust/lib.rs | 2 +- stack-graphs/src/stitching.rs | 1 + tree-sitter-stack-graphs/src/cli/index.rs | 2 +- tree-sitter-stack-graphs/src/cli/test.rs | 2 +- tree-sitter-stack-graphs/src/loader.rs | 23 ++++++++++--------- tree-sitter-stack-graphs/tests/it/loader.rs | 2 +- 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs index 0f84d64c1..3590649b2 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs @@ -57,6 +57,6 @@ pub fn try_language_configuration( lc.special_files .add("tsconfig.json".to_string(), TsConfigAnalyzer {}) .add("package.json".to_string(), NpmPackageAnalyzer {}); - lc.has_similar_paths = false; + lc.no_similar_paths_in_file = true; Ok(lc) } diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index 328dc63a9..dcf1d70c0 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -870,6 +870,7 @@ impl ForwardPartialPathStitcher { initial_paths: next_iteration.0.len(), next_iteration, appended_paths, + // By default, all paths are checked for similarity similar_path_detector: Some(SimilarPathDetector::new()), // By default, all nodes are checked for cycles and (if enabled) similarity check_only_join_nodes: false, diff --git a/tree-sitter-stack-graphs/src/cli/index.rs b/tree-sitter-stack-graphs/src/cli/index.rs index a37806d45..dab12e537 100644 --- a/tree-sitter-stack-graphs/src/cli/index.rs +++ b/tree-sitter-stack-graphs/src/cli/index.rs @@ -281,7 +281,7 @@ impl<'a> Indexer<'a> { Err(e) => return Err(IndexError::LoadError(e)), }; let stitcher_config = - StitcherConfig::default().with_detect_similar_paths(lcs.has_similar_paths()); + StitcherConfig::default().with_detect_similar_paths(!lcs.no_similar_paths_in_file()); let source = file_reader.get(source_path)?; let tag = sha1(source); diff --git a/tree-sitter-stack-graphs/src/cli/test.rs b/tree-sitter-stack-graphs/src/cli/test.rs index 3331a713b..780d478f6 100644 --- a/tree-sitter-stack-graphs/src/cli/test.rs +++ b/tree-sitter-stack-graphs/src/cli/test.rs @@ -326,7 +326,7 @@ impl TestArgs { } } let stitcher_config = - StitcherConfig::default().with_detect_similar_paths(lc.has_similar_paths); + StitcherConfig::default().with_detect_similar_paths(!lc.no_similar_paths_in_file); let mut partials = PartialPaths::new(); let mut db = Database::new(); for file in test.graph.iter_files() { diff --git a/tree-sitter-stack-graphs/src/loader.rs b/tree-sitter-stack-graphs/src/loader.rs index b44996ffe..9ffc1d674 100644 --- a/tree-sitter-stack-graphs/src/loader.rs +++ b/tree-sitter-stack-graphs/src/loader.rs @@ -44,7 +44,11 @@ pub struct LanguageConfiguration { pub sgl: StackGraphLanguage, pub builtins: StackGraph, pub special_files: FileAnalyzers, - pub has_similar_paths: bool, + /// Can be set to true if the stack graph rules ensure that there can be no similar + /// paths in a file, in which case it is safe to turn of similar path detection. If + /// incorrectly set to true, performance of path finding suffers from exponential + /// blow up. + pub no_similar_paths_in_file: bool, } impl LanguageConfiguration { @@ -98,7 +102,7 @@ impl LanguageConfiguration { sgl, builtins, special_files: FileAnalyzers::new(), - has_similar_paths: true, + no_similar_paths_in_file: false, }) } @@ -369,18 +373,15 @@ impl FileLanguageConfigurations<'_> { self.primary.is_some() || !self.secondary.is_empty() } - pub fn has_similar_paths(&self) -> bool { + pub fn no_similar_paths_in_file(&self) -> bool { + let mut no_similar_paths_in_file = true; if let Some(lc) = &self.primary { - if lc.has_similar_paths { - return true; - } + no_similar_paths_in_file &= lc.no_similar_paths_in_file; } for (lc, _) in &self.secondary { - if lc.has_similar_paths { - return true; - } + no_similar_paths_in_file &= lc.no_similar_paths_in_file; } - return false; + return no_similar_paths_in_file; } } @@ -593,7 +594,7 @@ impl PathLoader { builtins, special_files: FileAnalyzers::new(), // always detect similar paths, we don't know the language configuration when loading from the file system - has_similar_paths: true, + no_similar_paths_in_file: false, }; self.cache.push((language.language, lc)); diff --git a/tree-sitter-stack-graphs/tests/it/loader.rs b/tree-sitter-stack-graphs/tests/it/loader.rs index 176600435..257326952 100644 --- a/tree-sitter-stack-graphs/tests/it/loader.rs +++ b/tree-sitter-stack-graphs/tests/it/loader.rs @@ -35,7 +35,7 @@ fn can_load_from_provided_language_configuration() { sgl, builtins: StackGraph::new(), special_files: FileAnalyzers::new(), - has_similar_paths: true, + no_similar_paths_in_file: false, }; let mut loader = Loader::from_language_configurations(vec![lc], None).expect("Expected loader to succeed"); From 2c97ba23f225b36c93096eacab34e7cf858b7e25 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Sun, 22 Oct 2023 13:11:39 +0200 Subject: [PATCH 271/500] Add database reader stats --- stack-graphs/src/storage.rs | 54 ++++++++++++++++++++++- tree-sitter-stack-graphs/src/cli/query.rs | 22 ++++++++- 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/stack-graphs/src/storage.rs b/stack-graphs/src/storage.rs index d3f1348dc..c3b3e8ebf 100644 --- a/stack-graphs/src/storage.rs +++ b/stack-graphs/src/storage.rs @@ -419,6 +419,7 @@ impl SQLiteWriter { graph: StackGraph::new(), partials: PartialPaths::new(), db: Database::new(), + stats: Stats::default(), } } } @@ -432,6 +433,7 @@ pub struct SQLiteReader { graph: StackGraph, partials: PartialPaths, db: Database, + stats: Stats, } impl SQLiteReader { @@ -454,6 +456,7 @@ impl SQLiteReader { graph: StackGraph::new(), partials: PartialPaths::new(), db: Database::new(), + stats: Stats::default(), }) } @@ -467,6 +470,8 @@ impl SQLiteReader { self.loaded_root_paths.clear(); self.partials.clear(); self.db.clear(); + + self.stats.clear(); } /// Clear path data that has been loaded into this reader instance. @@ -477,6 +482,8 @@ impl SQLiteReader { self.loaded_root_paths.clear(); self.partials.clear(); self.db.clear(); + + self.stats.clear_paths(); } /// Get the file's status in the database. If a tag is provided, it must match or the file @@ -518,7 +525,13 @@ impl SQLiteReader { /// Ensure the graph for the given file is loaded. pub fn load_graph_for_file(&mut self, file: &str) -> Result> { - Self::load_graph_for_file_inner(file, &mut self.graph, &mut self.loaded_graphs, &self.conn) + Self::load_graph_for_file_inner( + file, + &mut self.graph, + &mut self.loaded_graphs, + &self.conn, + &mut self.stats, + ) } fn load_graph_for_file_inner( @@ -526,13 +539,16 @@ impl SQLiteReader { graph: &mut StackGraph, loaded_graphs: &mut HashSet, conn: &Connection, + stats: &mut Stats, ) -> Result> { copious_debugging!("--> Load graph for {}", file); if !loaded_graphs.insert(file.to_string()) { copious_debugging!(" * Already loaded"); + stats.file_cached += 1; return Ok(graph.get_file(file).expect("loaded file to exist")); } copious_debugging!(" * Load from database"); + stats.file_loads += 1; let mut stmt = conn.prepare_cached("SELECT value FROM graphs WHERE file = ?")?; let value = stmt.query_row([file], |row| row.get::<_, Vec>(0))?; let (file_graph, _): (serde::StackGraph, usize) = @@ -554,6 +570,7 @@ impl SQLiteReader { &mut self.graph, &mut self.loaded_graphs, &self.conn, + &mut self.stats, )?; } Ok(()) @@ -568,8 +585,10 @@ impl SQLiteReader { copious_debugging!(" * Load extensions from node {}", node.display(&self.graph)); if !self.loaded_node_paths.insert(node) { copious_debugging!(" > Already loaded"); + self.stats.node_path_cached += 1; return Ok(()); } + self.stats.node_path_loads += 1; let id = self.graph[node].id(); let file = id.file().expect("file node required"); let file = self.graph[file].name(); @@ -591,6 +610,7 @@ impl SQLiteReader { &mut self.graph, &mut self.loaded_graphs, &self.conn, + &mut self.stats, )?; let (path, _): (serde::PartialPath, usize) = bincode::decode_from_slice(&value, BINCODE_CONFIG)?; @@ -629,8 +649,10 @@ impl SQLiteReader { ); if !self.loaded_root_paths.insert(symbol_stack.clone()) { copious_debugging!(" > Already loaded"); + self.stats.root_path_cached += 1; continue; } + self.stats.root_path_loads += 1; let paths = stmt.query_map([symbol_stack, escape.clone()], |row| { let file = row.get::<_, String>(0)?; let value = row.get::<_, Vec>(1)?; @@ -646,6 +668,7 @@ impl SQLiteReader { &mut self.graph, &mut self.loaded_graphs, &self.conn, + &mut self.stats, )?; let (path, _): (serde::PartialPath, usize) = bincode::decode_from_slice(&value, BINCODE_CONFIG)?; @@ -686,6 +709,11 @@ impl SQLiteReader { pub fn get(&mut self) -> (&mut StackGraph, &mut PartialPaths, &mut Database) { (&mut self.graph, &mut self.partials, &mut self.db) } + + /// Return stats about this database reader. + pub fn stats(&self) -> Stats { + self.stats.clone() + } } // Methods for computing keys and patterns for a symbol stack. The format of a storage key is: @@ -765,6 +793,30 @@ impl ForwardCandidates, PartialPath, Database, StorageError> } } +#[derive(Clone, Debug, Default)] +pub struct Stats { + pub file_loads: usize, + pub file_cached: usize, + pub root_path_loads: usize, + pub root_path_cached: usize, + pub node_path_loads: usize, + pub node_path_cached: usize, +} + +impl Stats { + fn clear(&mut self) { + *self = Stats::default(); + } + + fn clear_paths(&mut self) { + *self = Stats { + file_loads: self.file_loads, + file_cached: self.file_cached, + ..Stats::default() + } + } +} + /// Check if the database has the version supported by this library version. fn check_version(conn: &Connection) -> Result<()> { let version = conn.query_row("SELECT version FROM metadata", [], |r| r.get::<_, usize>(0))?; diff --git a/tree-sitter-stack-graphs/src/cli/query.rs b/tree-sitter-stack-graphs/src/cli/query.rs index 6bbf46702..296052748 100644 --- a/tree-sitter-stack-graphs/src/cli/query.rs +++ b/tree-sitter-stack-graphs/src/cli/query.rs @@ -9,6 +9,7 @@ use clap::Args; use clap::Parser; use clap::Subcommand; use clap::ValueHint; +use indoc::printdoc; use stack_graphs::stitching::ForwardPartialPathStitcher; use stack_graphs::stitching::StitcherConfig; use stack_graphs::storage::FileStatus; @@ -34,6 +35,9 @@ pub struct QueryArgs { #[clap(long)] pub wait_at_start: bool, + #[clap(long)] + pub stats: bool, + #[clap(subcommand)] target: Target, } @@ -44,7 +48,23 @@ impl QueryArgs { wait_for_input()?; } let mut db = SQLiteReader::open(&db_path)?; - self.target.run(&mut db) + self.target.run(&mut db)?; + if self.stats { + let stats = db.stats(); + printdoc! {r#" + + db stats | loads | cached + ------------+--------+-------- + files | {:>6} | {:>6} + root paths | {:>6} | {:>6} + node paths | {:>6} | {:>6} + "#, + stats.file_loads, stats.file_cached, + stats.root_path_loads, stats.root_path_cached, + stats.node_path_loads, stats.node_path_cached, + }; + } + Ok(()) } } From a2ce328807228b703841eb086b0190da1361494f Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 24 Oct 2023 16:20:52 +0100 Subject: [PATCH 272/500] Add frequency distribution type --- stack-graphs/src/lib.rs | 1 + stack-graphs/src/stats.rs | 90 ++++++++++++++++++++++++++++++++++ stack-graphs/tests/it/main.rs | 1 + stack-graphs/tests/it/stats.rs | 45 +++++++++++++++++ 4 files changed, 137 insertions(+) create mode 100644 stack-graphs/src/stats.rs create mode 100644 stack-graphs/tests/it/stats.rs diff --git a/stack-graphs/src/lib.rs b/stack-graphs/src/lib.rs index 009076af9..a8573c5e5 100644 --- a/stack-graphs/src/lib.rs +++ b/stack-graphs/src/lib.rs @@ -69,6 +69,7 @@ pub mod graph; pub mod partial; pub mod paths; pub mod serde; +pub mod stats; pub mod stitching; #[cfg(feature = "storage")] pub mod storage; diff --git a/stack-graphs/src/stats.rs b/stack-graphs/src/stats.rs new file mode 100644 index 000000000..b74098f12 --- /dev/null +++ b/stack-graphs/src/stats.rs @@ -0,0 +1,90 @@ +use std::collections::HashMap; +use std::hash::Hash; + +use itertools::Itertools; + +/// Frequency distribution maintains the frequency of T values. +#[derive(Clone, Debug, Default)] +pub struct FrequencyDistribution +where + T: Eq + Hash, +{ + values: HashMap, + total: usize, +} + +impl FrequencyDistribution { + pub fn total(&self) -> usize { + return self.total; + } + + pub fn unique(&self) -> usize { + return self.values.len(); + } + + pub fn frequencies(&self) -> FrequencyDistribution { + let mut fs = FrequencyDistribution::default(); + for count in self.values.values() { + fs += *count + } + fs + } +} + +impl FrequencyDistribution { + pub fn quantiles(&self, q: usize) -> Vec<&T> { + if q == 0 || self.total == 0 { + return vec![]; + } + + let mut it = self.values.iter().sorted_by_key(|e| e.0); + let mut total_count = 0; + let mut last_value; + let mut result = Vec::new(); + + if let Some((value, count)) = it.next() { + total_count += count; + last_value = value; + } else { + return vec![]; + } + result.push(last_value); + + for k in 1..=q { + let limit = ((self.total as f64 * k as f64) / q as f64).round() as usize; + while total_count < limit { + if let Some((value, count)) = it.next() { + total_count += count; + last_value = value; + } else { + break; + } + } + result.push(last_value); + } + + result + } +} + +impl std::ops::AddAssign for FrequencyDistribution +where + T: Eq + Hash, +{ + fn add_assign(&mut self, rhs: T) { + *self.values.entry(rhs).or_default() += 1; + self.total += 1; + } +} + +impl std::ops::AddAssign<&Self> for FrequencyDistribution +where + T: Eq + Hash + Clone, +{ + fn add_assign(&mut self, rhs: &Self) { + for (value, count) in &rhs.values { + *self.values.entry(value.clone()).or_default() += count; + } + self.total += rhs.total; + } +} diff --git a/stack-graphs/tests/it/main.rs b/stack-graphs/tests/it/main.rs index 3f0162c3b..e5a0e6edd 100644 --- a/stack-graphs/tests/it/main.rs +++ b/stack-graphs/tests/it/main.rs @@ -24,6 +24,7 @@ mod graph; mod partial; #[cfg(feature = "serde")] mod serde; +mod stats; mod stitching; #[cfg(feature = "storage")] mod storage; diff --git a/stack-graphs/tests/it/stats.rs b/stack-graphs/tests/it/stats.rs new file mode 100644 index 000000000..f4a48cd03 --- /dev/null +++ b/stack-graphs/tests/it/stats.rs @@ -0,0 +1,45 @@ +use itertools::Itertools; +use pretty_assertions::assert_eq; + +use stack_graphs::stats::*; + +#[test] +fn empty_distribution() { + let hist: FrequencyDistribution = FrequencyDistribution::default(); + + assert_eq!(0, hist.unique()); + assert_eq!(0, hist.total()); + + let result = hist.quantiles(0).into_iter().cloned().collect_vec(); + let expected: Vec = vec![]; + assert_eq!(expected, result); +} + +#[test] +fn singleton_distribution() { + let mut hist = FrequencyDistribution::default(); + hist += 42; + + assert_eq!(1, hist.unique()); + assert_eq!(1, hist.total()); + + let result = hist.quantiles(4).into_iter().cloned().collect_vec(); + let expected: Vec = vec![42, 42, 42, 42, 42]; + assert_eq!(expected, result); +} + +#[test] +fn four_value_distribution() { + let mut hist = FrequencyDistribution::default(); + hist += 3; + hist += 4; + hist += 1; + hist += 2; + + assert_eq!(4, hist.unique()); + assert_eq!(4, hist.total()); + + let result = hist.quantiles(4).into_iter().cloned().collect_vec(); + let expected: Vec = vec![1, 1, 2, 3, 4]; + assert_eq!(expected, result); +} From c28ca80bd09c4fc443f402aefbee89d85fb12915 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 25 Oct 2023 00:52:16 +0100 Subject: [PATCH 273/500] Add stitcher stats --- stack-graphs/src/graph.rs | 2 +- stack-graphs/src/stitching.rs | 85 ++++++++++++- tree-sitter-stack-graphs/src/cli/query.rs | 138 +++++++++++++++++----- 3 files changed, 191 insertions(+), 34 deletions(-) diff --git a/stack-graphs/src/graph.rs b/stack-graphs/src/graph.rs index 53dd392da..fe1321387 100644 --- a/stack-graphs/src/graph.rs +++ b/stack-graphs/src/graph.rs @@ -425,7 +425,7 @@ impl Handle { /// Each node (except for the _root node_ and _jump to scope_ node) lives in a file, and has a /// _local ID_ that must be unique within its file. #[repr(C)] -#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct NodeID { file: ControlledOption>, local_id: u32, diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index dcf1d70c0..51aab53ba 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -66,6 +66,7 @@ use crate::partial::PartialPaths; use crate::partial::PartialSymbolStack; use crate::paths::Extend; use crate::paths::PathResolutionError; +use crate::stats::FrequencyDistribution; use crate::CancellationError; use crate::CancellationFlag; @@ -839,6 +840,7 @@ pub struct ForwardPartialPathStitcher { similar_path_detector: Option>, check_only_join_nodes: bool, max_work_per_phase: usize, + stats: Stats, #[cfg(feature = "copious-debugging")] phase_number: usize, } @@ -876,6 +878,7 @@ impl ForwardPartialPathStitcher { check_only_join_nodes: false, // By default, there's no artificial bound on the amount of work done per phase max_work_per_phase: usize::MAX, + stats: Stats::default(), #[cfg(feature = "copious-debugging")] phase_number: 1, } @@ -909,6 +912,10 @@ impl ForwardPartialPathStitcher { pub fn set_max_work_per_phase(&mut self, max_work_per_phase: usize) { self.max_work_per_phase = max_work_per_phase; } + + pub fn into_stats(self) -> Stats { + self.stats + } } impl ForwardPartialPathStitcher { @@ -1056,6 +1063,21 @@ impl ForwardPartialPathStitcher { self.next_iteration.2.push(new_has_split); } + let (graph, _, _) = candidates.get_graph_partials_and_db(); + let end_node = &graph[partial_path.end_node]; + if end_node.is_root() { + self.stats.candidates_per_root_path += candidate_count; + self.stats.extensions_per_root_path += extension_count; + self.stats.root_visits += 1; + } else { + self.stats.candidates_per_node_path += candidate_count; + self.stats.extensions_per_node_path += extension_count; + self.stats.node_visits += end_node.id(); + } + + if extension_count == 0 { + self.stats.maximal_path_lengh += partial_path.edges.len(); + } candidate_count } @@ -1089,6 +1111,7 @@ impl ForwardPartialPathStitcher { self.next_iteration.1.drain(..), self.next_iteration.2.drain(..), )); + self.stats.queued_paths_per_phase += self.queue.len(); let mut work_performed = 0; while let Some((partial_path, cycle_detector, has_split)) = self.queue.pop_front() { let (graph, partials, _) = candidates.get_graph_partials_and_db(); @@ -1110,6 +1133,7 @@ impl ForwardPartialPathStitcher { break; } } + self.stats.processed_paths_per_phase += work_performed; #[cfg(feature = "copious-debugging")] { @@ -1149,7 +1173,7 @@ impl ForwardPartialPathStitcher { config: StitcherConfig, cancellation_flag: &dyn CancellationFlag, mut visit: F, - ) -> Result<(), CancellationError> + ) -> Result where F: FnMut(&StackGraph, &mut PartialPaths, &PartialPath), { @@ -1168,6 +1192,8 @@ impl ForwardPartialPathStitcher { ForwardPartialPathStitcher::from_partial_paths(graph, partials, initial_paths); config.apply(&mut stitcher); stitcher.set_check_only_join_nodes(true); + + let mut accepted_path_length = FrequencyDistribution::default(); while !stitcher.is_complete() { cancellation_flag.check("finding complete partial paths")?; stitcher.process_next_phase( @@ -1176,11 +1202,16 @@ impl ForwardPartialPathStitcher { ); for path in stitcher.previous_phase_partial_paths() { if as_complete_as_necessary(graph, path) { + accepted_path_length += path.edges.len(); visit(graph, partials, path); } } } - Ok(()) + + Ok(Stats { + accepted_path_length, + ..stitcher.stats + }) } } @@ -1202,7 +1233,7 @@ impl ForwardPartialPathStitcher { config: StitcherConfig, cancellation_flag: &dyn CancellationFlag, mut visit: F, - ) -> Result<(), Err> + ) -> Result where I: IntoIterator>, A: Appendable, @@ -1225,6 +1256,8 @@ impl ForwardPartialPathStitcher { ForwardPartialPathStitcher::from_partial_paths(graph, partials, initial_paths); config.apply(&mut stitcher); stitcher.set_check_only_join_nodes(true); + + let mut accepted_path_length = FrequencyDistribution::default(); while !stitcher.is_complete() { cancellation_flag.check("finding complete partial paths")?; for path in stitcher.previous_phase_partial_paths() { @@ -1234,11 +1267,55 @@ impl ForwardPartialPathStitcher { let (graph, partials, _) = candidates.get_graph_partials_and_db(); for path in stitcher.previous_phase_partial_paths() { if path.is_complete(graph) { + accepted_path_length += path.edges.len(); visit(graph, partials, path); } } } - Ok(()) + + Ok(Stats { + accepted_path_length, + ..stitcher.stats + }) + } +} + +#[derive(Clone, Debug, Default)] +pub struct Stats { + /// The distribution of the number of queued paths per stitching phase + pub queued_paths_per_phase: FrequencyDistribution, + /// The distribution of the number of processed paths per stitching phase + pub processed_paths_per_phase: FrequencyDistribution, + /// The distribution of the length of accepted paths + pub accepted_path_length: FrequencyDistribution, + /// The distribution of the maximal length of paths (when they cannot be extended more) + pub maximal_path_lengh: FrequencyDistribution, + /// The distribution of the number of candidates for paths ending in a regular node + pub candidates_per_node_path: FrequencyDistribution, + /// The distribution of the number of candidates for paths ending in the root node + pub candidates_per_root_path: FrequencyDistribution, + /// The distribution of the number of extensions (accepted candidates) for paths ending in a regular node + pub extensions_per_node_path: FrequencyDistribution, + /// The distribution of the number of extensions (accepted candidates) for paths ending in the root node + pub extensions_per_root_path: FrequencyDistribution, + /// The number of times the root node is visited + pub root_visits: usize, + /// The distribution of the number of times a regular node is visited + pub node_visits: FrequencyDistribution, +} + +impl std::ops::AddAssign<&Self> for Stats { + fn add_assign(&mut self, rhs: &Self) { + self.queued_paths_per_phase += &rhs.queued_paths_per_phase; + self.processed_paths_per_phase += &rhs.processed_paths_per_phase; + self.accepted_path_length += &rhs.accepted_path_length; + self.maximal_path_lengh += &rhs.maximal_path_lengh; + self.candidates_per_node_path += &rhs.candidates_per_node_path; + self.candidates_per_root_path += &rhs.candidates_per_root_path; + self.extensions_per_node_path += &rhs.extensions_per_node_path; + self.extensions_per_root_path += &rhs.extensions_per_root_path; + self.root_visits += rhs.root_visits; + self.node_visits += &rhs.node_visits; } } diff --git a/tree-sitter-stack-graphs/src/cli/query.rs b/tree-sitter-stack-graphs/src/cli/query.rs index 296052748..74cbb658f 100644 --- a/tree-sitter-stack-graphs/src/cli/query.rs +++ b/tree-sitter-stack-graphs/src/cli/query.rs @@ -5,17 +5,22 @@ // Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. // ------------------------------------------------------------------------------------------------ +use std::fmt::Display; +use std::hash::Hash; +use std::path::Path; +use std::path::PathBuf; + use clap::Args; use clap::Parser; use clap::Subcommand; use clap::ValueHint; -use indoc::printdoc; +use stack_graphs::stats::FrequencyDistribution; use stack_graphs::stitching::ForwardPartialPathStitcher; +use stack_graphs::stitching::Stats as StitchingStats; use stack_graphs::stitching::StitcherConfig; use stack_graphs::storage::FileStatus; use stack_graphs::storage::SQLiteReader; -use std::path::Path; -use std::path::PathBuf; +use stack_graphs::storage::Stats as StorageStats; use thiserror::Error; use tree_sitter_graph::parse_error::Excerpt; @@ -48,24 +53,91 @@ impl QueryArgs { wait_for_input()?; } let mut db = SQLiteReader::open(&db_path)?; - self.target.run(&mut db)?; + let stitcher_stats = self.target.run(&mut db)?; if self.stats { - let stats = db.stats(); - printdoc! {r#" - - db stats | loads | cached - ------------+--------+-------- - files | {:>6} | {:>6} - root paths | {:>6} | {:>6} - node paths | {:>6} | {:>6} - "#, - stats.file_loads, stats.file_cached, - stats.root_path_loads, stats.root_path_cached, - stats.node_path_loads, stats.node_path_cached, - }; + Self::print_stats(stitcher_stats, db.stats()); } Ok(()) } + + fn print_stats(stitcher_stats: StitchingStats, db_stats: StorageStats) { + fn quartiles(hist: FrequencyDistribution) -> String { + let qs = hist.quantiles(4); + if qs.is_empty() { + format!( + "{:>7} | {:>7} | {:>7} | {:>7} | {:>7} | {:>7}", + "-", "-", "-", "-", "-", 0 + ) + } else { + format!( + "{:>7} | {:>7} | {:>7} | {:>7} | {:>7} | {:>7}", + qs[0], + qs[1], + qs[2], + qs[3], + qs[4], + hist.total(), + ) + } + } + println!(" stitching stats | min | p25 | p50 | p75 | max | total "); + println!("---------------------------+---------+---------+---------+---------+---------+---------"); + println!( + " queued paths per phase | {} ", + quartiles(stitcher_stats.queued_paths_per_phase) + ); + println!( + " processed paths per phase | {} ", + quartiles(stitcher_stats.processed_paths_per_phase) + ); + println!( + " accepted path length | {} ", + quartiles(stitcher_stats.accepted_path_length) + ); + println!( + " maximal path length | {} ", + quartiles(stitcher_stats.maximal_path_lengh) + ); + println!( + " node path candidates | {} ", + quartiles(stitcher_stats.candidates_per_node_path) + ); + println!( + " node path extensions | {} ", + quartiles(stitcher_stats.extensions_per_node_path) + ); + println!( + " root path candidates | {} ", + quartiles(stitcher_stats.candidates_per_root_path) + ); + println!( + " root path extensions | {} ", + quartiles(stitcher_stats.extensions_per_root_path) + ); + println!( + " node visits | {} ", + quartiles(stitcher_stats.node_visits.frequencies()) + ); + println!( + " root visits | {:>7} ", + stitcher_stats.root_visits + ); + println!(); + println!(" database stats | loads | cached "); + println!("---------------------------+---------+---------"); + println!( + " files | {:>7} | {:>7} ", + db_stats.file_loads, db_stats.file_cached + ); + println!( + " node paths | {:>7} | {:>7} ", + db_stats.node_path_loads, db_stats.node_path_cached + ); + println!( + " root paths | {:>7} | {:>7} ", + db_stats.root_path_loads, db_stats.root_path_cached + ); + } } #[derive(Subcommand)] @@ -74,7 +146,7 @@ pub enum Target { } impl Target { - pub fn run(self, db: &mut SQLiteReader) -> anyhow::Result<()> { + pub fn run(self, db: &mut SQLiteReader) -> anyhow::Result { let reporter = ConsoleReporter::details(); let mut querier = Querier::new(db, &reporter); match self { @@ -96,13 +168,16 @@ pub struct Definition { } impl Definition { - pub fn run(self, querier: &mut Querier) -> anyhow::Result<()> { + pub fn run(self, querier: &mut Querier) -> anyhow::Result { let cancellation_flag = NoCancellation; + let mut stats = StitchingStats::default(); let mut file_reader = FileReader::new(); for mut reference in self.references { reference.canonicalize()?; - let results = querier.definitions(reference.clone(), &cancellation_flag)?; + let (results, ref_stats) = + querier.definitions(reference.clone(), &cancellation_flag)?; + stats += &ref_stats; let numbered = results.len() > 1; let indent = if numbered { 6 } else { 0 }; if numbered { @@ -150,7 +225,7 @@ impl Definition { } } } - Ok(()) + Ok(stats) } } @@ -168,7 +243,7 @@ impl<'a> Querier<'a> { &mut self, reference: SourcePosition, cancellation_flag: &dyn CancellationFlag, - ) -> Result> { + ) -> Result<(Vec, StitchingStats)> { let log_path = PathBuf::from(reference.to_string()); let mut file_reader = FileReader::new(); @@ -181,7 +256,7 @@ impl<'a> Querier<'a> { _ => { self.reporter.started(&log_path); self.reporter.failed(&log_path, "file not indexed", None); - return Ok(Vec::default()); + return Ok(Default::default()); } } @@ -195,10 +270,11 @@ impl<'a> Querier<'a> { if starting_nodes.is_empty() { self.reporter .cancelled(&log_path, "no references at location", None); - return Ok(Vec::default()); + return Ok(Default::default()); } let mut result = Vec::new(); + let mut stats = StitchingStats::default(); for (node, span) in starting_nodes { let reference_span = SourceSpan { path: reference.path.clone(), @@ -209,7 +285,7 @@ impl<'a> Querier<'a> { let stitcher_config = StitcherConfig::default() // always detect similar paths, we don't know the language configurations for the data in the database .with_detect_similar_paths(true); - if let Err(err) = ForwardPartialPathStitcher::find_all_complete_partial_paths( + let ref_result = ForwardPartialPathStitcher::find_all_complete_partial_paths( self.db, std::iter::once(node), stitcher_config, @@ -217,9 +293,13 @@ impl<'a> Querier<'a> { |_g, _ps, p| { reference_paths.push(p.clone()); }, - ) { - self.reporter.failed(&log_path, "query timed out", None); - return Err(err.into()); + ); + match ref_result { + Ok(ref_stats) => stats += &ref_stats, + Err(err) => { + self.reporter.failed(&log_path, "query timed out", None); + return Err(err.into()); + } } let (graph, partials, _) = self.db.get(); @@ -269,7 +349,7 @@ impl<'a> Querier<'a> { None, ); - Ok(result) + Ok((result, stats)) } } From 9a49f57ec34b31d8b08b968b74da065e3f068320 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 25 Oct 2023 09:18:21 +0100 Subject: [PATCH 274/500] Move stats printing to util module --- tree-sitter-stack-graphs/src/cli/query.rs | 89 ++--------------------- tree-sitter-stack-graphs/src/cli/util.rs | 87 ++++++++++++++++++++++ 2 files changed, 92 insertions(+), 84 deletions(-) diff --git a/tree-sitter-stack-graphs/src/cli/query.rs b/tree-sitter-stack-graphs/src/cli/query.rs index 74cbb658f..99c07e668 100644 --- a/tree-sitter-stack-graphs/src/cli/query.rs +++ b/tree-sitter-stack-graphs/src/cli/query.rs @@ -5,8 +5,6 @@ // Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. // ------------------------------------------------------------------------------------------------ -use std::fmt::Display; -use std::hash::Hash; use std::path::Path; use std::path::PathBuf; @@ -14,16 +12,16 @@ use clap::Args; use clap::Parser; use clap::Subcommand; use clap::ValueHint; -use stack_graphs::stats::FrequencyDistribution; use stack_graphs::stitching::ForwardPartialPathStitcher; use stack_graphs::stitching::Stats as StitchingStats; use stack_graphs::stitching::StitcherConfig; use stack_graphs::storage::FileStatus; use stack_graphs::storage::SQLiteReader; -use stack_graphs::storage::Stats as StorageStats; use thiserror::Error; use tree_sitter_graph::parse_error::Excerpt; +use crate::cli::util::print_database_stats; +use crate::cli::util::print_stitcher_stats; use crate::cli::util::reporter::ConsoleReporter; use crate::cli::util::reporter::Reporter; use crate::cli::util::sha1; @@ -55,89 +53,12 @@ impl QueryArgs { let mut db = SQLiteReader::open(&db_path)?; let stitcher_stats = self.target.run(&mut db)?; if self.stats { - Self::print_stats(stitcher_stats, db.stats()); + print_stitcher_stats(stitcher_stats); + println!(); + print_database_stats(db.stats()); } Ok(()) } - - fn print_stats(stitcher_stats: StitchingStats, db_stats: StorageStats) { - fn quartiles(hist: FrequencyDistribution) -> String { - let qs = hist.quantiles(4); - if qs.is_empty() { - format!( - "{:>7} | {:>7} | {:>7} | {:>7} | {:>7} | {:>7}", - "-", "-", "-", "-", "-", 0 - ) - } else { - format!( - "{:>7} | {:>7} | {:>7} | {:>7} | {:>7} | {:>7}", - qs[0], - qs[1], - qs[2], - qs[3], - qs[4], - hist.total(), - ) - } - } - println!(" stitching stats | min | p25 | p50 | p75 | max | total "); - println!("---------------------------+---------+---------+---------+---------+---------+---------"); - println!( - " queued paths per phase | {} ", - quartiles(stitcher_stats.queued_paths_per_phase) - ); - println!( - " processed paths per phase | {} ", - quartiles(stitcher_stats.processed_paths_per_phase) - ); - println!( - " accepted path length | {} ", - quartiles(stitcher_stats.accepted_path_length) - ); - println!( - " maximal path length | {} ", - quartiles(stitcher_stats.maximal_path_lengh) - ); - println!( - " node path candidates | {} ", - quartiles(stitcher_stats.candidates_per_node_path) - ); - println!( - " node path extensions | {} ", - quartiles(stitcher_stats.extensions_per_node_path) - ); - println!( - " root path candidates | {} ", - quartiles(stitcher_stats.candidates_per_root_path) - ); - println!( - " root path extensions | {} ", - quartiles(stitcher_stats.extensions_per_root_path) - ); - println!( - " node visits | {} ", - quartiles(stitcher_stats.node_visits.frequencies()) - ); - println!( - " root visits | {:>7} ", - stitcher_stats.root_visits - ); - println!(); - println!(" database stats | loads | cached "); - println!("---------------------------+---------+---------"); - println!( - " files | {:>7} | {:>7} ", - db_stats.file_loads, db_stats.file_cached - ); - println!( - " node paths | {:>7} | {:>7} ", - db_stats.node_path_loads, db_stats.node_path_cached - ); - println!( - " root paths | {:>7} | {:>7} ", - db_stats.root_path_loads, db_stats.root_path_cached - ); - } } #[derive(Subcommand)] diff --git a/tree-sitter-stack-graphs/src/cli/util.rs b/tree-sitter-stack-graphs/src/cli/util.rs index 7d50c8a44..91c861a8c 100644 --- a/tree-sitter-stack-graphs/src/cli/util.rs +++ b/tree-sitter-stack-graphs/src/cli/util.rs @@ -18,8 +18,13 @@ use sha1::Sha1; use stack_graphs::arena::Handle; use stack_graphs::graph::Node; use stack_graphs::graph::StackGraph; +use stack_graphs::stats::FrequencyDistribution; +use stack_graphs::stitching::Stats as StitchingStats; +use stack_graphs::storage::Stats as StorageStats; use std::ffi::OsStr; use std::ffi::OsString; +use std::fmt::Display; +use std::hash::Hash; use std::io::Write; use std::ops::Range; use std::path::Path; @@ -495,3 +500,85 @@ impl std::fmt::Display for DisplayBuildErrorPretty<'_> { ) } } + +pub(super) fn print_stitcher_stats(stats: StitchingStats) { + fn quartiles(hist: FrequencyDistribution) -> String { + let qs = hist.quantiles(4); + if qs.is_empty() { + format!( + "{:>7} | {:>7} | {:>7} | {:>7} | {:>7} | {:>7}", + "-", "-", "-", "-", "-", 0 + ) + } else { + format!( + "{:>7} | {:>7} | {:>7} | {:>7} | {:>7} | {:>7}", + qs[0], + qs[1], + qs[2], + qs[3], + qs[4], + hist.total(), + ) + } + } + println!( + " stitching stats | min | p25 | p50 | p75 | max | total " + ); + println!( + "---------------------------+---------+---------+---------+---------+---------+---------" + ); + println!( + " queued paths per phase | {} ", + quartiles(stats.queued_paths_per_phase) + ); + println!( + " processed paths per phase | {} ", + quartiles(stats.processed_paths_per_phase) + ); + println!( + " accepted path length | {} ", + quartiles(stats.accepted_path_length) + ); + println!( + " maximal path length | {} ", + quartiles(stats.maximal_path_lengh) + ); + println!( + " node path candidates | {} ", + quartiles(stats.candidates_per_node_path) + ); + println!( + " node path extensions | {} ", + quartiles(stats.extensions_per_node_path) + ); + println!( + " root path candidates | {} ", + quartiles(stats.candidates_per_root_path) + ); + println!( + " root path extensions | {} ", + quartiles(stats.extensions_per_root_path) + ); + println!( + " node visits | {} ", + quartiles(stats.node_visits.frequencies()) + ); + println!(" root visits | {:>7} ", stats.root_visits); +} + +pub(super) fn print_database_stats(stats: StorageStats) { + println!(" database stats | loads | cached "); + println!("---------------------------+---------+---------"); + println!( + " files | {:>7} | {:>7} ", + stats.file_loads, stats.file_cached + ); + println!( + " node paths | {:>7} | {:>7} ", + stats.node_path_loads, stats.node_path_cached + ); + println!( + " root paths | {:>7} | {:>7} ", + stats.root_path_loads, stats.root_path_cached + ); +} From 350b46d83467062097cfa5115ce8d42cd0901c85 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 25 Oct 2023 09:41:24 +0100 Subject: [PATCH 275/500] Add stats to indexing --- tree-sitter-stack-graphs/src/cli/index.rs | 24 +++++++++++++++++++- tree-sitter-stack-graphs/src/cli/query.rs | 27 ++++++++++++++++------- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/tree-sitter-stack-graphs/src/cli/index.rs b/tree-sitter-stack-graphs/src/cli/index.rs index dab12e537..3c48f624a 100644 --- a/tree-sitter-stack-graphs/src/cli/index.rs +++ b/tree-sitter-stack-graphs/src/cli/index.rs @@ -12,6 +12,7 @@ use stack_graphs::graph::File; use stack_graphs::graph::StackGraph; use stack_graphs::partial::PartialPaths; use stack_graphs::stitching::ForwardPartialPathStitcher; +use stack_graphs::stitching::Stats as StitchingStats; use stack_graphs::stitching::StitcherConfig; use stack_graphs::storage::FileStatus; use stack_graphs::storage::SQLiteWriter; @@ -24,6 +25,7 @@ use tree_sitter_graph::Variables; use crate::cli::util::duration_from_seconds_str; use crate::cli::util::iter_files_and_directories; +use crate::cli::util::print_stitcher_stats; use crate::cli::util::reporter::ConsoleReporter; use crate::cli::util::reporter::Level; use crate::cli::util::reporter::Reporter; @@ -79,6 +81,9 @@ pub struct IndexArgs { )] pub max_file_time: Option, + #[clap(long)] + pub stats: bool, + /// Wait for user input before starting analysis. Useful for profiling. #[clap(long)] pub wait_at_start: bool, @@ -94,6 +99,7 @@ impl IndexArgs { hide_error_details: false, max_file_time: None, wait_at_start: false, + stats: false, } } @@ -113,6 +119,10 @@ impl IndexArgs { .map(|p| p.canonicalize()) .collect::, _>>()?; indexer.index_all(source_paths, self.continue_from, &NoCancellation)?; + + if self.stats { + print_stitcher_stats(indexer.into_stats()); + } Ok(()) } @@ -146,6 +156,7 @@ pub struct Indexer<'a> { db: &'a mut SQLiteWriter, loader: &'a mut Loader, reporter: &'a dyn Reporter, + stats: StitchingStats, /// Index files, even if they already exist in the database. pub force: bool, /// Maximum time per file. @@ -164,6 +175,7 @@ impl<'a> Indexer<'a> { reporter, force: false, max_file_time: None, + stats: StitchingStats::default(), } } @@ -364,7 +376,9 @@ impl<'a> Indexer<'a> { paths.push(p.clone()); }, ) { - Ok(_) => {} + Ok(stats) => { + self.stats += &stats; + } Err(_) => { file_status.warning("path computation timed out", None); self.db.store_error_for_file( @@ -442,6 +456,14 @@ impl<'a> Indexer<'a> { *continue_from = None; false } + + pub fn stats(&self) -> &StitchingStats { + &self.stats + } + + pub fn into_stats(self) -> StitchingStats { + self.stats + } } #[derive(Debug, Error)] diff --git a/tree-sitter-stack-graphs/src/cli/query.rs b/tree-sitter-stack-graphs/src/cli/query.rs index 99c07e668..2132b88ea 100644 --- a/tree-sitter-stack-graphs/src/cli/query.rs +++ b/tree-sitter-stack-graphs/src/cli/query.rs @@ -96,9 +96,8 @@ impl Definition { for mut reference in self.references { reference.canonicalize()?; - let (results, ref_stats) = - querier.definitions(reference.clone(), &cancellation_flag)?; - stats += &ref_stats; + let results = querier.definitions(reference.clone(), &cancellation_flag)?; + stats += querier.stats(); let numbered = results.len() > 1; let indent = if numbered { 6 } else { 0 }; if numbered { @@ -153,18 +152,23 @@ impl Definition { pub struct Querier<'a> { db: &'a mut SQLiteReader, reporter: &'a dyn Reporter, + stats: StitchingStats, } impl<'a> Querier<'a> { pub fn new(db: &'a mut SQLiteReader, reporter: &'a dyn Reporter) -> Self { - Self { db, reporter } + Self { + db, + reporter, + stats: StitchingStats::default(), + } } pub fn definitions( &mut self, reference: SourcePosition, cancellation_flag: &dyn CancellationFlag, - ) -> Result<(Vec, StitchingStats)> { + ) -> Result> { let log_path = PathBuf::from(reference.to_string()); let mut file_reader = FileReader::new(); @@ -195,7 +199,6 @@ impl<'a> Querier<'a> { } let mut result = Vec::new(); - let mut stats = StitchingStats::default(); for (node, span) in starting_nodes { let reference_span = SourceSpan { path: reference.path.clone(), @@ -216,7 +219,7 @@ impl<'a> Querier<'a> { }, ); match ref_result { - Ok(ref_stats) => stats += &ref_stats, + Ok(ref_stats) => self.stats += &ref_stats, Err(err) => { self.reporter.failed(&log_path, "query timed out", None); return Err(err.into()); @@ -270,7 +273,15 @@ impl<'a> Querier<'a> { None, ); - Ok((result, stats)) + Ok(result) + } + + pub fn stats(&self) -> &StitchingStats { + &self.stats + } + + pub fn into_stats(self) -> StitchingStats { + self.stats } } From c36df79356438130ac7e38ab01f44c65a330e6dd Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 25 Oct 2023 09:59:42 +0100 Subject: [PATCH 276/500] Make whitespace before stats consistent --- tree-sitter-stack-graphs/src/cli/index.rs | 1 + tree-sitter-stack-graphs/src/cli/query.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tree-sitter-stack-graphs/src/cli/index.rs b/tree-sitter-stack-graphs/src/cli/index.rs index 3c48f624a..63b17cbb8 100644 --- a/tree-sitter-stack-graphs/src/cli/index.rs +++ b/tree-sitter-stack-graphs/src/cli/index.rs @@ -121,6 +121,7 @@ impl IndexArgs { indexer.index_all(source_paths, self.continue_from, &NoCancellation)?; if self.stats { + println!(); print_stitcher_stats(indexer.into_stats()); } Ok(()) diff --git a/tree-sitter-stack-graphs/src/cli/query.rs b/tree-sitter-stack-graphs/src/cli/query.rs index 2132b88ea..451a57271 100644 --- a/tree-sitter-stack-graphs/src/cli/query.rs +++ b/tree-sitter-stack-graphs/src/cli/query.rs @@ -53,6 +53,7 @@ impl QueryArgs { let mut db = SQLiteReader::open(&db_path)?; let stitcher_stats = self.target.run(&mut db)?; if self.stats { + println!(); print_stitcher_stats(stitcher_stats); println!(); print_database_stats(db.stats()); @@ -132,7 +133,7 @@ impl Definition { n => println!("{}has {} definitions", " ".repeat(indent), n), } for definition in definitions.into_iter() { - println!( + print!( "{}", Excerpt::from_source( &definition.path, From 5e86ee868903cb1bad6df4be8f018e971ce2f645 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 25 Oct 2023 10:03:38 +0100 Subject: [PATCH 277/500] Use consistent names --- tree-sitter-stack-graphs/src/cli/index.rs | 4 ++-- tree-sitter-stack-graphs/src/cli/query.rs | 6 +++--- tree-sitter-stack-graphs/src/cli/util.rs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tree-sitter-stack-graphs/src/cli/index.rs b/tree-sitter-stack-graphs/src/cli/index.rs index 63b17cbb8..9a03bf1b6 100644 --- a/tree-sitter-stack-graphs/src/cli/index.rs +++ b/tree-sitter-stack-graphs/src/cli/index.rs @@ -25,7 +25,7 @@ use tree_sitter_graph::Variables; use crate::cli::util::duration_from_seconds_str; use crate::cli::util::iter_files_and_directories; -use crate::cli::util::print_stitcher_stats; +use crate::cli::util::print_stitching_stats; use crate::cli::util::reporter::ConsoleReporter; use crate::cli::util::reporter::Level; use crate::cli::util::reporter::Reporter; @@ -122,7 +122,7 @@ impl IndexArgs { if self.stats { println!(); - print_stitcher_stats(indexer.into_stats()); + print_stitching_stats(indexer.into_stats()); } Ok(()) } diff --git a/tree-sitter-stack-graphs/src/cli/query.rs b/tree-sitter-stack-graphs/src/cli/query.rs index 451a57271..42c210e83 100644 --- a/tree-sitter-stack-graphs/src/cli/query.rs +++ b/tree-sitter-stack-graphs/src/cli/query.rs @@ -21,7 +21,7 @@ use thiserror::Error; use tree_sitter_graph::parse_error::Excerpt; use crate::cli::util::print_database_stats; -use crate::cli::util::print_stitcher_stats; +use crate::cli::util::print_stitching_stats; use crate::cli::util::reporter::ConsoleReporter; use crate::cli::util::reporter::Reporter; use crate::cli::util::sha1; @@ -51,10 +51,10 @@ impl QueryArgs { wait_for_input()?; } let mut db = SQLiteReader::open(&db_path)?; - let stitcher_stats = self.target.run(&mut db)?; + let stitching_stats = self.target.run(&mut db)?; if self.stats { println!(); - print_stitcher_stats(stitcher_stats); + print_stitching_stats(stitching_stats); println!(); print_database_stats(db.stats()); } diff --git a/tree-sitter-stack-graphs/src/cli/util.rs b/tree-sitter-stack-graphs/src/cli/util.rs index 91c861a8c..ff2cddb32 100644 --- a/tree-sitter-stack-graphs/src/cli/util.rs +++ b/tree-sitter-stack-graphs/src/cli/util.rs @@ -501,7 +501,7 @@ impl std::fmt::Display for DisplayBuildErrorPretty<'_> { } } -pub(super) fn print_stitcher_stats(stats: StitchingStats) { +pub(super) fn print_stitching_stats(stats: StitchingStats) { fn quartiles(hist: FrequencyDistribution) -> String { let qs = hist.quantiles(4); if qs.is_empty() { From 61122ba1dd08cfdc199057b5c5096d10a785320a Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 25 Oct 2023 10:11:43 +0100 Subject: [PATCH 278/500] Give stats more space --- tree-sitter-stack-graphs/src/cli/util.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tree-sitter-stack-graphs/src/cli/util.rs b/tree-sitter-stack-graphs/src/cli/util.rs index ff2cddb32..882fd1bd3 100644 --- a/tree-sitter-stack-graphs/src/cli/util.rs +++ b/tree-sitter-stack-graphs/src/cli/util.rs @@ -506,12 +506,12 @@ pub(super) fn print_stitching_stats(stats: StitchingStats) { let qs = hist.quantiles(4); if qs.is_empty() { format!( - "{:>7} | {:>7} | {:>7} | {:>7} | {:>7} | {:>7}", + "{:>9} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9}", "-", "-", "-", "-", "-", 0 ) } else { format!( - "{:>7} | {:>7} | {:>7} | {:>7} | {:>7} | {:>7}", + "{:>9} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9}", qs[0], qs[1], qs[2], @@ -522,10 +522,10 @@ pub(super) fn print_stitching_stats(stats: StitchingStats) { } } println!( - " stitching stats | min | p25 | p50 | p75 | max | total " + " stitching stats | min | p25 | p50 | p75 | max | total " ); println!( - "---------------------------+---------+---------+---------+---------+---------+---------" + "---------------------------+-----------+-----------+-----------+-----------+-----------+-----------" ); println!( " queued paths per phase | {} ", @@ -563,22 +563,22 @@ pub(super) fn print_stitching_stats(stats: StitchingStats) { " node visits | {} ", quartiles(stats.node_visits.frequencies()) ); - println!(" root visits | {:>7} ", stats.root_visits); + println!(" root visits | {:>9} ", stats.root_visits); } pub(super) fn print_database_stats(stats: StorageStats) { println!(" database stats | loads | cached "); println!("---------------------------+---------+---------"); println!( - " files | {:>7} | {:>7} ", + " files | {:>9} | {:>9} ", stats.file_loads, stats.file_cached ); println!( - " node paths | {:>7} | {:>7} ", + " node paths | {:>9} | {:>9} ", stats.node_path_loads, stats.node_path_cached ); println!( - " root paths | {:>7} | {:>7} ", + " root paths | {:>9} | {:>9} ", stats.root_path_loads, stats.root_path_cached ); } From 57119900f231598e12005025b78125240aa1ddba Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 27 Oct 2023 20:32:26 +0100 Subject: [PATCH 279/500] Replace += with record() --- stack-graphs/src/stats.rs | 24 ++++++++++++--- stack-graphs/src/stitching.rs | 37 +++++++++++++++++------ stack-graphs/tests/it/stats.rs | 17 ++++++++--- tree-sitter-stack-graphs/src/cli/index.rs | 2 +- tree-sitter-stack-graphs/src/cli/query.rs | 11 +++---- 5 files changed, 64 insertions(+), 27 deletions(-) diff --git a/stack-graphs/src/stats.rs b/stack-graphs/src/stats.rs index b74098f12..62bde332b 100644 --- a/stack-graphs/src/stats.rs +++ b/stack-graphs/src/stats.rs @@ -1,3 +1,10 @@ +// -*- coding: utf-8 -*- +// ------------------------------------------------------------------------------------------------ +// Copyright © 2023, stack-graphs authors. +// Licensed under either of Apache License, Version 2.0, or MIT license, at your option. +// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. +// ------------------------------------------------------------------------------------------------ + use std::collections::HashMap; use std::hash::Hash; @@ -14,6 +21,11 @@ where } impl FrequencyDistribution { + pub fn record(&mut self, value: T) { + *self.values.entry(value).or_default() += 1; + self.total += 1; + } + pub fn total(&self) -> usize { return self.total; } @@ -25,7 +37,7 @@ impl FrequencyDistribution { pub fn frequencies(&self) -> FrequencyDistribution { let mut fs = FrequencyDistribution::default(); for count in self.values.values() { - fs += *count + fs.record(*count); } fs } @@ -67,13 +79,15 @@ impl FrequencyDistribution { } } -impl std::ops::AddAssign for FrequencyDistribution +impl std::ops::AddAssign for FrequencyDistribution where T: Eq + Hash, { - fn add_assign(&mut self, rhs: T) { - *self.values.entry(rhs).or_default() += 1; - self.total += 1; + fn add_assign(&mut self, rhs: Self) { + for (value, count) in rhs.values { + *self.values.entry(value).or_default() += count; + } + self.total += rhs.total; } } diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index 51aab53ba..c5e9b97ed 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -1066,17 +1066,19 @@ impl ForwardPartialPathStitcher { let (graph, _, _) = candidates.get_graph_partials_and_db(); let end_node = &graph[partial_path.end_node]; if end_node.is_root() { - self.stats.candidates_per_root_path += candidate_count; - self.stats.extensions_per_root_path += extension_count; + self.stats.candidates_per_root_path.record(candidate_count); + self.stats.extensions_per_root_path.record(extension_count); self.stats.root_visits += 1; } else { - self.stats.candidates_per_node_path += candidate_count; - self.stats.extensions_per_node_path += extension_count; - self.stats.node_visits += end_node.id(); + self.stats.candidates_per_node_path.record(candidate_count); + self.stats.extensions_per_node_path.record(extension_count); + self.stats.node_visits.record(end_node.id()); } if extension_count == 0 { - self.stats.maximal_path_lengh += partial_path.edges.len(); + self.stats + .maximal_path_lengh + .record(partial_path.edges.len()); } candidate_count } @@ -1111,7 +1113,7 @@ impl ForwardPartialPathStitcher { self.next_iteration.1.drain(..), self.next_iteration.2.drain(..), )); - self.stats.queued_paths_per_phase += self.queue.len(); + self.stats.queued_paths_per_phase.record(self.queue.len()); let mut work_performed = 0; while let Some((partial_path, cycle_detector, has_split)) = self.queue.pop_front() { let (graph, partials, _) = candidates.get_graph_partials_and_db(); @@ -1133,7 +1135,7 @@ impl ForwardPartialPathStitcher { break; } } - self.stats.processed_paths_per_phase += work_performed; + self.stats.processed_paths_per_phase.record(work_performed); #[cfg(feature = "copious-debugging")] { @@ -1202,7 +1204,7 @@ impl ForwardPartialPathStitcher { ); for path in stitcher.previous_phase_partial_paths() { if as_complete_as_necessary(graph, path) { - accepted_path_length += path.edges.len(); + accepted_path_length.record(path.edges.len()); visit(graph, partials, path); } } @@ -1267,7 +1269,7 @@ impl ForwardPartialPathStitcher { let (graph, partials, _) = candidates.get_graph_partials_and_db(); for path in stitcher.previous_phase_partial_paths() { if path.is_complete(graph) { - accepted_path_length += path.edges.len(); + accepted_path_length.record(path.edges.len()); visit(graph, partials, path); } } @@ -1304,6 +1306,21 @@ pub struct Stats { pub node_visits: FrequencyDistribution, } +impl std::ops::AddAssign for Stats { + fn add_assign(&mut self, rhs: Self) { + self.queued_paths_per_phase += rhs.queued_paths_per_phase; + self.processed_paths_per_phase += rhs.processed_paths_per_phase; + self.accepted_path_length += rhs.accepted_path_length; + self.maximal_path_lengh += rhs.maximal_path_lengh; + self.candidates_per_node_path += rhs.candidates_per_node_path; + self.candidates_per_root_path += rhs.candidates_per_root_path; + self.extensions_per_node_path += rhs.extensions_per_node_path; + self.extensions_per_root_path += rhs.extensions_per_root_path; + self.root_visits += rhs.root_visits; + self.node_visits += rhs.node_visits; + } +} + impl std::ops::AddAssign<&Self> for Stats { fn add_assign(&mut self, rhs: &Self) { self.queued_paths_per_phase += &rhs.queued_paths_per_phase; diff --git a/stack-graphs/tests/it/stats.rs b/stack-graphs/tests/it/stats.rs index f4a48cd03..d0ebd4757 100644 --- a/stack-graphs/tests/it/stats.rs +++ b/stack-graphs/tests/it/stats.rs @@ -1,3 +1,10 @@ +// -*- coding: utf-8 -*- +// ------------------------------------------------------------------------------------------------ +// Copyright © 2023, stack-graphs authors. +// Licensed under either of Apache License, Version 2.0, or MIT license, at your option. +// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. +// ------------------------------------------------------------------------------------------------ + use itertools::Itertools; use pretty_assertions::assert_eq; @@ -18,7 +25,7 @@ fn empty_distribution() { #[test] fn singleton_distribution() { let mut hist = FrequencyDistribution::default(); - hist += 42; + hist.record(42); assert_eq!(1, hist.unique()); assert_eq!(1, hist.total()); @@ -31,10 +38,10 @@ fn singleton_distribution() { #[test] fn four_value_distribution() { let mut hist = FrequencyDistribution::default(); - hist += 3; - hist += 4; - hist += 1; - hist += 2; + hist.record(3); + hist.record(4); + hist.record(1); + hist.record(2); assert_eq!(4, hist.unique()); assert_eq!(4, hist.total()); diff --git a/tree-sitter-stack-graphs/src/cli/index.rs b/tree-sitter-stack-graphs/src/cli/index.rs index 9a03bf1b6..bbfda9d22 100644 --- a/tree-sitter-stack-graphs/src/cli/index.rs +++ b/tree-sitter-stack-graphs/src/cli/index.rs @@ -378,7 +378,7 @@ impl<'a> Indexer<'a> { }, ) { Ok(stats) => { - self.stats += &stats; + self.stats += stats; } Err(_) => { file_status.warning("path computation timed out", None); diff --git a/tree-sitter-stack-graphs/src/cli/query.rs b/tree-sitter-stack-graphs/src/cli/query.rs index 42c210e83..1c57145fe 100644 --- a/tree-sitter-stack-graphs/src/cli/query.rs +++ b/tree-sitter-stack-graphs/src/cli/query.rs @@ -72,8 +72,9 @@ impl Target { let reporter = ConsoleReporter::details(); let mut querier = Querier::new(db, &reporter); match self { - Self::Definition(cmd) => cmd.run(&mut querier), + Self::Definition(cmd) => cmd.run(&mut querier)?, } + Ok(querier.into_stats()) } } @@ -90,15 +91,13 @@ pub struct Definition { } impl Definition { - pub fn run(self, querier: &mut Querier) -> anyhow::Result { + pub fn run(self, querier: &mut Querier) -> anyhow::Result<()> { let cancellation_flag = NoCancellation; - let mut stats = StitchingStats::default(); let mut file_reader = FileReader::new(); for mut reference in self.references { reference.canonicalize()?; let results = querier.definitions(reference.clone(), &cancellation_flag)?; - stats += querier.stats(); let numbered = results.len() > 1; let indent = if numbered { 6 } else { 0 }; if numbered { @@ -146,7 +145,7 @@ impl Definition { } } } - Ok(stats) + Ok(()) } } @@ -220,7 +219,7 @@ impl<'a> Querier<'a> { }, ); match ref_result { - Ok(ref_stats) => self.stats += &ref_stats, + Ok(ref_stats) => self.stats += ref_stats, Err(err) => { self.reporter.failed(&log_path, "query timed out", None); return Err(err.into()); From 08a636f6ea1cbe0420e682db5774abc8f648bd91 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 9 Nov 2023 19:16:20 +0100 Subject: [PATCH 280/500] Add some indexing stats --- tree-sitter-stack-graphs/src/cli/index.rs | 44 ++++++-- tree-sitter-stack-graphs/src/cli/util.rs | 123 +++++++++++----------- 2 files changed, 96 insertions(+), 71 deletions(-) diff --git a/tree-sitter-stack-graphs/src/cli/index.rs b/tree-sitter-stack-graphs/src/cli/index.rs index bbfda9d22..ac445b36f 100644 --- a/tree-sitter-stack-graphs/src/cli/index.rs +++ b/tree-sitter-stack-graphs/src/cli/index.rs @@ -11,6 +11,7 @@ use stack_graphs::arena::Handle; use stack_graphs::graph::File; use stack_graphs::graph::StackGraph; use stack_graphs::partial::PartialPaths; +use stack_graphs::stats::FrequencyDistribution; use stack_graphs::stitching::ForwardPartialPathStitcher; use stack_graphs::stitching::Stats as StitchingStats; use stack_graphs::stitching::StitcherConfig; @@ -25,7 +26,7 @@ use tree_sitter_graph::Variables; use crate::cli::util::duration_from_seconds_str; use crate::cli::util::iter_files_and_directories; -use crate::cli::util::print_stitching_stats; +use crate::cli::util::print_indexing_stats; use crate::cli::util::reporter::ConsoleReporter; use crate::cli::util::reporter::Level; use crate::cli::util::reporter::Reporter; @@ -122,7 +123,7 @@ impl IndexArgs { if self.stats { println!(); - print_stitching_stats(indexer.into_stats()); + print_indexing_stats(indexer.into_stats()); } Ok(()) } @@ -157,7 +158,7 @@ pub struct Indexer<'a> { db: &'a mut SQLiteWriter, loader: &'a mut Loader, reporter: &'a dyn Reporter, - stats: StitchingStats, + stats: IndexingStats, /// Index files, even if they already exist in the database. pub force: bool, /// Maximum time per file. @@ -176,7 +177,7 @@ impl<'a> Indexer<'a> { reporter, force: false, max_file_time: None, - stats: StitchingStats::default(), + stats: IndexingStats::default(), } } @@ -364,6 +365,21 @@ impl<'a> Indexer<'a> { } } }; + { + self.stats + .total_graph_nodes + .record(graph.iter_nodes().count()); + let mut total_edges = 0; + for node_edges in graph + .iter_nodes() + .filter(|n| !graph[*n].is_root()) + .map(|n| graph.outgoing_edges(n).count()) + { + self.stats.node_out_degrees.record(node_edges); + total_edges += node_edges; + } + self.stats.total_graph_edges.record(total_edges); + } let mut partials = PartialPaths::new(); let mut paths = Vec::new(); @@ -377,8 +393,8 @@ impl<'a> Indexer<'a> { paths.push(p.clone()); }, ) { - Ok(stats) => { - self.stats += stats; + Ok(stitching_stats) => { + self.stats.stitching_stats += stitching_stats; } Err(_) => { file_status.warning("path computation timed out", None); @@ -458,11 +474,11 @@ impl<'a> Indexer<'a> { false } - pub fn stats(&self) -> &StitchingStats { + pub fn stats(&self) -> &IndexingStats { &self.stats } - pub fn into_stats(self) -> StitchingStats { + pub fn into_stats(self) -> IndexingStats { self.stats } } @@ -488,3 +504,15 @@ impl From for IndexError { } type Result = std::result::Result; + +#[derive(Clone, Debug, Default)] +pub struct IndexingStats { + // The distribution of the total number of nodes per file graph. + pub total_graph_nodes: FrequencyDistribution, + // The distribution of the total number of edges per file graph. + pub total_graph_edges: FrequencyDistribution, + // The distribution of the out-degrees of non-root nodes. + pub node_out_degrees: FrequencyDistribution, + // The stitching statistics. + pub stitching_stats: StitchingStats, +} diff --git a/tree-sitter-stack-graphs/src/cli/util.rs b/tree-sitter-stack-graphs/src/cli/util.rs index 882fd1bd3..54864bea7 100644 --- a/tree-sitter-stack-graphs/src/cli/util.rs +++ b/tree-sitter-stack-graphs/src/cli/util.rs @@ -32,7 +32,8 @@ use std::path::PathBuf; use std::time::Duration; use walkdir::WalkDir; -use self::reporter::Reporter; +use crate::cli::index::IndexingStats; +use crate::cli::util::reporter::Reporter; pub mod reporter; @@ -501,69 +502,27 @@ impl std::fmt::Display for DisplayBuildErrorPretty<'_> { } } +pub(super) fn print_indexing_stats(stats: IndexingStats) { + print_quartiles_header("graph stats"); + print_quartiles_row("total graph nodes", stats.total_graph_nodes); + print_quartiles_row("total graph edges", stats.total_graph_edges); + print_quartiles_row("node out degrees", stats.node_out_degrees); + println!(); + print_stitching_stats(stats.stitching_stats); +} + pub(super) fn print_stitching_stats(stats: StitchingStats) { - fn quartiles(hist: FrequencyDistribution) -> String { - let qs = hist.quantiles(4); - if qs.is_empty() { - format!( - "{:>9} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9}", - "-", "-", "-", "-", "-", 0 - ) - } else { - format!( - "{:>9} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9}", - qs[0], - qs[1], - qs[2], - qs[3], - qs[4], - hist.total(), - ) - } - } - println!( - " stitching stats | min | p25 | p50 | p75 | max | total " - ); - println!( - "---------------------------+-----------+-----------+-----------+-----------+-----------+-----------" - ); - println!( - " queued paths per phase | {} ", - quartiles(stats.queued_paths_per_phase) - ); - println!( - " processed paths per phase | {} ", - quartiles(stats.processed_paths_per_phase) - ); - println!( - " accepted path length | {} ", - quartiles(stats.accepted_path_length) - ); - println!( - " maximal path length | {} ", - quartiles(stats.maximal_path_lengh) - ); - println!( - " node path candidates | {} ", - quartiles(stats.candidates_per_node_path) - ); - println!( - " node path extensions | {} ", - quartiles(stats.extensions_per_node_path) - ); - println!( - " root path candidates | {} ", - quartiles(stats.candidates_per_root_path) - ); - println!( - " root path extensions | {} ", - quartiles(stats.extensions_per_root_path) - ); - println!( - " node visits | {} ", - quartiles(stats.node_visits.frequencies()) - ); - println!(" root visits | {:>9} ", stats.root_visits); + print_quartiles_header("stitching stats"); + print_quartiles_row("queued paths per phase", stats.queued_paths_per_phase); + print_quartiles_row("processed paths per phase", stats.processed_paths_per_phase); + print_quartiles_row("accepted path length", stats.accepted_path_length); + print_quartiles_row("maximal path length", stats.maximal_path_lengh); + print_quartiles_row("node path candidates", stats.candidates_per_node_path); + print_quartiles_row("node path extensions", stats.extensions_per_node_path); + print_quartiles_row("root path candidates", stats.candidates_per_root_path); + print_quartiles_row("root path extensions", stats.extensions_per_root_path); + print_quartiles_row("node visits", stats.node_visits.frequencies()); + print_value_row("root visits", stats.root_visits); } pub(super) fn print_database_stats(stats: StorageStats) { @@ -582,3 +541,41 @@ pub(super) fn print_database_stats(stats: StorageStats) { stats.root_path_loads, stats.root_path_cached ); } + +fn print_quartiles_header(title: &str) { + println!( + "| {:^25} | min | p25 | p50 | p75 | max | total |", + title + ); + println!( + "|---------------------------|-----------|-----------|-----------|-----------|-----------|-----------|" + ); +} + +fn print_quartiles_row(title: &str, hist: FrequencyDistribution) { + let qs = hist.quantiles(4); + if qs.is_empty() { + println!( + "| {:>25} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9} |", + title, "-", "-", "-", "-", "-", 0 + ); + } else { + println!( + "| {:>25} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9} |", + title, + qs[0], + qs[1], + qs[2], + qs[3], + qs[4], + hist.total(), + ); + } +} + +fn print_value_row(title: &str, value: X) { + println!( + "| {:>25} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9} |", + title, "-", "-", "-", "-", "-", value + ); +} From 6ed0f3cf64def2e622c7f8fb57565e3b7a0c571d Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 10 Nov 2023 11:05:33 +0100 Subject: [PATCH 281/500] Collect similar path stats --- stack-graphs/src/cycles.rs | 54 ++++++++++++++++++++++-- stack-graphs/src/stitching.rs | 14 ++++-- tree-sitter-stack-graphs/src/cli/util.rs | 8 ++++ 3 files changed, 70 insertions(+), 6 deletions(-) diff --git a/stack-graphs/src/cycles.rs b/stack-graphs/src/cycles.rs index d10679385..e989dc471 100644 --- a/stack-graphs/src/cycles.rs +++ b/stack-graphs/src/cycles.rs @@ -44,12 +44,18 @@ use crate::partial::Cyclicity; use crate::partial::PartialPath; use crate::partial::PartialPaths; use crate::paths::PathResolutionError; +use crate::stats::FrequencyDistribution; use crate::stitching::Appendable; use crate::stitching::ToAppendable; /// Helps detect similar paths in the path-finding algorithm. pub struct SimilarPathDetector

{ - paths: HashMap>, + paths: HashMap; 4]>>, +} + +struct SimilarPath

{ + path: P, + count: usize, } #[doc(hidden)] @@ -115,16 +121,20 @@ where // is shadowed by the new path! let possibly_similar_paths = self.paths.entry(key).or_default(); let mut idx = 0; + let mut count = 0; while idx < possibly_similar_paths.len() { - match cmp(arena, path, &possibly_similar_paths[idx]) { + let other_path = &mut possibly_similar_paths[idx]; + match cmp(arena, path, &other_path.path) { Some(Ordering::Less) => { // the new path is better, remove the old one + count += other_path.count; possibly_similar_paths.remove(idx); // keep `idx` which now points to the next element continue; } Some(_) => { // the new path is equal or worse, and ignored + other_path.count += 1; return true; } None => { @@ -133,7 +143,11 @@ where } } - possibly_similar_paths.push(path.clone()); + // this path is either new or better, keep it + possibly_similar_paths.push(SimilarPath { + path: path.clone(), + count, + }); false } @@ -141,6 +155,40 @@ where pub fn max_bucket_size(&self) -> usize { self.paths.iter().map(|b| b.1.len()).max().unwrap_or(0) } + + // Returns the distribution of similar path counts. + pub fn stats(&self) -> SimilarPathStats { + let mut stats = SimilarPathStats::default(); + for bucket in self.paths.values() { + stats.similar_path_bucket_size.record(bucket.len()); + for path in bucket.iter() { + stats.similar_path_count.record(path.count); + } + } + stats + } +} + +#[derive(Clone, Debug, Default)] +pub struct SimilarPathStats { + // The distribution of the number of similar paths detected + pub similar_path_count: FrequencyDistribution, + // The distribution of the internal bucket sizes in the similar path detector + pub similar_path_bucket_size: FrequencyDistribution, +} + +impl std::ops::AddAssign for SimilarPathStats { + fn add_assign(&mut self, rhs: Self) { + self.similar_path_bucket_size += rhs.similar_path_bucket_size; + self.similar_path_count += rhs.similar_path_count; + } +} + +impl std::ops::AddAssign<&Self> for SimilarPathStats { + fn add_assign(&mut self, rhs: &Self) { + self.similar_path_bucket_size += &rhs.similar_path_bucket_size; + self.similar_path_count += &rhs.similar_path_count; + } } // ---------------------------------------------------------------------------- diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index c5e9b97ed..9c1f4ef58 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -54,6 +54,7 @@ use crate::arena::SupplementalArena; use crate::cycles::Appendables; use crate::cycles::AppendingCycleDetector; use crate::cycles::SimilarPathDetector; +use crate::cycles::SimilarPathStats; use crate::graph::Degree; use crate::graph::Edge; use crate::graph::File; @@ -913,7 +914,10 @@ impl ForwardPartialPathStitcher { self.max_work_per_phase = max_work_per_phase; } - pub fn into_stats(self) -> Stats { + pub fn into_stats(mut self) -> Stats { + if let Some(similar_path_detector) = self.similar_path_detector { + self.stats.similar_paths_stats = similar_path_detector.stats(); + } self.stats } } @@ -1212,7 +1216,7 @@ impl ForwardPartialPathStitcher { Ok(Stats { accepted_path_length, - ..stitcher.stats + ..stitcher.into_stats() }) } } @@ -1277,7 +1281,7 @@ impl ForwardPartialPathStitcher { Ok(Stats { accepted_path_length, - ..stitcher.stats + ..stitcher.into_stats() }) } } @@ -1304,6 +1308,8 @@ pub struct Stats { pub root_visits: usize, /// The distribution of the number of times a regular node is visited pub node_visits: FrequencyDistribution, + /// The distribution of the number of similar paths between node pairs. + pub similar_paths_stats: SimilarPathStats, } impl std::ops::AddAssign for Stats { @@ -1318,6 +1324,7 @@ impl std::ops::AddAssign for Stats { self.extensions_per_root_path += rhs.extensions_per_root_path; self.root_visits += rhs.root_visits; self.node_visits += rhs.node_visits; + self.similar_paths_stats += rhs.similar_paths_stats; } } @@ -1333,6 +1340,7 @@ impl std::ops::AddAssign<&Self> for Stats { self.extensions_per_root_path += &rhs.extensions_per_root_path; self.root_visits += rhs.root_visits; self.node_visits += &rhs.node_visits; + self.similar_paths_stats += &rhs.similar_paths_stats; } } diff --git a/tree-sitter-stack-graphs/src/cli/util.rs b/tree-sitter-stack-graphs/src/cli/util.rs index 54864bea7..fd93046c4 100644 --- a/tree-sitter-stack-graphs/src/cli/util.rs +++ b/tree-sitter-stack-graphs/src/cli/util.rs @@ -522,6 +522,14 @@ pub(super) fn print_stitching_stats(stats: StitchingStats) { print_quartiles_row("root path candidates", stats.candidates_per_root_path); print_quartiles_row("root path extensions", stats.extensions_per_root_path); print_quartiles_row("node visits", stats.node_visits.frequencies()); + print_quartiles_row( + "similar path counts", + stats.similar_paths_stats.similar_path_count, + ); + print_quartiles_row( + "similar path bucket sizes", + stats.similar_paths_stats.similar_path_bucket_size, + ); print_value_row("root visits", stats.root_visits); } From d677b86893f7c494bc282542ce16e94a105ab1da Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Sat, 11 Nov 2023 17:26:40 +0100 Subject: [PATCH 282/500] Tweak stitching stats --- stack-graphs/src/stats.rs | 4 ++- stack-graphs/src/stitching.rs | 19 +++++++---- stack-graphs/tests/it/stats.rs | 6 ++-- tree-sitter-stack-graphs/src/cli/index.rs | 17 ++++++---- tree-sitter-stack-graphs/src/cli/util.rs | 39 +++++++++++++---------- 5 files changed, 50 insertions(+), 35 deletions(-) diff --git a/stack-graphs/src/stats.rs b/stack-graphs/src/stats.rs index 62bde332b..6b9f6ead8 100644 --- a/stack-graphs/src/stats.rs +++ b/stack-graphs/src/stats.rs @@ -26,10 +26,12 @@ impl FrequencyDistribution { self.total += 1; } - pub fn total(&self) -> usize { + // The number of recorded values. + pub fn count(&self) -> usize { return self.total; } + // The number of unique recorded values. pub fn unique(&self) -> usize { return self.values.len(); } diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index 9c1f4ef58..9a4cca91c 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -866,6 +866,8 @@ impl ForwardPartialPathStitcher { (p, c, false) }) .multiunzip(); + let mut stats = Stats::default(); + stats.initial_paths.record(next_iteration.0.len()); Self { candidates: Vec::new(), extensions: Vec::new(), @@ -879,7 +881,7 @@ impl ForwardPartialPathStitcher { check_only_join_nodes: false, // By default, there's no artificial bound on the amount of work done per phase max_work_per_phase: usize::MAX, - stats: Stats::default(), + stats, #[cfg(feature = "copious-debugging")] phase_number: 1, } @@ -1081,7 +1083,7 @@ impl ForwardPartialPathStitcher { if extension_count == 0 { self.stats - .maximal_path_lengh + .nonextensible_path_lengh .record(partial_path.edges.len()); } candidate_count @@ -1185,7 +1187,7 @@ impl ForwardPartialPathStitcher { { fn as_complete_as_necessary(graph: &StackGraph, path: &PartialPath) -> bool { path.starts_at_endpoint(graph) - && (path.ends_at_endpoint(graph) || graph[path.end_node].is_jump_to()) + && (path.ends_at_endpoint(graph) || path.ends_in_jump(graph)) } let initial_paths = graph @@ -1288,6 +1290,8 @@ impl ForwardPartialPathStitcher { #[derive(Clone, Debug, Default)] pub struct Stats { + /// The distribution of the number of initial paths + pub initial_paths: FrequencyDistribution, /// The distribution of the number of queued paths per stitching phase pub queued_paths_per_phase: FrequencyDistribution, /// The distribution of the number of processed paths per stitching phase @@ -1295,7 +1299,7 @@ pub struct Stats { /// The distribution of the length of accepted paths pub accepted_path_length: FrequencyDistribution, /// The distribution of the maximal length of paths (when they cannot be extended more) - pub maximal_path_lengh: FrequencyDistribution, + pub nonextensible_path_lengh: FrequencyDistribution, /// The distribution of the number of candidates for paths ending in a regular node pub candidates_per_node_path: FrequencyDistribution, /// The distribution of the number of candidates for paths ending in the root node @@ -1314,10 +1318,11 @@ pub struct Stats { impl std::ops::AddAssign for Stats { fn add_assign(&mut self, rhs: Self) { + self.initial_paths += rhs.initial_paths; self.queued_paths_per_phase += rhs.queued_paths_per_phase; self.processed_paths_per_phase += rhs.processed_paths_per_phase; self.accepted_path_length += rhs.accepted_path_length; - self.maximal_path_lengh += rhs.maximal_path_lengh; + self.nonextensible_path_lengh += rhs.nonextensible_path_lengh; self.candidates_per_node_path += rhs.candidates_per_node_path; self.candidates_per_root_path += rhs.candidates_per_root_path; self.extensions_per_node_path += rhs.extensions_per_node_path; @@ -1330,10 +1335,10 @@ impl std::ops::AddAssign for Stats { impl std::ops::AddAssign<&Self> for Stats { fn add_assign(&mut self, rhs: &Self) { - self.queued_paths_per_phase += &rhs.queued_paths_per_phase; + self.initial_paths += &rhs.initial_paths; self.processed_paths_per_phase += &rhs.processed_paths_per_phase; self.accepted_path_length += &rhs.accepted_path_length; - self.maximal_path_lengh += &rhs.maximal_path_lengh; + self.nonextensible_path_lengh += &rhs.nonextensible_path_lengh; self.candidates_per_node_path += &rhs.candidates_per_node_path; self.candidates_per_root_path += &rhs.candidates_per_root_path; self.extensions_per_node_path += &rhs.extensions_per_node_path; diff --git a/stack-graphs/tests/it/stats.rs b/stack-graphs/tests/it/stats.rs index d0ebd4757..4d83d0c1d 100644 --- a/stack-graphs/tests/it/stats.rs +++ b/stack-graphs/tests/it/stats.rs @@ -15,7 +15,7 @@ fn empty_distribution() { let hist: FrequencyDistribution = FrequencyDistribution::default(); assert_eq!(0, hist.unique()); - assert_eq!(0, hist.total()); + assert_eq!(0, hist.count()); let result = hist.quantiles(0).into_iter().cloned().collect_vec(); let expected: Vec = vec![]; @@ -28,7 +28,7 @@ fn singleton_distribution() { hist.record(42); assert_eq!(1, hist.unique()); - assert_eq!(1, hist.total()); + assert_eq!(1, hist.count()); let result = hist.quantiles(4).into_iter().cloned().collect_vec(); let expected: Vec = vec![42, 42, 42, 42, 42]; @@ -44,7 +44,7 @@ fn four_value_distribution() { hist.record(2); assert_eq!(4, hist.unique()); - assert_eq!(4, hist.total()); + assert_eq!(4, hist.count()); let result = hist.quantiles(4).into_iter().cloned().collect_vec(); let expected: Vec = vec![1, 1, 2, 3, 4]; diff --git a/tree-sitter-stack-graphs/src/cli/index.rs b/tree-sitter-stack-graphs/src/cli/index.rs index ac445b36f..8faa050d0 100644 --- a/tree-sitter-stack-graphs/src/cli/index.rs +++ b/tree-sitter-stack-graphs/src/cli/index.rs @@ -370,13 +370,14 @@ impl<'a> Indexer<'a> { .total_graph_nodes .record(graph.iter_nodes().count()); let mut total_edges = 0; - for node_edges in graph - .iter_nodes() - .filter(|n| !graph[*n].is_root()) - .map(|n| graph.outgoing_edges(n).count()) - { - self.stats.node_out_degrees.record(node_edges); - total_edges += node_edges; + for n in graph.iter_nodes() { + let edge_count = graph.outgoing_edges(n).count(); + if graph[n].is_root() { + self.stats.root_out_degree = edge_count; + } else { + self.stats.node_out_degrees.record(edge_count); + total_edges += edge_count; + } } self.stats.total_graph_edges.record(total_edges); } @@ -513,6 +514,8 @@ pub struct IndexingStats { pub total_graph_edges: FrequencyDistribution, // The distribution of the out-degrees of non-root nodes. pub node_out_degrees: FrequencyDistribution, + // The root node's out-degree. + pub root_out_degree: usize, // The stitching statistics. pub stitching_stats: StitchingStats, } diff --git a/tree-sitter-stack-graphs/src/cli/util.rs b/tree-sitter-stack-graphs/src/cli/util.rs index fd93046c4..564f13f4d 100644 --- a/tree-sitter-stack-graphs/src/cli/util.rs +++ b/tree-sitter-stack-graphs/src/cli/util.rs @@ -507,21 +507,24 @@ pub(super) fn print_indexing_stats(stats: IndexingStats) { print_quartiles_row("total graph nodes", stats.total_graph_nodes); print_quartiles_row("total graph edges", stats.total_graph_edges); print_quartiles_row("node out degrees", stats.node_out_degrees); + print_value_row("root out degree", stats.root_out_degree); println!(); print_stitching_stats(stats.stitching_stats); } pub(super) fn print_stitching_stats(stats: StitchingStats) { print_quartiles_header("stitching stats"); + print_quartiles_row("initial paths", stats.initial_paths); print_quartiles_row("queued paths per phase", stats.queued_paths_per_phase); print_quartiles_row("processed paths per phase", stats.processed_paths_per_phase); print_quartiles_row("accepted path length", stats.accepted_path_length); - print_quartiles_row("maximal path length", stats.maximal_path_lengh); + print_quartiles_row("non-extensible path length", stats.nonextensible_path_lengh); print_quartiles_row("node path candidates", stats.candidates_per_node_path); print_quartiles_row("node path extensions", stats.extensions_per_node_path); print_quartiles_row("root path candidates", stats.candidates_per_root_path); print_quartiles_row("root path extensions", stats.extensions_per_root_path); print_quartiles_row("node visits", stats.node_visits.frequencies()); + print_value_row("root visits", stats.root_visits); print_quartiles_row( "similar path counts", stats.similar_paths_stats.similar_path_count, @@ -530,33 +533,35 @@ pub(super) fn print_stitching_stats(stats: StitchingStats) { "similar path bucket sizes", stats.similar_paths_stats.similar_path_bucket_size, ); - print_value_row("root visits", stats.root_visits); } pub(super) fn print_database_stats(stats: StorageStats) { - println!(" database stats | loads | cached "); - println!("---------------------------+---------+---------"); println!( - " files | {:>9} | {:>9} ", - stats.file_loads, stats.file_cached + "| {:^29} | {:^9} | {:^9} |", + "database stats", "loads", "cached", + ); + println!("|-------------------------------|-----------|-----------|"); + println!( + "| {:>29} | {:>9} | {:>9} |", + "files", stats.file_loads, stats.file_cached ); println!( - " node paths | {:>9} | {:>9} ", - stats.node_path_loads, stats.node_path_cached + "| {:>29} | {:>9} | {:>9} |", + "node paths", stats.node_path_loads, stats.node_path_cached ); println!( - " root paths | {:>9} | {:>9} ", - stats.root_path_loads, stats.root_path_cached + "| {:>29} | {:>9} | {:>9} |", + "rootpaths", stats.root_path_loads, stats.root_path_cached ); } fn print_quartiles_header(title: &str) { println!( - "| {:^25} | min | p25 | p50 | p75 | max | total |", - title + "| {:^29} | {:^9} | {:^9} | {:^9} | {:^9} | {:^9} | {:^9} |", + title, "min", "p25", "p50", "p75", "max", "count", ); println!( - "|---------------------------|-----------|-----------|-----------|-----------|-----------|-----------|" + "|-------------------------------|-----------|-----------|-----------|-----------|-----------|-----------|" ); } @@ -564,26 +569,26 @@ fn print_quartiles_row(title: &str, hist: Frequenc let qs = hist.quantiles(4); if qs.is_empty() { println!( - "| {:>25} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9} |", + "| {:>29} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9} |", title, "-", "-", "-", "-", "-", 0 ); } else { println!( - "| {:>25} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9} |", + "| {:>29} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9} |", title, qs[0], qs[1], qs[2], qs[3], qs[4], - hist.total(), + hist.count(), ); } } fn print_value_row(title: &str, value: X) { println!( - "| {:>25} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9} |", + "| {:>29} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9} | {:>9} |", title, "-", "-", "-", "-", "-", value ); } From 25139d87306da6229de38e7fefcdd9e69e9847f2 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Sat, 11 Nov 2023 18:58:40 +0100 Subject: [PATCH 283/500] Tweak name --- stack-graphs/src/stitching.rs | 8 ++++---- tree-sitter-stack-graphs/src/cli/util.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index 9a4cca91c..d31caef93 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -1083,7 +1083,7 @@ impl ForwardPartialPathStitcher { if extension_count == 0 { self.stats - .nonextensible_path_lengh + .terminal_path_lengh .record(partial_path.edges.len()); } candidate_count @@ -1299,7 +1299,7 @@ pub struct Stats { /// The distribution of the length of accepted paths pub accepted_path_length: FrequencyDistribution, /// The distribution of the maximal length of paths (when they cannot be extended more) - pub nonextensible_path_lengh: FrequencyDistribution, + pub terminal_path_lengh: FrequencyDistribution, /// The distribution of the number of candidates for paths ending in a regular node pub candidates_per_node_path: FrequencyDistribution, /// The distribution of the number of candidates for paths ending in the root node @@ -1322,7 +1322,7 @@ impl std::ops::AddAssign for Stats { self.queued_paths_per_phase += rhs.queued_paths_per_phase; self.processed_paths_per_phase += rhs.processed_paths_per_phase; self.accepted_path_length += rhs.accepted_path_length; - self.nonextensible_path_lengh += rhs.nonextensible_path_lengh; + self.terminal_path_lengh += rhs.terminal_path_lengh; self.candidates_per_node_path += rhs.candidates_per_node_path; self.candidates_per_root_path += rhs.candidates_per_root_path; self.extensions_per_node_path += rhs.extensions_per_node_path; @@ -1338,7 +1338,7 @@ impl std::ops::AddAssign<&Self> for Stats { self.initial_paths += &rhs.initial_paths; self.processed_paths_per_phase += &rhs.processed_paths_per_phase; self.accepted_path_length += &rhs.accepted_path_length; - self.nonextensible_path_lengh += &rhs.nonextensible_path_lengh; + self.terminal_path_lengh += &rhs.terminal_path_lengh; self.candidates_per_node_path += &rhs.candidates_per_node_path; self.candidates_per_root_path += &rhs.candidates_per_root_path; self.extensions_per_node_path += &rhs.extensions_per_node_path; diff --git a/tree-sitter-stack-graphs/src/cli/util.rs b/tree-sitter-stack-graphs/src/cli/util.rs index 564f13f4d..6b7deab4c 100644 --- a/tree-sitter-stack-graphs/src/cli/util.rs +++ b/tree-sitter-stack-graphs/src/cli/util.rs @@ -518,7 +518,7 @@ pub(super) fn print_stitching_stats(stats: StitchingStats) { print_quartiles_row("queued paths per phase", stats.queued_paths_per_phase); print_quartiles_row("processed paths per phase", stats.processed_paths_per_phase); print_quartiles_row("accepted path length", stats.accepted_path_length); - print_quartiles_row("non-extensible path length", stats.nonextensible_path_lengh); + print_quartiles_row("terminal path length", stats.terminal_path_lengh); print_quartiles_row("node path candidates", stats.candidates_per_node_path); print_quartiles_row("node path extensions", stats.extensions_per_node_path); print_quartiles_row("root path candidates", stats.candidates_per_root_path); From 8fbdfd395ed2b2c2dc2c5fee22a9cd3f1ac1db49 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 13 Nov 2023 16:34:21 +0100 Subject: [PATCH 284/500] Only collect stats when explicitly enabled --- stack-graphs/src/stitching.rs | 88 +++++++++++++++-------- tree-sitter-stack-graphs/src/cli/index.rs | 40 ++++++----- tree-sitter-stack-graphs/src/cli/query.rs | 32 ++++++--- 3 files changed, 103 insertions(+), 57 deletions(-) diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index d31caef93..46881037d 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -829,7 +829,7 @@ pub struct ForwardPartialPathStitcher { queue: VecDeque<(PartialPath, AppendingCycleDetector, bool)>, // tracks the number of initial paths in the queue because we do not want call // extend_until on those - initial_paths: usize, + initial_paths_in_queue: usize, // next_iteration is a tuple of queues instead of an queue of tuples so that the path queue // can be cheaply exposed through the C API as a continuous memory block next_iteration: ( @@ -841,7 +841,8 @@ pub struct ForwardPartialPathStitcher { similar_path_detector: Option>, check_only_join_nodes: bool, max_work_per_phase: usize, - stats: Stats, + initial_paths: usize, + stats: Option, #[cfg(feature = "copious-debugging")] phase_number: usize, } @@ -866,13 +867,12 @@ impl ForwardPartialPathStitcher { (p, c, false) }) .multiunzip(); - let mut stats = Stats::default(); - stats.initial_paths.record(next_iteration.0.len()); + let initial_paths = next_iteration.0.len(); Self { candidates: Vec::new(), extensions: Vec::new(), queue: VecDeque::new(), - initial_paths: next_iteration.0.len(), + initial_paths_in_queue: initial_paths, next_iteration, appended_paths, // By default, all paths are checked for similarity @@ -881,7 +881,8 @@ impl ForwardPartialPathStitcher { check_only_join_nodes: false, // By default, there's no artificial bound on the amount of work done per phase max_work_per_phase: usize::MAX, - stats, + initial_paths, + stats: None, #[cfg(feature = "copious-debugging")] phase_number: 1, } @@ -916,11 +917,24 @@ impl ForwardPartialPathStitcher { self.max_work_per_phase = max_work_per_phase; } + /// Sets whether to collect statistics during stitching. + pub fn set_collect_stats(&mut self, collect_stats: bool) { + if !collect_stats { + self.stats = None; + } else if self.stats.is_none() { + let mut stats = Stats::default(); + stats.initial_paths.record(self.initial_paths); + self.stats = Some(stats); + } + } + pub fn into_stats(mut self) -> Stats { - if let Some(similar_path_detector) = self.similar_path_detector { - self.stats.similar_paths_stats = similar_path_detector.stats(); + if let (Some(stats), Some(similar_path_detector)) = + (&mut self.stats, self.similar_path_detector) + { + stats.similar_paths_stats = similar_path_detector.stats(); } - self.stats + self.stats.unwrap_or_default() } } @@ -1069,22 +1083,21 @@ impl ForwardPartialPathStitcher { self.next_iteration.2.push(new_has_split); } - let (graph, _, _) = candidates.get_graph_partials_and_db(); - let end_node = &graph[partial_path.end_node]; - if end_node.is_root() { - self.stats.candidates_per_root_path.record(candidate_count); - self.stats.extensions_per_root_path.record(extension_count); - self.stats.root_visits += 1; - } else { - self.stats.candidates_per_node_path.record(candidate_count); - self.stats.extensions_per_node_path.record(extension_count); - self.stats.node_visits.record(end_node.id()); - } - - if extension_count == 0 { - self.stats - .terminal_path_lengh - .record(partial_path.edges.len()); + if let Some(stats) = &mut self.stats { + let (graph, _, _) = candidates.get_graph_partials_and_db(); + let end_node = &graph[partial_path.end_node]; + if end_node.is_root() { + stats.candidates_per_root_path.record(candidate_count); + stats.extensions_per_root_path.record(extension_count); + stats.root_visits += 1; + } else { + stats.candidates_per_node_path.record(candidate_count); + stats.extensions_per_node_path.record(extension_count); + stats.node_visits.record(end_node.id()); + } + if extension_count == 0 { + stats.terminal_path_lengh.record(partial_path.edges.len()); + } } candidate_count } @@ -1119,7 +1132,9 @@ impl ForwardPartialPathStitcher { self.next_iteration.1.drain(..), self.next_iteration.2.drain(..), )); - self.stats.queued_paths_per_phase.record(self.queue.len()); + if let Some(stats) = &mut self.stats { + stats.queued_paths_per_phase.record(self.queue.len()); + } let mut work_performed = 0; while let Some((partial_path, cycle_detector, has_split)) = self.queue.pop_front() { let (graph, partials, _) = candidates.get_graph_partials_and_db(); @@ -1127,8 +1142,8 @@ impl ForwardPartialPathStitcher { "--> Candidate partial path {}", partial_path.display(graph, partials) ); - if self.initial_paths > 0 { - self.initial_paths -= 1; + if self.initial_paths_in_queue > 0 { + self.initial_paths_in_queue -= 1; } else if !extend_while(graph, partials, &partial_path) { copious_debugging!( " Do not extend {}", @@ -1141,7 +1156,9 @@ impl ForwardPartialPathStitcher { break; } } - self.stats.processed_paths_per_phase.record(work_performed); + if let Some(stats) = &mut self.stats { + stats.processed_paths_per_phase.record(work_performed); + } #[cfg(feature = "copious-debugging")] { @@ -1354,6 +1371,8 @@ impl std::ops::AddAssign<&Self> for Stats { pub struct StitcherConfig { /// Enables similar path detection during path stitching. detect_similar_paths: bool, + /// Collect statistics about path stitching. + collect_stats: bool, } impl StitcherConfig { @@ -1365,11 +1384,21 @@ impl StitcherConfig { self.detect_similar_paths = detect_similar_paths; self } + + pub fn collect_stats(&self) -> bool { + self.collect_stats + } + + pub fn with_collect_stats(mut self, collect_stats: bool) -> Self { + self.collect_stats = collect_stats; + self + } } impl StitcherConfig { fn apply(&self, stitcher: &mut ForwardPartialPathStitcher) { stitcher.set_similar_path_detection(self.detect_similar_paths); + stitcher.set_collect_stats(self.collect_stats); } } @@ -1377,6 +1406,7 @@ impl Default for StitcherConfig { fn default() -> Self { Self { detect_similar_paths: true, + collect_stats: false, } } } diff --git a/tree-sitter-stack-graphs/src/cli/index.rs b/tree-sitter-stack-graphs/src/cli/index.rs index 8faa050d0..f47e03cf0 100644 --- a/tree-sitter-stack-graphs/src/cli/index.rs +++ b/tree-sitter-stack-graphs/src/cli/index.rs @@ -113,6 +113,7 @@ impl IndexArgs { let mut indexer = Indexer::new(&mut db, &mut loader, &reporter); indexer.force = self.force; indexer.max_file_time = self.max_file_time; + indexer.set_collect_stats(self.stats); let source_paths = self .source_paths @@ -158,7 +159,7 @@ pub struct Indexer<'a> { db: &'a mut SQLiteWriter, loader: &'a mut Loader, reporter: &'a dyn Reporter, - stats: IndexingStats, + stats: Option, /// Index files, even if they already exist in the database. pub force: bool, /// Maximum time per file. @@ -177,7 +178,15 @@ impl<'a> Indexer<'a> { reporter, force: false, max_file_time: None, - stats: IndexingStats::default(), + stats: None, + } + } + + pub fn set_collect_stats(&mut self, collect_stats: bool) { + if !collect_stats { + self.stats = None; + } else if self.stats.is_none() { + self.stats = Some(IndexingStats::default()); } } @@ -294,8 +303,9 @@ impl<'a> Indexer<'a> { } Err(e) => return Err(IndexError::LoadError(e)), }; - let stitcher_config = - StitcherConfig::default().with_detect_similar_paths(!lcs.no_similar_paths_in_file()); + let stitcher_config = StitcherConfig::default() + .with_detect_similar_paths(!lcs.no_similar_paths_in_file()) + .with_collect_stats(self.stats.is_some()); let source = file_reader.get(source_path)?; let tag = sha1(source); @@ -365,21 +375,19 @@ impl<'a> Indexer<'a> { } } }; - { - self.stats - .total_graph_nodes - .record(graph.iter_nodes().count()); + if let Some(stats) = &mut self.stats { + stats.total_graph_nodes.record(graph.iter_nodes().count()); let mut total_edges = 0; for n in graph.iter_nodes() { let edge_count = graph.outgoing_edges(n).count(); if graph[n].is_root() { - self.stats.root_out_degree = edge_count; + stats.root_out_degree = edge_count; } else { - self.stats.node_out_degrees.record(edge_count); + stats.node_out_degrees.record(edge_count); total_edges += edge_count; } } - self.stats.total_graph_edges.record(total_edges); + stats.total_graph_edges.record(total_edges); } let mut partials = PartialPaths::new(); @@ -395,7 +403,9 @@ impl<'a> Indexer<'a> { }, ) { Ok(stitching_stats) => { - self.stats.stitching_stats += stitching_stats; + if let Some(stats) = &mut self.stats { + stats.stitching_stats += stitching_stats; + } } Err(_) => { file_status.warning("path computation timed out", None); @@ -475,12 +485,8 @@ impl<'a> Indexer<'a> { false } - pub fn stats(&self) -> &IndexingStats { - &self.stats - } - pub fn into_stats(self) -> IndexingStats { - self.stats + self.stats.unwrap_or_default() } } diff --git a/tree-sitter-stack-graphs/src/cli/query.rs b/tree-sitter-stack-graphs/src/cli/query.rs index 1c57145fe..dd5526570 100644 --- a/tree-sitter-stack-graphs/src/cli/query.rs +++ b/tree-sitter-stack-graphs/src/cli/query.rs @@ -51,7 +51,7 @@ impl QueryArgs { wait_for_input()?; } let mut db = SQLiteReader::open(&db_path)?; - let stitching_stats = self.target.run(&mut db)?; + let stitching_stats = self.target.run(&mut db, self.stats)?; if self.stats { println!(); print_stitching_stats(stitching_stats); @@ -68,9 +68,10 @@ pub enum Target { } impl Target { - pub fn run(self, db: &mut SQLiteReader) -> anyhow::Result { + fn run(self, db: &mut SQLiteReader, collect_stats: bool) -> anyhow::Result { let reporter = ConsoleReporter::details(); let mut querier = Querier::new(db, &reporter); + querier.set_collect_stats(collect_stats); match self { Self::Definition(cmd) => cmd.run(&mut querier)?, } @@ -152,7 +153,7 @@ impl Definition { pub struct Querier<'a> { db: &'a mut SQLiteReader, reporter: &'a dyn Reporter, - stats: StitchingStats, + stats: Option, } impl<'a> Querier<'a> { @@ -160,7 +161,15 @@ impl<'a> Querier<'a> { Self { db, reporter, - stats: StitchingStats::default(), + stats: None, + } + } + + pub fn set_collect_stats(&mut self, collect_stats: bool) { + if !collect_stats { + self.stats = None; + } else if self.stats.is_none() { + self.stats = Some(StitchingStats::default()); } } @@ -208,7 +217,8 @@ impl<'a> Querier<'a> { let mut reference_paths = Vec::new(); let stitcher_config = StitcherConfig::default() // always detect similar paths, we don't know the language configurations for the data in the database - .with_detect_similar_paths(true); + .with_detect_similar_paths(true) + .with_collect_stats(self.stats.is_some()); let ref_result = ForwardPartialPathStitcher::find_all_complete_partial_paths( self.db, std::iter::once(node), @@ -219,7 +229,11 @@ impl<'a> Querier<'a> { }, ); match ref_result { - Ok(ref_stats) => self.stats += ref_stats, + Ok(ref_stats) => { + if let Some(stats) = &mut self.stats { + *stats += ref_stats + } + } Err(err) => { self.reporter.failed(&log_path, "query timed out", None); return Err(err.into()); @@ -276,12 +290,8 @@ impl<'a> Querier<'a> { Ok(result) } - pub fn stats(&self) -> &StitchingStats { - &self.stats - } - pub fn into_stats(self) -> StitchingStats { - self.stats + self.stats.unwrap_or_default() } } From 04626dc5687bf3639f3c13143e97e708453e8f4b Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 20 Nov 2023 14:16:13 +0100 Subject: [PATCH 285/500] Split similar paths and counts to reduce memory usage when stats are not collected --- stack-graphs/src/cycles.rs | 61 ++++++++++++++++++++++------------- stack-graphs/src/stitching.rs | 9 ++++-- 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/stack-graphs/src/cycles.rs b/stack-graphs/src/cycles.rs index e989dc471..0f00ad16f 100644 --- a/stack-graphs/src/cycles.rs +++ b/stack-graphs/src/cycles.rs @@ -50,12 +50,8 @@ use crate::stitching::ToAppendable; /// Helps detect similar paths in the path-finding algorithm. pub struct SimilarPathDetector

{ - paths: HashMap; 4]>>, -} - -struct SimilarPath

{ - path: P, - count: usize, + paths: HashMap>, + counts: Option>>, } #[doc(hidden)] @@ -98,13 +94,23 @@ where pub fn new() -> SimilarPathDetector

{ SimilarPathDetector { paths: HashMap::new(), + counts: None, + } + } + + /// Set whether to collect statistics for this similar path detector. + pub fn set_collect_stats(&mut self, collect_stats: bool) { + if !collect_stats { + self.counts = None; + } else if self.counts.is_none() { + self.counts = Some(HashMap::new()); } } - /// Determines whether we should process this path during the path-finding algorithm. If we have seen - /// a path with the same start and end node, and the same pre- and postcondition, then we return false. - /// Otherwise, we return true. - pub fn has_similar_path( + /// Add a apth, and determine whether we should process this path during the path-finding algorithm. + /// If we have seen a path with the same start and end node, and the same pre- and postcondition, then + /// we return false. Otherwise, we return true. + pub fn add_path( &mut self, _graph: &StackGraph, arena: &mut P::Arena, @@ -119,22 +125,31 @@ where // Iterate through the bucket to determine if this paths is better than any already known // path. Note that the bucket might be modified during the loop if a path is removed which // is shadowed by the new path! - let possibly_similar_paths = self.paths.entry(key).or_default(); + let possibly_similar_paths = self.paths.entry(key.clone()).or_default(); + let mut possible_similar_counts = self + .counts + .as_mut() + .map(move |cs| cs.entry(key).or_default()); let mut idx = 0; let mut count = 0; while idx < possibly_similar_paths.len() { let other_path = &mut possibly_similar_paths[idx]; - match cmp(arena, path, &other_path.path) { + match cmp(arena, path, other_path) { Some(Ordering::Less) => { // the new path is better, remove the old one - count += other_path.count; possibly_similar_paths.remove(idx); + if let Some(possible_similar_counts) = possible_similar_counts.as_mut() { + count += possible_similar_counts[idx]; + possible_similar_counts.remove(idx); + } // keep `idx` which now points to the next element continue; } Some(_) => { // the new path is equal or worse, and ignored - other_path.count += 1; + if let Some(possible_similar_counts) = possible_similar_counts { + possible_similar_counts[idx] += 1; + } return true; } None => { @@ -144,10 +159,10 @@ where } // this path is either new or better, keep it - possibly_similar_paths.push(SimilarPath { - path: path.clone(), - count, - }); + possibly_similar_paths.push(path.clone()); + if let Some(possible_similar_counts) = possible_similar_counts { + possible_similar_counts.push(count); + } false } @@ -159,10 +174,12 @@ where // Returns the distribution of similar path counts. pub fn stats(&self) -> SimilarPathStats { let mut stats = SimilarPathStats::default(); - for bucket in self.paths.values() { - stats.similar_path_bucket_size.record(bucket.len()); - for path in bucket.iter() { - stats.similar_path_count.record(path.count); + if let Some(counts) = &self.counts { + for bucket in counts.values() { + stats.similar_path_bucket_size.record(bucket.len()); + for count in bucket.iter() { + stats.similar_path_count.record(*count); + } } } stats diff --git a/stack-graphs/src/stitching.rs b/stack-graphs/src/stitching.rs index 46881037d..99aaa8df1 100644 --- a/stack-graphs/src/stitching.rs +++ b/stack-graphs/src/stitching.rs @@ -896,7 +896,9 @@ impl ForwardPartialPathStitcher { if !detect_similar_paths { self.similar_path_detector = None; } else if self.similar_path_detector.is_none() { - self.similar_path_detector = Some(SimilarPathDetector::new()); + let mut similar_path_detector = SimilarPathDetector::new(); + similar_path_detector.set_collect_stats(self.stats.is_some()); + self.similar_path_detector = Some(similar_path_detector); } } @@ -926,6 +928,9 @@ impl ForwardPartialPathStitcher { stats.initial_paths.record(self.initial_paths); self.stats = Some(stats); } + if let Some(similar_path_detector) = &mut self.similar_path_detector { + similar_path_detector.set_collect_stats(collect_stats); + } } pub fn into_stats(mut self) -> Stats { @@ -1050,7 +1055,7 @@ impl ForwardPartialPathStitcher { let (graph, partials, _) = candidates.get_graph_partials_and_db(); if check_similar_path { if let Some(similar_path_detector) = &mut self.similar_path_detector { - if similar_path_detector.has_similar_path( + if similar_path_detector.add_path( graph, partials, &new_partial_path, From 63bf3a5b78645c5454f5f0ecd7a4c355f82b823a Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 21 Nov 2023 15:37:28 +0100 Subject: [PATCH 286/500] Remove unnecessary dependency --- languages/tree-sitter-stack-graphs-java/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-java/Cargo.toml b/languages/tree-sitter-stack-graphs-java/Cargo.toml index 72646a905..8bd3e5f93 100644 --- a/languages/tree-sitter-stack-graphs-java/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-java/Cargo.toml @@ -36,6 +36,5 @@ harness = false # need to provide own main function to handle running tests [dependencies] anyhow = "1.0" clap = { version = "4", features = ["derive"] } -stack-graphs = { version = "0.12", path = "../../stack-graphs" } tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs", features=["cli"] } tree-sitter-java = { version = "=0.20.0" } From 1b01a8c4c2c8a19010370207f3277ed8c469d50d Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 21 Nov 2023 15:46:07 +0100 Subject: [PATCH 287/500] spelling --- stack-graphs/src/cycles.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack-graphs/src/cycles.rs b/stack-graphs/src/cycles.rs index 0f00ad16f..212d14085 100644 --- a/stack-graphs/src/cycles.rs +++ b/stack-graphs/src/cycles.rs @@ -107,7 +107,7 @@ where } } - /// Add a apth, and determine whether we should process this path during the path-finding algorithm. + /// Add a path, and determine whether we should process this path during the path-finding algorithm. /// If we have seen a path with the same start and end node, and the same pre- and postcondition, then /// we return false. Otherwise, we return true. pub fn add_path( From 163ff76c6de412c025c9cc784667cc30419a0c35 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 20 Nov 2023 18:02:12 +0100 Subject: [PATCH 288/500] Support `satisfies` expression --- .../src/stack-graphs.tsg | 16 ++++++++++++++++ .../test/expressions/satisfies-type.ts | 8 ++++++++ 2 files changed, 24 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/expressions/satisfies-type.ts diff --git a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg index 2d05f5891..f96c28122 100644 --- a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg @@ -2649,6 +2649,7 @@ if none @is_async { (object) (parenthesized_expression) (regex) + (satisfies_expression) (sequence_expression) (spread_element) (string) @@ -2961,6 +2962,21 @@ if none @is_def { +;; Satisfies Expressions + +; { foo: 42 } satisfies { foo: number } + +(satisfies_expression (_)@expr . (_)@type)@satisfies { + ; propagate lexical scope + edge @expr.lexical_scope -> @satisfies.lexical_scope + edge @type.lexical_scope -> @satisfies.lexical_scope + + ; type is union of both + edge @satisfies.type -> @expr.type + edge @satisfies.type -> @type.type +} + + ;; Spread Element (spread_element (_)@expr)@spread_elem { diff --git a/languages/tree-sitter-stack-graphs-typescript/test/expressions/satisfies-type.ts b/languages/tree-sitter-stack-graphs-typescript/test/expressions/satisfies-type.ts new file mode 100644 index 000000000..48b3a86f5 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/expressions/satisfies-type.ts @@ -0,0 +1,8 @@ +type Foo = { foo: number }; + +let x = { foo: 42 } satisfies Foo; + + x.foo +// ^ defined: 3, 1 + +export {} From 282d241780873dedbadb346d772edc2ee418e2cb Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 20 Nov 2023 19:01:45 +0100 Subject: [PATCH 289/500] Fix bug in reexport as module --- .../src/stack-graphs.tsg | 8 ++++---- .../test/modules/reexport-as-object.ts | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/modules/reexport-as-object.ts diff --git a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg index f96c28122..af6b80071 100644 --- a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg @@ -923,8 +923,8 @@ if none @is_default { ; ) (export_statement - (namespace_export (identifier)) - source:(_)@name + (namespace_export (identifier)@name) + source:(_)@from )@export_stmt { ; namespace definitions are specified together with (module) and (internal_module) @@ -933,8 +933,8 @@ if none @is_default { edge @export_stmt.exports -> @name.type_def__ns ; connect definitions to exports - edge @export_stmt.expr_member__ns -> @name.mod_ref - edge @export_stmt.type_member__ns -> @name.mod_ref + edge @export_stmt.expr_member__ns -> @from.mod_ref + edge @export_stmt.type_member__ns -> @from.mod_ref } ; export as namespace NAME diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/reexport-as-object.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/reexport-as-object.ts new file mode 100644 index 000000000..54e5494b9 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/reexport-as-object.ts @@ -0,0 +1,15 @@ +/* --- path: foo.ts --- */ + +export const FOO = 42; + +/* --- path: bar.ts --- */ + +export * as quz from "./foo"; + +/* --- path: test.ts --- */ + +import { quz } from "./bar"; + + quz.FOO +// ^ defined: 11, 7 +// ^ defined: 3 From 9323b4c9325f57999a36314e87bad47a00b48c0c Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 22 Nov 2023 11:35:29 +0100 Subject: [PATCH 290/500] Eliminate nested identifier unrolling --- .../src/stack-graphs.tsg | 358 +++++++++--------- .../test/modules/very-deep-namespace.ts | 6 + 2 files changed, 175 insertions(+), 189 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/modules/very-deep-namespace.ts diff --git a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg index af6b80071..965047812 100644 --- a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg @@ -928,13 +928,33 @@ if none @is_default { )@export_stmt { ; namespace definitions are specified together with (module) and (internal_module) - ; export definitions - edge @export_stmt.exports -> @name.expr_def__ns - edge @export_stmt.exports -> @name.type_def__ns + ; export expression definition + node expr_ns_pop + attr (expr_ns_pop) pop_symbol = "%E" + ; + edge @export_stmt.exports -> expr_ns_pop + edge expr_ns_pop -> @name.expr_def + + ; export type definition + node type_ns_pop + attr (type_ns_pop) pop_symbol = "%T" + ; + edge @export_stmt.exports -> type_ns_pop + edge type_ns_pop -> @name.type_def - ; connect definitions to exports - edge @export_stmt.expr_member__ns -> @from.mod_ref - edge @export_stmt.type_member__ns -> @from.mod_ref + ; connect expression definition to exports + node expr_ns_push + attr (expr_ns_push) push_symbol = "%E" + ; + edge @name.expr_def_member -> expr_ns_push + edge expr_ns_push -> @from.mod_ref + + ; connect type definition to exports + node type_ns_push + attr (type_ns_push) push_symbol = "%T" + ; + edge @name.type_def_member -> type_ns_push + edge type_ns_push -> @from.mod_ref } ; export as namespace NAME @@ -947,16 +967,36 @@ if none @is_default { (program (export_statement "as" "namespace" . (_)@name -)@export_stmt)@prog { +))@prog { ; namespace definitions are specified together with (module) and (internal_module) - ; make definitions global - edge @prog.globals -> @name.expr_def__ns - edge @prog.globals -> @name.type_def__ns + ; make expression definition global + node expr_ns_pop + attr (expr_ns_pop) pop_symbol = "%E" + ; + edge @prog.globals -> expr_ns_pop + edge expr_ns_pop -> @name.expr_def - ; connect definitions to exports - edge @export_stmt.expr_member__ns -> @prog.exports - edge @export_stmt.type_member__ns -> @prog.exports + ; make type definition global + node type_ns_pop + attr (type_ns_pop) pop_symbol = "%T" + ; + edge @prog.globals -> type_ns_pop + edge type_ns_pop -> @name.type_def + + ; connect expression definition to exports + node expr_ns_push + attr (expr_ns_push) push_symbol = "%E" + ; + edge @name.expr_def_member -> expr_ns_push + edge expr_ns_push -> @prog.exports + + ; connect type definition to exports + node type_ns_push + attr (type_ns_push) push_symbol = "%T" + ; + edge @name.type_def_member -> type_ns_push + edge type_ns_push -> @prog.exports } ;; Imports @@ -1085,14 +1125,38 @@ if none @is_type { (import_statement "type"? - (import_clause (namespace_import (identifier))) + (import_clause (namespace_import (identifier)@name)) source:(_)@from )@import_stmt { ; namespace definitions are specified together with (module) and (internal_module) - ; connect definitions to import - edge @import_stmt.expr_member__ns -> @from.mod_ref - edge @import_stmt.type_member__ns -> @from.mod_ref + ; expose expression definition + node expr_ns_pop + attr (expr_ns_pop) pop_symbol = "%E" + ; + edge @import_stmt.lexical_defs -> expr_ns_pop + edge expr_ns_pop -> @name.expr_def + + ; expose type definition + node type_ns_pop + attr (type_ns_pop) pop_symbol = "%T" + ; + edge @import_stmt.lexical_defs -> type_ns_pop + edge type_ns_pop -> @name.type_def + + ; connect expression definition to import + node expr_ns_push + attr (expr_ns_push) push_symbol = "%E" + ; + edge @name.expr_def_member -> expr_ns_push + edge expr_ns_push -> @from.mod_ref + + ; connect type definition to import + node type_ns_push + attr (type_ns_push) push_symbol = "%T" + ; + edge @name.type_def_member -> type_ns_push + edge type_ns_push -> @from.mod_ref } ;; Import Alias @@ -2262,147 +2326,89 @@ if none @is_async { [ ; X - (module name:(identifier)@name @mod) - (internal_module name:(identifier)@name @mod) - (export_statement "as" "namespace" . (identifier)@name) @mod - (export_statement (namespace_export (identifier)@name))@mod - (import_statement (import_clause (namespace_import (identifier)@name)))@mod - (ambient_declaration (module name:(string)@name @mod)) + (module name:(identifier)@name) + (internal_module name:(identifier)@name) + (export_statement "as" "namespace" . (identifier)@name) + (export_statement (namespace_export (identifier)@name)) + (import_statement (import_clause (namespace_import (identifier)@name))) + (ambient_declaration (module name:(string) @name)) ; X._ - (module name:(nested_identifier . (identifier)@name @mod)) - (internal_module name:(nested_identifier . (identifier)@name @mod)) - ; X._._ - (module name:(nested_identifier . (nested_identifier . (identifier)@name @mod))) - (internal_module name:(nested_identifier . (nested_identifier . (identifier)@name @mod))) - ; X._._._ - (module name:(nested_identifier . (nested_identifier . (nested_identifier . (identifier)@name @mod)))) - (internal_module name:(nested_identifier . (nested_identifier . (nested_identifier . (identifier)@name @mod)))) - ; X._._._._ - (module name:(nested_identifier . (nested_identifier . (nested_identifier . (nested_identifier . (identifier)@name @mod))))) - (internal_module name:(nested_identifier . (nested_identifier . (nested_identifier . (nested_identifier . (identifier)@name @mod))))) -]@mod_decl { + (nested_identifier (identifier)@name) +] { node @name.expr_def - node @name.expr_def__ns - node @name.expr_def__typeof - node @mod.expr_member - node @mod.expr_member__ns + node expr_def_typeof + node @name.expr_def_member node @name.type_def - node @name.type_def__ns - node @mod.type_member - node @mod.type_member__ns - - ; expose expression definition - edge @mod_decl.lexical_defs -> @name.expr_def__ns + node @name.type_def_member ; expression definition - attr (@name.expr_def__ns) pop_symbol = "%E" - edge @name.expr_def__ns -> @name.expr_def - ; attr (@name.expr_def) node_definition = @name, syntax_type = "module" - - ; namespaces mimic objects with members to access exported expressions - edge @name.expr_def -> @name.expr_def__typeof + attr (expr_def_typeof) pop_symbol = ":" + attr (@name.expr_def_member) pop_symbol = "." ; - attr (@name.expr_def__typeof) pop_symbol = ":" - edge @name.expr_def__typeof -> @mod.expr_member - ; - attr (@mod.expr_member) pop_symbol = "." - edge @mod.expr_member -> @mod.expr_member__ns - ; - attr (@mod.expr_member__ns) push_symbol = "%E" - - ; expose type definition - edge @mod_decl.lexical_defs -> @name.type_def__ns + edge @name.expr_def -> expr_def_typeof + edge expr_def_typeof -> @name.expr_def_member ; type definition - attr (@name.type_def__ns) pop_symbol = "%T" - edge @name.type_def__ns -> @name.type_def - ; attr (@name.type_def) node_definition = @name, syntax_type = "module" - - ; namespaces mimic types with member types to access exported expressions - edge @name.type_def -> @mod.type_member - ; - attr (@mod.type_member) pop_symbol = "." - edge @mod.type_member -> @mod.type_member__ns + attr (@name.type_def_member) pop_symbol = "." ; - attr (@mod.type_member__ns) push_symbol = "%T" + edge @name.type_def -> @name.type_def_member } -[ - ; _.X - (module name:(nested_identifier . (_)@basemod . (identifier)@name)@mod) - (internal_module name:(nested_identifier . (_)@basemod . (identifier)@name)@mod) - ; _._.X - (module name:(nested_identifier . (nested_identifier . (_)@basemod . (identifier)@name)@mod)) - (internal_module name:(nested_identifier . (nested_identifier . (_)@basemod . (identifier)@name)@mod)) - ; _._._.X - (module name:(nested_identifier . (nested_identifier . (nested_identifier . (_)@basemod . (identifier)@name)@mod))) - (internal_module name:(nested_identifier . (nested_identifier . (nested_identifier . (_)@basemod . (identifier)@name)@mod))) - ; _._._._.X - (module name:(nested_identifier . (nested_identifier . (nested_identifier . (nested_identifier . (_)@basemod . (identifier)@name)@mod)))) - (internal_module name:(nested_identifier . (nested_identifier . (nested_identifier . (nested_identifier . (_)@basemod . (identifier)@name)@mod)))) -] { - node @name.expr_def - node @name.expr_def__ns - node @name.expr_def__typeof - node @mod.expr_member - node @mod.expr_member__ns - node @name.type_def - node @name.type_def__ns - node @mod.type_member - node @mod.type_member__ns - - ; expose expression definition - edge @basemod.expr_member__ns -> @name.expr_def__ns - - ; expression definition - attr (@name.expr_def__ns) pop_symbol = "%E" - edge @name.expr_def__ns -> @name.expr_def - ; - attr (@name.expr_def) node_definition = @name, syntax_type = "module" +(nested_identifier . (_) @mod) @nested { + node @nested.expr_def + node @nested.type_def - ; namespaces mimic objects with members to access exported expressions - edge @name.expr_def -> @name.expr_def__typeof - ; - attr (@name.expr_def__typeof) pop_symbol = ":" - edge @name.expr_def__typeof -> @mod.expr_member - ; - attr (@mod.expr_member) pop_symbol = "." - edge @mod.expr_member -> @mod.expr_member__ns - ; - attr (@mod.expr_member__ns) push_symbol = "%E" + edge @nested.expr_def -> @mod.expr_def + edge @nested.type_def -> @mod.type_def +} - ; expose type definition - edge @basemod.type_member__ns -> @name.type_def__ns +(nested_identifier . (_) @mod . (_) @name .) { + edge @mod.expr_def_member -> @name.expr_def + edge @mod.type_def_member -> @name.type_def +} - ; type definition - attr (@name.type_def__ns) pop_symbol = "%T" - edge @name.type_def__ns -> @name.type_def - ; - attr (@name.type_def) node_definition = @name, syntax_type = "module" +(nested_identifier (_) @name .) @nested { + node @nested.expr_def_member + node @nested.type_def_member - ; namespaces mimic types with member types to access exported expressions - edge @name.type_def -> @mod.type_member - ; - attr (@mod.type_member) pop_symbol = "." - edge @mod.type_member -> @mod.type_member__ns - ; - attr (@mod.type_member__ns) push_symbol = "%T" + edge @name.expr_def_member -> @nested.expr_def_member + edge @name.type_def_member -> @nested.type_def_member } [ - (module name:(_)@mod body:(_)@body) - (internal_module name:(_)@mod body:(_)@body) + (module name:(_)@mod body:(_)@body) + (internal_module name:(_)@mod body:(_)@body) ]@mod_decl { ; propagate lexical scope edge @body.lexical_scope -> @mod_decl.lexical_scope - ; connect object to exports - edge @mod.expr_member__ns -> @body.exports + ; expose expression definition + node expr_ns_pop + attr (expr_ns_pop) pop_symbol = "%E" + ; + edge @mod_decl.lexical_defs -> expr_ns_pop + edge expr_ns_pop -> @mod.expr_def + + ; expose type definition + node type_ns_pop + attr (type_ns_pop) pop_symbol = "%T" + ; + edge @mod_decl.lexical_defs -> type_ns_pop + edge type_ns_pop -> @mod.type_def + + ; connect expression definition to exports + node expr_ns_push + attr (expr_ns_push) push_symbol = "%E" + edge @mod.expr_def_member -> expr_ns_push + edge expr_ns_push -> @body.exports - ; connect type to exports - edge @mod.type_member__ns -> @body.exports + ; connect type definition to exports + node type_ns_push + attr (type_ns_push) push_symbol = "%T" + edge @mod.type_def_member -> type_ns_push + edge type_ns_push -> @body.exports } ; NOTE internal_module is also an expression in the grammar, not only a statement. @@ -5541,70 +5547,44 @@ if none @is_acc { [ ; X - (nested_type_identifier module:(identifier)@name @mod) - ; X._ - (nested_type_identifier module:(nested_identifier . (identifier)@name @mod)) - ; X._._ - (nested_type_identifier module:(nested_identifier . (nested_identifier . (identifier)@name @mod))) - ; X._._._ - (nested_type_identifier module:(nested_identifier . (nested_identifier . (nested_identifier . (identifier)@name @mod)))) - ; X._._._._ - (nested_type_identifier module:(nested_identifier . (nested_identifier . (nested_identifier . (nested_identifier . (identifier)@name @mod))))) -]@nested_type_id { + (nested_type_identifier module:(identifier)@name) + ; X._, _.X._ + (nested_identifier (identifier)@name) +] { node @name.type_ref - node @name.type_ref__ns - node @mod.type - - ; type reference to namespace name - edge @mod.type -> @name.type_ref - ; attr (@name.type_ref) node_reference = @name - edge @name.type_ref -> @name.type_ref__ns - ; - attr (@name.type_ref__ns) push_symbol = "%T" - edge @name.type_ref__ns -> @nested_type_id.lexical_scope + + node @name.type_ref_member + attr (@name.type_ref_member) push_symbol = "." + + edge @name.type_ref_member -> @name.type_ref } -[ - ; _.X - (nested_type_identifier module:(nested_identifier . (_)@basemod . (identifier)@name .)@mod) - ; _._.X - (nested_type_identifier module:(nested_identifier . (nested_identifier . (_)@basemod . (identifier)@name .)@mod)) - ; _._._.X - (nested_type_identifier module:(nested_identifier . (nested_identifier . (nested_identifier . (_)@basemod . (identifier)@name .)@mod))) - ; _._._._.X - (nested_type_identifier module:(nested_identifier . (nested_identifier . (nested_identifier . (nested_identifier . (_)@basemod . (identifier)@name .)@mod)))) -] { - node @name.type_ref - node @name.type_ref__ns - node @mod.member - node @mod.type +(nested_identifier . (_)@mod) @nested { + node @nested.type_ref + edge @mod.type_ref -> @nested.type_ref +} - ; type reference to namespace name - edge @mod.type -> @name.type_ref - ; - attr (@name.type_ref) node_reference = @name - edge @name.type_ref -> @mod.member - ; - attr (@mod.member) push_symbol = "." - edge @mod.member -> @basemod.type +(nested_identifier . (_)@mod . (_)@name .) { + edge @name.type_ref -> @mod.type_ref_member } -(nested_type_identifier - module:(_)@mod - name:(_)@name -)@nested_type_id { - node @name.nested_type_ref ; FIXME non-standard name because the general (type_identifier) rule is also applied to @name - node @nested_type_id.member +(nested_identifier (_)@name .) @nested { + node @nested.type_ref_member + edge @nested.type_ref_member -> @name.type_ref_member +} - ; type reference into namespace type - edge @nested_type_id.type -> @name.nested_type_ref - ; - attr (@name.nested_type_ref) node_reference = @name - edge @name.nested_type_ref -> @nested_type_id.member - ; - attr (@nested_type_id.member) push_symbol = "." - edge @nested_type_id.member -> @mod.type +(nested_type_identifier module:(_)@mod)@nested_type_id { + node type_ns + attr (type_ns) push_symbol = "%T" + + edge @mod.type_ref -> type_ns + edge type_ns -> @nested_type_id.lexical_scope +} + +(nested_type_identifier module:(_)@mod name:(_)@name)@nested_type_id { + edge @nested_type_id.type -> @name.type_ref + edge @name.type_ref -> @mod.type_ref_member } diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/very-deep-namespace.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/very-deep-namespace.ts new file mode 100644 index 000000000..71af87eee --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/very-deep-namespace.ts @@ -0,0 +1,6 @@ +namespace a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y { + export const Z = 42; +} + +a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.Z +// ^ defined: 2 From 1af38d2cf7a3c13f75154557948afd01138fbd5a Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 22 Nov 2023 17:33:40 +0100 Subject: [PATCH 291/500] Fix missing scoped variable on undefined as pattern --- .../tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg | 1 + .../test/expressions/undefined-pattern.ts | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/expressions/undefined-pattern.ts diff --git a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg index 965047812..01808435e 100644 --- a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg @@ -4118,6 +4118,7 @@ if none @is_async { (this) (member_expression) (subscript_expression) + (undefined) ]@pat { node @pat.defs } diff --git a/languages/tree-sitter-stack-graphs-typescript/test/expressions/undefined-pattern.ts b/languages/tree-sitter-stack-graphs-typescript/test/expressions/undefined-pattern.ts new file mode 100644 index 000000000..652adf3c6 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/expressions/undefined-pattern.ts @@ -0,0 +1,5 @@ +interface Foo { + bar(undefined?: any): any; +} + +export {} \ No newline at end of file From c17bcd26bfd14127d231bc776fe488e9ddb60aa9 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 22 Nov 2023 17:47:24 +0100 Subject: [PATCH 292/500] Fix rest array pattern crash --- .../src/stack-graphs.tsg | 4 ++-- .../test/expressions/rest-array-attern.ts | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/expressions/rest-array-attern.ts diff --git a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg index 01808435e..f08f962b6 100644 --- a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg @@ -4127,7 +4127,7 @@ if none @is_async { (for_in_statement ["var" "let" "const"] left:(identifier)@name) (variable_declarator name:(identifier)@name) (pattern/identifier)@name - (rest_pattern (_)@name) + (rest_pattern (identifier)@name) ] { node @name.cotype node @name.lexical_scope @@ -4137,7 +4137,7 @@ if none @is_async { (for_in_statement ["var" "let" "const"] left:(identifier)@name) (variable_declarator name:(identifier)@name) (pattern/identifier)@name - (rest_pattern (_)@name) + (rest_pattern (identifier)@name) ] { node @name.defs node @name.expr_def diff --git a/languages/tree-sitter-stack-graphs-typescript/test/expressions/rest-array-attern.ts b/languages/tree-sitter-stack-graphs-typescript/test/expressions/rest-array-attern.ts new file mode 100644 index 000000000..7bc38c4a0 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/expressions/rest-array-attern.ts @@ -0,0 +1,6 @@ +function foo(...[bar]) { + bar; +// ^ defined: 1 +} + +export {} \ No newline at end of file From 2cabfdfa6b5d4425e4e9ec75622a385e8dbeb78d Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 22 Nov 2023 18:05:07 +0100 Subject: [PATCH 293/500] Add support for class static blocks --- .../src/stack-graphs.tsg | 9 +++++++++ .../test/statements/class-static-block.ts | 12 ++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/statements/class-static-block.ts diff --git a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg index f08f962b6..66c432b46 100644 --- a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg @@ -4348,6 +4348,7 @@ if none @is_async { [ (abstract_method_signature) (call_signature) + (class_static_block) (construct_signature) (decorator) ; not strictly a member, but appears in same positions (index_signature) @@ -4371,6 +4372,14 @@ if none @is_async { +;; Static Block + +(class_static_block body:(_)@body)@static { + edge @body.lexical_scope -> @static.lexical_scope +} + + + ;; Construct Signature ; (construct_signature diff --git a/languages/tree-sitter-stack-graphs-typescript/test/statements/class-static-block.ts b/languages/tree-sitter-stack-graphs-typescript/test/statements/class-static-block.ts new file mode 100644 index 000000000..6ccdadea4 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/statements/class-static-block.ts @@ -0,0 +1,12 @@ +let bar = 42; + +class Foo { + static foo: number; + static { + this.foo = bar; + // ^ defined: 4 + // ^ defined: 1 + } +} + +export {} From 90f9a2117704a4110661e02e4697d9c052c04d5a Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 4 Dec 2023 17:39:18 +0100 Subject: [PATCH 294/500] Stop using LFS for our small archives --- .gitattributes | 3 --- data/typescript_benchmark.zip | Bin 131 -> 238818 bytes data/typescript_minimal_project.zip | Bin 129 -> 1117 bytes 3 files changed, 3 deletions(-) delete mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 041b0e4e4..000000000 --- a/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -data/*.tar.gz filter=lfs diff=lfs merge=lfs -text -data/*.tgz filter=lfs diff=lfs merge=lfs -text -data/*.zip filter=lfs diff=lfs merge=lfs -text diff --git a/data/typescript_benchmark.zip b/data/typescript_benchmark.zip index 97f24b96d1dfd9129e30226959a982299ebdc79c..9cf6105adccd4d0458c3872674ebddd7c802e836 100644 GIT binary patch literal 238818 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

RHYU?aJ{J1FA;>A2sm8&E! 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 literal 131 zcmWN?%MrpL5CG6SRnUL|mfw~vm6}|l9~#2R zz%2IVa0&>QR&X;gvV3J^U|xu$LA){FH#AAgqqx(1OI|?8Nj`y{zK= zJg^1rFAt}HFq#F`Tna#-l$V&Bs$`|01a+G()NM*!wOj}%2u%7DW|aEqx+u_k5LUwP zgwm4C9KDiau8!`8p*;ZKtHo>Sa_EiXc-7= z;J2`(I5|HrEi)bA>29F4AdK#5h_65a%)!73^i}DD{q6cdo*57;2p2AEh$o6;w{e~yh(2@<%HY`a7;wxM!2HCcC_-#X^ dAD~5`^n>9oRyJU`Ft7q4FB1cU6%aEp003RaIAZ_+ literal 129 zcmWN?K@!3s3;@7;U(pX(2v9QiHwj5BGb$aSJ@|Uv%U=5FwY}$kjH7SPJ?gkUtuO!g zlb6z7t{+<51yids_npF;x2$muQoy4oA`?r1CZRAhh!1F9A`2x}PN;W6D-^P2!W5GS Mn|l4~3;;O&00FBgkN^Mx From 364395d1e57db42d95b43bef64b6258f43278704 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Mon, 18 Dec 2023 12:08:48 -0800 Subject: [PATCH 295/500] Fix guard typo Co-Authored-By: Rob Rix --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 4e82e857d..3923aafe7 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4476,7 +4476,7 @@ inherit .return_or_yield edge pop_default_guard -> @right.value ;; For ES6 interoperability, expose members as named exports - attr (pop_dot) pop_symbol = "GAURD:MEMBER" + attr (pop_dot) pop_symbol = "GUARD:MEMBER" edge @assignment_expr.exports -> pop_dot edge pop_dot -> @right.value From e76fbe40f4c6e4f8c413df2fe919d4f19a7122dc Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Mon, 18 Dec 2023 12:08:58 -0800 Subject: [PATCH 296/500] Remove extraneous edge Co-Authored-By: Rob Rix --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 3 --- 1 file changed, 3 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 3923aafe7..d7faf39f2 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3184,9 +3184,6 @@ inherit .return_or_yield edge @new_expr.value -> new_expr_guard_this edge new_expr_guard_this -> new_expr_call - ; value coming from the field decls in the class - edge @new_expr.value -> @constructor.value - ; value also coming from the prototype node guard_prototype attr (guard_prototype) push_symbol = "GUARD:PROTOTYPE" From f011526f86d687e1a8725cdddc23360fdb93dab3 Mon Sep 17 00:00:00 2001 From: Jason Lefever Date: Mon, 8 Jan 2024 17:13:45 -0500 Subject: [PATCH 297/500] Replace "stank graph" with "stack graph" --- tree-sitter-stack-graphs/src/cli/index.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tree-sitter-stack-graphs/src/cli/index.rs b/tree-sitter-stack-graphs/src/cli/index.rs index f47e03cf0..6d192e382 100644 --- a/tree-sitter-stack-graphs/src/cli/index.rs +++ b/tree-sitter-stack-graphs/src/cli/index.rs @@ -498,7 +498,7 @@ pub enum IndexError { LoadError(#[source] crate::loader::LoadError<'static>), #[error("failed to read file")] ReadError(#[from] std::io::Error), - #[error("failed to build stank graph")] + #[error("failed to build stack graph")] StackGraph, #[error(transparent)] StorageError(#[from] stack_graphs::storage::StorageError), From be380496728a91744ab449682af6d7bac6efdc6a Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 11 Jan 2024 13:57:32 -0800 Subject: [PATCH 298/500] Update README to include some usage guidance --- .github/workflows/ci.yml | 39 +++-- CONTRIBUTING.md | 5 +- .../tree-sitter-stack-graphs-java/README.md | 134 ++++++++++++++++-- .../README.md | 102 +++++++++---- .../README.md | 116 +++++++++------ script/ci-test-init | 18 +++ tree-sitter-stack-graphs/README.md | 105 +++++++++----- tree-sitter-stack-graphs/examples/README.md | 8 +- tree-sitter-stack-graphs/src/cli/init.rs | 126 ++++++++++------ 9 files changed, 465 insertions(+), 188 deletions(-) create mode 100755 script/ci-test-init diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c561bd429..cad93d701 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,21 +58,32 @@ jobs: run: cargo test --all-features - name: Run test suite with all optimizations run: cargo test --release - # Do the new project test last, because it adds the crate in the current source - # folder, and that shouldn't influence other tests. + + test-init: + needs: [test-rust] + runs-on: ubuntu-latest + strategy: + matrix: + rust: [stable] + + steps: + - name: Install Rust environment + uses: hecrj/setup-rust-action@v1 + with: + rust-version: ${{ matrix.rust }} + - name: Checkout code + uses: actions/checkout@v3 + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: | + ~/.cargo + target + key: ${{ runner.OS }}-cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.OS }}-cargo- - name: Generate, build, and run new language project - run: | - cargo run --bin tree-sitter-stack-graphs --features cli -- init \ - --language-name InitTest \ - --language-id init_test \ - --language-file-extension it \ - --grammar-crate-name tree-sitter-python \ - --grammar-crate-version 0.20.0 \ - --internal \ - --non-interactive - cargo check -p tree-sitter-stack-graphs-init_test --all-features - cargo test -p tree-sitter-stack-graphs-init_test - cargo run -p tree-sitter-stack-graphs-init_test --features cli -- help + run: script/ci-test-init list-languages: runs-on: ubuntu-latest diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1992fceca..3827e3473 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,8 +32,8 @@ Here are a few things you can do that will increase the likelihood of your pull If you are one of the maintainers of this package, bump the version numbers in [`Cargo.toml`](Cargo.toml) and [`README.md`](README.md), then follow the typical instructions to publish a new version to [crates.io][]: ``` -$ cargo package -$ cargo publish +cargo package +cargo publish ``` [crates.io]: https://crates.io/stack-graphs/ @@ -43,4 +43,3 @@ $ cargo publish - [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/) - [Using Pull Requests](https://help.github.com/articles/about-pull-requests/) - [GitHub Help](https://help.github.com) - diff --git a/languages/tree-sitter-stack-graphs-java/README.md b/languages/tree-sitter-stack-graphs-java/README.md index 821796b67..40c0f847f 100644 --- a/languages/tree-sitter-stack-graphs-java/README.md +++ b/languages/tree-sitter-stack-graphs-java/README.md @@ -1,30 +1,138 @@ # tree-sitter-stack-graphs definition for Java -This project defines tree-sitter-stack-graphs rules for Java using the [tree-sitter-java](https://www.npmjs.com/package/tree-sitter-java) grammar. +This project defines tree-sitter-stack-graphs rules for Java using the [tree-sitter-java][] grammar. -## Local Development +[tree-sitter-java]: https://crates.io/crates/tree-sitter-java + +- [API documentation](https://docs.rs/tree-sitter-stack-graphs-java/) +- [Release notes](https://github.com/github/stack-graphs/blob/main/languages/tree-sitter-stack-graphs-java/CHANGELOG.md) + +## Using the API + +To use this library, add the following to your `Cargo.toml`: + +```toml +[dependencies] +tree-sitter-stack-graphs-java = "0.2.0" +``` + +Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-java/*/) for more details on how to use this library. + +## Using the Command-line Program + +The command-line program for `tree-sitter-stack-graphs-java` lets you do stack graph based analysis and lookup from the command line. + +The CLI can be run as follows: + +1. _(Installed)_ Install the CLI using Cargo as follows: + + ```sh + cargo install --features cli tree-sitter-stack-graphs-java + ``` + + After this, the CLI should be available as `tree-sitter-stack-graphs-java`. + +2. _(From source)_ Instead of installing the CLI, it can also be run directly from the crate directory, as a replacement for a `tree-sitter-stack-graphs-java` invocation, as follows: + + ```sh + cargo run --features cli -- + ``` + +The basic CLI workflow for the command-line program is to index source code and issue queries against the resulting database: + +1. Index a source folder as follows: + + ```sh + tree-sitter-stack-graphs-java index SOURCE_DIR + ``` + + _Indexing will skip any files that have already be indexed. To force a re-index, add the `-f` flag._ + + To check the status if a source folder, run: + + ```sh + tree-sitter-stack-graphs-java status SOURCE_DIR + ``` + + To clean the database and start with a clean slate, run: + + ```sh + tree-sitter-stack-graphs-java clean + ``` + + _Pass the `--delete` flag to not just empty the database, but also delete it. This is useful to resolve `unsupported database version` errors that may occur after a version update._ + +2. Run a query to find the definition(s) for a reference on a given line and column, run: + + ```sh + tree-sitter-stack-graphs-java query definition SOURCE_PATH:LINE:COLUMN + ``` + + Resulting definitions are printed, including a source line if the source file is available. + +Discover all available commands and flags by passing the `-h` flag to the CLI directly, or to any of the subcommands. + +## Development + +The project is written in Rust, and requires a recent version installed. Rust can be installed and updated using [rustup][]. + +[rustup]: https://rustup.rs/ The project is organized as follows: - The stack graph rules are defined in `src/stack-graphs.tsg`. +- Builtins sources and configuration are defined in `src/builtins.it` and `builtins.cfg` respectively. - Tests are put into the `test` directory. -The following commands are intended to be run from the repo root. +### Running Tests + +Run the tests as follows: + +```sh +cargo test +``` + +The project consists of a library and a CLI. By default, running `cargo` only applies to the library. To run `cargo` commands on the CLI as well, add `--features cli` or `--all-features`. + +Run the CLI from source as follows: + +```sh +cargo run --features cli -- ARGS +``` + +Sources are formatted using the standard Rust formatted, which is applied by running: + +```sh +cargo fmt +``` + +### Writing TSG + +The stack graph rules are written in [tree-sitter-graph][]. Checkout the [examples][], +which contain self-contained TSG rules for specific language features. A VSCode +[extension][] is available that provides syntax highlighting for TSG files. -Run all tests in the project by executing the following: +[tree-sitter-graph]: https://github.com/tree-sitter/tree-sitter-graph +[examples]: https://github.com/github/stack-graphs/blob/main/tree-sitter-stack-graphs/examples/ +[extension]: https://marketplace.visualstudio.com/items?itemName=tree-sitter.tree-sitter-graph - cargo test -p tree-sitter-stack-graphs-java +Parse and test a single file by executing the following commands: -Parse a single test file: - `cargo run -p tree-sitter-stack-graphs-java -- parse OPTIONS FILENAME` +```sh +cargo run --features cli -- parse FILES... +cargo run --features cli -- test TESTFILES... +``` -Test a single file: - `cargo run -p tree-sitter-stack-graphs-java -- test OPTIONS FILENAME` +Generate a visualization to debug failing tests by passing the `-V` flag: -For debugging purposes, it is useful to run the visualization tool to generate graphs for the tests being run. +```sh +cargo run --features cli -- test -V TESTFILES... +``` -To run a test and generate the visualization: +To generate the visualization regardless of test outcome, execute: -`cargo run -p tree-sitter-stack-graphs-java -- test --output-mode=always -V=%r/%d/%n.html FILENAME` +```sh +cargo run --features cli -- test -V --output-mode=always TESTFILES... +``` -Go to https://crates.io/crates/tree-sitter-stack-graphs for links to examples and documentation. +Go to for links to examples and documentation. diff --git a/languages/tree-sitter-stack-graphs-javascript/README.md b/languages/tree-sitter-stack-graphs-javascript/README.md index 3b53f03de..6d449be9c 100644 --- a/languages/tree-sitter-stack-graphs-javascript/README.md +++ b/languages/tree-sitter-stack-graphs-javascript/README.md @@ -4,27 +4,73 @@ This project defines tree-sitter-stack-graphs rules for JavaScript using the [tr [tree-sitter-javascript]: https://crates.io/crates/tree-sitter-javascript -## Usage +- [API documentation](https://docs.rs/tree-sitter-stack-graphs-javascript/) +- [Release notes](https://github.com/github/stack-graphs/blob/main/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md) + +## Using the API To use this library, add the following to your `Cargo.toml`: -``` toml +```toml [dependencies] -tree-sitter-stack-graphs-javascript = "0.0.1" +tree-sitter-stack-graphs-javascript = "0.1.0" ``` Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-javascript/*/) for more details on how to use this library. -## Command-line Program +## Using the Command-line Program The command-line program for `tree-sitter-stack-graphs-javascript` lets you do stack graph based analysis and lookup from the command line. -Install the program using `cargo install` as follows: +The CLI can be run as follows: -``` sh -$ cargo install --features cli tree-sitter-stack-graphs-javascript -$ tree-sitter-stack-graphs-javascript --help -``` +1. _(Installed)_ Install the CLI using Cargo as follows: + + ```sh + cargo install --features cli tree-sitter-stack-graphs-javascript + ``` + + After this, the CLI should be available as `tree-sitter-stack-graphs-javascript`. + +2. _(From source)_ Instead of installing the CLI, it can also be run directly from the crate directory, as a replacement for a `tree-sitter-stack-graphs-javascript` invocation, as follows: + + ```sh + cargo run --features cli -- + ``` + +The basic CLI workflow for the command-line program is to index source code and issue queries against the resulting database: + +1. Index a source folder as follows: + + ```sh + tree-sitter-stack-graphs-javascript index SOURCE_DIR + ``` + + _Indexing will skip any files that have already be indexed. To force a re-index, add the `-f` flag._ + + To check the status if a source folder, run: + + ```sh + tree-sitter-stack-graphs-javascript status SOURCE_DIR + ``` + + To clean the database and start with a clean slate, run: + + ```sh + tree-sitter-stack-graphs-javascript clean + ``` + + _Pass the `--delete` flag to not just empty the database, but also delete it. This is useful to resolve `unsupported database version` errors that may occur after a version update._ + +2. Run a query to find the definition(s) for a reference on a given line and column, run: + + ```sh + tree-sitter-stack-graphs-javascript query definition SOURCE_PATH:LINE:COLUMN + ``` + + Resulting definitions are printed, including a source line if the source file is available. + +Discover all available commands and flags by passing the `-h` flag to the CLI directly, or to any of the subcommands. ## Development @@ -35,35 +81,29 @@ The project is written in Rust, and requires a recent version installed. Rust c The project is organized as follows: - The stack graph rules are defined in `src/stack-graphs.tsg`. -- Builtins sources and configuration are defined in `src/builtins.js` and `builtins.cfg` respectively. +- Builtins sources and configuration are defined in `src/builtins.it` and `builtins.cfg` respectively. - Tests are put into the `test` directory. -### Building and Running Tests - -Build the project by running: - -``` sh -$ cargo build -``` +### Running Tests Run the tests as follows: -``` sh -$ cargo test +```sh +cargo test ``` The project consists of a library and a CLI. By default, running `cargo` only applies to the library. To run `cargo` commands on the CLI as well, add `--features cli` or `--all-features`. Run the CLI from source as follows: -``` sh -$ cargo run --features cli -- ARGS +```sh +cargo run --features cli -- ARGS ``` Sources are formatted using the standard Rust formatted, which is applied by running: -``` sh -$ cargo fmt +```sh +cargo fmt ``` ### Writing TSG @@ -78,21 +118,21 @@ which contain self-contained TSG rules for specific language features. A VSCode Parse and test a single file by executing the following commands: -``` sh -$ cargo run --features cli -- parse FILES... -$ cargo run --features cli -- test TESTFILES... +```sh +cargo run --features cli -- parse FILES... +cargo run --features cli -- test TESTFILES... ``` Generate a visualization to debug failing tests by passing the `-V` flag: -``` sh -$ cargo run --features cli -- test -V TESTFILES... +```sh +cargo run --features cli -- test -V TESTFILES... ``` To generate the visualization regardless of test outcome, execute: -``` sh -$ cargo run --features cli -- test -V --output-mode=always TESTFILES... +```sh +cargo run --features cli -- test -V --output-mode=always TESTFILES... ``` -Go to https://crates.io/crates/tree-sitter-stack-graphs for links to examples and documentation. +Go to for links to examples and documentation. diff --git a/languages/tree-sitter-stack-graphs-typescript/README.md b/languages/tree-sitter-stack-graphs-typescript/README.md index 0c1f9d5ee..fada7e2df 100644 --- a/languages/tree-sitter-stack-graphs-typescript/README.md +++ b/languages/tree-sitter-stack-graphs-typescript/README.md @@ -4,72 +4,106 @@ This project defines tree-sitter-stack-graphs rules for TypeScript using the [tr [tree-sitter-typescript]: https://crates.io/crates/tree-sitter-typescript -## Usage +- [API documentation](https://docs.rs/tree-sitter-stack-graphs-typescript/) +- [Release notes](https://github.com/github/stack-graphs/blob/main/languages/tree-sitter-stack-graphs-typescript/CHANGELOG.md) + +## Using the API To use this library, add the following to your `Cargo.toml`: -``` toml +```toml [dependencies] -tree-sitter-stack-graphs-typescript = "0.1" +tree-sitter-stack-graphs-typescript = "0.1.0" ``` -Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-typescript/*/) for -more details on how to use this library. +Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-typescript/*/) for more details on how to use this library. -## Command-line Program +## Using the Command-line Program -The command-line program for `tree-sitter-stack-graphs-typescript` lets you do -stack graph based analysis and lookup from the command line. +The command-line program for `tree-sitter-stack-graphs-typescript` lets you do stack graph based analysis and lookup from the command line. -Install the program using `cargo install` as follows: +The CLI can be run as follows: -``` sh -$ cargo install --features cli tree-sitter-stack-graphs-typescript -$ tree-sitter-stack-graphs-typescript --help -``` +1. _(Installed)_ Install the CLI using Cargo as follows: + + ```sh + cargo install --features cli tree-sitter-stack-graphs-typescript + ``` + + After this, the CLI should be available as `tree-sitter-stack-graphs-typescript`. + +2. _(From source)_ Instead of installing the CLI, it can also be run directly from the crate directory, as a replacement for a `tree-sitter-stack-graphs-typescript` invocation, as follows: + + ```sh + cargo run --features cli -- + ``` + +The basic CLI workflow for the command-line program is to index source code and issue queries against the resulting database: + +1. Index a source folder as follows: + + ```sh + tree-sitter-stack-graphs-typescript index SOURCE_DIR + ``` + + _Indexing will skip any files that have already be indexed. To force a re-index, add the `-f` flag._ + + To check the status if a source folder, run: + + ```sh + tree-sitter-stack-graphs-typescript status SOURCE_DIR + ``` + + To clean the database and start with a clean slate, run: + + ```sh + tree-sitter-stack-graphs-typescript clean + ``` + + _Pass the `--delete` flag to not just empty the database, but also delete it. This is useful to resolve `unsupported database version` errors that may occur after a version update._ + +2. Run a query to find the definition(s) for a reference on a given line and column, run: + + ```sh + tree-sitter-stack-graphs-typescript query definition SOURCE_PATH:LINE:COLUMN + ``` + + Resulting definitions are printed, including a source line if the source file is available. + +Discover all available commands and flags by passing the `-h` flag to the CLI directly, or to any of the subcommands. ## Development -The project is written in Rust, and requires a recent version installed. -Rust can be installed and updated using [rustup][]. +The project is written in Rust, and requires a recent version installed. Rust can be installed and updated using [rustup][]. [rustup]: https://rustup.rs/ - The project is organized as follows: - The stack graph rules are defined in `src/stack-graphs.tsg`. -- Builtins sources and configuration are defined in `src/builtins.ts` and `builtins.cfg` respectively. +- Builtins sources and configuration are defined in `src/builtins.it` and `builtins.cfg` respectively. - Tests are put into the `test` directory. -### Building and Running Tests - -Build the project by running: - -``` sh -$ cargo build -``` +### Running Tests Run the tests as follows: -``` sh -$ cargo test +```sh +cargo test ``` -The project consists of a library and a CLI. -By default, running `cargo` only applies to the library. -To run `cargo` commands on the CLI as well, add `--features cli` or `--all-features`. +The project consists of a library and a CLI. By default, running `cargo` only applies to the library. To run `cargo` commands on the CLI as well, add `--features cli` or `--all-features`. Run the CLI from source as follows: -``` sh -$ cargo run --features cli -- ARGS +```sh +cargo run --features cli -- ARGS ``` Sources are formatted using the standard Rust formatted, which is applied by running: -``` sh -$ cargo fmt +```sh +cargo fmt ``` ### Writing TSG @@ -84,21 +118,21 @@ which contain self-contained TSG rules for specific language features. A VSCode Parse and test a single file by executing the following commands: -``` sh -$ cargo run --features cli -- parse FILES... -$ cargo run --features cli -- test TESTFILES... +```sh +cargo run --features cli -- parse FILES... +cargo run --features cli -- test TESTFILES... ``` Generate a visualization to debug failing tests by passing the `-V` flag: -``` sh -$ cargo run --features cli -- test -V TESTFILES... +```sh +cargo run --features cli -- test -V TESTFILES... ``` To generate the visualization regardless of test outcome, execute: -``` sh -$ cargo run --features cli -- test -V --output-mode=always TESTFILES... +```sh +cargo run --features cli -- test -V --output-mode=always TESTFILES... ``` -Go to https://crates.io/crates/tree-sitter-stack-graphs for links to examples and documentation. +Go to for links to examples and documentation. diff --git a/script/ci-test-init b/script/ci-test-init new file mode 100755 index 000000000..c58532fd5 --- /dev/null +++ b/script/ci-test-init @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +set -eu + +cargo run --bin tree-sitter-stack-graphs --features cli -- init \ + --language-name InitTest \ + --language-id init_test \ + --language-file-extension it \ + --grammar-crate-name tree-sitter-python \ + --grammar-crate-version 0.20.0 \ + --internal \ + --non-interactive + +cargo check -p tree-sitter-stack-graphs-init_test --all-features + +cargo test -p tree-sitter-stack-graphs-init_test + +cargo run -p tree-sitter-stack-graphs-init_test --features cli -- -V diff --git a/tree-sitter-stack-graphs/README.md b/tree-sitter-stack-graphs/README.md index 01ce41971..dc7b18a80 100644 --- a/tree-sitter-stack-graphs/README.md +++ b/tree-sitter-stack-graphs/README.md @@ -1,7 +1,6 @@ # tree-sitter-stack-graphs -The `tree-sitter-stack-graphs` crate lets you create stack graphs using the -[tree-sitter][] grammar for a language. +The `tree-sitter-stack-graphs` crate lets you create stack graphs using the [tree-sitter][] grammar for a language. [tree-sitter]: https://tree-sitter.github.io/ @@ -9,50 +8,82 @@ The `tree-sitter-stack-graphs` crate lets you create stack graphs using the - [Examples](https://github.com/github/stack-graphs/blob/main/tree-sitter-stack-graphs/examples/) - [Release notes](https://github.com/github/stack-graphs/blob/main/tree-sitter-stack-graphs/CHANGELOG.md) -## Usage +## Using the API To use this library, add the following to your `Cargo.toml`: -``` toml +```toml [dependencies] tree-sitter-stack-graphs = "0.7" ``` -Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs/*/) for -more details on how to use this library. +Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs/*/) for more details on how to use this library. -## Command-line Program +## Using the Command-line Program -The command-line program for `tree-sitter-stack-graphs` lets you do stack -graph based analysis and lookup from the command line. +The command-line program for `tree-sitter-stack-graphs` lets you do stack graph based analysis and lookup from the command line. -Install the program using `cargo install` as follows: +The CLI can be run as follows: -``` sh -$ cargo install --features cli tree-sitter-stack-graphs -$ tree-sitter-stack-graphs --help -``` +1. _(Installed)_ Install the CLI using Cargo as follows: -Alternatively, the program can be invoked via NPM as follows: + ```sh + cargo install --features cli tree-sitter-stack-graphs + ``` -``` sh -$ npx tree-sitter-stack-graphs -``` + After this, the CLI should be available as `tree-sitter-stack-graphs`. + +2. _(From source)_ Instead of installing the CLI, it can also be run directly from the crate directory, as a replacement for a `tree-sitter-stack-graphs` invocation, as follows: + + ```sh + cargo run --features cli -- + ``` + +The basic CLI workflow for the command-line program is to index source code and issue queries against the resulting database: + +1. Index a source folder as follows: + + ```sh + tree-sitter-stack-graphs index SOURCE_DIR + ``` + + _Indexing will skip any files that have already be indexed. To force a re-index, add the `-f` flag._ + + To check the status if a source folder, run: + + ```sh + tree-sitter-stack-graphs status SOURCE_DIR + ``` -## Getting Started + To clean the database and start with a clean slate, run: -Starting a new project to develop stack graph definitions for your favourite language -is as easy as running the `init` command: + ```sh + tree-sitter-stack-graphs clean + ``` -``` sh -$ tree-sitter-stack-graphs init PROJECT_DIR + _Pass the `--delete` flag to not just empty the database, but also delete it. This is useful to resolve `unsupported database version` errors that may occur after a version update._ + +2. Run a query to find the definition(s) for a reference on a given line and column, run: + + ```sh + tree-sitter-stack-graphs query definition SOURCE_PATH:LINE:COLUMN + ``` + + Resulting definitions are printed, including a source line if the source file is available. + +Discover all available commands and flags by passing the `-h` flag to the CLI directly, or to any of the subcommands. + +## Getting Started on a new Language + +Starting a new project to develop stack graph definitions for your favourite language is as easy as running the `init` command: + +```sh +tree-sitter-stack-graphs init PROJECT_DIR ``` -Answer the questions to provide information about the language, the grammar dependency, and -the project and hit `Generate` to generate the new project. Check out `PROJECT_DIR/README.md` -to find out how to start developing. +Answer the questions to provide information about the language, the grammar dependency, and the project and hit `Generate` to generate the new project. Check out `PROJECT_DIR/README.md` to find out how to start developing. -Also check out our [examples][] for more details on how to work with the CLI. +Check out [examples][] of stack graph rules for typical language features. [examples]: https://github.com/github/stack-graphs/blob/main/tree-sitter-stack-graphs/examples/ @@ -65,14 +96,14 @@ Rust can be installed and updated using [rustup][]. Build the project by running: -``` -$ cargo build +```sh +cargo build ``` Run the tests by running: -``` -$ cargo test +```sh +cargo test ``` The project consists of a library and a CLI. @@ -81,22 +112,22 @@ To run `cargo` commands on the CLI as well, add `--features cli` or `--all-featu Run the CLI from source as follows: -``` sh -$ cargo run --features cli -- ARGS +```sh +cargo run --features cli -- ARGS ``` Sources are formatted using the standard Rust formatted, which is applied by running: -``` -$ cargo fmt +```sh +cargo fmt ``` ## License Licensed under either of - - [Apache License, Version 2.0][apache] ([LICENSE-APACHE](LICENSE-APACHE)) - - [MIT license][mit] ([LICENSE-MIT](LICENSE-MIT)) +- [Apache License, Version 2.0][apache] ([LICENSE-APACHE](LICENSE-APACHE)) +- [MIT license][mit] ([LICENSE-MIT](LICENSE-MIT)) at your option. diff --git a/tree-sitter-stack-graphs/examples/README.md b/tree-sitter-stack-graphs/examples/README.md index 901616422..5d5186ad5 100644 --- a/tree-sitter-stack-graphs/examples/README.md +++ b/tree-sitter-stack-graphs/examples/README.md @@ -7,19 +7,19 @@ Each directory contains a `stack-graphs.tsg` file that describes at the top what Running the examples requires the Python grammar to be available. This can be installed (in this directory) by executing: ```bash -$ ./bootstrap +./bootstrap ``` Run the tests for an example by executing: ```bash -$ ./run EXAMPLE_DIR +./run EXAMPLE_DIR ``` or, from within the example's directory: ```bash -$ ../run +../run ``` To render HTML visualizations of the stack graphs for the tests in an example, add the `-V` flag to run. @@ -27,7 +27,7 @@ To render HTML visualizations of the stack graphs for the tests in an example, a Print the parse tree of an example file by executing: ```bash -$ ./parse EXAMPLE_FILE +./parse EXAMPLE_FILE ``` The following examples are available: diff --git a/tree-sitter-stack-graphs/src/cli/init.rs b/tree-sitter-stack-graphs/src/cli/init.rs index e381786b9..df18339aa 100644 --- a/tree-sitter-stack-graphs/src/cli/init.rs +++ b/tree-sitter-stack-graphs/src/cli/init.rs @@ -455,33 +455,79 @@ impl ProjectSettings<'_> { fn generate_readme(&self, project_path: &Path) -> anyhow::Result<()> { let mut file = File::create(project_path.join("README.md"))?; writedoc! {file, r####" - # tree-sitter-stack-graphs definition for {} + # tree-sitter-stack-graphs definition for {language_name} - This project defines tree-sitter-stack-graphs rules for {} using the [{}][] grammar. + This project defines tree-sitter-stack-graphs rules for {language_name} using the [{grammar_crate_name}][] grammar. - [{}]: https://crates.io/crates/{} + [{grammar_crate_name}]: https://crates.io/crates/{grammar_crate_name} - ## Usage + - [API documentation](https://docs.rs/{crate_name}/) + - [Release notes](https://github.com/github/stack-graphs/blob/main/languages/{crate_name}/CHANGELOG.md) + + ## Using the API To use this library, add the following to your `Cargo.toml`: - ``` toml + ```toml [dependencies] - {} = "{}" + {crate_name} = "{crate_version}" ``` - Check out our [documentation](https://docs.rs/{}/*/) for more details on how to use this library. + Check out our [documentation](https://docs.rs/{crate_name}/*/) for more details on how to use this library. - ## Command-line Program + ## Using the Command-line Program - The command-line program for `{}` lets you do stack graph based analysis and lookup from the command line. + The command-line program for `{crate_name}` lets you do stack graph based analysis and lookup from the command line. - Install the program using `cargo install` as follows: + The CLI can be run as follows: - ``` sh - $ cargo install --features cli {} - $ {} --help - ``` + 1. _(Installed)_ Install the CLI using Cargo as follows: + + ```sh + cargo install --features cli {crate_name} + ``` + + After this, the CLI should be available as `{crate_name}`. + + 2. _(From source)_ Instead of installing the CLI, it can also be run directly from the crate directory, as a replacement for a `{crate_name}` invocation, as follows: + + ```sh + cargo run --features cli -- + ``` + + The basic CLI workflow for the command-line program is to index source code and issue queries against the resulting database: + + 1. Index a source folder as follows: + + ```sh + {crate_name} index SOURCE_DIR + ``` + + _Indexing will skip any files that have already be indexed. To force a re-index, add the `-f` flag._ + + To check the status if a source folder, run: + + ```sh + {crate_name} status SOURCE_DIR + ``` + + To clean the database and start with a clean slate, run: + + ```sh + {crate_name} clean + ``` + + _Pass the `--delete` flag to not just empty the database, but also delete it. This is useful to resolve `unsupported database version` errors that may occur after a version update._ + + 2. Run a query to find the definition(s) for a reference on a given line and column, run: + + ```sh + {crate_name} query definition SOURCE_PATH:LINE:COLUMN + ``` + + Resulting definitions are printed, including a source line if the source file is available. + + Discover all available commands and flags by passing the `-h` flag to the CLI directly, or to any of the subcommands. ## Development @@ -492,35 +538,29 @@ impl ProjectSettings<'_> { The project is organized as follows: - The stack graph rules are defined in `src/stack-graphs.tsg`. - - Builtins sources and configuration are defined in `src/builtins.{}` and `builtins.cfg` respectively. + - Builtins sources and configuration are defined in `src/builtins.{language_file_extension}` and `builtins.cfg` respectively. - Tests are put into the `test` directory. - ### Building and Running Tests - - Build the project by running: - - ``` sh - $ cargo build - ``` + ### Running Tests Run the tests as follows: - ``` sh - $ cargo test + ```sh + cargo test ``` The project consists of a library and a CLI. By default, running `cargo` only applies to the library. To run `cargo` commands on the CLI as well, add `--features cli` or `--all-features`. Run the CLI from source as follows: - ``` sh - $ cargo run --features cli -- ARGS + ```sh + cargo run --features cli -- ARGS ``` Sources are formatted using the standard Rust formatted, which is applied by running: - ``` sh - $ cargo fmt + ```sh + cargo fmt ``` ### Writing TSG @@ -535,34 +575,30 @@ impl ProjectSettings<'_> { Parse and test a single file by executing the following commands: - ``` sh - $ cargo run --features cli -- parse FILES... - $ cargo run --features cli -- test TESTFILES... + ```sh + cargo run --features cli -- parse FILES... + cargo run --features cli -- test TESTFILES... ``` Generate a visualization to debug failing tests by passing the `-V` flag: - ``` sh - $ cargo run --features cli -- test -V TESTFILES... + ```sh + cargo run --features cli -- test -V TESTFILES... ``` To generate the visualization regardless of test outcome, execute: - ``` sh - $ cargo run --features cli -- test -V --output-mode=always TESTFILES... + ```sh + cargo run --features cli -- test -V --output-mode=always TESTFILES... ``` - Go to https://crates.io/crates/tree-sitter-stack-graphs for links to examples and documentation. + Go to for links to examples and documentation. "####, - self.language_name, - self.language_name, self.grammar_crate_name(), - self.grammar_crate_name(), self.grammar_crate_name(), - self.crate_name(), self.crate_version(), - self.crate_name(), - self.crate_name(), - self.crate_name(), - self.crate_name(), - self.language_file_extension, + language_name=self.language_name, + grammar_crate_name=self.grammar_crate_name(), + crate_name=self.crate_name(), + crate_version=self.crate_version(), + language_file_extension=self.language_file_extension, }?; Ok(()) } From 13b5e25b3603126883074caffc6409e8a73b8d4c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 16 Jan 2024 14:38:57 -0500 Subject: [PATCH 299/500] Nested arrow functions. Co-Authored-By: Rebecca Valentine <171941+BekaValentine@users.noreply.github.com> --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index e732ced2a..17a9ddcca 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -46,6 +46,7 @@ undefined; [1, 2, 3]; function () { return; }; () => { }; +() => () => { }; function* () { yield 1; }; foo(); foo(bar); From 1f75acb21053475198da0962f730dd02e5419165 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 16 Jan 2024 14:52:44 -0500 Subject: [PATCH 300/500] Trace return_or_yield through an edge. Co-Authored-By: Rebecca Valentine <171941+BekaValentine@users.noreply.github.com> --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index d7faf39f2..e15e3e301 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -2818,7 +2818,7 @@ inherit .return_or_yield ; function values have return nodes which need to be visible for returns attr (fun_value_return) pop_symbol = "GUARD:RETURN" edge fun_value_call -> fun_value_return - let @body.return_or_yield = fun_value_return + edge fun_value_return -> @fun.return_or_yield ; function values have this nodes which need to be visible for method calls attr (fun_value_this) push_symbol = "this" From d31bd76627cab9f041810070b189cfb959450331 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 16 Jan 2024 15:18:12 -0500 Subject: [PATCH 301/500] Nested functions. Co-Authored-By: Rebecca Valentine <171941+BekaValentine@users.noreply.github.com> --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index 17a9ddcca..3f21383b5 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -45,6 +45,7 @@ undefined; []; [1, 2, 3]; function () { return; }; +function () { return function () { }; }; () => { }; () => () => { }; function* () { yield 1; }; From 4a70bcf496f5a26bfdb5cddc1eb593b3ab06373e Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 16 Jan 2024 15:25:05 -0500 Subject: [PATCH 302/500] Test comments in param lists. Co-Authored-By: Rebecca Valentine <171941+BekaValentine@users.noreply.github.com> --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index e732ced2a..6bd200294 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -47,6 +47,7 @@ undefined; function () { return; }; () => { }; function* () { yield 1; }; +function (/**/) { }; foo(); foo(bar); foo.bar; From 8c46a27829bfe4b9adfcabd5964aed7cfa5813b2 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 16 Jan 2024 15:32:02 -0500 Subject: [PATCH 303/500] Give comments covalues. Co-Authored-By: Rebecca Valentine <171941+BekaValentine@users.noreply.github.com> --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index d7faf39f2..2afc77d71 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -398,6 +398,7 @@ inherit .return_or_yield node @comment.after_scope node @comment.before_scope node @comment.value + node @comment.covalue edge @comment.after_scope -> @comment.before_scope } From 8f39af50b135abc630ae5705018ff318fef76f18 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 16 Jan 2024 15:40:38 -0500 Subject: [PATCH 304/500] Test with parameters. Co-Authored-By: Rebecca Valentine <171941+BekaValentine@users.noreply.github.com> --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index 6bd200294..697edaac6 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -48,6 +48,8 @@ function () { return; }; () => { }; function* () { yield 1; }; function (/**/) { }; +function (x /**/) { }; +function (/**/ x) { }; foo(); foo(bar); foo.bar; From c1b16560b0353fdb3ad039ed632b60f6878f1b3c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 16 Jan 2024 16:03:30 -0500 Subject: [PATCH 305/500] Extract the else_clause nodes into their own rule. They were being run twice due to :sparkles: comments :sparkles: Co-Authored-By: Rebecca Valentine <171941+BekaValentine@users.noreply.github.com> --- .../src/stack-graphs.tsg | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 9e887ea32..602d19244 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -1708,6 +1708,11 @@ inherit .return_or_yield edge @if_stmt.after_scope -> @alternative.after_scope } +(else_clause)@else_clause { + node @else_clause.after_scope + node @else_clause.before_scope +} + (else_clause (_)@inner)@else_clause { @@ -1716,8 +1721,6 @@ inherit .return_or_yield } (else_clause (_)@inner)@else_clause { - node @else_clause.after_scope - node @else_clause.before_scope ; scopes flow in and right back out edge @inner.before_scope -> @else_clause.before_scope edge @else_clause.after_scope -> @inner.after_scope From 500f5fc4f9789dba24ff9984cba0fcc41d619d87 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 16 Jan 2024 16:06:50 -0500 Subject: [PATCH 306/500] The first child is the hoist point. Co-Authored-By: Rebecca Valentine <171941+BekaValentine@users.noreply.github.com> --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 602d19244..b1c6481d2 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -1714,7 +1714,7 @@ inherit .return_or_yield } (else_clause - (_)@inner)@else_clause { + . (_)@inner)@else_clause { let @else_clause.hoist_point = @inner.before_scope From 726aa2931129b1925488afd48b1f5d68df7cefad Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 16 Jan 2024 16:13:54 -0500 Subject: [PATCH 307/500] Test comments around if statements. Co-Authored-By: Rebecca Valentine <171941+BekaValentine@users.noreply.github.com> --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index b557e8bcf..99a0f98b2 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -12,6 +12,11 @@ function* foo() { } class Foo { } { } if (true) { } +if (true) { } else { } +if (/**/ true) /**/ { } else /**/ { } +if (true) return; +if (true) return; else return; +if (/**/ true) /**/ return; else /**/ return; switch (x) { } for (x; y; z) { } for (x in xs) { } From 62a1ff3bb22b4f0934bf8f3deba5b297340b418a Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Wed, 17 Jan 2024 14:06:12 -0800 Subject: [PATCH 308/500] Makes class definiens be the constructor instead of the class body --- .../src/stack-graphs.tsg | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index b1c6481d2..e4eb58924 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4629,11 +4629,19 @@ inherit .return_or_yield ;; These rules are all about declarations and terms that have the names ;; directly in them. -(class_declaration - name:(_)@name - body:(_)@_body)@class_decl { +( + (class_declaration + name:(_)@name + body:(class_body + (method_definition + name:(_)@name)@constructor + ) + ) + + (#eq? @name "constructor") +) { - attr (@name.pop) definiens_node = @class_decl + attr (@name.pop) definiens_node = @constructor } @@ -4680,11 +4688,19 @@ inherit .return_or_yield } -(class - name:(_)@name - body:(_)@_body)@class { +( + (class + name:(_)@name + body:(class_body + (method_definition + name:(_)@name)@constructor + ) + ) - attr (@name.pop) definiens_node = @class + (#eq? @name "constructor") +) { + + attr (@name.pop) definiens_node = @constructor } From dbcf25ce0dbd1700e1ef492da73bcd0ffbac912d Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 18 Jan 2024 11:25:57 -0800 Subject: [PATCH 309/500] Adds member field name --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index e4eb58924..4d9266296 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4633,7 +4633,7 @@ inherit .return_or_yield (class_declaration name:(_)@name body:(class_body - (method_definition + member:(method_definition name:(_)@name)@constructor ) ) @@ -4692,7 +4692,7 @@ inherit .return_or_yield (class name:(_)@name body:(class_body - (method_definition + member:(method_definition name:(_)@name)@constructor ) ) From 7f1034f4358f25a284a29a8a61cbc0e8617896a3 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 18 Jan 2024 11:37:10 -0800 Subject: [PATCH 310/500] Fixes bug --- .../src/stack-graphs.tsg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 4d9266296..5d4100acb 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4634,11 +4634,11 @@ inherit .return_or_yield name:(_)@name body:(class_body member:(method_definition - name:(_)@name)@constructor + name:(_)@_method_name)@constructor ) ) - (#eq? @name "constructor") + (#eq? @_method_name "constructor") ) { attr (@name.pop) definiens_node = @constructor @@ -4693,11 +4693,11 @@ inherit .return_or_yield name:(_)@name body:(class_body member:(method_definition - name:(_)@name)@constructor + name:(_)@_method_name)@constructor ) ) - (#eq? @name "constructor") + (#eq? @_method_name "constructor") ) { attr (@name.pop) definiens_node = @constructor From e7718570ec9f0f4966bcecead9fa16c8f7a82b2a Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Fri, 26 Jan 2024 15:41:24 -0800 Subject: [PATCH 311/500] Adds reference test --- ...ion_fields_and_methods_visible_in_other_methods.js | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_fields_and_methods_visible_in_other_methods.js diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_fields_and_methods_visible_in_other_methods.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_fields_and_methods_visible_in_other_methods.js new file mode 100644 index 000000000..d00499691 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_fields_and_methods_visible_in_other_methods.js @@ -0,0 +1,11 @@ +class Foo { + bar = 1; + baz() { } + quux() { + this.bar; + // ^ defined: 2 + + this.baz(); + // ^ defined: 2 + } +} \ No newline at end of file From d4f7b88bfc26f358878321450dd369e025b34832 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Fri, 26 Jan 2024 17:05:34 -0800 Subject: [PATCH 312/500] fixes bug in test --- ...s_declaration_fields_and_methods_visible_in_other_methods.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_fields_and_methods_visible_in_other_methods.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_fields_and_methods_visible_in_other_methods.js index d00499691..5ea5db72e 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_fields_and_methods_visible_in_other_methods.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_fields_and_methods_visible_in_other_methods.js @@ -6,6 +6,6 @@ class Foo { // ^ defined: 2 this.baz(); - // ^ defined: 2 + // ^ defined: 3 } } \ No newline at end of file From e0198278edb028a1db035abb89df59f18a130305 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Fri, 26 Jan 2024 17:05:43 -0800 Subject: [PATCH 313/500] Makes test pass --- .../src/stack-graphs.tsg | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 5d4100acb..a9274f6f3 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -257,6 +257,7 @@ inherit .import_statement inherit .pkg_pop inherit .pkg_push inherit .return_or_yield +inherit .containing_class_value @@ -357,6 +358,10 @@ inherit .return_or_yield node @prog.builtins_Regex_prototype node @prog.builtins_arguments_prototype node @prog.builtins_empty_object + ; !!!! HACK + ; stack graphs currently make it impossible to test if an inherited variable + ; like this is defined or not + let @prog.containing_class_value = @prog.builtins_null } @@ -1429,6 +1434,7 @@ inherit .return_or_yield node @name.pop node @class_decl.class_value + let @class_decl.containing_class_value = @class_decl.class_value node guard_prototype node @class_decl.prototype node @class_decl.constructor @@ -2382,6 +2388,14 @@ inherit .return_or_yield ; this is a lookup, ie a push attr (@this.value) symbol_reference = "this", source_node = @this edge @this.value -> @this.before_scope + + node pop_this + attr (pop_this) symbol_definition = "this" + node guard_prototype + attr (guard_prototype) push_symbol = "GUARD:PROTOTYPE" + edge @this.value -> pop_this + edge pop_this -> guard_prototype + edge guard_prototype -> @this.containing_class_value } From cc0e93705be92d3c3c56780f3a290393b3e959d3 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Fri, 26 Jan 2024 17:27:44 -0800 Subject: [PATCH 314/500] Adds class expressions --- .../src/stack-graphs.tsg | 1 + ..._fields_and_methods_visible_in_other_methods.js | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index a9274f6f3..93cd66066 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3464,6 +3464,7 @@ inherit .containing_class_value body:(_)@body)@class { node @class.class_value + let @class.containing_class_value = @class.class_value node guard_prototype node @class.prototype node @class.constructor diff --git a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_fields_and_methods_visible_in_other_methods.js b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_fields_and_methods_visible_in_other_methods.js index 5ea5db72e..3bed1c415 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_fields_and_methods_visible_in_other_methods.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/computation_flow/class_declaration_fields_and_methods_visible_in_other_methods.js @@ -8,4 +8,16 @@ class Foo { this.baz(); // ^ defined: 3 } -} \ No newline at end of file +} + +(class { + bar = 1; + baz() { } + quux() { + this.bar; + // ^ defined: 14 + + this.baz(); + // ^ defined: 15 + } +}); \ No newline at end of file From 30d216ffe01223e225bd3c9946f016b8f648500b Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 08:52:47 +0200 Subject: [PATCH 315/500] Add initial Python language project --- .../.gitignore | 3 + .../CHANGELOG.md | 6 ++ .../Cargo.toml | 38 +++++++ .../tree-sitter-stack-graphs-python/LICENSE | 0 .../tree-sitter-stack-graphs-python/README.md | 98 +++++++++++++++++++ .../rust/bin.rs | 32 ++++++ .../rust/lib.rs | 48 +++++++++ .../rust/test.rs | 23 +++++ .../src/builtins.cfg | 1 + .../src/builtins.py | 0 .../src/stack-graphs.tsg | 42 ++++++++ .../test/test.py | 0 12 files changed, 291 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-python/.gitignore create mode 100644 languages/tree-sitter-stack-graphs-python/CHANGELOG.md create mode 100644 languages/tree-sitter-stack-graphs-python/Cargo.toml create mode 100644 languages/tree-sitter-stack-graphs-python/LICENSE create mode 100644 languages/tree-sitter-stack-graphs-python/README.md create mode 100644 languages/tree-sitter-stack-graphs-python/rust/bin.rs create mode 100644 languages/tree-sitter-stack-graphs-python/rust/lib.rs create mode 100644 languages/tree-sitter-stack-graphs-python/rust/test.rs create mode 100644 languages/tree-sitter-stack-graphs-python/src/builtins.cfg create mode 100644 languages/tree-sitter-stack-graphs-python/src/builtins.py create mode 100644 languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg create mode 100644 languages/tree-sitter-stack-graphs-python/test/test.py diff --git a/languages/tree-sitter-stack-graphs-python/.gitignore b/languages/tree-sitter-stack-graphs-python/.gitignore new file mode 100644 index 000000000..faf6459fb --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/.gitignore @@ -0,0 +1,3 @@ +*.html +/Cargo.lock +/target diff --git a/languages/tree-sitter-stack-graphs-python/CHANGELOG.md b/languages/tree-sitter-stack-graphs-python/CHANGELOG.md new file mode 100644 index 000000000..9e6604deb --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/CHANGELOG.md @@ -0,0 +1,6 @@ +# Changelog for tree-sitter-stack-graphs-python + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). diff --git a/languages/tree-sitter-stack-graphs-python/Cargo.toml b/languages/tree-sitter-stack-graphs-python/Cargo.toml new file mode 100644 index 000000000..9270879c0 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "tree-sitter-stack-graphs-python" +version = "0.1.0" +description = "Stack graphs definition for Python using tree-sitter-python" +readme = "README.md" +keywords = ["tree-sitter", "stack-graphs", "python"] +authors = [ + "GitHub ", +] +license = "MIT OR Apache-2.0" +edition = "2018" + +[[bin]] +name = "tree-sitter-stack-graphs-python" +path = "rust/bin.rs" +required-features = ["cli"] + +[lib] +path = "rust/lib.rs" +test = false + +[[test]] +name = "test" +path = "rust/test.rs" +harness = false + +[features] +cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"] + +[dependencies] +anyhow = { version = "1.0", optional = true } +clap = { version = "4", optional = true, features = ["derive"] } +tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs" } +tree-sitter-python = "0.20.2" + +[dev-dependencies] +anyhow = "1.0" +tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs", features = ["cli"] } diff --git a/languages/tree-sitter-stack-graphs-python/LICENSE b/languages/tree-sitter-stack-graphs-python/LICENSE new file mode 100644 index 000000000..e69de29bb diff --git a/languages/tree-sitter-stack-graphs-python/README.md b/languages/tree-sitter-stack-graphs-python/README.md new file mode 100644 index 000000000..3bf115da0 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/README.md @@ -0,0 +1,98 @@ +# tree-sitter-stack-graphs definition for Python + +This project defines tree-sitter-stack-graphs rules for Python using the [tree-sitter-python][] grammar. + +[tree-sitter-python]: https://crates.io/crates/tree-sitter-python + +## Usage + +To use this library, add the following to your `Cargo.toml`: + +``` toml +[dependencies] +tree-sitter-stack-graphs-python = "0.1.0" +``` + +Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-python/*/) for more details on how to use this library. + +## Command-line Program + +The command-line program for `tree-sitter-stack-graphs-python` lets you do stack graph based analysis and lookup from the command line. + +Install the program using `cargo install` as follows: + +``` sh +$ cargo install --features cli tree-sitter-stack-graphs-python +$ tree-sitter-stack-graphs-python --help +``` + +## Development + +The project is written in Rust, and requires a recent version installed. Rust can be installed and updated using [rustup][]. + +[rustup]: https://rustup.rs/ + +The project is organized as follows: + +- The stack graph rules are defined in `src/stack-graphs.tsg`. +- Builtins sources and configuration are defined in `src/builtins.py` and `builtins.cfg` respectively. +- Tests are put into the `test` directory. + +### Building and Running Tests + +Build the project by running: + +``` sh +$ cargo build +``` + +Run the tests as follows: + +``` sh +$ cargo test +``` + +The project consists of a library and a CLI. By default, running `cargo` only applies to the library. To run `cargo` commands on the CLI as well, add `--features cli` or `--all-features`. + +Run the CLI from source as follows: + +``` sh +$ cargo run --features cli -- ARGS +``` + +Sources are formatted using the standard Rust formatted, which is applied by running: + +``` sh +$ cargo fmt +``` + +### Writing TSG + +The stack graph rules are written in [tree-sitter-graph][]. Checkout the [examples][], +which contain self-contained TSG rules for specific language features. A VSCode +[extension][] is available that provides syntax highlighting for TSG files. + +[tree-sitter-graph]: https://github.com/tree-sitter/tree-sitter-graph +[examples]: https://github.com/github/stack-graphs/blob/main/tree-sitter-stack-graphs/examples/ +[extension]: https://marketplace.visualstudio.com/items?itemName=tree-sitter.tree-sitter-graph + +Parse and test a single file by executing the following commands: + +``` sh +$ cargo run --features cli -- parse FILES... +$ cargo run --features cli -- test TESTFILES... +``` + +Generate a visualization to debug failing tests by passing the `-V` flag: + +``` sh +$ cargo run --features cli -- test -V TESTFILES... +``` + +To generate the visualization regardless of test outcome, execute: + +``` sh +$ cargo run --features cli -- test -V --output-mode=always TESTFILES... +``` + +Go to https://crates.io/crates/tree-sitter-stack-graphs for links to examples and documentation. diff --git a/languages/tree-sitter-stack-graphs-python/rust/bin.rs b/languages/tree-sitter-stack-graphs-python/rust/bin.rs new file mode 100644 index 000000000..dc9a6772c --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/rust/bin.rs @@ -0,0 +1,32 @@ +// -*- coding: utf-8 -*- +// ------------------------------------------------------------------------------------------------ +// Copyright © 2023, stack-graphs authors. +// Licensed under either of Apache License, Version 2.0, or MIT license, at your option. +// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. +// ------------------------------------------------------------------------------------------------ + +use anyhow::anyhow; +use clap::Parser; +use tree_sitter_stack_graphs::cli::database::default_user_database_path_for_crate; +use tree_sitter_stack_graphs::cli::provided_languages::Subcommands; +use tree_sitter_stack_graphs::NoCancellation; + +fn main() -> anyhow::Result<()> { + let lc = match tree_sitter_stack_graphs_python::try_language_configuration(&NoCancellation) { + Ok(lc) => lc, + Err(err) => { + eprintln!("{}", err.display_pretty()); + return Err(anyhow!("Language configuration error")); + } + }; + let cli = Cli::parse(); + let default_db_path = default_user_database_path_for_crate(env!("CARGO_PKG_NAME"))?; + cli.subcommand.run(default_db_path, vec![lc]) +} + +#[derive(Parser)] +#[clap(about, version)] +pub struct Cli { + #[clap(subcommand)] + subcommand: Subcommands, +} diff --git a/languages/tree-sitter-stack-graphs-python/rust/lib.rs b/languages/tree-sitter-stack-graphs-python/rust/lib.rs new file mode 100644 index 000000000..74176a475 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/rust/lib.rs @@ -0,0 +1,48 @@ +// -*- coding: utf-8 -*- +// ------------------------------------------------------------------------------------------------ +// Copyright © 2023, stack-graphs authors. +// Licensed under either of Apache License, Version 2.0, or MIT license, at your option. +// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. +// ------------------------------------------------------------------------------------------------ + +use tree_sitter_stack_graphs::loader::LanguageConfiguration; +use tree_sitter_stack_graphs::loader::LoadError; +use tree_sitter_stack_graphs::CancellationFlag; + +/// The stack graphs tsg source for this language. +pub const STACK_GRAPHS_TSG_PATH: &str = "src/stack-graphs.tsg"; +/// The stack graphs tsg source for this language. +pub const STACK_GRAPHS_TSG_SOURCE: &str = include_str!("../src/stack-graphs.tsg"); + +/// The stack graphs builtins configuration for this language. +pub const STACK_GRAPHS_BUILTINS_CONFIG: &str = include_str!("../src/builtins.cfg"); +/// The stack graphs builtins path for this language +pub const STACK_GRAPHS_BUILTINS_PATH: &str = "src/builtins.py"; +/// The stack graphs builtins source for this language. +pub const STACK_GRAPHS_BUILTINS_SOURCE: &str = include_str!("../src/builtins.py"); + +/// The name of the file path global variable. +pub const FILE_PATH_VAR: &str = "FILE_PATH"; + +pub fn language_configuration(cancellation_flag: &dyn CancellationFlag) -> LanguageConfiguration { + try_language_configuration(cancellation_flag).unwrap_or_else(|err| panic!("{}", err)) +} + +pub fn try_language_configuration( + cancellation_flag: &dyn CancellationFlag, +) -> Result { + LanguageConfiguration::from_sources( + tree_sitter_python::language(), + Some(String::from("source.py")), + None, + vec![String::from("py")], + STACK_GRAPHS_TSG_PATH.into(), + STACK_GRAPHS_TSG_SOURCE, + Some(( + STACK_GRAPHS_BUILTINS_PATH.into(), + STACK_GRAPHS_BUILTINS_SOURCE, + )), + Some(STACK_GRAPHS_BUILTINS_CONFIG), + cancellation_flag, + ) +} diff --git a/languages/tree-sitter-stack-graphs-python/rust/test.rs b/languages/tree-sitter-stack-graphs-python/rust/test.rs new file mode 100644 index 000000000..c81edf0d4 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/rust/test.rs @@ -0,0 +1,23 @@ +// -*- coding: utf-8 -*- +// ------------------------------------------------------------------------------------------------ +// Copyright © 2023, stack-graphs authors. +// Licensed under either of Apache License, Version 2.0, or MIT license, at your option. +// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. +// ------------------------------------------------------------------------------------------------ + +use anyhow::anyhow; +use std::path::PathBuf; +use tree_sitter_stack_graphs::ci::Tester; +use tree_sitter_stack_graphs::NoCancellation; + +fn main() -> anyhow::Result<()> { + let lc = match tree_sitter_stack_graphs_python::try_language_configuration(&NoCancellation) { + Ok(lc) => lc, + Err(err) => { + eprintln!("{}", err.display_pretty()); + return Err(anyhow!("Language configuration error")); + } + }; + let test_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test"); + Tester::new(vec![lc], vec![test_path]).run() +} diff --git a/languages/tree-sitter-stack-graphs-python/src/builtins.cfg b/languages/tree-sitter-stack-graphs-python/src/builtins.cfg new file mode 100644 index 000000000..d685061be --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/src/builtins.cfg @@ -0,0 +1 @@ +[globals] diff --git a/languages/tree-sitter-stack-graphs-python/src/builtins.py b/languages/tree-sitter-stack-graphs-python/src/builtins.py new file mode 100644 index 000000000..e69de29bb diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg new file mode 100644 index 000000000..99647e75b --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -0,0 +1,42 @@ +;; -*- coding: utf-8 -*- +;; ------------------------------------------------------------------------------------------------ +;; Copyright © 2023, stack-graphs authors. +;; Licensed under either of Apache License, Version 2.0, or MIT license, at your option. +;; Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. +;; ------------------------------------------------------------------------------------------------ + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Stack graphs definition for Python +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Global Variables +;; ^^^^^^^^^^^^^^^^ + +global FILE_PATH +global ROOT_NODE +global JUMP_TO_SCOPE_NODE + +;; Attribute Shorthands +;; ^^^^^^^^^^^^^^^^^^^^ + +attribute node_definition = node => type = "pop_symbol", node_symbol = node, is_definition +attribute node_reference = node => type = "push_symbol", node_symbol = node, is_reference +attribute pop_node = node => type = "pop_symbol", node_symbol = node +attribute pop_scoped_node = node => type = "pop_scoped_symbol", node_symbol = node +attribute pop_scoped_symbol = symbol => type = "pop_scoped_symbol", symbol = symbol +attribute pop_symbol = symbol => type = "pop_symbol", symbol = symbol +attribute push_node = node => type = "push_symbol", node_symbol = node +attribute push_scoped_node = node => type = "push_scoped_symbol", node_symbol = node +attribute push_scoped_symbol = symbol => type = "push_scoped_symbol", symbol = symbol +attribute push_symbol = symbol => type = "push_symbol", symbol = symbol +attribute scoped_node_definition = node => type = "pop_scoped_symbol", node_symbol = node, is_definition +attribute scoped_node_reference = node => type = "push_scoped_symbol", node_symbol = node, is_reference +attribute symbol_definition = symbol => type = "pop_symbol", symbol = symbol, is_definition +attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, is_reference + +attribute node_symbol = node => symbol = (source-text node), source_node = node + +;; Stack Graph Rules +;; ^^^^^^^^^^^^^^^^^ + +; Have fun! diff --git a/languages/tree-sitter-stack-graphs-python/test/test.py b/languages/tree-sitter-stack-graphs-python/test/test.py new file mode 100644 index 000000000..e69de29bb From 75a3ec5939ead46a7d50c18ad8a936067402c4f6 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 09:37:26 +0200 Subject: [PATCH 316/500] Add legacy queries and tests for reference --- .../src/stack-graphs.scm | 779 ++++++++++++++++++ .../test/legacy.skip/aliased_imports.py | 31 + .../test/legacy.skip/attributes.py | 14 + .../test/legacy.skip/blocks.py | 21 + .../test/legacy.skip/chained_functions.py | 23 + .../test/legacy.skip/chained_methods.py | 27 + .../test/legacy.skip/class_members.py | 23 + .../test/legacy.skip/decorators.py | 10 + .../test/legacy.skip/exceptions.py | 5 + .../test/legacy.skip/functions.py | 31 + .../test/legacy.skip/imported_functions.py | 17 + .../test/legacy.skip/imports.py | 31 + .../test/legacy.skip/instance_members.py | 38 + .../test/legacy.skip/loops.py | 19 + .../test/legacy.skip/many_definitions.py | 76 ++ .../test/legacy.skip/pattern_matching.py | 39 + .../test/legacy.skip/redundant_reexport.py | 15 + .../test/legacy.skip/relative_imports.py | 60 ++ .../test/legacy.skip/statement_bindings.py | 9 + .../test/legacy.skip/superclasses.py | 19 + .../test/{ => legacy.skip}/test.py | 0 .../test/legacy.skip/tuples.py | 38 + .../test/legacy.skip/wildcard_import.py | 21 + 23 files changed, 1346 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-python/src/stack-graphs.scm create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/aliased_imports.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/attributes.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/blocks.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/chained_functions.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/chained_methods.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/class_members.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/decorators.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/exceptions.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/functions.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/imported_functions.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/imports.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/instance_members.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/loops.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/many_definitions.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/pattern_matching.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/redundant_reexport.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/relative_imports.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/statement_bindings.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/superclasses.py rename languages/tree-sitter-stack-graphs-python/test/{ => legacy.skip}/test.py (100%) create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/tuples.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/legacy.skip/wildcard_import.py diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.scm b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.scm new file mode 100644 index 000000000..380af7d95 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.scm @@ -0,0 +1,779 @@ +;; -*- coding: utf-8 -*- +;; ------------------------------------------------------------------------------------------------ +;; Copyright © 2023, stack-graphs authors. +;; Licensed under either of Apache License, Version 2.0, or MIT license, at your option. +;; Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. +;; ------------------------------------------------------------------------------------------------ + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; LEGACY DEFINITION! INCLUDED FOR REFERENCE ONLY! ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; Modules and Imports +;--------------------- + +(module) @mod +{ + var module_def = @mod.file_def + attr module_def "no_span" + var module_ref = @mod.file_ref + attr module_ref "no_span" + var parent_module_def = module_def + var parent_module_ref = module_ref + var grandparent_module_ref = module_ref + + scan filepath { + "([^/]+)/" + { + edge module_def -> module_def.dot + edge module_def.dot -> module_def.next_def + edge module_ref.next_ref -> module_ref.dot + edge module_ref.dot -> module_ref + + attr module_def "pop" = $1 + attr module_def.dot "pop" = "." + attr module_ref "push" = $1 + attr module_ref.dot "push" = "." + + set grandparent_module_ref = parent_module_ref + set parent_module_def = module_def + set parent_module_ref = module_ref + set module_ref = module_ref.next_ref + set module_def = module_def.next_def + attr module_def "no_span" + attr module_ref "no_span" + } + + "__init__\\.py$" + { + attr parent_module_def "definition" + } + + "([^/]+)$" + { + edge module_def -> module_def.dot + edge module_def.dot -> module_def.next_def + + attr module_def "definition", "pop" = (replace $1 "\\.py" "") + attr module_def.dot "pop" = "." + + set module_def = module_def.next_def + attr module_def "no_span" + attr module_ref "no_span" + } + } + + edge root -> @mod.file_def + edge @mod.file_ref -> root + edge module_def -> @mod.after_scope + + edge @mod.before_scope -> @mod.global_dot + edge @mod.global -> root + attr @mod.global "push" = "" + + edge @mod.global_dot -> @mod.global + attr @mod.global_dot "push" = "." + + var @mod::parent_module = parent_module_ref + var @mod::grandparent_module = grandparent_module_ref + var @mod::bottom = @mod.after_scope + var @mod::global = @mod.global + var @mod::global_dot = @mod.global_dot +} + +(import_statement + name: (dotted_name + . (identifier) @root_name)) @stmt +{ + edge @stmt.after_scope -> @root_name.def, "precedence" = 1 + edge @root_name.ref -> root + attr @root_name.ref "push", "reference" + attr @root_name.def "pop", "definition" +} + +(import_statement + name: (aliased_import + (dotted_name . (identifier) @root_name))) @stmt +{ + edge @stmt.after_scope -> @root_name.def + edge @root_name.ref -> root + attr @root_name.ref "push", "reference" +} + +(import_from_statement + module_name: (dotted_name + . (identifier) @prefix_root_name)) @stmt +{ + edge @prefix_root_name.ref -> root + attr @prefix_root_name.ref "push", "reference" +} + +(import_from_statement + name: (dotted_name + . (identifier) @import_root_name)) @stmt +{ + edge @stmt.after_scope -> @import_root_name.def, "precedence" = 1 + edge @import_root_name.ref -> @import_root_name.ref_dot + attr @import_root_name.def "pop", "definition" + attr @import_root_name.ref "push", "reference" + attr @import_root_name.ref_dot "push" = "." +} + +(import_from_statement + name: (aliased_import + (dotted_name + . (identifier) @import_root_name))) @stmt +{ + edge @import_root_name.ref -> @import_root_name.ref_dot + attr @import_root_name.ref "push", "reference" + attr @import_root_name.ref_dot "push" = "." +} + +(import_from_statement + module_name: [ + (dotted_name (identifier) @prefix_leaf_name .) + (relative_import (dotted_name (identifier) @prefix_leaf_name .)) + (relative_import (import_prefix) @prefix_leaf_name .) + ] + name: [ + (dotted_name + . (identifier) @import_root_name) + (aliased_import + (dotted_name + . (identifier) @import_root_name)) + ]) +{ + edge @import_root_name.ref_dot -> @prefix_leaf_name.ref +} + +[ + (import_from_statement + (aliased_import + name: (dotted_name (identifier) @name .) + alias: (identifier) @alias)) + (import_statement + (aliased_import + name: (dotted_name (identifier) @name .) + alias: (identifier) @alias)) +] @stmt +{ + edge @stmt.after_scope -> @alias + edge @alias -> @name.ref + attr @alias "pop", "definition" +} + +[ + (import_statement + name: (dotted_name + (identifier) @leaf_name .)) + (import_from_statement + name: (dotted_name + (identifier) @leaf_name .)) +] +{ + attr @leaf_name.def "pop", "definition" + attr @leaf_name.ref "push", "reference" + edge @leaf_name.def -> @leaf_name.ref +} + +(relative_import + (import_prefix) @prefix + (#eq? @prefix ".")) @import +{ + edge @prefix.ref -> @import::parent_module +} + +(relative_import + (import_prefix) @prefix + (#eq? @prefix "..")) @import +{ + edge @prefix.ref -> @import::grandparent_module +} + +(relative_import + (import_prefix) @prefix + (dotted_name + . (identifier) @name)) +{ + attr @name.ref "push", "reference" + attr @name.ref_dot "push" = "." + edge @name.ref -> @name.ref_dot + edge @name.ref_dot -> @prefix.ref +} + +[ + (import_from_statement + module_name: (relative_import + (dotted_name + (identifier) @parent_name + . + (identifier) @child_name))) + (import_from_statement + module_name: (dotted_name + (identifier) @parent_name + . + (identifier) @child_name)) +] +{ + attr @child_name.ref "push", "reference" + attr @child_name.ref_dot "push" = "." + edge @child_name.ref -> @child_name.ref_dot + edge @child_name.ref_dot -> @parent_name.ref +} + +(import_from_statement + module_name: (dotted_name + . (identifier) @root_name)) +{ + attr @root_name.ref "push", "reference" + edge @root_name.ref -> root +} + +(import_from_statement + module_name: (dotted_name + (identifier) @leaf_name .) + (wildcard_import) @star) @stmt +{ + edge @stmt.after_scope -> @star.ref_dot, "precedence" = 1 + edge @star.ref_dot -> @leaf_name.ref + attr @star.ref_dot "push" = "." +} + +[ + (import_statement + name: (dotted_name + (identifier) @parent_name + . + (identifier) @child_name)) + (import_from_statement + name: (dotted_name + (identifier) @parent_name + . + (identifier) @child_name)) + (import_from_statement + name: (aliased_import + name: (dotted_name + (identifier) @parent_name + . + (identifier) @child_name))) +] +{ + edge @child_name.ref -> @child_name.ref_dot + edge @child_name.ref_dot -> @parent_name.ref + edge @parent_name.def -> @parent_name.def_dot + edge @parent_name.def_dot -> @child_name.def + attr @child_name.def "pop", "definition" + attr @child_name.ref "push","reference" + attr @parent_name.def_dot "pop" = "." + attr @child_name.ref_dot "push" = "." +} + +;-------- +; Scopes +;-------- + +[ + (module (_) @last_stmt .) + (block (_) @last_stmt .) +] @block +{ + edge @block.after_scope -> @last_stmt.after_scope +} + +[ + (module (_) @stmt1 . (_) @stmt2) + (block (_) @stmt1 . (_) @stmt2) +] +{ + edge @stmt2.before_scope -> @stmt1.after_scope +} + +[ + (module (_) @stmt) + (block (_) @stmt) +] +{ + edge @stmt.after_scope -> @stmt.before_scope + let @stmt::local_scope = @stmt.before_scope +} + +[ + (block . (_) @stmt) + (module . (_) @stmt) +] @block +{ + edge @stmt.before_scope -> @block.before_scope +} + +(block (_) @stmt . ) @block +{ + edge @block.after_scope -> @stmt.after_scope +} + +(function_definition (block) @block) +{ + edge @block.before_scope -> @block::local_scope +} + +[ + (while_statement (block) @block) + (if_statement (block) @block) + (with_statement (block) @block) + (try_statement (block) @block) + (for_statement (block) @block) + (_ [ + (else_clause (block) @block) + (elif_clause (block) @block) + (except_clause (block) @block) + (finally_clause (block) @block) + ]) +] @stmt +{ + edge @block.before_scope -> @block::local_scope + edge @stmt.after_scope -> @block.after_scope +} + +(match_statement (case_clause) @block) @stmt +{ + let @block::local_scope = @block.before_scope + edge @block.before_scope -> @stmt.before_scope + edge @stmt.after_scope -> @block.after_scope +} + +[ + (for_statement) + (while_statement) +] @stmt +{ + edge @stmt.before_scope -> @stmt.after_scope +} + +;------------- +; Definitions +;------------- + +[ + (assignment + left: (_) @pattern + right: (_) @value) + (with_item + value: + (as_pattern + (_) @value + alias: (as_pattern_target (_) @pattern))) +] +{ + edge @pattern.input -> @value.output +} + +(function_definition + name: (identifier) @name + parameters: (parameters) @params + body: (block) @body) @func +{ + attr @name "definiens" = @func + edge @func.after_scope -> @name + edge @name -> @func.call + edge @func.call -> @func.return_value + edge @body.before_scope -> @params.after_scope + edge @body.before_scope -> @func.drop_scope + edge @func.drop_scope -> @func::bottom + attr @func.drop_scope "drop" + attr @name "pop", "definition" + attr @func.call "pop" = "()", "pop-scope" + attr @params.before_scope "jump-to" + attr @func.return_value "endpoint" + let @func::function_returns = @func.return_value + + ; Prevent functions defined inside of method bodies from being treated like methods + let @body::class_self_scope = nil + let @body::class_member_attr_scope = nil +} + +;; +;; BEGIN BIG GNARLY DISJUNCTION +;; +;; The following pair of rules is intended to capture the following behavior: +;; +;; If a function definition is used to define a method, by being inside a class +;; definition, then we make its syntax type `method`. Otherwise, we make it's +;; syntax type `function`. Unfortunately, because of the limitations on negation +;; and binding in tree sitter queries, we cannot negate `class_definition` or +;; similar things directly. Instead, we have to manually push the negation down +;; to form the finite disjunction it corresponds to. +;; + +[ + (class_definition (block (decorated_definition (function_definition name: (_)@name)))) + (class_definition (block (function_definition name: (_)@name))) +] +{ + attr @name "syntax_type" = "method" +} + +[ + (module (decorated_definition (function_definition name: (_)@name))) + (module (function_definition name: (_)@name)) + + (if_statement (block (decorated_definition (function_definition name: (_)@name)))) + (if_statement (block (function_definition name: (_)@name))) + + (elif_clause (block (decorated_definition (function_definition name: (_)@name)))) + (elif_clause (block (function_definition name: (_)@name))) + + (else_clause (block (decorated_definition (function_definition name: (_)@name)))) + (else_clause (block (function_definition name: (_)@name))) + + (case_clause (block (decorated_definition (function_definition name: (_)@name)))) + (case_clause (block (function_definition name: (_)@name))) + + (for_statement (block (decorated_definition (function_definition name: (_)@name)))) + (for_statement (block (function_definition name: (_)@name))) + + (while_statement (block (decorated_definition (function_definition name: (_)@name)))) + (while_statement (block (function_definition name: (_)@name))) + + (try_statement (block (decorated_definition (function_definition name: (_)@name)))) + (try_statement (block (function_definition name: (_)@name))) + + (except_clause (block (decorated_definition (function_definition name: (_)@name)))) + (except_clause (block (function_definition name: (_)@name))) + + (finally_clause (block (decorated_definition (function_definition name: (_)@name)))) + (finally_clause (block (function_definition name: (_)@name))) + + (with_statement (block (decorated_definition (function_definition name: (_)@name)))) + (with_statement (block (function_definition name: (_)@name))) + + (function_definition (block (decorated_definition (function_definition name: (_)@name)))) + (function_definition (block (function_definition name: (_)@name))) +] +{ + attr @name "syntax_type" = "function" +} + +;; +;; END BIG GNARLY DISJUNCTION +;; + +(function_definition + parameters: (parameters + . (identifier) @param) + body: (block) @body) +{ + edge @param.input -> @param::class_self_scope + edge @param::class_member_attr_scope -> @param.output + edge @param.output -> @body.after_scope + attr @param.output "push" +} + +(parameter/identifier) @param +{ + attr @param.input "definition", "pop" + attr @param.param_name "push" + edge @param.input -> @param.param_index + edge @param.input -> @param.param_name +} + +[ + (parameter/default_parameter + name: (identifier) @name + value: (_) @value) @param + (parameter/typed_default_parameter + name: (_) @name + value: (_) @value) @param +] +{ + attr @name "definition", "pop" + attr @param.param_name "push" = @name + edge @name -> @param.param_name + edge @name -> @param.param_index + edge @param.input -> @name + edge @name -> @value.output +} + +[ + (parameter/typed_parameter + . (_) @name) @param + (parameter/list_splat_pattern + (_) @name) @param + (parameter/dictionary_splat_pattern + (_) @name) @param +] +{ + attr @name "definition", "pop" + attr @param.param_name "push" = @name + edge @name -> @param.param_name + edge @name -> @param.param_index + edge @param.input -> @name +} + +[ + (pattern_list (_) @pattern) + (tuple_pattern (_) @pattern) +] @list +{ + let statement_scope = @list::local_scope + let @pattern::local_scope = @pattern.pattern_before_scope + edge statement_scope -> @pattern::local_scope, "precedence" = (+ 1 (child-index @pattern)) + + edge @pattern.pattern_index -> @list.input + edge @pattern.input -> @pattern.pattern_index + attr @pattern.pattern_index "push" = (child-index @pattern) +} + +(parameters + (_) @param) @params +{ + attr @param.param_index "push" = (child-index @param) + edge @param.param_index -> @params.before_scope + edge @params.after_scope -> @param.input + edge @param.param_name -> @params.before_scope +} + +(return_statement (_) @expr) @stmt +{ + edge @stmt::function_returns -> @expr.output +} + +(class_definition + name: (identifier) @name) @class +{ + attr @name "definiens" = @class + attr @name "syntax_type" = "class" + edge @class.parent_scope -> @class::class_parent_scope + edge @class.parent_scope -> @class::local_scope + edge @class.after_scope -> @name + edge @name -> @class.call + edge @name -> @class.dot + edge @class.dot -> @class.members + edge @class.call -> @class.call_drop + edge @class.call_drop -> @class.self_scope + edge @class.self_scope -> @class.super_scope + edge @class.self_scope -> @class.self_dot + edge @class.self_dot -> @class.members + edge @class.members -> @class.member_attrs + attr @class.call "pop" = "()", "pop-scope" + attr @class.call_drop "drop" + attr @class.dot "pop" = "." + attr @class.self_dot "pop" = "." + attr @name "pop", "definition" + attr @class.member_attrs "push" = "." + attr @class.self_scope "endpoint" + let @class::super_scope = @class.super_scope + let @class::class_parent_scope = @class.parent_scope + let @class::class_self_scope = @class.call_drop + let @class::class_member_attr_scope = @class.member_attrs +} + +(class_definition + body: (block + (_) @last_stmt .) @body) @class +{ + edge @class.members -> @last_stmt.after_scope +} + +(class_definition + superclasses: (argument_list + (_) @superclass)) @class +{ + edge @class.super_scope -> @superclass.output +} + +(decorated_definition + definition: (_) @def) @stmt +{ + edge @def.before_scope -> @stmt.before_scope + edge @stmt.after_scope -> @def.after_scope +} + +(case_clause + pattern: (_) @pattern + consequence: (_) @consequence) @clause +{ + edge @consequence.before_scope -> @pattern.new_bindings + edge @consequence.before_scope -> @clause.before_scope + edge @clause.after_scope -> @consequence.after_scope +} + +;------------- +; Expressions +;------------- + +(call + function: (_) @fn + arguments: (argument_list) @args) @call +{ + edge @call.output -> @call.output_args + edge @call.output_args -> @fn.output + attr @call.output_args "push" = "()", "push-scope" = @args +} + +(call + function: (attribute + object: (_) @receiver) + arguments: (argument_list + (expression) @arg) @args) +{ + edge @args -> @arg.arg_index + edge @receiver -> @receiver.arg_index + + attr @receiver.arg_index "pop" = "0" + edge @receiver.arg_index -> @receiver.output + + attr @arg.arg_index "pop" = (+ 1 (child-index @arg)) + edge @arg.arg_index -> @arg.output +} + +(call + arguments: (argument_list + (keyword_argument + name: (identifier) @name + value: (_) @val) @arg) @args) @call +{ + edge @args -> @arg.arg_name + attr @arg.arg_name "pop" = @name + edge @arg.arg_name -> @val.output +} + +(argument_list + (expression) @arg) @args +{ + edge @args -> @arg.arg_index + attr @arg.arg_index "pop" = (child-index @arg) + edge @arg.arg_index -> @arg.output +} + +( + (call + function: (identifier) @fn-name) @call + (#eq? @fn-name "super") +) +{ + edge @call.output -> @call::super_scope +} + +[ + (tuple (_) @element) + (expression_list (_) @element) +] @tuple +{ + edge @tuple.output -> @element.el_index + attr @element.el_index "pop" = (child-index @element) + edge @element.el_index -> @element.output + + edge @tuple.new_bindings -> @element.new_bindings +} + +(attribute + object: (_) @object + attribute: (identifier) @name) @expr +{ + edge @expr.output -> @name.output + edge @name.output -> @expr.output_dot + edge @expr.output_dot -> @object.output + edge @object.input -> @expr.input_dot + edge @expr.input_dot -> @name.input + edge @name.input -> @expr.input + attr @expr.output_dot "push" = "." + attr @expr.input_dot "pop" = "." + attr @name.input "pop" + attr @name.output "push" +} + +(pattern/attribute + attribute: (identifier) @name) +{ + attr @name.input "definition" +} + +(primary_expression/attribute + attribute: (identifier) @name) +{ + attr @name.output "reference" +} + +(primary_expression/identifier) @id +{ + edge @id.output -> @id::local_scope + edge @id.output -> @id::class_parent_scope + edge @id::local_scope -> @id.input + attr @id.input "pop" + attr @id.output "push", "reference" + + attr @id.new_binding_pop "pop", "definition" + edge @id.new_bindings -> @id.new_binding_pop +} + +(pattern/identifier) @id +{ + edge @id.output -> @id::local_scope + edge @id.output -> @id::class_parent_scope + edge @id::local_scope -> @id.input, "precedence" = 1 + attr @id.input "pop", "definition" + attr @id.output "push" + + attr @id.new_binding_pop "pop", "definition" + edge @id.new_bindings -> @id.new_binding_pop +} + +(as_pattern + (expression) @value + alias: (as_pattern_target (primary_expression/identifier) @id)) @as_pattern +{ + edge @id.output -> @id::local_scope + edge @id.output -> @id::class_parent_scope + edge @id::local_scope -> @id.input, "precedence" = 1 + attr @id.input "pop", "definition" + attr @id.output "push" + + edge @as_pattern.new_bindings -> @value.new_bindings + edge @as_pattern.new_bindings -> @id.new_bindings +} + +(list) @list +{ + edge @list.output -> @list.called + edge @list.called -> @list::global_dot + attr @list.called "push" = "list" +} + +(list (_) @el) @list +{ + edge @list.new_bindings -> @el.new_bindings +} + +(dictionary (pair) @pair) @dict +{ + edge @dict.new_bindings -> @pair.new_bindings +} + +(pair + value: (_) @value) @pair +{ + edge @pair.new_bindings -> @value.new_bindings +} + +(set (_) @el) @set +{ + edge @set.new_bindings -> @el.new_bindings +} + +(list_splat (_) @splatted) @splat +{ +attr @splat.new_bindings_pop "pop" = @splatted, "definition" +edge @splat.new_bindings -> @splat.new_bindings_pop +} + +(binary_operator + (_) @left + (_) @right) @binop +{ + edge @binop.new_bindings -> @left.new_bindings + edge @binop.new_bindings -> @right.new_bindings +} + +(case_pattern (_) @expr) @pat +{ + edge @pat.new_bindings -> @expr.new_bindings +} diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/aliased_imports.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/aliased_imports.py new file mode 100644 index 000000000..d988757a5 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/aliased_imports.py @@ -0,0 +1,31 @@ +#------ path: foo.py ------# + +# module +class A: + a = 1 + +class B: + class C: + class D: + d = 2 + +#------ path: main.py ---# + +from foo import A as X, B.C.D as Y +import foo as f + +print X.a, Y.d +# ^ defined: 5 +# ^ defined: 10 + +print A, B.C +# ^ defined: +# ^ defined: +# ^ defined: + +print f.B +# ^ defined: 2, 15 +# ^ defined: 7 + +print foo +# ^ defined: diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/attributes.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/attributes.py new file mode 100644 index 000000000..6dd3d0e48 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/attributes.py @@ -0,0 +1,14 @@ +a = 1 + +a.b = 2 + +a.c.d = 5 + +print a.b +# ^ defined: 1 +# ^ defined: 3 + +print a.c, a.c.d +# ^ defined: 1 +# ^ defined: +# ^ defined: 5 diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/blocks.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/blocks.py new file mode 100644 index 000000000..462890baf --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/blocks.py @@ -0,0 +1,21 @@ +def f(): + if a: + b = 1 + else: + c = 2 + + print b, c + # ^ defined: 3 + # ^ defined: 5 + +class G: + if d: + e = 1 + + print e + # ^ defined: 13 + +print b, c, e +# ^ defined: +# ^ defined: +# ^ defined: diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/chained_functions.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/chained_functions.py new file mode 100644 index 000000000..ef1dac21d --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/chained_functions.py @@ -0,0 +1,23 @@ +class A: + w = 1 + x = 2 + y = 3 + z = 4 + +def get_a(): + return A +def get_b(): + return get_a() +def get_c(): + return get_b() +def get_d(): + return get_c() +def get_e(): + return get_d() +def get_f(): + return get_e() + +g = get_f(A) +print g.x, g.y +# ^ defined: 3 +# ^ defined: 4 diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/chained_methods.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/chained_methods.py new file mode 100644 index 000000000..9c4f53115 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/chained_methods.py @@ -0,0 +1,27 @@ +class Builder: + def set_a(self, a): + self.a = a + return self + + def set_b(self, b): + self.b = b + return self + + def set_c(self, c): + self.c = c + return self + + def set_d(self, d): + self.d = d + return self + + def set_e(self, e): + self.d = d + return self + +Builder().set_a('a1').set_b('b2').set_c('c3').set_d('d4').set_e('e4') +# ^ defined: 2 +# ^ defined: 6 +# ^ defined: 10 +# ^ defined: 14 +# ^ defined: 18 diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/class_members.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/class_members.py new file mode 100644 index 000000000..c67ace992 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/class_members.py @@ -0,0 +1,23 @@ +a = 1 + +class B: + c = a + # ^ defined: 1 + + def d(self): + return self.c + + class E: + f = a + # ^ defined: 1 + +print B.c +# ^ defined: 3 +# ^ defined: 1, 4 + +print B.d(1) +# ^ defined: 7 + +print B.a, E.a +# ^ defined: +# ^ defined: diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/decorators.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/decorators.py new file mode 100644 index 000000000..b55f44b2f --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/decorators.py @@ -0,0 +1,10 @@ +from a import deprecated +from b import ignore_warnings + +class A: + @deprecated + # ^ defined: 1 + @ignore_warnings.all + # ^ defined: 2 + def b(self): + pass diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/exceptions.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/exceptions.py new file mode 100644 index 000000000..b6b2e57e1 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/exceptions.py @@ -0,0 +1,5 @@ +try: + print() +except Exception as e: + x = e + # ^ defined: 3 diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/functions.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/functions.py new file mode 100644 index 000000000..31a1d6782 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/functions.py @@ -0,0 +1,31 @@ +import a.x.y +import b.x.y + +def get_x(value): + return value.x + # ^ defined: 4 + +print get_x(a).y +# ^ defined: 1 + +print get_x(b).y +# ^ defined: 2 + +def get_a(): + return a + +print get_a(b).x +# ^ defined: 1 + +print get_x(foo=1, value=a).y +# ^ defined: 1 + +def foo(w: int, x, y=1, z: int=4, *args, **dict): + local = x +# ^ defined: 23 + print(args, w, z) +# ^ defined: 23 +# ^ defined: 23 +# ^ defined: 23 + return y +# ^ defined: 23 diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/imported_functions.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/imported_functions.py new file mode 100644 index 000000000..495697740 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/imported_functions.py @@ -0,0 +1,17 @@ +#------ path: a.py ------# + +def foo(x): + return x + +#------ path: b.py ------# + +class A: + bar = 1 + +#------ path: main.py ---------# + +from a import * +from b import * + +foo(A).bar +# ^ defined: 9 diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/imports.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/imports.py new file mode 100644 index 000000000..2f21795da --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/imports.py @@ -0,0 +1,31 @@ +#------ path: one/two.py -----------# + +# module +import a.b.c + +d = 1 + +e = a.b + +#------ path: three/__init__.py ---# + +# module +f = 3 + +#------ path: main.py -------------# + +from one.two import d, e.c +# ^ defined: 2 +# ^ defined: 6, 17 +# ^ defined: 4, 8, 17 + +import three +# ^ defined: 11, 22 + +print(d, e.c) +# ^ defined: 6, 17 +# ^ defined: 4, 17 + +print three.f +# ^ defined: 11, 22 +# ^ defined: 13 diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/instance_members.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/instance_members.py new file mode 100644 index 000000000..38a6b6d75 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/instance_members.py @@ -0,0 +1,38 @@ +#---- path: a.py ------- + +class A: + def __init__(self, b, c): + self.b = b + self.c = A(c, 1) + + def get_b(self): + return self.b + # ^ defined: 4, 5 + + def get_c(self): + return self.c + # ^ defined: 6 + + def get_all(self): + return [self.get_b(), self.get_c()] + # ^ defined: 8 + # ^ defined: 12 + +a = A(1, 2) +a.get_all() +# ^ defined: 16 + +a.b +# ^ defined: 4, 5 + +a.c.b +# ^ defined: 4, 5 +# ^ defined: 6 + +#----- path: main.py --------- + +import a + +print a.A, a.a +# ^ defined: 3 +# ^ defined: 21 diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/loops.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/loops.py new file mode 100644 index 000000000..2f0663295 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/loops.py @@ -0,0 +1,19 @@ +class Node3: + value = 3 +class Node2: + value = 2 + next = Node3 +class Node1: + value = 1 + next = Node2 + +def linked_list_search(l, item): + node = l + while node: + if node.value == item: + return node + # ^ defined: 10, 11, 16 + node = node.next + +linked_list_search(Node1, 5).value +# ^ defined: 6 diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/many_definitions.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/many_definitions.py new file mode 100644 index 000000000..f85f3a8ec --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/many_definitions.py @@ -0,0 +1,76 @@ +#--- path: a.py ---# + +def f0(a): return X.a + X.b +def f1(a): return f0(1) +def f2(a): return f1(2) +def f3(a): return f2(3) +def f4(a): return f3(4) +def f5(a): return f4(5) +def f6(a): return f5(6) +def f7(a): return f6(7) +def f8(a): return f7(8) +def f9(a): return f8(9) + +class C1: + def m0(self, b): return f9(0) + def m1(self, b): return self.m0(1) + def m2(self, b): return self.m1(2) + def m3(self, b): return self.m2(3) + def m4(self, b): return self.m3(4) + def m5(self, b): return self.m4(5) + def m6(self, b): return self.m5(6) + def m7(self, b): return self.m6(7) + def m8(self, b): return self.m7(8) + +def f10(): return C1.m8(0) +def f11(): return f10(1) +def f12(): return X.c(2) +def f13(): return X.c(3) +def f14(): return x(4) +def f15(): return x(5) +def f16(): return x(6) +def f17(): return x(7) +def f18(): return x(8) + +class C2: + def m0(self): return X.d(0) + def m1(self): return X.d(1) + def m2(self): return X.d(2) + def m3(self): return X.d(3) + def m4(self): return X.d(4) + def m5(self): return X.d(5) + def m6(self): return X.d(6) + def m7(self): return X.d(7) + def m8(self): return X.d(8) + +#--- path: main.py ---# + +from a import * + +print f0(), f4(), f8() +# ^ defined: 3 +# ^ defined: 7 +# ^ defined: 11 + +print C1.m0, C1().m0(), C1.m4, C1().m4, C1.m8, C1.m8 +# ^ defined: 14 +# ^ defined: 15 +# ^ defined: 15 +# ^ defined: 19 +# ^ defined: 19 +# ^ defined: 23 +# ^ defined: 23 + +print f10(), f14(), f18() +# ^ defined: 25 +# ^ defined: 29 +# ^ defined: 33 + +print C2.m0, C2().m0(), C2.m4, C2().m4, C2.m8, C2.m8 +# ^ defined: 35 +# ^ defined: 36 +# ^ defined: 36 +# ^ defined: 40 +# ^ defined: 40 +# ^ defined: 44 +# ^ defined: 44 diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/pattern_matching.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/pattern_matching.py new file mode 100644 index 000000000..58c0d16fc --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/pattern_matching.py @@ -0,0 +1,39 @@ +command = 1 +current_room = 2 +character = 3 + +match command.split(): + # ^ defined: 1 + case ["quit"]: + print("Goodbye!") + quit_game() + case ["look"]: + current_room.describe() + # ^ defined: 2 + case ["get", obj]: + character.get(obj, current_room) + # ^ defined: 3 + # ^ defined: 13 + # ^ defined: 2 + case ["go", direction]: + current_room = current_room.neighbor(direction) + # ^ defined: 18 + case { "foo": foo }: + print(foo) + # ^ defined: 21 + case {bar,quux}: + print(bar,quux) + # ^ defined: 24 + # ^ defined: 24 + case ["grab", { "key": {garply}}]: + print(garply) + # ^ defined: 28 + case ["drop", *objs]: + print(objs) + # ^ defined: 31 + case ["get", obj] | ["pick", "up", obj] | ["pick", obj, "up"]: + print(obj) + # ^ defined: 34, 34, 34 + case ["go", ("north" | "south" | "east" | "west") as direction2]: + current_room = current_room.neighbor(direction2) + # ^ defined: 37 diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/redundant_reexport.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/redundant_reexport.py new file mode 100644 index 000000000..53afca29e --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/redundant_reexport.py @@ -0,0 +1,15 @@ +#--- path: a/__init__.py ---# + +from . import child + +#--- path: a/child.py ---- + +def f(): + pass + +#--- path: main.py ---# + +import a + +print a.child.f() +# ^ defined: 7 diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/relative_imports.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/relative_imports.py new file mode 100644 index 000000000..2d6e14eb4 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/relative_imports.py @@ -0,0 +1,60 @@ +#------ path: foo/bar/main.py ------# + +from . import a +from .b import B +from ..c import see +from ..c.d import D + +print a.A +# ^ defined: 3, 24 +# ^ defined: 26 + +print B.bee +# ^ defined: 4, 31 +# ^ defined: 32 + +print see() +# ^ defined: 5, 37 + + +print D.d +# ^ defined: 44 + +#------ path: foo/bar/a.py --------# + +# module +A = "a" + +#------ path: foo/bar/b.py --------# + +# module +class B: + bee = 1 + +#------ path: foo/c.py ------------# + +# module +def see(): + pass + +#------ path: foo/c/d.py ---------# + +# module +class D: + d = "d" + +#------ path: foo/e/g.py ---# + +# module +G = 1 + +#------ path: foo/e/__init__.py ---# + +# module +from .g import G +# ^ defined: 49, 54 + +from ..c import see +# ^ defined: 37, 57 + +E = 1 diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/statement_bindings.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/statement_bindings.py new file mode 100644 index 000000000..6e3a13abb --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/statement_bindings.py @@ -0,0 +1,9 @@ +import a.b +import c.d + +with a as x, c as y: + print x.b, y.d + # ^ defined: 1, 4 + # ^ defined: 1 + # ^ defined: 2, 4 + # ^ defined: 2 diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/superclasses.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/superclasses.py new file mode 100644 index 000000000..849a192a6 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/superclasses.py @@ -0,0 +1,19 @@ +class A: + def __init__(self): + self.some_attr = 2 + + def some_method(self): + print self + +class B(A): + def method2(self): + print self.some_attr, self.some_method() + # ^ defined: 3 + # ^ defined: 5, 14 + + def some_method(self): + pass + + def other(self): + super().some_method() + # ^ defined: 5 diff --git a/languages/tree-sitter-stack-graphs-python/test/test.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/test.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/test.py rename to languages/tree-sitter-stack-graphs-python/test/legacy.skip/test.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/tuples.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/tuples.py new file mode 100644 index 000000000..1ea6ee3ef --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/tuples.py @@ -0,0 +1,38 @@ +class a: + x = 1 +class b: + x = 1 +class c: + x = 1 + +(a1, b1) = (a, b) +a2, b2 = (a, b) +(a3, b3) = (a, b) +a4, b4 = a, b + +print a1.x, b1.x +# ^ defined: 2 +# ^ defined: 4 +print a2.x, b2.x +# ^ defined: 2 +# ^ defined: 4 +print a3.x, b3.x +# ^ defined: 2 +# ^ defined: 4 +print a4.x, b4.x +# ^ defined: 2 +# ^ defined: 4 + +t = (a, b), c +(a5, b5), c5 = t + +print a5.x, b5.x, c5.x +# ^ defined: 2 +# ^ defined: 4 +# ^ defined: 6 + +(a6, (b6, c6)) = (a, (b, c)) + +print a6.x, b6.x +# ^ defined: 2 +# ^ defined: 4 diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/wildcard_import.py b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/wildcard_import.py new file mode 100644 index 000000000..f2ac040f2 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/legacy.skip/wildcard_import.py @@ -0,0 +1,21 @@ +#------ path: one/two.py ------# + +a = 1 +b = 2 + +#------ path: one/three.py ------# + +b = 3 +c = 4 + +#------ path: main.py ---------# + +from one.two import * +from one.three import * + +print a +# ^ defined: 3 +print b +# ^ defined: 8 +print c +# ^ defined: 9 From decf584c173adcfc038b3f8c398c0025715832bf Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 09:42:41 +0200 Subject: [PATCH 317/500] convert: copy old --- .../src/stack-graphs.tsg | 770 +++++++++++++++++- 1 file changed, 767 insertions(+), 3 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 99647e75b..99fd0acaf 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -36,7 +36,771 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol attribute node_symbol = node => symbol = (source-text node), source_node = node -;; Stack Graph Rules -;; ^^^^^^^^^^^^^^^^^ +; Modules and Imports +;--------------------- -; Have fun! +(module) @mod +{ + var module_def = @mod.file_def + attr module_def "no_span" + var module_ref = @mod.file_ref + attr module_ref "no_span" + var parent_module_def = module_def + var parent_module_ref = module_ref + var grandparent_module_ref = module_ref + + scan filepath { + "([^/]+)/" + { + edge module_def -> module_def.dot + edge module_def.dot -> module_def.next_def + edge module_ref.next_ref -> module_ref.dot + edge module_ref.dot -> module_ref + + attr module_def "pop" = $1 + attr module_def.dot "pop" = "." + attr module_ref "push" = $1 + attr module_ref.dot "push" = "." + + set grandparent_module_ref = parent_module_ref + set parent_module_def = module_def + set parent_module_ref = module_ref + set module_ref = module_ref.next_ref + set module_def = module_def.next_def + attr module_def "no_span" + attr module_ref "no_span" + } + + "__init__\\.py$" + { + attr parent_module_def "definition" + } + + "([^/]+)$" + { + edge module_def -> module_def.dot + edge module_def.dot -> module_def.next_def + + attr module_def "definition", "pop" = (replace $1 "\\.py" "") + attr module_def.dot "pop" = "." + + set module_def = module_def.next_def + attr module_def "no_span" + attr module_ref "no_span" + } + } + + edge root -> @mod.file_def + edge @mod.file_ref -> root + edge module_def -> @mod.after_scope + + edge @mod.before_scope -> @mod.global_dot + edge @mod.global -> root + attr @mod.global "push" = "" + + edge @mod.global_dot -> @mod.global + attr @mod.global_dot "push" = "." + + var @mod::parent_module = parent_module_ref + var @mod::grandparent_module = grandparent_module_ref + var @mod::bottom = @mod.after_scope + var @mod::global = @mod.global + var @mod::global_dot = @mod.global_dot +} + +(import_statement + name: (dotted_name + . (identifier) @root_name)) @stmt +{ + edge @stmt.after_scope -> @root_name.def, "precedence" = 1 + edge @root_name.ref -> root + attr @root_name.ref "push", "reference" + attr @root_name.def "pop", "definition" +} + +(import_statement + name: (aliased_import + (dotted_name . (identifier) @root_name))) @stmt +{ + edge @stmt.after_scope -> @root_name.def + edge @root_name.ref -> root + attr @root_name.ref "push", "reference" +} + +(import_from_statement + module_name: (dotted_name + . (identifier) @prefix_root_name)) @stmt +{ + edge @prefix_root_name.ref -> root + attr @prefix_root_name.ref "push", "reference" +} + +(import_from_statement + name: (dotted_name + . (identifier) @import_root_name)) @stmt +{ + edge @stmt.after_scope -> @import_root_name.def, "precedence" = 1 + edge @import_root_name.ref -> @import_root_name.ref_dot + attr @import_root_name.def "pop", "definition" + attr @import_root_name.ref "push", "reference" + attr @import_root_name.ref_dot "push" = "." +} + +(import_from_statement + name: (aliased_import + (dotted_name + . (identifier) @import_root_name))) @stmt +{ + edge @import_root_name.ref -> @import_root_name.ref_dot + attr @import_root_name.ref "push", "reference" + attr @import_root_name.ref_dot "push" = "." +} + +(import_from_statement + module_name: [ + (dotted_name (identifier) @prefix_leaf_name .) + (relative_import (dotted_name (identifier) @prefix_leaf_name .)) + (relative_import (import_prefix) @prefix_leaf_name .) + ] + name: [ + (dotted_name + . (identifier) @import_root_name) + (aliased_import + (dotted_name + . (identifier) @import_root_name)) + ]) +{ + edge @import_root_name.ref_dot -> @prefix_leaf_name.ref +} + +[ + (import_from_statement + (aliased_import + name: (dotted_name (identifier) @name .) + alias: (identifier) @alias)) + (import_statement + (aliased_import + name: (dotted_name (identifier) @name .) + alias: (identifier) @alias)) +] @stmt +{ + edge @stmt.after_scope -> @alias + edge @alias -> @name.ref + attr @alias "pop", "definition" +} + +[ + (import_statement + name: (dotted_name + (identifier) @leaf_name .)) + (import_from_statement + name: (dotted_name + (identifier) @leaf_name .)) +] +{ + attr @leaf_name.def "pop", "definition" + attr @leaf_name.ref "push", "reference" + edge @leaf_name.def -> @leaf_name.ref +} + +(relative_import + (import_prefix) @prefix + (#eq? @prefix ".")) @import +{ + edge @prefix.ref -> @import::parent_module +} + +(relative_import + (import_prefix) @prefix + (#eq? @prefix "..")) @import +{ + edge @prefix.ref -> @import::grandparent_module +} + +(relative_import + (import_prefix) @prefix + (dotted_name + . (identifier) @name)) +{ + attr @name.ref "push", "reference" + attr @name.ref_dot "push" = "." + edge @name.ref -> @name.ref_dot + edge @name.ref_dot -> @prefix.ref +} + +[ + (import_from_statement + module_name: (relative_import + (dotted_name + (identifier) @parent_name + . + (identifier) @child_name))) + (import_from_statement + module_name: (dotted_name + (identifier) @parent_name + . + (identifier) @child_name)) +] +{ + attr @child_name.ref "push", "reference" + attr @child_name.ref_dot "push" = "." + edge @child_name.ref -> @child_name.ref_dot + edge @child_name.ref_dot -> @parent_name.ref +} + +(import_from_statement + module_name: (dotted_name + . (identifier) @root_name)) +{ + attr @root_name.ref "push", "reference" + edge @root_name.ref -> root +} + +(import_from_statement + module_name: (dotted_name + (identifier) @leaf_name .) + (wildcard_import) @star) @stmt +{ + edge @stmt.after_scope -> @star.ref_dot, "precedence" = 1 + edge @star.ref_dot -> @leaf_name.ref + attr @star.ref_dot "push" = "." +} + +[ + (import_statement + name: (dotted_name + (identifier) @parent_name + . + (identifier) @child_name)) + (import_from_statement + name: (dotted_name + (identifier) @parent_name + . + (identifier) @child_name)) + (import_from_statement + name: (aliased_import + name: (dotted_name + (identifier) @parent_name + . + (identifier) @child_name))) +] +{ + edge @child_name.ref -> @child_name.ref_dot + edge @child_name.ref_dot -> @parent_name.ref + edge @parent_name.def -> @parent_name.def_dot + edge @parent_name.def_dot -> @child_name.def + attr @child_name.def "pop", "definition" + attr @child_name.ref "push","reference" + attr @parent_name.def_dot "pop" = "." + attr @child_name.ref_dot "push" = "." +} + +;-------- +; Scopes +;-------- + +[ + (module (_) @last_stmt .) + (block (_) @last_stmt .) +] @block +{ + edge @block.after_scope -> @last_stmt.after_scope +} + +[ + (module (_) @stmt1 . (_) @stmt2) + (block (_) @stmt1 . (_) @stmt2) +] +{ + edge @stmt2.before_scope -> @stmt1.after_scope +} + +[ + (module (_) @stmt) + (block (_) @stmt) +] +{ + edge @stmt.after_scope -> @stmt.before_scope + let @stmt::local_scope = @stmt.before_scope +} + +[ + (block . (_) @stmt) + (module . (_) @stmt) +] @block +{ + edge @stmt.before_scope -> @block.before_scope +} + +(block (_) @stmt . ) @block +{ + edge @block.after_scope -> @stmt.after_scope +} + +(function_definition (block) @block) +{ + edge @block.before_scope -> @block::local_scope +} + +[ + (while_statement (block) @block) + (if_statement (block) @block) + (with_statement (block) @block) + (try_statement (block) @block) + (for_statement (block) @block) + (_ [ + (else_clause (block) @block) + (elif_clause (block) @block) + (except_clause (block) @block) + (finally_clause (block) @block) + ]) +] @stmt +{ + edge @block.before_scope -> @block::local_scope + edge @stmt.after_scope -> @block.after_scope +} + +(match_statement (case_clause) @block) @stmt +{ + let @block::local_scope = @block.before_scope + edge @block.before_scope -> @stmt.before_scope + edge @stmt.after_scope -> @block.after_scope +} + +[ + (for_statement) + (while_statement) +] @stmt +{ + edge @stmt.before_scope -> @stmt.after_scope +} + +;------------- +; Definitions +;------------- + +[ + (assignment + left: (_) @pattern + right: (_) @value) + (with_item + value: + (as_pattern + (_) @value + alias: (as_pattern_target (_) @pattern))) +] +{ + edge @pattern.input -> @value.output +} + +(function_definition + name: (identifier) @name + parameters: (parameters) @params + body: (block) @body) @func +{ + attr @name "definiens" = @func + edge @func.after_scope -> @name + edge @name -> @func.call + edge @func.call -> @func.return_value + edge @body.before_scope -> @params.after_scope + edge @body.before_scope -> @func.drop_scope + edge @func.drop_scope -> @func::bottom + attr @func.drop_scope "drop" + attr @name "pop", "definition" + attr @func.call "pop" = "()", "pop-scope" + attr @params.before_scope "jump-to" + attr @func.return_value "endpoint" + let @func::function_returns = @func.return_value + + ; Prevent functions defined inside of method bodies from being treated like methods + let @body::class_self_scope = nil + let @body::class_member_attr_scope = nil +} + +;; +;; BEGIN BIG GNARLY DISJUNCTION +;; +;; The following pair of rules is intended to capture the following behavior: +;; +;; If a function definition is used to define a method, by being inside a class +;; definition, then we make its syntax type `method`. Otherwise, we make it's +;; syntax type `function`. Unfortunately, because of the limitations on negation +;; and binding in tree sitter queries, we cannot negate `class_definition` or +;; similar things directly. Instead, we have to manually push the negation down +;; to form the finite disjunction it corresponds to. +;; + +[ + (class_definition (block (decorated_definition (function_definition name: (_)@name)))) + (class_definition (block (function_definition name: (_)@name))) +] +{ + attr @name "syntax_type" = "method" +} + +[ + (module (decorated_definition (function_definition name: (_)@name))) + (module (function_definition name: (_)@name)) + + (if_statement (block (decorated_definition (function_definition name: (_)@name)))) + (if_statement (block (function_definition name: (_)@name))) + + (elif_clause (block (decorated_definition (function_definition name: (_)@name)))) + (elif_clause (block (function_definition name: (_)@name))) + + (else_clause (block (decorated_definition (function_definition name: (_)@name)))) + (else_clause (block (function_definition name: (_)@name))) + + (case_clause (block (decorated_definition (function_definition name: (_)@name)))) + (case_clause (block (function_definition name: (_)@name))) + + (for_statement (block (decorated_definition (function_definition name: (_)@name)))) + (for_statement (block (function_definition name: (_)@name))) + + (while_statement (block (decorated_definition (function_definition name: (_)@name)))) + (while_statement (block (function_definition name: (_)@name))) + + (try_statement (block (decorated_definition (function_definition name: (_)@name)))) + (try_statement (block (function_definition name: (_)@name))) + + (except_clause (block (decorated_definition (function_definition name: (_)@name)))) + (except_clause (block (function_definition name: (_)@name))) + + (finally_clause (block (decorated_definition (function_definition name: (_)@name)))) + (finally_clause (block (function_definition name: (_)@name))) + + (with_statement (block (decorated_definition (function_definition name: (_)@name)))) + (with_statement (block (function_definition name: (_)@name))) + + (function_definition (block (decorated_definition (function_definition name: (_)@name)))) + (function_definition (block (function_definition name: (_)@name))) +] +{ + attr @name "syntax_type" = "function" +} + +;; +;; END BIG GNARLY DISJUNCTION +;; + +(function_definition + parameters: (parameters + . (identifier) @param) + body: (block) @body) +{ + edge @param.input -> @param::class_self_scope + edge @param::class_member_attr_scope -> @param.output + edge @param.output -> @body.after_scope + attr @param.output "push" +} + +(parameter/identifier) @param +{ + attr @param.input "definition", "pop" + attr @param.param_name "push" + edge @param.input -> @param.param_index + edge @param.input -> @param.param_name +} + +[ + (parameter/default_parameter + name: (identifier) @name + value: (_) @value) @param + (parameter/typed_default_parameter + name: (_) @name + value: (_) @value) @param +] +{ + attr @name "definition", "pop" + attr @param.param_name "push" = @name + edge @name -> @param.param_name + edge @name -> @param.param_index + edge @param.input -> @name + edge @name -> @value.output +} + +[ + (parameter/typed_parameter + . (_) @name) @param + (parameter/list_splat_pattern + (_) @name) @param + (parameter/dictionary_splat_pattern + (_) @name) @param +] +{ + attr @name "definition", "pop" + attr @param.param_name "push" = @name + edge @name -> @param.param_name + edge @name -> @param.param_index + edge @param.input -> @name +} + +[ + (pattern_list (_) @pattern) + (tuple_pattern (_) @pattern) +] @list +{ + let statement_scope = @list::local_scope + let @pattern::local_scope = @pattern.pattern_before_scope + edge statement_scope -> @pattern::local_scope, "precedence" = (+ 1 (child-index @pattern)) + + edge @pattern.pattern_index -> @list.input + edge @pattern.input -> @pattern.pattern_index + attr @pattern.pattern_index "push" = (child-index @pattern) +} + +(parameters + (_) @param) @params +{ + attr @param.param_index "push" = (child-index @param) + edge @param.param_index -> @params.before_scope + edge @params.after_scope -> @param.input + edge @param.param_name -> @params.before_scope +} + +(return_statement (_) @expr) @stmt +{ + edge @stmt::function_returns -> @expr.output +} + +(class_definition + name: (identifier) @name) @class +{ + attr @name "definiens" = @class + attr @name "syntax_type" = "class" + edge @class.parent_scope -> @class::class_parent_scope + edge @class.parent_scope -> @class::local_scope + edge @class.after_scope -> @name + edge @name -> @class.call + edge @name -> @class.dot + edge @class.dot -> @class.members + edge @class.call -> @class.call_drop + edge @class.call_drop -> @class.self_scope + edge @class.self_scope -> @class.super_scope + edge @class.self_scope -> @class.self_dot + edge @class.self_dot -> @class.members + edge @class.members -> @class.member_attrs + attr @class.call "pop" = "()", "pop-scope" + attr @class.call_drop "drop" + attr @class.dot "pop" = "." + attr @class.self_dot "pop" = "." + attr @name "pop", "definition" + attr @class.member_attrs "push" = "." + attr @class.self_scope "endpoint" + let @class::super_scope = @class.super_scope + let @class::class_parent_scope = @class.parent_scope + let @class::class_self_scope = @class.call_drop + let @class::class_member_attr_scope = @class.member_attrs +} + +(class_definition + body: (block + (_) @last_stmt .) @body) @class +{ + edge @class.members -> @last_stmt.after_scope +} + +(class_definition + superclasses: (argument_list + (_) @superclass)) @class +{ + edge @class.super_scope -> @superclass.output +} + +(decorated_definition + definition: (_) @def) @stmt +{ + edge @def.before_scope -> @stmt.before_scope + edge @stmt.after_scope -> @def.after_scope +} + +(case_clause + pattern: (_) @pattern + consequence: (_) @consequence) @clause +{ + edge @consequence.before_scope -> @pattern.new_bindings + edge @consequence.before_scope -> @clause.before_scope + edge @clause.after_scope -> @consequence.after_scope +} + +;------------- +; Expressions +;------------- + +(call + function: (_) @fn + arguments: (argument_list) @args) @call +{ + edge @call.output -> @call.output_args + edge @call.output_args -> @fn.output + attr @call.output_args "push" = "()", "push-scope" = @args +} + +(call + function: (attribute + object: (_) @receiver) + arguments: (argument_list + (expression) @arg) @args) +{ + edge @args -> @arg.arg_index + edge @receiver -> @receiver.arg_index + + attr @receiver.arg_index "pop" = "0" + edge @receiver.arg_index -> @receiver.output + + attr @arg.arg_index "pop" = (+ 1 (child-index @arg)) + edge @arg.arg_index -> @arg.output +} + +(call + arguments: (argument_list + (keyword_argument + name: (identifier) @name + value: (_) @val) @arg) @args) @call +{ + edge @args -> @arg.arg_name + attr @arg.arg_name "pop" = @name + edge @arg.arg_name -> @val.output +} + +(argument_list + (expression) @arg) @args +{ + edge @args -> @arg.arg_index + attr @arg.arg_index "pop" = (child-index @arg) + edge @arg.arg_index -> @arg.output +} + +( + (call + function: (identifier) @fn-name) @call + (#eq? @fn-name "super") +) +{ + edge @call.output -> @call::super_scope +} + +[ + (tuple (_) @element) + (expression_list (_) @element) +] @tuple +{ + edge @tuple.output -> @element.el_index + attr @element.el_index "pop" = (child-index @element) + edge @element.el_index -> @element.output + + edge @tuple.new_bindings -> @element.new_bindings +} + +(attribute + object: (_) @object + attribute: (identifier) @name) @expr +{ + edge @expr.output -> @name.output + edge @name.output -> @expr.output_dot + edge @expr.output_dot -> @object.output + edge @object.input -> @expr.input_dot + edge @expr.input_dot -> @name.input + edge @name.input -> @expr.input + attr @expr.output_dot "push" = "." + attr @expr.input_dot "pop" = "." + attr @name.input "pop" + attr @name.output "push" +} + +(pattern/attribute + attribute: (identifier) @name) +{ + attr @name.input "definition" +} + +(primary_expression/attribute + attribute: (identifier) @name) +{ + attr @name.output "reference" +} + +(primary_expression/identifier) @id +{ + edge @id.output -> @id::local_scope + edge @id.output -> @id::class_parent_scope + edge @id::local_scope -> @id.input + attr @id.input "pop" + attr @id.output "push", "reference" + + attr @id.new_binding_pop "pop", "definition" + edge @id.new_bindings -> @id.new_binding_pop +} + +(pattern/identifier) @id +{ + edge @id.output -> @id::local_scope + edge @id.output -> @id::class_parent_scope + edge @id::local_scope -> @id.input, "precedence" = 1 + attr @id.input "pop", "definition" + attr @id.output "push" + + attr @id.new_binding_pop "pop", "definition" + edge @id.new_bindings -> @id.new_binding_pop +} + +(as_pattern + (expression) @value + alias: (as_pattern_target (primary_expression/identifier) @id)) @as_pattern +{ + edge @id.output -> @id::local_scope + edge @id.output -> @id::class_parent_scope + edge @id::local_scope -> @id.input, "precedence" = 1 + attr @id.input "pop", "definition" + attr @id.output "push" + + edge @as_pattern.new_bindings -> @value.new_bindings + edge @as_pattern.new_bindings -> @id.new_bindings +} + +(list) @list +{ + edge @list.output -> @list.called + edge @list.called -> @list::global_dot + attr @list.called "push" = "list" +} + +(list (_) @el) @list +{ + edge @list.new_bindings -> @el.new_bindings +} + +(dictionary (pair) @pair) @dict +{ + edge @dict.new_bindings -> @pair.new_bindings +} + +(pair + value: (_) @value) @pair +{ + edge @pair.new_bindings -> @value.new_bindings +} + +(set (_) @el) @set +{ + edge @set.new_bindings -> @el.new_bindings +} + +(list_splat (_) @splatted) @splat +{ +attr @splat.new_bindings_pop "pop" = @splatted, "definition" +edge @splat.new_bindings -> @splat.new_bindings_pop +} + +(binary_operator + (_) @left + (_) @right) @binop +{ + edge @binop.new_bindings -> @left.new_bindings + edge @binop.new_bindings -> @right.new_bindings +} + +(case_pattern (_) @expr) @pat +{ + edge @pat.new_bindings -> @expr.new_bindings +} From edfe903f0f5b976fd08d490e9ffe1925ea724ed0 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 09:42:59 +0200 Subject: [PATCH 318/500] convert: attr syntax --- .../src/stack-graphs.tsg | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 99fd0acaf..5aed50404 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -42,9 +42,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n (module) @mod { var module_def = @mod.file_def - attr module_def "no_span" + attr (module_def) "no_span" var module_ref = @mod.file_ref - attr module_ref "no_span" + attr (module_ref) "no_span" var parent_module_def = module_def var parent_module_ref = module_ref var grandparent_module_ref = module_ref @@ -57,9 +57,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge module_ref.next_ref -> module_ref.dot edge module_ref.dot -> module_ref - attr module_def "pop" = $1 + attr (module_def) "pop" = $1 attr module_def.dot "pop" = "." - attr module_ref "push" = $1 + attr (module_ref) "push" = $1 attr module_ref.dot "push" = "." set grandparent_module_ref = parent_module_ref @@ -67,13 +67,13 @@ attribute node_symbol = node => symbol = (source-text node), source_n set parent_module_ref = module_ref set module_ref = module_ref.next_ref set module_def = module_def.next_def - attr module_def "no_span" - attr module_ref "no_span" + attr (module_def) "no_span" + attr (module_ref) "no_span" } "__init__\\.py$" { - attr parent_module_def "definition" + attr (parent_module_def) "definition" } "([^/]+)$" @@ -81,12 +81,12 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge module_def -> module_def.dot edge module_def.dot -> module_def.next_def - attr module_def "definition", "pop" = (replace $1 "\\.py" "") + attr (module_def) "definition", "pop" = (replace $1 "\\.py" "") attr module_def.dot "pop" = "." set module_def = module_def.next_def - attr module_def "no_span" - attr module_ref "no_span" + attr (module_def) "no_span" + attr (module_ref) "no_span" } } From 58c67fd2dbc806ebb331c6a26deb1f45ec1bf871 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 09:43:51 +0200 Subject: [PATCH 319/500] convert: no_span --- .../src/stack-graphs.tsg | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 5aed50404..afe702317 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -42,9 +42,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n (module) @mod { var module_def = @mod.file_def - attr (module_def) "no_span" + attr (module_def) empty_source_span var module_ref = @mod.file_ref - attr (module_ref) "no_span" + attr (module_ref) empty_source_span var parent_module_def = module_def var parent_module_ref = module_ref var grandparent_module_ref = module_ref @@ -67,8 +67,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n set parent_module_ref = module_ref set module_ref = module_ref.next_ref set module_def = module_def.next_def - attr (module_def) "no_span" - attr (module_ref) "no_span" + attr (module_def) empty_source_span + attr (module_ref) empty_source_span } "__init__\\.py$" @@ -85,8 +85,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr module_def.dot "pop" = "." set module_def = module_def.next_def - attr (module_def) "no_span" - attr (module_ref) "no_span" + attr (module_def) empty_source_span + attr (module_ref) empty_source_span } } From a830ef55ab2b304f3d59c438d1ba1dfcf942537e Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 09:48:03 +0200 Subject: [PATCH 320/500] convert: more attr syntax --- .../src/stack-graphs.tsg | 150 +++++++++--------- 1 file changed, 75 insertions(+), 75 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index afe702317..f6d557b50 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -58,9 +58,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge module_ref.dot -> module_ref attr (module_def) "pop" = $1 - attr module_def.dot "pop" = "." + attr (module_def.dot) "pop" = "." attr (module_ref) "push" = $1 - attr module_ref.dot "push" = "." + attr (module_ref.dot) "push" = "." set grandparent_module_ref = parent_module_ref set parent_module_def = module_def @@ -82,7 +82,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge module_def.dot -> module_def.next_def attr (module_def) "definition", "pop" = (replace $1 "\\.py" "") - attr module_def.dot "pop" = "." + attr (module_def.dot) "pop" = "." set module_def = module_def.next_def attr (module_def) empty_source_span @@ -96,10 +96,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @mod.before_scope -> @mod.global_dot edge @mod.global -> root - attr @mod.global "push" = "" + attr (@mod.global) "push" = "" edge @mod.global_dot -> @mod.global - attr @mod.global_dot "push" = "." + attr (@mod.global_dot) "push" = "." var @mod::parent_module = parent_module_ref var @mod::grandparent_module = grandparent_module_ref @@ -114,8 +114,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n { edge @stmt.after_scope -> @root_name.def, "precedence" = 1 edge @root_name.ref -> root - attr @root_name.ref "push", "reference" - attr @root_name.def "pop", "definition" + attr (@root_name.ref) "push", "reference" + attr (@root_name.def) "pop", "definition" } (import_statement @@ -124,7 +124,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n { edge @stmt.after_scope -> @root_name.def edge @root_name.ref -> root - attr @root_name.ref "push", "reference" + attr (@root_name.ref) "push", "reference" } (import_from_statement @@ -132,7 +132,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n . (identifier) @prefix_root_name)) @stmt { edge @prefix_root_name.ref -> root - attr @prefix_root_name.ref "push", "reference" + attr (@prefix_root_name.ref) "push", "reference" } (import_from_statement @@ -141,9 +141,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n { edge @stmt.after_scope -> @import_root_name.def, "precedence" = 1 edge @import_root_name.ref -> @import_root_name.ref_dot - attr @import_root_name.def "pop", "definition" - attr @import_root_name.ref "push", "reference" - attr @import_root_name.ref_dot "push" = "." + attr (@import_root_name.def) "pop", "definition" + attr (@import_root_name.ref) "push", "reference" + attr (@import_root_name.ref_dot) "push" = "." } (import_from_statement @@ -152,8 +152,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n . (identifier) @import_root_name))) @stmt { edge @import_root_name.ref -> @import_root_name.ref_dot - attr @import_root_name.ref "push", "reference" - attr @import_root_name.ref_dot "push" = "." + attr (@import_root_name.ref) "push", "reference" + attr (@import_root_name.ref_dot) "push" = "." } (import_from_statement @@ -186,7 +186,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n { edge @stmt.after_scope -> @alias edge @alias -> @name.ref - attr @alias "pop", "definition" + attr (@alias) "pop", "definition" } [ @@ -198,8 +198,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n (identifier) @leaf_name .)) ] { - attr @leaf_name.def "pop", "definition" - attr @leaf_name.ref "push", "reference" + attr (@leaf_name.def) "pop", "definition" + attr (@leaf_name.ref) "push", "reference" edge @leaf_name.def -> @leaf_name.ref } @@ -222,8 +222,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n (dotted_name . (identifier) @name)) { - attr @name.ref "push", "reference" - attr @name.ref_dot "push" = "." + attr (@name.ref) "push", "reference" + attr (@name.ref_dot) "push" = "." edge @name.ref -> @name.ref_dot edge @name.ref_dot -> @prefix.ref } @@ -242,8 +242,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n (identifier) @child_name)) ] { - attr @child_name.ref "push", "reference" - attr @child_name.ref_dot "push" = "." + attr (@child_name.ref) "push", "reference" + attr (@child_name.ref_dot) "push" = "." edge @child_name.ref -> @child_name.ref_dot edge @child_name.ref_dot -> @parent_name.ref } @@ -252,7 +252,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n module_name: (dotted_name . (identifier) @root_name)) { - attr @root_name.ref "push", "reference" + attr (@root_name.ref) "push", "reference" edge @root_name.ref -> root } @@ -263,7 +263,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n { edge @stmt.after_scope -> @star.ref_dot, "precedence" = 1 edge @star.ref_dot -> @leaf_name.ref - attr @star.ref_dot "push" = "." + attr (@star.ref_dot) "push" = "." } [ @@ -289,10 +289,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @child_name.ref_dot -> @parent_name.ref edge @parent_name.def -> @parent_name.def_dot edge @parent_name.def_dot -> @child_name.def - attr @child_name.def "pop", "definition" - attr @child_name.ref "push","reference" - attr @parent_name.def_dot "pop" = "." - attr @child_name.ref_dot "push" = "." + attr (@child_name.def) "pop", "definition" + attr (@child_name.ref) "push","reference" + attr (@parent_name.def_dot) "pop" = "." + attr (@child_name.ref_dot) "push" = "." } ;-------- @@ -398,18 +398,18 @@ attribute node_symbol = node => symbol = (source-text node), source_n parameters: (parameters) @params body: (block) @body) @func { - attr @name "definiens" = @func + attr (@name) "definiens" = @func edge @func.after_scope -> @name edge @name -> @func.call edge @func.call -> @func.return_value edge @body.before_scope -> @params.after_scope edge @body.before_scope -> @func.drop_scope edge @func.drop_scope -> @func::bottom - attr @func.drop_scope "drop" - attr @name "pop", "definition" - attr @func.call "pop" = "()", "pop-scope" - attr @params.before_scope "jump-to" - attr @func.return_value "endpoint" + attr (@func.drop_scope) "drop" + attr (@name) "pop", "definition" + attr (@func.call) "pop" = "()", "pop-scope" + attr (@params.before_scope) "jump-to" + attr (@func.return_value) "endpoint" let @func::function_returns = @func.return_value ; Prevent functions defined inside of method bodies from being treated like methods @@ -435,7 +435,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (class_definition (block (function_definition name: (_)@name))) ] { - attr @name "syntax_type" = "method" + attr (@name) "syntax_type" = "method" } [ @@ -476,7 +476,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (function_definition (block (function_definition name: (_)@name))) ] { - attr @name "syntax_type" = "function" + attr (@name) "syntax_type" = "function" } ;; @@ -491,13 +491,13 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @param.input -> @param::class_self_scope edge @param::class_member_attr_scope -> @param.output edge @param.output -> @body.after_scope - attr @param.output "push" + attr (@param.output) "push" } (parameter/identifier) @param { - attr @param.input "definition", "pop" - attr @param.param_name "push" + attr (@param.input) "definition", "pop" + attr (@param.param_name) "push" edge @param.input -> @param.param_index edge @param.input -> @param.param_name } @@ -511,8 +511,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n value: (_) @value) @param ] { - attr @name "definition", "pop" - attr @param.param_name "push" = @name + attr (@name) "definition", "pop" + attr (@param.param_name) "push" = @name edge @name -> @param.param_name edge @name -> @param.param_index edge @param.input -> @name @@ -528,8 +528,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n (_) @name) @param ] { - attr @name "definition", "pop" - attr @param.param_name "push" = @name + attr (@name) "definition", "pop" + attr (@param.param_name) "push" = @name edge @name -> @param.param_name edge @name -> @param.param_index edge @param.input -> @name @@ -546,13 +546,13 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @pattern.pattern_index -> @list.input edge @pattern.input -> @pattern.pattern_index - attr @pattern.pattern_index "push" = (child-index @pattern) + attr (@pattern.pattern_index) "push" = (child-index @pattern) } (parameters (_) @param) @params { - attr @param.param_index "push" = (child-index @param) + attr (@param.param_index) "push" = (child-index @param) edge @param.param_index -> @params.before_scope edge @params.after_scope -> @param.input edge @param.param_name -> @params.before_scope @@ -566,8 +566,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n (class_definition name: (identifier) @name) @class { - attr @name "definiens" = @class - attr @name "syntax_type" = "class" + attr (@name) "definiens" = @class + attr (@name) "syntax_type" = "class" edge @class.parent_scope -> @class::class_parent_scope edge @class.parent_scope -> @class::local_scope edge @class.after_scope -> @name @@ -580,13 +580,13 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @class.self_scope -> @class.self_dot edge @class.self_dot -> @class.members edge @class.members -> @class.member_attrs - attr @class.call "pop" = "()", "pop-scope" - attr @class.call_drop "drop" - attr @class.dot "pop" = "." - attr @class.self_dot "pop" = "." - attr @name "pop", "definition" - attr @class.member_attrs "push" = "." - attr @class.self_scope "endpoint" + attr (@class.call) "pop" = "()", "pop-scope" + attr (@class.call_drop) "drop" + attr (@class.dot) "pop" = "." + attr (@class.self_dot) "pop" = "." + attr (@name) "pop", "definition" + attr (@class.member_attrs) "push" = "." + attr (@class.self_scope) "endpoint" let @class::super_scope = @class.super_scope let @class::class_parent_scope = @class.parent_scope let @class::class_self_scope = @class.call_drop @@ -633,7 +633,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n { edge @call.output -> @call.output_args edge @call.output_args -> @fn.output - attr @call.output_args "push" = "()", "push-scope" = @args + attr (@call.output_args) "push" = "()", "push-scope" = @args } (call @@ -645,10 +645,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @args -> @arg.arg_index edge @receiver -> @receiver.arg_index - attr @receiver.arg_index "pop" = "0" + attr (@receiver.arg_index) "pop" = "0" edge @receiver.arg_index -> @receiver.output - attr @arg.arg_index "pop" = (+ 1 (child-index @arg)) + attr (@arg.arg_index) "pop" = (+ 1 (child-index @arg)) edge @arg.arg_index -> @arg.output } @@ -659,7 +659,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n value: (_) @val) @arg) @args) @call { edge @args -> @arg.arg_name - attr @arg.arg_name "pop" = @name + attr (@arg.arg_name) "pop" = @name edge @arg.arg_name -> @val.output } @@ -667,7 +667,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (expression) @arg) @args { edge @args -> @arg.arg_index - attr @arg.arg_index "pop" = (child-index @arg) + attr (@arg.arg_index) "pop" = (child-index @arg) edge @arg.arg_index -> @arg.output } @@ -686,7 +686,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ] @tuple { edge @tuple.output -> @element.el_index - attr @element.el_index "pop" = (child-index @element) + attr (@element.el_index) "pop" = (child-index @element) edge @element.el_index -> @element.output edge @tuple.new_bindings -> @element.new_bindings @@ -702,22 +702,22 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @object.input -> @expr.input_dot edge @expr.input_dot -> @name.input edge @name.input -> @expr.input - attr @expr.output_dot "push" = "." - attr @expr.input_dot "pop" = "." - attr @name.input "pop" - attr @name.output "push" + attr (@expr.output_dot) "push" = "." + attr (@expr.input_dot) "pop" = "." + attr (@name.input) "pop" + attr (@name.output) "push" } (pattern/attribute attribute: (identifier) @name) { - attr @name.input "definition" + attr (@name.input) "definition" } (primary_expression/attribute attribute: (identifier) @name) { - attr @name.output "reference" + attr (@name.output) "reference" } (primary_expression/identifier) @id @@ -725,10 +725,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @id.output -> @id::local_scope edge @id.output -> @id::class_parent_scope edge @id::local_scope -> @id.input - attr @id.input "pop" - attr @id.output "push", "reference" + attr (@id.input) "pop" + attr (@id.output) "push", "reference" - attr @id.new_binding_pop "pop", "definition" + attr (@id.new_binding_pop) "pop", "definition" edge @id.new_bindings -> @id.new_binding_pop } @@ -737,10 +737,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @id.output -> @id::local_scope edge @id.output -> @id::class_parent_scope edge @id::local_scope -> @id.input, "precedence" = 1 - attr @id.input "pop", "definition" - attr @id.output "push" + attr (@id.input) "pop", "definition" + attr (@id.output) "push" - attr @id.new_binding_pop "pop", "definition" + attr (@id.new_binding_pop) "pop", "definition" edge @id.new_bindings -> @id.new_binding_pop } @@ -751,8 +751,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @id.output -> @id::local_scope edge @id.output -> @id::class_parent_scope edge @id::local_scope -> @id.input, "precedence" = 1 - attr @id.input "pop", "definition" - attr @id.output "push" + attr (@id.input) "pop", "definition" + attr (@id.output) "push" edge @as_pattern.new_bindings -> @value.new_bindings edge @as_pattern.new_bindings -> @id.new_bindings @@ -762,7 +762,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n { edge @list.output -> @list.called edge @list.called -> @list::global_dot - attr @list.called "push" = "list" + attr (@list.called) "push" = "list" } (list (_) @el) @list @@ -788,7 +788,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (list_splat (_) @splatted) @splat { -attr @splat.new_bindings_pop "pop" = @splatted, "definition" +attr (@splat.new_bindings_pop) "pop" = @splatted, "definition" edge @splat.new_bindings -> @splat.new_bindings_pop } From d5a97bd101f600745fa71c1562e9d1b1291def13 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 09:49:10 +0200 Subject: [PATCH 321/500] convert: pop_scoped_symbol --- .../src/stack-graphs.tsg | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index f6d557b50..d7b6c33ed 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -58,7 +58,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge module_ref.dot -> module_ref attr (module_def) "pop" = $1 - attr (module_def.dot) "pop" = "." + attr (module_def.dot) pop_symbol = "." attr (module_ref) "push" = $1 attr (module_ref.dot) "push" = "." @@ -82,7 +82,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge module_def.dot -> module_def.next_def attr (module_def) "definition", "pop" = (replace $1 "\\.py" "") - attr (module_def.dot) "pop" = "." + attr (module_def.dot) pop_symbol = "." set module_def = module_def.next_def attr (module_def) empty_source_span @@ -291,7 +291,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @parent_name.def_dot -> @child_name.def attr (@child_name.def) "pop", "definition" attr (@child_name.ref) "push","reference" - attr (@parent_name.def_dot) "pop" = "." + attr (@parent_name.def_dot) pop_symbol = "." attr (@child_name.ref_dot) "push" = "." } @@ -407,7 +407,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @func.drop_scope -> @func::bottom attr (@func.drop_scope) "drop" attr (@name) "pop", "definition" - attr (@func.call) "pop" = "()", "pop-scope" + attr (@func.call) pop_scoped_symbol = "()" attr (@params.before_scope) "jump-to" attr (@func.return_value) "endpoint" let @func::function_returns = @func.return_value @@ -580,10 +580,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @class.self_scope -> @class.self_dot edge @class.self_dot -> @class.members edge @class.members -> @class.member_attrs - attr (@class.call) "pop" = "()", "pop-scope" + attr (@class.call) pop_scoped_symbol = "()" attr (@class.call_drop) "drop" - attr (@class.dot) "pop" = "." - attr (@class.self_dot) "pop" = "." + attr (@class.dot) pop_symbol = "." + attr (@class.self_dot) pop_symbol = "." attr (@name) "pop", "definition" attr (@class.member_attrs) "push" = "." attr (@class.self_scope) "endpoint" @@ -645,7 +645,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @args -> @arg.arg_index edge @receiver -> @receiver.arg_index - attr (@receiver.arg_index) "pop" = "0" + attr (@receiver.arg_index) pop_symbol = "0" edge @receiver.arg_index -> @receiver.output attr (@arg.arg_index) "pop" = (+ 1 (child-index @arg)) @@ -703,7 +703,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @expr.input_dot -> @name.input edge @name.input -> @expr.input attr (@expr.output_dot) "push" = "." - attr (@expr.input_dot) "pop" = "." + attr (@expr.input_dot) pop_symbol = "." attr (@name.input) "pop" attr (@name.output) "push" } From 01cf05d84a85afa8d4c944c3ff4ccf01bdca22e6 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 09:50:13 +0200 Subject: [PATCH 322/500] convert: push symbol --- .../src/stack-graphs.tsg | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index d7b6c33ed..e4ef4ada4 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -60,7 +60,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (module_def) "pop" = $1 attr (module_def.dot) pop_symbol = "." attr (module_ref) "push" = $1 - attr (module_ref.dot) "push" = "." + attr (module_ref.dot) push_symbol = "." set grandparent_module_ref = parent_module_ref set parent_module_def = module_def @@ -96,10 +96,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @mod.before_scope -> @mod.global_dot edge @mod.global -> root - attr (@mod.global) "push" = "" + attr (@mod.global) push_symbol = "" edge @mod.global_dot -> @mod.global - attr (@mod.global_dot) "push" = "." + attr (@mod.global_dot) push_symbol = "." var @mod::parent_module = parent_module_ref var @mod::grandparent_module = grandparent_module_ref @@ -143,7 +143,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @import_root_name.ref -> @import_root_name.ref_dot attr (@import_root_name.def) "pop", "definition" attr (@import_root_name.ref) "push", "reference" - attr (@import_root_name.ref_dot) "push" = "." + attr (@import_root_name.ref_dot) push_symbol = "." } (import_from_statement @@ -153,7 +153,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n { edge @import_root_name.ref -> @import_root_name.ref_dot attr (@import_root_name.ref) "push", "reference" - attr (@import_root_name.ref_dot) "push" = "." + attr (@import_root_name.ref_dot) push_symbol = "." } (import_from_statement @@ -223,7 +223,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n . (identifier) @name)) { attr (@name.ref) "push", "reference" - attr (@name.ref_dot) "push" = "." + attr (@name.ref_dot) push_symbol = "." edge @name.ref -> @name.ref_dot edge @name.ref_dot -> @prefix.ref } @@ -243,7 +243,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ] { attr (@child_name.ref) "push", "reference" - attr (@child_name.ref_dot) "push" = "." + attr (@child_name.ref_dot) push_symbol = "." edge @child_name.ref -> @child_name.ref_dot edge @child_name.ref_dot -> @parent_name.ref } @@ -263,7 +263,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n { edge @stmt.after_scope -> @star.ref_dot, "precedence" = 1 edge @star.ref_dot -> @leaf_name.ref - attr (@star.ref_dot) "push" = "." + attr (@star.ref_dot) push_symbol = "." } [ @@ -292,7 +292,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (@child_name.def) "pop", "definition" attr (@child_name.ref) "push","reference" attr (@parent_name.def_dot) pop_symbol = "." - attr (@child_name.ref_dot) "push" = "." + attr (@child_name.ref_dot) push_symbol = "." } ;-------- @@ -585,7 +585,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (@class.dot) pop_symbol = "." attr (@class.self_dot) pop_symbol = "." attr (@name) "pop", "definition" - attr (@class.member_attrs) "push" = "." + attr (@class.member_attrs) push_symbol = "." attr (@class.self_scope) "endpoint" let @class::super_scope = @class.super_scope let @class::class_parent_scope = @class.parent_scope @@ -633,7 +633,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n { edge @call.output -> @call.output_args edge @call.output_args -> @fn.output - attr (@call.output_args) "push" = "()", "push-scope" = @args + attr (@call.output_args) push_scoped_symbol = "()", scope = @args } (call @@ -702,7 +702,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @object.input -> @expr.input_dot edge @expr.input_dot -> @name.input edge @name.input -> @expr.input - attr (@expr.output_dot) "push" = "." + attr (@expr.output_dot) push_symbol = "." attr (@expr.input_dot) pop_symbol = "." attr (@name.input) "pop" attr (@name.output) "push" @@ -762,7 +762,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n { edge @list.output -> @list.called edge @list.called -> @list::global_dot - attr (@list.called) "push" = "list" + attr (@list.called) push_symbol = "list" } (list (_) @el) @list From 3ab39ce7281c4a6a44c6176bde76f1b223c20bea Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 10:04:39 +0200 Subject: [PATCH 323/500] convert: push and pop nodes --- .../src/stack-graphs.tsg | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index e4ef4ada4..ee9d010eb 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -57,9 +57,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge module_ref.next_ref -> module_ref.dot edge module_ref.dot -> module_ref - attr (module_def) "pop" = $1 + attr (module_def) pop_symbol = $1 attr (module_def.dot) pop_symbol = "." - attr (module_ref) "push" = $1 + attr (module_ref) push_symbol = $1 attr (module_ref.dot) push_symbol = "." set grandparent_module_ref = parent_module_ref @@ -81,7 +81,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge module_def -> module_def.dot edge module_def.dot -> module_def.next_def - attr (module_def) "definition", "pop" = (replace $1 "\\.py" "") + attr (module_def) symbol_definition = (replace $1 "\\.py" ""), source_node = @mod attr (module_def.dot) pop_symbol = "." set module_def = module_def.next_def @@ -114,8 +114,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n { edge @stmt.after_scope -> @root_name.def, "precedence" = 1 edge @root_name.ref -> root - attr (@root_name.ref) "push", "reference" - attr (@root_name.def) "pop", "definition" + attr (@root_name.ref) node_reference = @root_name + attr (@root_name.def) node_definition = @root_name } (import_statement @@ -124,7 +124,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n { edge @stmt.after_scope -> @root_name.def edge @root_name.ref -> root - attr (@root_name.ref) "push", "reference" + attr (@root_name.ref) node_reference = @root_name } (import_from_statement @@ -132,7 +132,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n . (identifier) @prefix_root_name)) @stmt { edge @prefix_root_name.ref -> root - attr (@prefix_root_name.ref) "push", "reference" + attr (@prefix_root_name.ref) node_reference = @prefix_root_name } (import_from_statement @@ -141,8 +141,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n { edge @stmt.after_scope -> @import_root_name.def, "precedence" = 1 edge @import_root_name.ref -> @import_root_name.ref_dot - attr (@import_root_name.def) "pop", "definition" - attr (@import_root_name.ref) "push", "reference" + attr (@import_root_name.def) node_definition = @import_root_name + attr (@import_root_name.ref) node_reference = @import_root_name attr (@import_root_name.ref_dot) push_symbol = "." } @@ -152,7 +152,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n . (identifier) @import_root_name))) @stmt { edge @import_root_name.ref -> @import_root_name.ref_dot - attr (@import_root_name.ref) "push", "reference" + attr (@import_root_name.ref) node_reference = @import_root_name attr (@import_root_name.ref_dot) push_symbol = "." } @@ -186,7 +186,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n { edge @stmt.after_scope -> @alias edge @alias -> @name.ref - attr (@alias) "pop", "definition" + attr (@alias) node_definition = @alias } [ @@ -198,8 +198,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n (identifier) @leaf_name .)) ] { - attr (@leaf_name.def) "pop", "definition" - attr (@leaf_name.ref) "push", "reference" + attr (@leaf_name.def) node_definition = @leaf_name + attr (@leaf_name.ref) node_reference = @leaf_name edge @leaf_name.def -> @leaf_name.ref } @@ -222,7 +222,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (dotted_name . (identifier) @name)) { - attr (@name.ref) "push", "reference" + attr (@name.ref) node_reference = @name attr (@name.ref_dot) push_symbol = "." edge @name.ref -> @name.ref_dot edge @name.ref_dot -> @prefix.ref @@ -242,7 +242,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (identifier) @child_name)) ] { - attr (@child_name.ref) "push", "reference" + attr (@child_name.ref) node_reference = @child_name attr (@child_name.ref_dot) push_symbol = "." edge @child_name.ref -> @child_name.ref_dot edge @child_name.ref_dot -> @parent_name.ref @@ -252,7 +252,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n module_name: (dotted_name . (identifier) @root_name)) { - attr (@root_name.ref) "push", "reference" + attr (@root_name.ref) node_reference = @root_name edge @root_name.ref -> root } @@ -289,8 +289,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @child_name.ref_dot -> @parent_name.ref edge @parent_name.def -> @parent_name.def_dot edge @parent_name.def_dot -> @child_name.def - attr (@child_name.def) "pop", "definition" - attr (@child_name.ref) "push","reference" + attr (@child_name.def) node_definition = @child_name + attr (@child_name.ref) node_reference = @child_name attr (@parent_name.def_dot) pop_symbol = "." attr (@child_name.ref_dot) push_symbol = "." } @@ -406,7 +406,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @body.before_scope -> @func.drop_scope edge @func.drop_scope -> @func::bottom attr (@func.drop_scope) "drop" - attr (@name) "pop", "definition" + attr (@name) node_definition = @name attr (@func.call) pop_scoped_symbol = "()" attr (@params.before_scope) "jump-to" attr (@func.return_value) "endpoint" @@ -491,13 +491,13 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @param.input -> @param::class_self_scope edge @param::class_member_attr_scope -> @param.output edge @param.output -> @body.after_scope - attr (@param.output) "push" + attr (@param.output) push_node = @param } (parameter/identifier) @param { - attr (@param.input) "definition", "pop" - attr (@param.param_name) "push" + attr (@param.input) node_definition = @param + attr (@param.param_name) push_node = @param edge @param.input -> @param.param_index edge @param.input -> @param.param_name } @@ -511,7 +511,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n value: (_) @value) @param ] { - attr (@name) "definition", "pop" + attr (@name) node_definition = @name attr (@param.param_name) "push" = @name edge @name -> @param.param_name edge @name -> @param.param_index @@ -528,7 +528,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (_) @name) @param ] { - attr (@name) "definition", "pop" + attr (@name) node_definition = @name attr (@param.param_name) "push" = @name edge @name -> @param.param_name edge @name -> @param.param_index @@ -584,7 +584,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (@class.call_drop) "drop" attr (@class.dot) pop_symbol = "." attr (@class.self_dot) pop_symbol = "." - attr (@name) "pop", "definition" + attr (@name) node_definition = @name attr (@class.member_attrs) push_symbol = "." attr (@class.self_scope) "endpoint" let @class::super_scope = @class.super_scope @@ -704,8 +704,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @name.input -> @expr.input attr (@expr.output_dot) push_symbol = "." attr (@expr.input_dot) pop_symbol = "." - attr (@name.input) "pop" - attr (@name.output) "push" + attr (@name.input) pop_node = @name + attr (@name.output) push_node = @name } (pattern/attribute @@ -725,10 +725,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @id.output -> @id::local_scope edge @id.output -> @id::class_parent_scope edge @id::local_scope -> @id.input - attr (@id.input) "pop" - attr (@id.output) "push", "reference" + attr (@id.input) pop_node = @id + attr (@id.output) node_reference = @id - attr (@id.new_binding_pop) "pop", "definition" + attr (@id.new_binding_pop) node_definition = @id edge @id.new_bindings -> @id.new_binding_pop } @@ -737,10 +737,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @id.output -> @id::local_scope edge @id.output -> @id::class_parent_scope edge @id::local_scope -> @id.input, "precedence" = 1 - attr (@id.input) "pop", "definition" - attr (@id.output) "push" + attr (@id.input) node_definition = @id + attr (@id.output) push_node = @id - attr (@id.new_binding_pop) "pop", "definition" + attr (@id.new_binding_pop) node_definition = @id edge @id.new_bindings -> @id.new_binding_pop } @@ -751,8 +751,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @id.output -> @id::local_scope edge @id.output -> @id::class_parent_scope edge @id::local_scope -> @id.input, "precedence" = 1 - attr (@id.input) "pop", "definition" - attr (@id.output) "push" + attr (@id.input) node_definition = @id + attr (@id.output) push_node = @id edge @as_pattern.new_bindings -> @value.new_bindings edge @as_pattern.new_bindings -> @id.new_bindings From a838d6e8fab1031d5025b41d7fc6b30aec110bc1 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 10:06:08 +0200 Subject: [PATCH 324/500] convert: push and pop with explicit values --- .../src/stack-graphs.tsg | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index ee9d010eb..6f65fdfbd 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -512,7 +512,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ] { attr (@name) node_definition = @name - attr (@param.param_name) "push" = @name + attr (@param.param_name) push_node = @name edge @name -> @param.param_name edge @name -> @param.param_index edge @param.input -> @name @@ -529,7 +529,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ] { attr (@name) node_definition = @name - attr (@param.param_name) "push" = @name + attr (@param.param_name) push_node = @name edge @name -> @param.param_name edge @name -> @param.param_index edge @param.input -> @name @@ -546,13 +546,13 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @pattern.pattern_index -> @list.input edge @pattern.input -> @pattern.pattern_index - attr (@pattern.pattern_index) "push" = (child-index @pattern) + attr (@pattern.pattern_index) push_symbol = (child-index @pattern) } (parameters (_) @param) @params { - attr (@param.param_index) "push" = (child-index @param) + attr (@param.param_index) push_symbol = (child-index @param) edge @param.param_index -> @params.before_scope edge @params.after_scope -> @param.input edge @param.param_name -> @params.before_scope @@ -648,7 +648,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (@receiver.arg_index) pop_symbol = "0" edge @receiver.arg_index -> @receiver.output - attr (@arg.arg_index) "pop" = (+ 1 (child-index @arg)) + attr (@arg.arg_index) pop_symbol = (+ 1 (child-index @arg)) edge @arg.arg_index -> @arg.output } @@ -659,7 +659,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n value: (_) @val) @arg) @args) @call { edge @args -> @arg.arg_name - attr (@arg.arg_name) "pop" = @name + attr (@arg.arg_name) pop_node = @name edge @arg.arg_name -> @val.output } @@ -667,7 +667,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (expression) @arg) @args { edge @args -> @arg.arg_index - attr (@arg.arg_index) "pop" = (child-index @arg) + attr (@arg.arg_index) pop_symbol = (child-index @arg) edge @arg.arg_index -> @arg.output } @@ -686,7 +686,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ] @tuple { edge @tuple.output -> @element.el_index - attr (@element.el_index) "pop" = (child-index @element) + attr (@element.el_index) pop_symbol = (child-index @element) edge @element.el_index -> @element.output edge @tuple.new_bindings -> @element.new_bindings @@ -788,7 +788,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (list_splat (_) @splatted) @splat { -attr (@splat.new_bindings_pop) "pop" = @splatted, "definition" +attr (@splat.new_bindings_pop) node_definition = @splatted edge @splat.new_bindings -> @splat.new_bindings_pop } From b3179de0b457b539a6066ede2386fa6a4575b5eb Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 10:08:29 +0200 Subject: [PATCH 325/500] convert: more references and definitions --- .../tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 6f65fdfbd..7088f8b6f 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -73,7 +73,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n "__init__\\.py$" { - attr (parent_module_def) "definition" + attr (parent_module_def) node_definition = @mod } "([^/]+)$" @@ -711,13 +711,13 @@ attribute node_symbol = node => symbol = (source-text node), source_n (pattern/attribute attribute: (identifier) @name) { - attr (@name.input) "definition" + attr (@name.input) node_definition = @name } (primary_expression/attribute attribute: (identifier) @name) { - attr (@name.output) "reference" + attr (@name.output) node_reference = @name } (primary_expression/identifier) @id From 2f2a4ccb601ce10b1b8adc84018717bda7994e08 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 10:11:18 +0200 Subject: [PATCH 326/500] convert: edge precedence --- .../src/stack-graphs.tsg | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 7088f8b6f..b5433f967 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -112,7 +112,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n name: (dotted_name . (identifier) @root_name)) @stmt { - edge @stmt.after_scope -> @root_name.def, "precedence" = 1 + edge @stmt.after_scope -> @root_name.def + attr (@stmt.after_scope -> @root_name.def) precedence = 1 edge @root_name.ref -> root attr (@root_name.ref) node_reference = @root_name attr (@root_name.def) node_definition = @root_name @@ -139,7 +140,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n name: (dotted_name . (identifier) @import_root_name)) @stmt { - edge @stmt.after_scope -> @import_root_name.def, "precedence" = 1 + edge @stmt.after_scope -> @import_root_name.def + attr (@stmt.after_scope -> @import_root_name.def) precedence = 1 edge @import_root_name.ref -> @import_root_name.ref_dot attr (@import_root_name.def) node_definition = @import_root_name attr (@import_root_name.ref) node_reference = @import_root_name @@ -261,7 +263,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n (identifier) @leaf_name .) (wildcard_import) @star) @stmt { - edge @stmt.after_scope -> @star.ref_dot, "precedence" = 1 + edge @stmt.after_scope -> @star.ref_dot + attr (@stmt.after_scope -> @star.ref_dot) precedence = 1 edge @star.ref_dot -> @leaf_name.ref attr (@star.ref_dot) push_symbol = "." } @@ -542,7 +545,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n { let statement_scope = @list::local_scope let @pattern::local_scope = @pattern.pattern_before_scope - edge statement_scope -> @pattern::local_scope, "precedence" = (+ 1 (child-index @pattern)) + edge statement_scope -> @pattern::local_scope + attr (statement_scope -> @pattern::local_scope) precedence = (+ 1 (child-index @pattern)) edge @pattern.pattern_index -> @list.input edge @pattern.input -> @pattern.pattern_index @@ -736,7 +740,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n { edge @id.output -> @id::local_scope edge @id.output -> @id::class_parent_scope - edge @id::local_scope -> @id.input, "precedence" = 1 + edge @id::local_scope -> @id.input + attr (@id::local_scope -> @id.input) precedence = 1 attr (@id.input) node_definition = @id attr (@id.output) push_node = @id @@ -750,7 +755,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n { edge @id.output -> @id::local_scope edge @id.output -> @id::class_parent_scope - edge @id::local_scope -> @id.input, "precedence" = 1 + edge @id::local_scope -> @id.input + attr (@id::local_scope -> @id.input) precedence = 1 attr (@id.input) node_definition = @id attr (@id.output) push_node = @id From 90399c7c91aa5abb6bd16c9b27d830c4dd290b17 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 10:14:54 +0200 Subject: [PATCH 327/500] convert: drop --- .../tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index b5433f967..84e8fddb0 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -408,7 +408,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @body.before_scope -> @params.after_scope edge @body.before_scope -> @func.drop_scope edge @func.drop_scope -> @func::bottom - attr (@func.drop_scope) "drop" + attr (@func.drop_scope) type = "drop_scopes" attr (@name) node_definition = @name attr (@func.call) pop_scoped_symbol = "()" attr (@params.before_scope) "jump-to" @@ -585,7 +585,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @class.self_dot -> @class.members edge @class.members -> @class.member_attrs attr (@class.call) pop_scoped_symbol = "()" - attr (@class.call_drop) "drop" + attr (@class.call_drop) type = "drop_scopes" attr (@class.dot) pop_symbol = "." attr (@class.self_dot) pop_symbol = "." attr (@name) node_definition = @name From cfc004ad453f143d6f2e08bbe17228e5745e6d25 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 10:15:36 +0200 Subject: [PATCH 328/500] convert: endpoint --- .../tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 84e8fddb0..9b959b271 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -412,7 +412,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (@name) node_definition = @name attr (@func.call) pop_scoped_symbol = "()" attr (@params.before_scope) "jump-to" - attr (@func.return_value) "endpoint" + attr (@func.return_value) is_exported let @func::function_returns = @func.return_value ; Prevent functions defined inside of method bodies from being treated like methods @@ -590,7 +590,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (@class.self_dot) pop_symbol = "." attr (@name) node_definition = @name attr (@class.member_attrs) push_symbol = "." - attr (@class.self_scope) "endpoint" + attr (@class.self_scope) is_exported let @class::super_scope = @class.super_scope let @class::class_parent_scope = @class.parent_scope let @class::class_self_scope = @class.call_drop From b14aba9220314697c0c470ff97cc72b4b1a8d7a1 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 10:17:25 +0200 Subject: [PATCH 329/500] convert: definiens --- .../tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 9b959b271..fac43e2b3 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -401,7 +401,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n parameters: (parameters) @params body: (block) @body) @func { - attr (@name) "definiens" = @func + attr (@name) definiens_node = @func edge @func.after_scope -> @name edge @name -> @func.call edge @func.call -> @func.return_value @@ -570,7 +570,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (class_definition name: (identifier) @name) @class { - attr (@name) "definiens" = @class + attr (@name) definiens_node = @class attr (@name) "syntax_type" = "class" edge @class.parent_scope -> @class::class_parent_scope edge @class.parent_scope -> @class::local_scope From 129aa5d3a651fb025139931aa290f15b92f1c8e6 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 10:18:08 +0200 Subject: [PATCH 330/500] convert: syntax type --- .../tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index fac43e2b3..d86aba3e0 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -438,7 +438,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (class_definition (block (function_definition name: (_)@name))) ] { - attr (@name) "syntax_type" = "method" + attr (@name) syntax_type = "method" } [ @@ -479,7 +479,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (function_definition (block (function_definition name: (_)@name))) ] { - attr (@name) "syntax_type" = "function" + attr (@name) syntax_type = "function" } ;; @@ -571,7 +571,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n name: (identifier) @name) @class { attr (@name) definiens_node = @class - attr (@name) "syntax_type" = "class" + attr (@name) syntax_type = "class" edge @class.parent_scope -> @class::class_parent_scope edge @class.parent_scope -> @class::local_scope edge @class.after_scope -> @name From dba45d9ddcc8e9bf60948f62f0ec362bf15d8014 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 10:18:54 +0200 Subject: [PATCH 331/500] convert: jump --- languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index d86aba3e0..0ddad1079 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -411,7 +411,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (@func.drop_scope) type = "drop_scopes" attr (@name) node_definition = @name attr (@func.call) pop_scoped_symbol = "()" - attr (@params.before_scope) "jump-to" + edge @params.before_scope -> JUMP_TO_SCOPE_NODE attr (@func.return_value) is_exported let @func::function_returns = @func.return_value From 6bb4d577d1e811fb76204ac751fbd63db649feb0 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 15:38:22 +0200 Subject: [PATCH 332/500] convert: nodes --- .../src/stack-graphs.tsg | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 0ddad1079..1323bccba 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -36,6 +36,49 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol attribute node_symbol = node => symbol = (source-text node), source_node = node +;; Nodes +;; ^^^^^ + +(_)@node { + node @node.after_scope + node @node.arg_index + node @node.arg_name + node @node.before_scope + node @node.call + node @node.call_drop + node @node.called + node @node.def + node @node.def_dot + node @node.dot + node @node.drop_scope + node @node.el_index + node @node.file_def + node @node.file_ref + node @node.global + node @node.global_dot + node @node.input + node @node.input_dot + node @node.member_attrs + node @node.members + node @node.new_binding_pop + node @node.new_bindings + node @node.new_bindings_pop + node @node.output + node @node.output_args + node @node.output_dot + node @node.param_index + node @node.param_name + node @node.parent_scope + node @node.pattern_before_scope + node @node.pattern_index + node @node.ref + node @node.ref_dot + node @node.return_value + node @node.self_dot + node @node.self_scope + node @node.super_scope +} + ; Modules and Imports ;--------------------- From da3728c74f269dd8240e45a49ad2090aa183527a Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 19:49:58 +0200 Subject: [PATCH 333/500] convert: scoped variables --- .../src/stack-graphs.tsg | 101 ++++++++++-------- 1 file changed, 58 insertions(+), 43 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 1323bccba..896ab715a 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -79,6 +79,21 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.super_scope } +;; Inherited Variables +;; ^^^^^^^^^^^^^^^^^^^ + +inherit .bottom +inherit .class_member_attr_scope +inherit .class_parent_scope +inherit .class_self_scope +inherit .function_returns +inherit .global +inherit .global_dot +inherit .grandparent_module +inherit .local_scope +inherit .parent_module +inherit .super_scope + ; Modules and Imports ;--------------------- @@ -92,7 +107,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n var parent_module_ref = module_ref var grandparent_module_ref = module_ref - scan filepath { + scan FILE_PATH { "([^/]+)/" { edge module_def -> module_def.dot @@ -144,11 +159,11 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @mod.global_dot -> @mod.global attr (@mod.global_dot) push_symbol = "." - var @mod::parent_module = parent_module_ref - var @mod::grandparent_module = grandparent_module_ref - var @mod::bottom = @mod.after_scope - var @mod::global = @mod.global - var @mod::global_dot = @mod.global_dot + let @mod.parent_module = parent_module_ref + let @mod.grandparent_module = grandparent_module_ref + let @mod.bottom = @mod.after_scope + let @mod.global = @mod.global + let @mod.global_dot = @mod.global_dot } (import_statement @@ -252,14 +267,14 @@ attribute node_symbol = node => symbol = (source-text node), source_n (import_prefix) @prefix (#eq? @prefix ".")) @import { - edge @prefix.ref -> @import::parent_module + edge @prefix.ref -> @import.parent_module } (relative_import (import_prefix) @prefix (#eq? @prefix "..")) @import { - edge @prefix.ref -> @import::grandparent_module + edge @prefix.ref -> @import.grandparent_module } (relative_import @@ -367,7 +382,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ] { edge @stmt.after_scope -> @stmt.before_scope - let @stmt::local_scope = @stmt.before_scope + let @stmt.local_scope = @stmt.before_scope } [ @@ -385,7 +400,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (function_definition (block) @block) { - edge @block.before_scope -> @block::local_scope + edge @block.before_scope -> @block.local_scope } [ @@ -402,13 +417,13 @@ attribute node_symbol = node => symbol = (source-text node), source_n ]) ] @stmt { - edge @block.before_scope -> @block::local_scope + edge @block.before_scope -> @block.local_scope edge @stmt.after_scope -> @block.after_scope } (match_statement (case_clause) @block) @stmt { - let @block::local_scope = @block.before_scope + let @block.local_scope = @block.before_scope edge @block.before_scope -> @stmt.before_scope edge @stmt.after_scope -> @block.after_scope } @@ -450,17 +465,17 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @func.call -> @func.return_value edge @body.before_scope -> @params.after_scope edge @body.before_scope -> @func.drop_scope - edge @func.drop_scope -> @func::bottom + edge @func.drop_scope -> @func.bottom attr (@func.drop_scope) type = "drop_scopes" attr (@name) node_definition = @name attr (@func.call) pop_scoped_symbol = "()" edge @params.before_scope -> JUMP_TO_SCOPE_NODE attr (@func.return_value) is_exported - let @func::function_returns = @func.return_value + let @func.function_returns = @func.return_value ; Prevent functions defined inside of method bodies from being treated like methods - let @body::class_self_scope = nil - let @body::class_member_attr_scope = nil + let @body.class_self_scope = nil + let @body.class_member_attr_scope = nil } ;; @@ -534,8 +549,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n . (identifier) @param) body: (block) @body) { - edge @param.input -> @param::class_self_scope - edge @param::class_member_attr_scope -> @param.output + edge @param.input -> @param.class_self_scope + edge @param.class_member_attr_scope -> @param.output edge @param.output -> @body.after_scope attr (@param.output) push_node = @param } @@ -586,10 +601,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n (tuple_pattern (_) @pattern) ] @list { - let statement_scope = @list::local_scope - let @pattern::local_scope = @pattern.pattern_before_scope - edge statement_scope -> @pattern::local_scope - attr (statement_scope -> @pattern::local_scope) precedence = (+ 1 (child-index @pattern)) + let statement_scope = @list.local_scope + let @pattern.local_scope = @pattern.pattern_before_scope + edge statement_scope -> @pattern.local_scope + attr (statement_scope -> @pattern.local_scope) precedence = (plus 1 (child-index @pattern)) edge @pattern.pattern_index -> @list.input edge @pattern.input -> @pattern.pattern_index @@ -607,7 +622,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (return_statement (_) @expr) @stmt { - edge @stmt::function_returns -> @expr.output + edge @stmt.function_returns -> @expr.output } (class_definition @@ -615,8 +630,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n { attr (@name) definiens_node = @class attr (@name) syntax_type = "class" - edge @class.parent_scope -> @class::class_parent_scope - edge @class.parent_scope -> @class::local_scope + edge @class.parent_scope -> @class.class_parent_scope + edge @class.parent_scope -> @class.local_scope edge @class.after_scope -> @name edge @name -> @class.call edge @name -> @class.dot @@ -634,10 +649,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (@name) node_definition = @name attr (@class.member_attrs) push_symbol = "." attr (@class.self_scope) is_exported - let @class::super_scope = @class.super_scope - let @class::class_parent_scope = @class.parent_scope - let @class::class_self_scope = @class.call_drop - let @class::class_member_attr_scope = @class.member_attrs + let @class.super_scope = @class.super_scope + let @class.class_parent_scope = @class.parent_scope + let @class.class_self_scope = @class.call_drop + let @class.class_member_attr_scope = @class.member_attrs } (class_definition @@ -695,7 +710,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n attr (@receiver.arg_index) pop_symbol = "0" edge @receiver.arg_index -> @receiver.output - attr (@arg.arg_index) pop_symbol = (+ 1 (child-index @arg)) + attr (@arg.arg_index) pop_symbol = (plus 1 (child-index @arg)) edge @arg.arg_index -> @arg.output } @@ -724,7 +739,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (#eq? @fn-name "super") ) { - edge @call.output -> @call::super_scope + edge @call.output -> @call.super_scope } [ @@ -769,9 +784,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n (primary_expression/identifier) @id { - edge @id.output -> @id::local_scope - edge @id.output -> @id::class_parent_scope - edge @id::local_scope -> @id.input + edge @id.output -> @id.local_scope + edge @id.output -> @id.class_parent_scope + edge @id.local_scope -> @id.input attr (@id.input) pop_node = @id attr (@id.output) node_reference = @id @@ -781,10 +796,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n (pattern/identifier) @id { - edge @id.output -> @id::local_scope - edge @id.output -> @id::class_parent_scope - edge @id::local_scope -> @id.input - attr (@id::local_scope -> @id.input) precedence = 1 + edge @id.output -> @id.local_scope + edge @id.output -> @id.class_parent_scope + edge @id.local_scope -> @id.input + attr (@id.local_scope -> @id.input) precedence = 1 attr (@id.input) node_definition = @id attr (@id.output) push_node = @id @@ -796,10 +811,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n (expression) @value alias: (as_pattern_target (primary_expression/identifier) @id)) @as_pattern { - edge @id.output -> @id::local_scope - edge @id.output -> @id::class_parent_scope - edge @id::local_scope -> @id.input - attr (@id::local_scope -> @id.input) precedence = 1 + edge @id.output -> @id.local_scope + edge @id.output -> @id.class_parent_scope + edge @id.local_scope -> @id.input + attr (@id.local_scope -> @id.input) precedence = 1 attr (@id.input) node_definition = @id attr (@id.output) push_node = @id @@ -810,7 +825,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (list) @list { edge @list.output -> @list.called - edge @list.called -> @list::global_dot + edge @list.called -> @list.global_dot attr (@list.called) push_symbol = "list" } From 39c262494bdf2252cda5c603918f0cec4fb72bf3 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 19:51:04 +0200 Subject: [PATCH 334/500] convert: root --- .../src/stack-graphs.tsg | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 896ab715a..8460d2527 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -148,12 +148,12 @@ inherit .super_scope } } - edge root -> @mod.file_def - edge @mod.file_ref -> root + edge ROOT_NODE -> @mod.file_def + edge @mod.file_ref -> ROOT_NODE edge module_def -> @mod.after_scope edge @mod.before_scope -> @mod.global_dot - edge @mod.global -> root + edge @mod.global -> ROOT_NODE attr (@mod.global) push_symbol = "" edge @mod.global_dot -> @mod.global @@ -172,7 +172,7 @@ inherit .super_scope { edge @stmt.after_scope -> @root_name.def attr (@stmt.after_scope -> @root_name.def) precedence = 1 - edge @root_name.ref -> root + edge @root_name.ref -> ROOT_NODE attr (@root_name.ref) node_reference = @root_name attr (@root_name.def) node_definition = @root_name } @@ -182,7 +182,7 @@ inherit .super_scope (dotted_name . (identifier) @root_name))) @stmt { edge @stmt.after_scope -> @root_name.def - edge @root_name.ref -> root + edge @root_name.ref -> ROOT_NODE attr (@root_name.ref) node_reference = @root_name } @@ -190,7 +190,7 @@ inherit .super_scope module_name: (dotted_name . (identifier) @prefix_root_name)) @stmt { - edge @prefix_root_name.ref -> root + edge @prefix_root_name.ref -> ROOT_NODE attr (@prefix_root_name.ref) node_reference = @prefix_root_name } @@ -313,7 +313,7 @@ inherit .super_scope . (identifier) @root_name)) { attr (@root_name.ref) node_reference = @root_name - edge @root_name.ref -> root + edge @root_name.ref -> ROOT_NODE } (import_from_statement From 8e05b65573ea1c148aaaaa6860105aa0440dbdd4 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 1 Jun 2023 19:53:19 +0200 Subject: [PATCH 335/500] convert: captures --- .../src/stack-graphs.tsg | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 8460d2527..3746841b7 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -188,7 +188,7 @@ inherit .super_scope (import_from_statement module_name: (dotted_name - . (identifier) @prefix_root_name)) @stmt + . (identifier) @prefix_root_name)) { edge @prefix_root_name.ref -> ROOT_NODE attr (@prefix_root_name.ref) node_reference = @prefix_root_name @@ -209,7 +209,7 @@ inherit .super_scope (import_from_statement name: (aliased_import (dotted_name - . (identifier) @import_root_name))) @stmt + . (identifier) @import_root_name))) { edge @import_root_name.ref -> @import_root_name.ref_dot attr (@import_root_name.ref) node_reference = @import_root_name @@ -474,8 +474,8 @@ inherit .super_scope let @func.function_returns = @func.return_value ; Prevent functions defined inside of method bodies from being treated like methods - let @body.class_self_scope = nil - let @body.class_member_attr_scope = nil + let @body.class_self_scope = #null + let @body.class_member_attr_scope = #null } ;; @@ -657,7 +657,7 @@ inherit .super_scope (class_definition body: (block - (_) @last_stmt .) @body) @class + (_) @last_stmt .)) @class { edge @class.members -> @last_stmt.after_scope } @@ -718,7 +718,7 @@ inherit .super_scope arguments: (argument_list (keyword_argument name: (identifier) @name - value: (_) @val) @arg) @args) @call + value: (_) @val) @arg) @args) { edge @args -> @arg.arg_name attr (@arg.arg_name) pop_node = @name @@ -735,8 +735,8 @@ inherit .super_scope ( (call - function: (identifier) @fn-name) @call - (#eq? @fn-name "super") + function: (identifier) @_fn_name) @call + (#eq? @_fn_name "super") ) { edge @call.output -> @call.super_scope From 10e33f794042323e114132de66bff03d4f4701f6 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 2 Jun 2023 10:45:13 +0200 Subject: [PATCH 336/500] convert: module ref and def --- .../src/stack-graphs.tsg | 73 +++++++++++-------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 3746841b7..019a21db6 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -100,51 +100,64 @@ inherit .super_scope (module) @mod { var module_def = @mod.file_def - attr (module_def) empty_source_span + + node parent_module_def_node + var parent_module_def = parent_module_def_node + var module_ref = @mod.file_ref - attr (module_ref) empty_source_span - var parent_module_def = module_def - var parent_module_ref = module_ref - var grandparent_module_ref = module_ref + + node parent_module_ref_node + var parent_module_ref = parent_module_ref_node + + node grandparent_module_ref_node + var grandparent_module_ref = grandparent_module_ref_node scan FILE_PATH { "([^/]+)/" { - edge module_def -> module_def.dot - edge module_def.dot -> module_def.next_def - edge module_ref.next_ref -> module_ref.dot - edge module_ref.dot -> module_ref - + node def_dot + attr (def_dot) pop_symbol = "." + node next_def + ; + edge module_def -> def_dot + edge def_dot -> next_def + ; attr (module_def) pop_symbol = $1 - attr (module_def.dot) pop_symbol = "." + ; + set parent_module_def = module_def + set module_def = next_def + + node ref_dot + attr (ref_dot) push_symbol = "." + node next_ref + ; + edge next_ref -> ref_dot + edge ref_dot -> module_ref + ; attr (module_ref) push_symbol = $1 - attr (module_ref.dot) push_symbol = "." - + ; set grandparent_module_ref = parent_module_ref - set parent_module_def = module_def set parent_module_ref = module_ref - set module_ref = module_ref.next_ref - set module_def = module_def.next_def - attr (module_def) empty_source_span - attr (module_ref) empty_source_span + set module_ref = next_ref } - "__init__\\.py$" + "__init__\.py$" { - attr (parent_module_def) node_definition = @mod + attr (parent_module_def) is_definition, source_node = @mod, empty_source_span } - "([^/]+)$" + "([^/]+)\.py$" { - edge module_def -> module_def.dot - edge module_def.dot -> module_def.next_def - - attr (module_def) symbol_definition = (replace $1 "\\.py" ""), source_node = @mod - attr (module_def.dot) pop_symbol = "." - - set module_def = module_def.next_def - attr (module_def) empty_source_span - attr (module_ref) empty_source_span + node def_dot + attr (def_dot) pop_symbol = "." + node next_def + ; + edge module_def -> def_dot + edge def_dot -> next_def + ; + attr (module_def) pop_symbol = $1, is_definition, source_node = @mod, empty_source_span + ; + set module_def = next_def } } From ff21d32e812d4343393909b087a77f355cb0cdb1 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 2 Jun 2023 10:51:30 +0200 Subject: [PATCH 337/500] convert: global/global_dot --- .../src/stack-graphs.tsg | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 019a21db6..93515f30e 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -54,8 +54,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.el_index node @node.file_def node @node.file_ref - node @node.global - node @node.global_dot node @node.input node @node.input_dot node @node.member_attrs @@ -165,18 +163,21 @@ inherit .super_scope edge @mod.file_ref -> ROOT_NODE edge module_def -> @mod.after_scope - edge @mod.before_scope -> @mod.global_dot - edge @mod.global -> ROOT_NODE - attr (@mod.global) push_symbol = "" + node global + node global_dot - edge @mod.global_dot -> @mod.global - attr (@mod.global_dot) push_symbol = "." + edge @mod.before_scope -> global_dot + edge global -> ROOT_NODE + attr (global) push_symbol = "" + + edge global_dot -> global + attr (global_dot) push_symbol = "." let @mod.parent_module = parent_module_ref let @mod.grandparent_module = grandparent_module_ref let @mod.bottom = @mod.after_scope - let @mod.global = @mod.global - let @mod.global_dot = @mod.global_dot + let @mod.global = global + let @mod.global_dot = global_dot } (import_statement From fb9e45cbadb164be9562d8ee1e389bb9bdc413e7 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 2 Jun 2023 10:55:16 +0200 Subject: [PATCH 338/500] convert: syntax nodes as graph nodes --- .../src/stack-graphs.tsg | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 93515f30e..e3b54923e 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -259,8 +259,8 @@ inherit .super_scope ] @stmt { edge @stmt.after_scope -> @alias - edge @alias -> @name.ref - attr (@alias) node_definition = @alias + edge @alias.def -> @name.ref + attr (@alias.def) node_definition = @alias } [ @@ -473,15 +473,15 @@ inherit .super_scope parameters: (parameters) @params body: (block) @body) @func { - attr (@name) definiens_node = @func - edge @func.after_scope -> @name - edge @name -> @func.call + attr (@name.def) definiens_node = @func + edge @func.after_scope -> @name.def + edge @name.def -> @func.call edge @func.call -> @func.return_value edge @body.before_scope -> @params.after_scope edge @body.before_scope -> @func.drop_scope edge @func.drop_scope -> @func.bottom attr (@func.drop_scope) type = "drop_scopes" - attr (@name) node_definition = @name + attr (@name.def) node_definition = @name attr (@func.call) pop_scoped_symbol = "()" edge @params.before_scope -> JUMP_TO_SCOPE_NODE attr (@func.return_value) is_exported @@ -510,7 +510,7 @@ inherit .super_scope (class_definition (block (function_definition name: (_)@name))) ] { - attr (@name) syntax_type = "method" + attr (@name.def) syntax_type = "method" } [ @@ -551,7 +551,7 @@ inherit .super_scope (function_definition (block (function_definition name: (_)@name))) ] { - attr (@name) syntax_type = "function" + attr (@name.def) syntax_type = "function" } ;; @@ -586,12 +586,12 @@ inherit .super_scope value: (_) @value) @param ] { - attr (@name) node_definition = @name + attr (@name.def) node_definition = @name attr (@param.param_name) push_node = @name - edge @name -> @param.param_name - edge @name -> @param.param_index - edge @param.input -> @name - edge @name -> @value.output + edge @name.def -> @param.param_name + edge @name.def -> @param.param_index + edge @param.input -> @name.def + edge @name.def -> @value.output } [ @@ -603,11 +603,11 @@ inherit .super_scope (_) @name) @param ] { - attr (@name) node_definition = @name + attr (@name.def) node_definition = @name attr (@param.param_name) push_node = @name - edge @name -> @param.param_name - edge @name -> @param.param_index - edge @param.input -> @name + edge @name.def -> @param.param_name + edge @name.def -> @param.param_index + edge @param.input -> @name.def } [ @@ -642,13 +642,13 @@ inherit .super_scope (class_definition name: (identifier) @name) @class { - attr (@name) definiens_node = @class - attr (@name) syntax_type = "class" + attr (@name.def) definiens_node = @class + attr (@name.def) syntax_type = "class" edge @class.parent_scope -> @class.class_parent_scope edge @class.parent_scope -> @class.local_scope - edge @class.after_scope -> @name - edge @name -> @class.call - edge @name -> @class.dot + edge @class.after_scope -> @name.def + edge @name.def -> @class.call + edge @name.def -> @class.dot edge @class.dot -> @class.members edge @class.call -> @class.call_drop edge @class.call_drop -> @class.self_scope @@ -660,7 +660,7 @@ inherit .super_scope attr (@class.call_drop) type = "drop_scopes" attr (@class.dot) pop_symbol = "." attr (@class.self_dot) pop_symbol = "." - attr (@name) node_definition = @name + attr (@name.def) node_definition = @name attr (@class.member_attrs) push_symbol = "." attr (@class.self_scope) is_exported let @class.super_scope = @class.super_scope From e614b60205d9e2c784a33f6aa5cf0038c7d57a42 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 2 Jun 2023 10:58:43 +0200 Subject: [PATCH 339/500] convert: super scope --- .../src/stack-graphs.tsg | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index e3b54923e..f9d0fc0e2 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -84,13 +84,13 @@ inherit .bottom inherit .class_member_attr_scope inherit .class_parent_scope inherit .class_self_scope +inherit .class_super_scope inherit .function_returns inherit .global inherit .global_dot inherit .grandparent_module inherit .local_scope inherit .parent_module -inherit .super_scope ; Modules and Imports ;--------------------- @@ -663,10 +663,10 @@ inherit .super_scope attr (@name.def) node_definition = @name attr (@class.member_attrs) push_symbol = "." attr (@class.self_scope) is_exported - let @class.super_scope = @class.super_scope + let @class.class_member_attr_scope = @class.member_attrs let @class.class_parent_scope = @class.parent_scope let @class.class_self_scope = @class.call_drop - let @class.class_member_attr_scope = @class.member_attrs + let @class.class_super_scope = @class.super_scope } (class_definition @@ -680,7 +680,7 @@ inherit .super_scope superclasses: (argument_list (_) @superclass)) @class { - edge @class.super_scope -> @superclass.output + edge @class.class_super_scope -> @superclass.output } (decorated_definition @@ -753,7 +753,7 @@ inherit .super_scope (#eq? @_fn_name "super") ) { - edge @call.output -> @call.super_scope + edge @call.output -> @call.class_super_scope } [ From cd0255c73212b671471152336261c96d65acb20c Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 2 Jun 2023 11:15:53 +0200 Subject: [PATCH 340/500] convert: duplicate edge --- .../tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 5 ----- 1 file changed, 5 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index f9d0fc0e2..e19ffdac0 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -407,11 +407,6 @@ inherit .parent_module edge @stmt.before_scope -> @block.before_scope } -(block (_) @stmt . ) @block -{ - edge @block.after_scope -> @stmt.after_scope -} - (function_definition (block) @block) { edge @block.before_scope -> @block.local_scope From 307e03cb757b47041fd32ac93b463b58261a3474 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 2 Jun 2023 11:17:10 +0200 Subject: [PATCH 341/500] convert: duplicate stanza --- .../tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 8 -------- 1 file changed, 8 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index e19ffdac0..91376a956 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -200,14 +200,6 @@ inherit .parent_module attr (@root_name.ref) node_reference = @root_name } -(import_from_statement - module_name: (dotted_name - . (identifier) @prefix_root_name)) -{ - edge @prefix_root_name.ref -> ROOT_NODE - attr (@prefix_root_name.ref) node_reference = @prefix_root_name -} - (import_from_statement name: (dotted_name . (identifier) @import_root_name)) @stmt From 861fbca8f7473c396251be296182d6ca45e1f1c1 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 2 Jun 2023 11:25:15 +0200 Subject: [PATCH 342/500] convert: one more syntax node used directly as grap hnode --- languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 91376a956..3083dcff6 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -250,7 +250,7 @@ inherit .parent_module alias: (identifier) @alias)) ] @stmt { - edge @stmt.after_scope -> @alias + edge @stmt.after_scope -> @alias.def edge @alias.def -> @name.ref attr (@alias.def) node_definition = @alias } From 7aa54c8bd6bac0d694527c8dc09c50ed1be76f04 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 2 Jun 2023 11:29:06 +0200 Subject: [PATCH 343/500] convert: toplevel dummy values for inherited variables --- .../tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 3083dcff6..851d358ff 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -178,6 +178,14 @@ inherit .parent_module let @mod.bottom = @mod.after_scope let @mod.global = global let @mod.global_dot = global_dot + + ;; add a dummy nodes for inherited variables + node @mod.class_member_attr_scope + node @mod.class_parent_scope + node @mod.class_self_scope + node @mod.class_super_scope + node @mod.function_returns + node @mod.local_scope } (import_statement From 1624d70afd320e5c061100a2167966ad0c76ccb9 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 2 Jun 2023 11:31:11 +0200 Subject: [PATCH 344/500] convert: duplicate attribute --- .../tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 851d358ff..63831ff7d 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -782,13 +782,13 @@ inherit .parent_module (pattern/attribute attribute: (identifier) @name) { - attr (@name.input) node_definition = @name + attr (@name.input) is_definition } (primary_expression/attribute attribute: (identifier) @name) { - attr (@name.output) node_reference = @name + attr (@name.output) is_reference } (primary_expression/identifier) @id From 5318655f366e714e085dbf5fc8818310eaea26f5 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 2 Jun 2023 11:33:55 +0200 Subject: [PATCH 345/500] convert: graph node for argument_list --- .../tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 63831ff7d..de8198d25 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -704,7 +704,7 @@ inherit .parent_module { edge @call.output -> @call.output_args edge @call.output_args -> @fn.output - attr (@call.output_args) push_scoped_symbol = "()", scope = @args + attr (@call.output_args) push_scoped_symbol = "()", scope = @args.def } (call @@ -713,7 +713,7 @@ inherit .parent_module arguments: (argument_list (expression) @arg) @args) { - edge @args -> @arg.arg_index + edge @args.def -> @arg.arg_index edge @receiver -> @receiver.arg_index attr (@receiver.arg_index) pop_symbol = "0" @@ -729,7 +729,7 @@ inherit .parent_module name: (identifier) @name value: (_) @val) @arg) @args) { - edge @args -> @arg.arg_name + edge @args.def -> @arg.arg_name attr (@arg.arg_name) pop_node = @name edge @arg.arg_name -> @val.output } @@ -737,7 +737,7 @@ inherit .parent_module (argument_list (expression) @arg) @args { - edge @args -> @arg.arg_index + edge @args.def -> @arg.arg_index attr (@arg.arg_index) pop_symbol = (child-index @arg) edge @arg.arg_index -> @arg.output } From ec0f61b6cd93232e57ccb8db0606fcf778b70b25 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 2 Jun 2023 11:34:28 +0200 Subject: [PATCH 346/500] convert: function name --- languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index de8198d25..105c576af 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -738,7 +738,7 @@ inherit .parent_module (expression) @arg) @args { edge @args.def -> @arg.arg_index - attr (@arg.arg_index) pop_symbol = (child-index @arg) + attr (@arg.arg_index) pop_symbol = (named-child-index @arg) edge @arg.arg_index -> @arg.output } From 38595361d9b6fbde5567098c98faffad26244c19 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 2 Jun 2023 11:36:01 +0200 Subject: [PATCH 347/500] convert: export scope --- languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 105c576af..d5d980e10 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -705,6 +705,7 @@ inherit .parent_module edge @call.output -> @call.output_args edge @call.output_args -> @fn.output attr (@call.output_args) push_scoped_symbol = "()", scope = @args.def + attr (@args.def) is_exported } (call From 02f4b5e56aa0a22a6aac52c77676c78057fefa5e Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 2 Jun 2023 11:37:19 +0200 Subject: [PATCH 348/500] convert: function name --- .../src/stack-graphs.tsg | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index d5d980e10..8b176f66c 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -613,17 +613,17 @@ inherit .parent_module let statement_scope = @list.local_scope let @pattern.local_scope = @pattern.pattern_before_scope edge statement_scope -> @pattern.local_scope - attr (statement_scope -> @pattern.local_scope) precedence = (plus 1 (child-index @pattern)) + attr (statement_scope -> @pattern.local_scope) precedence = (plus 1 (named-child-index @pattern)) edge @pattern.pattern_index -> @list.input edge @pattern.input -> @pattern.pattern_index - attr (@pattern.pattern_index) push_symbol = (child-index @pattern) + attr (@pattern.pattern_index) push_symbol = (named-child-index @pattern) } (parameters (_) @param) @params { - attr (@param.param_index) push_symbol = (child-index @param) + attr (@param.param_index) push_symbol = (named-child-index @param) edge @param.param_index -> @params.before_scope edge @params.after_scope -> @param.input edge @param.param_name -> @params.before_scope @@ -720,7 +720,7 @@ inherit .parent_module attr (@receiver.arg_index) pop_symbol = "0" edge @receiver.arg_index -> @receiver.output - attr (@arg.arg_index) pop_symbol = (plus 1 (child-index @arg)) + attr (@arg.arg_index) pop_symbol = (plus 1 (named-child-index @arg)) edge @arg.arg_index -> @arg.output } @@ -758,7 +758,7 @@ inherit .parent_module ] @tuple { edge @tuple.output -> @element.el_index - attr (@element.el_index) pop_symbol = (child-index @element) + attr (@element.el_index) pop_symbol = (named-child-index @element) edge @element.el_index -> @element.output edge @tuple.new_bindings -> @element.new_bindings From 6e39e4a4787df62abf6d264ad2ef232209f36df2 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 2 Jun 2023 11:53:22 +0200 Subject: [PATCH 349/500] convert: argument lists --- .../src/stack-graphs.tsg | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 8b176f66c..8d1adf538 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -41,8 +41,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n (_)@node { node @node.after_scope - node @node.arg_index - node @node.arg_name node @node.before_scope node @node.call node @node.call_drop @@ -702,10 +700,12 @@ inherit .parent_module function: (_) @fn arguments: (argument_list) @args) @call { + node @args.args + attr (@args.args) is_exported + edge @call.output -> @call.output_args edge @call.output_args -> @fn.output - attr (@call.output_args) push_scoped_symbol = "()", scope = @args.def - attr (@args.def) is_exported + attr (@call.output_args) push_scoped_symbol = "()", scope = @args.args } (call @@ -714,33 +714,37 @@ inherit .parent_module arguments: (argument_list (expression) @arg) @args) { - edge @args.def -> @arg.arg_index - edge @receiver -> @receiver.arg_index - - attr (@receiver.arg_index) pop_symbol = "0" - edge @receiver.arg_index -> @receiver.output + node receiver_arg_index + attr (receiver_arg_index) pop_symbol = "0" + edge @args.args -> receiver_arg_index + edge receiver_arg_index -> @receiver.output - attr (@arg.arg_index) pop_symbol = (plus 1 (named-child-index @arg)) - edge @arg.arg_index -> @arg.output + ;; FIXME the arguments will also exist with their unshifted indices because of the general + ;; rule below! + node arg_index + attr (arg_index) pop_symbol = (plus 1 (named-child-index @arg)) + edge arg_index -> @arg.output } (call arguments: (argument_list (keyword_argument name: (identifier) @name - value: (_) @val) @arg) @args) + value: (_) @val)) @args) { - edge @args.def -> @arg.arg_name - attr (@arg.arg_name) pop_node = @name - edge @arg.arg_name -> @val.output + node arg_name + edge @args.args -> arg_name + attr (arg_name) pop_node = @name + edge arg_name -> @val.output } (argument_list (expression) @arg) @args { - edge @args.def -> @arg.arg_index - attr (@arg.arg_index) pop_symbol = (named-child-index @arg) - edge @arg.arg_index -> @arg.output + node arg_index + edge @args.args -> arg_index + attr (arg_index) pop_symbol = (named-child-index @arg) + edge arg_index -> @arg.output } ( From ac61586343112446eaf3e3f1a60d6306a6402118 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 2 Jun 2023 12:19:10 +0200 Subject: [PATCH 350/500] convert: duplicate edges --- .../tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 8d1adf538..090790af3 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -213,8 +213,6 @@ inherit .parent_module edge @stmt.after_scope -> @import_root_name.def attr (@stmt.after_scope -> @import_root_name.def) precedence = 1 edge @import_root_name.ref -> @import_root_name.ref_dot - attr (@import_root_name.def) node_definition = @import_root_name - attr (@import_root_name.ref) node_reference = @import_root_name attr (@import_root_name.ref_dot) push_symbol = "." } @@ -825,12 +823,8 @@ inherit .parent_module (expression) @value alias: (as_pattern_target (primary_expression/identifier) @id)) @as_pattern { - edge @id.output -> @id.local_scope - edge @id.output -> @id.class_parent_scope - edge @id.local_scope -> @id.input attr (@id.local_scope -> @id.input) precedence = 1 - attr (@id.input) node_definition = @id - attr (@id.output) push_node = @id + attr (@id.input) is_definition edge @as_pattern.new_bindings -> @value.new_bindings edge @as_pattern.new_bindings -> @id.new_bindings From a127916f7511bac46cac77c7ab6aa108925699dd Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 2 Jun 2023 12:33:05 +0200 Subject: [PATCH 351/500] convert: duplicate edges --- languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 2 -- 1 file changed, 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 090790af3..1d79c8e1f 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -268,8 +268,6 @@ inherit .parent_module (identifier) @leaf_name .)) ] { - attr (@leaf_name.def) node_definition = @leaf_name - attr (@leaf_name.ref) node_reference = @leaf_name edge @leaf_name.def -> @leaf_name.ref } From 6407b1dba56dfd876827ad2b8a2fb809e39a3011 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 2 Jun 2023 12:34:46 +0200 Subject: [PATCH 352/500] convert: always create .args --- .../tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 1d79c8e1f..a88151398 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -696,9 +696,6 @@ inherit .parent_module function: (_) @fn arguments: (argument_list) @args) @call { - node @args.args - attr (@args.args) is_exported - edge @call.output -> @call.output_args edge @call.output_args -> @fn.output attr (@call.output_args) push_scoped_symbol = "()", scope = @args.args @@ -734,6 +731,11 @@ inherit .parent_module edge arg_name -> @val.output } +(argument_list) @args { + node @args.args + attr (@args.args) is_exported +} + (argument_list (expression) @arg) @args { From d5d312ecebab9f351b2727d2af93e6fe009fd0d7 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 2 Jun 2023 12:36:13 +0200 Subject: [PATCH 353/500] Enable tests --- .../test/{legacy.skip => }/aliased_imports.py | 0 .../test/{legacy.skip => }/attributes.py | 0 .../test/{legacy.skip => }/blocks.py | 0 .../test/{legacy.skip => }/chained_functions.py | 0 .../{legacy.skip/chained_methods.py => chained_methods.py.skip} | 0 .../test/{legacy.skip => }/class_members.py | 0 .../test/{legacy.skip => }/decorators.py | 0 .../test/{legacy.skip => }/exceptions.py | 0 .../test/{legacy.skip => }/functions.py | 0 .../test/{legacy.skip => }/imported_functions.py | 0 .../test/{legacy.skip => }/imports.py | 0 .../test/{legacy.skip => }/instance_members.py | 0 .../test/{legacy.skip => }/loops.py | 0 .../test/{legacy.skip => }/many_definitions.py | 0 .../test/{legacy.skip => }/pattern_matching.py | 0 .../test/{legacy.skip => }/redundant_reexport.py | 0 .../test/{legacy.skip => }/relative_imports.py | 0 .../test/{legacy.skip => }/statement_bindings.py | 0 .../test/{legacy.skip => }/superclasses.py | 0 .../test/{legacy.skip => }/test.py | 0 .../test/{legacy.skip => }/tuples.py | 0 .../test/{legacy.skip => }/wildcard_import.py | 0 22 files changed, 0 insertions(+), 0 deletions(-) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/aliased_imports.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/attributes.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/blocks.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/chained_functions.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip/chained_methods.py => chained_methods.py.skip} (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/class_members.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/decorators.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/exceptions.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/functions.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/imported_functions.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/imports.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/instance_members.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/loops.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/many_definitions.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/pattern_matching.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/redundant_reexport.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/relative_imports.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/statement_bindings.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/superclasses.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/test.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/tuples.py (100%) rename languages/tree-sitter-stack-graphs-python/test/{legacy.skip => }/wildcard_import.py (100%) diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/aliased_imports.py b/languages/tree-sitter-stack-graphs-python/test/aliased_imports.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/aliased_imports.py rename to languages/tree-sitter-stack-graphs-python/test/aliased_imports.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/attributes.py b/languages/tree-sitter-stack-graphs-python/test/attributes.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/attributes.py rename to languages/tree-sitter-stack-graphs-python/test/attributes.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/blocks.py b/languages/tree-sitter-stack-graphs-python/test/blocks.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/blocks.py rename to languages/tree-sitter-stack-graphs-python/test/blocks.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/chained_functions.py b/languages/tree-sitter-stack-graphs-python/test/chained_functions.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/chained_functions.py rename to languages/tree-sitter-stack-graphs-python/test/chained_functions.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/chained_methods.py b/languages/tree-sitter-stack-graphs-python/test/chained_methods.py.skip similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/chained_methods.py rename to languages/tree-sitter-stack-graphs-python/test/chained_methods.py.skip diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/class_members.py b/languages/tree-sitter-stack-graphs-python/test/class_members.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/class_members.py rename to languages/tree-sitter-stack-graphs-python/test/class_members.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/decorators.py b/languages/tree-sitter-stack-graphs-python/test/decorators.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/decorators.py rename to languages/tree-sitter-stack-graphs-python/test/decorators.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/exceptions.py b/languages/tree-sitter-stack-graphs-python/test/exceptions.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/exceptions.py rename to languages/tree-sitter-stack-graphs-python/test/exceptions.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/functions.py b/languages/tree-sitter-stack-graphs-python/test/functions.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/functions.py rename to languages/tree-sitter-stack-graphs-python/test/functions.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/imported_functions.py b/languages/tree-sitter-stack-graphs-python/test/imported_functions.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/imported_functions.py rename to languages/tree-sitter-stack-graphs-python/test/imported_functions.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/imports.py b/languages/tree-sitter-stack-graphs-python/test/imports.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/imports.py rename to languages/tree-sitter-stack-graphs-python/test/imports.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/instance_members.py b/languages/tree-sitter-stack-graphs-python/test/instance_members.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/instance_members.py rename to languages/tree-sitter-stack-graphs-python/test/instance_members.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/loops.py b/languages/tree-sitter-stack-graphs-python/test/loops.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/loops.py rename to languages/tree-sitter-stack-graphs-python/test/loops.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/many_definitions.py b/languages/tree-sitter-stack-graphs-python/test/many_definitions.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/many_definitions.py rename to languages/tree-sitter-stack-graphs-python/test/many_definitions.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/pattern_matching.py b/languages/tree-sitter-stack-graphs-python/test/pattern_matching.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/pattern_matching.py rename to languages/tree-sitter-stack-graphs-python/test/pattern_matching.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/redundant_reexport.py b/languages/tree-sitter-stack-graphs-python/test/redundant_reexport.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/redundant_reexport.py rename to languages/tree-sitter-stack-graphs-python/test/redundant_reexport.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/relative_imports.py b/languages/tree-sitter-stack-graphs-python/test/relative_imports.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/relative_imports.py rename to languages/tree-sitter-stack-graphs-python/test/relative_imports.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/statement_bindings.py b/languages/tree-sitter-stack-graphs-python/test/statement_bindings.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/statement_bindings.py rename to languages/tree-sitter-stack-graphs-python/test/statement_bindings.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/superclasses.py b/languages/tree-sitter-stack-graphs-python/test/superclasses.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/superclasses.py rename to languages/tree-sitter-stack-graphs-python/test/superclasses.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/test.py b/languages/tree-sitter-stack-graphs-python/test/test.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/test.py rename to languages/tree-sitter-stack-graphs-python/test/test.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/tuples.py b/languages/tree-sitter-stack-graphs-python/test/tuples.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/tuples.py rename to languages/tree-sitter-stack-graphs-python/test/tuples.py diff --git a/languages/tree-sitter-stack-graphs-python/test/legacy.skip/wildcard_import.py b/languages/tree-sitter-stack-graphs-python/test/wildcard_import.py similarity index 100% rename from languages/tree-sitter-stack-graphs-python/test/legacy.skip/wildcard_import.py rename to languages/tree-sitter-stack-graphs-python/test/wildcard_import.py From 8d8c7e07b4ca3e9515af1bf58c2f1e22e036e332 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 2 Jun 2023 19:06:30 +0200 Subject: [PATCH 354/500] convert: comment out syntax_type and definiens_node which are not yet supported --- .../src/stack-graphs.tsg | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index a88151398..23b69b499 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -462,7 +462,7 @@ inherit .parent_module parameters: (parameters) @params body: (block) @body) @func { - attr (@name.def) definiens_node = @func +; attr (@name.def) definiens_node = @func edge @func.after_scope -> @name.def edge @name.def -> @func.call edge @func.call -> @func.return_value @@ -495,52 +495,52 @@ inherit .parent_module ;; [ - (class_definition (block (decorated_definition (function_definition name: (_)@name)))) - (class_definition (block (function_definition name: (_)@name))) + (class_definition (block (decorated_definition (function_definition name: (_)@_name)))) + (class_definition (block (function_definition name: (_)@_name))) ] { - attr (@name.def) syntax_type = "method" +; attr (@name.def) syntax_type = "method" } [ - (module (decorated_definition (function_definition name: (_)@name))) - (module (function_definition name: (_)@name)) + (module (decorated_definition (function_definition name: (_)@_name))) + (module (function_definition name: (_)@_name)) - (if_statement (block (decorated_definition (function_definition name: (_)@name)))) - (if_statement (block (function_definition name: (_)@name))) + (if_statement (block (decorated_definition (function_definition name: (_)@_name)))) + (if_statement (block (function_definition name: (_)@_name))) - (elif_clause (block (decorated_definition (function_definition name: (_)@name)))) - (elif_clause (block (function_definition name: (_)@name))) + (elif_clause (block (decorated_definition (function_definition name: (_)@_name)))) + (elif_clause (block (function_definition name: (_)@_name))) - (else_clause (block (decorated_definition (function_definition name: (_)@name)))) - (else_clause (block (function_definition name: (_)@name))) + (else_clause (block (decorated_definition (function_definition name: (_)@_name)))) + (else_clause (block (function_definition name: (_)@_name))) - (case_clause (block (decorated_definition (function_definition name: (_)@name)))) - (case_clause (block (function_definition name: (_)@name))) + (case_clause (block (decorated_definition (function_definition name: (_)@_name)))) + (case_clause (block (function_definition name: (_)@_name))) - (for_statement (block (decorated_definition (function_definition name: (_)@name)))) - (for_statement (block (function_definition name: (_)@name))) + (for_statement (block (decorated_definition (function_definition name: (_)@_name)))) + (for_statement (block (function_definition name: (_)@_name))) - (while_statement (block (decorated_definition (function_definition name: (_)@name)))) - (while_statement (block (function_definition name: (_)@name))) + (while_statement (block (decorated_definition (function_definition name: (_)@_name)))) + (while_statement (block (function_definition name: (_)@_name))) - (try_statement (block (decorated_definition (function_definition name: (_)@name)))) - (try_statement (block (function_definition name: (_)@name))) + (try_statement (block (decorated_definition (function_definition name: (_)@_name)))) + (try_statement (block (function_definition name: (_)@_name))) - (except_clause (block (decorated_definition (function_definition name: (_)@name)))) - (except_clause (block (function_definition name: (_)@name))) + (except_clause (block (decorated_definition (function_definition name: (_)@_name)))) + (except_clause (block (function_definition name: (_)@_name))) - (finally_clause (block (decorated_definition (function_definition name: (_)@name)))) - (finally_clause (block (function_definition name: (_)@name))) + (finally_clause (block (decorated_definition (function_definition name: (_)@_name)))) + (finally_clause (block (function_definition name: (_)@_name))) - (with_statement (block (decorated_definition (function_definition name: (_)@name)))) - (with_statement (block (function_definition name: (_)@name))) + (with_statement (block (decorated_definition (function_definition name: (_)@_name)))) + (with_statement (block (function_definition name: (_)@_name))) - (function_definition (block (decorated_definition (function_definition name: (_)@name)))) - (function_definition (block (function_definition name: (_)@name))) + (function_definition (block (decorated_definition (function_definition name: (_)@_name)))) + (function_definition (block (function_definition name: (_)@_name))) ] { - attr (@name.def) syntax_type = "function" +; attr (@name.def) syntax_type = "function" } ;; @@ -631,8 +631,8 @@ inherit .parent_module (class_definition name: (identifier) @name) @class { - attr (@name.def) definiens_node = @class - attr (@name.def) syntax_type = "class" +; attr (@name.def) definiens_node = @class +; attr (@name.def) syntax_type = "class" edge @class.parent_scope -> @class.class_parent_scope edge @class.parent_scope -> @class.local_scope edge @class.after_scope -> @name.def From e44bad923c8f91e788e6a3ed18e093e6ca7f4ba4 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 15 Nov 2023 12:06:56 +0100 Subject: [PATCH 355/500] Re-enable syntax_type and definiens_node --- .../src/stack-graphs.tsg | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 23b69b499..a88151398 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -462,7 +462,7 @@ inherit .parent_module parameters: (parameters) @params body: (block) @body) @func { -; attr (@name.def) definiens_node = @func + attr (@name.def) definiens_node = @func edge @func.after_scope -> @name.def edge @name.def -> @func.call edge @func.call -> @func.return_value @@ -495,52 +495,52 @@ inherit .parent_module ;; [ - (class_definition (block (decorated_definition (function_definition name: (_)@_name)))) - (class_definition (block (function_definition name: (_)@_name))) + (class_definition (block (decorated_definition (function_definition name: (_)@name)))) + (class_definition (block (function_definition name: (_)@name))) ] { -; attr (@name.def) syntax_type = "method" + attr (@name.def) syntax_type = "method" } [ - (module (decorated_definition (function_definition name: (_)@_name))) - (module (function_definition name: (_)@_name)) + (module (decorated_definition (function_definition name: (_)@name))) + (module (function_definition name: (_)@name)) - (if_statement (block (decorated_definition (function_definition name: (_)@_name)))) - (if_statement (block (function_definition name: (_)@_name))) + (if_statement (block (decorated_definition (function_definition name: (_)@name)))) + (if_statement (block (function_definition name: (_)@name))) - (elif_clause (block (decorated_definition (function_definition name: (_)@_name)))) - (elif_clause (block (function_definition name: (_)@_name))) + (elif_clause (block (decorated_definition (function_definition name: (_)@name)))) + (elif_clause (block (function_definition name: (_)@name))) - (else_clause (block (decorated_definition (function_definition name: (_)@_name)))) - (else_clause (block (function_definition name: (_)@_name))) + (else_clause (block (decorated_definition (function_definition name: (_)@name)))) + (else_clause (block (function_definition name: (_)@name))) - (case_clause (block (decorated_definition (function_definition name: (_)@_name)))) - (case_clause (block (function_definition name: (_)@_name))) + (case_clause (block (decorated_definition (function_definition name: (_)@name)))) + (case_clause (block (function_definition name: (_)@name))) - (for_statement (block (decorated_definition (function_definition name: (_)@_name)))) - (for_statement (block (function_definition name: (_)@_name))) + (for_statement (block (decorated_definition (function_definition name: (_)@name)))) + (for_statement (block (function_definition name: (_)@name))) - (while_statement (block (decorated_definition (function_definition name: (_)@_name)))) - (while_statement (block (function_definition name: (_)@_name))) + (while_statement (block (decorated_definition (function_definition name: (_)@name)))) + (while_statement (block (function_definition name: (_)@name))) - (try_statement (block (decorated_definition (function_definition name: (_)@_name)))) - (try_statement (block (function_definition name: (_)@_name))) + (try_statement (block (decorated_definition (function_definition name: (_)@name)))) + (try_statement (block (function_definition name: (_)@name))) - (except_clause (block (decorated_definition (function_definition name: (_)@_name)))) - (except_clause (block (function_definition name: (_)@_name))) + (except_clause (block (decorated_definition (function_definition name: (_)@name)))) + (except_clause (block (function_definition name: (_)@name))) - (finally_clause (block (decorated_definition (function_definition name: (_)@_name)))) - (finally_clause (block (function_definition name: (_)@_name))) + (finally_clause (block (decorated_definition (function_definition name: (_)@name)))) + (finally_clause (block (function_definition name: (_)@name))) - (with_statement (block (decorated_definition (function_definition name: (_)@_name)))) - (with_statement (block (function_definition name: (_)@_name))) + (with_statement (block (decorated_definition (function_definition name: (_)@name)))) + (with_statement (block (function_definition name: (_)@name))) - (function_definition (block (decorated_definition (function_definition name: (_)@_name)))) - (function_definition (block (function_definition name: (_)@_name))) + (function_definition (block (decorated_definition (function_definition name: (_)@name)))) + (function_definition (block (function_definition name: (_)@name))) ] { -; attr (@name.def) syntax_type = "function" + attr (@name.def) syntax_type = "function" } ;; @@ -631,8 +631,8 @@ inherit .parent_module (class_definition name: (identifier) @name) @class { -; attr (@name.def) definiens_node = @class -; attr (@name.def) syntax_type = "class" + attr (@name.def) definiens_node = @class + attr (@name.def) syntax_type = "class" edge @class.parent_scope -> @class.class_parent_scope edge @class.parent_scope -> @class.local_scope edge @class.after_scope -> @name.def From 5a63def5d66fd5ef048d219f3abf3525dbc7e380 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 15 Nov 2023 12:07:26 +0100 Subject: [PATCH 356/500] Don't crash visualization on self edges --- stack-graphs/src/visualization/visualization.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/stack-graphs/src/visualization/visualization.js b/stack-graphs/src/visualization/visualization.js index 116850791..6fdab1ef6 100644 --- a/stack-graphs/src/visualization/visualization.js +++ b/stack-graphs/src/visualization/visualization.js @@ -24,6 +24,7 @@ class StackGraph { this.graph = graph; this.paths = paths; + this.cleanup_data(); this.compute_data(); this.current_node = null; @@ -33,6 +34,19 @@ class StackGraph { this.render(); } + cleanup_data() { + let idx = 0; + while (idx < this.graph.edges.length) { + let edge = this.graph.edges[idx]; + if (edge.source.file === edge.sink.file && edge.source.local_id === edge.sink.local_id) { + console.log("ignoring self loop", edge); + this.graph.edges.splice(idx, 1); + } else { + idx += 1; + } + } + } + compute_data() { this.F = {}; this.ID = {}; @@ -47,7 +61,6 @@ class StackGraph { const file = graph.files[i]; this.F[file] = i; } - console.log(this.F); } compute_node_data() { From fe70ba08f34bfec2aa9cb485117ba4ceb827fc65 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 15 Nov 2023 12:21:09 +0100 Subject: [PATCH 357/500] Cleanup accidental self loop --- .../src/stack-graphs.tsg | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index a88151398..d538431b0 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -64,7 +64,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.output_dot node @node.param_index node @node.param_name - node @node.parent_scope node @node.pattern_before_scope node @node.pattern_index node @node.ref @@ -633,8 +632,6 @@ inherit .parent_module { attr (@name.def) definiens_node = @class attr (@name.def) syntax_type = "class" - edge @class.parent_scope -> @class.class_parent_scope - edge @class.parent_scope -> @class.local_scope edge @class.after_scope -> @name.def edge @name.def -> @class.call edge @name.def -> @class.dot @@ -652,10 +649,17 @@ inherit .parent_module attr (@name.def) node_definition = @name attr (@class.member_attrs) push_symbol = "." attr (@class.self_scope) is_exported - let @class.class_member_attr_scope = @class.member_attrs - let @class.class_parent_scope = @class.parent_scope - let @class.class_self_scope = @class.call_drop - let @class.class_super_scope = @class.super_scope +} + +(class_definition + body: (_) @body) @class +{ + let @body.class_member_attr_scope = @class.member_attrs + node @body.class_parent_scope + edge @body.class_parent_scope -> @class.class_parent_scope + edge @body.class_parent_scope -> @class.local_scope + let @body.class_self_scope = @class.call_drop + let @body.class_super_scope = @class.super_scope } (class_definition @@ -669,7 +673,7 @@ inherit .parent_module superclasses: (argument_list (_) @superclass)) @class { - edge @class.class_super_scope -> @superclass.output + edge @class.super_scope -> @superclass.output } (decorated_definition From dbfb1720f2347ba6afb38cab6c27402c2d10bca1 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 15 Nov 2023 12:40:08 +0100 Subject: [PATCH 358/500] Fix module start lines and do not expect definitions at assertion position --- .../test/aliased_imports.py | 2 +- .../tree-sitter-stack-graphs-python/test/imports.py | 10 +++++----- .../test/relative_imports.py | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/test/aliased_imports.py b/languages/tree-sitter-stack-graphs-python/test/aliased_imports.py index d988757a5..0373a33be 100644 --- a/languages/tree-sitter-stack-graphs-python/test/aliased_imports.py +++ b/languages/tree-sitter-stack-graphs-python/test/aliased_imports.py @@ -24,7 +24,7 @@ class D: # ^ defined: print f.B -# ^ defined: 2, 15 +# ^ defined: 3, 15 # ^ defined: 7 print foo diff --git a/languages/tree-sitter-stack-graphs-python/test/imports.py b/languages/tree-sitter-stack-graphs-python/test/imports.py index 2f21795da..96d561813 100644 --- a/languages/tree-sitter-stack-graphs-python/test/imports.py +++ b/languages/tree-sitter-stack-graphs-python/test/imports.py @@ -15,17 +15,17 @@ #------ path: main.py -------------# from one.two import d, e.c -# ^ defined: 2 -# ^ defined: 6, 17 -# ^ defined: 4, 8, 17 +# ^ defined: 3 +# ^ defined: 6 +# ^ defined: 4, 8 import three -# ^ defined: 11, 22 +# ^ defined: 12 print(d, e.c) # ^ defined: 6, 17 # ^ defined: 4, 17 print three.f -# ^ defined: 11, 22 +# ^ defined: 12, 22 # ^ defined: 13 diff --git a/languages/tree-sitter-stack-graphs-python/test/relative_imports.py b/languages/tree-sitter-stack-graphs-python/test/relative_imports.py index 2d6e14eb4..f14571575 100644 --- a/languages/tree-sitter-stack-graphs-python/test/relative_imports.py +++ b/languages/tree-sitter-stack-graphs-python/test/relative_imports.py @@ -6,7 +6,7 @@ from ..c.d import D print a.A -# ^ defined: 3, 24 +# ^ defined: 3, 25 # ^ defined: 26 print B.bee @@ -52,9 +52,9 @@ class D: # module from .g import G -# ^ defined: 49, 54 +# ^ defined: 49 from ..c import see -# ^ defined: 37, 57 +# ^ defined: 37 E = 1 From 2d8fd6bf0a9fd064782a8a4900d4b75276de9772 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 15 Nov 2023 12:47:47 +0100 Subject: [PATCH 359/500] Factor out identifier rules --- .../src/stack-graphs.tsg | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index d538431b0..80a0a2625 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -192,17 +192,13 @@ inherit .parent_module edge @stmt.after_scope -> @root_name.def attr (@stmt.after_scope -> @root_name.def) precedence = 1 edge @root_name.ref -> ROOT_NODE - attr (@root_name.ref) node_reference = @root_name - attr (@root_name.def) node_definition = @root_name } (import_statement name: (aliased_import - (dotted_name . (identifier) @root_name))) @stmt + (dotted_name . (identifier) @root_name))) { - edge @stmt.after_scope -> @root_name.def edge @root_name.ref -> ROOT_NODE - attr (@root_name.ref) node_reference = @root_name } (import_from_statement @@ -221,7 +217,6 @@ inherit .parent_module . (identifier) @import_root_name))) { edge @import_root_name.ref -> @import_root_name.ref_dot - attr (@import_root_name.ref) node_reference = @import_root_name attr (@import_root_name.ref_dot) push_symbol = "." } @@ -255,7 +250,6 @@ inherit .parent_module { edge @stmt.after_scope -> @alias.def edge @alias.def -> @name.ref - attr (@alias.def) node_definition = @alias } [ @@ -289,7 +283,6 @@ inherit .parent_module (dotted_name . (identifier) @name)) { - attr (@name.ref) node_reference = @name attr (@name.ref_dot) push_symbol = "." edge @name.ref -> @name.ref_dot edge @name.ref_dot -> @prefix.ref @@ -309,7 +302,6 @@ inherit .parent_module (identifier) @child_name)) ] { - attr (@child_name.ref) node_reference = @child_name attr (@child_name.ref_dot) push_symbol = "." edge @child_name.ref -> @child_name.ref_dot edge @child_name.ref_dot -> @parent_name.ref @@ -319,7 +311,6 @@ inherit .parent_module module_name: (dotted_name . (identifier) @root_name)) { - attr (@root_name.ref) node_reference = @root_name edge @root_name.ref -> ROOT_NODE } @@ -357,8 +348,6 @@ inherit .parent_module edge @child_name.ref_dot -> @parent_name.ref edge @parent_name.def -> @parent_name.def_dot edge @parent_name.def_dot -> @child_name.def - attr (@child_name.def) node_definition = @child_name - attr (@child_name.ref) node_reference = @child_name attr (@parent_name.def_dot) pop_symbol = "." attr (@child_name.ref_dot) push_symbol = "." } @@ -442,6 +431,10 @@ inherit .parent_module ; Definitions ;------------- +(identifier) @name { + attr (@name.def) node_definition = @name +} + [ (assignment left: (_) @pattern @@ -469,7 +462,6 @@ inherit .parent_module edge @body.before_scope -> @func.drop_scope edge @func.drop_scope -> @func.bottom attr (@func.drop_scope) type = "drop_scopes" - attr (@name.def) node_definition = @name attr (@func.call) pop_scoped_symbol = "()" edge @params.before_scope -> JUMP_TO_SCOPE_NODE attr (@func.return_value) is_exported @@ -574,7 +566,6 @@ inherit .parent_module value: (_) @value) @param ] { - attr (@name.def) node_definition = @name attr (@param.param_name) push_node = @name edge @name.def -> @param.param_name edge @name.def -> @param.param_index @@ -591,7 +582,6 @@ inherit .parent_module (_) @name) @param ] { - attr (@name.def) node_definition = @name attr (@param.param_name) push_node = @name edge @name.def -> @param.param_name edge @name.def -> @param.param_index @@ -646,7 +636,6 @@ inherit .parent_module attr (@class.call_drop) type = "drop_scopes" attr (@class.dot) pop_symbol = "." attr (@class.self_dot) pop_symbol = "." - attr (@name.def) node_definition = @name attr (@class.member_attrs) push_symbol = "." attr (@class.self_scope) is_exported } @@ -696,6 +685,10 @@ inherit .parent_module ; Expressions ;------------- +(identifier) @name { + attr (@name.ref) node_reference = @name +} + (call function: (_) @fn arguments: (argument_list) @args) @call From fd57fbd4b462d82889464984b1e9fdecd974f668 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 15 Nov 2023 13:07:03 +0100 Subject: [PATCH 360/500] Add bug test --- .../relative_import_resolves_to_itself.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-python/test/bugs.skip/relative_import_resolves_to_itself.py diff --git a/languages/tree-sitter-stack-graphs-python/test/bugs.skip/relative_import_resolves_to_itself.py b/languages/tree-sitter-stack-graphs-python/test/bugs.skip/relative_import_resolves_to_itself.py new file mode 100644 index 000000000..838595ab7 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/bugs.skip/relative_import_resolves_to_itself.py @@ -0,0 +1,14 @@ +#--- path: a/__init__.py ---# +from . import b +# ^ defined: 6 + +#--- path: a/b/__init__.py ---# +B = 'b' + +#--- path: main.py ---# +from a import b +# ^ defined: 6 + +print b.B +# ^ defined: 9, 6 +# ^ defined: 6 \ No newline at end of file From 2f619fa3d72524bca0d7eb64db37596d01eed036 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 15 Nov 2023 13:10:20 +0100 Subject: [PATCH 361/500] Fix Python grammar versions --- languages/tree-sitter-stack-graphs-python/Cargo.toml | 2 +- tree-sitter-stack-graphs/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/Cargo.toml b/languages/tree-sitter-stack-graphs-python/Cargo.toml index 9270879c0..ca123cc0f 100644 --- a/languages/tree-sitter-stack-graphs-python/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-python/Cargo.toml @@ -31,7 +31,7 @@ cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"] anyhow = { version = "1.0", optional = true } clap = { version = "4", optional = true, features = ["derive"] } tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs" } -tree-sitter-python = "0.20.2" +tree-sitter-python = "=0.20.2" [dev-dependencies] anyhow = "1.0" diff --git a/tree-sitter-stack-graphs/Cargo.toml b/tree-sitter-stack-graphs/Cargo.toml index 2de26a86f..d5429304a 100644 --- a/tree-sitter-stack-graphs/Cargo.toml +++ b/tree-sitter-stack-graphs/Cargo.toml @@ -82,4 +82,4 @@ walkdir = { version = "2.3", optional = true } [dev-dependencies] pretty_assertions = "0.7" -tree-sitter-python = "0.19.1" +tree-sitter-python = "=0.19.1" From aae723f0fdf97678224fe91c63542edbe9391054 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 15 Nov 2023 14:18:43 +0100 Subject: [PATCH 362/500] Remove obsolete nodes because of general identifier rules --- .../tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 80a0a2625..945428672 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -56,7 +56,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.input_dot node @node.member_attrs node @node.members - node @node.new_binding_pop node @node.new_bindings node @node.new_bindings_pop node @node.output @@ -799,8 +798,7 @@ inherit .parent_module attr (@id.input) pop_node = @id attr (@id.output) node_reference = @id - attr (@id.new_binding_pop) node_definition = @id - edge @id.new_bindings -> @id.new_binding_pop + edge @id.new_bindings -> @id.def } (pattern/identifier) @id @@ -812,8 +810,7 @@ inherit .parent_module attr (@id.input) node_definition = @id attr (@id.output) push_node = @id - attr (@id.new_binding_pop) node_definition = @id - edge @id.new_bindings -> @id.new_binding_pop + edge @id.new_bindings -> @id.def } (as_pattern From 0b54f6c38a1c031a70c8bdc7aebea59608bd91fc Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 15 Nov 2023 14:30:28 +0100 Subject: [PATCH 363/500] Fix rule to make it similar to others --- languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 945428672..b1845109c 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -854,8 +854,7 @@ inherit .parent_module (list_splat (_) @splatted) @splat { -attr (@splat.new_bindings_pop) node_definition = @splatted -edge @splat.new_bindings -> @splat.new_bindings_pop + edge @splat.new_bindings -> @splatted.new_bindings } (binary_operator From a899983928d3a0be7bae4fcbfce86ae3b9204e6f Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 15 Nov 2023 16:45:48 +0100 Subject: [PATCH 364/500] Reuse general definition for parameters --- .../src/stack-graphs.tsg | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index b1845109c..f86683c8c 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -542,18 +542,18 @@ inherit .parent_module . (identifier) @param) body: (block) @body) { - edge @param.input -> @param.class_self_scope + edge @param.def -> @param.class_self_scope edge @param.class_member_attr_scope -> @param.output edge @param.output -> @body.after_scope attr (@param.output) push_node = @param } -(parameter/identifier) @param +(parameter/identifier) @param @name { - attr (@param.input) node_definition = @param attr (@param.param_name) push_node = @param - edge @param.input -> @param.param_index - edge @param.input -> @param.param_name + edge @name.def -> @param.param_name + edge @name.def -> @param.param_index + edge @param.input -> @name.def } [ From 1668eece08d779b5083e319687f65976d1eb27b2 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 15 Nov 2023 17:01:07 +0100 Subject: [PATCH 365/500] Lower .before_scope and .after_scope --- .../src/stack-graphs.tsg | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index f86683c8c..588f7bcf4 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -39,9 +39,63 @@ attribute node_symbol = node => symbol = (source-text node), source_n ;; Nodes ;; ^^^^^ -(_)@node { +(module) @node { + node @node.after_scope + node @node.before_scope +} + +[ + ; _simple_statement + (future_import_statement) + (import_statement) + (import_from_statement) + (print_statement) + (assert_statement) + (expression_statement) + (return_statement) + (delete_statement) + (raise_statement) + (pass_statement) + (break_statement) + (continue_statement) + (global_statement) + (nonlocal_statement) + (exec_statement) + ; _compund_statement + (if_statement) + (for_statement) + (while_statement) + (try_statement) + (with_statement) + (function_definition) + (class_definition) + (decorated_definition) + (match_statement) + ; block + (block) + ; statement clauses + (elif_clause) + (else_clause) + (case_clause) + (except_clause) + (finally_clause) + (with_clause) +] @node { node @node.after_scope node @node.before_scope +} + +(parameters) @node { + node @node.after_scope + node @node.before_scope +} + +(comment) @node { + node @node.after_scope + node @node.before_scope +} + +(_)@node { node @node.call node @node.call_drop node @node.called From e1a0dcfe805205439b02d7df6258d8c0a1993eea Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 15 Nov 2023 17:06:15 +0100 Subject: [PATCH 366/500] Lower .input and .output --- .../src/stack-graphs.tsg | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 588f7bcf4..740f08233 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -90,9 +90,24 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.before_scope } +[ + (identifier) + (expression) + (expression_list) + (primary_expression) + (pattern) + (pattern_list) + (parameter) +] @node { + node @node.input + node @node.output +} + (comment) @node { node @node.after_scope node @node.before_scope + node @node.input + node @node.output } (_)@node { @@ -106,13 +121,11 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.el_index node @node.file_def node @node.file_ref - node @node.input node @node.input_dot node @node.member_attrs node @node.members node @node.new_bindings node @node.new_bindings_pop - node @node.output node @node.output_args node @node.output_dot node @node.param_index From 94365dcac5aed77022178c1038f393997a7b10e9 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 15 Nov 2023 17:13:25 +0100 Subject: [PATCH 367/500] Lower more nodes --- .../src/stack-graphs.tsg | 50 ++++++++++++------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 740f08233..424cb2349 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -92,6 +92,18 @@ attribute node_symbol = node => symbol = (source-text node), source_n [ (identifier) + (import_prefix) + (wildcard_import) +] @node { + node @node.def + node @node.def_dot + node @node.ref + node @node.ref_dot +} + +[ + (identifier) + (wildcard_import) (expression) (expression_list) (primary_expression) @@ -106,34 +118,30 @@ attribute node_symbol = node => symbol = (source-text node), source_n (comment) @node { node @node.after_scope node @node.before_scope + node @node.def + node @node.def_dot node @node.input node @node.output + node @node.ref + node @node.ref_dot } (_)@node { node @node.call node @node.call_drop node @node.called - node @node.def - node @node.def_dot node @node.dot node @node.drop_scope node @node.el_index - node @node.file_def - node @node.file_ref - node @node.input_dot node @node.member_attrs node @node.members node @node.new_bindings node @node.new_bindings_pop node @node.output_args - node @node.output_dot node @node.param_index node @node.param_name node @node.pattern_before_scope node @node.pattern_index - node @node.ref - node @node.ref_dot node @node.return_value node @node.self_dot node @node.self_scope @@ -160,12 +168,15 @@ inherit .parent_module (module) @mod { - var module_def = @mod.file_def + node mod_file_def + node mod_file_ref + + var module_def = mod_file_def node parent_module_def_node var parent_module_def = parent_module_def_node - var module_ref = @mod.file_ref + var module_ref = mod_file_ref node parent_module_ref_node var parent_module_ref = parent_module_ref_node @@ -222,8 +233,8 @@ inherit .parent_module } } - edge ROOT_NODE -> @mod.file_def - edge @mod.file_ref -> ROOT_NODE + edge ROOT_NODE -> mod_file_def + edge mod_file_ref -> ROOT_NODE edge module_def -> @mod.after_scope node global @@ -833,14 +844,17 @@ inherit .parent_module object: (_) @object attribute: (identifier) @name) @expr { + node input_dot + node output_dot + edge @expr.output -> @name.output - edge @name.output -> @expr.output_dot - edge @expr.output_dot -> @object.output - edge @object.input -> @expr.input_dot - edge @expr.input_dot -> @name.input + edge @name.output -> output_dot + edge output_dot -> @object.output + edge @object.input -> input_dot + edge input_dot -> @name.input edge @name.input -> @expr.input - attr (@expr.output_dot) push_symbol = "." - attr (@expr.input_dot) pop_symbol = "." + attr (output_dot) push_symbol = "." + attr (input_dot) pop_symbol = "." attr (@name.input) pop_node = @name attr (@name.output) push_node = @name } From bb0f034ed92ec2d082ad211a7b7333e41ebe0a3b Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 15 Nov 2023 17:34:48 +0100 Subject: [PATCH 368/500] Lower final set of nodes --- .../src/stack-graphs.tsg | 123 ++++++++++-------- 1 file changed, 68 insertions(+), 55 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 424cb2349..0028994c2 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -109,9 +109,16 @@ attribute node_symbol = node => symbol = (source-text node), source_n (primary_expression) (pattern) (pattern_list) + (case_pattern) (parameter) + (pair) + (list_splat) + (parenthesized_list_splat) + (dictionary_splat) + (keyword_argument) ] @node { node @node.input + node @node.new_bindings node @node.output } @@ -121,33 +128,12 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.def node @node.def_dot node @node.input + node @node.new_bindings node @node.output node @node.ref node @node.ref_dot } -(_)@node { - node @node.call - node @node.call_drop - node @node.called - node @node.dot - node @node.drop_scope - node @node.el_index - node @node.member_attrs - node @node.members - node @node.new_bindings - node @node.new_bindings_pop - node @node.output_args - node @node.param_index - node @node.param_name - node @node.pattern_before_scope - node @node.pattern_index - node @node.return_value - node @node.self_dot - node @node.self_scope - node @node.super_scope -} - ;; Inherited Variables ;; ^^^^^^^^^^^^^^^^^^^ @@ -531,18 +517,22 @@ inherit .parent_module parameters: (parameters) @params body: (block) @body) @func { + node call + node drop_scope + node return_value + attr (@name.def) definiens_node = @func edge @func.after_scope -> @name.def - edge @name.def -> @func.call - edge @func.call -> @func.return_value + edge @name.def -> call + edge call -> return_value edge @body.before_scope -> @params.after_scope - edge @body.before_scope -> @func.drop_scope - edge @func.drop_scope -> @func.bottom - attr (@func.drop_scope) type = "drop_scopes" - attr (@func.call) pop_scoped_symbol = "()" + edge @body.before_scope -> drop_scope + edge drop_scope -> @func.bottom + attr (drop_scope) type = "drop_scopes" + attr (call) pop_scoped_symbol = "()" edge @params.before_scope -> JUMP_TO_SCOPE_NODE - attr (@func.return_value) is_exported - let @func.function_returns = @func.return_value + attr (return_value) is_exported + let @func.function_returns = return_value ; Prevent functions defined inside of method bodies from being treated like methods let @body.class_self_scope = #null @@ -670,19 +660,24 @@ inherit .parent_module (tuple_pattern (_) @pattern) ] @list { + node pattern_index + let statement_scope = @list.local_scope - let @pattern.local_scope = @pattern.pattern_before_scope + node @pattern.local_scope edge statement_scope -> @pattern.local_scope attr (statement_scope -> @pattern.local_scope) precedence = (plus 1 (named-child-index @pattern)) - edge @pattern.pattern_index -> @list.input - edge @pattern.input -> @pattern.pattern_index - attr (@pattern.pattern_index) push_symbol = (named-child-index @pattern) + edge pattern_index -> @list.input + edge @pattern.input -> pattern_index + attr (pattern_index) push_symbol = (named-child-index @pattern) } (parameters (_) @param) @params { + node @param.param_index + node @param.param_name + attr (@param.param_index) push_symbol = (named-child-index @param) edge @param.param_index -> @params.before_scope edge @params.after_scope -> @param.input @@ -694,27 +689,39 @@ inherit .parent_module edge @stmt.function_returns -> @expr.output } +(class_definition) @class { + node @class.call_drop + node @class.member_attrs + node @class.members + node @class.super_scope +} + (class_definition name: (identifier) @name) @class { + node call + node self_dot + node self_scope + node members_dot + attr (@name.def) definiens_node = @class attr (@name.def) syntax_type = "class" edge @class.after_scope -> @name.def - edge @name.def -> @class.call - edge @name.def -> @class.dot - edge @class.dot -> @class.members - edge @class.call -> @class.call_drop - edge @class.call_drop -> @class.self_scope - edge @class.self_scope -> @class.super_scope - edge @class.self_scope -> @class.self_dot - edge @class.self_dot -> @class.members + edge @name.def -> call + edge @name.def -> members_dot + edge members_dot -> @class.members + edge call -> @class.call_drop + edge @class.call_drop -> self_scope + edge self_scope -> @class.super_scope + edge self_scope -> self_dot + edge self_dot -> @class.members edge @class.members -> @class.member_attrs - attr (@class.call) pop_scoped_symbol = "()" + attr (call) pop_scoped_symbol = "()" attr (@class.call_drop) type = "drop_scopes" - attr (@class.dot) pop_symbol = "." - attr (@class.self_dot) pop_symbol = "." + attr (members_dot) pop_symbol = "." + attr (self_dot) pop_symbol = "." attr (@class.member_attrs) push_symbol = "." - attr (@class.self_scope) is_exported + attr (self_scope) is_exported } (class_definition @@ -770,9 +777,11 @@ inherit .parent_module function: (_) @fn arguments: (argument_list) @args) @call { - edge @call.output -> @call.output_args - edge @call.output_args -> @fn.output - attr (@call.output_args) push_scoped_symbol = "()", scope = @args.args + node output_args + + edge @call.output -> output_args + edge output_args -> @fn.output + attr (output_args) push_scoped_symbol = "()", scope = @args.args } (call @@ -833,9 +842,11 @@ inherit .parent_module (expression_list (_) @element) ] @tuple { - edge @tuple.output -> @element.el_index - attr (@element.el_index) pop_symbol = (named-child-index @element) - edge @element.el_index -> @element.output + node el_index + + edge @tuple.output -> el_index + attr (el_index) pop_symbol = (named-child-index @element) + edge el_index -> @element.output edge @tuple.new_bindings -> @element.new_bindings } @@ -907,9 +918,11 @@ inherit .parent_module (list) @list { - edge @list.output -> @list.called - edge @list.called -> @list.global_dot - attr (@list.called) push_symbol = "list" + node called + + edge @list.output -> called + edge called -> @list.global_dot + attr (called) push_symbol = "list" } (list (_) @el) @list From d15cb9b23403907611a093e82e84f4061a7e0c19 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 17 Nov 2023 12:15:55 +0100 Subject: [PATCH 369/500] Add tests --- .../relative_import_resolves_to_itself.py | 14 -------------- .../imports/import_from_module_a_submodule.py | 14 ++++++++++++++ .../test/imports/import_from_module_a_value.py | 13 +++++++++++++ .../import_from_module_a_value_aliased.py | 13 +++++++++++++ .../imports/import_from_module_wildcard.py | 13 +++++++++++++ .../imports/import_from_submodule_a_value.py | 16 ++++++++++++++++ .../import_from_super_package_a_value.py | 10 ++++++++++ ...ort_from_super_package_submodule_a_value.py | 10 ++++++++++ .../import_from_this_package_a_value.py | 10 ++++++++++ ...port_from_this_package_submodule_a_value.py | 10 ++++++++++ .../test/imports/import_module.py | 11 +++++++++++ .../test/imports/import_module_aliased.py | 14 ++++++++++++++ .../test/imports/import_submodule.py | 15 +++++++++++++++ .../imports/import_submodule_aliased.py.skip | 17 +++++++++++++++++ .../relative_import_resolves_to_itself.py.skip | 14 ++++++++++++++ .../require_explicit_submodule_import.py.skip | 18 ++++++++++++++++++ 16 files changed, 198 insertions(+), 14 deletions(-) delete mode 100644 languages/tree-sitter-stack-graphs-python/test/bugs.skip/relative_import_resolves_to_itself.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/imports/import_from_module_a_submodule.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/imports/import_from_module_a_value.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/imports/import_from_module_a_value_aliased.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/imports/import_from_module_wildcard.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/imports/import_from_submodule_a_value.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/imports/import_from_super_package_a_value.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/imports/import_from_super_package_submodule_a_value.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/imports/import_from_this_package_a_value.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/imports/import_from_this_package_submodule_a_value.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/imports/import_module.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/imports/import_module_aliased.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/imports/import_submodule.py create mode 100644 languages/tree-sitter-stack-graphs-python/test/imports/import_submodule_aliased.py.skip create mode 100644 languages/tree-sitter-stack-graphs-python/test/imports/relative_import_resolves_to_itself.py.skip create mode 100644 languages/tree-sitter-stack-graphs-python/test/imports/require_explicit_submodule_import.py.skip diff --git a/languages/tree-sitter-stack-graphs-python/test/bugs.skip/relative_import_resolves_to_itself.py b/languages/tree-sitter-stack-graphs-python/test/bugs.skip/relative_import_resolves_to_itself.py deleted file mode 100644 index 838595ab7..000000000 --- a/languages/tree-sitter-stack-graphs-python/test/bugs.skip/relative_import_resolves_to_itself.py +++ /dev/null @@ -1,14 +0,0 @@ -#--- path: a/__init__.py ---# -from . import b -# ^ defined: 6 - -#--- path: a/b/__init__.py ---# -B = 'b' - -#--- path: main.py ---# -from a import b -# ^ defined: 6 - -print b.B -# ^ defined: 9, 6 -# ^ defined: 6 \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-python/test/imports/import_from_module_a_submodule.py b/languages/tree-sitter-stack-graphs-python/test/imports/import_from_module_a_submodule.py new file mode 100644 index 000000000..ea51f9450 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/imports/import_from_module_a_submodule.py @@ -0,0 +1,14 @@ +# --- path: foo/bar.py --- + +BAR = 42 + +# --- path: test.py --- + +from foo import bar + +bar.BAR +# ^ defined: 7, 3 +# ^ defined: 3 + +foo +# ^ defined: diff --git a/languages/tree-sitter-stack-graphs-python/test/imports/import_from_module_a_value.py b/languages/tree-sitter-stack-graphs-python/test/imports/import_from_module_a_value.py new file mode 100644 index 000000000..1eb97ffe2 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/imports/import_from_module_a_value.py @@ -0,0 +1,13 @@ +# --- path: foo.py --- + +FOO = 42 + +# --- path: test.py --- + +from foo import FOO + +FOO +# ^ defined: 7, 3 + +foo +# ^ defined: diff --git a/languages/tree-sitter-stack-graphs-python/test/imports/import_from_module_a_value_aliased.py b/languages/tree-sitter-stack-graphs-python/test/imports/import_from_module_a_value_aliased.py new file mode 100644 index 000000000..088ca9544 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/imports/import_from_module_a_value_aliased.py @@ -0,0 +1,13 @@ +# --- path: foo.py --- + +FOO = 42 + +# --- path: test.py --- + +from foo import FOO as QUX + +QUX +# ^ defined: 7, 3 + +FOO +# ^ defined: diff --git a/languages/tree-sitter-stack-graphs-python/test/imports/import_from_module_wildcard.py b/languages/tree-sitter-stack-graphs-python/test/imports/import_from_module_wildcard.py new file mode 100644 index 000000000..3a1de4ffe --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/imports/import_from_module_wildcard.py @@ -0,0 +1,13 @@ +# --- path: foo.py --- + +FOO = 42 + +# --- path: test.py --- + +from foo import * + +FOO +# ^ defined: 3 + +foo +# ^ defined: diff --git a/languages/tree-sitter-stack-graphs-python/test/imports/import_from_submodule_a_value.py b/languages/tree-sitter-stack-graphs-python/test/imports/import_from_submodule_a_value.py new file mode 100644 index 000000000..8d89d8538 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/imports/import_from_submodule_a_value.py @@ -0,0 +1,16 @@ +# --- path: foo/bar.py --- + +BAR = 42 + +# --- path: test.py --- + +from foo.bar import BAR + +BAR +# ^ defined: 7, 3 + +foo +# ^ defined: + +bar +# ^ defined: diff --git a/languages/tree-sitter-stack-graphs-python/test/imports/import_from_super_package_a_value.py b/languages/tree-sitter-stack-graphs-python/test/imports/import_from_super_package_a_value.py new file mode 100644 index 000000000..961cd1622 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/imports/import_from_super_package_a_value.py @@ -0,0 +1,10 @@ +# --- path: foo/__init__.py --- + +FOO = 42 + +# --- path: foo/bar/test.py --- + +from .. import FOO + +FOO +# ^ defined: 7, 3 diff --git a/languages/tree-sitter-stack-graphs-python/test/imports/import_from_super_package_submodule_a_value.py b/languages/tree-sitter-stack-graphs-python/test/imports/import_from_super_package_submodule_a_value.py new file mode 100644 index 000000000..75652f7cd --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/imports/import_from_super_package_submodule_a_value.py @@ -0,0 +1,10 @@ +# --- path: foo/bar.py --- + +BAR = 42 + +# --- path: foo/baz/test.py --- + +from ..bar import BAR + +BAR +# ^ defined: 7, 3 diff --git a/languages/tree-sitter-stack-graphs-python/test/imports/import_from_this_package_a_value.py b/languages/tree-sitter-stack-graphs-python/test/imports/import_from_this_package_a_value.py new file mode 100644 index 000000000..f8de8042c --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/imports/import_from_this_package_a_value.py @@ -0,0 +1,10 @@ +# --- path: foo/__init__.py --- + +FOO = 42 + +# --- path: foo/test.py --- + +from . import FOO + +FOO +# ^ defined: 7, 3 diff --git a/languages/tree-sitter-stack-graphs-python/test/imports/import_from_this_package_submodule_a_value.py b/languages/tree-sitter-stack-graphs-python/test/imports/import_from_this_package_submodule_a_value.py new file mode 100644 index 000000000..dc64ce387 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/imports/import_from_this_package_submodule_a_value.py @@ -0,0 +1,10 @@ +# --- path: foo/bar.py --- + +BAR = 42 + +# --- path: foo/test.py --- + +from .bar import BAR + +BAR +# ^ defined: 7, 3 diff --git a/languages/tree-sitter-stack-graphs-python/test/imports/import_module.py b/languages/tree-sitter-stack-graphs-python/test/imports/import_module.py new file mode 100644 index 000000000..897acdf63 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/imports/import_module.py @@ -0,0 +1,11 @@ +# --- path: foo.py --- + +FOO = 42 + +# --- path: test.py --- + +import foo + +foo.FOO +# ^ defined: 7, 3 +# ^ defined: 3 diff --git a/languages/tree-sitter-stack-graphs-python/test/imports/import_module_aliased.py b/languages/tree-sitter-stack-graphs-python/test/imports/import_module_aliased.py new file mode 100644 index 000000000..220a6b72d --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/imports/import_module_aliased.py @@ -0,0 +1,14 @@ +# --- path: foo.py --- + +FOO = 42 + +# --- path: test.py --- + +import foo as qux + +qux.FOO +# ^ defined: 7, 3 +# ^ defined: 3 + +foo +# ^ defined: diff --git a/languages/tree-sitter-stack-graphs-python/test/imports/import_submodule.py b/languages/tree-sitter-stack-graphs-python/test/imports/import_submodule.py new file mode 100644 index 000000000..312cd66a1 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/imports/import_submodule.py @@ -0,0 +1,15 @@ +# --- path: foo/bar.py --- + +BAR = 42 + +# --- path: test.py --- + +import foo.bar + +foo.bar.BAR +# ^ defined: 7 +# ^ defined: 7, 3 +# ^ defined: 3 + +bar +# ^ defined: diff --git a/languages/tree-sitter-stack-graphs-python/test/imports/import_submodule_aliased.py.skip b/languages/tree-sitter-stack-graphs-python/test/imports/import_submodule_aliased.py.skip new file mode 100644 index 000000000..dd84f39b5 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/imports/import_submodule_aliased.py.skip @@ -0,0 +1,17 @@ +# --- path: foo/bar.py --- + +BAR = 42 + +# --- path: test.py --- + +import foo.bar as qux + +qux.BAR +# ^ defined: 7 +# ^ defined: 3 + +foo +# ^ defined: + +bar +# ^ defined: diff --git a/languages/tree-sitter-stack-graphs-python/test/imports/relative_import_resolves_to_itself.py.skip b/languages/tree-sitter-stack-graphs-python/test/imports/relative_import_resolves_to_itself.py.skip new file mode 100644 index 000000000..2cdb2cf66 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/imports/relative_import_resolves_to_itself.py.skip @@ -0,0 +1,14 @@ +# --- path: foo/__init__.py --- +from . import bar +# ^ defined: 6 + +# --- path: foo/bar/__init__.py --- +BAR = 'b' + +# --- path: main.py --- +from foo import bar +# ^ defined: 6 + +bar.BAR +# ^ defined: 9, 6 +# ^ defined: 6 diff --git a/languages/tree-sitter-stack-graphs-python/test/imports/require_explicit_submodule_import.py.skip b/languages/tree-sitter-stack-graphs-python/test/imports/require_explicit_submodule_import.py.skip new file mode 100644 index 000000000..a9d12848c --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/imports/require_explicit_submodule_import.py.skip @@ -0,0 +1,18 @@ +# --- path: foo/__init__.py --- + +FOO = 42 + +# --- path: foo/bar.py --- + +BAR = 42 + +# --- path: test.py --- + +import foo + +foo.FOO +# ^ defined: 11, 3 +# ^ defined: 3 + +foo.bar +# ^ defined: From 34eba6ea3fc32f424c05d990634e318109d121b5 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 18 Jan 2024 15:13:42 +0100 Subject: [PATCH 370/500] Update README --- .../tree-sitter-stack-graphs-python/README.md | 100 ++++++++++++------ 1 file changed, 70 insertions(+), 30 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/README.md b/languages/tree-sitter-stack-graphs-python/README.md index 3bf115da0..b5fbc2f32 100644 --- a/languages/tree-sitter-stack-graphs-python/README.md +++ b/languages/tree-sitter-stack-graphs-python/README.md @@ -4,27 +4,73 @@ This project defines tree-sitter-stack-graphs rules for Python using the [tree-s [tree-sitter-python]: https://crates.io/crates/tree-sitter-python -## Usage +- [API documentation](https://docs.rs/tree-sitter-stack-graphs-python/) +- [Release notes](https://github.com/github/stack-graphs/blob/main/languages/tree-sitter-stack-graphs-python/CHANGELOG.md) + +## Using the API To use this library, add the following to your `Cargo.toml`: -``` toml +```toml [dependencies] tree-sitter-stack-graphs-python = "0.1.0" ``` Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-python/*/) for more details on how to use this library. -## Command-line Program +## Using the Command-line Program The command-line program for `tree-sitter-stack-graphs-python` lets you do stack graph based analysis and lookup from the command line. -Install the program using `cargo install` as follows: +The CLI can be run as follows: -``` sh -$ cargo install --features cli tree-sitter-stack-graphs-python -$ tree-sitter-stack-graphs-python --help -``` +1. _(Installed)_ Install the CLI using Cargo as follows: + + ```sh + cargo install --features cli tree-sitter-stack-graphs-python + ``` + + After this, the CLI should be available as `tree-sitter-stack-graphs-python`. + +2. _(From source)_ Instead of installing the CLI, it can also be run directly from the crate directory, as a replacement for a `tree-sitter-stack-graphs-python` invocation, as follows: + + ```sh + cargo run --features cli -- + ``` + +The basic CLI workflow for the command-line program is to index source code and issue queries against the resulting database: + +1. Index a source folder as follows: + + ```sh + tree-sitter-stack-graphs-python index SOURCE_DIR + ``` + + _Indexing will skip any files that have already be indexed. To force a re-index, add the `-f` flag._ + + To check the status if a source folder, run: + + ```sh + tree-sitter-stack-graphs-python status SOURCE_DIR + ``` + + To clean the database and start with a clean slate, run: + + ```sh + tree-sitter-stack-graphs-python clean + ``` + + _Pass the `--delete` flag to not just empty the database, but also delete it. This is useful to resolve `unsupported database version` errors that may occur after a version update._ + +2. Run a query to find the definition(s) for a reference on a given line and column, run: + + ```sh + tree-sitter-stack-graphs-python query definition SOURCE_PATH:LINE:COLUMN + ``` + + Resulting definitions are printed, including a source line if the source file is available. + +Discover all available commands and flags by passing the `-h` flag to the CLI directly, or to any of the subcommands. ## Development @@ -35,35 +81,29 @@ The project is written in Rust, and requires a recent version installed. Rust c The project is organized as follows: - The stack graph rules are defined in `src/stack-graphs.tsg`. -- Builtins sources and configuration are defined in `src/builtins.py` and `builtins.cfg` respectively. +- Builtins sources and configuration are defined in `src/builtins.it` and `builtins.cfg` respectively. - Tests are put into the `test` directory. -### Building and Running Tests - -Build the project by running: - -``` sh -$ cargo build -``` +### Running Tests Run the tests as follows: -``` sh -$ cargo test +```sh +cargo test ``` The project consists of a library and a CLI. By default, running `cargo` only applies to the library. To run `cargo` commands on the CLI as well, add `--features cli` or `--all-features`. Run the CLI from source as follows: -``` sh -$ cargo run --features cli -- ARGS +```sh +cargo run --features cli -- ARGS ``` Sources are formatted using the standard Rust formatted, which is applied by running: -``` sh -$ cargo fmt +```sh +cargo fmt ``` ### Writing TSG @@ -78,21 +118,21 @@ which contain self-contained TSG rules for specific language features. A VSCode Parse and test a single file by executing the following commands: -``` sh -$ cargo run --features cli -- parse FILES... -$ cargo run --features cli -- test TESTFILES... +```sh +cargo run --features cli -- parse FILES... +cargo run --features cli -- test TESTFILES... ``` Generate a visualization to debug failing tests by passing the `-V` flag: -``` sh -$ cargo run --features cli -- test -V TESTFILES... +```sh +cargo run --features cli -- test -V TESTFILES... ``` To generate the visualization regardless of test outcome, execute: -``` sh -$ cargo run --features cli -- test -V --output-mode=always TESTFILES... +```sh +cargo run --features cli -- test -V --output-mode=always TESTFILES... ``` -Go to https://crates.io/crates/tree-sitter-stack-graphs for links to examples and documentation. +Go to for links to examples and documentation. From c23f7ca23d354b08ba9b80adee5433f0f815513b Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 16 Nov 2023 12:33:46 +0100 Subject: [PATCH 371/500] Upgrade Python and reorganize rules according to syntax categories --- .../Cargo.toml | 2 +- .../src/stack-graphs.tsg | 726 ++++++++++++------ .../test/pattern_matching.py | 7 +- 3 files changed, 517 insertions(+), 218 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/Cargo.toml b/languages/tree-sitter-stack-graphs-python/Cargo.toml index ca123cc0f..4ac4c0633 100644 --- a/languages/tree-sitter-stack-graphs-python/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-python/Cargo.toml @@ -31,7 +31,7 @@ cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"] anyhow = { version = "1.0", optional = true } clap = { version = "4", optional = true, features = ["derive"] } tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs" } -tree-sitter-python = "=0.20.2" +tree-sitter-python = "=0.20.4" [dev-dependencies] anyhow = "1.0" diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 0028994c2..00314b687 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -45,6 +45,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n } [ + ; _statement ; _simple_statement (future_import_statement) (import_statement) @@ -61,7 +62,8 @@ attribute node_symbol = node => symbol = (source-text node), source_n (global_statement) (nonlocal_statement) (exec_statement) - ; _compund_statement + (type_alias_statement) + ; _compound_statement (if_statement) (for_statement) (while_statement) @@ -74,18 +76,23 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; block (block) ; statement clauses + (if_clause) (elif_clause) (else_clause) - (case_clause) + (except_group_clause) (except_clause) (finally_clause) (with_clause) + (case_clause) ] @node { node @node.after_scope node @node.before_scope } -(parameters) @node { +[ + (parameters) + (lambda_parameters) +] @node { node @node.after_scope node @node.before_scope } @@ -102,20 +109,95 @@ attribute node_symbol = node => symbol = (source-text node), source_n } [ + ; expressions + (comparison_operator) + (not_operator) + (boolean_operator) + (lambda) + ;(primary_expression) ; unfolded below + (conditional_expression) + (named_expression) + (as_pattern) + ; primary_expression + (await) + (binary_operator) (identifier) - (wildcard_import) - (expression) + ;(keyword_identifier) ; invalid query pattern? + (string) + (concatenated_string) + (integer) + (float) + (true) + (false) + (none) + (unary_operator) + (attribute) + (subscript) + (call) + (list) + (list_comprehension) + (dictionary) + (dictionary_comprehension) + (set) + (set_comprehension) + (tuple) + (parenthesized_expression) + (generator_expression) + (ellipsis) + (list_splat) + + ; expression list (expression_list) - (primary_expression) - (pattern) - (pattern_list) + + ; pattern + (pattern/identifier) + ;(keyword_identifier) ; invalid query pattern? + ;(subscript) + ;(attribute) + (list_splat_pattern) + (tuple_pattern) + (list_pattern) + ; _simple_patterns + (class_pattern) + (splat_pattern) + (union_pattern) + ;(list_pattern) ; already in pattern + ;(tuple_pattern) ; already in pattern + (dict_pattern) + ;(string) ; already in primary_expression + ;(concatenated_string) ; already in primary_expression + ;(true) ; already in primary_expression + ;(false) ; already in primary_expression + ;(none) ; already in primary_expression + ;(integer) ; already in primary_expression + ;(float) ; already in primary_expression + (complex_pattern) + (dotted_name) + ; _as_attern + (as_pattern) + ; keyword pattern + (keyword_pattern) + ; case pattern (case_pattern) - (parameter) - (pair) - (list_splat) - (parenthesized_list_splat) - (dictionary_splat) - (keyword_argument) + ; with item + (with_item) + + ; pattern list + (pattern_list) + + ; parameter + ;(identifier) ; already in expressions + (typed_parameter) + (default_parameter) + (typed_default_parameter) + ;(list_splat_pattern) ; already in patterns + ;(tuple_pattern) ; already in patterns + (keyword_separator) + (positional_separator) + (dictionary_splat_pattern) + + ; parameters + (parameters) ] @node { node @node.input node @node.new_bindings @@ -149,8 +231,16 @@ inherit .grandparent_module inherit .local_scope inherit .parent_module -; Modules and Imports -;--------------------- +;; +;; # # +;; ## ## #### ##### # # # ###### #### +;; # # # # # # # # # # # # # +;; # # # # # # # # # # ##### #### +;; # # # # # # # # # # # +;; # # # # # # # # # # # # +;; # # #### ##### #### ###### ###### #### +;; +;; Modules (module) @mod { @@ -248,6 +338,18 @@ inherit .parent_module node @mod.local_scope } +;; +;; ### +;; # # # ##### #### ##### ##### #### +;; # ## ## # # # # # # # # +;; # # ## # # # # # # # # #### +;; # # # ##### # # ##### # # +;; # # # # # # # # # # # +;; ### # # # #### # # # #### +;; +;; Imports + +;; import _.X (import_statement name: (dotted_name . (identifier) @root_name)) @stmt @@ -257,6 +359,7 @@ inherit .parent_module edge @root_name.ref -> ROOT_NODE } +;; import _.X as _ (import_statement name: (aliased_import (dotted_name . (identifier) @root_name))) @@ -264,6 +367,7 @@ inherit .parent_module edge @root_name.ref -> ROOT_NODE } +;; from _ import _.X (import_from_statement name: (dotted_name . (identifier) @import_root_name)) @stmt @@ -274,6 +378,7 @@ inherit .parent_module attr (@import_root_name.ref_dot) push_symbol = "." } +;; from _ import _.X as _ (import_from_statement name: (aliased_import (dotted_name @@ -283,6 +388,11 @@ inherit .parent_module attr (@import_root_name.ref_dot) push_symbol = "." } +;; from X._ import _ +;; from ._.X import _ +;; from .._.X import _ +;; from . import _ +;; from .. import _ (import_from_statement module_name: [ (dotted_name (identifier) @prefix_leaf_name .) @@ -300,6 +410,8 @@ inherit .parent_module edge @import_root_name.ref_dot -> @prefix_leaf_name.ref } +;; from _ import _.X as Y +;; import _.X as Y [ (import_from_statement (aliased_import @@ -315,6 +427,8 @@ inherit .parent_module edge @alias.def -> @name.ref } +;; import _.X +;; from _ import _.X [ (import_statement name: (dotted_name @@ -327,6 +441,7 @@ inherit .parent_module edge @leaf_name.def -> @leaf_name.ref } +;; . (relative_import (import_prefix) @prefix (#eq? @prefix ".")) @import @@ -334,6 +449,7 @@ inherit .parent_module edge @prefix.ref -> @import.parent_module } +;; .. (relative_import (import_prefix) @prefix (#eq? @prefix "..")) @import @@ -341,6 +457,8 @@ inherit .parent_module edge @prefix.ref -> @import.grandparent_module } +;; .X +;; ..X (relative_import (import_prefix) @prefix (dotted_name @@ -351,6 +469,7 @@ inherit .parent_module edge @name.ref_dot -> @prefix.ref } +;; from . [ (import_from_statement module_name: (relative_import @@ -370,6 +489,7 @@ inherit .parent_module edge @child_name.ref_dot -> @parent_name.ref } +;; from X._ import _ (import_from_statement module_name: (dotted_name . (identifier) @root_name)) @@ -377,6 +497,7 @@ inherit .parent_module edge @root_name.ref -> ROOT_NODE } +;; from _.X import * (import_from_statement module_name: (dotted_name (identifier) @leaf_name .) @@ -388,6 +509,9 @@ inherit .parent_module attr (@star.ref_dot) push_symbol = "." } +;; import _.X.Y._ +;; from _ import _.X.Y._ +;; from _ import _.X.Y._ as _ [ (import_statement name: (dotted_name @@ -415,9 +539,16 @@ inherit .parent_module attr (@child_name.ref_dot) push_symbol = "." } -;-------- -; Scopes -;-------- +;; +;; ###### +;; # # # #### #### # # #### +;; # # # # # # # # # # +;; ###### # # # # #### #### +;; # # # # # # # # # +;; # # # # # # # # # # # +;; ###### ###### #### #### # # #### +;; +;; Blocks [ (module (_) @last_stmt .) @@ -475,7 +606,7 @@ inherit .parent_module edge @stmt.after_scope -> @block.after_scope } -(match_statement (case_clause) @block) @stmt +(match_statement body: (_) @block) @stmt { let @block.local_scope = @block.before_scope edge @block.before_scope -> @stmt.before_scope @@ -490,26 +621,77 @@ inherit .parent_module edge @stmt.before_scope -> @stmt.after_scope } -;------------- -; Definitions -;------------- +;; +;; ##### +;; # # ##### ## ##### ###### # # ###### # # ##### #### +;; # # # # # # ## ## # ## # # # +;; ##### # # # # ##### # ## # ##### # # # # #### +;; # # ###### # # # # # # # # # # +;; # # # # # # # # # # # ## # # # +;; ##### # # # # ###### # # ###### # # # #### +;; +;; Statements -(identifier) @name { - attr (@name.def) node_definition = @name -} +;;;; Simple Statements -[ - (assignment - left: (_) @pattern - right: (_) @value) - (with_item - value: - (as_pattern - (_) @value - alias: (as_pattern_target (_) @pattern))) -] +(print_statement) {} + +(assert_statement) {} + +(expression_statement) {} + +(return_statement (_) @expr) @stmt { - edge @pattern.input -> @value.output + edge @stmt.function_returns -> @expr.output +} + +(delete_statement) {} + +(raise_statement) {} + +(pass_statement) {} + +(break_statement) {} + +(continue_statement) {} + +(global_statement) {} + +(nonlocal_statement) {} + +(exec_statement) {} + +(type_alias_statement) {} + +;;;; Compound Statements + +(if_statement) {} + +(if_clause) {} + +(elif_clause) {} + +(else_clause) {} + +(for_statement) {} + +(while_statement) {} + +(try_statement) {} + +(except_group_clause) {} + +(except_clause) {} + +(finally_clause) {} + +(with_statement) {} + +(with_clause) {} + +(function_definition + name: (identifier) @name) { + attr (@name.def) node_definition = @name } (function_definition @@ -539,72 +721,6 @@ inherit .parent_module let @body.class_member_attr_scope = #null } -;; -;; BEGIN BIG GNARLY DISJUNCTION -;; -;; The following pair of rules is intended to capture the following behavior: -;; -;; If a function definition is used to define a method, by being inside a class -;; definition, then we make its syntax type `method`. Otherwise, we make it's -;; syntax type `function`. Unfortunately, because of the limitations on negation -;; and binding in tree sitter queries, we cannot negate `class_definition` or -;; similar things directly. Instead, we have to manually push the negation down -;; to form the finite disjunction it corresponds to. -;; - -[ - (class_definition (block (decorated_definition (function_definition name: (_)@name)))) - (class_definition (block (function_definition name: (_)@name))) -] -{ - attr (@name.def) syntax_type = "method" -} - -[ - (module (decorated_definition (function_definition name: (_)@name))) - (module (function_definition name: (_)@name)) - - (if_statement (block (decorated_definition (function_definition name: (_)@name)))) - (if_statement (block (function_definition name: (_)@name))) - - (elif_clause (block (decorated_definition (function_definition name: (_)@name)))) - (elif_clause (block (function_definition name: (_)@name))) - - (else_clause (block (decorated_definition (function_definition name: (_)@name)))) - (else_clause (block (function_definition name: (_)@name))) - - (case_clause (block (decorated_definition (function_definition name: (_)@name)))) - (case_clause (block (function_definition name: (_)@name))) - - (for_statement (block (decorated_definition (function_definition name: (_)@name)))) - (for_statement (block (function_definition name: (_)@name))) - - (while_statement (block (decorated_definition (function_definition name: (_)@name)))) - (while_statement (block (function_definition name: (_)@name))) - - (try_statement (block (decorated_definition (function_definition name: (_)@name)))) - (try_statement (block (function_definition name: (_)@name))) - - (except_clause (block (decorated_definition (function_definition name: (_)@name)))) - (except_clause (block (function_definition name: (_)@name))) - - (finally_clause (block (decorated_definition (function_definition name: (_)@name)))) - (finally_clause (block (function_definition name: (_)@name))) - - (with_statement (block (decorated_definition (function_definition name: (_)@name)))) - (with_statement (block (function_definition name: (_)@name))) - - (function_definition (block (decorated_definition (function_definition name: (_)@name)))) - (function_definition (block (function_definition name: (_)@name))) -] -{ - attr (@name.def) syntax_type = "function" -} - -;; -;; END BIG GNARLY DISJUNCTION -;; - (function_definition parameters: (parameters . (identifier) @param) @@ -616,6 +732,22 @@ inherit .parent_module attr (@param.output) push_node = @param } +(parameters + (_) @param) @params +{ + node @param.param_index + node @param.param_name + + attr (@param.param_index) push_symbol = (named-child-index @param) + edge @param.param_index -> @params.before_scope + edge @params.after_scope -> @param.input + edge @param.param_name -> @params.before_scope +} + +(parameter/identifier) @name { + attr (@name.def) node_definition = @name +} + (parameter/identifier) @param @name { attr (@param.param_name) push_node = @param @@ -655,40 +787,6 @@ inherit .parent_module edge @param.input -> @name.def } -[ - (pattern_list (_) @pattern) - (tuple_pattern (_) @pattern) -] @list -{ - node pattern_index - - let statement_scope = @list.local_scope - node @pattern.local_scope - edge statement_scope -> @pattern.local_scope - attr (statement_scope -> @pattern.local_scope) precedence = (plus 1 (named-child-index @pattern)) - - edge pattern_index -> @list.input - edge @pattern.input -> pattern_index - attr (pattern_index) push_symbol = (named-child-index @pattern) -} - -(parameters - (_) @param) @params -{ - node @param.param_index - node @param.param_name - - attr (@param.param_index) push_symbol = (named-child-index @param) - edge @param.param_index -> @params.before_scope - edge @params.after_scope -> @param.input - edge @param.param_name -> @params.before_scope -} - -(return_statement (_) @expr) @stmt -{ - edge @stmt.function_returns -> @expr.output -} - (class_definition) @class { node @class.call_drop node @class.member_attrs @@ -696,6 +794,11 @@ inherit .parent_module node @class.super_scope } +(class_definition + name: (identifier) @name) { + attr (@name.def) node_definition = @name +} + (class_definition name: (identifier) @name) @class { @@ -756,23 +859,107 @@ inherit .parent_module edge @stmt.after_scope -> @def.after_scope } +(match_statement) {} + (case_clause - pattern: (_) @pattern - consequence: (_) @consequence) @clause + (case_pattern) @pattern + consequence: (_) @consequence) { edge @consequence.before_scope -> @pattern.new_bindings +} + +(case_clause + consequence: (_) @consequence) @clause +{ edge @consequence.before_scope -> @clause.before_scope edge @clause.after_scope -> @consequence.after_scope } -;------------- -; Expressions -;------------- +;; +;; ####### +;; # # # ##### ##### ###### #### #### # #### # # #### +;; # # # # # # # # # # # # # ## # # +;; ##### ## # # # # ##### #### #### # # # # # # #### +;; # ## ##### ##### # # # # # # # # # # +;; # # # # # # # # # # # # # # # ## # # +;; ####### # # # # # ###### #### #### # #### # # #### +;; +;; Expressions + +(conditional_expression) {} + +(named_expression) {} + +(as_pattern) {} + +(await) {} + +(binary_operator + (_) @left + (_) @right) @binop +{ + edge @binop.new_bindings -> @left.new_bindings + edge @binop.new_bindings -> @right.new_bindings +} -(identifier) @name { +(primary_expression/identifier) @name { attr (@name.ref) node_reference = @name } +(primary_expression/identifier) @name +{ + edge @name.output -> @name.local_scope + edge @name.output -> @name.class_parent_scope + edge @name.local_scope -> @name.input + attr (@name.input) pop_node = @name + attr (@name.output) node_reference = @name + + edge @name.new_bindings -> @name.def +} + +(string) {} + +(concatenated_string) {} + +(integer) {} + +(float) {} + +(true) {} + +(false) {} + +(none) {} + +(unary_operator) {} + +(attribute + object: (_) @object + attribute: (identifier) @name) @expr +{ + node input_dot + node output_dot + + edge @expr.output -> @name.output + edge @name.output -> output_dot + edge output_dot -> @object.output + edge @object.input -> input_dot + edge input_dot -> @name.input + edge @name.input -> @expr.input + attr (output_dot) push_symbol = "." + attr (input_dot) pop_symbol = "." + attr (@name.input) pop_node = @name + attr (@name.output) push_node = @name +} + +(primary_expression/attribute + attribute: (identifier) @name) +{ + attr (@name.output) is_reference +} + +(subscript) {} + (call function: (_) @fn arguments: (argument_list) @args) @call @@ -837,6 +1024,42 @@ inherit .parent_module edge @call.output -> @call.class_super_scope } +(list) @list +{ + node called + + edge @list.output -> called + edge called -> @list.global_dot + attr (called) push_symbol = "list" +} + +(list (_) @el) @list +{ + edge @list.new_bindings -> @el.new_bindings +} + +(list_comprehension) {} + +(dictionary (pair) @pair) @dict +{ + edge @dict.new_bindings -> @pair.new_bindings +} + +(pair + value: (_) @value) @pair +{ + edge @pair.new_bindings -> @value.new_bindings +} + +(dictionary_comprehension) {} + +(set (_) @el) @set +{ + edge @set.new_bindings -> @el.new_bindings +} + +(set_comprehension) {} + [ (tuple (_) @element) (expression_list (_) @element) @@ -851,115 +1074,188 @@ inherit .parent_module edge @tuple.new_bindings -> @element.new_bindings } -(attribute - object: (_) @object - attribute: (identifier) @name) @expr +(parenthesized_expression) {} + +(generator_expression) {} + +(ellipsis) {} + +(list_splat (_) @splatted) @splat { - node input_dot - node output_dot + edge @splat.new_bindings -> @splatted.new_bindings +} - edge @expr.output -> @name.output - edge @name.output -> output_dot - edge output_dot -> @object.output - edge @object.input -> input_dot - edge input_dot -> @name.input - edge @name.input -> @expr.input - attr (output_dot) push_symbol = "." - attr (input_dot) pop_symbol = "." - attr (@name.input) pop_node = @name +;; +;; ###### +;; # # ## ##### ##### ###### ##### # # #### +;; # # # # # # # # # ## # # +;; ###### # # # # ##### # # # # # #### +;; # ###### # # # ##### # # # # +;; # # # # # # # # # ## # # +;; # # # # # ###### # # # # #### +;; +;; Patterns + +(pattern/identifier) @name { + attr (@name.def) node_definition = @name +} + +(pattern/identifier) @name +{ + edge @name.output -> @name.local_scope + edge @name.output -> @name.class_parent_scope + edge @name.local_scope -> @name.input + attr (@name.local_scope -> @name.input) precedence = 1 + attr (@name.input) node_definition = @name attr (@name.output) push_node = @name + + edge @name.new_bindings -> @name.def } +(pattern/subscript) {} + (pattern/attribute attribute: (identifier) @name) { attr (@name.input) is_definition } -(primary_expression/attribute - attribute: (identifier) @name) -{ - attr (@name.output) is_reference -} -(primary_expression/identifier) @id +(list_splat_pattern) {} + +[ + (pattern_list (_) @pattern) + (tuple_pattern (_) @pattern) + (list_pattern (_) @pattern) +] @list { - edge @id.output -> @id.local_scope - edge @id.output -> @id.class_parent_scope - edge @id.local_scope -> @id.input - attr (@id.input) pop_node = @id - attr (@id.output) node_reference = @id + node pattern_index - edge @id.new_bindings -> @id.def + let statement_scope = @list.local_scope + node @pattern.local_scope + edge statement_scope -> @pattern.local_scope + attr (statement_scope -> @pattern.local_scope) precedence = (plus 1 (named-child-index @pattern)) + + edge pattern_index -> @list.input + edge @pattern.input -> pattern_index + attr (pattern_index) push_symbol = (named-child-index @pattern) } -(pattern/identifier) @id -{ - edge @id.output -> @id.local_scope - edge @id.output -> @id.class_parent_scope - edge @id.local_scope -> @id.input - attr (@id.local_scope -> @id.input) precedence = 1 - attr (@id.input) node_definition = @id - attr (@id.output) push_node = @id +(class_pattern) {} - edge @id.new_bindings -> @id.def -} +(splat_pattern) {} + +(union_pattern) {} + +(dict_pattern) {} + +(complex_pattern) {} (as_pattern (expression) @value - alias: (as_pattern_target (primary_expression/identifier) @id)) @as_pattern + alias: (as_pattern_target (primary_expression/identifier) @name)) @as_pattern { - attr (@id.local_scope -> @id.input) precedence = 1 - attr (@id.input) is_definition + attr (@name.local_scope -> @name.input) precedence = 1 + attr (@name.input) is_definition edge @as_pattern.new_bindings -> @value.new_bindings - edge @as_pattern.new_bindings -> @id.new_bindings + edge @as_pattern.new_bindings -> @name.new_bindings } -(list) @list -{ - node called - - edge @list.output -> called - edge called -> @list.global_dot - attr (called) push_symbol = "list" -} +(keyword_pattern) {} -(list (_) @el) @list +(case_pattern (_) @expr) @pat { - edge @list.new_bindings -> @el.new_bindings + edge @pat.new_bindings -> @expr.new_bindings } -(dictionary (pair) @pair) @dict +[ + (assignment + left: (_) @pattern + right: (_) @value) + (with_item + value: + (as_pattern + (_) @value + alias: (as_pattern_target (_) @pattern))) +] { - edge @dict.new_bindings -> @pair.new_bindings + edge @pattern.input -> @value.output } -(pair - value: (_) @value) @pair -{ - edge @pair.new_bindings -> @value.new_bindings -} +;; +;; ##### ####### +;; # # # # # # ##### ## # # # # # ##### ###### #### +;; # # # ## # # # # # # # # # # # # # +;; ##### # # # # # # # ## # # # # ##### #### +;; # # # # # # ###### ## # # ##### # # +;; # # # # ## # # # # # # # # # # # +;; ##### # # # # # # # # # # # ###### #### +;; +;; Syntax Types -(set (_) @el) @set -{ - edge @set.new_bindings -> @el.new_bindings -} +;; +;; BEGIN BIG GNARLY DISJUNCTION +;; +;; The following pair of rules is intended to capture the following behavior: +;; +;; If a function definition is used to define a method, by being inside a class +;; definition, then we make its syntax type `method`. Otherwise, we make it's +;; syntax type `function`. Unfortunately, because of the limitations on negation +;; and binding in tree sitter queries, we cannot negate `class_definition` or +;; similar things directly. Instead, we have to manually push the negation down +;; to form the finite disjunction it corresponds to. +;; -(list_splat (_) @splatted) @splat +[ + (class_definition (block (decorated_definition (function_definition name: (_)@name)))) + (class_definition (block (function_definition name: (_)@name))) +] { - edge @splat.new_bindings -> @splatted.new_bindings + attr (@name.def) syntax_type = "method" } -(binary_operator - (_) @left - (_) @right) @binop -{ - edge @binop.new_bindings -> @left.new_bindings - edge @binop.new_bindings -> @right.new_bindings -} +[ + (module (decorated_definition (function_definition name: (_)@name))) + (module (function_definition name: (_)@name)) -(case_pattern (_) @expr) @pat + (if_statement (block (decorated_definition (function_definition name: (_)@name)))) + (if_statement (block (function_definition name: (_)@name))) + + (elif_clause (block (decorated_definition (function_definition name: (_)@name)))) + (elif_clause (block (function_definition name: (_)@name))) + + (else_clause (block (decorated_definition (function_definition name: (_)@name)))) + (else_clause (block (function_definition name: (_)@name))) + + (case_clause (block (decorated_definition (function_definition name: (_)@name)))) + (case_clause (block (function_definition name: (_)@name))) + + (for_statement (block (decorated_definition (function_definition name: (_)@name)))) + (for_statement (block (function_definition name: (_)@name))) + + (while_statement (block (decorated_definition (function_definition name: (_)@name)))) + (while_statement (block (function_definition name: (_)@name))) + + (try_statement (block (decorated_definition (function_definition name: (_)@name)))) + (try_statement (block (function_definition name: (_)@name))) + + (except_clause (block (decorated_definition (function_definition name: (_)@name)))) + (except_clause (block (function_definition name: (_)@name))) + + (finally_clause (block (decorated_definition (function_definition name: (_)@name)))) + (finally_clause (block (function_definition name: (_)@name))) + + (with_statement (block (decorated_definition (function_definition name: (_)@name)))) + (with_statement (block (function_definition name: (_)@name))) + + (function_definition (block (decorated_definition (function_definition name: (_)@name)))) + (function_definition (block (function_definition name: (_)@name))) +] { - edge @pat.new_bindings -> @expr.new_bindings + attr (@name.def) syntax_type = "function" } + +;; +;; END BIG GNARLY DISJUNCTION +;; diff --git a/languages/tree-sitter-stack-graphs-python/test/pattern_matching.py b/languages/tree-sitter-stack-graphs-python/test/pattern_matching.py index 58c0d16fc..d6b8980a3 100644 --- a/languages/tree-sitter-stack-graphs-python/test/pattern_matching.py +++ b/languages/tree-sitter-stack-graphs-python/test/pattern_matching.py @@ -21,11 +21,11 @@ case { "foo": foo }: print(foo) # ^ defined: 21 - case {bar,quux}: + case {"bar": bar, "quux": quux}: print(bar,quux) # ^ defined: 24 # ^ defined: 24 - case ["grab", { "key": {garply}}]: + case ["grab", { "key": {"garply": garply}}]: print(garply) # ^ defined: 28 case ["drop", *objs]: @@ -37,3 +37,6 @@ case ["go", ("north" | "south" | "east" | "west") as direction2]: current_room = current_room.neighbor(direction2) # ^ defined: 37 + case (foo, "bar"): + print(foo) + # ^ defined: 40 From 41c8f32fa628c86dfdd76e75a3f9debac65c4d0a Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 17 Nov 2023 19:09:37 +0100 Subject: [PATCH 372/500] Reorganize imports --- .../src/stack-graphs.tsg | 393 ++++++++++-------- ...ed.py.skip => import_submodule_aliased.py} | 2 +- 2 files changed, 232 insertions(+), 163 deletions(-) rename languages/tree-sitter-stack-graphs-python/test/imports/{import_submodule_aliased.py.skip => import_submodule_aliased.py} (89%) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 00314b687..2c8c1e847 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -99,8 +99,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n [ (identifier) - (import_prefix) - (wildcard_import) ] @node { node @node.def node @node.def_dot @@ -108,6 +106,19 @@ attribute node_symbol = node => symbol = (source-text node), source_n node @node.ref_dot } +[ + (dotted_name) + (aliased_import) + (relative_import) + (wildcard_import) + (import_prefix) +] @node { + node @node.after_scope + node @node.before_scope + node @node.def + node @node.ref +} + [ ; expressions (comparison_operator) @@ -349,194 +360,252 @@ inherit .parent_module ;; ;; Imports -;; import _.X -(import_statement - name: (dotted_name - . (identifier) @root_name)) @stmt -{ - edge @stmt.after_scope -> @root_name.def - attr (@stmt.after_scope -> @root_name.def) precedence = 1 - edge @root_name.ref -> ROOT_NODE +;; Import References +;; ^^^^^^^^^^^^^^^^^ + +;;;; Dotted Names +;; +;; (dotted_name).ref node to connect to to use the reference +;; (dotted_name).before_scope node to connect from to ensure the reference resolves + +;; all names are references +[ + (import_statement name: (dotted_name (identifier) @name)) + (future_import_statement name: (dotted_name (identifier) @name)) + (import_from_statement name: (dotted_name (identifier) @name)) + (import_statement name: (aliased_import name: (dotted_name (identifier) @name))) + (future_import_statement name: (aliased_import name: (dotted_name (identifier) @name))) + (import_from_statement name: (aliased_import name: (dotted_name (identifier) @name))) + (import_from_statement module_name: (dotted_name (identifier) @name)) + (import_from_statement module_name: (relative_import (dotted_name (identifier) @name))) +] { + attr (@name.ref) node_reference = @name } -;; import _.X as _ -(import_statement - name: (aliased_import - (dotted_name . (identifier) @root_name))) -{ - edge @root_name.ref -> ROOT_NODE +;; references are chained +[ + (import_statement name: (dotted_name (identifier) @left . (identifier) @right)) + (future_import_statement name: (dotted_name (identifier) @left . (identifier) @right)) + (import_from_statement name: (dotted_name (identifier) @left . (identifier) @right)) + (import_statement name: (aliased_import name: (dotted_name (identifier) @left . (identifier) @right))) + (future_import_statement name: (aliased_import name: (dotted_name (identifier) @left . (identifier) @right))) + (import_from_statement name: (aliased_import name: (dotted_name (identifier) @left . (identifier) @right))) + (import_from_statement module_name: (dotted_name (identifier) @left . (identifier) @right)) + (import_from_statement module_name: (relative_import (dotted_name (identifier) @left . (identifier) @right))) +] { + node push_dot + attr (push_dot) push_symbol = "." + + edge @right.ref -> push_dot + edge push_dot -> @left.ref +} + +;; lookup first reference +[ + (import_statement name: (dotted_name . (identifier) @first) @dotted) + (future_import_statement name: (dotted_name . (identifier) @first) @dotted) + (import_from_statement name: (dotted_name . (identifier) @first) @dotted) + (import_statement name: (aliased_import name: (dotted_name . (identifier) @first) @dotted)) + (future_import_statement name: (aliased_import name: (dotted_name . (identifier) @first) @dotted)) + (import_from_statement name: (aliased_import name: (dotted_name . (identifier) @first) @dotted)) + (import_from_statement module_name: (dotted_name . (identifier) @first) @dotted) + (import_from_statement module_name: (relative_import (dotted_name . (identifier) @first) @dotted)) +] { + edge @first.ref -> @dotted.before_scope +} + +;; expose last reference +[ + (import_statement name: (dotted_name (identifier) @last .) @dotted) + (future_import_statement name: (dotted_name (identifier) @last .) @dotted) + (import_from_statement name: (dotted_name (identifier) @last .) @dotted) + (import_statement name: (aliased_import name: (dotted_name (identifier) @last .) @dotted)) + (future_import_statement name: (aliased_import name: (dotted_name (identifier) @last .) @dotted)) + (import_from_statement name: (aliased_import name: (dotted_name (identifier) @last .) @dotted)) + (import_from_statement module_name: (dotted_name (identifier) @last .) @dotted) + (import_from_statement module_name: (relative_import (dotted_name (identifier) @last .) @dotted)) +] { + edge @dotted.ref -> @last.ref +} + +;;;; Aliased Import +;; +;; An aliased import behaves like its wrapped dotted_name as a reference +;; +;; (aliased_import).ref node to connect to, to use the reference +;; (aliased_import).before_scope node to connect from to ensure the reference resolves + +(aliased_import name: (dotted_name) @dotted) @aliased { + edge @aliased.ref -> @dotted.ref + edge @dotted.before_scope -> @aliased.before_scope } -;; from _ import _.X -(import_from_statement - name: (dotted_name - . (identifier) @import_root_name)) @stmt -{ - edge @stmt.after_scope -> @import_root_name.def - attr (@stmt.after_scope -> @import_root_name.def) precedence = 1 - edge @import_root_name.ref -> @import_root_name.ref_dot - attr (@import_root_name.ref_dot) push_symbol = "." +;;;; Relative Import +;; +;; A relative import behaves like its wrapped dotted_name as a reference +;; +;; (relative_import).ref node to connect to, to use the reference +;; (relative_import).before_scope node to connect from to ensure the reference resolves + +(relative_import (import_prefix) . (dotted_name) @dotted) @relative { + edge @relative.ref -> @dotted.ref + + node push_dot + attr (push_dot) push_symbol = "." + + edge @dotted.before_scope -> push_dot + edge push_dot -> @relative.before_scope } -;; from _ import _.X as _ -(import_from_statement - name: (aliased_import - (dotted_name - . (identifier) @import_root_name))) -{ - edge @import_root_name.ref -> @import_root_name.ref_dot - attr (@import_root_name.ref_dot) push_symbol = "." -} - -;; from X._ import _ -;; from ._.X import _ -;; from .._.X import _ -;; from . import _ -;; from .. import _ -(import_from_statement - module_name: [ - (dotted_name (identifier) @prefix_leaf_name .) - (relative_import (dotted_name (identifier) @prefix_leaf_name .)) - (relative_import (import_prefix) @prefix_leaf_name .) - ] - name: [ - (dotted_name - . (identifier) @import_root_name) - (aliased_import - (dotted_name - . (identifier) @import_root_name)) - ]) -{ - edge @import_root_name.ref_dot -> @prefix_leaf_name.ref +(relative_import (import_prefix) .) @relative { + edge @relative.ref -> @relative.before_scope +} + +;;;; Wildcard Import +;; +;; A wildcard import simply passes through +;; +;; (wildcard_import).ref node to connect to, to use the reference +;; (wildcard_import).before_scope node to connect from to ensure the reference resolves + +(wildcard_import) @wildcard { + edge @wildcard.ref -> @wildcard.before_scope } -;; from _ import _.X as Y -;; import _.X as Y +;;;; Import from +;; +;; The imported references are resolved in the from module + [ - (import_from_statement - (aliased_import - name: (dotted_name (identifier) @name .) - alias: (identifier) @alias)) - (import_statement - (aliased_import - name: (dotted_name (identifier) @name .) - alias: (identifier) @alias)) -] @stmt -{ - edge @stmt.after_scope -> @alias.def - edge @alias.def -> @name.ref + (import_from_statement module_name: (_) @left name: (_) @right) + (import_from_statement module_name: (_) @left (wildcard_import) @right) +] { + node push_dot + attr (push_dot) push_symbol = "." + + edge @right.before_scope -> push_dot + edge push_dot -> @left.ref } -;; import _.X -;; from _ import _.X +;;;; Non-relative Imports +;; +;; Non-relative imports are resolved in the root scope + [ - (import_statement - name: (dotted_name - (identifier) @leaf_name .)) - (import_from_statement - name: (dotted_name - (identifier) @leaf_name .)) -] -{ - edge @leaf_name.def -> @leaf_name.ref + (import_statement name: (_) @name) + (import_from_statement module_name: (dotted_name) @name) +] { + edge @name.before_scope -> ROOT_NODE } -;; . -(relative_import - (import_prefix) @prefix - (#eq? @prefix ".")) @import -{ - edge @prefix.ref -> @import.parent_module +;;;; Relative Imports +;; +;; Relative imports are resolved in scopes related to the current module + +;; . imports resolve in parent module scope +(import_from_statement module_name: (relative_import (import_prefix) @prefix (#eq? @prefix ".")) @relative) { + edge @relative.before_scope -> @prefix.parent_module } -;; .. -(relative_import - (import_prefix) @prefix - (#eq? @prefix "..")) @import -{ - edge @prefix.ref -> @import.grandparent_module +;; .. imports resolve in grandparent module scope +(import_from_statement module_name: (relative_import (import_prefix) @prefix (#eq? @prefix "..")) @relative) { + edge @relative.before_scope -> @prefix.grandparent_module } -;; .X -;; ..X -(relative_import - (import_prefix) @prefix - (dotted_name - . (identifier) @name)) -{ - attr (@name.ref_dot) push_symbol = "." - edge @name.ref -> @name.ref_dot - edge @name.ref_dot -> @prefix.ref +;;;; Future Imports +;; +;; We don't know the future, so we cannot connect references of future imports anywhere. Maybe one day? + +;; Import Definitions +;; ^^^^^^^^^^^^^^^^^^ + +;;;; Dotted Names & Aliased Imports +;; +;; (dotted_name).after_scope node to connect to, to expose the definition +;; (dotted_name).def node to connect from, to give definition content + +;; unaliased names and aliases are definitions +[ + (import_statement name: (dotted_name (identifier) @name)) + (future_import_statement name: (dotted_name (identifier) @name)) + (import_from_statement name: (dotted_name (identifier) @name)) + (import_statement name: (aliased_import alias: (identifier) @name)) + (future_import_statement name: (aliased_import alias: (identifier) @name)) + (import_from_statement name: (aliased_import alias: (identifier) @name)) +] { + attr (@name.def) node_definition = @name } -;; from . +;; definitions are chained [ - (import_from_statement - module_name: (relative_import - (dotted_name - (identifier) @parent_name - . - (identifier) @child_name))) - (import_from_statement - module_name: (dotted_name - (identifier) @parent_name - . - (identifier) @child_name)) -] -{ - attr (@child_name.ref_dot) push_symbol = "." - edge @child_name.ref -> @child_name.ref_dot - edge @child_name.ref_dot -> @parent_name.ref + (import_statement name: (dotted_name (identifier) @left . (identifier) @right)) + (future_import_statement name: (dotted_name (identifier) @left . (identifier) @right)) + (import_from_statement name: (dotted_name (identifier) @left . (identifier) @right)) +] { + node pop_dot + attr (pop_dot) pop_symbol = "." + + edge @left.def -> pop_dot + edge pop_dot -> @right.def } -;; from X._ import _ -(import_from_statement - module_name: (dotted_name - . (identifier) @root_name)) -{ - edge @root_name.ref -> ROOT_NODE +;; connect last definition +[ + (import_statement name: (dotted_name (identifier) @last .) @outer) + (future_import_statement name: (dotted_name (identifier) @last .) @outer) + (import_from_statement name: (dotted_name (identifier) @last .) @outer) + (import_statement name: (aliased_import alias: (identifier) @last ) @outer) + (future_import_statement name: (aliased_import alias: (identifier) @last ) @outer) + (import_from_statement name: (aliased_import alias: (identifier) @last ) @outer) +] { + edge @last.def -> @outer.def } -;; from _.X import * -(import_from_statement - module_name: (dotted_name - (identifier) @leaf_name .) - (wildcard_import) @star) @stmt -{ - edge @stmt.after_scope -> @star.ref_dot - attr (@stmt.after_scope -> @star.ref_dot) precedence = 1 - edge @star.ref_dot -> @leaf_name.ref - attr (@star.ref_dot) push_symbol = "." +;; expose first definition +[ + (import_statement name: (dotted_name . (identifier) @first) @outer) + (future_import_statement name: (dotted_name . (identifier) @first) @outer) + (import_from_statement name: (dotted_name . (identifier) @first) @outer) + (import_statement name: (aliased_import alias: (identifier) @first ) @outer) + (future_import_statement name: (aliased_import alias: (identifier) @first ) @outer) + (import_from_statement name: (aliased_import alias: (identifier) @first ) @outer) +] { + edge @outer.after_scope -> @first.def +} + +;;;; Wildcard Import +;; +;; Wildcard imports simply pass through + +(wildcard_import) @wildcard { + edge @wildcard.after_scope -> @wildcard.def } -;; import _.X.Y._ -;; from _ import _.X.Y._ -;; from _ import _.X.Y._ as _ +;;;; Import Definitions -> References +;; +;; The definitions introduced by imports are connected to the corresponding references + [ - (import_statement - name: (dotted_name - (identifier) @parent_name - . - (identifier) @child_name)) - (import_from_statement - name: (dotted_name - (identifier) @parent_name - . - (identifier) @child_name)) - (import_from_statement - name: (aliased_import - name: (dotted_name - (identifier) @parent_name - . - (identifier) @child_name))) -] -{ - edge @child_name.ref -> @child_name.ref_dot - edge @child_name.ref_dot -> @parent_name.ref - edge @parent_name.def -> @parent_name.def_dot - edge @parent_name.def_dot -> @child_name.def - attr (@parent_name.def_dot) pop_symbol = "." - attr (@child_name.ref_dot) push_symbol = "." + (import_statement name: (_) @name) + (future_import_statement name: (_) @name) + (import_from_statement name: (_) @name) + (import_from_statement (wildcard_import) @name) +] { + edge @name.def -> @name.ref +} + +;;;; Imports +;; +;; The definitions introduced by imports are visible after the import statement + +[ + (import_statement name: (_) @name) + (future_import_statement name: (_) @name) + (import_from_statement name: (_) @name) + (import_from_statement (wildcard_import) @name) +] @stmt { + edge @stmt.after_scope -> @name.after_scope + attr (@stmt.after_scope -> @name.after_scope) precedence = 1 } ;; diff --git a/languages/tree-sitter-stack-graphs-python/test/imports/import_submodule_aliased.py.skip b/languages/tree-sitter-stack-graphs-python/test/imports/import_submodule_aliased.py similarity index 89% rename from languages/tree-sitter-stack-graphs-python/test/imports/import_submodule_aliased.py.skip rename to languages/tree-sitter-stack-graphs-python/test/imports/import_submodule_aliased.py index dd84f39b5..b6bfdf7b7 100644 --- a/languages/tree-sitter-stack-graphs-python/test/imports/import_submodule_aliased.py.skip +++ b/languages/tree-sitter-stack-graphs-python/test/imports/import_submodule_aliased.py @@ -7,7 +7,7 @@ import foo.bar as qux qux.BAR -# ^ defined: 7 +# ^ defined: 7, 3 # ^ defined: 3 foo From 9135ff5cb66a71e9cda1f11af85e1903066ee4ed Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 30 Nov 2023 17:59:53 +0100 Subject: [PATCH 373/500] Fix parameter definitions --- .../src/stack-graphs.tsg | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 2c8c1e847..e784c37fc 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -813,12 +813,10 @@ inherit .parent_module edge @param.param_name -> @params.before_scope } -(parameter/identifier) @name { - attr (@name.def) node_definition = @name -} (parameter/identifier) @param @name { + attr (@name.def) node_definition = @name attr (@param.param_name) push_node = @param edge @name.def -> @param.param_name edge @name.def -> @param.param_index @@ -827,13 +825,13 @@ inherit .parent_module [ (parameter/default_parameter - name: (identifier) @name + name: (_) @name value: (_) @value) @param (parameter/typed_default_parameter name: (_) @name value: (_) @value) @param -] -{ +] { + attr (@name.def) node_definition = @name attr (@param.param_name) push_node = @name edge @name.def -> @param.param_name edge @name.def -> @param.param_index @@ -848,8 +846,8 @@ inherit .parent_module (_) @name) @param (parameter/dictionary_splat_pattern (_) @name) @param -] -{ +] { + attr (@name.def) node_definition = @name attr (@param.param_name) push_node = @name edge @name.def -> @param.param_name edge @name.def -> @param.param_index From 0f4bf9b5e14a71f451663c0383a6f26fe9c566c1 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 30 Nov 2023 23:47:41 +0100 Subject: [PATCH 374/500] Fixes for pattern identifiers --- .../src/stack-graphs.tsg | 58 ++++++++++++------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index e784c37fc..7cddd6783 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -1163,20 +1163,28 @@ inherit .parent_module ;; ;; Patterns -(pattern/identifier) @name { - attr (@name.def) node_definition = @name -} -(pattern/identifier) @name -{ - edge @name.output -> @name.local_scope - edge @name.output -> @name.class_parent_scope - edge @name.local_scope -> @name.input - attr (@name.local_scope -> @name.input) precedence = 1 - attr (@name.input) node_definition = @name - attr (@name.output) push_node = @name +[ + (pattern/identifier) @name @pattern + ; identifiers in patterns + (as_pattern (identifier) @name .) @pattern + (keyword_pattern (identifier) @name) @pattern + (splat_pattern (identifier) @name) @pattern + ; every context where _simple_pattern is used, because matching + ; pattern/dotted_name does not work + (case_pattern (dotted_name . (_) @name .) @pattern) + (keyword_pattern (dotted_name . (_) @name .) @pattern) + (union_pattern (dotted_name . (_) @name .) @pattern) +] { + attr (@name.def) node_definition = @name + edge @pattern.output -> @pattern.local_scope + edge @pattern.output -> @pattern.class_parent_scope + edge @pattern.local_scope -> @pattern.input + attr (@pattern.local_scope -> @pattern.input) precedence = 1 + attr (@pattern.input) node_definition = @name + attr (@pattern.output) push_node = @name - edge @name.new_bindings -> @name.def + edge @pattern.new_bindings -> @name.def } (pattern/subscript) {} @@ -1188,7 +1196,9 @@ inherit .parent_module } -(list_splat_pattern) {} +(list_splat_pattern (_) @pattern) @list { + edge @list.new_bindings -> @pattern.new_bindings +} [ (pattern_list (_) @pattern) @@ -1208,19 +1218,27 @@ inherit .parent_module attr (pattern_index) push_symbol = (named-child-index @pattern) } -(class_pattern) {} +(class_pattern (case_pattern) @pattern) @class { + edge @class.new_bindings -> @pattern.new_bindings +} -(splat_pattern) {} +(splat_pattern (_) @pattern) @splat { + edge @splat.new_bindings -> @pattern.new_bindings +} -(union_pattern) {} +(union_pattern (_) @pattern) @union { + edge @union.new_bindings -> @pattern.new_bindings +} -(dict_pattern) {} +(dict_pattern (_) @pattern) @dict { + edge @dict.new_bindings -> @pattern.new_bindings +} (complex_pattern) {} (as_pattern (expression) @value - alias: (as_pattern_target (primary_expression/identifier) @name)) @as_pattern + alias: (as_pattern_target (identifier) @name)) @as_pattern { attr (@name.local_scope -> @name.input) precedence = 1 attr (@name.input) is_definition @@ -1231,9 +1249,9 @@ inherit .parent_module (keyword_pattern) {} -(case_pattern (_) @expr) @pat +(case_pattern (_) @pattern) @case { - edge @pat.new_bindings -> @expr.new_bindings + edge @case.new_bindings -> @pattern.new_bindings } [ From 25ecd41bbaa97bbfe7e7a1f3f2a7665b08b4ccdb Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 10:56:29 -0500 Subject: [PATCH 375/500] Object patterns. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index 99a0f98b2..4036a2cd6 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -69,6 +69,7 @@ x++; 1 + 1; -2; (x = 1); +({ x: y } = 1); x += 1; (1, 2); 1 ? 2 : 3; From c6fe01a91f43dbaaf878809733a4262da76f9f91 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 10:57:00 -0500 Subject: [PATCH 376/500] Object patterns with comments. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index 4036a2cd6..817d41eaa 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -70,6 +70,7 @@ x++; -2; (x = 1); ({ x: y } = 1); +({/**/x: y } = 1); x += 1; (1, 2); 1 ? 2 : 3; From 95dda7decd09d6419c9cdf01dd27cfa7a62fe74f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 11:00:16 -0500 Subject: [PATCH 377/500] Allow comments occurring in object patterns. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 5d4100acb..25df7238d 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -399,6 +399,7 @@ inherit .return_or_yield node @comment.before_scope node @comment.value node @comment.covalue + node @comment.new_bindings ; for object patterns edge @comment.after_scope -> @comment.before_scope } From 1c2b0b04f7c50c9e13c933414e4e3e21c309fd0c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 11:04:47 -0500 Subject: [PATCH 378/500] Add a parameter. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index 99a0f98b2..f5986e241 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -8,6 +8,7 @@ debugger; var x; let x; function foo() { } +function foo(a) { } function* foo() { } class Foo { } { } From 5a22ebb33e597b3c23e40fc322edc16deaba4866 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 11:05:45 -0500 Subject: [PATCH 379/500] What if the parameter was named all collisiony? --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index f5986e241..b659631e5 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -9,6 +9,7 @@ var x; let x; function foo() { } function foo(a) { } +function foo(undefined) { } function* foo() { } class Foo { } { } From 3638c3010c91f5cb9cb95e7755208580bbd673e2 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 11:08:24 -0500 Subject: [PATCH 380/500] Hax! --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 5d4100acb..51a60c684 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -2412,6 +2412,9 @@ inherit .return_or_yield ; the value of undefined is the undefined primitive edge @undefined.value -> @undefined.builtins_undefined + + ; HACK: `undefined` is a perfectly cromulent name for a parameter, but the parser thinks it means this node instead. For the moment, work around the problem this causes by giving all `undefined` nodes covalues like parameters enjoy. + node @undefined.covalue } From fbc9e1745212baf9679e537752a5d9e6930b099b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 11:15:01 -0500 Subject: [PATCH 381/500] Array patterns. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index 99a0f98b2..e9828c76c 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -69,6 +69,7 @@ x++; 1 + 1; -2; (x = 1); +([x] = 1); x += 1; (1, 2); 1 ? 2 : 3; From 0ff55a0cc4020623459daaee05bbb1da940427e9 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 11:15:34 -0500 Subject: [PATCH 382/500] Subscripts in patterns. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index e9828c76c..c5a1b459c 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -70,6 +70,7 @@ x++; -2; (x = 1); ([x] = 1); +([x[i]] = 1); x += 1; (1, 2); 1 ? 2 : 3; From 8b3862fc025698dc6d9aad1a64b7d9aea67e0ccf Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 11:21:29 -0500 Subject: [PATCH 383/500] Subscript expressions get covalues. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 5d4100acb..5b30aa556 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3132,6 +3132,8 @@ inherit .return_or_yield edge @subscript_expr.value -> @subscript_expr.index_push edge @subscript_expr.index_push -> subscript_expr_push_dot + ; subscript expressions can appear in array patterns, on the left, and thus require a covalue + node @subscript_expr.covalue } (subscript_expression From 9e1b1fd529836d64a71e341bfa8cb4b0dcd94db0 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 11:22:07 -0500 Subject: [PATCH 384/500] Subscript expressions get bindings. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 5b30aa556..69d1737ae 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3132,8 +3132,9 @@ inherit .return_or_yield edge @subscript_expr.value -> @subscript_expr.index_push edge @subscript_expr.index_push -> subscript_expr_push_dot - ; subscript expressions can appear in array patterns, on the left, and thus require a covalue + ; subscript expressions can appear in array patterns, on the left, and thus require a covalue & bindings node @subscript_expr.covalue + node @subscript_expr.new_bindings } (subscript_expression From 39490e385290414367c2bf1b4f217cade4981728 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 11:23:46 -0500 Subject: [PATCH 385/500] Simplify the test. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index c5a1b459c..ba2101250 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -69,8 +69,8 @@ x++; 1 + 1; -2; (x = 1); +(x[i] = 1); ([x] = 1); -([x[i]] = 1); x += 1; (1, 2); 1 ? 2 : 3; From 19bba869d9fe983050de2530c4fa899f81c04a87 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 11:32:30 -0500 Subject: [PATCH 386/500] Blank. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index 99a0f98b2..cac4d04df 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -77,4 +77,5 @@ class { }; <>doo {garply} + {} \ No newline at end of file From 0f2ab27fc4454845aee0c6c437c008456aa1de8e Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 11:37:51 -0500 Subject: [PATCH 387/500] Space. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index cac4d04df..ee7e35755 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -77,5 +77,5 @@ class { }; <>doo {garply} - {} + { } \ No newline at end of file From 8bf750acd511923d9900ce8b1eff31780cbbaf1e Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 11:38:05 -0500 Subject: [PATCH 388/500] Comment. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index ee7e35755..fe122fd94 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -78,4 +78,5 @@ class { }; <>doo {garply} { } + {/**/x} \ No newline at end of file From b218bad5b8879fa7896dba046846d805d86da7b3 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 11:39:51 -0500 Subject: [PATCH 389/500] Allow for comments in JSX expressions. --- .../src/stack-graphs.tsg | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 5d4100acb..1b6b3e778 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3675,11 +3675,15 @@ inherit .return_or_yield } -(jsx_expression (_)?@child)@jsx_expression { +(jsx_expression)@jsx_expression { node @jsx_expression.before_scope node @jsx_expression.after_scope +} + +(jsx_expression (_)?@child)@jsx_expression { + if none @child { edge @jsx_expression.after_scope -> @jsx_expression.before_scope } else { From 3efe33ef883653334e2c52ee88216963c81711c9 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 11:46:43 -0500 Subject: [PATCH 390/500] Member expressions in patterns. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index 99a0f98b2..dde20b4a1 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -69,6 +69,7 @@ x++; 1 + 1; -2; (x = 1); +({x:y.z} = 1); x += 1; (1, 2); 1 ? 2 : 3; From a6ebb27be5ab47fa9b093487ae9104991efa8197 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 11:47:43 -0500 Subject: [PATCH 391/500] Member expressions get covalues. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 5d4100acb..8c126984c 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3108,6 +3108,8 @@ inherit .return_or_yield edge @member_expr.value -> property_push edge member_push -> @object.value + ; (member_expression) nodes can occur in patterns + node @member_expr.covalue } ;; ##### Subscript Expressions From a0d8fb64711d2b794e1b9a416fe8155749318318 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 11:48:02 -0500 Subject: [PATCH 392/500] Member expressions get bindings. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 8c126984c..f4ee64588 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3110,6 +3110,7 @@ inherit .return_or_yield ; (member_expression) nodes can occur in patterns node @member_expr.covalue + node @member_expr.new_bindings } ;; ##### Subscript Expressions From 5bfd95af033c9c66e84e2d939cf460cf33480a5d Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 11:54:40 -0500 Subject: [PATCH 393/500] Tests returns of values from the top-level scope. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index 99a0f98b2..4213068ea 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -27,6 +27,7 @@ with (x) { } break; continue; return; +return x; ; foo: x; From 198e06ce1b4b562e4691a13df3e29b7af254c26d Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 11:55:09 -0500 Subject: [PATCH 394/500] Plumb the program node for returns. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 5d4100acb..e182aa5ef 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -282,6 +282,9 @@ inherit .return_or_yield node @prog.after_scope node @prog.before_scope let @prog.closure_point = @prog.after_scope + + ; apparently it's perfectly cromulent to `return` from the top level scope (because control flow happens there too), so we make a top-level return node. + node @prog.return_or_yield } ;; ### Program Queries From cf5a9f6fe774295531fe9a11820e65d2fe38cc3a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 29 Jan 2024 12:46:17 -0500 Subject: [PATCH 395/500] Emphatically hacky. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 51a60c684..fccd318d9 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -2413,7 +2413,7 @@ inherit .return_or_yield ; the value of undefined is the undefined primitive edge @undefined.value -> @undefined.builtins_undefined - ; HACK: `undefined` is a perfectly cromulent name for a parameter, but the parser thinks it means this node instead. For the moment, work around the problem this causes by giving all `undefined` nodes covalues like parameters enjoy. + ; !!!! HACK: `undefined` is a perfectly cromulent name for a parameter, but the parser thinks it means this node instead. For the moment, work around the problem this causes by giving all `undefined` nodes covalues like parameters enjoy. node @undefined.covalue } From 16efa5cc91ee5aa7af498096d7b08a934164d6c3 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 1 Feb 2024 12:33:58 -0800 Subject: [PATCH 396/500] Adds missing function syntax type --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index d8b383c35..9bc0831b8 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4792,6 +4792,7 @@ inherit .containing_class_value attr (left_ignore_guard) pop_symbol = "GUARD:GANDALF" attr (left_definiens_hook) node_definition = @left attr (left_definiens_hook) definiens_node = @assignment_expr + attr (left_definiens_hook) syntax_type = "function" edge @assignment_expr.pkg_pop -> left_ignore_guard edge left_ignore_guard -> left_definiens_hook From fea338920dc3d8b1a4c1cea74eab404903a6eab0 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 1 Feb 2024 13:35:29 -0800 Subject: [PATCH 397/500] Fixes predicate bug --- .../src/stack-graphs.tsg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 9bc0831b8..17de7f014 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4761,8 +4761,8 @@ inherit .containing_class_value property:(_)@left ) right: (_))@assignment_expr - (#not-eq @_object "module") - (#not-eq @left "exports") + (#not-eq? @_object "module") + (#not-eq? @left "exports") ) { node left_definiens_hook @@ -4782,8 +4782,8 @@ inherit .containing_class_value property:(_)@left ) right: (_))@assignment_expr - (#eq @_object "module") - (#eq @left "exports") + (#eq? @_object "module") + (#eq? @left "exports") ) { node left_definiens_hook From 94de9153970f0a2f8b509cca504a875f45378a5c Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 1 Feb 2024 14:36:18 -0800 Subject: [PATCH 398/500] Revert "Adds missing function syntax type" This reverts commit 16efa5cc91ee5aa7af498096d7b08a934164d6c3. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 1 - 1 file changed, 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 17de7f014..273e2388e 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -4792,7 +4792,6 @@ inherit .containing_class_value attr (left_ignore_guard) pop_symbol = "GUARD:GANDALF" attr (left_definiens_hook) node_definition = @left attr (left_definiens_hook) definiens_node = @assignment_expr - attr (left_definiens_hook) syntax_type = "function" edge @assignment_expr.pkg_pop -> left_ignore_guard edge left_ignore_guard -> left_definiens_hook From 26bc1b12b4ad4bd448b3e5adfd53cb7a040a8ca9 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 1 Feb 2024 15:12:45 -0800 Subject: [PATCH 399/500] Fixes syntax types for exports --- .../src/stack-graphs.tsg | 240 +++++++++++++++--- 1 file changed, 204 insertions(+), 36 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 273e2388e..e67bfe332 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -557,6 +557,54 @@ inherit .containing_class_value } +(export_statement "default" + value:(_)@value)@export_stmt { + + node @export_stmt.pop_guard_default + attr (@export_stmt.pop_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @value, definiens_node = @export_stmt.export_statement + edge @export_stmt.exports -> @export_stmt.pop_guard_default + edge @export_stmt.pop_guard_default -> @value.value + + ; !!!! HACK These detour nodes are a massive hack to allow find all refs land on defs + ; for the default values of modules that have useful names like the module name or + ; package name + + node detour_push + node @export_stmt.detour_pop + + scan FILE_PATH { + + "^(.+/)?([^/]+)/index\.js$" { + let module_name = $2 + attr (detour_push) push_symbol = module_name + attr (@export_stmt.detour_pop) symbol_definition = module_name, source_node = @value, definiens_node = @export_stmt + edge @export_stmt.pop_guard_default -> detour_push + edge detour_push -> @export_stmt.detour_pop + edge @export_stmt.detour_pop -> @value.value + } + + "^(.+/)?([^/]+)\.js$" { + let module_name = $2 + attr (detour_push) push_symbol = module_name + attr (@export_stmt.detour_pop) symbol_definition = module_name, source_node = @value, definiens_node = @export_stmt + edge @export_stmt.pop_guard_default -> detour_push + edge detour_push -> @export_stmt.detour_pop + edge @export_stmt.detour_pop -> @value.value + } + + } + + node default_detour_push + node @export_stmt.default_detour_pop + + attr (default_detour_push) push_symbol = "default" + attr (@export_stmt.default_detour_pop) symbol_definition = "default", source_node = @value, definiens_node = @value + edge @export_stmt.pop_guard_default -> default_detour_push + edge default_detour_push -> @export_stmt.default_detour_pop + edge @export_stmt.default_detour_pop -> @value.value + +} + (export_statement declaration: [ (function_declaration name:(identifier)@name) @@ -4438,7 +4486,7 @@ inherit .containing_class_value node pop_default_guard node pop_dot - node pop_name + node @assignment_expr.pop_name attr (pop_default_guard) symbol_definition = "GUARD:DEFAULT", source_node = @exports edge @assignment_expr.exports -> pop_default_guard @@ -4446,47 +4494,47 @@ inherit .containing_class_value attr (pop_dot) pop_symbol = "GUARD:MEMBER" edge pop_default_guard -> pop_dot - attr (pop_name) node_definition = @property - attr (pop_name) definiens_node = @assignment_expr - edge pop_dot -> pop_name - edge pop_name -> @right.value + attr (@assignment_expr.pop_name) node_definition = @property + attr (@assignment_expr.pop_name) definiens_node = @assignment_expr + edge pop_dot -> @assignment_expr.pop_name + edge @assignment_expr.pop_name -> @right.value ;; For ES6 interoperability, expose members as named exports - edge @assignment_expr.exports -> pop_name + edge @assignment_expr.exports -> @assignment_expr.pop_name node detour_push - node detour_pop + node @assignment_expr.detour_pop scan FILE_PATH { "^(.+/)?([^/]+)/index\.js$" { let module_name = $2 attr (detour_push) push_symbol = module_name - attr (detour_pop) symbol_definition = module_name, source_node = @assignment_expr, definiens_node = @assignment_expr + attr (@assignment_expr.detour_pop) symbol_definition = module_name, source_node = @assignment_expr, definiens_node = @assignment_expr edge pop_default_guard -> detour_push - edge detour_push -> detour_pop - edge detour_pop -> @right.value + edge detour_push -> @assignment_expr.detour_pop + edge @assignment_expr.detour_pop -> @right.value } "^(.+/)?([^/]+)\.js$" { let module_name = $2 attr (detour_push) push_symbol = module_name - attr (detour_pop) symbol_definition = module_name, source_node = @assignment_expr, definiens_node = @assignment_expr + attr (@assignment_expr.detour_pop) symbol_definition = module_name, source_node = @assignment_expr, definiens_node = @assignment_expr edge pop_default_guard -> detour_push - edge detour_push -> detour_pop - edge detour_pop -> @right.value + edge detour_push -> @assignment_expr.detour_pop + edge @assignment_expr.detour_pop -> @right.value } } node default_detour_push - node default_detour_pop + node @assignment_expr.default_detour_pop attr (default_detour_push) push_symbol = "default" - attr (default_detour_pop) symbol_definition = "default", source_node = @assignment_expr, definiens_node = @assignment_expr + attr (@assignment_expr.default_detour_pop) symbol_definition = "default", source_node = @assignment_expr, definiens_node = @assignment_expr edge pop_default_guard -> default_detour_push - edge default_detour_push -> default_detour_pop - edge default_detour_pop -> @right.value + edge default_detour_push -> @assignment_expr.default_detour_pop + edge @assignment_expr.default_detour_pop -> @right.value } @@ -4500,13 +4548,13 @@ inherit .containing_class_value (#eq? @exports "exports") ) { - node pop_default_guard + node @assignment_expr.pop_default_guard node pop_dot - attr (pop_default_guard) symbol_definition = "GUARD:DEFAULT", source_node = @exports - attr (pop_default_guard) definiens_node = @assignment_expr - edge @assignment_expr.exports -> pop_default_guard - edge pop_default_guard -> @right.value + attr (@assignment_expr.pop_default_guard) symbol_definition = "GUARD:DEFAULT", source_node = @exports + attr (@assignment_expr.pop_default_guard) definiens_node = @assignment_expr + edge @assignment_expr.exports -> @assignment_expr.pop_default_guard + edge @assignment_expr.pop_default_guard -> @right.value ;; For ES6 interoperability, expose members as named exports attr (pop_dot) pop_symbol = "GUARD:MEMBER" @@ -4514,38 +4562,38 @@ inherit .containing_class_value edge pop_dot -> @right.value node detour_push - node detour_pop + node @assignment_expr.detour_pop scan FILE_PATH { "^(.+/)?([^/]+)/index\.js$" { let module_name = $2 attr (detour_push) push_symbol = module_name - attr (detour_pop) symbol_definition = module_name, source_node = @assignment_expr, definiens_node = @assignment_expr - edge pop_default_guard -> detour_push - edge detour_push -> detour_pop - edge detour_pop -> @right.value + attr (@assignment_expr.detour_pop) symbol_definition = module_name, source_node = @assignment_expr, definiens_node = @assignment_expr + edge @assignment_expr.pop_default_guard -> detour_push + edge detour_push -> @assignment_expr.detour_pop + edge @assignment_expr.detour_pop -> @right.value } "^(.+/)?([^/]+)\.js$" { let module_name = $2 attr (detour_push) push_symbol = module_name - attr (detour_pop) symbol_definition = module_name, source_node = @assignment_expr, definiens_node = @assignment_expr - edge pop_default_guard -> detour_push - edge detour_push -> detour_pop - edge detour_pop -> @right.value + attr (@assignment_expr.detour_pop) symbol_definition = module_name, source_node = @assignment_expr, definiens_node = @assignment_expr + edge @assignment_expr.pop_default_guard -> detour_push + edge detour_push -> @assignment_expr.detour_pop + edge @assignment_expr.detour_pop -> @right.value } } node default_detour_push - node default_detour_pop + node @assignment_expr.default_detour_pop attr (default_detour_push) push_symbol = "default" - attr (default_detour_pop) symbol_definition = "default", source_node = @assignment_expr, definiens_node = @assignment_expr - edge pop_default_guard -> default_detour_push - edge default_detour_push -> default_detour_pop - edge default_detour_pop -> @right.value + attr (@assignment_expr.default_detour_pop) symbol_definition = "default", source_node = @assignment_expr, definiens_node = @assignment_expr + edge @assignment_expr.pop_default_guard -> default_detour_push + edge default_detour_push -> @assignment_expr.default_detour_pop + edge @assignment_expr.default_detour_pop -> @right.value } @@ -4846,6 +4894,72 @@ inherit .containing_class_value } +( + (assignment_expression + left: [ + ( ; exports.foo = ... + (member_expression + object:(_)@_exports + property:(_)@_property) + (#eq? @_exports "exports") + ) + ( ; module.exports.foo = ... + (member_expression + object:(member_expression + object:(_)@_module + property:(_)@_exports) + property:(_)@_property) + (#eq? @_module "module") + (#eq? @_exports "exports") + ) + ] + right: [ + (function) + (generator_function) + (arrow_function) + ])@assignment_expr + +) { + + attr (@assignment_expr.pop_name) syntax_type = "function" + attr (@assignment_expr.detour_pop) syntax_type = "function" + attr (@assignment_expr.default_detour_pop) syntax_type = "function" + +} + +( + (assignment_expression + left: (member_expression + object:(_)@_module + property:(_)@_exports) + right: [ + (function) + (generator_function) + (arrow_function) + ])@assignment_expr + (#eq? @_module "module") + (#eq? @_exports "exports") +) { + + attr (@assignment_expr.pop_default_guard) syntax_type = "function" + attr (@assignment_expr.detour_pop) syntax_type = "function" + attr (@assignment_expr.default_detour_pop) syntax_type = "function" + +} + +(export_statement "default" + value:[ + (function) + (generator_function) + (arrow_function) + ])@export_stmt { + + attr (@export_stmt.pop_guard_default) syntax_type = "function" + attr (@export_stmt.detour_pop) syntax_type = "function" + attr (@export_stmt.default_detour_pop) syntax_type = "function" + +} + (pair key: (_)@name value: [ @@ -4880,6 +4994,60 @@ inherit .containing_class_value } +( + (assignment_expression + left: [ + ( ; exports.foo = ... + (member_expression + object:(_)@_exports + property:(_)@_property) + (#eq? @_exports "exports") + ) + ( ; module.exports.foo = ... + (member_expression + object:(member_expression + object:(_)@_module + property:(_)@_exports) + property:(_)@_property) + (#eq? @_module "module") + (#eq? @_exports "exports") + ) + ] + right: (class))@assignment_expr + +) { + + attr (@assignment_expr.pop_name) syntax_type = "class" + attr (@assignment_expr.detour_pop) syntax_type = "class" + attr (@assignment_expr.default_detour_pop) syntax_type = "class" + +} + +( + (assignment_expression + left: (member_expression + object:(_)@_module + property:(_)@_exports) + right: (class))@assignment_expr + (#eq? @_module "module") + (#eq? @_exports "exports") +) { + + attr (@assignment_expr.pop_default_guard) syntax_type = "class" + attr (@assignment_expr.detour_pop) syntax_type = "class" + attr (@assignment_expr.default_detour_pop) syntax_type = "class" + +} + +(export_statement "default" + value:(class))@export_stmt { + + attr (@export_stmt.pop_guard_default) syntax_type = "class" + attr (@export_stmt.detour_pop) syntax_type = "class" + attr (@export_stmt.default_detour_pop) syntax_type = "class" + +} + (pair key: (_)@name value: (class)) { From 5b7b4d657ace1f20592a115b78ae415db32f41dd Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 1 Feb 2024 15:55:29 -0800 Subject: [PATCH 400/500] Fixes minor export statement definiens bugs --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index e67bfe332..907a1cb47 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -550,7 +550,7 @@ inherit .containing_class_value node default_detour_pop attr (default_detour_push) push_symbol = "default" - attr (default_detour_pop) symbol_definition = "default", source_node = @decl, definiens_node = @decl + attr (default_detour_pop) symbol_definition = "default", source_node = @decl, definiens_node = @export_stmt edge pop_guard_default -> default_detour_push edge default_detour_push -> default_detour_pop ; edge default_detour_pop -> @decl.value ;; FIXME declarations have no .value @@ -598,7 +598,7 @@ inherit .containing_class_value node @export_stmt.default_detour_pop attr (default_detour_push) push_symbol = "default" - attr (@export_stmt.default_detour_pop) symbol_definition = "default", source_node = @value, definiens_node = @value + attr (@export_stmt.default_detour_pop) symbol_definition = "default", source_node = @value, definiens_node = @export_stmt edge @export_stmt.pop_guard_default -> default_detour_push edge default_detour_push -> @export_stmt.default_detour_pop edge @export_stmt.default_detour_pop -> @value.value From 6bdf56879ed999e4e9a847dfb671c9c91ba0a944 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 1 Feb 2024 15:55:48 -0800 Subject: [PATCH 401/500] Fixes unneeded scoped variable --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 907a1cb47..28497a917 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -513,7 +513,7 @@ inherit .containing_class_value (declaration)@decl)@export_stmt { node pop_guard_default - attr (pop_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @decl, definiens_node = @export_stmt.export_statement + attr (pop_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @decl, definiens_node = @export_stmt edge @export_stmt.exports -> pop_guard_default ;; edge export_stmt_pop_guard_default -> @decl.value ;; FIXME declarations have no .value @@ -561,7 +561,7 @@ inherit .containing_class_value value:(_)@value)@export_stmt { node @export_stmt.pop_guard_default - attr (@export_stmt.pop_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @value, definiens_node = @export_stmt.export_statement + attr (@export_stmt.pop_guard_default) symbol_definition = "GUARD:DEFAULT", source_node = @value, definiens_node = @export_stmt edge @export_stmt.exports -> @export_stmt.pop_guard_default edge @export_stmt.pop_guard_default -> @value.value From 840d9f8fa58a70d915f469097d3687ac6c3fedb5 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 1 Feb 2024 16:22:58 -0800 Subject: [PATCH 402/500] Removes redundant default nodes --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 5 ----- 1 file changed, 5 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 28497a917..be7041697 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -790,13 +790,8 @@ inherit .containing_class_value (export_statement value:(_)@default_expr)@export_stmt { - node pop_default_guard - - attr (pop_default_guard) symbol_definition = "GUARD:DEFAULT", source_node = @export_stmt, definiens_node = @export_stmt.export_statement edge @default_expr.before_scope -> @export_stmt.before_scope edge @export_stmt.after_scope -> @default_expr.after_scope - edge @export_stmt.exports -> pop_default_guard - edge pop_default_guard -> @default_expr.value } From 187f972a06aa56d0104fed6a7079afa02c532fb2 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 2 Feb 2024 10:23:32 -0500 Subject: [PATCH 403/500] Test an identifier decorator. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index fde1656aa..4e61d5389 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -12,6 +12,7 @@ function foo(a) { } function foo(undefined) { } function* foo() { } class Foo { } +@Foo class Bar { } { } if (true) { } if (true) { } else { } From 8e9114e78e0ae61b110dfe04bdd0fda6ca461ae6 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 2 Feb 2024 10:24:19 -0500 Subject: [PATCH 404/500] Test a call expression decorator. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index 4e61d5389..8eb29e333 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -13,6 +13,7 @@ function foo(undefined) { } function* foo() { } class Foo { } @Foo class Bar { } +@Foo() class Bar { } { } if (true) { } if (true) { } else { } From 55ba0852f12fd979917387ab8bce918c5a6f9fd3 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 2 Feb 2024 10:43:31 -0500 Subject: [PATCH 405/500] Test member expression decorators. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index 8eb29e333..e3c659745 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -13,6 +13,7 @@ function foo(undefined) { } function* foo() { } class Foo { } @Foo class Bar { } +@Foo.Quux class Bar { } @Foo() class Bar { } { } if (true) { } From 1350957293760199b94f72e21e175d80cfcbfabc Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 2 Feb 2024 10:44:49 -0500 Subject: [PATCH 406/500] Test member expression in call expression decorators. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index e3c659745..cc4076cf5 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -15,6 +15,7 @@ class Foo { } @Foo class Bar { } @Foo.Quux class Bar { } @Foo() class Bar { } +@Foo.Quux() class Bar { } { } if (true) { } if (true) { } else { } From 0b386a1fa84373dca1cb29643c5e66a08651d09b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 2 Feb 2024 13:13:07 -0500 Subject: [PATCH 407/500] Handle identifiers more or less uniformly. --- .../src/stack-graphs.tsg | 32 ++++++------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index d8b383c35..4b2aef557 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -411,6 +411,15 @@ inherit .containing_class_value edge @comment.after_scope -> @comment.before_scope } +(identifier) @identifier { + node @identifier.before_scope + node @identifier.after_scope + node @identifier.value + node @identifier.covalue + node @identifier.new_bindings + edge @identifier.after_scope -> @identifier.before_scope +} + @@ -2226,7 +2235,6 @@ inherit .containing_class_value (member_expression) (parenthesized_expression) (undefined) - (primary_expression/identifier) (this) (super) (number) @@ -2355,9 +2363,6 @@ inherit .containing_class_value ;; #### Variables (primary_expression/identifier)@variable { - ; scopes don't change - edge @variable.after_scope -> @variable.before_scope - ; value is a lookup, ie a push attr (@variable.value) node_reference = @variable edge @variable.value -> @variable.before_scope @@ -2864,16 +2869,9 @@ inherit .containing_class_value (arrow_function parameter:(_)@param)@fun { - - node @param.after_scope node param_arg_index - node @param.before_scope - node @param.covalue node param_pop - ; scope flows from the param right back out - edge @param.after_scope -> @param.before_scope - ; but augmented with a pop, b/c it's not a pattern attr (param_pop) node_definition = @param edge param_pop -> @param.covalue @@ -3742,12 +3740,6 @@ inherit .containing_class_value name:(identifier)@element_name) ] { - - node @element_name.before_scope - node @element_name.after_scope - - edge @element_name.after_scope -> @element_name.before_scope - scan (source-text @element_name) { ; standard HTML elements "^(a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdi|bdo|big|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|data|datalist|dd|del|details|dfn|dialog|dir|div|dl|dt|em|embed|fieldset|figcaption|figure|font|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|header|hgroup|hr|html|i|iframe|input|ins|kbd|label|legend|li|link|main|map|mark|menu|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|picture|pre|progress|q|rp|rt|ruby|s|samp|script|search|section|select|small|source|span|strike|strong|style|sub|summary|sup|svg|table|tbody|td|template|textarea|tfoot|th|thead|time|title|tr|track|tt|u|ul|var|video|wbr)$" { @@ -3776,8 +3768,6 @@ inherit .containing_class_value (identifier)@first_part (identifier)@second_part)@nested_identifier { - node @first_part.value - node @second_part.value node guard_member attr (@first_part.value) node_reference = @first_part @@ -3794,7 +3784,6 @@ inherit .containing_class_value (nested_identifier)@first_part (identifier)@second_part)@nested_identifier { - node @second_part.value node guard_member attr (@second_part.value) node_reference = @second_part @@ -4086,13 +4075,11 @@ inherit .containing_class_value ;; ### Attributes Defined on Patterns ;; TODO [ - (assignment_expression left:(identifier)@pattern) (assignment_pattern)@pattern (object_pattern)@pattern (array_pattern)@pattern (rest_pattern)@pattern (pair_pattern)@pattern - (pattern/identifier)@pattern (pattern/property_identifier)@pattern (object_assignment_pattern)@pattern (shorthand_property_identifier_pattern)@pattern @@ -4117,7 +4104,6 @@ inherit .containing_class_value ; scope flows through, binding via a pop edge that goes to an unknown value attr (ident_pat_pop) node_definition = @ident_pat edge ident_pat_pop -> @ident_pat.covalue - edge @ident_pat.after_scope -> @ident_pat.before_scope edge @ident_pat.after_scope -> ident_pat_pop edge @ident_pat.new_bindings -> ident_pat_pop From 76e4b05d9a11e6ccd4a09f240a7e37700a2671fe Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 6 Feb 2024 12:08:23 -0500 Subject: [PATCH 408/500] Test fields. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index cc4076cf5..686dfb340 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -11,7 +11,9 @@ function foo() { } function foo(a) { } function foo(undefined) { } function* foo() { } -class Foo { } +class Foo { + #x = null; +} @Foo class Bar { } @Foo.Quux class Bar { } @Foo() class Bar { } From 5563c01a9c8310ce1af729661800614fbd2effe2 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 6 Feb 2024 12:13:57 -0500 Subject: [PATCH 409/500] Always give field defs scopes. --- .../src/stack-graphs.tsg | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 6680f4a90..84b11546f 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -1661,11 +1661,14 @@ inherit .containing_class_value +(field_definition)@field_def { + node @field_def.after_scope + node @field_def.before_scope +} + (field_definition property:(property_identifier)@property)@field_def { - node @field_def.after_scope - node @field_def.before_scope node @property.pop node property_pop_dot From 82679f8acfd9b63b5dd60a134c89d39a6711a5de Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 6 Feb 2024 12:15:48 -0500 Subject: [PATCH 410/500] Generalize to accept private properties. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 84b11546f..956cd0406 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -1667,7 +1667,7 @@ inherit .containing_class_value } (field_definition - property:(property_identifier)@property)@field_def { + property:(_)@property)@field_def { node @property.pop node property_pop_dot From b01ce15ea301937a8a501e8404ff34c9d1c33405 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Thu, 8 Feb 2024 12:53:13 -0500 Subject: [PATCH 411/500] Test comments in export lists. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index 686dfb340..44e7727c4 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -3,6 +3,10 @@ // foo export let x = 1; +export { + // x + A +}; import "foo"; debugger; var x; From 0e6ef5be587b649ed64d1d8e7172f821db527b61 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Thu, 8 Feb 2024 12:56:35 -0500 Subject: [PATCH 412/500] Support comments in export clauses. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 956cd0406..677436013 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -409,6 +409,7 @@ inherit .containing_class_value node @comment.covalue node @comment.new_bindings ; for object patterns edge @comment.after_scope -> @comment.before_scope + node @comment.source ; for export clauses with multiple exports } (identifier) @identifier { From b4f16e10a6fef97cc7125b5924cc67e3511f53af Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 9 Feb 2024 09:47:32 -0500 Subject: [PATCH 413/500] Test class static blocks. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index 686dfb340..ab0cf1c05 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -13,6 +13,7 @@ function foo(undefined) { } function* foo() { } class Foo { #x = null; + static {} } @Foo class Bar { } @Foo.Quux class Bar { } From e69c8cbe27156edefbc26e2b9417e53c54fa403c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 9 Feb 2024 09:51:46 -0500 Subject: [PATCH 414/500] Class static blocks have before/after scopes. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 956cd0406..c5e72fd27 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -1693,6 +1693,11 @@ inherit .containing_class_value edge @property.pop -> @value.value } +(class_static_block) @static_block { + node @static_block.before_scope + node @static_block.after_scope +} + ;; #### Statement Block From 4ef094357d0ef1a2058785bc1865230063bb7563 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 9 Feb 2024 09:54:15 -0500 Subject: [PATCH 415/500] Propagate scopes internally. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index c5e72fd27..6d32ef9d8 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -1693,9 +1693,11 @@ inherit .containing_class_value edge @property.pop -> @value.value } -(class_static_block) @static_block { +(class_static_block body: (_) @body) @static_block { node @static_block.before_scope node @static_block.after_scope + + edge @body.before_scope -> @static_block.before_scope } From 7c36737c08c9e66d407da2ec03b3904aa6a2665d Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 9 Feb 2024 09:54:39 -0500 Subject: [PATCH 416/500] Propagate scopes laterally. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 6d32ef9d8..1f0ef3d9a 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -1698,6 +1698,8 @@ inherit .containing_class_value node @static_block.after_scope edge @body.before_scope -> @static_block.before_scope + + edge @static_block.after_scope -> @static_block.before_scope } From e05c9db6a7a4813cb035ca61f93ed90545855583 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 9 Feb 2024 10:10:26 -0500 Subject: [PATCH 417/500] Test computed property names. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index 686dfb340..75c74691f 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -13,6 +13,7 @@ function foo(undefined) { } function* foo() { } class Foo { #x = null; + get [/**/ foo]() {} } @Foo class Bar { } @Foo.Quux class Bar { } From c4255f04fad9fc0414b70aea88f53922d0d7fef5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 9 Feb 2024 10:11:59 -0500 Subject: [PATCH 418/500] Construct the scopes exactly once. --- .../src/stack-graphs.tsg | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 956cd0406..f5729a37a 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -2582,10 +2582,13 @@ inherit .containing_class_value ; pairs -(computed_property_name (_)@expr)@computed_property_name { - +(computed_property_name)@computed_property_name { node @computed_property_name.after_scope node @computed_property_name.before_scope +} + +(computed_property_name (_)@expr)@computed_property_name { + edge @expr.before_scope -> @computed_property_name.before_scope edge @computed_property_name.after_scope -> @expr.after_scope From bd403b61969f57f0d49fe75c6e0c4b0c892a24e5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 9 Feb 2024 13:05:30 -0500 Subject: [PATCH 419/500] Test namespaced JSX names. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index 686dfb340..74556c075 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -93,4 +93,6 @@ class { }; {garply} { } {/**/x} - \ No newline at end of file +; +; +; \ No newline at end of file From 4fc8fe354f84ebe7165d505a6fcd70f7662ffc7d Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 9 Feb 2024 13:09:43 -0500 Subject: [PATCH 420/500] Namespace names have scopes. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 956cd0406..9043ee469 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3698,6 +3698,11 @@ inherit .containing_class_value } +(jsx_namespace_name (_) @lhs (_) @rhs)@name { + node @name.before_scope + node @name.after_scope +} + (jsx_self_closing_element name:(_)@element_name)@jsx_self_closing_element { From f631081cd53d2cf3b2d498a5c8064bbd505f5dbc Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 9 Feb 2024 13:10:23 -0500 Subject: [PATCH 421/500] The namespace follows the scopes. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 9043ee469..8db276908 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3701,6 +3701,8 @@ inherit .containing_class_value (jsx_namespace_name (_) @lhs (_) @rhs)@name { node @name.before_scope node @name.after_scope + + edge @lhs.before_scope -> @name.before_scope } (jsx_self_closing_element From 297d6078f9ad5175f7576e49dbcd7e7d619c1d3a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 9 Feb 2024 13:11:43 -0500 Subject: [PATCH 422/500] Namespaced names' namespaced names are namespaced. I'm unsure whether this is the right thing to do, and I'm unsure whether it matters. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 8db276908..8a01f4a3d 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3703,6 +3703,7 @@ inherit .containing_class_value node @name.after_scope edge @lhs.before_scope -> @name.before_scope + edge @rhs.before_scope -> @lhs.after_scope } (jsx_self_closing_element From 397a9c9d1cf7c2d375af5f46921c71366784f5b1 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 9 Feb 2024 13:12:03 -0500 Subject: [PATCH 423/500] Flow. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index 8a01f4a3d..75b93e9d4 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -3704,6 +3704,7 @@ inherit .containing_class_value edge @lhs.before_scope -> @name.before_scope edge @rhs.before_scope -> @lhs.after_scope + edge @name.after_scope -> @name.before_scope } (jsx_self_closing_element From 1afad1c1fcc47c6af1c659f00b28931ef9f9cb8b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 9 Feb 2024 15:24:05 -0500 Subject: [PATCH 424/500] Test with a method (property?) named constructor. --- .../tree-sitter-stack-graphs-javascript/test/base_syntax.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js index cd29e4266..4cf3170d0 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/base_syntax.js @@ -11,6 +11,9 @@ import "foo"; debugger; var x; let x; +let x = { + get constructor() {} +}; function foo() { } function foo(a) { } function foo(undefined) { } From 61648e1cf51a12625657a404020bb28620aed46d Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 9 Feb 2024 15:28:14 -0500 Subject: [PATCH 425/500] Add the requisite things for objects/classes. --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index cc33b7e23..e69a4636a 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -2525,6 +2525,9 @@ inherit .containing_class_value attr (@object.member_pop) pop_symbol = "GUARD:MEMBER" edge @object.value -> @object.member_pop + node @object.class_value + node @object.constructor + } ; empty objects From 3f3b9bca955567497b031aebfd9d981408ad887e Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 13 Feb 2024 13:46:12 -0800 Subject: [PATCH 426/500] Adds pairs --- languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 7cddd6783..48353f14a 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -152,6 +152,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (set) (set_comprehension) (tuple) + (pair) (parenthesized_expression) (generator_expression) (ellipsis) From 4b613bf38963f8a0cce38e070d2e48d35a6c2101 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 5 Mar 2024 14:17:16 +0100 Subject: [PATCH 427/500] Update dependency versions to fix install problems. --- .github/workflows/ci.yml | 37 ++++++++++--------- .../tree-sitter-stack-graphs-java/Cargo.toml | 14 +++++-- lsp-positions/Cargo.toml | 10 +++-- stack-graphs/Cargo.toml | 7 ++-- tree-sitter-stack-graphs/Cargo.toml | 9 +++-- 5 files changed, 45 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cad93d701..0d6ec91bb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,12 +17,17 @@ jobs: strategy: matrix: rust: [stable] + env: + # cargo hack does not use the default-members in Cargo.toml, so we restrict to those explicitly + CARGO_HACK: cargo hack -p lsp-positions -p stack-graphs -p tree-sitter-stack-graphs --feature-powerset --exclude-features copious-debugging steps: - name: Install Rust environment uses: hecrj/setup-rust-action@v1 with: rust-version: ${{ matrix.rust }} + - name: Install cargo-hack + run: cargo install cargo-hack - name: Checkout code uses: actions/checkout@v3 - name: Check formatting @@ -36,28 +41,24 @@ jobs: key: ${{ runner.OS }}-cargo-${{ hashFiles('**/Cargo.lock') }} restore-keys: | ${{ runner.OS }}-cargo- + - name: Build library (all feature combinations) + run: ${{ env.CARGO_HACK }} --no-dev-deps build + - name: Run test suite (all feature combinations) + run: ${{ env.CARGO_HACK }} test + - name: Run test suite with all optimizations (default features) + run: cargo test --release - name: Install cargo-valgrind run: | sudo apt-get update sudo apt-get install -y valgrind cargo install cargo-valgrind - - name: Build library - run: cargo build + - name: Run test suite under valgrind (default features) + # We only need to use valgrind to test the crates that have C bindings. + run: cargo valgrind test -p stack-graphs - name: Ensure C headers are up to date run: | script/cbindgen test -z "$(git status --porcelain)" - - name: Run test suite - run: cargo test - - name: Run test suite under valgrind - # We only need to use valgrind to test the crates that have C bindings. - run: cargo valgrind test -p stack-graphs - - name: Run lsp-positions tests without tree-sitter - run: cargo test -p lsp-positions --no-default-features - - name: Run test suite with all features enabled - run: cargo test --all-features - - name: Run test suite with all optimizations - run: cargo test --release test-init: needs: [test-rust] @@ -112,6 +113,8 @@ jobs: uses: hecrj/setup-rust-action@v1 with: rust-version: ${{ matrix.rust }} + - name: Install cargo-hack + run: cargo install cargo-hack - name: Cache dependencies uses: actions/cache@v3 with: @@ -123,10 +126,10 @@ jobs: ${{ runner.OS }}-cargo- - name: Checkout code uses: actions/checkout@v3 - - name: Build - run: cargo build -p ${{ matrix.language }} - - name: Test - run: cargo test -p ${{ matrix.language }} + - name: Build (all feature combinations) + run: cargo hack -p ${{ matrix.language }} --feature-powerset build + - name: Test (all features) + run: cargo test -p ${{ matrix.language }} --all-features test-cli: runs-on: ubuntu-latest diff --git a/languages/tree-sitter-stack-graphs-java/Cargo.toml b/languages/tree-sitter-stack-graphs-java/Cargo.toml index 8bd3e5f93..21b5b25fa 100644 --- a/languages/tree-sitter-stack-graphs-java/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-java/Cargo.toml @@ -23,6 +23,7 @@ keywords = ["tree-sitter", "stack-graphs", "java"] [[bin]] name = "tree-sitter-stack-graphs-java" path = "rust/bin.rs" +required-features = ["cli"] [lib] path = "rust/lib.rs" @@ -33,8 +34,15 @@ name = "test" path = "rust/test.rs" harness = false # need to provide own main function to handle running tests +[features] +cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"] + [dependencies] -anyhow = "1.0" -clap = { version = "4", features = ["derive"] } -tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs", features=["cli"] } +anyhow = { version = "1.0", optional = true } +clap = { version = "4", features = ["derive"], optional = true } tree-sitter-java = { version = "=0.20.0" } +tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs" } + +[dev-dependencies] +anyhow = { version = "1.0" } +tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs", features = ["cli"] } diff --git a/lsp-positions/Cargo.toml b/lsp-positions/Cargo.toml index 242a894ff..b7422a9d7 100644 --- a/lsp-positions/Cargo.toml +++ b/lsp-positions/Cargo.toml @@ -22,7 +22,9 @@ tree-sitter = ["dep:tree-sitter"] [dependencies] memchr = "2.4" -tree-sitter = { version=">= 0.19", optional=true } -unicode-segmentation = { version="1.8" } -serde = { version="1", optional=true, features=["derive"] } -bincode = { version="2.0.0-rc.3", optional=true } +tree-sitter = { version = "0.20", optional = true } # keep the same minor version as the tree-sitter + # dependency of tree-sitter-stack-graphs to prevent + # install problems +unicode-segmentation = { version = "1.8" } +serde = { version = "1", features = ["derive"], optional = true } +bincode = { version = "2.0.0-rc.3", optional = true } diff --git a/stack-graphs/Cargo.toml b/stack-graphs/Cargo.toml index 2e55e1768..0633d40c4 100644 --- a/stack-graphs/Cargo.toml +++ b/stack-graphs/Cargo.toml @@ -25,12 +25,12 @@ test = false [dependencies] bincode = { version = "2.0.0-rc.3", optional = true } -bitvec = "1.0" -controlled-option = "0.4" +bitvec = "1.0.1" +controlled-option = "0.4.1" either = "1.6" enumset = "1.1" fxhash = "0.2" -itertools = "0.10" +itertools = "0.10.2" libc = "0.2" lsp-positions = { version = "0.3", path = "../lsp-positions" } rusqlite = { version = "0.28", optional = true, features = ["bundled", "functions"] } @@ -42,7 +42,6 @@ thiserror = { version = "1.0" } [dev-dependencies] assert-json-diff = "2" -itertools = "0.10" maplit = "1.0" pretty_assertions = "0.7" serde_json = { version = "1.0" } diff --git a/tree-sitter-stack-graphs/Cargo.toml b/tree-sitter-stack-graphs/Cargo.toml index d5429304a..ddce19309 100644 --- a/tree-sitter-stack-graphs/Cargo.toml +++ b/tree-sitter-stack-graphs/Cargo.toml @@ -49,12 +49,12 @@ lsp = [ ] [dependencies] -anyhow = "1.0" +anyhow = "1.0.4" base64 = { version = "0.21", optional = true } capture-it = { version = "0.3", optional = true } clap = { version = "4", optional = true, features = ["derive"] } colored = { version = "2.0", optional = true } -controlled-option = ">=0.4" +controlled-option = "0.4.1" crossbeam-channel = { version = "0.5", optional = true } dialoguer = { version = "0.10", optional = true } dirs = { version = "5", optional = true } @@ -69,12 +69,13 @@ regex = "1" rust-ini = "0.18" serde_json = { version="1.0", optional=true } sha1 = { version="0.10", optional=true } -stack-graphs = { version=">=0.11, <=0.12", path="../stack-graphs" } +stack-graphs = { version="0.12", path="../stack-graphs" } thiserror = "1.0" time = { version = "0.3", optional = true } tokio = { version = "1.26", optional = true, features = ["io-std", "rt", "rt-multi-thread"] } tower-lsp = { version = "0.19", optional = true } -tree-sitter = ">= 0.19" +tree-sitter = "0.20" # keep the same minor version as the tree-sitter dependency + # of tree-sitter-graph to prevent install problems tree-sitter-config = { version = "0.19", optional = true } tree-sitter-graph = "0.11" tree-sitter-loader = "0.20" From 9a7a566f8f4ce13d3bfb3b3be60d37761a895f7d Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 5 Mar 2024 19:06:59 +0100 Subject: [PATCH 428/500] Bump lsp-positions to v0.3.3 --- lsp-positions/CHANGELOG.md | 4 ++++ lsp-positions/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lsp-positions/CHANGELOG.md b/lsp-positions/CHANGELOG.md index 36a0d4ebd..a9e17c13f 100644 --- a/lsp-positions/CHANGELOG.md +++ b/lsp-positions/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v0.3.3 -- 2024-03-05 + +The `tree-sitter` dependency version was updated to fix install problems. + ## v0.3.2 -- 2023-06-08 ### Added diff --git a/lsp-positions/Cargo.toml b/lsp-positions/Cargo.toml index b7422a9d7..7054def14 100644 --- a/lsp-positions/Cargo.toml +++ b/lsp-positions/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lsp-positions" -version = "0.3.2" +version = "0.3.3" description = "LSP-compatible character positions" homepage = "https://github.com/github/stack-graphs/tree/main/lsp-positions" repository = "https://github.com/github/stack-graphs/" From a7f9d9cb0e682aa672d77a5ce2e57f148776ac78 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 5 Mar 2024 19:21:23 +0100 Subject: [PATCH 429/500] Bump tree-sitter-stack-graphs to v0.8.0 --- languages/tree-sitter-stack-graphs-java/Cargo.toml | 4 ++-- languages/tree-sitter-stack-graphs-javascript/Cargo.toml | 4 ++-- languages/tree-sitter-stack-graphs-python/Cargo.toml | 4 ++-- languages/tree-sitter-stack-graphs-typescript/Cargo.toml | 4 ++-- tree-sitter-stack-graphs/CHANGELOG.md | 4 +++- tree-sitter-stack-graphs/Cargo.toml | 2 +- tree-sitter-stack-graphs/README.md | 2 +- 7 files changed, 13 insertions(+), 11 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-java/Cargo.toml b/languages/tree-sitter-stack-graphs-java/Cargo.toml index 21b5b25fa..8af4b3277 100644 --- a/languages/tree-sitter-stack-graphs-java/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-java/Cargo.toml @@ -41,8 +41,8 @@ cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"] anyhow = { version = "1.0", optional = true } clap = { version = "4", features = ["derive"], optional = true } tree-sitter-java = { version = "=0.20.0" } -tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs" } +tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs" } [dev-dependencies] anyhow = { version = "1.0" } -tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs", features = ["cli"] } +tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs", features = ["cli"] } diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml index 624edbab2..5c9522f77 100644 --- a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -31,9 +31,9 @@ clap = { version = "4", optional = true } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" stack-graphs = { version = "0.12", path = "../../stack-graphs" } -tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs" } +tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs" } tree-sitter-javascript = { git = "https://github.com/tree-sitter/tree-sitter-javascript", rev = "5720b249490b3c17245ba772f6be4a43edb4e3b7" } [dev-dependencies] anyhow = "1.0" -tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs", features = ["cli"] } +tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs", features = ["cli"] } diff --git a/languages/tree-sitter-stack-graphs-python/Cargo.toml b/languages/tree-sitter-stack-graphs-python/Cargo.toml index 4ac4c0633..17cfa3d72 100644 --- a/languages/tree-sitter-stack-graphs-python/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-python/Cargo.toml @@ -30,9 +30,9 @@ cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"] [dependencies] anyhow = { version = "1.0", optional = true } clap = { version = "4", optional = true, features = ["derive"] } -tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs" } +tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs" } tree-sitter-python = "=0.20.4" [dev-dependencies] anyhow = "1.0" -tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs", features = ["cli"] } +tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs", features = ["cli"] } diff --git a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml index da5df7ef9..fa273c2cd 100644 --- a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml @@ -33,10 +33,10 @@ glob = "0.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" stack-graphs = { version = ">=0.11, <=0.12", path = "../../stack-graphs" } -tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs" } +tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs" } tree-sitter-typescript = "=0.20.2" tsconfig = "0.1.0" [dev-dependencies] anyhow = { version = "1.0" } -tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs", features = ["cli"] } +tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs", features = ["cli"] } diff --git a/tree-sitter-stack-graphs/CHANGELOG.md b/tree-sitter-stack-graphs/CHANGELOG.md index 8d8ef7ca1..50f8b1f9b 100644 --- a/tree-sitter-stack-graphs/CHANGELOG.md +++ b/tree-sitter-stack-graphs/CHANGELOG.md @@ -5,7 +5,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## v0.8.0 -- 2024-03-05 + +The `tree-sitter` dependency version was updated to fix install problems. ### Library diff --git a/tree-sitter-stack-graphs/Cargo.toml b/tree-sitter-stack-graphs/Cargo.toml index ddce19309..40b750641 100644 --- a/tree-sitter-stack-graphs/Cargo.toml +++ b/tree-sitter-stack-graphs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tree-sitter-stack-graphs" -version = "0.7.1" +version = "0.8.0" description = "Create stack graphs using tree-sitter parsers" homepage = "https://github.com/github/stack-graphs/tree/main/tree-sitter-stack-graphs" repository = "https://github.com/github/stack-graphs/" diff --git a/tree-sitter-stack-graphs/README.md b/tree-sitter-stack-graphs/README.md index dc7b18a80..ad1287ad5 100644 --- a/tree-sitter-stack-graphs/README.md +++ b/tree-sitter-stack-graphs/README.md @@ -14,7 +14,7 @@ To use this library, add the following to your `Cargo.toml`: ```toml [dependencies] -tree-sitter-stack-graphs = "0.7" +tree-sitter-stack-graphs = "0.8" ``` Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs/*/) for more details on how to use this library. From 640ba5efeeb67c39f2bea9e3f71c663be3d90376 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 6 Mar 2024 11:30:31 +0100 Subject: [PATCH 430/500] Release stack-graphs v0.13.0 and tree-sitter-stack-graphs v0.8.1 --- .../Cargo.toml | 2 +- .../Cargo.toml | 2 +- stack-graphs/CHANGELOG.md | 26 +++++++++++++++++++ stack-graphs/Cargo.toml | 2 +- stack-graphs/README.md | 2 +- stack-graphs/src/graph.rs | 2 +- tree-sitter-stack-graphs/CHANGELOG.md | 4 +++ tree-sitter-stack-graphs/Cargo.toml | 4 +-- 8 files changed, 37 insertions(+), 7 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml index 5c9522f77..6c7006d9a 100644 --- a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -30,7 +30,7 @@ anyhow = { version = "1.0", optional = true } clap = { version = "4", optional = true } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -stack-graphs = { version = "0.12", path = "../../stack-graphs" } +stack-graphs = { version = "0.13", path = "../../stack-graphs" } tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs" } tree-sitter-javascript = { git = "https://github.com/tree-sitter/tree-sitter-javascript", rev = "5720b249490b3c17245ba772f6be4a43edb4e3b7" } diff --git a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml index fa273c2cd..be86d78cd 100644 --- a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml @@ -32,7 +32,7 @@ clap = { version = "4", optional = true } glob = "0.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -stack-graphs = { version = ">=0.11, <=0.12", path = "../../stack-graphs" } +stack-graphs = { version = "0.13", path = "../../stack-graphs" } tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs" } tree-sitter-typescript = "=0.20.2" tsconfig = "0.1.0" diff --git a/stack-graphs/CHANGELOG.md b/stack-graphs/CHANGELOG.md index c61221e8e..fa051176d 100644 --- a/stack-graphs/CHANGELOG.md +++ b/stack-graphs/CHANGELOG.md @@ -5,6 +5,32 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v0.13.0 -- 2024-03-06 + +### Added + +- New type `StitcherConfig` to specify configuration flags that control stitching. +- Path stiching statistics can now be collected during stitching for debugging purposes. Disabled by default and can be enabled with `StitcherConfig`. +- A method `StackGraph::set_edge_precedence` that allows changing the precendence of an existing edge in a stack graph. +- A method `StackGraph::incoming_edge_degree` that returns the number of edges ending in a given node. +- A method `Database::get_incoming_path_degree` that returns the number of partial paths in the database ending in a given node. +- Cycle detection improved by using incoming path or edge degrees to reduce the amount of data to keep in memory. +- Visualization uses different colors for nodes of different files, which makes understanding multi-file graphs easier. + +### Changed + +- Methods and types that do stitching in their implementation now require a `StitcherConfig` value. These include `Assertion::run`, `ForwardPartialPathStitcher::find_*`, and `Test::run`. +- The SQLite storage data encoding and queries changed to improve performance. + +### Removed + +- Method `StackGraph::remove_edge` has been removed. + +### Fixed + +- A panic when using an arena after `Arena::clear` or `SupplementalArena::clear` was called. +- Missing candidates when looking up root paths in a `Database`. + ## v0.12.0 -- 2023-07-27 ### Added diff --git a/stack-graphs/Cargo.toml b/stack-graphs/Cargo.toml index 0633d40c4..2e40b76eb 100644 --- a/stack-graphs/Cargo.toml +++ b/stack-graphs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "stack-graphs" -version = "0.12.0" +version = "0.13.0" description = "Name binding for arbitrary programming languages" homepage = "https://github.com/github/stack-graphs/tree/main/stack-graphs" repository = "https://github.com/github/stack-graphs/" diff --git a/stack-graphs/README.md b/stack-graphs/README.md index 7805d19ef..0c6a9e878 100644 --- a/stack-graphs/README.md +++ b/stack-graphs/README.md @@ -9,7 +9,7 @@ To use this library, add the following to your `Cargo.toml`: ``` toml [dependencies] -stack-graphs = "0.12" +stack-graphs = "0.13" ``` Check out our [documentation](https://docs.rs/stack-graphs/) for more details on diff --git a/stack-graphs/src/graph.rs b/stack-graphs/src/graph.rs index fe1321387..84748c6bf 100644 --- a/stack-graphs/src/graph.rs +++ b/stack-graphs/src/graph.rs @@ -1307,7 +1307,7 @@ impl StackGraph { } } - /// Removes an edge from the stack graph. + /// Sets edge precedence of the given edge. pub fn set_edge_precedence( &mut self, source: Handle, diff --git a/tree-sitter-stack-graphs/CHANGELOG.md b/tree-sitter-stack-graphs/CHANGELOG.md index 50f8b1f9b..2b907e682 100644 --- a/tree-sitter-stack-graphs/CHANGELOG.md +++ b/tree-sitter-stack-graphs/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v0.8.1 -- 2024-03-06 + +The `stack-graphs` dependency was updated to `v0.13` to fix the build problems of the `v0.8.0` release. + ## v0.8.0 -- 2024-03-05 The `tree-sitter` dependency version was updated to fix install problems. diff --git a/tree-sitter-stack-graphs/Cargo.toml b/tree-sitter-stack-graphs/Cargo.toml index 40b750641..875faf4ef 100644 --- a/tree-sitter-stack-graphs/Cargo.toml +++ b/tree-sitter-stack-graphs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tree-sitter-stack-graphs" -version = "0.8.0" +version = "0.8.1" description = "Create stack graphs using tree-sitter parsers" homepage = "https://github.com/github/stack-graphs/tree/main/tree-sitter-stack-graphs" repository = "https://github.com/github/stack-graphs/" @@ -69,7 +69,7 @@ regex = "1" rust-ini = "0.18" serde_json = { version="1.0", optional=true } sha1 = { version="0.10", optional=true } -stack-graphs = { version="0.12", path="../stack-graphs" } +stack-graphs = { version="0.13", path="../stack-graphs" } thiserror = "1.0" time = { version = "0.3", optional = true } tokio = { version = "1.26", optional = true, features = ["io-std", "rt", "rt-multi-thread"] } From 4ced0962bca76f800d653de5b2c7d8696ac4ddf9 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 6 Mar 2024 16:43:42 +0100 Subject: [PATCH 431/500] Release tree-sitter-stack-graphs-java v0.3.0 --- languages/tree-sitter-stack-graphs-java/CHANGELOG.md | 10 ++++++++-- languages/tree-sitter-stack-graphs-java/Cargo.toml | 2 +- languages/tree-sitter-stack-graphs-java/README.md | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-java/CHANGELOG.md b/languages/tree-sitter-stack-graphs-java/CHANGELOG.md index f7483cabc..0f3a4b861 100644 --- a/languages/tree-sitter-stack-graphs-java/CHANGELOG.md +++ b/languages/tree-sitter-stack-graphs-java/CHANGELOG.md @@ -5,9 +5,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## v0.3.0 -- 2024-03-06 -## [0.2.0] - 2023-03-21 +The `tree-sitter-stack-graphs` is updated to `v0.8`. + +### Changed + +- The `cli` feature is now required to install the CLI. + +## v0.2.0 -- 2023-03-21 ### Added diff --git a/languages/tree-sitter-stack-graphs-java/Cargo.toml b/languages/tree-sitter-stack-graphs-java/Cargo.toml index 8af4b3277..13e9e7340 100644 --- a/languages/tree-sitter-stack-graphs-java/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-java/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tree-sitter-stack-graphs-java" -version = "0.2.0" +version = "0.3.0" description = "Stack graphs for the Java programming language" homepage = "https://github.com/github/stack-graphs/tree/main/languages/tree-sitter-stack-graphs-java" diff --git a/languages/tree-sitter-stack-graphs-java/README.md b/languages/tree-sitter-stack-graphs-java/README.md index 40c0f847f..cf16b7dab 100644 --- a/languages/tree-sitter-stack-graphs-java/README.md +++ b/languages/tree-sitter-stack-graphs-java/README.md @@ -13,7 +13,7 @@ To use this library, add the following to your `Cargo.toml`: ```toml [dependencies] -tree-sitter-stack-graphs-java = "0.2.0" +tree-sitter-stack-graphs-java = "0.3" ``` Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-java/*/) for more details on how to use this library. From 426e14dceb2252785ceed2de666dcdab20ef393c Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 6 Mar 2024 17:00:39 +0100 Subject: [PATCH 432/500] Release tree-sitter-stack-graphs-javascript v0.1.0 --- languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md | 4 ++++ languages/tree-sitter-stack-graphs-javascript/README.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md b/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md index 3b21ea383..2ba28c310 100644 --- a/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md +++ b/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md @@ -4,3 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## v0.1.0 -- 2024-03-06 + +Initial release. diff --git a/languages/tree-sitter-stack-graphs-javascript/README.md b/languages/tree-sitter-stack-graphs-javascript/README.md index 6d449be9c..04317fbd0 100644 --- a/languages/tree-sitter-stack-graphs-javascript/README.md +++ b/languages/tree-sitter-stack-graphs-javascript/README.md @@ -13,7 +13,7 @@ To use this library, add the following to your `Cargo.toml`: ```toml [dependencies] -tree-sitter-stack-graphs-javascript = "0.1.0" +tree-sitter-stack-graphs-javascript = "0.1" ``` Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-javascript/*/) for more details on how to use this library. From 91e8a5edefb946ae7aa04ae564a39d7cd72230d5 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 6 Mar 2024 17:01:39 +0100 Subject: [PATCH 433/500] Release tree-sitter-stack-graphs-python v0.1.0 --- ...ublish-tree-sitter-stack-graphs-python.yml | 45 +++++++++++++++++++ .../CHANGELOG.md | 4 ++ .../tree-sitter-stack-graphs-python/README.md | 2 +- 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/publish-tree-sitter-stack-graphs-python.yml diff --git a/.github/workflows/publish-tree-sitter-stack-graphs-python.yml b/.github/workflows/publish-tree-sitter-stack-graphs-python.yml new file mode 100644 index 000000000..5d6c83ba2 --- /dev/null +++ b/.github/workflows/publish-tree-sitter-stack-graphs-python.yml @@ -0,0 +1,45 @@ +name: Publish tree-sitter-stack-graphs-python release + +on: + push: + tags: + - tree-sitter-stack-graphs-python-v* + +jobs: + publish-crate: + runs-on: ubuntu-latest + env: + CARGO_TERM_COLOR: always + CARGO_INCREMENTAL: 0 + CRATE_DIR: './languages/tree-sitter-stack-graphs-python' + steps: + - name: Install Rust environment + uses: hecrj/setup-rust-action@v1 + - name: Checkout repository + uses: actions/checkout@v3 + # TODO Verify the crate version matches the tag + - name: Test crate + run: cargo test --all-features + working-directory: ${{ env.CRATE_DIR }} + - name: Verify publish crate + run: cargo publish --dry-run + working-directory: ${{ env.CRATE_DIR }} + - name: Publish crate + run: cargo publish + working-directory: ${{ env.CRATE_DIR }} + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + create-release: + needs: publish-crate + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Create GitHub release + uses: ncipollo/release-action@v1 + with: + body: | + Find more info on all releases at https://crates.io/crates/tree-sitter-stack-graphs-python. + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/languages/tree-sitter-stack-graphs-python/CHANGELOG.md b/languages/tree-sitter-stack-graphs-python/CHANGELOG.md index 9e6604deb..876b16cb9 100644 --- a/languages/tree-sitter-stack-graphs-python/CHANGELOG.md +++ b/languages/tree-sitter-stack-graphs-python/CHANGELOG.md @@ -4,3 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## v0.1.0 -- 2024-03-06 + +Initial release. diff --git a/languages/tree-sitter-stack-graphs-python/README.md b/languages/tree-sitter-stack-graphs-python/README.md index b5fbc2f32..0393e0004 100644 --- a/languages/tree-sitter-stack-graphs-python/README.md +++ b/languages/tree-sitter-stack-graphs-python/README.md @@ -13,7 +13,7 @@ To use this library, add the following to your `Cargo.toml`: ```toml [dependencies] -tree-sitter-stack-graphs-python = "0.1.0" +tree-sitter-stack-graphs-python = "0.1" ``` Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-python/*/) for more details on how to use this library. From f1d2ef591786f32c496c901c8ad344901ab3055c Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 6 Mar 2024 17:03:04 +0100 Subject: [PATCH 434/500] Release tree-sitter-stack-graphs-typescript v0.2.0 --- .../CHANGELOG.md | 14 +++++++++++++- .../tree-sitter-stack-graphs-typescript/Cargo.toml | 2 +- .../tree-sitter-stack-graphs-typescript/README.md | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-typescript/CHANGELOG.md b/languages/tree-sitter-stack-graphs-typescript/CHANGELOG.md index e5b478f09..a23db2f0e 100644 --- a/languages/tree-sitter-stack-graphs-typescript/CHANGELOG.md +++ b/languages/tree-sitter-stack-graphs-typescript/CHANGELOG.md @@ -5,7 +5,19 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## v0.2.0 -- 2024-03-06 + +The `tree-sitter-stack-graphs` is updated to `v0.8`. + +### Added + +- An experimental VSCode LSP plugin that supports code navigation based on the stack graph rules. _Purely an experiment, not ready for serious use!_ Requires the `lsp` feature to be enabled. + +### Changed + +- Various improvements to the rules for imports and packages. + +## v0.1.0 -- 2023-01-27 ### Added diff --git a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml index be86d78cd..822eeb498 100644 --- a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tree-sitter-stack-graphs-typescript" -version = "0.1.0" +version = "0.2.0" description = "Stack graphs definition for TypeScript using tree-sitter-typescript" readme = "README.md" keywords = ["tree-sitter", "stack-graphs", "typescript"] diff --git a/languages/tree-sitter-stack-graphs-typescript/README.md b/languages/tree-sitter-stack-graphs-typescript/README.md index fada7e2df..9b6c82069 100644 --- a/languages/tree-sitter-stack-graphs-typescript/README.md +++ b/languages/tree-sitter-stack-graphs-typescript/README.md @@ -13,7 +13,7 @@ To use this library, add the following to your `Cargo.toml`: ```toml [dependencies] -tree-sitter-stack-graphs-typescript = "0.1.0" +tree-sitter-stack-graphs-typescript = "0.2" ``` Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-typescript/*/) for more details on how to use this library. From 1547ea202ba54ab3703c8334182b3c1f06fc9965 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 8 Mar 2024 16:57:46 +0100 Subject: [PATCH 435/500] Update tree-sitter-javascript to 0.20.1 --- .../Cargo.toml | 3 +- .../src/stack-graphs.tsg | 155 +++++++----------- 2 files changed, 57 insertions(+), 101 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml index 6c7006d9a..fe8863bba 100644 --- a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -31,8 +31,9 @@ clap = { version = "4", optional = true } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" stack-graphs = { version = "0.13", path = "../../stack-graphs" } +tree-sitter-graph = "0.11.2" +tree-sitter-javascript = "=0.20.1" tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs" } -tree-sitter-javascript = { git = "https://github.com/tree-sitter/tree-sitter-javascript", rev = "5720b249490b3c17245ba772f6be4a43edb4e3b7" } [dev-dependencies] anyhow = "1.0" diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index e69a4636a..f9e724011 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -1564,7 +1564,7 @@ inherit .containing_class_value node @method_def.after_scope node @method_def.before_scope node @method_def.method_value - + } ( @@ -1572,7 +1572,7 @@ inherit .containing_class_value name:(_)@name)@method_def (#eq? @name "constructor") ) { - + ; augmentation for the constructor attr (@name.pop) symbol_definition = "GUARD:CONSTRUCTOR", source_node = @name edge @method_def.class_value -> @name.pop @@ -1672,7 +1672,7 @@ inherit .containing_class_value node @property.pop node property_pop_dot - + attr (@property.pop) node_definition = @property attr (property_pop_dot) pop_symbol = "GUARD:MEMBER" edge @field_def.after_scope -> property_pop_dot @@ -2321,7 +2321,7 @@ inherit .containing_class_value (yield_expression) (spread_element) ]@expr { - + node @expr.after_scope node @expr.before_scope node @expr.value @@ -2418,7 +2418,10 @@ inherit .containing_class_value ;; #### Variables -(primary_expression/identifier)@variable { +[ + (primary_expression/identifier)@variable + (member_expression . (identifier)@variable) +] { ; value is a lookup, ie a push attr (@variable.value) node_reference = @variable edge @variable.value -> @variable.before_scope @@ -2565,7 +2568,7 @@ inherit .containing_class_value ; shorthand property identifier (shorthand_property_identifier)@shorthand_property_identifier { - + node @shorthand_property_identifier.after_scope node @shorthand_property_identifier.before_scope @@ -2616,7 +2619,7 @@ inherit .containing_class_value ; This is done differently depending on what the key is. See next rules. ; attr @key.pop "pop" = @key, "definition" - + node @pair.key_pop edge @pair.key_pop -> @value.value edge @object.member_pop -> @pair.key_pop @@ -3171,8 +3174,7 @@ inherit .containing_class_value ;; ##### Member Expressions (member_expression - object: (_)@object - property: (_)@property)@member_expr + (_)@object . (_)@property)@member_expr { node member_push @@ -3555,7 +3557,7 @@ inherit .containing_class_value (class name:(_)@name body:(_)@body)@class { - + node @name.pop attr (@name.pop) syntax_type = "class" @@ -3604,7 +3606,6 @@ inherit .containing_class_value (jsx_text) (jsx_element) (jsx_self_closing_element) - (jsx_fragment) (jsx_expression) ]@first_child ) { @@ -3616,7 +3617,6 @@ inherit .containing_class_value (jsx_text) (jsx_element) (jsx_self_closing_element) - (jsx_fragment) (jsx_expression) ]@left_child . @@ -3624,7 +3624,6 @@ inherit .containing_class_value (jsx_text) (jsx_element) (jsx_self_closing_element) - (jsx_fragment) (jsx_expression) ]@right_child ) { @@ -3636,7 +3635,6 @@ inherit .containing_class_value (jsx_text) (jsx_element) (jsx_self_closing_element) - (jsx_fragment) (jsx_expression) ]@last_child . @@ -3648,25 +3646,37 @@ inherit .containing_class_value (jsx_text)@jsx_text { node @jsx_text.before_scope node @jsx_text.after_scope - + edge @jsx_text.after_scope -> @jsx_text.before_scope } -(jsx_opening_element - name:(_)@element_name)@jsx_opening_element { +(jsx_opening_element)@jsx_opening_element { node @jsx_opening_element.before_scope node @jsx_opening_element.after_scope +} + +(jsx_opening_element + name:(_)@element_name)@jsx_opening_element { + edge @element_name.before_scope -> @jsx_opening_element.before_scope } +(jsx_opening_element + !name)@jsx_opening_element +{ + + edge @jsx_opening_element.after_scope -> @jsx_opening_element.before_scope + +} + (jsx_opening_element name:(_)@element_name !attribute)@jsx_opening_element { - + edge @jsx_opening_element.after_scope -> @element_name.after_scope } @@ -3734,11 +3744,20 @@ inherit .containing_class_value } +(jsx_self_closing_element + !name + !attribute)@jsx_self_closing_element +{ + + edge @jsx_self_closing_element.after_scope -> @jsx_self_closing_element.before_scope + +} + (jsx_self_closing_element name:(_)@element_name !attribute)@jsx_self_closing_element { - + edge @jsx_self_closing_element.after_scope -> @element_name.after_scope } @@ -3790,13 +3809,26 @@ inherit .containing_class_value } -(jsx_closing_element - name:(_)@element_name)@jsx_closing_element +(jsx_closing_element)@jsx_closing_element { node @jsx_closing_element.before_scope node @jsx_closing_element.after_scope - + +} + +(jsx_closing_element + !name)@jsx_closing_element +{ + + edge @jsx_closing_element.after_scope -> @jsx_closing_element.before_scope + +} + +(jsx_closing_element + name:(_)@element_name)@jsx_closing_element +{ + edge @element_name.before_scope -> @jsx_closing_element.before_scope edge @jsx_closing_element.after_scope -> @element_name.after_scope @@ -3827,83 +3859,6 @@ inherit .containing_class_value } -(nested_identifier)@nested_identifier { - node @nested_identifier.before_scope - node @nested_identifier.after_scope - node @nested_identifier.value - - edge @nested_identifier.after_scope -> @nested_identifier.before_scope -} - -(nested_identifier - (identifier)@first_part - (identifier)@second_part)@nested_identifier -{ - node guard_member - - attr (@first_part.value) node_reference = @first_part - attr (@second_part.value) node_reference = @second_part - attr (guard_member) symbol_reference = "GUARD:MEMBER" - - edge @first_part.value -> @nested_identifier.before_scope - edge guard_member -> @first_part.value - edge @second_part.value -> guard_member - edge @nested_identifier.value -> @second_part.value -} - -(nested_identifier - (nested_identifier)@first_part - (identifier)@second_part)@nested_identifier -{ - node guard_member - - attr (@second_part.value) node_reference = @second_part - attr (guard_member) symbol_reference = "GUARD:MEMBER" - - edge @first_part.before_scope -> @nested_identifier.before_scope - edge guard_member -> @first_part.value - edge @second_part.value -> guard_member - edge @nested_identifier.value -> @second_part.value -} - -(jsx_fragment (_)*@children)@jsx_fragment { - node @jsx_fragment.before_scope - node @jsx_fragment.after_scope - node @jsx_fragment.value - - if (is-empty @children) { - edge @jsx_fragment.after_scope -> @jsx_fragment.before_scope - } -} - -(jsx_fragment - . - (_)@first_child)@jsx_fragment -{ - edge @first_child.before_scope -> @jsx_fragment.before_scope -} - -(jsx_fragment - (_)@left_child - . - (_)@right_child) -{ - edge @right_child.before_scope -> @left_child.after_scope -} - -(jsx_fragment - (_)@last_child - .)@jsx_fragment -{ - edge @jsx_fragment.after_scope -> @last_child.after_scope -} - - - - - - - @@ -4785,7 +4740,7 @@ inherit .containing_class_value name:(_)@_method_name)@constructor ) ) - + (#eq? @_method_name "constructor") ) { From b785a8e70e72312387796e8b45b1df92516ebff1 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 8 Mar 2024 17:26:46 +0100 Subject: [PATCH 436/500] Update tree-sitter-javascript to 0.20.2 --- .../Cargo.toml | 2 +- .../src/stack-graphs.tsg | 86 ++++++++++++------- 2 files changed, 55 insertions(+), 33 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml index fe8863bba..72f9069f8 100644 --- a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -32,7 +32,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" stack-graphs = { version = "0.13", path = "../../stack-graphs" } tree-sitter-graph = "0.11.2" -tree-sitter-javascript = "=0.20.1" +tree-sitter-javascript = "=0.20.2" tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs" } [dev-dependencies] diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index f9e724011..a9167c3a1 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -2296,6 +2296,9 @@ inherit .containing_class_value (number) (string) (template_string) + (template_substitution) + (string_fragment) + (escape_sequence) (regex) (true) (false) @@ -2304,7 +2307,7 @@ inherit .containing_class_value (import) (object) (array) - (function) + (function_expression) (arrow_function) (generator_function) (class) @@ -2329,7 +2332,7 @@ inherit .containing_class_value } [ - (function body:(_)@body) + (function_expression body:(_)@body) (arrow_function body:(_)@body) (generator_function body:(_)@body) ] { @@ -2367,8 +2370,8 @@ inherit .containing_class_value ;; #### Template Strings ; template_strings w/ no substitutions -(template_string (_)* @substs)@template_string { - if (is-empty @substs) { +(template_string (_)* @parts)@template_string { + if (is-empty @parts) { edge @template_string.after_scope -> @template_string.before_scope } } @@ -2376,33 +2379,45 @@ inherit .containing_class_value ; nonempty template string, value ; LATER-TODO this isn't really right, but it gets flows through the template string ; which may be useful -(template_string (template_substitution (_)@inner_expr))@template_string { +(template_string (_)@part)@template_string { ; the value of a template string is a template string value built from the values of its substitutions ; attr (@template_string.value) "template_string_value" - edge @template_string.value -> @inner_expr.value + edge @template_string.value -> @part.value } ; nonempty template string, first substitution -(template_string . (template_substitution (_)@first_inner_expr))@template_string { +(template_string . (_)@first)@template_string { ; scopes propagate into the first subtitution of the template string - edge @first_inner_expr.before_scope -> @template_string.before_scope + edge @first.before_scope -> @template_string.before_scope } ; nonempty template string, between substitutions (template_string - (template_substitution (_)@left_inner_expr) + (_) @left . - (template_substitution (_)@right_inner_expr))@_template_string { + (_) @right) { ; scopes propagate from left substitutions to right substitutions - edge @right_inner_expr.before_scope -> @left_inner_expr.after_scope + edge @right.before_scope -> @left.after_scope } ; nonempty template string, last substitution -(template_string . (template_substitution (_)@last_inner_expr))@template_string { +(template_string (_) @last .)@template_string { ; scopes propagate out of the last substitution to the template string - edge @template_string.after_scope -> @last_inner_expr.after_scope + edge @template_string.after_scope -> @last.after_scope +} + +[ + (string_fragment) + (escape_sequence) +]@part { + edge @part.after_scope -> @part.before_scope } +(template_substitution (_)@expr)@subst { + edge @expr.before_scope -> @subst.before_scope + edge @subst.after_scope -> @expr.after_scope + edge @subst.value -> @expr.value +} ;; #### Numbers @@ -2785,7 +2800,7 @@ inherit .containing_class_value ;; #### Function Literals ; functions with names -(function +(function_expression name:(_)@name parameters:(_)@call_sig)@fun { @@ -2800,7 +2815,7 @@ inherit .containing_class_value ; function -(function +(function_expression parameters:(_)@call_sig body:(_)@body)@fun { @@ -2859,7 +2874,7 @@ inherit .containing_class_value edge @fun.value_arg_scope -> JUMP_TO_SCOPE_NODE } -(function +(function_expression parameters: (formal_parameters (_)@param))@fun { @@ -3485,20 +3500,27 @@ inherit .containing_class_value ;; #### Comma Operator / Sequence Expressions -(sequence_expression - left: (_)@left - right: (_)@right)@sequence_expr { +(sequence_expression (_)* @elems)@sequence_expr { + if (is-empty @elems) { + edge @sequence_expr.after_scope -> @sequence_expr.before_scope + } +} + +(sequence_expression . (_)@first)@sequence_expr { + edge @first.before_scope -> @sequence_expr.before_scope +} - ; scopes propagate left to right - edge @left.before_scope -> @sequence_expr.before_scope +(sequence_expression (_)@left . (_)@right) { edge @right.before_scope -> @left.after_scope - edge @sequence_expr.after_scope -> @right.after_scope +} - ; the value is just the value of the right - edge @sequence_expr.value -> @right.value +(sequence_expression (_)@last .)@sequence_expr { + edge @sequence_expr.after_scope -> @last.after_scope + edge @sequence_expr.value -> @last.value } + ;; #### Ternary Expression (ternary_expression @@ -4716,7 +4738,7 @@ inherit .containing_class_value } -(function +(function_expression name:(_)@name parameters:(_)@_call_sig)@fun { @@ -4830,7 +4852,7 @@ inherit .containing_class_value (variable_declarator name:(identifier)@name value: [ - (function) + (function_expression) (generator_function) (arrow_function) ])) @@ -4838,7 +4860,7 @@ inherit .containing_class_value (variable_declarator name:(identifier)@name value: [ - (function) + (function_expression) (generator_function) (arrow_function) ])) @@ -4848,7 +4870,7 @@ inherit .containing_class_value ; (member_expression property:(_)@name) ; FIXME member expressions are references and have no .pop ] right: [ - (function) + (function_expression) (generator_function) (arrow_function) ]) @@ -4878,7 +4900,7 @@ inherit .containing_class_value ) ] right: [ - (function) + (function_expression) (generator_function) (arrow_function) ])@assignment_expr @@ -4897,7 +4919,7 @@ inherit .containing_class_value object:(_)@_module property:(_)@_exports) right: [ - (function) + (function_expression) (generator_function) (arrow_function) ])@assignment_expr @@ -4913,7 +4935,7 @@ inherit .containing_class_value (export_statement "default" value:[ - (function) + (function_expression) (generator_function) (arrow_function) ])@export_stmt { @@ -4927,7 +4949,7 @@ inherit .containing_class_value (pair key: (_)@name value: [ - (function) + (function_expression) (generator_function) (arrow_function) ]) { From b5cb3eb2603c06b54a1f2ba1449bb176f1e82f5a Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 8 Mar 2024 17:27:22 +0100 Subject: [PATCH 437/500] Update tree-sitter-javascript to 0.20.3 --- languages/tree-sitter-stack-graphs-javascript/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml index 72f9069f8..b56925c75 100644 --- a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -32,7 +32,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" stack-graphs = { version = "0.13", path = "../../stack-graphs" } tree-sitter-graph = "0.11.2" -tree-sitter-javascript = "=0.20.2" +tree-sitter-javascript = "=0.20.3" tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs" } [dev-dependencies] From 88bc1700ad54d09bf30f4c3aa1e7eb2b399c7f75 Mon Sep 17 00:00:00 2001 From: Eugene Yakubovich Date: Wed, 28 Feb 2024 17:18:26 -0800 Subject: [PATCH 438/500] Support for TSX Support TSX dialect of the TypeScript. Because the TSX is almost a superset of TypeScript, it makes sense to reuse the .tsg file. However it requires a bit of preprocessing to handle the differences. --- .../Cargo.toml | 2 + .../askama.toml | 9 +++ .../rust/lib.rs | 56 ++++++++++++++++++- .../src/stack-graphs.tsg | 6 +- tree-sitter-stack-graphs/src/loader.rs | 6 ++ 5 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-typescript/askama.toml diff --git a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml index 822eeb498..35bd6e3ae 100644 --- a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml @@ -28,8 +28,10 @@ lsp = ["tree-sitter-stack-graphs/lsp"] [dependencies] anyhow = { version = "1.0", optional = true } +askama = "0.12.1" clap = { version = "4", optional = true } glob = "0.3" +lazy_static = "1.4.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" stack-graphs = { version = "0.13", path = "../../stack-graphs" } diff --git a/languages/tree-sitter-stack-graphs-typescript/askama.toml b/languages/tree-sitter-stack-graphs-typescript/askama.toml new file mode 100644 index 000000000..124fdbde6 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/askama.toml @@ -0,0 +1,9 @@ +[general] +# Directories to search for templates, relative to the crate root. +dirs = ["src"] +# Unless you add a `-` in a block, whitespace characters won't be trimmed. +whitespace = "preserve" + +[[escaper]] +path = "::askama::Text" +extensions = ["tsg"] diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs index 3590649b2..43bc1efb6 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs @@ -5,6 +5,11 @@ // Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. // ------------------------------------------------------------------------------------------------ +use std::path::PathBuf; +use std::borrow::Cow; + +use askama::Template; +use lazy_static::lazy_static; use tree_sitter_stack_graphs::loader::LanguageConfiguration; use tree_sitter_stack_graphs::loader::LoadError; use tree_sitter_stack_graphs::CancellationFlag; @@ -33,10 +38,25 @@ pub const FILE_PATH_VAR: &str = "FILE_PATH"; /// The name of the project name global variable pub const PROJECT_NAME_VAR: &str = "PROJECT_NAME"; +lazy_static! { + static ref STACK_GRAPHS_TS_TSG_SOURCE: String = preprocess_tsg("typescript").unwrap(); + static ref STACK_GRAPHS_TSX_TSG_SOURCE: String = preprocess_tsg("tsx").unwrap(); +} + +#[derive(Template)] +#[template(path = "stack-graphs.tsg")] +struct TsgTemplate<'a> { + dialect: &'a str, +} + pub fn language_configuration(cancellation_flag: &dyn CancellationFlag) -> LanguageConfiguration { try_language_configuration(cancellation_flag).unwrap_or_else(|err| panic!("{}", err)) } +pub fn tsx_language_configuration(cancellation_flag: &dyn CancellationFlag) -> LanguageConfiguration { + try_tsx_language_configuration(cancellation_flag).unwrap_or_else(|err| panic!("{}", err)) +} + pub fn try_language_configuration( cancellation_flag: &dyn CancellationFlag, ) -> Result { @@ -46,7 +66,31 @@ pub fn try_language_configuration( None, vec![String::from("ts")], STACK_GRAPHS_TSG_PATH.into(), - STACK_GRAPHS_TSG_SOURCE, + &STACK_GRAPHS_TS_TSG_SOURCE, + Some(( + STACK_GRAPHS_BUILTINS_PATH.into(), + STACK_GRAPHS_BUILTINS_SOURCE, + )), + Some(STACK_GRAPHS_BUILTINS_CONFIG), + cancellation_flag, + )?; + lc.special_files + .add("tsconfig.json".to_string(), TsConfigAnalyzer {}) + .add("package.json".to_string(), NpmPackageAnalyzer {}); + lc.no_similar_paths_in_file = true; + Ok(lc) +} + +pub fn try_tsx_language_configuration( + cancellation_flag: &dyn CancellationFlag, +) -> Result { + let mut lc = LanguageConfiguration::from_sources( + tree_sitter_typescript::language_tsx(), + Some(String::from("source.tsx")), + None, + vec![String::from("tsx")], + STACK_GRAPHS_TSG_PATH.into(), + &STACK_GRAPHS_TSX_TSG_SOURCE, Some(( STACK_GRAPHS_BUILTINS_PATH.into(), STACK_GRAPHS_BUILTINS_SOURCE, @@ -60,3 +104,13 @@ pub fn try_language_configuration( lc.no_similar_paths_in_file = true; Ok(lc) } + +fn preprocess_tsg(dialect: &'static str) -> Result> { + let tmpl = TsgTemplate{ dialect }; + tmpl.render() + .map_err(|err| LoadError::PreprocessorError { + inner: err.to_string(), + tsg_path: PathBuf::from(STACK_GRAPHS_TSG_PATH), + tsg: Cow::from(STACK_GRAPHS_TSG_SOURCE), + }) +} diff --git a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg index 66c432b46..1fc595b9a 100644 --- a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg @@ -2665,7 +2665,9 @@ if none @is_async { (ternary_expression) (this) (true) +{% if dialect == "typescript" -%} (type_assertion) +{% endif -%} (unary_expression) (undefined) (update_expression) @@ -4040,7 +4042,7 @@ if none @is_async { } - +{% if dialect == "typescript" -%} ;; Type Assertion ; (type_assertion @@ -4055,7 +4057,7 @@ if none @is_async { ; propagate lexical scope edge @expr.lexical_scope -> @type_assert.lexical_scope } - +{% endif -%} ;; As Expression diff --git a/tree-sitter-stack-graphs/src/loader.rs b/tree-sitter-stack-graphs/src/loader.rs index 9ffc1d674..88be0acf1 100644 --- a/tree-sitter-stack-graphs/src/loader.rs +++ b/tree-sitter-stack-graphs/src/loader.rs @@ -423,6 +423,12 @@ pub enum LoadError<'a> { }, #[error(transparent)] TreeSitter(anyhow::Error), + #[error("Preprocessor error: {inner}")] + PreprocessorError { + inner: String, + tsg_path: PathBuf, + tsg: Cow<'a, str>, + } } impl LoadError<'_> { From cd323fdfb8dcf30578a61aced42c2721c322174e Mon Sep 17 00:00:00 2001 From: Eugene Yakubovich Date: Sat, 9 Mar 2024 20:31:05 -0800 Subject: [PATCH 439/500] Support for TSX Preprocesses the .tsg file into typescript and tsx specific .tsg files. The preprocessing is done in the build script. Add a --dialect|-d option to the CLI to select the dialect. --- .../Cargo.toml | 6 +- .../askama.toml | 9 -- .../build.rs | 98 +++++++++++++++++++ .../rust/bin.rs | 21 +++- .../rust/lib.rs | 50 +++------- .../src/stack-graphs.tsg | 8 +- tree-sitter-stack-graphs/src/loader.rs | 6 -- 7 files changed, 137 insertions(+), 61 deletions(-) delete mode 100644 languages/tree-sitter-stack-graphs-typescript/askama.toml create mode 100644 languages/tree-sitter-stack-graphs-typescript/build.rs diff --git a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml index 35bd6e3ae..46360f19c 100644 --- a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml @@ -28,10 +28,8 @@ lsp = ["tree-sitter-stack-graphs/lsp"] [dependencies] anyhow = { version = "1.0", optional = true } -askama = "0.12.1" clap = { version = "4", optional = true } glob = "0.3" -lazy_static = "1.4.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" stack-graphs = { version = "0.13", path = "../../stack-graphs" } @@ -42,3 +40,7 @@ tsconfig = "0.1.0" [dev-dependencies] anyhow = { version = "1.0" } tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs", features = ["cli"] } + +[build-dependencies] +anyhow = { version = "1.0" } +regex = "1.10.3" diff --git a/languages/tree-sitter-stack-graphs-typescript/askama.toml b/languages/tree-sitter-stack-graphs-typescript/askama.toml deleted file mode 100644 index 124fdbde6..000000000 --- a/languages/tree-sitter-stack-graphs-typescript/askama.toml +++ /dev/null @@ -1,9 +0,0 @@ -[general] -# Directories to search for templates, relative to the crate root. -dirs = ["src"] -# Unless you add a `-` in a block, whitespace characters won't be trimmed. -whitespace = "preserve" - -[[escaper]] -path = "::askama::Text" -extensions = ["tsg"] diff --git a/languages/tree-sitter-stack-graphs-typescript/build.rs b/languages/tree-sitter-stack-graphs-typescript/build.rs new file mode 100644 index 000000000..3d5867cfa --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/build.rs @@ -0,0 +1,98 @@ +// -*- coding: utf-8 -*- +// ------------------------------------------------------------------------------------------------ +// Copyright © 2024, stack-graphs authors. +// Licensed under either of Apache License, Version 2.0, or MIT license, at your option. +// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. +// ------------------------------------------------------------------------------------------------ + +use std::collections::HashSet; +use std::path::Path; + +use anyhow::{Result, anyhow, bail}; +use regex::Regex; + +/// A stack of dialects as selected by the directives +#[derive(Debug, Default)] +struct DialectStack(Vec>); + +impl DialectStack { + fn push(&mut self, values: Vec) -> Result<()> { + // ensure that the new values are a subset of the current scope + if let Some(current) = self.0.last() { + if !values.iter().all(|v| current.contains(v)) { + bail!("Directive values are not a subset of the current scope"); + } + } + + self.0.push(values.into_iter().collect()); + + Ok(()) + } + + fn pop(&mut self) -> Result<()> { + if let Some(_) = self.0.pop() { + Ok(()) + } else { + Err(anyhow!("Directive stack is empty")) + } + } + + fn contains(&self, query: &str) -> bool { + if let Some(current) = self.0.last() { + current.contains(query) + } else { + true + } + } +} + +/// preprocess the input file, removing lines that are not for the selected dialect +fn preprocess(input: impl std::io::Read, mut output: impl std::io::Write, dialect: &str) -> anyhow::Result<()> { + // Matches: ; # dialect typescript tsx + let directive_start = Regex::new(r";[ \t]*#[ \t]*dialect[ \t]+([a-zA-Z\t ]+)").unwrap(); + + // Matches: ; # end + let directirve_end = Regex::new(r";[ \t]*#[ \t]*end").unwrap(); + + let input = std::io::read_to_string(input)?; + + let mut stack = DialectStack::default(); + + for line in input.lines() { + if let Some(captures) = directive_start.captures(line) { + let directive = captures.get(1).unwrap().as_str(); + let dialects = directive.split_whitespace().map(|s| s.to_string()).collect(); + stack.push(dialects)?; + output.write_all(line.as_bytes())?; + } else if directirve_end.is_match(line) { + stack.pop()?; + output.write_all(line.as_bytes())?; + } else { + if stack.contains(dialect) { + output.write_all(line.as_bytes())?; + } + } + // a new line is always written so that removed lines are padded to preserve line numbers + output.write(b"\n")?; + } + + Ok(()) +} + +const TSG_SOURCE: &str = "src/stack-graphs.tsg"; +const DIALECTS: [&str; 2] = ["typescript", "tsx"]; + +fn main() { + let out_dir = std::env::var_os("OUT_DIR").unwrap(); + for dialect in DIALECTS { + let input = std::fs::File::open(TSG_SOURCE).unwrap(); + + let out_filename = Path::new(&out_dir).join(format!("stack-graphs-{dialect}.tsg")); + let output = std::fs::File::create(out_filename).unwrap(); + + preprocess(input, output, dialect).unwrap(); + } + + println!("cargo:rerun-if-changed={TSG_SOURCE}"); + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/bin.rs b/languages/tree-sitter-stack-graphs-typescript/rust/bin.rs index b1ee4f568..7352111dd 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/bin.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/bin.rs @@ -12,22 +12,37 @@ use tree_sitter_stack_graphs::cli::provided_languages::Subcommands; use tree_sitter_stack_graphs::NoCancellation; fn main() -> anyhow::Result<()> { - let lc = match tree_sitter_stack_graphs_typescript::try_language_configuration(&NoCancellation) + let cli = Cli::parse(); + let lc = match language_configuration(&cli.dialect) { Ok(lc) => lc, Err(err) => { - eprintln!("{}", err.display_pretty()); + eprintln!("{err}"); return Err(anyhow!("Language configuration error")); } }; - let cli = Cli::parse(); let default_db_path = default_user_database_path_for_crate(env!("CARGO_PKG_NAME"))?; cli.subcommand.run(default_db_path, vec![lc]) } +fn language_configuration(dialect: &str) -> anyhow::Result { + match dialect { + "typescript" => tree_sitter_stack_graphs_typescript::try_language_configuration(&NoCancellation) + .map_err(|e| anyhow::anyhow!("{}", e.display_pretty())), + + "tsx" => tree_sitter_stack_graphs_typescript::try_language_configuration_tsx(&NoCancellation) + .map_err(|e| anyhow::anyhow!("{}", e.display_pretty())), + + _ => anyhow::bail!("Unknown dialect: {}", dialect) + } +} + #[derive(Parser)] #[clap(about, version)] pub struct Cli { + #[clap(short, long, default_value = "typescript")] + dialect: String, + #[clap(subcommand)] subcommand: Subcommands, } diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs index 43bc1efb6..b87a038d4 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs @@ -5,11 +5,6 @@ // Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. // ------------------------------------------------------------------------------------------------ -use std::path::PathBuf; -use std::borrow::Cow; - -use askama::Template; -use lazy_static::lazy_static; use tree_sitter_stack_graphs::loader::LanguageConfiguration; use tree_sitter_stack_graphs::loader::LoadError; use tree_sitter_stack_graphs::CancellationFlag; @@ -22,9 +17,11 @@ pub mod tsconfig; pub mod util; /// The stacks graphs tsg path for this language. -pub const STACK_GRAPHS_TSG_PATH: &str = "src/stack-graphs.tsg"; +pub const STACK_GRAPHS_TSG_TS_PATH: &str = concat!(env!("OUT_DIR"), "/stack-graphs-typescript.tsg"); +pub const STACK_GRAPHS_TSG_TSX_PATH: &str = concat!(env!("OUT_DIR"), "/stack-graphs-tsx.tsg"); /// The stack graphs tsg source for this language -pub const STACK_GRAPHS_TSG_SOURCE: &str = include_str!("../src/stack-graphs.tsg"); +pub const STACK_GRAPHS_TSG_TS_SOURCE: &str = include_str!(concat!(env!("OUT_DIR"), "/stack-graphs-typescript.tsg")); +pub const STACK_GRAPHS_TSG_TSX_SOURCE: &str = include_str!(concat!(env!("OUT_DIR"), "/stack-graphs-tsx.tsg")); /// The stack graphs builtins configuration for this language pub const STACK_GRAPHS_BUILTINS_CONFIG: &str = include_str!("../src/builtins.cfg"); @@ -38,25 +35,10 @@ pub const FILE_PATH_VAR: &str = "FILE_PATH"; /// The name of the project name global variable pub const PROJECT_NAME_VAR: &str = "PROJECT_NAME"; -lazy_static! { - static ref STACK_GRAPHS_TS_TSG_SOURCE: String = preprocess_tsg("typescript").unwrap(); - static ref STACK_GRAPHS_TSX_TSG_SOURCE: String = preprocess_tsg("tsx").unwrap(); -} - -#[derive(Template)] -#[template(path = "stack-graphs.tsg")] -struct TsgTemplate<'a> { - dialect: &'a str, -} - pub fn language_configuration(cancellation_flag: &dyn CancellationFlag) -> LanguageConfiguration { try_language_configuration(cancellation_flag).unwrap_or_else(|err| panic!("{}", err)) } -pub fn tsx_language_configuration(cancellation_flag: &dyn CancellationFlag) -> LanguageConfiguration { - try_tsx_language_configuration(cancellation_flag).unwrap_or_else(|err| panic!("{}", err)) -} - pub fn try_language_configuration( cancellation_flag: &dyn CancellationFlag, ) -> Result { @@ -65,8 +47,8 @@ pub fn try_language_configuration( Some(String::from("source.ts")), None, vec![String::from("ts")], - STACK_GRAPHS_TSG_PATH.into(), - &STACK_GRAPHS_TS_TSG_SOURCE, + STACK_GRAPHS_TSG_TS_PATH.into(), + STACK_GRAPHS_TSG_TS_SOURCE, Some(( STACK_GRAPHS_BUILTINS_PATH.into(), STACK_GRAPHS_BUILTINS_SOURCE, @@ -81,7 +63,11 @@ pub fn try_language_configuration( Ok(lc) } -pub fn try_tsx_language_configuration( +pub fn language_configuration_tsx(cancellation_flag: &dyn CancellationFlag) -> LanguageConfiguration { + try_language_configuration_tsx(cancellation_flag).unwrap_or_else(|err| panic!("{}", err)) +} + +pub fn try_language_configuration_tsx( cancellation_flag: &dyn CancellationFlag, ) -> Result { let mut lc = LanguageConfiguration::from_sources( @@ -89,8 +75,8 @@ pub fn try_tsx_language_configuration( Some(String::from("source.tsx")), None, vec![String::from("tsx")], - STACK_GRAPHS_TSG_PATH.into(), - &STACK_GRAPHS_TSX_TSG_SOURCE, + STACK_GRAPHS_TSG_TSX_PATH.into(), + STACK_GRAPHS_TSG_TSX_SOURCE, Some(( STACK_GRAPHS_BUILTINS_PATH.into(), STACK_GRAPHS_BUILTINS_SOURCE, @@ -104,13 +90,3 @@ pub fn try_tsx_language_configuration( lc.no_similar_paths_in_file = true; Ok(lc) } - -fn preprocess_tsg(dialect: &'static str) -> Result> { - let tmpl = TsgTemplate{ dialect }; - tmpl.render() - .map_err(|err| LoadError::PreprocessorError { - inner: err.to_string(), - tsg_path: PathBuf::from(STACK_GRAPHS_TSG_PATH), - tsg: Cow::from(STACK_GRAPHS_TSG_SOURCE), - }) -} diff --git a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg index 1fc595b9a..63c56760f 100644 --- a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg @@ -2665,9 +2665,9 @@ if none @is_async { (ternary_expression) (this) (true) -{% if dialect == "typescript" -%} +; #dialect typescript (type_assertion) -{% endif -%} +; #end (unary_expression) (undefined) (update_expression) @@ -4042,7 +4042,7 @@ if none @is_async { } -{% if dialect == "typescript" -%} +; #dialect typescript ;; Type Assertion ; (type_assertion @@ -4057,7 +4057,7 @@ if none @is_async { ; propagate lexical scope edge @expr.lexical_scope -> @type_assert.lexical_scope } -{% endif -%} +; #end ;; As Expression diff --git a/tree-sitter-stack-graphs/src/loader.rs b/tree-sitter-stack-graphs/src/loader.rs index 88be0acf1..9ffc1d674 100644 --- a/tree-sitter-stack-graphs/src/loader.rs +++ b/tree-sitter-stack-graphs/src/loader.rs @@ -423,12 +423,6 @@ pub enum LoadError<'a> { }, #[error(transparent)] TreeSitter(anyhow::Error), - #[error("Preprocessor error: {inner}")] - PreprocessorError { - inner: String, - tsg_path: PathBuf, - tsg: Cow<'a, str>, - } } impl LoadError<'_> { From 921975535e55f4d5f5451a05df14367a06e78898 Mon Sep 17 00:00:00 2001 From: Eugene Yakubovich Date: Mon, 11 Mar 2024 11:20:02 -0700 Subject: [PATCH 440/500] Address feedback - Remove dialect stack - Better error handling - Use clap::ValueEnum - Append _typescript to {try}_language_configuration --- .../build.rs | 89 +++++++------------ .../rust/bin.rs | 34 ++++--- .../rust/lib.rs | 13 ++- .../rust/test.rs | 2 +- 4 files changed, 60 insertions(+), 78 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-typescript/build.rs b/languages/tree-sitter-stack-graphs-typescript/build.rs index 3d5867cfa..4527a7e8e 100644 --- a/languages/tree-sitter-stack-graphs-typescript/build.rs +++ b/languages/tree-sitter-stack-graphs-typescript/build.rs @@ -5,72 +5,45 @@ // Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. // ------------------------------------------------------------------------------------------------ -use std::collections::HashSet; use std::path::Path; -use anyhow::{Result, anyhow, bail}; +use anyhow::{Result, bail}; use regex::Regex; -/// A stack of dialects as selected by the directives -#[derive(Debug, Default)] -struct DialectStack(Vec>); - -impl DialectStack { - fn push(&mut self, values: Vec) -> Result<()> { - // ensure that the new values are a subset of the current scope - if let Some(current) = self.0.last() { - if !values.iter().all(|v| current.contains(v)) { - bail!("Directive values are not a subset of the current scope"); - } - } - - self.0.push(values.into_iter().collect()); - - Ok(()) - } - - fn pop(&mut self) -> Result<()> { - if let Some(_) = self.0.pop() { - Ok(()) - } else { - Err(anyhow!("Directive stack is empty")) - } - } - - fn contains(&self, query: &str) -> bool { - if let Some(current) = self.0.last() { - current.contains(query) - } else { - true - } - } -} +const TSG_SOURCE: &str = "src/stack-graphs.tsg"; +const DIALECTS: [&str; 2] = ["typescript", "tsx"]; /// preprocess the input file, removing lines that are not for the selected dialect -fn preprocess(input: impl std::io::Read, mut output: impl std::io::Write, dialect: &str) -> anyhow::Result<()> { - // Matches: ; # dialect typescript tsx - let directive_start = Regex::new(r";[ \t]*#[ \t]*dialect[ \t]+([a-zA-Z\t ]+)").unwrap(); +fn preprocess(input: impl std::io::Read, mut output: impl std::io::Write, dialect: &str) -> Result<()> { + // Matches: ; #dialect typescript + let directive_start = Regex::new(r";\s*#dialect\s+(\w+)").unwrap(); - // Matches: ; # end - let directirve_end = Regex::new(r";[ \t]*#[ \t]*end").unwrap(); + // Matches: ; #end + let directirve_end = Regex::new(r";\s*#end").unwrap(); let input = std::io::read_to_string(input)?; - let mut stack = DialectStack::default(); + // If the filter is None or Some(true), the lines are written to the output + let mut filter: Option = None; - for line in input.lines() { + for (line_no, line) in input.lines().enumerate() { if let Some(captures) = directive_start.captures(line) { let directive = captures.get(1).unwrap().as_str(); - let dialects = directive.split_whitespace().map(|s| s.to_string()).collect(); - stack.push(dialects)?; + if !DIALECTS.contains(&directive) { + bail!("Line {line_no}: unknown dialect: {directive}"); + } + + filter = Some(dialect == directive); output.write_all(line.as_bytes())?; } else if directirve_end.is_match(line) { - stack.pop()?; - output.write_all(line.as_bytes())?; - } else { - if stack.contains(dialect) { - output.write_all(line.as_bytes())?; + if filter.is_none() { + bail!("Line {line_no}: unmatched directive end"); } + + filter = None; + output.write_all(line.as_bytes())?; + } else if filter.unwrap_or(true) { + output.write_all(line.as_bytes())?; } // a new line is always written so that removed lines are padded to preserve line numbers output.write(b"\n")?; @@ -79,18 +52,20 @@ fn preprocess(input: impl std::io::Read, mut output: impl std::io::Write, dialec Ok(()) } -const TSG_SOURCE: &str = "src/stack-graphs.tsg"; -const DIALECTS: [&str; 2] = ["typescript", "tsx"]; - fn main() { - let out_dir = std::env::var_os("OUT_DIR").unwrap(); + let out_dir = std::env::var_os("OUT_DIR") + .expect("OUT_DIR is not set"); + for dialect in DIALECTS { - let input = std::fs::File::open(TSG_SOURCE).unwrap(); + let input = std::fs::File::open(TSG_SOURCE) + .expect("Failed to open stack-graphs.tsg"); let out_filename = Path::new(&out_dir).join(format!("stack-graphs-{dialect}.tsg")); - let output = std::fs::File::create(out_filename).unwrap(); + let output = std::fs::File::create(out_filename) + .expect("Failed to create output file"); - preprocess(input, output, dialect).unwrap(); + preprocess(input, output, dialect) + .expect("Failed to preprocess stack-graphs.tsg"); } println!("cargo:rerun-if-changed={TSG_SOURCE}"); diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/bin.rs b/languages/tree-sitter-stack-graphs-typescript/rust/bin.rs index 7352111dd..d303f3a62 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/bin.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/bin.rs @@ -6,18 +6,26 @@ // ------------------------------------------------------------------------------------------------ use anyhow::anyhow; -use clap::Parser; +use clap::{Parser, ValueEnum}; use tree_sitter_stack_graphs::cli::database::default_user_database_path_for_crate; use tree_sitter_stack_graphs::cli::provided_languages::Subcommands; +use tree_sitter_stack_graphs::loader::{LanguageConfiguration, LoadError}; use tree_sitter_stack_graphs::NoCancellation; + /// Flag to select the dialect of the language + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)] + pub enum Dialect { + Typescript, + TSX, + } + fn main() -> anyhow::Result<()> { let cli = Cli::parse(); - let lc = match language_configuration(&cli.dialect) + let lc = match language_configuration(cli.dialect) { Ok(lc) => lc, Err(err) => { - eprintln!("{err}"); + eprintln!("{}", err.display_pretty()); return Err(anyhow!("Language configuration error")); } }; @@ -25,23 +33,23 @@ fn main() -> anyhow::Result<()> { cli.subcommand.run(default_db_path, vec![lc]) } -fn language_configuration(dialect: &str) -> anyhow::Result { +fn language_configuration<'a>(dialect: Dialect) -> Result> { match dialect { - "typescript" => tree_sitter_stack_graphs_typescript::try_language_configuration(&NoCancellation) - .map_err(|e| anyhow::anyhow!("{}", e.display_pretty())), - - "tsx" => tree_sitter_stack_graphs_typescript::try_language_configuration_tsx(&NoCancellation) - .map_err(|e| anyhow::anyhow!("{}", e.display_pretty())), - - _ => anyhow::bail!("Unknown dialect: {}", dialect) + Dialect::Typescript => tree_sitter_stack_graphs_typescript::try_language_configuration_typescript(&NoCancellation), + Dialect::TSX => tree_sitter_stack_graphs_typescript::try_language_configuration_tsx(&NoCancellation), } } #[derive(Parser)] #[clap(about, version)] pub struct Cli { - #[clap(short, long, default_value = "typescript")] - dialect: String, + #[clap( + short, + long, + value_enum, + default_value_t = Dialect::Typescript, + )] + dialect: Dialect, #[clap(subcommand)] subcommand: Subcommands, diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs index b87a038d4..500bd29f0 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs @@ -17,8 +17,7 @@ pub mod tsconfig; pub mod util; /// The stacks graphs tsg path for this language. -pub const STACK_GRAPHS_TSG_TS_PATH: &str = concat!(env!("OUT_DIR"), "/stack-graphs-typescript.tsg"); -pub const STACK_GRAPHS_TSG_TSX_PATH: &str = concat!(env!("OUT_DIR"), "/stack-graphs-tsx.tsg"); +pub const STACK_GRAPHS_TSG_PATH: &str = "./stack-graphs.tsg"; /// The stack graphs tsg source for this language pub const STACK_GRAPHS_TSG_TS_SOURCE: &str = include_str!(concat!(env!("OUT_DIR"), "/stack-graphs-typescript.tsg")); pub const STACK_GRAPHS_TSG_TSX_SOURCE: &str = include_str!(concat!(env!("OUT_DIR"), "/stack-graphs-tsx.tsg")); @@ -35,11 +34,11 @@ pub const FILE_PATH_VAR: &str = "FILE_PATH"; /// The name of the project name global variable pub const PROJECT_NAME_VAR: &str = "PROJECT_NAME"; -pub fn language_configuration(cancellation_flag: &dyn CancellationFlag) -> LanguageConfiguration { - try_language_configuration(cancellation_flag).unwrap_or_else(|err| panic!("{}", err)) +pub fn language_configuration_typescript(cancellation_flag: &dyn CancellationFlag) -> LanguageConfiguration { + try_language_configuration_typescript(cancellation_flag).unwrap_or_else(|err| panic!("{}", err)) } -pub fn try_language_configuration( +pub fn try_language_configuration_typescript( cancellation_flag: &dyn CancellationFlag, ) -> Result { let mut lc = LanguageConfiguration::from_sources( @@ -47,7 +46,7 @@ pub fn try_language_configuration( Some(String::from("source.ts")), None, vec![String::from("ts")], - STACK_GRAPHS_TSG_TS_PATH.into(), + STACK_GRAPHS_TSG_PATH.into(), STACK_GRAPHS_TSG_TS_SOURCE, Some(( STACK_GRAPHS_BUILTINS_PATH.into(), @@ -75,7 +74,7 @@ pub fn try_language_configuration_tsx( Some(String::from("source.tsx")), None, vec![String::from("tsx")], - STACK_GRAPHS_TSG_TSX_PATH.into(), + STACK_GRAPHS_TSG_PATH.into(), STACK_GRAPHS_TSG_TSX_SOURCE, Some(( STACK_GRAPHS_BUILTINS_PATH.into(), diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/test.rs b/languages/tree-sitter-stack-graphs-typescript/rust/test.rs index ca5b8494c..72d41d900 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/test.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/test.rs @@ -11,7 +11,7 @@ use tree_sitter_stack_graphs::ci::Tester; use tree_sitter_stack_graphs::NoCancellation; fn main() -> anyhow::Result<()> { - let lc = match tree_sitter_stack_graphs_typescript::try_language_configuration(&NoCancellation) + let lc = match tree_sitter_stack_graphs_typescript::try_language_configuration_typescript(&NoCancellation) { Ok(lc) => lc, Err(err) => { From bf0a4476d3e99df9ee8a944a42e21e3ce4387a5c Mon Sep 17 00:00:00 2001 From: Eugene Yakubovich Date: Tue, 12 Mar 2024 11:11:14 -0700 Subject: [PATCH 441/500] Fix formatting and typos - Also fixes error msgs to use 1-based line nums --- .../build.rs | 29 ++++++++++--------- .../rust/bin.rs | 25 +++++++++------- .../rust/lib.rs | 16 ++++++---- .../rust/test.rs | 5 ++-- 4 files changed, 45 insertions(+), 30 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-typescript/build.rs b/languages/tree-sitter-stack-graphs-typescript/build.rs index 4527a7e8e..0c2d01c25 100644 --- a/languages/tree-sitter-stack-graphs-typescript/build.rs +++ b/languages/tree-sitter-stack-graphs-typescript/build.rs @@ -7,26 +7,33 @@ use std::path::Path; -use anyhow::{Result, bail}; +use anyhow::{bail, Result}; use regex::Regex; const TSG_SOURCE: &str = "src/stack-graphs.tsg"; const DIALECTS: [&str; 2] = ["typescript", "tsx"]; /// preprocess the input file, removing lines that are not for the selected dialect -fn preprocess(input: impl std::io::Read, mut output: impl std::io::Write, dialect: &str) -> Result<()> { +fn preprocess( + input: impl std::io::Read, + mut output: impl std::io::Write, + dialect: &str, +) -> Result<()> { // Matches: ; #dialect typescript let directive_start = Regex::new(r";\s*#dialect\s+(\w+)").unwrap(); // Matches: ; #end - let directirve_end = Regex::new(r";\s*#end").unwrap(); + let directive_end = Regex::new(r";\s*#end").unwrap(); let input = std::io::read_to_string(input)?; // If the filter is None or Some(true), the lines are written to the output let mut filter: Option = None; - for (line_no, line) in input.lines().enumerate() { + for (mut line_no, line) in input.lines().enumerate() { + // Line numbers are one based + line_no += 1; + if let Some(captures) = directive_start.captures(line) { let directive = captures.get(1).unwrap().as_str(); if !DIALECTS.contains(&directive) { @@ -35,7 +42,7 @@ fn preprocess(input: impl std::io::Read, mut output: impl std::io::Write, dialec filter = Some(dialect == directive); output.write_all(line.as_bytes())?; - } else if directirve_end.is_match(line) { + } else if directive_end.is_match(line) { if filter.is_none() { bail!("Line {line_no}: unmatched directive end"); } @@ -53,19 +60,15 @@ fn preprocess(input: impl std::io::Read, mut output: impl std::io::Write, dialec } fn main() { - let out_dir = std::env::var_os("OUT_DIR") - .expect("OUT_DIR is not set"); + let out_dir = std::env::var_os("OUT_DIR").expect("OUT_DIR is not set"); for dialect in DIALECTS { - let input = std::fs::File::open(TSG_SOURCE) - .expect("Failed to open stack-graphs.tsg"); + let input = std::fs::File::open(TSG_SOURCE).expect("Failed to open stack-graphs.tsg"); let out_filename = Path::new(&out_dir).join(format!("stack-graphs-{dialect}.tsg")); - let output = std::fs::File::create(out_filename) - .expect("Failed to create output file"); + let output = std::fs::File::create(out_filename).expect("Failed to create output file"); - preprocess(input, output, dialect) - .expect("Failed to preprocess stack-graphs.tsg"); + preprocess(input, output, dialect).expect("Failed to preprocess stack-graphs.tsg"); } println!("cargo:rerun-if-changed={TSG_SOURCE}"); diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/bin.rs b/languages/tree-sitter-stack-graphs-typescript/rust/bin.rs index d303f3a62..797e8cea7 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/bin.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/bin.rs @@ -12,17 +12,16 @@ use tree_sitter_stack_graphs::cli::provided_languages::Subcommands; use tree_sitter_stack_graphs::loader::{LanguageConfiguration, LoadError}; use tree_sitter_stack_graphs::NoCancellation; - /// Flag to select the dialect of the language - #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)] - pub enum Dialect { - Typescript, - TSX, - } +/// Flag to select the dialect of the language +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)] +pub enum Dialect { + Typescript, + TSX, +} fn main() -> anyhow::Result<()> { let cli = Cli::parse(); - let lc = match language_configuration(cli.dialect) - { + let lc = match language_configuration(cli.dialect) { Ok(lc) => lc, Err(err) => { eprintln!("{}", err.display_pretty()); @@ -35,8 +34,14 @@ fn main() -> anyhow::Result<()> { fn language_configuration<'a>(dialect: Dialect) -> Result> { match dialect { - Dialect::Typescript => tree_sitter_stack_graphs_typescript::try_language_configuration_typescript(&NoCancellation), - Dialect::TSX => tree_sitter_stack_graphs_typescript::try_language_configuration_tsx(&NoCancellation), + Dialect::Typescript => { + tree_sitter_stack_graphs_typescript::try_language_configuration_typescript( + &NoCancellation, + ) + } + Dialect::TSX => { + tree_sitter_stack_graphs_typescript::try_language_configuration_tsx(&NoCancellation) + } } } diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs index 500bd29f0..1216de4a2 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs @@ -17,10 +17,12 @@ pub mod tsconfig; pub mod util; /// The stacks graphs tsg path for this language. -pub const STACK_GRAPHS_TSG_PATH: &str = "./stack-graphs.tsg"; +pub const STACK_GRAPHS_TSG_PATH: &str = "src/stack-graphs.tsg"; /// The stack graphs tsg source for this language -pub const STACK_GRAPHS_TSG_TS_SOURCE: &str = include_str!(concat!(env!("OUT_DIR"), "/stack-graphs-typescript.tsg")); -pub const STACK_GRAPHS_TSG_TSX_SOURCE: &str = include_str!(concat!(env!("OUT_DIR"), "/stack-graphs-tsx.tsg")); +const STACK_GRAPHS_TSG_TS_SOURCE: &str = + include_str!(concat!(env!("OUT_DIR"), "/stack-graphs-typescript.tsg")); +const STACK_GRAPHS_TSG_TSX_SOURCE: &str = + include_str!(concat!(env!("OUT_DIR"), "/stack-graphs-tsx.tsg")); /// The stack graphs builtins configuration for this language pub const STACK_GRAPHS_BUILTINS_CONFIG: &str = include_str!("../src/builtins.cfg"); @@ -34,7 +36,9 @@ pub const FILE_PATH_VAR: &str = "FILE_PATH"; /// The name of the project name global variable pub const PROJECT_NAME_VAR: &str = "PROJECT_NAME"; -pub fn language_configuration_typescript(cancellation_flag: &dyn CancellationFlag) -> LanguageConfiguration { +pub fn language_configuration_typescript( + cancellation_flag: &dyn CancellationFlag, +) -> LanguageConfiguration { try_language_configuration_typescript(cancellation_flag).unwrap_or_else(|err| panic!("{}", err)) } @@ -62,7 +66,9 @@ pub fn try_language_configuration_typescript( Ok(lc) } -pub fn language_configuration_tsx(cancellation_flag: &dyn CancellationFlag) -> LanguageConfiguration { +pub fn language_configuration_tsx( + cancellation_flag: &dyn CancellationFlag, +) -> LanguageConfiguration { try_language_configuration_tsx(cancellation_flag).unwrap_or_else(|err| panic!("{}", err)) } diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/test.rs b/languages/tree-sitter-stack-graphs-typescript/rust/test.rs index 72d41d900..3ff155b6f 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/test.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/test.rs @@ -11,8 +11,9 @@ use tree_sitter_stack_graphs::ci::Tester; use tree_sitter_stack_graphs::NoCancellation; fn main() -> anyhow::Result<()> { - let lc = match tree_sitter_stack_graphs_typescript::try_language_configuration_typescript(&NoCancellation) - { + let lc = match tree_sitter_stack_graphs_typescript::try_language_configuration_typescript( + &NoCancellation, + ) { Ok(lc) => lc, Err(err) => { eprintln!("{}", err.display_pretty()); From 805bffdbf08c64ad29e1adda8b0fdf0388327f31 Mon Sep 17 00:00:00 2001 From: Eugene Yakubovich Date: Tue, 12 Mar 2024 11:39:45 -0700 Subject: [PATCH 442/500] Don't allow code mixed with directives on a line --- .../tree-sitter-stack-graphs-typescript/build.rs | 12 ++++++++++-- .../tree-sitter-stack-graphs-typescript/rust/lib.rs | 4 ++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-typescript/build.rs b/languages/tree-sitter-stack-graphs-typescript/build.rs index 0c2d01c25..d7e71e72c 100644 --- a/languages/tree-sitter-stack-graphs-typescript/build.rs +++ b/languages/tree-sitter-stack-graphs-typescript/build.rs @@ -25,6 +25,8 @@ fn preprocess( // Matches: ; #end let directive_end = Regex::new(r";\s*#end").unwrap(); + let no_code = Regex::new(r"^[\s;]+").unwrap(); + let input = std::io::read_to_string(input)?; // If the filter is None or Some(true), the lines are written to the output @@ -35,20 +37,26 @@ fn preprocess( line_no += 1; if let Some(captures) = directive_start.captures(line) { + if !no_code.is_match(line) { + bail!("Line {line_no}: unexpected code before directive"); + } + let directive = captures.get(1).unwrap().as_str(); if !DIALECTS.contains(&directive) { bail!("Line {line_no}: unknown dialect: {directive}"); } filter = Some(dialect == directive); - output.write_all(line.as_bytes())?; } else if directive_end.is_match(line) { + if !no_code.is_match(line) { + bail!("Line {line_no}: unexpected code before directive end"); + } + if filter.is_none() { bail!("Line {line_no}: unmatched directive end"); } filter = None; - output.write_all(line.as_bytes())?; } else if filter.unwrap_or(true) { output.write_all(line.as_bytes())?; } diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs index 1216de4a2..396fbc68b 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs @@ -19,9 +19,9 @@ pub mod util; /// The stacks graphs tsg path for this language. pub const STACK_GRAPHS_TSG_PATH: &str = "src/stack-graphs.tsg"; /// The stack graphs tsg source for this language -const STACK_GRAPHS_TSG_TS_SOURCE: &str = +pub const STACK_GRAPHS_TSG_TS_SOURCE: &str = include_str!(concat!(env!("OUT_DIR"), "/stack-graphs-typescript.tsg")); -const STACK_GRAPHS_TSG_TSX_SOURCE: &str = +pub const STACK_GRAPHS_TSG_TSX_SOURCE: &str = include_str!(concat!(env!("OUT_DIR"), "/stack-graphs-tsx.tsg")); /// The stack graphs builtins configuration for this language From b96c015ad67b63520093c83c25728183675ad0ef Mon Sep 17 00:00:00 2001 From: Eugene Yakubovich Date: Fri, 15 Mar 2024 10:23:46 -0700 Subject: [PATCH 443/500] Check for nested and unmatched directives - Error if one #dialect directive is nested in another - Error if #dialect is missing #end at the end of file --- languages/tree-sitter-stack-graphs-typescript/build.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/languages/tree-sitter-stack-graphs-typescript/build.rs b/languages/tree-sitter-stack-graphs-typescript/build.rs index d7e71e72c..31e3dd9de 100644 --- a/languages/tree-sitter-stack-graphs-typescript/build.rs +++ b/languages/tree-sitter-stack-graphs-typescript/build.rs @@ -41,6 +41,10 @@ fn preprocess( bail!("Line {line_no}: unexpected code before directive"); } + if filter.is_some() { + bail!("Line {line_no}: dialect directive cannot be nested"); + } + let directive = captures.get(1).unwrap().as_str(); if !DIALECTS.contains(&directive) { bail!("Line {line_no}: unknown dialect: {directive}"); @@ -64,6 +68,10 @@ fn preprocess( output.write(b"\n")?; } + if filter.is_some() { + bail!("Unmatched directive end at the end of the file"); + } + Ok(()) } From 1e1207237cab1ac72dc4fbad0a8c5085a6f66612 Mon Sep 17 00:00:00 2001 From: Eugene Yakubovich Date: Thu, 14 Mar 2024 11:39:57 -0700 Subject: [PATCH 444/500] Support JSX elements in TSX - Adds support for JSX elements: {expr} - The grammar uses nested_identifier for tags in the Foo.Bar.Baz form. It's the same symbol as what's used in namespaces: namespace Foo.Bar.Baz {} As such it ends up producing a bit of junk (unconnected cliques) but I don't know if it can be fixed w/o tree sitter queries supporting matching only if under a specified ancestor. - Unlike JavaScript, TypeScript requires variables to be declared. In JSX, {y = 2} is allowed if x, y are not in scope. They'll be created on first use. In TSX, this is disallowed which simplifies lexical_scope propogation compared to the JS TSG implementation. --- .../rust/test.rs | 23 ++- .../src/stack-graphs.tsg | 176 +++++++++++++++++- .../test/jsx/jsx_core.tsx | 39 ++++ .../test/jsx/jsx_fragment.tsx | 12 ++ .../test/jsx/jsx_namespace_name.tsx | 30 +++ .../test/jsx/jsx_self_closing_element.tsx | 37 ++++ .../test/jsx/jsx_text.tsx | 8 + 7 files changed, 311 insertions(+), 14 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_core.tsx create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_fragment.tsx create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_namespace_name.tsx create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_self_closing_element.tsx create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_text.tsx diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/test.rs b/languages/tree-sitter-stack-graphs-typescript/rust/test.rs index 3ff155b6f..51ef9cdca 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/test.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/test.rs @@ -11,15 +11,18 @@ use tree_sitter_stack_graphs::ci::Tester; use tree_sitter_stack_graphs::NoCancellation; fn main() -> anyhow::Result<()> { - let lc = match tree_sitter_stack_graphs_typescript::try_language_configuration_typescript( - &NoCancellation, - ) { - Ok(lc) => lc, - Err(err) => { - eprintln!("{}", err.display_pretty()); - return Err(anyhow!("Language configuration error")); - } - }; + let lc_factories = [ + tree_sitter_stack_graphs_typescript::try_language_configuration_typescript, + tree_sitter_stack_graphs_typescript::try_language_configuration_tsx, + ]; + + let lcs = lc_factories + .iter() + .map(|lc_factory| lc_factory(&NoCancellation)) + .collect::, _>>() + .inspect_err(|err| eprintln!("{}", err.display_pretty())) + .map_err(|_| anyhow!("Language configuration error"))?; + let test_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test"); - Tester::new(vec![lc], vec![test_path]).run() + Tester::new(lcs, vec![test_path]).run() } diff --git a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg index 63c56760f..fa1cbf8f8 100644 --- a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg @@ -2667,6 +2667,13 @@ if none @is_async { (true) ; #dialect typescript (type_assertion) +; #end +; #dialect tsx + (jsx_element) + (jsx_self_closing_element) + (jsx_opening_element) + (jsx_closing_element) + (jsx_expression) ; #end (unary_expression) (undefined) @@ -2805,6 +2812,15 @@ if none @is_async { (decorator (call_expression function:(member_expression object:(identifier)@name))) (decorator (call_expression function:(member_expression object:(member_expression object:(identifier)@name)))) (decorator (call_expression function:(member_expression object:(member_expression object:(member_expression object:(identifier)@name))))) +; #dialect tsx + (nested_identifier (identifier)@name) + (nested_identifier (nested_identifier)@name) + (nested_type_identifier module:(nested_identifier)@name) + (internal_module name:(_)@name) + (jsx_opening_element name: (_)@name) + (jsx_closing_element name: (_)@name) + (jsx_self_closing_element name: (_)@name) +; #end ] { if none @is_def { node @name.cotype @@ -2852,6 +2868,12 @@ if none @is_def { (decorator (call_expression function:(member_expression object:(identifier)@name))) (decorator (call_expression function:(member_expression object:(member_expression object:(identifier)@name)))) (decorator (call_expression function:(member_expression object:(member_expression object:(member_expression object:(identifier)@name))))) +; #dialect tsx + (nested_identifier (identifier)@name (identifier)) ; to pick up foo in JSX: + (jsx_opening_element name: (identifier)@name) + (jsx_closing_element name: (identifier)@name) + (jsx_self_closing_element name: (identifier)@name) +; #end ] { if none @is_def { node @name.expr_ref @@ -3524,10 +3546,22 @@ if none @is_async { ; (member_expression (identifier) (property_identifier)) ; (subscript_expression (identifier) (string)) -(member_expression - object: (_)@object - property: (_)@prop -)@member_expr { +[ + (member_expression + object: (_)@object + property: (_)@prop + )@member_expr +; #dialect tsx + (nested_identifier + (nested_identifier)@object + (identifier)@prop + )@member_expr + (nested_identifier + (identifier)@object + (identifier)@prop + )@member_expr +; #end + ] { node @member_expr.member node @prop.expr_ref node @prop.expr_ref__typeof @@ -6160,3 +6194,137 @@ if none @is_acc { attr (@async.async_type__promise_ref__ns) push_symbol = "%T" edge @async.async_type__promise_ref__ns -> @async.lexical_scope } + +; +; # ##### # # +; # # # # # +; # # # # +; # ##### # +; # # # # # +; # # # # # # +; ##### ##### # # +; +; ;;;;;;;;;;;;;;;;;;;; +; #dialect tsx +; ;;;;;;;;;;;;;;;;;;;; + +(jsx_element + open_tag:(_)@open_tag + close_tag:(_)@close_tag)@jsx_element { + + edge @open_tag.lexical_scope -> @jsx_element.lexical_scope + edge @close_tag.lexical_scope -> @jsx_element.lexical_scope +} + +(jsx_element + [ + (jsx_text) + (jsx_element) + (jsx_fragment) + (jsx_self_closing_element) + (jsx_expression) + ]@child +)@parent { + edge @child.lexical_scope -> @parent.lexical_scope +} + +(jsx_fragment)@fragment { + node @fragment.lexical_scope + node @fragment.value + node @fragment.type +} + +(jsx_fragment + [ + (jsx_text) + (jsx_element) + (jsx_fragment) + (jsx_self_closing_element) + (jsx_expression) + ]@child +) @parent { + edge @child.lexical_scope -> @parent.lexical_scope +} + +(jsx_text)@jsx_text { + node @jsx_text.lexical_scope +} + +[ + (jsx_opening_element name: (_)@name)@element + (jsx_closing_element name: (_)@name)@element + (jsx_self_closing_element name: (_)@name)@element +] { + edge @name.lexical_scope -> @element.lexical_scope +} + +(jsx_opening_element + name:(_)@element_name + attribute:(_)@attr +) { + edge @attr.lexical_scope -> @element_name.lexical_scope +} + +(jsx_attribute (_) . (_)?@attr_value)@jsx_attribute { + node @jsx_attribute.lexical_scope + + if some @attr_value { + edge @attr_value.lexical_scope -> @jsx_attribute.lexical_scope + } +} + +(jsx_namespace_name (_) @lhs (_) @rhs)@name { + node @name.lexical_scope + + edge @lhs.lexical_scope -> @name.lexical_scope + edge @rhs.lexical_scope -> @name.lexical_scope +} + +(jsx_self_closing_element + name:(_)@element_name)@element { + edge @element_name.lexical_scope -> @element.lexical_scope +} + +(jsx_self_closing_element + name:(_)@element_name + attribute:(_)@attr +) { + edge @attr.lexical_scope -> @element_name.lexical_scope +} + +(jsx_expression (_)@child)@expr { + edge @child.lexical_scope -> @expr.lexical_scope +} + +(jsx_closing_element + name:(_)@element_name)@element +{ + edge @element_name.lexical_scope -> @element.lexical_scope +} + +[ + (jsx_opening_element + name:(identifier)@element_name) + (jsx_self_closing_element + name:(identifier)@element_name) + (jsx_closing_element + name:(identifier)@element_name) +] { + scan (source-text @element_name) { + ; standard HTML elements + "^(a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdi|bdo|big|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|data|datalist|dd|del|details|dfn|dialog|dir|div|dl|dt|em|embed|fieldset|figcaption|figure|font|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|header|hgroup|hr|html|i|iframe|input|ins|kbd|label|legend|li|link|main|map|mark|menu|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|picture|pre|progress|q|rp|rt|ruby|s|samp|script|search|section|select|small|source|span|strike|strong|style|sub|summary|sup|svg|table|tbody|td|template|textarea|tfoot|th|thead|time|title|tr|track|tt|u|ul|var|video|wbr)$" { + ; do nothing! + } + + ; everything else + "^.+$" { + node element_name_pop + attr (element_name_pop) node_reference = @element_name + edge element_name_pop -> @element_name.lexical_scope + } + } +} + +; ;;;;;;;;;;;;;;;;;;;; +; #end +; ;;;;;;;;;;;;;;;;;;;; diff --git a/languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_core.tsx b/languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_core.tsx new file mode 100644 index 000000000..93285bc93 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_core.tsx @@ -0,0 +1,39 @@ +// The core of JSX tests here verify the behavior of the following node types: +// jsx_element +// jsx_identifier +// jsx_attribute +// jsx_expression +// jsx_opening_element +// jsx_closing_element +// There is no real way to avoid testing all of these at once, +// and so we don't even try to. + +let x = 1; + +// Flow In + +const el = {x}; +// ^ defined: 11 +// ^ defined: 11 + +const el2 = +// ^ defined: 11 +// ^ defined: 11 + +let y = 0; +let z = 2; + +const el = +// ^ defined: 23 + {z = 3} +// ^ defined: 24 +; + +/**/ y; +// ^ defined: 23 + +/**/ z; +// ^ defined: 24 + +/**/ x; +// ^ defined: 11 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_fragment.tsx b/languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_fragment.tsx new file mode 100644 index 000000000..1713694f7 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_fragment.tsx @@ -0,0 +1,12 @@ +let x = 1; + +// Flow Around + +const el = <>; + +/**/ x; +// ^ defined: 1 + +// Children +({x}); +// ^ defined: 1 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_namespace_name.tsx b/languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_namespace_name.tsx new file mode 100644 index 000000000..74fe0ff9b --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_namespace_name.tsx @@ -0,0 +1,30 @@ +let x = 1; + +// Flow Around +namespace noo.bar { + export let baz = 1; +} + +const el = ; +// ^ defined: 4 +// ^ defined: 4 +// ^ defined: 5 +// ^ defined: 4 +// ^ defined: 4 +// ^ defined: 5 + +/**/ x; +// ^ defined: 1 + +// Flow In + +let foo = { + bar: { + baz: 1 + } +}; + +const el2 = ; +// ^ defined: 21 +// ^ defined: 22 +// ^ defined: 23 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_self_closing_element.tsx b/languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_self_closing_element.tsx new file mode 100644 index 000000000..d26746137 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_self_closing_element.tsx @@ -0,0 +1,37 @@ +// The core of JSX tests here verify the behavior of the following node types: +// jsx_element +// jsx_identifier +// jsx_attribute +// jsx_expression +// jsx_opening_element +// jsx_closing_element +// There is no real way to avoid testing all of these at once, +// and so we don't even try to. + +let x = 1; + +// Flow In + +const el = ; +// ^ defined: 11 + +const el2 = +// ^ defined: 11 + +// Flow Out + +let y = 2; + +const el = ; +// ^ defined: 23 + +// Flow Across + +const el = ; +// ^ defined: 23 + +// Flow Around + +/**/ x; +// ^ defined: 11 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_text.tsx b/languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_text.tsx new file mode 100644 index 000000000..0cc359765 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_text.tsx @@ -0,0 +1,8 @@ +let x = 1; + +// Flow Around + +const el = bar; + +/**/ x; +// ^ defined: 1 \ No newline at end of file From 7db914c01b35ce024f6767e02dd1ad97022a6bc1 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 10 Apr 2024 17:26:28 +0200 Subject: [PATCH 445/500] Skip failed files during indexing instead of aborting the whole index operation --- tree-sitter-stack-graphs/CHANGELOG.md | 8 ++++++++ tree-sitter-stack-graphs/Cargo.toml | 2 +- tree-sitter-stack-graphs/src/cli/index.rs | 18 +++++------------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tree-sitter-stack-graphs/CHANGELOG.md b/tree-sitter-stack-graphs/CHANGELOG.md index 2b907e682..f72fb402c 100644 --- a/tree-sitter-stack-graphs/CHANGELOG.md +++ b/tree-sitter-stack-graphs/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v0.8.2 -- unreleased + +### CLI + +#### Changed + +- Failure to index a file will not abort indexing anymore, but simply mark the file as failed, as we already do for files with parse errors. + ## v0.8.1 -- 2024-03-06 The `stack-graphs` dependency was updated to `v0.13` to fix the build problems of the `v0.8.0` release. diff --git a/tree-sitter-stack-graphs/Cargo.toml b/tree-sitter-stack-graphs/Cargo.toml index 875faf4ef..d1b0fc1c6 100644 --- a/tree-sitter-stack-graphs/Cargo.toml +++ b/tree-sitter-stack-graphs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tree-sitter-stack-graphs" -version = "0.8.1" +version = "0.8.2" description = "Create stack graphs using tree-sitter parsers" homepage = "https://github.com/github/stack-graphs/tree/main/tree-sitter-stack-graphs" repository = "https://github.com/github/stack-graphs/" diff --git a/tree-sitter-stack-graphs/src/cli/index.rs b/tree-sitter-stack-graphs/src/cli/index.rs index 6d192e382..e8704f99d 100644 --- a/tree-sitter-stack-graphs/src/cli/index.rs +++ b/tree-sitter-stack-graphs/src/cli/index.rs @@ -355,23 +355,15 @@ impl<'a> Indexer<'a> { if let Err(err) = result { match err.inner { BuildError::Cancelled(_) => { - file_status.warning("parsing timed out", None); + file_status.warning("timed out", None); self.db - .store_error_for_file(source_path, &tag, "parsing timed out")?; - return Ok(()); - } - BuildError::ParseErrors { .. } => { - file_status.failure("parsing failed", Some(&err.display_pretty())); - self.db.store_error_for_file( - source_path, - &tag, - &format!("parsing failed: {}", err.inner), - )?; + .store_error_for_file(source_path, &tag, "timed out")?; return Ok(()); } _ => { - file_status.failure("failed to build stack graph", Some(&err.display_pretty())); - return Err(IndexError::StackGraph); + file_status.failure("failed", Some(&err.display_pretty())); + self.db.store_error_for_file(source_path, &tag, "failed")?; + return Ok(()); } } }; From 4ef3678a28f3521572653b38974999bf6b2778cf Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Mon, 22 Apr 2024 11:33:16 +0200 Subject: [PATCH 446/500] Add support for lambda parameters --- .../src/stack-graphs.tsg | 59 +++++++++++++------ .../test/lambdas.py | 2 + 2 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-python/test/lambdas.py diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 48353f14a..f9798fe54 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -759,32 +759,39 @@ inherit .parent_module (with_clause) {} -(function_definition - name: (identifier) @name) { - attr (@name.def) node_definition = @name -} - -(function_definition - name: (identifier) @name - parameters: (parameters) @params - body: (block) @body) @func -{ - node call - node drop_scope +[ + (function_definition + parameters: (_) @params + body: (_) @body + ) @func + (lambda + parameters: (_) @params + body: (_) @body + )@func +] { + node @func.call node return_value + node drop_scope - attr (@name.def) definiens_node = @func - edge @func.after_scope -> @name.def - edge @name.def -> call - edge call -> return_value + edge @func.call -> return_value edge @body.before_scope -> @params.after_scope edge @body.before_scope -> drop_scope edge drop_scope -> @func.bottom attr (drop_scope) type = "drop_scopes" - attr (call) pop_scoped_symbol = "()" + attr (@func.call) pop_scoped_symbol = "()" edge @params.before_scope -> JUMP_TO_SCOPE_NODE attr (return_value) is_exported let @func.function_returns = return_value +} + +(function_definition + name: (identifier) @name + body: (_) @body +) @func { + attr (@name.def) node_definition = @name + attr (@name.def) definiens_node = @func + edge @func.after_scope -> @name.def + edge @name.def -> @func.call ; Prevent functions defined inside of method bodies from being treated like methods let @body.class_self_scope = #null @@ -802,8 +809,10 @@ inherit .parent_module attr (@param.output) push_node = @param } -(parameters - (_) @param) @params +[ + (parameters (_) @param) @params + (lambda_parameters (_) @param) @params +] { node @param.param_index node @param.param_name @@ -954,6 +963,18 @@ inherit .parent_module ;; ;; Expressions +(lambda + body: (_) @body +)@lam { + ;; TODO Unify .before_scope, .local_scope, and .input to simplify + ;; uniform treatment of lambdas and function definitions. + node @body.before_scope + let @body.local_scope = @body.before_scope + edge @body.input -> @body.before_scope + + edge @lam.output -> @lam.call +} + (conditional_expression) {} (named_expression) {} diff --git a/languages/tree-sitter-stack-graphs-python/test/lambdas.py b/languages/tree-sitter-stack-graphs-python/test/lambdas.py new file mode 100644 index 000000000..9812df4de --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/lambdas.py @@ -0,0 +1,2 @@ +sorted([1, 2, 3], key=lambda x: x) +# ^ defined: 1 From f7e8984e70350160b1019ac3c12f68bcfe823580 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 23 Apr 2024 13:47:25 +0200 Subject: [PATCH 447/500] Cache partial paths for builtins when running tests --- stack-graphs/src/graph.rs | 8 ++- tree-sitter-stack-graphs/src/cli/test.rs | 90 +++++++++++++++++++----- 2 files changed, 77 insertions(+), 21 deletions(-) diff --git a/stack-graphs/src/graph.rs b/stack-graphs/src/graph.rs index 84748c6bf..686344ee5 100644 --- a/stack-graphs/src/graph.rs +++ b/stack-graphs/src/graph.rs @@ -1497,12 +1497,16 @@ impl StackGraph { /// Copies the given stack graph into this stack graph. Panics if any of the files /// in the other stack graph are already defined in the current one. - pub fn add_from_graph(&mut self, other: &StackGraph) -> Result<(), Handle> { + pub fn add_from_graph( + &mut self, + other: &StackGraph, + ) -> Result>, Handle> { let mut files = HashMap::new(); for other_file in other.iter_files() { let file = self.add_file(other[other_file].name())?; files.insert(other_file, file); } + let files = files; let node_id = |other_node_id: NodeID| { if other_node_id.is_root() { NodeID::root() @@ -1645,7 +1649,7 @@ impl StackGraph { } } } - Ok(()) + Ok(files.into_values().collect()) } } diff --git a/tree-sitter-stack-graphs/src/cli/test.rs b/tree-sitter-stack-graphs/src/cli/test.rs index 780d478f6..c7f73e7ce 100644 --- a/tree-sitter-stack-graphs/src/cli/test.rs +++ b/tree-sitter-stack-graphs/src/cli/test.rs @@ -19,9 +19,13 @@ use stack_graphs::stitching::Database; use stack_graphs::stitching::DatabaseCandidates; use stack_graphs::stitching::ForwardPartialPathStitcher; use stack_graphs::stitching::StitcherConfig; +use std::collections::hash_map::Entry; +use std::collections::HashMap; +use std::collections::HashSet; use std::path::Path; use std::path::PathBuf; use std::time::Duration; +use tree_sitter::Language; use tree_sitter_graph::Variables; use crate::cli::util::duration_from_seconds_str; @@ -176,10 +180,16 @@ impl TestArgs { pub fn run(self, mut loader: Loader) -> anyhow::Result<()> { let reporter = self.get_reporter(); let mut total_result = TestResult::new(); + let mut cache = HashMap::new(); for (test_root, test_path, _) in iter_files_and_directories(self.test_paths.clone()) { let mut file_status = CLIFileReporter::new(&reporter, &test_path); - let test_result = - self.run_test(&test_root, &test_path, &mut loader, &mut file_status)?; + let test_result = self.run_test( + &test_root, + &test_path, + &mut loader, + &mut file_status, + &mut cache, + )?; file_status.assert_reported(); total_result.absorb(test_result); } @@ -211,14 +221,15 @@ impl TestArgs { } /// Run test file. Takes care of the output when an error is returned. - fn run_test( + fn run_test<'a>( &self, test_root: &Path, test_path: &Path, - loader: &mut Loader, + loader: &'a mut Loader, file_status: &mut CLIFileReporter, + cache: &mut HashMap, ) -> anyhow::Result { - match self.run_test_inner(test_root, test_path, loader, file_status) { + match self.run_test_inner(test_root, test_path, loader, file_status, cache) { ok @ Ok(_) => ok, err @ Err(_) => { file_status.failure_if_processing("error", None); @@ -227,12 +238,13 @@ impl TestArgs { } } - fn run_test_inner( + fn run_test_inner<'a>( &self, test_root: &Path, test_path: &Path, - loader: &mut Loader, + loader: &'a mut Loader, file_status: &mut CLIFileReporter, + cache: &mut HashMap, ) -> anyhow::Result { let cancellation_flag = CancelAfterDuration::from_option(self.max_test_time); @@ -263,11 +275,24 @@ impl TestArgs { file_status.processing(); + let stitcher_config = + StitcherConfig::default().with_detect_similar_paths(!lc.no_similar_paths_in_file); + let mut partials = PartialPaths::new(); + let mut db = Database::new(); + let source = file_reader.get(test_path)?; let default_fragment_path = test_path.strip_prefix(test_root).unwrap(); let mut test = Test::from_source(test_path, source, default_fragment_path)?; if !self.no_builtins { - self.load_builtins_into(&lc, &mut test.graph)?; + self.load_builtins_into( + &lc, + &mut test.graph, + &mut partials, + &mut db, + stitcher_config, + cancellation_flag.as_ref(), + cache, + )?; } let mut globals = Variables::new(); for test_fragment in &test.fragments { @@ -325,15 +350,11 @@ impl TestArgs { Ok(_) => {} } } - let stitcher_config = - StitcherConfig::default().with_detect_similar_paths(!lc.no_similar_paths_in_file); - let mut partials = PartialPaths::new(); - let mut db = Database::new(); - for file in test.graph.iter_files() { + for fragment in &test.fragments { ForwardPartialPathStitcher::find_minimal_partial_path_set_in_file( &test.graph, &mut partials, - file, + fragment.file, stitcher_config, &cancellation_flag.as_ref(), |g, ps, p| { @@ -387,14 +408,45 @@ impl TestArgs { Ok(result) } - fn load_builtins_into( + fn load_builtins_into<'a>( &self, - lc: &LanguageConfiguration, + lc: &'a LanguageConfiguration, graph: &mut StackGraph, + partials: &mut PartialPaths, + db: &mut Database, + stitcher_config: StitcherConfig, + cancellation_flag: &dyn CancellationFlag, + cache: &mut HashMap, ) -> anyhow::Result<()> { - if let Err(h) = graph.add_from_graph(&lc.builtins) { - return Err(anyhow!("Duplicate builtin file {}", &graph[h])); - } + let files = graph + .add_from_graph(&lc.builtins) + .map_err(|h| anyhow!("Duplicate builtin file {}", &graph[h]))?; + let files = files.into_iter().collect::>(); + match cache.entry(lc.language) { + Entry::Occupied(o) => { + o.get().load_into(graph, partials, db)?; + } + Entry::Vacant(v) => { + for file in &files { + ForwardPartialPathStitcher::find_minimal_partial_path_set_in_file( + graph, + partials, + *file, + stitcher_config, + &cancellation_flag, + |g, ps, p| { + db.add_partial_path(g, ps, p.clone()); + }, + )?; + } + v.insert(db.to_serializable_filter( + graph, + partials, + &|_: &StackGraph, f: &Handle| files.contains(f), + )); + } + }; + Ok(()) } From 6499341a531111afe10489e8cf0fe8495b353e9b Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 23 Apr 2024 13:55:37 +0200 Subject: [PATCH 448/500] Update changelog --- tree-sitter-stack-graphs/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tree-sitter-stack-graphs/CHANGELOG.md b/tree-sitter-stack-graphs/CHANGELOG.md index f72fb402c..e7538592a 100644 --- a/tree-sitter-stack-graphs/CHANGELOG.md +++ b/tree-sitter-stack-graphs/CHANGELOG.md @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### CLI +#### Added + +- Tests run faster for languages with builtins sources by caching the partial paths for the builtins. + #### Changed - Failure to index a file will not abort indexing anymore, but simply mark the file as failed, as we already do for files with parse errors. From b533b31add3953f851baba12983a4bccf1c1d47d Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 15 May 2024 12:04:21 +0200 Subject: [PATCH 449/500] Always enable both TS & TSX in CLI --- .../rust/bin.rs | 54 ++++++------------- 1 file changed, 16 insertions(+), 38 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/bin.rs b/languages/tree-sitter-stack-graphs-typescript/rust/bin.rs index 797e8cea7..ea7713595 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/bin.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/bin.rs @@ -6,56 +6,34 @@ // ------------------------------------------------------------------------------------------------ use anyhow::anyhow; -use clap::{Parser, ValueEnum}; +use clap::Parser; use tree_sitter_stack_graphs::cli::database::default_user_database_path_for_crate; use tree_sitter_stack_graphs::cli::provided_languages::Subcommands; -use tree_sitter_stack_graphs::loader::{LanguageConfiguration, LoadError}; use tree_sitter_stack_graphs::NoCancellation; -/// Flag to select the dialect of the language -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)] -pub enum Dialect { - Typescript, - TSX, -} - fn main() -> anyhow::Result<()> { let cli = Cli::parse(); - let lc = match language_configuration(cli.dialect) { - Ok(lc) => lc, - Err(err) => { - eprintln!("{}", err.display_pretty()); - return Err(anyhow!("Language configuration error")); - } - }; - let default_db_path = default_user_database_path_for_crate(env!("CARGO_PKG_NAME"))?; - cli.subcommand.run(default_db_path, vec![lc]) -} - -fn language_configuration<'a>(dialect: Dialect) -> Result> { - match dialect { - Dialect::Typescript => { - tree_sitter_stack_graphs_typescript::try_language_configuration_typescript( - &NoCancellation, - ) - } - Dialect::TSX => { - tree_sitter_stack_graphs_typescript::try_language_configuration_tsx(&NoCancellation) - } + let mut lcs = Vec::new(); + for r in [ + tree_sitter_stack_graphs_typescript::try_language_configuration_typescript(&NoCancellation), + tree_sitter_stack_graphs_typescript::try_language_configuration_tsx(&NoCancellation), + ] { + let lc = match r { + Ok(lc) => lc, + Err(err) => { + eprintln!("{}", err.display_pretty()); + return Err(anyhow!("Language configuration error")); + } + }; + lcs.push(lc); } + let default_db_path = default_user_database_path_for_crate(env!("CARGO_PKG_NAME"))?; + cli.subcommand.run(default_db_path, lcs) } #[derive(Parser)] #[clap(about, version)] pub struct Cli { - #[clap( - short, - long, - value_enum, - default_value_t = Dialect::Typescript, - )] - dialect: Dialect, - #[clap(subcommand)] subcommand: Subcommands, } From 36f83ea6b262ee871bf4f7b64a9dcbabfd98e3f7 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 15 May 2024 12:14:44 +0200 Subject: [PATCH 450/500] Update version and changelog --- languages/tree-sitter-stack-graphs-typescript/CHANGELOG.md | 6 ++++++ languages/tree-sitter-stack-graphs-typescript/Cargo.toml | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-typescript/CHANGELOG.md b/languages/tree-sitter-stack-graphs-typescript/CHANGELOG.md index a23db2f0e..b4260b2a6 100644 --- a/languages/tree-sitter-stack-graphs-typescript/CHANGELOG.md +++ b/languages/tree-sitter-stack-graphs-typescript/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v0.3.0 -- unreleased + +### Added + +- Support for TSX. A new language configuration for TSX is available, and TSX is enabled in the CLI next to TypeScript. + ## v0.2.0 -- 2024-03-06 The `tree-sitter-stack-graphs` is updated to `v0.8`. diff --git a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml index 46360f19c..e40c12625 100644 --- a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "tree-sitter-stack-graphs-typescript" -version = "0.2.0" -description = "Stack graphs definition for TypeScript using tree-sitter-typescript" +version = "0.3.0" +description = "Stack graphs definition for TypeScript & TSX using tree-sitter-typescript" readme = "README.md" -keywords = ["tree-sitter", "stack-graphs", "typescript"] +keywords = ["tree-sitter", "stack-graphs", "typescript", "tsx"] authors = ["Hendrik van Antwerpen "] license = "MIT OR Apache-2.0" edition = "2018" From 3f1ebc2f2e14d40e5d358848570e4863f704870d Mon Sep 17 00:00:00 2001 From: nohehf Date: Thu, 23 May 2024 10:20:25 +0200 Subject: [PATCH 451/500] test: add nested functions --- .../test/nested_functions.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-python/test/nested_functions.py diff --git a/languages/tree-sitter-stack-graphs-python/test/nested_functions.py b/languages/tree-sitter-stack-graphs-python/test/nested_functions.py new file mode 100644 index 000000000..0c6e6666e --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/nested_functions.py @@ -0,0 +1,11 @@ +def outer(a): + def inner(b, c): + pass + + inner(1) + # ^ defined: 2 + + +class A: + def method(a): + pass From 3dfe218ef25cd2eb79bf7d8faece8d0f7d36325c Mon Sep 17 00:00:00 2001 From: nohehf Date: Thu, 23 May 2024 10:23:11 +0200 Subject: [PATCH 452/500] test: nested function test --- .../test/nested_functions.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/test/nested_functions.py b/languages/tree-sitter-stack-graphs-python/test/nested_functions.py index 0c6e6666e..db655e3a3 100644 --- a/languages/tree-sitter-stack-graphs-python/test/nested_functions.py +++ b/languages/tree-sitter-stack-graphs-python/test/nested_functions.py @@ -1,11 +1,6 @@ def outer(a): - def inner(b, c): + def inner(b): pass inner(1) # ^ defined: 2 - - -class A: - def method(a): - pass From 5164f4b19f7d35097c9ed43dc57de01518647c88 Mon Sep 17 00:00:00 2001 From: nohehf Date: Thu, 23 May 2024 11:11:51 +0200 Subject: [PATCH 453/500] test: not a method --- .../test/not_a_method.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 languages/tree-sitter-stack-graphs-python/test/not_a_method.py diff --git a/languages/tree-sitter-stack-graphs-python/test/not_a_method.py b/languages/tree-sitter-stack-graphs-python/test/not_a_method.py new file mode 100644 index 000000000..c58e9af1e --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/not_a_method.py @@ -0,0 +1,13 @@ +class Foo: + a = 1 + + # Self can be named anything + def first_method(actually_self): + return actually_self.a + # ^ defined: 2 + + def second_method(self): + # First argument here is not self + def not_a_method(not_self): + return not_self.a + # ^ defined: From b020128c0e0c487ccac8e9c12f68a989212ef910 Mon Sep 17 00:00:00 2001 From: nohehf Date: Thu, 23 May 2024 21:52:50 +0200 Subject: [PATCH 454/500] fix: method self --- .../tree-sitter-stack-graphs-python/query | 12 +++++++++ .../src/stack-graphs.tsg | 26 +++++++++++++------ .../test/not_a_method.py | 15 ++++++++--- .../test/self.py | 11 ++++++++ 4 files changed, 52 insertions(+), 12 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-python/query create mode 100644 languages/tree-sitter-stack-graphs-python/test/self.py diff --git a/languages/tree-sitter-stack-graphs-python/query b/languages/tree-sitter-stack-graphs-python/query new file mode 100644 index 000000000..546c1d8d2 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/query @@ -0,0 +1,12 @@ +(class_definition + body: ( + block + (function_definition + parameters: + (parameters + . (identifier) @first_param + ) + body: (block) @method_body + ) + ) +) \ No newline at end of file diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index f9798fe54..b3973b6ae 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -794,19 +794,29 @@ inherit .parent_module edge @name.def -> @func.call ; Prevent functions defined inside of method bodies from being treated like methods + ; There might be a bug here as calling .self_scope after this, will not fallback to the larger scope let @body.class_self_scope = #null let @body.class_member_attr_scope = #null } -(function_definition - parameters: (parameters - . (identifier) @param) - body: (block) @body) +; method definition +(class_definition + body: ( + block + (function_definition + parameters: + (parameters + . (identifier) @first_param + ) + body: (block) @method_body + ) + ) +) { - edge @param.def -> @param.class_self_scope - edge @param.class_member_attr_scope -> @param.output - edge @param.output -> @body.after_scope - attr (@param.output) push_node = @param + edge @first_param.def -> @first_param.class_self_scope + edge @first_param.class_member_attr_scope -> @first_param.output + edge @first_param.output -> @method_body.after_scope + attr (@first_param.output) push_node = @first_param } [ diff --git a/languages/tree-sitter-stack-graphs-python/test/not_a_method.py b/languages/tree-sitter-stack-graphs-python/test/not_a_method.py index c58e9af1e..f0a207eb0 100644 --- a/languages/tree-sitter-stack-graphs-python/test/not_a_method.py +++ b/languages/tree-sitter-stack-graphs-python/test/not_a_method.py @@ -1,13 +1,20 @@ class Foo: a = 1 - # Self can be named anything - def first_method(actually_self): - return actually_self.a - # ^ defined: 2 + def first_method(self): + self.a + # ^ defined: 2 def second_method(self): + self.a + # ^ defined: 2 + # First argument here is not self def not_a_method(not_self): return not_self.a # ^ defined: + + +def function(self): + self.a + # ^ defined: diff --git a/languages/tree-sitter-stack-graphs-python/test/self.py b/languages/tree-sitter-stack-graphs-python/test/self.py new file mode 100644 index 000000000..763a52eb6 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/self.py @@ -0,0 +1,11 @@ +class Foo: + a = 1 + + def mathod_1(self): + return self.a + # ^ defined: 2 + + # Self can be named anything + def method_2(actually_self): + return actually_self.a + # ^ defined: 2 From 9551ad995c79277d950ac2e0d5d9a2d5e42631e2 Mon Sep 17 00:00:00 2001 From: nohehf Date: Thu, 23 May 2024 21:59:18 +0200 Subject: [PATCH 455/500] chore: remove unused test tree sitter query --- languages/tree-sitter-stack-graphs-python/query | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 languages/tree-sitter-stack-graphs-python/query diff --git a/languages/tree-sitter-stack-graphs-python/query b/languages/tree-sitter-stack-graphs-python/query deleted file mode 100644 index 546c1d8d2..000000000 --- a/languages/tree-sitter-stack-graphs-python/query +++ /dev/null @@ -1,12 +0,0 @@ -(class_definition - body: ( - block - (function_definition - parameters: - (parameters - . (identifier) @first_param - ) - body: (block) @method_body - ) - ) -) \ No newline at end of file From 3d283157bc40442d5b9f12e21ef13342ccf23f35 Mon Sep 17 00:00:00 2001 From: nohehf Date: Mon, 27 May 2024 09:47:41 +0200 Subject: [PATCH 456/500] fix: ignore .ts and .js extensions form imports --- .../src/stack-graphs.tsg | 6 ++++-- .../test/modules/import-extension-js.ts | 6 ++++++ .../test/modules/import-extension-none.ts | 6 ++++++ .../test/modules/import-extension-ts.ts | 6 ++++++ 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/modules/import-extension-js.ts create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/modules/import-extension-none.ts create mode 100644 languages/tree-sitter-stack-graphs-typescript/test/modules/import-extension-ts.ts diff --git a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg index fa1cbf8f8..a51a80c07 100644 --- a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg @@ -260,7 +260,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; expose globals edge proj_scope -> @prog.globals - + var mod_scope = proj_scope if (not (is-empty @imexs)) { ; module definition @@ -541,7 +541,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; module reference var mod_scope = mod_ref__ns scan (path-normalize mod_path) { - "([^/]+)/?" { + ; ignore .js and .ts extensions on imports, as ts allows this + ; this might lead to false positives + "([^/|(\.j|ts)]+)/?" { node mod_ref attr (mod_ref) push_symbol = $1 edge mod_ref -> mod_scope diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-extension-js.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-extension-js.ts new file mode 100644 index 000000000..92817fbaf --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-extension-js.ts @@ -0,0 +1,6 @@ +/* --- path: src/foo.ts --- */ +export const bar = 42; + +/* --- path: src/index.ts --- */ +import { bar } from "./foo.js"; +// ^ defined: 2 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-extension-none.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-extension-none.ts new file mode 100644 index 000000000..f221684b4 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-extension-none.ts @@ -0,0 +1,6 @@ +/* --- path: src/foo.ts --- */ +export const bar = 42; + +/* --- path: src/index.ts --- */ +import { bar } from "./foo"; +// ^ defined: 2 diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/import-extension-ts.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-extension-ts.ts new file mode 100644 index 000000000..1e46349c9 --- /dev/null +++ b/languages/tree-sitter-stack-graphs-typescript/test/modules/import-extension-ts.ts @@ -0,0 +1,6 @@ +/* --- path: src/foo.ts --- */ +export const bar = 42; + +/* --- path: src/index.ts --- */ +import { bar } from "./foo.ts"; +// ^ defined: 2 From 7509f09fdbd55267c9b933c25ce04f6a8fe55581 Mon Sep 17 00:00:00 2001 From: nohehf <64989428+nohehf@users.noreply.github.com> Date: Mon, 27 May 2024 14:17:55 +0200 Subject: [PATCH 457/500] chore: fmt Co-authored-by: Hendrik van Antwerpen --- .../tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index b3973b6ae..751e2a3db 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -801,13 +801,10 @@ inherit .parent_module ; method definition (class_definition - body: ( - block + body: (block (function_definition parameters: - (parameters - . (identifier) @first_param - ) + (parameters . (identifier) @first_param) body: (block) @method_body ) ) From d0b940e66c0e0c2d83533cc743d30142e4728585 Mon Sep 17 00:00:00 2001 From: nohehf Date: Mon, 27 May 2024 15:46:23 +0200 Subject: [PATCH 458/500] fix: add auxiliary function to remove file ext --- .../src/stack-graphs.tsg | 9 ++--- tree-sitter-stack-graphs/src/functions.rs | 37 +++++++++++++++++++ 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg index a51a80c07..7e6359280 100644 --- a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg @@ -260,7 +260,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; expose globals edge proj_scope -> @prog.globals - + var mod_scope = proj_scope if (not (is-empty @imexs)) { ; module definition @@ -540,10 +540,9 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; module reference var mod_scope = mod_ref__ns - scan (path-normalize mod_path) { - ; ignore .js and .ts extensions on imports, as ts allows this - ; this might lead to false positives - "([^/|(\.j|ts)]+)/?" { + ; normalize path and remove the extension as we want to match 'foo', 'foo.js', 'foo.ts', etc. + scan (path-remove-ext (path-normalize mod_path)) { + "([^/]+)/?" { node mod_ref attr (mod_ref) push_symbol = $1 edge mod_ref -> mod_scope diff --git a/tree-sitter-stack-graphs/src/functions.rs b/tree-sitter-stack-graphs/src/functions.rs index 9082ba427..e1f9e94e5 100644 --- a/tree-sitter-stack-graphs/src/functions.rs +++ b/tree-sitter-stack-graphs/src/functions.rs @@ -43,6 +43,10 @@ pub mod path { path_fn(|p| normalize(p).map(|p| p.as_os_str().to_os_string())), ); functions.add("path-split".into(), PathSplit); + functions.add( + "path-remove-ext".into(), + path_fn(|p| remove_extension(p).map(|p| p.as_os_str().to_os_string())), + ); } pub fn path_fn(f: F) -> impl Function @@ -159,4 +163,37 @@ pub mod path { } Some(ret) } + + /// Removes the extension from a path. + /// eg. `foo/bar.rs` -> `foo/bar` + /// eg. `foo/bar` -> `foo/bar` + /// eg. `foo/bar.rs.bak` -> `foo/bar.rs` + pub fn remove_extension(path: &Path) -> Option { + path.extension() + .map_or(Some(path.into()), |_| path.with_extension("").into()) + } + + #[test] + fn test_remove_extension() { + assert_eq!( + remove_extension(Path::new("foo/bar.rs")), + Some(PathBuf::from("foo/bar")) + ); + assert_eq!( + remove_extension(Path::new("foo/bar")), + Some(PathBuf::from("foo/bar")) + ); + assert_eq!( + remove_extension(Path::new("foo/bar.rs.bak")), + Some(PathBuf::from("foo/bar.rs")) + ); + assert_eq!( + remove_extension(Path::new("foo")), + Some(PathBuf::from("foo")) + ); + assert_eq!( + remove_extension(Path::new("foo.rs")), + Some(PathBuf::from("foo")) + ); + } } From b049439a056a5bda754c6fac931b7ea686143fe2 Mon Sep 17 00:00:00 2001 From: nohehf Date: Mon, 27 May 2024 15:51:15 +0200 Subject: [PATCH 459/500] chore: remove unrelated comment --- languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg | 1 - 1 file changed, 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 751e2a3db..6b5efd35f 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -794,7 +794,6 @@ inherit .parent_module edge @name.def -> @func.call ; Prevent functions defined inside of method bodies from being treated like methods - ; There might be a bug here as calling .self_scope after this, will not fallback to the larger scope let @body.class_self_scope = #null let @body.class_member_attr_scope = #null } From 7621ac28eb34a0c32a7d6cbb5e485f8f306eeea9 Mon Sep 17 00:00:00 2001 From: nohehf Date: Tue, 28 May 2024 10:47:08 +0200 Subject: [PATCH 460/500] feat: add root path and pass file path explicitely --- .../src/stack-graphs.tsg | 5 ++- .../test/root_path.py | 21 ++++++++++++ tree-sitter-stack-graphs/src/cli/index.rs | 11 ++++++- tree-sitter-stack-graphs/src/cli/test.rs | 2 ++ tree-sitter-stack-graphs/src/lib.rs | 27 +++++++++++++-- tree-sitter-stack-graphs/src/loader.rs | 33 ++++++++++++++----- tree-sitter-stack-graphs/src/test.rs | 4 +++ tree-sitter-stack-graphs/tests/it/builder.rs | 27 ++++++++++++--- tree-sitter-stack-graphs/tests/it/main.rs | 17 ++++++++-- tree-sitter-stack-graphs/tests/it/test.rs | 14 +++++++- 10 files changed, 140 insertions(+), 21 deletions(-) create mode 100644 languages/tree-sitter-stack-graphs-python/test/root_path.py diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 6b5efd35f..887e171b3 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -13,6 +13,7 @@ ;; ^^^^^^^^^^^^^^^^ global FILE_PATH +global ROOT_PATH global ROOT_NODE global JUMP_TO_SCOPE_NODE @@ -272,7 +273,9 @@ inherit .parent_module node grandparent_module_ref_node var grandparent_module_ref = grandparent_module_ref_node - scan FILE_PATH { + ; get the file path relative to the root path + let rel_path = (replace FILE_PATH ROOT_PATH "") + scan rel_path { "([^/]+)/" { node def_dot diff --git a/languages/tree-sitter-stack-graphs-python/test/root_path.py b/languages/tree-sitter-stack-graphs-python/test/root_path.py new file mode 100644 index 000000000..23937db7c --- /dev/null +++ b/languages/tree-sitter-stack-graphs-python/test/root_path.py @@ -0,0 +1,21 @@ +# ------ path: foo/bar/module.py -----------# +# ------ global: ROOT_PATH=foo/bar -----------# + +foo = 42 + +# ------ path: foo/bar/baz/module.py -----------# +# ------ global: ROOT_PATH=foo/bar -----------# + +bar = "hello" + +# ------ path: foo/bar/main.py -------------# +# ------ global: ROOT_PATH=foo/bar -----------# + +from module import foo +from baz.module import bar + +print(foo) +# ^ defined: 4, 14 + +print(bar) +# ^ defined: 9, 15 diff --git a/tree-sitter-stack-graphs/src/cli/index.rs b/tree-sitter-stack-graphs/src/cli/index.rs index e8704f99d..5bf48f54f 100644 --- a/tree-sitter-stack-graphs/src/cli/index.rs +++ b/tree-sitter-stack-graphs/src/cli/index.rs @@ -428,10 +428,19 @@ impl<'a> Indexer<'a> { cancellation_flag: &dyn CancellationFlag, ) -> std::result::Result<(), BuildErrorWithSource<'b>> { let relative_source_path = source_path.strip_prefix(source_root).unwrap(); + // here the file should also have stripped the source_root from its path if let Some(lc) = lcs.primary { let globals = Variables::new(); lc.sgl - .build_stack_graph_into(graph, file, source, &globals, cancellation_flag) + .build_stack_graph_into( + graph, + file, + source, + source_path, + source_root, + &globals, + cancellation_flag, + ) .map_err(|inner| BuildErrorWithSource { inner, source_path: source_path.to_path_buf(), diff --git a/tree-sitter-stack-graphs/src/cli/test.rs b/tree-sitter-stack-graphs/src/cli/test.rs index c7f73e7ce..210d79947 100644 --- a/tree-sitter-stack-graphs/src/cli/test.rs +++ b/tree-sitter-stack-graphs/src/cli/test.rs @@ -321,6 +321,8 @@ impl TestArgs { &mut test.graph, test_fragment.file, &test_fragment.source, + &test_fragment.path, + &test_fragment.root_path, &globals, cancellation_flag.as_ref(), ) diff --git a/tree-sitter-stack-graphs/src/lib.rs b/tree-sitter-stack-graphs/src/lib.rs index 86651b6be..aee860420 100644 --- a/tree-sitter-stack-graphs/src/lib.rs +++ b/tree-sitter-stack-graphs/src/lib.rs @@ -438,6 +438,7 @@ static PRECEDENCE_ATTR: &'static str = "precedence"; static ROOT_NODE_VAR: &'static str = "ROOT_NODE"; static JUMP_TO_SCOPE_NODE_VAR: &'static str = "JUMP_TO_SCOPE_NODE"; static FILE_PATH_VAR: &'static str = "FILE_PATH"; +static ROOT_PATH_VAR: &'static str = "ROOT_PATH"; /// Holds information about how to construct stack graphs for a particular language. pub struct StackGraphLanguage { @@ -557,10 +558,12 @@ impl StackGraphLanguage { stack_graph: &'a mut StackGraph, file: Handle, source: &'a str, + source_path: &Path, + source_root: &Path, globals: &'a Variables<'a>, cancellation_flag: &'a dyn CancellationFlag, ) -> Result<(), BuildError> { - self.builder_into_stack_graph(stack_graph, file, source) + self.builder_into_stack_graph(stack_graph, file, source, source_path, source_root) .build(globals, cancellation_flag) } @@ -573,8 +576,10 @@ impl StackGraphLanguage { stack_graph: &'a mut StackGraph, file: Handle, source: &'a str, + source_path: &'a Path, + source_root: &'a Path, ) -> Builder<'a> { - Builder::new(self, stack_graph, file, source) + Builder::new(self, stack_graph, file, source, source_path, source_root) } } @@ -583,6 +588,8 @@ pub struct Builder<'a> { stack_graph: &'a mut StackGraph, file: Handle, source: &'a str, + source_path: &'a Path, + source_root: &'a Path, graph: Graph<'a>, remapped_nodes: HashMap, injected_node_count: usize, @@ -595,6 +602,8 @@ impl<'a> Builder<'a> { stack_graph: &'a mut StackGraph, file: Handle, source: &'a str, + source_path: &'a Path, + source_root: &'a Path, ) -> Self { let span_calculator = SpanCalculator::new(source); Builder { @@ -602,6 +611,8 @@ impl<'a> Builder<'a> { stack_graph, file, source, + source_path, + source_root, graph: Graph::new(), remapped_nodes: HashMap::new(), injected_node_count: 0, @@ -635,23 +646,33 @@ impl<'a> Builder<'a> { let tree = parse_errors.into_tree(); let mut globals = Variables::nested(globals); + if globals.get(&ROOT_NODE_VAR.into()).is_none() { let root_node = self.inject_node(NodeID::root()); globals .add(ROOT_NODE_VAR.into(), root_node.into()) .expect("Failed to set ROOT_NODE"); } + let jump_to_scope_node = self.inject_node(NodeID::jump_to()); globals .add(JUMP_TO_SCOPE_NODE_VAR.into(), jump_to_scope_node.into()) .expect("Failed to set JUMP_TO_SCOPE_NODE"); + if globals.get(&FILE_PATH_VAR.into()).is_none() { - let file_name = self.stack_graph[self.file].to_string(); + let file_name = self.source_path.to_str().unwrap().to_string(); globals .add(FILE_PATH_VAR.into(), file_name.into()) .expect("Failed to set FILE_PATH"); } + if globals.get(&ROOT_PATH_VAR.into()).is_none() { + let root_path = self.source_root.to_str().unwrap().to_string(); + globals + .add(ROOT_PATH_VAR.into(), root_path.into()) + .expect("Failed to set ROOT_PATH"); + } + let mut config = ExecutionConfig::new(&self.sgl.functions, &globals) .lazy(true) .debug_attributes( diff --git a/tree-sitter-stack-graphs/src/loader.rs b/tree-sitter-stack-graphs/src/loader.rs index 9ffc1d674..ced44c2ed 100644 --- a/tree-sitter-stack-graphs/src/loader.rs +++ b/tree-sitter-stack-graphs/src/loader.rs @@ -79,10 +79,14 @@ impl LanguageConfiguration { Loader::load_globals_from_config_str(builtins_config, &mut builtins_globals)?; } let file = builtins.add_file("").unwrap(); + let builtins_path_var = Path::new(""); + let builtins_root = Path::new(""); sgl.build_stack_graph_into( &mut builtins, file, builtins_source, + builtins_path_var, + builtins_root, &builtins_globals, cancellation_flag, ) @@ -325,17 +329,28 @@ impl Loader { graph: &mut StackGraph, cancellation_flag: &dyn CancellationFlag, ) -> Result<(), LoadError<'a>> { - let file = graph.add_file(&path.to_string_lossy()).unwrap(); + let file_name = path.to_string_lossy(); + let file: stack_graphs::arena::Handle = + graph.add_file(&file_name).unwrap(); + let builtins_root = Path::new(""); let mut globals = Variables::new(); Self::load_globals_from_config_str(&config, &mut globals)?; - sgl.build_stack_graph_into(graph, file, &source, &globals, cancellation_flag) - .map_err(|err| LoadError::Builtins { - inner: err, - source_path: path.to_path_buf(), - source, - tsg_path: sgl.tsg_path.to_path_buf(), - tsg: sgl.tsg_source.clone(), - })?; + sgl.build_stack_graph_into( + graph, + file, + &source, + path, + builtins_root, + &globals, + cancellation_flag, + ) + .map_err(|err| LoadError::Builtins { + inner: err, + source_path: path.to_path_buf(), + source, + tsg_path: sgl.tsg_path.to_path_buf(), + tsg: sgl.tsg_source.clone(), + })?; return Ok(()); } diff --git a/tree-sitter-stack-graphs/src/test.rs b/tree-sitter-stack-graphs/src/test.rs index 236e254c5..554783b5f 100644 --- a/tree-sitter-stack-graphs/src/test.rs +++ b/tree-sitter-stack-graphs/src/test.rs @@ -157,6 +157,7 @@ pub struct Test { pub struct TestFragment { pub file: Handle, pub path: PathBuf, + pub root_path: PathBuf, pub source: String, pub assertions: Vec, pub globals: HashMap, @@ -180,6 +181,7 @@ impl Test { let mut prev_source = String::new(); let mut line_files = Vec::new(); let mut line_count = 0; + let default_root_path = PathBuf::from(""); for (current_line_number, current_line) in PositionedSubstring::lines_iter(source).enumerate() { @@ -202,6 +204,7 @@ impl Test { fragments.push(TestFragment { file, path: current_path, + root_path: default_root_path.clone(), source: current_source, assertions: Vec::new(), globals: current_globals, @@ -254,6 +257,7 @@ impl Test { fragments.push(TestFragment { file, path: current_path, + root_path: default_root_path.clone(), source: current_source, assertions: Vec::new(), globals: current_globals, diff --git a/tree-sitter-stack-graphs/tests/it/builder.rs b/tree-sitter-stack-graphs/tests/it/builder.rs index 661e8b973..31dc46994 100644 --- a/tree-sitter-stack-graphs/tests/it/builder.rs +++ b/tree-sitter-stack-graphs/tests/it/builder.rs @@ -5,6 +5,8 @@ // Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. // ------------------------------------------------------------------------------------------------ +use std::path::Path; + use stack_graphs::graph::StackGraph; use tree_sitter_graph::Variables; use tree_sitter_stack_graphs::NoCancellation; @@ -22,15 +24,27 @@ fn can_support_preexisting_nodes() { "#; let python = "pass"; + let file_name = "test.py"; + let source_path = Path::new(file_name); + let source_root = Path::new(""); + let mut graph = StackGraph::new(); - let file = graph.get_or_create_file("test.py"); + let file = graph.get_or_create_file(file_name); let node_id = graph.new_node_id(file); let _preexisting_node = graph.add_scope_node(node_id, true).unwrap(); let globals = Variables::new(); let language = StackGraphLanguage::from_str(tree_sitter_python::language(), tsg).unwrap(); language - .build_stack_graph_into(&mut graph, file, python, &globals, &NoCancellation) + .build_stack_graph_into( + &mut graph, + file, + python, + source_path, + source_root, + &globals, + &NoCancellation, + ) .expect("Failed to build graph"); } @@ -45,13 +59,18 @@ fn can_support_injected_nodes() { "#; let python = "pass"; + let file_name = "test.py"; + let source_path = Path::new(file_name); + let source_root = Path::new(""); + let mut graph = StackGraph::new(); - let file = graph.get_or_create_file("test.py"); + let file = graph.get_or_create_file(file_name); let node_id = graph.new_node_id(file); let _preexisting_node = graph.add_scope_node(node_id, true).unwrap(); let language = StackGraphLanguage::from_str(tree_sitter_python::language(), tsg).unwrap(); - let mut builder = language.builder_into_stack_graph(&mut graph, file, python); + let mut builder = + language.builder_into_stack_graph(&mut graph, file, python, source_path, source_root); let mut globals = Variables::new(); globals diff --git a/tree-sitter-stack-graphs/tests/it/main.rs b/tree-sitter-stack-graphs/tests/it/main.rs index c1e37a40e..9d430bb73 100644 --- a/tree-sitter-stack-graphs/tests/it/main.rs +++ b/tree-sitter-stack-graphs/tests/it/main.rs @@ -5,6 +5,8 @@ // Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. // ------------------------------------------------------------------------------------------------ +use std::path::Path; + use stack_graphs::arena::Handle; use stack_graphs::graph::File; use stack_graphs::graph::StackGraph; @@ -23,11 +25,22 @@ pub(self) fn build_stack_graph( python_source: &str, tsg_source: &str, ) -> Result<(StackGraph, Handle), BuildError> { + let file_name = "test.py"; + let source_path = Path::new(file_name); + let source_root = Path::new(""); let language = StackGraphLanguage::from_str(tree_sitter_python::language(), tsg_source).unwrap(); let mut graph = StackGraph::new(); - let file = graph.get_or_create_file("test.py"); + let file = graph.get_or_create_file(file_name); let globals = Variables::new(); - language.build_stack_graph_into(&mut graph, file, python_source, &globals, &NoCancellation)?; + language.build_stack_graph_into( + &mut graph, + file, + python_source, + source_path, + source_root, + &globals, + &NoCancellation, + )?; Ok((graph, file)) } diff --git a/tree-sitter-stack-graphs/tests/it/test.rs b/tree-sitter-stack-graphs/tests/it/test.rs index 98ec3ab96..89ae7b279 100644 --- a/tree-sitter-stack-graphs/tests/it/test.rs +++ b/tree-sitter-stack-graphs/tests/it/test.rs @@ -68,12 +68,22 @@ fn build_stack_graph_into( graph: &mut StackGraph, file: Handle, python_source: &str, + source_path: &Path, + source_root: &Path, tsg_source: &str, globals: &Variables, ) -> Result<(), BuildError> { let language = StackGraphLanguage::from_str(tree_sitter_python::language(), tsg_source).unwrap(); - language.build_stack_graph_into(graph, file, python_source, globals, &NoCancellation)?; + language.build_stack_graph_into( + graph, + file, + python_source, + source_path, + source_root, + globals, + &NoCancellation, + )?; Ok(()) } @@ -102,6 +112,8 @@ fn check_test( &mut test.graph, fragments.file, &fragments.source, + &fragments.path, + &fragments.root_path, tsg_source, &globals, ) From c43fa8b1af2a5ced2174059d41d4b0f2b8da3983 Mon Sep 17 00:00:00 2001 From: nohehf Date: Thu, 30 May 2024 11:36:09 +0200 Subject: [PATCH 461/500] feat: use replace instead of custom function --- .../src/stack-graphs.tsg | 2 +- tree-sitter-stack-graphs/src/functions.rs | 37 ------------------- 2 files changed, 1 insertion(+), 38 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg index 7e6359280..b7478b4e4 100644 --- a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg @@ -541,7 +541,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n ; module reference var mod_scope = mod_ref__ns ; normalize path and remove the extension as we want to match 'foo', 'foo.js', 'foo.ts', etc. - scan (path-remove-ext (path-normalize mod_path)) { + scan (path-normalize (replace mod_path "\.(js|ts|jsx|tsx)$" "")) { "([^/]+)/?" { node mod_ref attr (mod_ref) push_symbol = $1 diff --git a/tree-sitter-stack-graphs/src/functions.rs b/tree-sitter-stack-graphs/src/functions.rs index e1f9e94e5..9082ba427 100644 --- a/tree-sitter-stack-graphs/src/functions.rs +++ b/tree-sitter-stack-graphs/src/functions.rs @@ -43,10 +43,6 @@ pub mod path { path_fn(|p| normalize(p).map(|p| p.as_os_str().to_os_string())), ); functions.add("path-split".into(), PathSplit); - functions.add( - "path-remove-ext".into(), - path_fn(|p| remove_extension(p).map(|p| p.as_os_str().to_os_string())), - ); } pub fn path_fn(f: F) -> impl Function @@ -163,37 +159,4 @@ pub mod path { } Some(ret) } - - /// Removes the extension from a path. - /// eg. `foo/bar.rs` -> `foo/bar` - /// eg. `foo/bar` -> `foo/bar` - /// eg. `foo/bar.rs.bak` -> `foo/bar.rs` - pub fn remove_extension(path: &Path) -> Option { - path.extension() - .map_or(Some(path.into()), |_| path.with_extension("").into()) - } - - #[test] - fn test_remove_extension() { - assert_eq!( - remove_extension(Path::new("foo/bar.rs")), - Some(PathBuf::from("foo/bar")) - ); - assert_eq!( - remove_extension(Path::new("foo/bar")), - Some(PathBuf::from("foo/bar")) - ); - assert_eq!( - remove_extension(Path::new("foo/bar.rs.bak")), - Some(PathBuf::from("foo/bar.rs")) - ); - assert_eq!( - remove_extension(Path::new("foo")), - Some(PathBuf::from("foo")) - ); - assert_eq!( - remove_extension(Path::new("foo.rs")), - Some(PathBuf::from("foo")) - ); - } } From b3260536a1002743a9a393a64ce8fd33ca859b70 Mon Sep 17 00:00:00 2001 From: nohehf Date: Thu, 30 May 2024 12:17:15 +0200 Subject: [PATCH 462/500] feat: pass paths in globals --- .../src/stack-graphs.tsg | 2 +- tree-sitter-stack-graphs/src/cli/index.rs | 23 +++++----- tree-sitter-stack-graphs/src/cli/test.rs | 12 ++++- tree-sitter-stack-graphs/src/lib.rs | 31 +++---------- tree-sitter-stack-graphs/src/loader.rs | 44 ++++++++++--------- tree-sitter-stack-graphs/src/test.rs | 4 -- tree-sitter-stack-graphs/tests/it/builder.rs | 13 +----- tree-sitter-stack-graphs/tests/it/main.rs | 23 +++++----- tree-sitter-stack-graphs/tests/it/test.rs | 14 +----- 9 files changed, 66 insertions(+), 100 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg index 887e171b3..5fb407ae8 100644 --- a/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-python/src/stack-graphs.tsg @@ -13,7 +13,7 @@ ;; ^^^^^^^^^^^^^^^^ global FILE_PATH -global ROOT_PATH +global ROOT_PATH = "" global ROOT_NODE global JUMP_TO_SCOPE_NODE diff --git a/tree-sitter-stack-graphs/src/cli/index.rs b/tree-sitter-stack-graphs/src/cli/index.rs index 5bf48f54f..6425d8ca7 100644 --- a/tree-sitter-stack-graphs/src/cli/index.rs +++ b/tree-sitter-stack-graphs/src/cli/index.rs @@ -42,6 +42,7 @@ use crate::BuildError; use crate::CancelAfterDuration; use crate::CancellationFlag; use crate::NoCancellation; +use crate::{FILE_PATH_VAR, ROOT_PATH_VAR}; #[derive(Args)] pub struct IndexArgs { @@ -428,19 +429,19 @@ impl<'a> Indexer<'a> { cancellation_flag: &dyn CancellationFlag, ) -> std::result::Result<(), BuildErrorWithSource<'b>> { let relative_source_path = source_path.strip_prefix(source_root).unwrap(); - // here the file should also have stripped the source_root from its path if let Some(lc) = lcs.primary { - let globals = Variables::new(); + let mut globals = Variables::new(); + + globals + .add(FILE_PATH_VAR.into(), source_path.to_str().unwrap().into()) + .expect("failed to add file path variable"); + + globals + .add(ROOT_PATH_VAR.into(), source_root.to_str().unwrap().into()) + .expect("failed to add root path variable"); + lc.sgl - .build_stack_graph_into( - graph, - file, - source, - source_path, - source_root, - &globals, - cancellation_flag, - ) + .build_stack_graph_into(graph, file, source, &globals, cancellation_flag) .map_err(|inner| BuildErrorWithSource { inner, source_path: source_path.to_path_buf(), diff --git a/tree-sitter-stack-graphs/src/cli/test.rs b/tree-sitter-stack-graphs/src/cli/test.rs index 210d79947..6ae04114c 100644 --- a/tree-sitter-stack-graphs/src/cli/test.rs +++ b/tree-sitter-stack-graphs/src/cli/test.rs @@ -43,6 +43,7 @@ use crate::test::Test; use crate::test::TestResult; use crate::CancelAfterDuration; use crate::CancellationFlag; +use crate::FILE_PATH_VAR; #[derive(Args)] #[clap(after_help = r#"PATH SPECIFICATIONS: @@ -316,13 +317,20 @@ impl TestArgs { &mut Some(test_fragment.source.as_ref()), )? { globals.clear(); + + // Add FILE_PATH to variables + globals + .add( + FILE_PATH_VAR.into(), + test_fragment.path.to_str().unwrap().into(), + ) + .expect("failed to add file path variable"); + test_fragment.add_globals_to(&mut globals); lc.sgl.build_stack_graph_into( &mut test.graph, test_fragment.file, &test_fragment.source, - &test_fragment.path, - &test_fragment.root_path, &globals, cancellation_flag.as_ref(), ) diff --git a/tree-sitter-stack-graphs/src/lib.rs b/tree-sitter-stack-graphs/src/lib.rs index aee860420..8a02b0d58 100644 --- a/tree-sitter-stack-graphs/src/lib.rs +++ b/tree-sitter-stack-graphs/src/lib.rs @@ -558,12 +558,10 @@ impl StackGraphLanguage { stack_graph: &'a mut StackGraph, file: Handle, source: &'a str, - source_path: &Path, - source_root: &Path, globals: &'a Variables<'a>, cancellation_flag: &'a dyn CancellationFlag, ) -> Result<(), BuildError> { - self.builder_into_stack_graph(stack_graph, file, source, source_path, source_root) + self.builder_into_stack_graph(stack_graph, file, source) .build(globals, cancellation_flag) } @@ -576,10 +574,8 @@ impl StackGraphLanguage { stack_graph: &'a mut StackGraph, file: Handle, source: &'a str, - source_path: &'a Path, - source_root: &'a Path, ) -> Builder<'a> { - Builder::new(self, stack_graph, file, source, source_path, source_root) + Builder::new(self, stack_graph, file, source) } } @@ -588,8 +584,6 @@ pub struct Builder<'a> { stack_graph: &'a mut StackGraph, file: Handle, source: &'a str, - source_path: &'a Path, - source_root: &'a Path, graph: Graph<'a>, remapped_nodes: HashMap, injected_node_count: usize, @@ -602,8 +596,6 @@ impl<'a> Builder<'a> { stack_graph: &'a mut StackGraph, file: Handle, source: &'a str, - source_path: &'a Path, - source_root: &'a Path, ) -> Self { let span_calculator = SpanCalculator::new(source); Builder { @@ -611,8 +603,6 @@ impl<'a> Builder<'a> { stack_graph, file, source, - source_path, - source_root, graph: Graph::new(), remapped_nodes: HashMap::new(), injected_node_count: 0, @@ -659,19 +649,10 @@ impl<'a> Builder<'a> { .add(JUMP_TO_SCOPE_NODE_VAR.into(), jump_to_scope_node.into()) .expect("Failed to set JUMP_TO_SCOPE_NODE"); - if globals.get(&FILE_PATH_VAR.into()).is_none() { - let file_name = self.source_path.to_str().unwrap().to_string(); - globals - .add(FILE_PATH_VAR.into(), file_name.into()) - .expect("Failed to set FILE_PATH"); - } - - if globals.get(&ROOT_PATH_VAR.into()).is_none() { - let root_path = self.source_root.to_str().unwrap().to_string(); - globals - .add(ROOT_PATH_VAR.into(), root_path.into()) - .expect("Failed to set ROOT_PATH"); - } + // FILE_PATH is mandatory + globals + .get(&FILE_PATH_VAR.into()) + .expect("FILE_PATH not set"); let mut config = ExecutionConfig::new(&self.sgl.functions, &globals) .lazy(true) diff --git a/tree-sitter-stack-graphs/src/loader.rs b/tree-sitter-stack-graphs/src/loader.rs index ced44c2ed..b0d6d1875 100644 --- a/tree-sitter-stack-graphs/src/loader.rs +++ b/tree-sitter-stack-graphs/src/loader.rs @@ -29,6 +29,7 @@ use tree_sitter_loader::Loader as TsLoader; use crate::CancellationFlag; use crate::FileAnalyzer; use crate::StackGraphLanguage; +use crate::FILE_PATH_VAR; pub static DEFAULT_TSG_PATHS: Lazy> = Lazy::new(|| vec![LoadPath::Grammar("queries/stack-graphs".into())]); @@ -75,18 +76,23 @@ impl LanguageConfiguration { let mut builtins = StackGraph::new(); if let Some((builtins_path, builtins_source)) = builtins_source { let mut builtins_globals = Variables::new(); + + let builtins_path_var = Path::new(""); + builtins_globals + .add( + FILE_PATH_VAR.into(), + builtins_path_var.to_str().unwrap().into(), + ) + .expect("failed to add file path variable"); + if let Some(builtins_config) = builtins_config { Loader::load_globals_from_config_str(builtins_config, &mut builtins_globals)?; } let file = builtins.add_file("").unwrap(); - let builtins_path_var = Path::new(""); - let builtins_root = Path::new(""); sgl.build_stack_graph_into( &mut builtins, file, builtins_source, - builtins_path_var, - builtins_root, &builtins_globals, cancellation_flag, ) @@ -332,25 +338,21 @@ impl Loader { let file_name = path.to_string_lossy(); let file: stack_graphs::arena::Handle = graph.add_file(&file_name).unwrap(); - let builtins_root = Path::new(""); let mut globals = Variables::new(); + + globals + .add(FILE_PATH_VAR.into(), path.to_str().unwrap().into()) + .expect("failed to add file path variable"); + Self::load_globals_from_config_str(&config, &mut globals)?; - sgl.build_stack_graph_into( - graph, - file, - &source, - path, - builtins_root, - &globals, - cancellation_flag, - ) - .map_err(|err| LoadError::Builtins { - inner: err, - source_path: path.to_path_buf(), - source, - tsg_path: sgl.tsg_path.to_path_buf(), - tsg: sgl.tsg_source.clone(), - })?; + sgl.build_stack_graph_into(graph, file, &source, &globals, cancellation_flag) + .map_err(|err| LoadError::Builtins { + inner: err, + source_path: path.to_path_buf(), + source, + tsg_path: sgl.tsg_path.to_path_buf(), + tsg: sgl.tsg_source.clone(), + })?; return Ok(()); } diff --git a/tree-sitter-stack-graphs/src/test.rs b/tree-sitter-stack-graphs/src/test.rs index 554783b5f..236e254c5 100644 --- a/tree-sitter-stack-graphs/src/test.rs +++ b/tree-sitter-stack-graphs/src/test.rs @@ -157,7 +157,6 @@ pub struct Test { pub struct TestFragment { pub file: Handle, pub path: PathBuf, - pub root_path: PathBuf, pub source: String, pub assertions: Vec, pub globals: HashMap, @@ -181,7 +180,6 @@ impl Test { let mut prev_source = String::new(); let mut line_files = Vec::new(); let mut line_count = 0; - let default_root_path = PathBuf::from(""); for (current_line_number, current_line) in PositionedSubstring::lines_iter(source).enumerate() { @@ -204,7 +202,6 @@ impl Test { fragments.push(TestFragment { file, path: current_path, - root_path: default_root_path.clone(), source: current_source, assertions: Vec::new(), globals: current_globals, @@ -257,7 +254,6 @@ impl Test { fragments.push(TestFragment { file, path: current_path, - root_path: default_root_path.clone(), source: current_source, assertions: Vec::new(), globals: current_globals, diff --git a/tree-sitter-stack-graphs/tests/it/builder.rs b/tree-sitter-stack-graphs/tests/it/builder.rs index 31dc46994..a87b80559 100644 --- a/tree-sitter-stack-graphs/tests/it/builder.rs +++ b/tree-sitter-stack-graphs/tests/it/builder.rs @@ -36,15 +36,7 @@ fn can_support_preexisting_nodes() { let globals = Variables::new(); let language = StackGraphLanguage::from_str(tree_sitter_python::language(), tsg).unwrap(); language - .build_stack_graph_into( - &mut graph, - file, - python, - source_path, - source_root, - &globals, - &NoCancellation, - ) + .build_stack_graph_into(&mut graph, file, python, &globals, &NoCancellation) .expect("Failed to build graph"); } @@ -69,8 +61,7 @@ fn can_support_injected_nodes() { let _preexisting_node = graph.add_scope_node(node_id, true).unwrap(); let language = StackGraphLanguage::from_str(tree_sitter_python::language(), tsg).unwrap(); - let mut builder = - language.builder_into_stack_graph(&mut graph, file, python, source_path, source_root); + let mut builder = language.builder_into_stack_graph(&mut graph, file, python); let mut globals = Variables::new(); globals diff --git a/tree-sitter-stack-graphs/tests/it/main.rs b/tree-sitter-stack-graphs/tests/it/main.rs index 9d430bb73..687564e1e 100644 --- a/tree-sitter-stack-graphs/tests/it/main.rs +++ b/tree-sitter-stack-graphs/tests/it/main.rs @@ -15,6 +15,8 @@ use tree_sitter_stack_graphs::BuildError; use tree_sitter_stack_graphs::NoCancellation; use tree_sitter_stack_graphs::StackGraphLanguage; +static FILE_PATH_VAR: &'static str = "FILE_PATH"; + mod builder; mod edges; mod loader; @@ -26,21 +28,18 @@ pub(self) fn build_stack_graph( tsg_source: &str, ) -> Result<(StackGraph, Handle), BuildError> { let file_name = "test.py"; - let source_path = Path::new(file_name); - let source_root = Path::new(""); let language = StackGraphLanguage::from_str(tree_sitter_python::language(), tsg_source).unwrap(); let mut graph = StackGraph::new(); let file = graph.get_or_create_file(file_name); - let globals = Variables::new(); - language.build_stack_graph_into( - &mut graph, - file, - python_source, - source_path, - source_root, - &globals, - &NoCancellation, - )?; + let mut globals = Variables::new(); + let source_path = Path::new(file_name); + + // The FILE_PATH_VAR is not accessible here + globals + .add(FILE_PATH_VAR.into(), source_path.to_str().unwrap().into()) + .expect("failed to add file path variable"); + + language.build_stack_graph_into(&mut graph, file, python_source, &globals, &NoCancellation)?; Ok((graph, file)) } diff --git a/tree-sitter-stack-graphs/tests/it/test.rs b/tree-sitter-stack-graphs/tests/it/test.rs index 89ae7b279..98ec3ab96 100644 --- a/tree-sitter-stack-graphs/tests/it/test.rs +++ b/tree-sitter-stack-graphs/tests/it/test.rs @@ -68,22 +68,12 @@ fn build_stack_graph_into( graph: &mut StackGraph, file: Handle, python_source: &str, - source_path: &Path, - source_root: &Path, tsg_source: &str, globals: &Variables, ) -> Result<(), BuildError> { let language = StackGraphLanguage::from_str(tree_sitter_python::language(), tsg_source).unwrap(); - language.build_stack_graph_into( - graph, - file, - python_source, - source_path, - source_root, - globals, - &NoCancellation, - )?; + language.build_stack_graph_into(graph, file, python_source, globals, &NoCancellation)?; Ok(()) } @@ -112,8 +102,6 @@ fn check_test( &mut test.graph, fragments.file, &fragments.source, - &fragments.path, - &fragments.root_path, tsg_source, &globals, ) From 8a98dce32fee057bc4d754ebc85055fecbbda0a1 Mon Sep 17 00:00:00 2001 From: nohehf Date: Thu, 30 May 2024 12:33:37 +0200 Subject: [PATCH 463/500] fix: add missing paths --- tree-sitter-stack-graphs/tests/it/builder.rs | 15 ++++++++++----- tree-sitter-stack-graphs/tests/it/test.rs | 10 ++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/tree-sitter-stack-graphs/tests/it/builder.rs b/tree-sitter-stack-graphs/tests/it/builder.rs index a87b80559..b0dad5449 100644 --- a/tree-sitter-stack-graphs/tests/it/builder.rs +++ b/tree-sitter-stack-graphs/tests/it/builder.rs @@ -14,6 +14,7 @@ use tree_sitter_stack_graphs::StackGraphLanguage; use crate::edges::check_stack_graph_edges; use crate::nodes::check_stack_graph_nodes; +use crate::FILE_PATH_VAR; #[test] fn can_support_preexisting_nodes() { @@ -25,15 +26,17 @@ fn can_support_preexisting_nodes() { let python = "pass"; let file_name = "test.py"; - let source_path = Path::new(file_name); - let source_root = Path::new(""); let mut graph = StackGraph::new(); let file = graph.get_or_create_file(file_name); let node_id = graph.new_node_id(file); let _preexisting_node = graph.add_scope_node(node_id, true).unwrap(); - let globals = Variables::new(); + let mut globals = Variables::new(); + globals + .add(FILE_PATH_VAR.into(), file_name.into()) + .expect("failed to add file path variable"); + let language = StackGraphLanguage::from_str(tree_sitter_python::language(), tsg).unwrap(); language .build_stack_graph_into(&mut graph, file, python, &globals, &NoCancellation) @@ -52,8 +55,6 @@ fn can_support_injected_nodes() { let python = "pass"; let file_name = "test.py"; - let source_path = Path::new(file_name); - let source_root = Path::new(""); let mut graph = StackGraph::new(); let file = graph.get_or_create_file(file_name); @@ -64,6 +65,10 @@ fn can_support_injected_nodes() { let mut builder = language.builder_into_stack_graph(&mut graph, file, python); let mut globals = Variables::new(); + globals + .add(FILE_PATH_VAR.into(), file_name.into()) + .expect("failed to add file path variable"); + globals .add("EXT_NODE".into(), builder.inject_node(node_id).into()) .expect("Failed to add EXT_NODE variable"); diff --git a/tree-sitter-stack-graphs/tests/it/test.rs b/tree-sitter-stack-graphs/tests/it/test.rs index 98ec3ab96..9624439c5 100644 --- a/tree-sitter-stack-graphs/tests/it/test.rs +++ b/tree-sitter-stack-graphs/tests/it/test.rs @@ -5,6 +5,7 @@ // Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. // ------------------------------------------------------------------------------------------------ +use crate::FILE_PATH_VAR; use once_cell::sync::Lazy; use pretty_assertions::assert_eq; use stack_graphs::arena::Handle; @@ -94,9 +95,18 @@ fn check_test( expected_successes + expected_failures, assertion_count, ); + let mut globals = Variables::new(); for fragments in &test.fragments { globals.clear(); + + globals + .add( + FILE_PATH_VAR.into(), + fragments.path.to_str().unwrap().into(), + ) + .expect("failed to add file path variable"); + fragments.add_globals_to(&mut globals); build_stack_graph_into( &mut test.graph, From ad4d517bf52b0615d7798f106e77bbd592ac694f Mon Sep 17 00:00:00 2001 From: nohehf Date: Sat, 1 Jun 2024 14:47:32 +0200 Subject: [PATCH 464/500] chore: clenup after review --- tree-sitter-stack-graphs/src/lib.rs | 19 ++++++++++--------- tree-sitter-stack-graphs/src/loader.rs | 12 +++++------- tree-sitter-stack-graphs/tests/it/builder.rs | 5 +---- tree-sitter-stack-graphs/tests/it/main.rs | 4 +--- 4 files changed, 17 insertions(+), 23 deletions(-) diff --git a/tree-sitter-stack-graphs/src/lib.rs b/tree-sitter-stack-graphs/src/lib.rs index 8a02b0d58..1a3e344b1 100644 --- a/tree-sitter-stack-graphs/src/lib.rs +++ b/tree-sitter-stack-graphs/src/lib.rs @@ -435,10 +435,16 @@ static SCOPE_ATTRS: Lazy> = static PRECEDENCE_ATTR: &'static str = "precedence"; // Global variables -static ROOT_NODE_VAR: &'static str = "ROOT_NODE"; -static JUMP_TO_SCOPE_NODE_VAR: &'static str = "JUMP_TO_SCOPE_NODE"; -static FILE_PATH_VAR: &'static str = "FILE_PATH"; -static ROOT_PATH_VAR: &'static str = "ROOT_PATH"; +/// Name of the variable used to pass the root node. +pub const ROOT_NODE_VAR: &'static str = "ROOT_NODE"; +/// Name of the variable used to pass the jump-to-scope node. +pub const JUMP_TO_SCOPE_NODE_VAR: &'static str = "JUMP_TO_SCOPE_NODE"; +/// Name of the variable used to pass the file path. +/// If a root path is given, it should be a descendant the root path. +pub const FILE_PATH_VAR: &'static str = "FILE_PATH"; +/// Name of the variable used to pass the root path. +/// If given, should be an ancestor of the file path. +pub const ROOT_PATH_VAR: &'static str = "ROOT_PATH"; /// Holds information about how to construct stack graphs for a particular language. pub struct StackGraphLanguage { @@ -649,11 +655,6 @@ impl<'a> Builder<'a> { .add(JUMP_TO_SCOPE_NODE_VAR.into(), jump_to_scope_node.into()) .expect("Failed to set JUMP_TO_SCOPE_NODE"); - // FILE_PATH is mandatory - globals - .get(&FILE_PATH_VAR.into()) - .expect("FILE_PATH not set"); - let mut config = ExecutionConfig::new(&self.sgl.functions, &globals) .lazy(true) .debug_attributes( diff --git a/tree-sitter-stack-graphs/src/loader.rs b/tree-sitter-stack-graphs/src/loader.rs index b0d6d1875..f0ab9891c 100644 --- a/tree-sitter-stack-graphs/src/loader.rs +++ b/tree-sitter-stack-graphs/src/loader.rs @@ -31,6 +31,8 @@ use crate::FileAnalyzer; use crate::StackGraphLanguage; use crate::FILE_PATH_VAR; +const BUILTINS_FILENAME: &str = ""; + pub static DEFAULT_TSG_PATHS: Lazy> = Lazy::new(|| vec![LoadPath::Grammar("queries/stack-graphs".into())]); pub static DEFAULT_BUILTINS_PATHS: Lazy> = @@ -77,18 +79,14 @@ impl LanguageConfiguration { if let Some((builtins_path, builtins_source)) = builtins_source { let mut builtins_globals = Variables::new(); - let builtins_path_var = Path::new(""); builtins_globals - .add( - FILE_PATH_VAR.into(), - builtins_path_var.to_str().unwrap().into(), - ) + .add(FILE_PATH_VAR.into(), BUILTINS_FILENAME.into()) .expect("failed to add file path variable"); if let Some(builtins_config) = builtins_config { Loader::load_globals_from_config_str(builtins_config, &mut builtins_globals)?; } - let file = builtins.add_file("").unwrap(); + let file = builtins.add_file(BUILTINS_FILENAME).unwrap(); sgl.build_stack_graph_into( &mut builtins, file, @@ -341,7 +339,7 @@ impl Loader { let mut globals = Variables::new(); globals - .add(FILE_PATH_VAR.into(), path.to_str().unwrap().into()) + .add(FILE_PATH_VAR.into(), BUILTINS_FILENAME.into()) .expect("failed to add file path variable"); Self::load_globals_from_config_str(&config, &mut globals)?; diff --git a/tree-sitter-stack-graphs/tests/it/builder.rs b/tree-sitter-stack-graphs/tests/it/builder.rs index b0dad5449..acc012eaa 100644 --- a/tree-sitter-stack-graphs/tests/it/builder.rs +++ b/tree-sitter-stack-graphs/tests/it/builder.rs @@ -4,17 +4,14 @@ // Licensed under either of Apache License, Version 2.0, or MIT license, at your option. // Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. // ------------------------------------------------------------------------------------------------ - -use std::path::Path; - use stack_graphs::graph::StackGraph; use tree_sitter_graph::Variables; use tree_sitter_stack_graphs::NoCancellation; use tree_sitter_stack_graphs::StackGraphLanguage; +use tree_sitter_stack_graphs::FILE_PATH_VAR; use crate::edges::check_stack_graph_edges; use crate::nodes::check_stack_graph_nodes; -use crate::FILE_PATH_VAR; #[test] fn can_support_preexisting_nodes() { diff --git a/tree-sitter-stack-graphs/tests/it/main.rs b/tree-sitter-stack-graphs/tests/it/main.rs index 687564e1e..33ee19241 100644 --- a/tree-sitter-stack-graphs/tests/it/main.rs +++ b/tree-sitter-stack-graphs/tests/it/main.rs @@ -14,8 +14,7 @@ use tree_sitter_graph::Variables; use tree_sitter_stack_graphs::BuildError; use tree_sitter_stack_graphs::NoCancellation; use tree_sitter_stack_graphs::StackGraphLanguage; - -static FILE_PATH_VAR: &'static str = "FILE_PATH"; +use tree_sitter_stack_graphs::FILE_PATH_VAR; mod builder; mod edges; @@ -35,7 +34,6 @@ pub(self) fn build_stack_graph( let mut globals = Variables::new(); let source_path = Path::new(file_name); - // The FILE_PATH_VAR is not accessible here globals .add(FILE_PATH_VAR.into(), source_path.to_str().unwrap().into()) .expect("failed to add file path variable"); From 5ba472ab81783908360aaf3d1b8b15d2e2b85534 Mon Sep 17 00:00:00 2001 From: nohehf Date: Sat, 1 Jun 2024 23:31:00 +0200 Subject: [PATCH 465/500] style: style --- tree-sitter-stack-graphs/src/loader.rs | 3 +-- tree-sitter-stack-graphs/tests/it/builder.rs | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tree-sitter-stack-graphs/src/loader.rs b/tree-sitter-stack-graphs/src/loader.rs index f0ab9891c..e0e1d236d 100644 --- a/tree-sitter-stack-graphs/src/loader.rs +++ b/tree-sitter-stack-graphs/src/loader.rs @@ -334,8 +334,7 @@ impl Loader { cancellation_flag: &dyn CancellationFlag, ) -> Result<(), LoadError<'a>> { let file_name = path.to_string_lossy(); - let file: stack_graphs::arena::Handle = - graph.add_file(&file_name).unwrap(); + let file = graph.add_file(&file_name).unwrap(); let mut globals = Variables::new(); globals diff --git a/tree-sitter-stack-graphs/tests/it/builder.rs b/tree-sitter-stack-graphs/tests/it/builder.rs index acc012eaa..14476111e 100644 --- a/tree-sitter-stack-graphs/tests/it/builder.rs +++ b/tree-sitter-stack-graphs/tests/it/builder.rs @@ -4,6 +4,7 @@ // Licensed under either of Apache License, Version 2.0, or MIT license, at your option. // Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details. // ------------------------------------------------------------------------------------------------ + use stack_graphs::graph::StackGraph; use tree_sitter_graph::Variables; use tree_sitter_stack_graphs::NoCancellation; From ba1d3cd125520583a4e56f5e11c92e34f1f855cf Mon Sep 17 00:00:00 2001 From: nohehf Date: Sun, 2 Jun 2024 00:09:42 +0200 Subject: [PATCH 466/500] fix: conditionnaly load FILE_PATH --- tree-sitter-stack-graphs/src/loader.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/tree-sitter-stack-graphs/src/loader.rs b/tree-sitter-stack-graphs/src/loader.rs index e0e1d236d..d382f72c9 100644 --- a/tree-sitter-stack-graphs/src/loader.rs +++ b/tree-sitter-stack-graphs/src/loader.rs @@ -79,13 +79,16 @@ impl LanguageConfiguration { if let Some((builtins_path, builtins_source)) = builtins_source { let mut builtins_globals = Variables::new(); - builtins_globals - .add(FILE_PATH_VAR.into(), BUILTINS_FILENAME.into()) - .expect("failed to add file path variable"); - if let Some(builtins_config) = builtins_config { Loader::load_globals_from_config_str(builtins_config, &mut builtins_globals)?; } + + if builtins_globals.get(&FILE_PATH_VAR.into()).is_some() { + builtins_globals + .add(FILE_PATH_VAR.into(), BUILTINS_FILENAME.into()) + .expect("failed to add file path variable"); + } + let file = builtins.add_file(BUILTINS_FILENAME).unwrap(); sgl.build_stack_graph_into( &mut builtins, @@ -337,11 +340,14 @@ impl Loader { let file = graph.add_file(&file_name).unwrap(); let mut globals = Variables::new(); - globals - .add(FILE_PATH_VAR.into(), BUILTINS_FILENAME.into()) - .expect("failed to add file path variable"); - Self::load_globals_from_config_str(&config, &mut globals)?; + + if globals.get(&FILE_PATH_VAR.into()).is_some() { + globals + .add(FILE_PATH_VAR.into(), BUILTINS_FILENAME.into()) + .expect("failed to add file path variable"); + } + sgl.build_stack_graph_into(graph, file, &source, &globals, cancellation_flag) .map_err(|err| LoadError::Builtins { inner: err, From a297647992b4a2f37e4aa11a3411039849d80a65 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Sun, 2 Jun 2024 11:31:51 +0200 Subject: [PATCH 467/500] Invert condition --- tree-sitter-stack-graphs/src/loader.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tree-sitter-stack-graphs/src/loader.rs b/tree-sitter-stack-graphs/src/loader.rs index d382f72c9..d03be0f93 100644 --- a/tree-sitter-stack-graphs/src/loader.rs +++ b/tree-sitter-stack-graphs/src/loader.rs @@ -83,7 +83,7 @@ impl LanguageConfiguration { Loader::load_globals_from_config_str(builtins_config, &mut builtins_globals)?; } - if builtins_globals.get(&FILE_PATH_VAR.into()).is_some() { + if builtins_globals.get(&FILE_PATH_VAR.into()).is_none() { builtins_globals .add(FILE_PATH_VAR.into(), BUILTINS_FILENAME.into()) .expect("failed to add file path variable"); From 6bcb5a3c3e39ed16db9ceaf2ae3eac03f4e337ce Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Sun, 2 Jun 2024 11:32:08 +0200 Subject: [PATCH 468/500] Invery condition --- tree-sitter-stack-graphs/src/loader.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tree-sitter-stack-graphs/src/loader.rs b/tree-sitter-stack-graphs/src/loader.rs index d03be0f93..977522528 100644 --- a/tree-sitter-stack-graphs/src/loader.rs +++ b/tree-sitter-stack-graphs/src/loader.rs @@ -342,7 +342,7 @@ impl Loader { Self::load_globals_from_config_str(&config, &mut globals)?; - if globals.get(&FILE_PATH_VAR.into()).is_some() { + if globals.get(&FILE_PATH_VAR.into()).is_none() { globals .add(FILE_PATH_VAR.into(), BUILTINS_FILENAME.into()) .expect("failed to add file path variable"); From c7f9fd9118b0642ae800d4c42237be577afa7d41 Mon Sep 17 00:00:00 2001 From: nohehf Date: Sun, 2 Jun 2024 16:34:44 +0200 Subject: [PATCH 469/500] fix: check that FILE_PATH variable is none everywhere --- tree-sitter-stack-graphs/src/cli/test.rs | 18 ++++++++++-------- tree-sitter-stack-graphs/tests/it/test.rs | 17 ++++++++++------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/tree-sitter-stack-graphs/src/cli/test.rs b/tree-sitter-stack-graphs/src/cli/test.rs index 6ae04114c..790a6c245 100644 --- a/tree-sitter-stack-graphs/src/cli/test.rs +++ b/tree-sitter-stack-graphs/src/cli/test.rs @@ -318,15 +318,17 @@ impl TestArgs { )? { globals.clear(); - // Add FILE_PATH to variables - globals - .add( - FILE_PATH_VAR.into(), - test_fragment.path.to_str().unwrap().into(), - ) - .expect("failed to add file path variable"); - test_fragment.add_globals_to(&mut globals); + + if globals.get(&FILE_PATH_VAR.into()).is_none() { + globals + .add( + FILE_PATH_VAR.into(), + test_fragment.path.to_str().unwrap().into(), + ) + .expect("failed to add file path variable"); + } + lc.sgl.build_stack_graph_into( &mut test.graph, test_fragment.file, diff --git a/tree-sitter-stack-graphs/tests/it/test.rs b/tree-sitter-stack-graphs/tests/it/test.rs index 9624439c5..4c630d57a 100644 --- a/tree-sitter-stack-graphs/tests/it/test.rs +++ b/tree-sitter-stack-graphs/tests/it/test.rs @@ -100,14 +100,17 @@ fn check_test( for fragments in &test.fragments { globals.clear(); - globals - .add( - FILE_PATH_VAR.into(), - fragments.path.to_str().unwrap().into(), - ) - .expect("failed to add file path variable"); - fragments.add_globals_to(&mut globals); + + if globals.get(&FILE_PATH_VAR.into()).is_none() { + globals + .add( + FILE_PATH_VAR.into(), + fragments.path.to_str().unwrap().into(), + ) + .expect("failed to add file path variable"); + } + build_stack_graph_into( &mut test.graph, fragments.file, From 20ad4befe1f8083ddcccf74e2e4b2fe261287fce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristia=CC=81n=20Arenas=20Ulloa?= Date: Fri, 28 Jun 2024 20:47:14 -0400 Subject: [PATCH 470/500] Update `tree-sitter-java` from `0.20.0` to `0.20.2` --- languages/tree-sitter-stack-graphs-java/Cargo.toml | 2 +- languages/tree-sitter-stack-graphs-java/src/stack-graphs.tsg | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-java/Cargo.toml b/languages/tree-sitter-stack-graphs-java/Cargo.toml index 13e9e7340..d50465aae 100644 --- a/languages/tree-sitter-stack-graphs-java/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-java/Cargo.toml @@ -40,7 +40,7 @@ cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"] [dependencies] anyhow = { version = "1.0", optional = true } clap = { version = "4", features = ["derive"], optional = true } -tree-sitter-java = { version = "=0.20.0" } +tree-sitter-java = { version = "=0.20.2" } tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs" } [dev-dependencies] diff --git a/languages/tree-sitter-stack-graphs-java/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-java/src/stack-graphs.tsg index 5f3c72466..cfeab55de 100644 --- a/languages/tree-sitter-stack-graphs-java/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-java/src/stack-graphs.tsg @@ -1078,6 +1078,10 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @child.lexical_scope -> @expr.lexical_scope } +(condition (_) @child) @expr { + edge @child.lexical_scope -> @expr.lexical_scope +} + ;; ============= ;; Expressions ;; ============= @@ -1107,6 +1111,7 @@ attribute node_symbol = node => symbol = (source-text node), source_n (this) ; (identifier) (parenthesized_expression) + (condition) (object_creation_expression) (field_access) (array_access) From 14b7556df1353773cc04b8efa0c745ab8424e201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristia=CC=81n=20Arenas=20Ulloa?= Date: Mon, 1 Jul 2024 18:14:54 -0400 Subject: [PATCH 471/500] Update `tree-sitter-javascript` from `0.20.3` to `0.20.4` --- languages/tree-sitter-stack-graphs-javascript/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml index b56925c75..49dc9890d 100644 --- a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -32,7 +32,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" stack-graphs = { version = "0.13", path = "../../stack-graphs" } tree-sitter-graph = "0.11.2" -tree-sitter-javascript = "=0.20.3" +tree-sitter-javascript = "=0.20.4" tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs" } [dev-dependencies] From f715ed1ba214cc91bbfb3da8a0fc8650635db264 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 9 Jul 2024 15:09:05 +0200 Subject: [PATCH 472/500] Release stack-graphs v0.14.0 --- languages/tree-sitter-stack-graphs-javascript/Cargo.toml | 2 +- languages/tree-sitter-stack-graphs-typescript/Cargo.toml | 2 +- stack-graphs/CHANGELOG.md | 6 ++++++ stack-graphs/Cargo.toml | 2 +- stack-graphs/README.md | 2 +- tree-sitter-stack-graphs/Cargo.toml | 2 +- 6 files changed, 11 insertions(+), 5 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml index 49dc9890d..07c21edb8 100644 --- a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -30,7 +30,7 @@ anyhow = { version = "1.0", optional = true } clap = { version = "4", optional = true } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -stack-graphs = { version = "0.13", path = "../../stack-graphs" } +stack-graphs = { path = "../../stack-graphs" } tree-sitter-graph = "0.11.2" tree-sitter-javascript = "=0.20.4" tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs" } diff --git a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml index e40c12625..988007874 100644 --- a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml @@ -32,7 +32,7 @@ clap = { version = "4", optional = true } glob = "0.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -stack-graphs = { version = "0.13", path = "../../stack-graphs" } +stack-graphs = { path = "../../stack-graphs" } tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs" } tree-sitter-typescript = "=0.20.2" tsconfig = "0.1.0" diff --git a/stack-graphs/CHANGELOG.md b/stack-graphs/CHANGELOG.md index fa051176d..eeaae0730 100644 --- a/stack-graphs/CHANGELOG.md +++ b/stack-graphs/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v0.14.0 -- 2024-07-09 + +### Changed + +- The method `StackGraph::add_from_graph` returns the handles of the newly added files. + ## v0.13.0 -- 2024-03-06 ### Added diff --git a/stack-graphs/Cargo.toml b/stack-graphs/Cargo.toml index 2e40b76eb..354adaa2b 100644 --- a/stack-graphs/Cargo.toml +++ b/stack-graphs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "stack-graphs" -version = "0.13.0" +version = "0.14.0" description = "Name binding for arbitrary programming languages" homepage = "https://github.com/github/stack-graphs/tree/main/stack-graphs" repository = "https://github.com/github/stack-graphs/" diff --git a/stack-graphs/README.md b/stack-graphs/README.md index 0c6a9e878..69efa5bd8 100644 --- a/stack-graphs/README.md +++ b/stack-graphs/README.md @@ -9,7 +9,7 @@ To use this library, add the following to your `Cargo.toml`: ``` toml [dependencies] -stack-graphs = "0.13" +stack-graphs = "0.14" ``` Check out our [documentation](https://docs.rs/stack-graphs/) for more details on diff --git a/tree-sitter-stack-graphs/Cargo.toml b/tree-sitter-stack-graphs/Cargo.toml index d1b0fc1c6..ed6fb44e0 100644 --- a/tree-sitter-stack-graphs/Cargo.toml +++ b/tree-sitter-stack-graphs/Cargo.toml @@ -69,7 +69,7 @@ regex = "1" rust-ini = "0.18" serde_json = { version="1.0", optional=true } sha1 = { version="0.10", optional=true } -stack-graphs = { version="0.13", path="../stack-graphs" } +stack-graphs = { path="../stack-graphs" } thiserror = "1.0" time = { version = "0.3", optional = true } tokio = { version = "1.26", optional = true, features = ["io-std", "rt", "rt-multi-thread"] } From 106c728e1da798e410e999473c4e02cf3e5f9d1d Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 9 Jul 2024 15:47:20 +0200 Subject: [PATCH 473/500] Release tree-sitter-stack-graphs v0.9.0 Includes a bit of code cleanup. --- .../tree-sitter-stack-graphs-java/Cargo.toml | 4 +-- .../tree-sitter-stack-graphs-java/rust/lib.rs | 2 -- .../Cargo.toml | 4 +-- .../rust/lib.rs | 3 +- .../Cargo.toml | 4 +-- .../rust/lib.rs | 3 -- .../Cargo.toml | 4 +-- .../rust/lib.rs | 2 -- tree-sitter-stack-graphs/CHANGELOG.md | 13 +++++++- tree-sitter-stack-graphs/Cargo.toml | 2 +- tree-sitter-stack-graphs/README.md | 2 +- tree-sitter-stack-graphs/npm/.gitignore | 4 --- tree-sitter-stack-graphs/npm/README.md | 13 -------- tree-sitter-stack-graphs/npm/cli.js | 15 ---------- tree-sitter-stack-graphs/npm/install.js | 30 ------------------- tree-sitter-stack-graphs/npm/package.json | 26 ---------------- tree-sitter-stack-graphs/src/cli/init.rs | 3 -- tree-sitter-stack-graphs/src/cli/test.rs | 14 ++++----- tree-sitter-stack-graphs/src/lib.rs | 12 ++++---- tree-sitter-stack-graphs/src/loader.rs | 16 ++++------ tree-sitter-stack-graphs/tests/it/test.rs | 14 ++++----- 21 files changed, 46 insertions(+), 144 deletions(-) delete mode 100644 tree-sitter-stack-graphs/npm/.gitignore delete mode 100644 tree-sitter-stack-graphs/npm/README.md delete mode 100755 tree-sitter-stack-graphs/npm/cli.js delete mode 100644 tree-sitter-stack-graphs/npm/install.js delete mode 100644 tree-sitter-stack-graphs/npm/package.json diff --git a/languages/tree-sitter-stack-graphs-java/Cargo.toml b/languages/tree-sitter-stack-graphs-java/Cargo.toml index d50465aae..21a856760 100644 --- a/languages/tree-sitter-stack-graphs-java/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-java/Cargo.toml @@ -41,8 +41,8 @@ cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"] anyhow = { version = "1.0", optional = true } clap = { version = "4", features = ["derive"], optional = true } tree-sitter-java = { version = "=0.20.2" } -tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs" } +tree-sitter-stack-graphs = { path = "../../tree-sitter-stack-graphs" } [dev-dependencies] anyhow = { version = "1.0" } -tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs", features = ["cli"] } +tree-sitter-stack-graphs = { path = "../../tree-sitter-stack-graphs", features = ["cli"] } diff --git a/languages/tree-sitter-stack-graphs-java/rust/lib.rs b/languages/tree-sitter-stack-graphs-java/rust/lib.rs index 942785044..14016b614 100644 --- a/languages/tree-sitter-stack-graphs-java/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-java/rust/lib.rs @@ -14,8 +14,6 @@ pub const STACK_GRAPHS_BUILTINS_PATH: &str = "src/builtins.java"; /// The stack graphs builtins source for this language. pub const STACK_GRAPHS_BUILTINS_SOURCE: &str = include_str!("../src/builtins.java"); -/// The name of the file path global variable -pub const FILE_PATH_VAR: &str = "FILE_PATH"; /// The name of the project name global variable pub const PROJECT_NAME_VAR: &str = "PROJECT_NAME"; diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml index 07c21edb8..6593327f6 100644 --- a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -33,8 +33,8 @@ serde_json = "1.0" stack-graphs = { path = "../../stack-graphs" } tree-sitter-graph = "0.11.2" tree-sitter-javascript = "=0.20.4" -tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs" } +tree-sitter-stack-graphs = { path = "../../tree-sitter-stack-graphs" } [dev-dependencies] anyhow = "1.0" -tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs", features = ["cli"] } +tree-sitter-stack-graphs = { path = "../../tree-sitter-stack-graphs", features = ["cli"] } diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/lib.rs b/languages/tree-sitter-stack-graphs-javascript/rust/lib.rs index 61f113149..718db8a2e 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/lib.rs @@ -26,8 +26,7 @@ pub const STACK_GRAPHS_BUILTINS_PATH: &str = "src/builtins.js"; /// The stack graphs builtins source for this language. pub const STACK_GRAPHS_BUILTINS_SOURCE: &str = include_str!("../src/builtins.js"); -/// The name of the file path global variable. -pub const FILE_PATH_VAR: &str = "FILE_PATH"; +/// The name of the project name global variable pub const PROJECT_NAME_VAR: &str = "PROJECT_NAME"; pub fn language_configuration(cancellation_flag: &dyn CancellationFlag) -> LanguageConfiguration { diff --git a/languages/tree-sitter-stack-graphs-python/Cargo.toml b/languages/tree-sitter-stack-graphs-python/Cargo.toml index 17cfa3d72..b57c039a8 100644 --- a/languages/tree-sitter-stack-graphs-python/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-python/Cargo.toml @@ -30,9 +30,9 @@ cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"] [dependencies] anyhow = { version = "1.0", optional = true } clap = { version = "4", optional = true, features = ["derive"] } -tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs" } +tree-sitter-stack-graphs = { path = "../../tree-sitter-stack-graphs" } tree-sitter-python = "=0.20.4" [dev-dependencies] anyhow = "1.0" -tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs", features = ["cli"] } +tree-sitter-stack-graphs = { path = "../../tree-sitter-stack-graphs", features = ["cli"] } diff --git a/languages/tree-sitter-stack-graphs-python/rust/lib.rs b/languages/tree-sitter-stack-graphs-python/rust/lib.rs index 74176a475..e0ffb40ec 100644 --- a/languages/tree-sitter-stack-graphs-python/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-python/rust/lib.rs @@ -21,9 +21,6 @@ pub const STACK_GRAPHS_BUILTINS_PATH: &str = "src/builtins.py"; /// The stack graphs builtins source for this language. pub const STACK_GRAPHS_BUILTINS_SOURCE: &str = include_str!("../src/builtins.py"); -/// The name of the file path global variable. -pub const FILE_PATH_VAR: &str = "FILE_PATH"; - pub fn language_configuration(cancellation_flag: &dyn CancellationFlag) -> LanguageConfiguration { try_language_configuration(cancellation_flag).unwrap_or_else(|err| panic!("{}", err)) } diff --git a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml index 988007874..1d7df3dbc 100644 --- a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml @@ -33,13 +33,13 @@ glob = "0.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" stack-graphs = { path = "../../stack-graphs" } -tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs" } +tree-sitter-stack-graphs = { path = "../../tree-sitter-stack-graphs" } tree-sitter-typescript = "=0.20.2" tsconfig = "0.1.0" [dev-dependencies] anyhow = { version = "1.0" } -tree-sitter-stack-graphs = { version = "0.8", path = "../../tree-sitter-stack-graphs", features = ["cli"] } +tree-sitter-stack-graphs = { path = "../../tree-sitter-stack-graphs", features = ["cli"] } [build-dependencies] anyhow = { version = "1.0" } diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs index 396fbc68b..2fa484a0a 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs @@ -31,8 +31,6 @@ pub const STACK_GRAPHS_BUILTINS_PATH: &str = "src/builtins.ts"; /// The stack graphs builtins source for this language pub const STACK_GRAPHS_BUILTINS_SOURCE: &str = include_str!("../src/builtins.ts"); -/// The name of the file path global variable -pub const FILE_PATH_VAR: &str = "FILE_PATH"; /// The name of the project name global variable pub const PROJECT_NAME_VAR: &str = "PROJECT_NAME"; diff --git a/tree-sitter-stack-graphs/CHANGELOG.md b/tree-sitter-stack-graphs/CHANGELOG.md index e7538592a..faa61295a 100644 --- a/tree-sitter-stack-graphs/CHANGELOG.md +++ b/tree-sitter-stack-graphs/CHANGELOG.md @@ -5,18 +5,29 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v0.8.2 -- unreleased +## v0.9.0 -- 2024-07-09 + + +### Library + +- New crate-level constants `FILE_PATH_VAR` and `ROOT_PATH_VAR` standardize the TSG global variable names to use for the file and root path. +- The file path variable will only use the filename set in the stack graph if no value was explicitly set. ### CLI #### Added - Tests run faster for languages with builtins sources by caching the partial paths for the builtins. +- Indexing will set a value for the root path variable that is passed to TSG. The value is based on the directory that was provided on the command line. #### Changed - Failure to index a file will not abort indexing anymore, but simply mark the file as failed, as we already do for files with parse errors. +#### Removed + +- The NPM distribution has been deprecated. + ## v0.8.1 -- 2024-03-06 The `stack-graphs` dependency was updated to `v0.13` to fix the build problems of the `v0.8.0` release. diff --git a/tree-sitter-stack-graphs/Cargo.toml b/tree-sitter-stack-graphs/Cargo.toml index ed6fb44e0..327ff4d47 100644 --- a/tree-sitter-stack-graphs/Cargo.toml +++ b/tree-sitter-stack-graphs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tree-sitter-stack-graphs" -version = "0.8.2" +version = "0.9.0" description = "Create stack graphs using tree-sitter parsers" homepage = "https://github.com/github/stack-graphs/tree/main/tree-sitter-stack-graphs" repository = "https://github.com/github/stack-graphs/" diff --git a/tree-sitter-stack-graphs/README.md b/tree-sitter-stack-graphs/README.md index ad1287ad5..a4e52add3 100644 --- a/tree-sitter-stack-graphs/README.md +++ b/tree-sitter-stack-graphs/README.md @@ -14,7 +14,7 @@ To use this library, add the following to your `Cargo.toml`: ```toml [dependencies] -tree-sitter-stack-graphs = "0.8" +tree-sitter-stack-graphs = "0.9" ``` Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs/*/) for more details on how to use this library. diff --git a/tree-sitter-stack-graphs/npm/.gitignore b/tree-sitter-stack-graphs/npm/.gitignore deleted file mode 100644 index 02b3615e1..000000000 --- a/tree-sitter-stack-graphs/npm/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/.crates.toml -/.crates2.json -/bin/ -/package-lock.json diff --git a/tree-sitter-stack-graphs/npm/README.md b/tree-sitter-stack-graphs/npm/README.md deleted file mode 100644 index 27dd321be..000000000 --- a/tree-sitter-stack-graphs/npm/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# tree-sitter-stack-graphs - -This package provides a convenient way to install the [tree-sitter-stack-graphs](https://crates.io/crates/tree-sitter-stack-graphs) CLI in an NPM project. - -Add it as a dev dependency to an existing project using: - - npm i -D tree-sitter-stack-graphs - -It is also possible to invoke it directly using: - - npx tree-sitter-stack-graphs - -See the tree-sitter-stack-graphs [documentation](https://crates.io/crates/tree-sitter-stack-graphs) for details on usage. diff --git a/tree-sitter-stack-graphs/npm/cli.js b/tree-sitter-stack-graphs/npm/cli.js deleted file mode 100755 index f4d654e15..000000000 --- a/tree-sitter-stack-graphs/npm/cli.js +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env node - -const spawn = require("child_process").spawn; -const path = require("path"); - -const tssg = process.platform === "win32" - ? "tree-sitter-stack-graphs.exe" - : "tree-sitter-stack-graphs"; - -spawn( - path.join(__dirname, "bin", tssg), process.argv.slice(2), - { - "stdio": "inherit" - }, -).on('close', process.exit); diff --git a/tree-sitter-stack-graphs/npm/install.js b/tree-sitter-stack-graphs/npm/install.js deleted file mode 100644 index 6ac20756b..000000000 --- a/tree-sitter-stack-graphs/npm/install.js +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env node - -const child_process = require("child_process"); -const packageJSON = require("./package.json"); - -const cargo = process.platform === "win32" - ? "cargo.exe" - : "cargo"; - -try { - child_process.execSync(cargo); -} catch (error) { - console.error(error.message); - console.error("Failed to execute Cargo. Cargo needs to be available to install this package!"); - process.exit(1); -} - -child_process.spawn( - cargo, [ - "install", - "--quiet", - "--root", ".", - "--version", "^"+packageJSON.version, - "--features", "cli", - packageJSON.name, - ], - { - "stdio": "inherit" - }, -).on('close', process.exit); diff --git a/tree-sitter-stack-graphs/npm/package.json b/tree-sitter-stack-graphs/npm/package.json deleted file mode 100644 index a49ec5fad..000000000 --- a/tree-sitter-stack-graphs/npm/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "tree-sitter-stack-graphs", - "version": "0.7.0", - "description": "Create stack graphs using tree-sitter parsers", - "homepage": "https://github.com/github/stack-graphs/tree/main/tree-sitter-stack-graphs", - "repository": { - "type": "git", - "url": "https://github.com/github/stack-graphs.git" - }, - "keywords": [ - "tree-sitter", - "stack-graphs" - ], - "license": "MIT OR Apache-2.0", - "author": "GitHub ", - "contributors": [ - "Douglas Creager ", - "Hendrik van Antwerpen " - ], - "bin": { - "tree-sitter-stack-graphs": "./cli.js" - }, - "scripts": { - "install": "node install.js" - } -} diff --git a/tree-sitter-stack-graphs/src/cli/init.rs b/tree-sitter-stack-graphs/src/cli/init.rs index df18339aa..f71890390 100644 --- a/tree-sitter-stack-graphs/src/cli/init.rs +++ b/tree-sitter-stack-graphs/src/cli/init.rs @@ -770,9 +770,6 @@ impl ProjectSettings<'_> { /// The stack graphs builtins source for this language. pub const STACK_GRAPHS_BUILTINS_SOURCE: &str = include_str!("../src/builtins.{}"); - /// The name of the file path global variable. - pub const FILE_PATH_VAR: &str = "FILE_PATH"; - pub fn language_configuration(cancellation_flag: &dyn CancellationFlag) -> LanguageConfiguration {{ try_language_configuration(cancellation_flag).unwrap_or_else(|err| panic!("{{}}", err)) }} diff --git a/tree-sitter-stack-graphs/src/cli/test.rs b/tree-sitter-stack-graphs/src/cli/test.rs index 790a6c245..1bff78a48 100644 --- a/tree-sitter-stack-graphs/src/cli/test.rs +++ b/tree-sitter-stack-graphs/src/cli/test.rs @@ -320,14 +320,12 @@ impl TestArgs { test_fragment.add_globals_to(&mut globals); - if globals.get(&FILE_PATH_VAR.into()).is_none() { - globals - .add( - FILE_PATH_VAR.into(), - test_fragment.path.to_str().unwrap().into(), - ) - .expect("failed to add file path variable"); - } + globals + .add( + FILE_PATH_VAR.into(), + test_fragment.path.to_str().unwrap().into(), + ) + .unwrap_or_default(); lc.sgl.build_stack_graph_into( &mut test.graph, diff --git a/tree-sitter-stack-graphs/src/lib.rs b/tree-sitter-stack-graphs/src/lib.rs index 1a3e344b1..717214832 100644 --- a/tree-sitter-stack-graphs/src/lib.rs +++ b/tree-sitter-stack-graphs/src/lib.rs @@ -440,7 +440,7 @@ pub const ROOT_NODE_VAR: &'static str = "ROOT_NODE"; /// Name of the variable used to pass the jump-to-scope node. pub const JUMP_TO_SCOPE_NODE_VAR: &'static str = "JUMP_TO_SCOPE_NODE"; /// Name of the variable used to pass the file path. -/// If a root path is given, it should be a descendant the root path. +/// If a root path is given, it should be a descendant of the root path. pub const FILE_PATH_VAR: &'static str = "FILE_PATH"; /// Name of the variable used to pass the root path. /// If given, should be an ancestor of the file path. @@ -643,12 +643,10 @@ impl<'a> Builder<'a> { let mut globals = Variables::nested(globals); - if globals.get(&ROOT_NODE_VAR.into()).is_none() { - let root_node = self.inject_node(NodeID::root()); - globals - .add(ROOT_NODE_VAR.into(), root_node.into()) - .expect("Failed to set ROOT_NODE"); - } + let root_node = self.inject_node(NodeID::root()); + globals + .add(ROOT_NODE_VAR.into(), root_node.into()) + .unwrap_or_default(); let jump_to_scope_node = self.inject_node(NodeID::jump_to()); globals diff --git a/tree-sitter-stack-graphs/src/loader.rs b/tree-sitter-stack-graphs/src/loader.rs index 977522528..14aa97916 100644 --- a/tree-sitter-stack-graphs/src/loader.rs +++ b/tree-sitter-stack-graphs/src/loader.rs @@ -83,11 +83,9 @@ impl LanguageConfiguration { Loader::load_globals_from_config_str(builtins_config, &mut builtins_globals)?; } - if builtins_globals.get(&FILE_PATH_VAR.into()).is_none() { - builtins_globals - .add(FILE_PATH_VAR.into(), BUILTINS_FILENAME.into()) - .expect("failed to add file path variable"); - } + builtins_globals + .add(FILE_PATH_VAR.into(), BUILTINS_FILENAME.into()) + .unwrap_or_default(); let file = builtins.add_file(BUILTINS_FILENAME).unwrap(); sgl.build_stack_graph_into( @@ -342,11 +340,9 @@ impl Loader { Self::load_globals_from_config_str(&config, &mut globals)?; - if globals.get(&FILE_PATH_VAR.into()).is_none() { - globals - .add(FILE_PATH_VAR.into(), BUILTINS_FILENAME.into()) - .expect("failed to add file path variable"); - } + globals + .add(FILE_PATH_VAR.into(), BUILTINS_FILENAME.into()) + .unwrap_or_default(); sgl.build_stack_graph_into(graph, file, &source, &globals, cancellation_flag) .map_err(|err| LoadError::Builtins { diff --git a/tree-sitter-stack-graphs/tests/it/test.rs b/tree-sitter-stack-graphs/tests/it/test.rs index 4c630d57a..cb1efff4f 100644 --- a/tree-sitter-stack-graphs/tests/it/test.rs +++ b/tree-sitter-stack-graphs/tests/it/test.rs @@ -102,14 +102,12 @@ fn check_test( fragments.add_globals_to(&mut globals); - if globals.get(&FILE_PATH_VAR.into()).is_none() { - globals - .add( - FILE_PATH_VAR.into(), - fragments.path.to_str().unwrap().into(), - ) - .expect("failed to add file path variable"); - } + globals + .add( + FILE_PATH_VAR.into(), + fragments.path.to_str().unwrap().into(), + ) + .unwrap_or_default(); build_stack_graph_into( &mut test.graph, From aff01c50c3d30162004f513573b646b889889fce Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 9 Jul 2024 16:09:19 +0200 Subject: [PATCH 474/500] Release languages - tree-sitter-stack-graphs-java v0.4.0 - tree-sitter-stack-graphs-javascript v0.2.0 - tree-sitter-stack-graphs-python v0.2.0 - tree-sitter-stack-graphs-typescript v0.3.0 --- .../tree-sitter-stack-graphs-java/CHANGELOG.md | 10 ++++++++++ .../tree-sitter-stack-graphs-java/Cargo.toml | 2 +- .../tree-sitter-stack-graphs-java/README.md | 2 +- .../CHANGELOG.md | 6 ++++++ .../Cargo.toml | 2 +- .../README.md | 2 +- .../tree-sitter-stack-graphs-python/CHANGELOG.md | 15 +++++++++++++++ .../tree-sitter-stack-graphs-python/Cargo.toml | 2 +- .../tree-sitter-stack-graphs-python/LICENSE | 0 .../tree-sitter-stack-graphs-python/README.md | 2 +- .../CHANGELOG.md | 16 ++++++++++++++-- .../README.md | 2 +- 12 files changed, 52 insertions(+), 9 deletions(-) delete mode 100644 languages/tree-sitter-stack-graphs-python/LICENSE diff --git a/languages/tree-sitter-stack-graphs-java/CHANGELOG.md b/languages/tree-sitter-stack-graphs-java/CHANGELOG.md index 0f3a4b861..5691a4985 100644 --- a/languages/tree-sitter-stack-graphs-java/CHANGELOG.md +++ b/languages/tree-sitter-stack-graphs-java/CHANGELOG.md @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v0.4.0 -- 2024-07-09 + +### Added + +- Add rules for the `condition` node that was missing. + +### Removed + +- The `FILE_PATH_VAR` constant has been replaced in favor of `tree_sitter_stack_graphs::FILE_PATH_VAR`. + ## v0.3.0 -- 2024-03-06 The `tree-sitter-stack-graphs` is updated to `v0.8`. diff --git a/languages/tree-sitter-stack-graphs-java/Cargo.toml b/languages/tree-sitter-stack-graphs-java/Cargo.toml index 21a856760..27534ef88 100644 --- a/languages/tree-sitter-stack-graphs-java/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-java/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tree-sitter-stack-graphs-java" -version = "0.3.0" +version = "0.4.0" description = "Stack graphs for the Java programming language" homepage = "https://github.com/github/stack-graphs/tree/main/languages/tree-sitter-stack-graphs-java" diff --git a/languages/tree-sitter-stack-graphs-java/README.md b/languages/tree-sitter-stack-graphs-java/README.md index cf16b7dab..69d276118 100644 --- a/languages/tree-sitter-stack-graphs-java/README.md +++ b/languages/tree-sitter-stack-graphs-java/README.md @@ -13,7 +13,7 @@ To use this library, add the following to your `Cargo.toml`: ```toml [dependencies] -tree-sitter-stack-graphs-java = "0.3" +tree-sitter-stack-graphs-java = "0.4" ``` Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-java/*/) for more details on how to use this library. diff --git a/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md b/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md index 2ba28c310..19730aeab 100644 --- a/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md +++ b/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v0.2.0 -- 2024-07-09 + +### Removed + +- The `FILE_PATH_VAR` constant has been replaced in favor of `tree_sitter_stack_graphs::FILE_PATH_VAR`. + ## v0.1.0 -- 2024-03-06 Initial release. diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml index 6593327f6..a4344c0f3 100644 --- a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tree-sitter-stack-graphs-javascript" -version = "0.1.0" +version = "0.2.0" description = "Stack graphs definition for JavaScript using tree-sitter-javascript" readme = "README.md" keywords = ["tree-sitter", "stack-graphs", "javascript"] diff --git a/languages/tree-sitter-stack-graphs-javascript/README.md b/languages/tree-sitter-stack-graphs-javascript/README.md index 04317fbd0..099e633e9 100644 --- a/languages/tree-sitter-stack-graphs-javascript/README.md +++ b/languages/tree-sitter-stack-graphs-javascript/README.md @@ -13,7 +13,7 @@ To use this library, add the following to your `Cargo.toml`: ```toml [dependencies] -tree-sitter-stack-graphs-javascript = "0.1" +tree-sitter-stack-graphs-javascript = "0.2" ``` Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-javascript/*/) for more details on how to use this library. diff --git a/languages/tree-sitter-stack-graphs-python/CHANGELOG.md b/languages/tree-sitter-stack-graphs-python/CHANGELOG.md index 876b16cb9..61e6ca4e9 100644 --- a/languages/tree-sitter-stack-graphs-python/CHANGELOG.md +++ b/languages/tree-sitter-stack-graphs-python/CHANGELOG.md @@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v0.2.0 -- 2024-07-09 + +### Added + +- Added support for root paths. This fixes import problems when indexing using absolute directory paths. + +### Fixed + +- Fixed crash for lambdas with parameters. +- Fixed crash for nested functions definitions. + +### Removed + +- The `FILE_PATH_VAR` constant has been replaced in favor of `tree_sitter_stack_graphs::FILE_PATH_VAR`. + ## v0.1.0 -- 2024-03-06 Initial release. diff --git a/languages/tree-sitter-stack-graphs-python/Cargo.toml b/languages/tree-sitter-stack-graphs-python/Cargo.toml index b57c039a8..38a5a191c 100644 --- a/languages/tree-sitter-stack-graphs-python/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-python/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tree-sitter-stack-graphs-python" -version = "0.1.0" +version = "0.2.0" description = "Stack graphs definition for Python using tree-sitter-python" readme = "README.md" keywords = ["tree-sitter", "stack-graphs", "python"] diff --git a/languages/tree-sitter-stack-graphs-python/LICENSE b/languages/tree-sitter-stack-graphs-python/LICENSE deleted file mode 100644 index e69de29bb..000000000 diff --git a/languages/tree-sitter-stack-graphs-python/README.md b/languages/tree-sitter-stack-graphs-python/README.md index 0393e0004..a313a3799 100644 --- a/languages/tree-sitter-stack-graphs-python/README.md +++ b/languages/tree-sitter-stack-graphs-python/README.md @@ -13,7 +13,7 @@ To use this library, add the following to your `Cargo.toml`: ```toml [dependencies] -tree-sitter-stack-graphs-python = "0.1" +tree-sitter-stack-graphs-python = "0.2" ``` Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-python/*/) for more details on how to use this library. diff --git a/languages/tree-sitter-stack-graphs-typescript/CHANGELOG.md b/languages/tree-sitter-stack-graphs-typescript/CHANGELOG.md index b4260b2a6..47539831f 100644 --- a/languages/tree-sitter-stack-graphs-typescript/CHANGELOG.md +++ b/languages/tree-sitter-stack-graphs-typescript/CHANGELOG.md @@ -5,11 +5,23 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v0.3.0 -- unreleased +## v0.3.0 -- 2024-07-09 ### Added -- Support for TSX. A new language configuration for TSX is available, and TSX is enabled in the CLI next to TypeScript. +- Support for TSX. A new language configuration for TSX is available with `{try_,}language_configuration_tsx`. TSX is enabled in the CLI next to TypeScript. + +### Fixed + +- Imports are more robust to the presence of file extensions in the import name. + +### Changed + +- The functions `{try_,}language_configuration` have been renamed to `{try_,}language_configuration_typescript`. + +### Removed + +- The `FILE_PATH_VAR` constant has been replaced in favor of `tree_sitter_stack_graphs::FILE_PATH_VAR`. ## v0.2.0 -- 2024-03-06 diff --git a/languages/tree-sitter-stack-graphs-typescript/README.md b/languages/tree-sitter-stack-graphs-typescript/README.md index 9b6c82069..46079a19a 100644 --- a/languages/tree-sitter-stack-graphs-typescript/README.md +++ b/languages/tree-sitter-stack-graphs-typescript/README.md @@ -13,7 +13,7 @@ To use this library, add the following to your `Cargo.toml`: ```toml [dependencies] -tree-sitter-stack-graphs-typescript = "0.2" +tree-sitter-stack-graphs-typescript = "0.3" ``` Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-typescript/*/) for more details on how to use this library. From a68b92dde2a39876d4dfdff9fc65a9668afeae63 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 10 Jul 2024 16:44:43 +0200 Subject: [PATCH 475/500] Improve changelog --- tree-sitter-stack-graphs/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tree-sitter-stack-graphs/CHANGELOG.md b/tree-sitter-stack-graphs/CHANGELOG.md index faa61295a..6f6e86f25 100644 --- a/tree-sitter-stack-graphs/CHANGELOG.md +++ b/tree-sitter-stack-graphs/CHANGELOG.md @@ -26,7 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 #### Removed -- The NPM distribution has been deprecated. +- The NPM distribution has been removed. ## v0.8.1 -- 2024-03-06 From 5fcc8517eb3ee045046fd5cff3b7ef79dedc9f4a Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 10 Jul 2024 17:07:22 +0200 Subject: [PATCH 476/500] Remove NPM publish workflow job --- .../publish-tree-sitter-stack-graphs.yml | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/.github/workflows/publish-tree-sitter-stack-graphs.yml b/.github/workflows/publish-tree-sitter-stack-graphs.yml index e9395ab1f..031289464 100644 --- a/.github/workflows/publish-tree-sitter-stack-graphs.yml +++ b/.github/workflows/publish-tree-sitter-stack-graphs.yml @@ -29,31 +29,6 @@ jobs: working-directory: ${{ env.CRATE_DIR }} env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} - publish-npm: - needs: publish-crate - runs-on: ubuntu-latest - env: - PACKAGE_DIR: './tree-sitter-stack-graphs/npm' - steps: - - name: Install Node environment - uses: actions/setup-node@v3 - with: - node-version: 16.x - registry-url: 'https://registry.npmjs.org' - - name: Checkout repository - uses: actions/checkout@v3 - # TODO Verify the package version matches the tag - - name: Install dependencies - run: npm install - working-directory: ${{ env.PACKAGE_DIR }} - - name: Verify package - run: npm publish --dry-run - working-directory: ${{ env.PACKAGE_DIR }} - - name: Publish package - run: npm publish - working-directory: ${{ env.PACKAGE_DIR }} - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} create-release: needs: publish-crate runs-on: ubuntu-latest From 9649181818590f321fd4538e2e0d70edbd903a84 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 10 Jul 2024 17:10:33 +0200 Subject: [PATCH 477/500] Restore versions for path dependencies, which are required to publish the crate --- languages/tree-sitter-stack-graphs-java/Cargo.toml | 2 +- languages/tree-sitter-stack-graphs-javascript/Cargo.toml | 4 ++-- languages/tree-sitter-stack-graphs-python/Cargo.toml | 2 +- languages/tree-sitter-stack-graphs-typescript/Cargo.toml | 4 ++-- stack-graphs/Cargo.toml | 2 +- tree-sitter-stack-graphs/Cargo.toml | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-java/Cargo.toml b/languages/tree-sitter-stack-graphs-java/Cargo.toml index 27534ef88..96a44ab0f 100644 --- a/languages/tree-sitter-stack-graphs-java/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-java/Cargo.toml @@ -41,7 +41,7 @@ cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"] anyhow = { version = "1.0", optional = true } clap = { version = "4", features = ["derive"], optional = true } tree-sitter-java = { version = "=0.20.2" } -tree-sitter-stack-graphs = { path = "../../tree-sitter-stack-graphs" } +tree-sitter-stack-graphs = { version = "0.9", path = "../../tree-sitter-stack-graphs" } # explicit version is required to be able to publish crate [dev-dependencies] anyhow = { version = "1.0" } diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml index a4344c0f3..ca03e2f9b 100644 --- a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -30,10 +30,10 @@ anyhow = { version = "1.0", optional = true } clap = { version = "4", optional = true } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -stack-graphs = { path = "../../stack-graphs" } +stack-graphs = { version = "0.14", path = "../../stack-graphs" } # explicit version is required to be able to publish crate tree-sitter-graph = "0.11.2" tree-sitter-javascript = "=0.20.4" -tree-sitter-stack-graphs = { path = "../../tree-sitter-stack-graphs" } +tree-sitter-stack-graphs = { version = "0.9", path = "../../tree-sitter-stack-graphs" } # explicit version is required to be able to publish crate [dev-dependencies] anyhow = "1.0" diff --git a/languages/tree-sitter-stack-graphs-python/Cargo.toml b/languages/tree-sitter-stack-graphs-python/Cargo.toml index 38a5a191c..53d714719 100644 --- a/languages/tree-sitter-stack-graphs-python/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-python/Cargo.toml @@ -30,7 +30,7 @@ cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"] [dependencies] anyhow = { version = "1.0", optional = true } clap = { version = "4", optional = true, features = ["derive"] } -tree-sitter-stack-graphs = { path = "../../tree-sitter-stack-graphs" } +tree-sitter-stack-graphs = { version = "0.9", path = "../../tree-sitter-stack-graphs" } # explicit version is required to be able to publish crate tree-sitter-python = "=0.20.4" [dev-dependencies] diff --git a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml index 1d7df3dbc..86feee2a1 100644 --- a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml @@ -32,8 +32,8 @@ clap = { version = "4", optional = true } glob = "0.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -stack-graphs = { path = "../../stack-graphs" } -tree-sitter-stack-graphs = { path = "../../tree-sitter-stack-graphs" } +stack-graphs = { version = "0.14", path = "../../stack-graphs" } # explicit version is required to be able to publish crate +tree-sitter-stack-graphs = { version = "0.9", path = "../../tree-sitter-stack-graphs" } # explicit version is required to be able to publish crate tree-sitter-typescript = "=0.20.2" tsconfig = "0.1.0" diff --git a/stack-graphs/Cargo.toml b/stack-graphs/Cargo.toml index 354adaa2b..f114fffdb 100644 --- a/stack-graphs/Cargo.toml +++ b/stack-graphs/Cargo.toml @@ -32,7 +32,7 @@ enumset = "1.1" fxhash = "0.2" itertools = "0.10.2" libc = "0.2" -lsp-positions = { version = "0.3", path = "../lsp-positions" } +lsp-positions = { version = "0.3", path = "../lsp-positions" } # explicit version is required to be able to publish crate rusqlite = { version = "0.28", optional = true, features = ["bundled", "functions"] } serde = { version = "1.0", optional = true, features = ["derive"] } serde_json = { version = "1.0", optional = true } diff --git a/tree-sitter-stack-graphs/Cargo.toml b/tree-sitter-stack-graphs/Cargo.toml index 327ff4d47..0ac84d012 100644 --- a/tree-sitter-stack-graphs/Cargo.toml +++ b/tree-sitter-stack-graphs/Cargo.toml @@ -62,14 +62,14 @@ env_logger = { version = "0.9", optional = true } indoc = { version = "1.0", optional = true } itertools = "0.10" log = "0.4" -lsp-positions = { version="0.3", path="../lsp-positions", features=["tree-sitter"] } +lsp-positions = { version="0.3", path="../lsp-positions", features=["tree-sitter"] } # explicit version is required to be able to publish crate once_cell = "1" pathdiff = { version = "0.2.1", optional = true } regex = "1" rust-ini = "0.18" serde_json = { version="1.0", optional=true } sha1 = { version="0.10", optional=true } -stack-graphs = { path="../stack-graphs" } +stack-graphs = { version = "0.14", path="../stack-graphs" } # explicit version is required to be able to publish crate thiserror = "1.0" time = { version = "0.3", optional = true } tokio = { version = "1.26", optional = true, features = ["io-std", "rt", "rt-multi-thread"] } From a8fe5283413ac79d4188ee2b299f911871d5e86d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 22:20:27 +0000 Subject: [PATCH 478/500] Bump actions/download-artifact Bumps the github_actions group with 1 update in the /.github/workflows directory: [actions/download-artifact](https://github.com/actions/download-artifact). Updates `actions/download-artifact` from 3 to 4.1.7 - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v3...v4.1.7) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-type: direct:production dependency-group: github_actions ... Signed-off-by: dependabot[bot] --- .github/workflows/perf.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/perf.yml b/.github/workflows/perf.yml index 5c4288c84..301dffd92 100644 --- a/.github/workflows/perf.yml +++ b/.github/workflows/perf.yml @@ -233,12 +233,12 @@ jobs: # Download results # - name: Download base results - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4.1.7 with: name: ${{ env.BASE_ARTIFACT }} path: ${{ env.BASE_ARTIFACT }} - name: Download head results - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4.1.7 with: name: ${{ env.HEAD_ARTIFACT }} path: ${{ env.HEAD_ARTIFACT }} From 3090222200a9859619f7b5310b0773bc0d4161d7 Mon Sep 17 00:00:00 2001 From: Bastiaan Marinus van de Weerd Date: Tue, 19 Nov 2024 16:47:44 -0300 Subject: [PATCH 479/500] Fix not defaulting to `Builder::file` for `FILE_PATH`. --- tree-sitter-stack-graphs/src/lib.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tree-sitter-stack-graphs/src/lib.rs b/tree-sitter-stack-graphs/src/lib.rs index 717214832..509e34a58 100644 --- a/tree-sitter-stack-graphs/src/lib.rs +++ b/tree-sitter-stack-graphs/src/lib.rs @@ -653,6 +653,13 @@ impl<'a> Builder<'a> { .add(JUMP_TO_SCOPE_NODE_VAR.into(), jump_to_scope_node.into()) .expect("Failed to set JUMP_TO_SCOPE_NODE"); + if globals.get(&FILE_PATH_VAR.into()).is_none() { + let file_name = self.stack_graph[self.file].to_string(); + globals + .add(FILE_PATH_VAR.into(), file_name.into()) + .expect("Failed to set FILE_PATH"); + } + let mut config = ExecutionConfig::new(&self.sgl.functions, &globals) .lazy(true) .debug_attributes( From c2df61c71ff098bd99a34d297d0cfb6def48f4ef Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 10 Dec 2024 14:51:39 +0100 Subject: [PATCH 480/500] Upgrade tree-sitter dependency to 0.24 --- .../CHANGELOG.md | 6 + .../tree-sitter-stack-graphs-java/Cargo.toml | 6 +- .../tree-sitter-stack-graphs-java/README.md | 2 +- .../tree-sitter-stack-graphs-java/rust/lib.rs | 2 +- .../src/stack-graphs.tsg | 5 - .../CHANGELOG.md | 6 + .../Cargo.toml | 8 +- .../README.md | 2 +- .../rust/lib.rs | 2 +- .../CHANGELOG.md | 6 + .../Cargo.toml | 6 +- .../tree-sitter-stack-graphs-python/README.md | 2 +- .../rust/lib.rs | 2 +- .../Cargo.toml | 4 +- .../rust/lib.rs | 4 +- .../src/stack-graphs.tsg | 163 ++++++++---------- ...e_name.tsx => jsx_namespace_name.tsx.skip} | 0 ...mespace.ts => very-deep-namespace.ts.skip} | 0 ...namespace-by-fully-qualified-name.ts.skip} | 0 ...namespace-by-fully-qualified-name.ts.skip} | 0 lsp-positions/CHANGELOG.md | 4 + lsp-positions/Cargo.toml | 4 +- tree-sitter-stack-graphs/CHANGELOG.md | 5 +- tree-sitter-stack-graphs/Cargo.toml | 14 +- tree-sitter-stack-graphs/README.md | 2 +- tree-sitter-stack-graphs/src/cli/init.rs | 2 +- tree-sitter-stack-graphs/src/cli/load.rs | 2 +- tree-sitter-stack-graphs/src/cli/lsp.rs | 19 -- tree-sitter-stack-graphs/src/cli/match.rs | 2 +- tree-sitter-stack-graphs/src/cli/parse.rs | 4 +- tree-sitter-stack-graphs/src/cli/test.rs | 2 +- tree-sitter-stack-graphs/src/lib.rs | 10 +- tree-sitter-stack-graphs/src/loader.rs | 32 ++-- tree-sitter-stack-graphs/tests/it/builder.rs | 4 +- tree-sitter-stack-graphs/tests/it/loader.rs | 11 +- tree-sitter-stack-graphs/tests/it/main.rs | 2 +- tree-sitter-stack-graphs/tests/it/test.rs | 2 +- 37 files changed, 169 insertions(+), 178 deletions(-) rename languages/tree-sitter-stack-graphs-typescript/test/jsx/{jsx_namespace_name.tsx => jsx_namespace_name.tsx.skip} (100%) rename languages/tree-sitter-stack-graphs-typescript/test/modules/{very-deep-namespace.ts => very-deep-namespace.ts.skip} (100%) rename languages/tree-sitter-stack-graphs-typescript/test/statements/{refer-to-interface-in-nested-namespace-by-fully-qualified-name.ts => refer-to-interface-in-nested-namespace-by-fully-qualified-name.ts.skip} (100%) rename languages/tree-sitter-stack-graphs-typescript/test/statements/{refer-to-interface-in-qualified-namespace-by-fully-qualified-name.ts => refer-to-interface-in-qualified-namespace-by-fully-qualified-name.ts.skip} (100%) diff --git a/languages/tree-sitter-stack-graphs-java/CHANGELOG.md b/languages/tree-sitter-stack-graphs-java/CHANGELOG.md index 5691a4985..23400faf0 100644 --- a/languages/tree-sitter-stack-graphs-java/CHANGELOG.md +++ b/languages/tree-sitter-stack-graphs-java/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v0.5.0 -- Unreleased + +- The `tree-sitter-stack-graphs` dependency is updated to version 0.10. + +- The `tree-sitter-java` dependency is updated to version 0.23.4. + ## v0.4.0 -- 2024-07-09 ### Added diff --git a/languages/tree-sitter-stack-graphs-java/Cargo.toml b/languages/tree-sitter-stack-graphs-java/Cargo.toml index 96a44ab0f..0ad8cb687 100644 --- a/languages/tree-sitter-stack-graphs-java/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-java/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tree-sitter-stack-graphs-java" -version = "0.4.0" +version = "0.5.0" description = "Stack graphs for the Java programming language" homepage = "https://github.com/github/stack-graphs/tree/main/languages/tree-sitter-stack-graphs-java" @@ -40,8 +40,8 @@ cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"] [dependencies] anyhow = { version = "1.0", optional = true } clap = { version = "4", features = ["derive"], optional = true } -tree-sitter-java = { version = "=0.20.2" } -tree-sitter-stack-graphs = { version = "0.9", path = "../../tree-sitter-stack-graphs" } # explicit version is required to be able to publish crate +tree-sitter-java = { version = "=0.23.4" } +tree-sitter-stack-graphs = { version = "0.10", path = "../../tree-sitter-stack-graphs" } # explicit version is required to be able to publish crate [dev-dependencies] anyhow = { version = "1.0" } diff --git a/languages/tree-sitter-stack-graphs-java/README.md b/languages/tree-sitter-stack-graphs-java/README.md index 69d276118..97820ed3f 100644 --- a/languages/tree-sitter-stack-graphs-java/README.md +++ b/languages/tree-sitter-stack-graphs-java/README.md @@ -13,7 +13,7 @@ To use this library, add the following to your `Cargo.toml`: ```toml [dependencies] -tree-sitter-stack-graphs-java = "0.4" +tree-sitter-stack-graphs-java = "0.5" ``` Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-java/*/) for more details on how to use this library. diff --git a/languages/tree-sitter-stack-graphs-java/rust/lib.rs b/languages/tree-sitter-stack-graphs-java/rust/lib.rs index 14016b614..9b2cb39c8 100644 --- a/languages/tree-sitter-stack-graphs-java/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-java/rust/lib.rs @@ -25,7 +25,7 @@ pub fn try_language_configuration( cancellation_flag: &dyn CancellationFlag, ) -> Result { LanguageConfiguration::from_sources( - tree_sitter_java::language(), + tree_sitter_java::LANGUAGE.into(), Some(String::from("source.java")), None, vec![String::from("java")], diff --git a/languages/tree-sitter-stack-graphs-java/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-java/src/stack-graphs.tsg index cfeab55de..5f3c72466 100644 --- a/languages/tree-sitter-stack-graphs-java/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-java/src/stack-graphs.tsg @@ -1078,10 +1078,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n edge @child.lexical_scope -> @expr.lexical_scope } -(condition (_) @child) @expr { - edge @child.lexical_scope -> @expr.lexical_scope -} - ;; ============= ;; Expressions ;; ============= @@ -1111,7 +1107,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n (this) ; (identifier) (parenthesized_expression) - (condition) (object_creation_expression) (field_access) (array_access) diff --git a/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md b/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md index 19730aeab..10f85abdd 100644 --- a/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md +++ b/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v0.3.0 -- Unreleased + +- The `tree-sitter-stack-graphs` dependency is updated to version 0.10. + +- The `tree-sitter-javascript` dependency is updated to version 0.23.1. + ## v0.2.0 -- 2024-07-09 ### Removed diff --git a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml index ca03e2f9b..d1206c6e5 100644 --- a/languages/tree-sitter-stack-graphs-javascript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-javascript/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tree-sitter-stack-graphs-javascript" -version = "0.2.0" +version = "0.3.0" description = "Stack graphs definition for JavaScript using tree-sitter-javascript" readme = "README.md" keywords = ["tree-sitter", "stack-graphs", "javascript"] @@ -31,9 +31,9 @@ clap = { version = "4", optional = true } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" stack-graphs = { version = "0.14", path = "../../stack-graphs" } # explicit version is required to be able to publish crate -tree-sitter-graph = "0.11.2" -tree-sitter-javascript = "=0.20.4" -tree-sitter-stack-graphs = { version = "0.9", path = "../../tree-sitter-stack-graphs" } # explicit version is required to be able to publish crate +tree-sitter-graph = "0.12" +tree-sitter-javascript = "=0.23.1" +tree-sitter-stack-graphs = { version = "0.10", path = "../../tree-sitter-stack-graphs" } # explicit version is required to be able to publish crate [dev-dependencies] anyhow = "1.0" diff --git a/languages/tree-sitter-stack-graphs-javascript/README.md b/languages/tree-sitter-stack-graphs-javascript/README.md index 099e633e9..c7eefa955 100644 --- a/languages/tree-sitter-stack-graphs-javascript/README.md +++ b/languages/tree-sitter-stack-graphs-javascript/README.md @@ -13,7 +13,7 @@ To use this library, add the following to your `Cargo.toml`: ```toml [dependencies] -tree-sitter-stack-graphs-javascript = "0.2" +tree-sitter-stack-graphs-javascript = "0.3" ``` Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-javascript/*/) for more details on how to use this library. diff --git a/languages/tree-sitter-stack-graphs-javascript/rust/lib.rs b/languages/tree-sitter-stack-graphs-javascript/rust/lib.rs index 718db8a2e..cbf80e5cd 100644 --- a/languages/tree-sitter-stack-graphs-javascript/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-javascript/rust/lib.rs @@ -37,7 +37,7 @@ pub fn try_language_configuration( cancellation_flag: &dyn CancellationFlag, ) -> Result { let mut lc = LanguageConfiguration::from_sources( - tree_sitter_javascript::language(), + tree_sitter_javascript::LANGUAGE.into(), Some(String::from("source.js")), None, vec![String::from("js")], diff --git a/languages/tree-sitter-stack-graphs-python/CHANGELOG.md b/languages/tree-sitter-stack-graphs-python/CHANGELOG.md index 61e6ca4e9..8ec44913d 100644 --- a/languages/tree-sitter-stack-graphs-python/CHANGELOG.md +++ b/languages/tree-sitter-stack-graphs-python/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v0.3.0 -- Unreleased + +- The `tree-sitter-stack-graphs` dependency is updated to version 0.10. + +- The `tree-sitter-python` dependency is updated to version 0.23.5. + ## v0.2.0 -- 2024-07-09 ### Added diff --git a/languages/tree-sitter-stack-graphs-python/Cargo.toml b/languages/tree-sitter-stack-graphs-python/Cargo.toml index 53d714719..afdfe6091 100644 --- a/languages/tree-sitter-stack-graphs-python/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-python/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tree-sitter-stack-graphs-python" -version = "0.2.0" +version = "0.3.0" description = "Stack graphs definition for Python using tree-sitter-python" readme = "README.md" keywords = ["tree-sitter", "stack-graphs", "python"] @@ -30,8 +30,8 @@ cli = ["anyhow", "clap", "tree-sitter-stack-graphs/cli"] [dependencies] anyhow = { version = "1.0", optional = true } clap = { version = "4", optional = true, features = ["derive"] } -tree-sitter-stack-graphs = { version = "0.9", path = "../../tree-sitter-stack-graphs" } # explicit version is required to be able to publish crate -tree-sitter-python = "=0.20.4" +tree-sitter-stack-graphs = { version = "0.10", path = "../../tree-sitter-stack-graphs" } # explicit version is required to be able to publish crate +tree-sitter-python = "=0.23.5" [dev-dependencies] anyhow = "1.0" diff --git a/languages/tree-sitter-stack-graphs-python/README.md b/languages/tree-sitter-stack-graphs-python/README.md index a313a3799..7ec9ded72 100644 --- a/languages/tree-sitter-stack-graphs-python/README.md +++ b/languages/tree-sitter-stack-graphs-python/README.md @@ -13,7 +13,7 @@ To use this library, add the following to your `Cargo.toml`: ```toml [dependencies] -tree-sitter-stack-graphs-python = "0.2" +tree-sitter-stack-graphs-python = "0.3" ``` Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-python/*/) for more details on how to use this library. diff --git a/languages/tree-sitter-stack-graphs-python/rust/lib.rs b/languages/tree-sitter-stack-graphs-python/rust/lib.rs index e0ffb40ec..332250511 100644 --- a/languages/tree-sitter-stack-graphs-python/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-python/rust/lib.rs @@ -29,7 +29,7 @@ pub fn try_language_configuration( cancellation_flag: &dyn CancellationFlag, ) -> Result { LanguageConfiguration::from_sources( - tree_sitter_python::language(), + tree_sitter_python::LANGUAGE.into(), Some(String::from("source.py")), None, vec![String::from("py")], diff --git a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml index 86feee2a1..379d4d3fe 100644 --- a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml @@ -33,8 +33,8 @@ glob = "0.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" stack-graphs = { version = "0.14", path = "../../stack-graphs" } # explicit version is required to be able to publish crate -tree-sitter-stack-graphs = { version = "0.9", path = "../../tree-sitter-stack-graphs" } # explicit version is required to be able to publish crate -tree-sitter-typescript = "=0.20.2" +tree-sitter-stack-graphs = { version = "0.10", path = "../../tree-sitter-stack-graphs" } # explicit version is required to be able to publish crate +tree-sitter-typescript = "=0.23.2" tsconfig = "0.1.0" [dev-dependencies] diff --git a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs index 2fa484a0a..8fd63881d 100644 --- a/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs +++ b/languages/tree-sitter-stack-graphs-typescript/rust/lib.rs @@ -44,7 +44,7 @@ pub fn try_language_configuration_typescript( cancellation_flag: &dyn CancellationFlag, ) -> Result { let mut lc = LanguageConfiguration::from_sources( - tree_sitter_typescript::language_typescript(), + tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(), Some(String::from("source.ts")), None, vec![String::from("ts")], @@ -74,7 +74,7 @@ pub fn try_language_configuration_tsx( cancellation_flag: &dyn CancellationFlag, ) -> Result { let mut lc = LanguageConfiguration::from_sources( - tree_sitter_typescript::language_tsx(), + tree_sitter_typescript::LANGUAGE_TSX.into(), Some(String::from("source.tsx")), None, vec![String::from("tsx")], diff --git a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg index b7478b4e4..a32c717f5 100644 --- a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg @@ -1469,6 +1469,8 @@ if none @is_async { edge @dec.lexical_scope -> @class_decl.lexical_scope } + + ; definitions [ (abstract_class_declaration name:(_)@name) @@ -1626,6 +1628,7 @@ if none @is_async { [ (abstract_class_declaration body:(_)@body) (class_declaration body:(_)@body) + (interface_declaration body:(_)@body) ]@class_decl { ; propagate lexical scope ; FIXME the static members have access to type variables like this @@ -1639,16 +1642,6 @@ if none @is_async { edge @class_decl.static_type -> @body.static_members attr (@class_decl.static_type -> @body.static_members) precedence = 2 } -[ - (interface_declaration body:(_)@body) -]@class_decl { - ; propagate lexical scope - edge @body.lexical_scope -> @class_decl.generic_inner_lexical_scope - - ; interface type equals body type - edge @class_decl.generic_inner_type -> @body.type -} - ;; Class Body @@ -1662,23 +1655,35 @@ if none @is_async { ; (public_field_definition)] ; ) -(class_body)@class_body { - node @class_body.lexical_scope - node @class_body.type_members - node @class_body.static_members +[ + (class_body) + (interface_body) +]@body { + node @body.lexical_scope + node @body.type_members + node @body.static_members } -(class_body - (_)@mem -)@class_body { +; decorators +[ + (class_body decorator:(_)@dec) +]@class_body { + ; connect lexical scope + edge @dec.lexical_scope -> @class_body.lexical_scope +} + +[ + (class_body (_)@mem) + (interface_body (_)@mem) +]@body { ; propagate lexical scope - edge @mem.lexical_scope -> @class_body.lexical_scope + edge @mem.lexical_scope -> @body.lexical_scope ; body members are member definitions - edge @class_body.type_members -> @mem.type_members + edge @body.type_members -> @mem.type_members ; body static members are static member definitions - edge @class_body.static_members -> @mem.static_members + edge @body.static_members -> @mem.static_members } @@ -2334,7 +2339,7 @@ if none @is_async { (import_statement (import_clause (namespace_import (identifier)@name))) (ambient_declaration (module name:(string) @name)) ; X._ - (nested_identifier (identifier)@name) + (nested_identifier object:(identifier)@name) ] { node @name.expr_def node expr_def_typeof @@ -2357,7 +2362,7 @@ if none @is_async { edge @name.type_def -> @name.type_def_member } -(nested_identifier . (_) @mod) @nested { +(nested_identifier object:(_)@mod) @nested { node @nested.expr_def node @nested.type_def @@ -2365,12 +2370,12 @@ if none @is_async { edge @nested.type_def -> @mod.type_def } -(nested_identifier . (_) @mod . (_) @name .) { +(nested_identifier object:(_)@mod property:(_)@name) { edge @mod.expr_def_member -> @name.expr_def edge @mod.type_def_member -> @name.type_def } -(nested_identifier (_) @name .) @nested { +(nested_identifier property:(_)@name)@nested { node @nested.expr_def_member node @nested.type_def_member @@ -2644,7 +2649,7 @@ if none @is_async { (call_expression) (class) (false) - (function) + (function_expression) (generator_function) (import) (member_expression) @@ -2814,8 +2819,7 @@ if none @is_async { (decorator (call_expression function:(member_expression object:(member_expression object:(identifier)@name)))) (decorator (call_expression function:(member_expression object:(member_expression object:(member_expression object:(identifier)@name))))) ; #dialect tsx - (nested_identifier (identifier)@name) - (nested_identifier (nested_identifier)@name) + (nested_identifier object:(_)@name) (nested_type_identifier module:(nested_identifier)@name) (internal_module name:(_)@name) (jsx_opening_element name: (_)@name) @@ -2870,7 +2874,7 @@ if none @is_def { (decorator (call_expression function:(member_expression object:(member_expression object:(identifier)@name)))) (decorator (call_expression function:(member_expression object:(member_expression object:(member_expression object:(identifier)@name))))) ; #dialect tsx - (nested_identifier (identifier)@name (identifier)) ; to pick up foo in JSX: +; (nested_identifier object:(identifier)@name property:(identifier)) ; to pick up foo in JSX: ; FIXME never matched (jsx_opening_element name: (identifier)@name) (jsx_closing_element name: (identifier)@name) (jsx_self_closing_element name: (identifier)@name) @@ -3259,20 +3263,20 @@ if none @is_def { ; function (x) {}; -; (function +; (function_expression ; (formal_parameters (identifier)) ; (statement_block)) ; this captures the parameters -; (function +; (function_expression ; parameters: (_)@params) ; this captures the body -; (function +; (function_expression ; body:(_)@body)@function ; functions with names -; (function +; (function_expression ; name:(_)@name ; parameters:(_)@call_sig)@fun { ; } @@ -3307,7 +3311,7 @@ if none @is_def { ; } [ - (function) + (function_expression) (arrow_function) (generator_function) ]@fun { @@ -3334,9 +3338,9 @@ if none @is_def { } [ - (function parameters:(_)@call_sig) - (arrow_function parameters:(_)@call_sig) - (generator_function parameters:(_)@call_sig) + (function_expression parameters:(_)@call_sig) + (arrow_function parameters:(_)@call_sig) + (generator_function parameters:(_)@call_sig) ]@fun { ; propagate lexical scope edge @call_sig.lexical_scope -> @fun.lexical_scope @@ -3385,9 +3389,9 @@ if none @is_def { } [ - (function body:(_)@body) - (arrow_function body:(_)@body) - (generator_function body:(_)@body) + (function_expression body:(_)@body) + (arrow_function body:(_)@body) + (generator_function body:(_)@body) ]@fun { ; propagate lexical scope edge @body.lexical_scope -> @fun.lexical_scope @@ -3396,8 +3400,8 @@ if none @is_def { ;;;; specified return type [ - (function return_type:(_)@return_type) - (arrow_function return_type:(_)@return_type) + (function_expression return_type:(_)@return_type) + (arrow_function return_type:(_)@return_type) ]@fun { ; propagate lexical scope edge @return_type.lexical_scope -> @fun.lexical_scope @@ -3409,8 +3413,8 @@ if none @is_def { ;;;; inferred return type [ - (function "async"?@is_async !return_type body:(_)@body) - (arrow_function "async"?@is_async !return_type body:(statement_block)@body) + (function_expression "async"?@is_async !return_type body:(_)@body) + (arrow_function "async"?@is_async !return_type body:(statement_block)@body) ]@fun { if none @is_async { ; callable is type of return statement @@ -3428,8 +3432,8 @@ if none @is_async { ;;;; inferred async return type [ - (function "async" !return_type body:(_)@body) - (arrow_function "async" body:(statement_block)@body) + (function_expression "async" !return_type body:(_)@body) + (arrow_function "async" body:(statement_block)@body) ]@fun_decl { ; function returns body return type edge @fun_decl.callable__return -> @fun_decl.async_type @@ -3548,19 +3552,9 @@ if none @is_async { ; (subscript_expression (identifier) (string)) [ - (member_expression - object: (_)@object - property: (_)@prop - )@member_expr + (member_expression object:(_)@object property:(_)@prop)@member_expr ; #dialect tsx - (nested_identifier - (nested_identifier)@object - (identifier)@prop - )@member_expr - (nested_identifier - (identifier)@object - (identifier)@prop - )@member_expr +; (nested_identifier object:(_)@object property:(identifier)@prop)@member_expr ; FIXME this never matched anything! ; #end ] { node @member_expr.member @@ -3890,15 +3884,13 @@ if none @is_async { ; (sequence_expression (number) (number)) -(sequence_expression - left: (_)@left - right: (_)@right -)@sequence_expr { +(sequence_expression (_)@expr)@sequence_expr { ; propagate lexical scope - edge @left.lexical_scope -> @sequence_expr.lexical_scope - edge @right.lexical_scope -> @sequence_expr.lexical_scope + edge @expr.lexical_scope -> @sequence_expr.lexical_scope +} - ; FIXME @sequence_expr.type is type of last, but cannot express because of nesting +(sequence_expression (_)@last .)@sequence_expr { + edge @sequence_expr.type -> @last.type } @@ -4040,6 +4032,12 @@ if none @is_async { edge @class_expr.this__type_def -> @class_expr.generic_inner_type } +; decorators +(class decorator:(_)@dec)@class_expr { + ; connect lexical scope + edge @dec.lexical_scope -> @class_expr.lexical_scope +} + ; default constructor ; FIXME only if no other constructor is defined (class)@class_expr { @@ -4571,6 +4569,12 @@ if none @is_async { ; value:(_)@value ; opt ; )@def +; decorators +(public_field_definition decorator:(_)@dec)@def { + ; connect lexical scope + edge @dec.lexical_scope -> @def.lexical_scope +} + (public_field_definition name:(_)@name )@def { @@ -4956,6 +4960,7 @@ if none @is_acc { [ (array_type) (asserts) + (asserts_annotation) (conditional_type) (constraint) (constructor_type) @@ -5071,6 +5076,9 @@ if none @is_acc { edge @type.lexical_scope -> @asserts.lexical_scope } +(asserts_annotation (_)@asserts)@asserts_annotation { + edge @asserts.lexical_scope -> @asserts_annotation.lexical_scope +} ;; Optional Type @@ -5596,7 +5604,7 @@ if none @is_acc { ; X (nested_type_identifier module:(identifier)@name) ; X._, _.X._ - (nested_identifier (identifier)@name) + (nested_identifier object:(identifier)@name) ] { node @name.type_ref attr (@name.type_ref) node_reference = @name @@ -5607,7 +5615,7 @@ if none @is_acc { edge @name.type_ref_member -> @name.type_ref } -(nested_identifier . (_)@mod) @nested { +(nested_identifier object:(_)@mod) @nested { node @nested.type_ref edge @mod.type_ref -> @nested.type_ref } @@ -5616,7 +5624,7 @@ if none @is_acc { edge @name.type_ref -> @mod.type_ref_member } -(nested_identifier (_)@name .) @nested { +(nested_identifier property:(_)@name) @nested { node @nested.type_ref_member edge @nested.type_ref_member -> @name.type_ref_member } @@ -6159,7 +6167,7 @@ if none @is_acc { [ (arrow_function "async") - (function "async") + (function_expression "async") (function_declaration "async") (generator_function "async") (generator_function_declaration "async") @@ -6221,7 +6229,6 @@ if none @is_acc { [ (jsx_text) (jsx_element) - (jsx_fragment) (jsx_self_closing_element) (jsx_expression) ]@child @@ -6229,24 +6236,6 @@ if none @is_acc { edge @child.lexical_scope -> @parent.lexical_scope } -(jsx_fragment)@fragment { - node @fragment.lexical_scope - node @fragment.value - node @fragment.type -} - -(jsx_fragment - [ - (jsx_text) - (jsx_element) - (jsx_fragment) - (jsx_self_closing_element) - (jsx_expression) - ]@child -) @parent { - edge @child.lexical_scope -> @parent.lexical_scope -} - (jsx_text)@jsx_text { node @jsx_text.lexical_scope } diff --git a/languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_namespace_name.tsx b/languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_namespace_name.tsx.skip similarity index 100% rename from languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_namespace_name.tsx rename to languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_namespace_name.tsx.skip diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/very-deep-namespace.ts b/languages/tree-sitter-stack-graphs-typescript/test/modules/very-deep-namespace.ts.skip similarity index 100% rename from languages/tree-sitter-stack-graphs-typescript/test/modules/very-deep-namespace.ts rename to languages/tree-sitter-stack-graphs-typescript/test/modules/very-deep-namespace.ts.skip diff --git a/languages/tree-sitter-stack-graphs-typescript/test/statements/refer-to-interface-in-nested-namespace-by-fully-qualified-name.ts b/languages/tree-sitter-stack-graphs-typescript/test/statements/refer-to-interface-in-nested-namespace-by-fully-qualified-name.ts.skip similarity index 100% rename from languages/tree-sitter-stack-graphs-typescript/test/statements/refer-to-interface-in-nested-namespace-by-fully-qualified-name.ts rename to languages/tree-sitter-stack-graphs-typescript/test/statements/refer-to-interface-in-nested-namespace-by-fully-qualified-name.ts.skip diff --git a/languages/tree-sitter-stack-graphs-typescript/test/statements/refer-to-interface-in-qualified-namespace-by-fully-qualified-name.ts b/languages/tree-sitter-stack-graphs-typescript/test/statements/refer-to-interface-in-qualified-namespace-by-fully-qualified-name.ts.skip similarity index 100% rename from languages/tree-sitter-stack-graphs-typescript/test/statements/refer-to-interface-in-qualified-namespace-by-fully-qualified-name.ts rename to languages/tree-sitter-stack-graphs-typescript/test/statements/refer-to-interface-in-qualified-namespace-by-fully-qualified-name.ts.skip diff --git a/lsp-positions/CHANGELOG.md b/lsp-positions/CHANGELOG.md index a9e17c13f..84aa962b4 100644 --- a/lsp-positions/CHANGELOG.md +++ b/lsp-positions/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v0.3.4 -- Unreleased + +Upgraded the `tree-sitter` dependency to version 0.24. + ## v0.3.3 -- 2024-03-05 The `tree-sitter` dependency version was updated to fix install problems. diff --git a/lsp-positions/Cargo.toml b/lsp-positions/Cargo.toml index 7054def14..a9f7acb20 100644 --- a/lsp-positions/Cargo.toml +++ b/lsp-positions/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lsp-positions" -version = "0.3.3" +version = "0.3.4" description = "LSP-compatible character positions" homepage = "https://github.com/github/stack-graphs/tree/main/lsp-positions" repository = "https://github.com/github/stack-graphs/" @@ -22,7 +22,7 @@ tree-sitter = ["dep:tree-sitter"] [dependencies] memchr = "2.4" -tree-sitter = { version = "0.20", optional = true } # keep the same minor version as the tree-sitter +tree-sitter = { version = "0.24", optional = true } # keep the same minor version as the tree-sitter # dependency of tree-sitter-stack-graphs to prevent # install problems unicode-segmentation = { version = "1.8" } diff --git a/tree-sitter-stack-graphs/CHANGELOG.md b/tree-sitter-stack-graphs/CHANGELOG.md index 6f6e86f25..b45b69b64 100644 --- a/tree-sitter-stack-graphs/CHANGELOG.md +++ b/tree-sitter-stack-graphs/CHANGELOG.md @@ -5,8 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v0.9.0 -- 2024-07-09 +## v0.10.0 -- Unreleased + +Upgraded `tree-sitter` dependency to version 0.24. +## v0.9.0 -- 2024-07-09 ### Library diff --git a/tree-sitter-stack-graphs/Cargo.toml b/tree-sitter-stack-graphs/Cargo.toml index 0ac84d012..3c1c01a80 100644 --- a/tree-sitter-stack-graphs/Cargo.toml +++ b/tree-sitter-stack-graphs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tree-sitter-stack-graphs" -version = "0.9.0" +version = "0.10.0" description = "Create stack graphs using tree-sitter parsers" homepage = "https://github.com/github/stack-graphs/tree/main/tree-sitter-stack-graphs" repository = "https://github.com/github/stack-graphs/" @@ -62,7 +62,7 @@ env_logger = { version = "0.9", optional = true } indoc = { version = "1.0", optional = true } itertools = "0.10" log = "0.4" -lsp-positions = { version="0.3", path="../lsp-positions", features=["tree-sitter"] } # explicit version is required to be able to publish crate +lsp-positions = { version="0.3.4", path="../lsp-positions", features=["tree-sitter"] } # explicit version is required to be able to publish crate once_cell = "1" pathdiff = { version = "0.2.1", optional = true } regex = "1" @@ -74,13 +74,13 @@ thiserror = "1.0" time = { version = "0.3", optional = true } tokio = { version = "1.26", optional = true, features = ["io-std", "rt", "rt-multi-thread"] } tower-lsp = { version = "0.19", optional = true } -tree-sitter = "0.20" # keep the same minor version as the tree-sitter dependency +tree-sitter = "0.24" # keep the same minor version as the tree-sitter dependency # of tree-sitter-graph to prevent install problems -tree-sitter-config = { version = "0.19", optional = true } -tree-sitter-graph = "0.11" -tree-sitter-loader = "0.20" +tree-sitter-config = { version = "0.24", optional = true } +tree-sitter-graph = "0.12" +tree-sitter-loader = "0.24" walkdir = { version = "2.3", optional = true } [dev-dependencies] pretty_assertions = "0.7" -tree-sitter-python = "=0.19.1" +tree-sitter-python = "=0.23.5" diff --git a/tree-sitter-stack-graphs/README.md b/tree-sitter-stack-graphs/README.md index a4e52add3..56f61e131 100644 --- a/tree-sitter-stack-graphs/README.md +++ b/tree-sitter-stack-graphs/README.md @@ -14,7 +14,7 @@ To use this library, add the following to your `Cargo.toml`: ```toml [dependencies] -tree-sitter-stack-graphs = "0.9" +tree-sitter-stack-graphs = "0.10" ``` Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs/*/) for more details on how to use this library. diff --git a/tree-sitter-stack-graphs/src/cli/init.rs b/tree-sitter-stack-graphs/src/cli/init.rs index f71890390..e513e5acd 100644 --- a/tree-sitter-stack-graphs/src/cli/init.rs +++ b/tree-sitter-stack-graphs/src/cli/init.rs @@ -778,7 +778,7 @@ impl ProjectSettings<'_> { cancellation_flag: &dyn CancellationFlag, ) -> Result {{ LanguageConfiguration::from_sources( - {}::language(), + {}::LANGUAGE.into(), Some(String::from("source.{}")), None, vec![String::from("{}")], diff --git a/tree-sitter-stack-graphs/src/cli/load.rs b/tree-sitter-stack-graphs/src/cli/load.rs index b32332f9d..1fd22fa2b 100644 --- a/tree-sitter-stack-graphs/src/cli/load.rs +++ b/tree-sitter-stack-graphs/src/cli/load.rs @@ -67,7 +67,7 @@ impl PathLoaderArgs { builtins_paths, )? } else { - let loader_config = TsConfig::load() + let loader_config = TsConfig::load(None) .and_then(|v| v.get()) .map_err(LoadError::TreeSitter)?; Loader::from_tree_sitter_configuration( diff --git a/tree-sitter-stack-graphs/src/cli/lsp.rs b/tree-sitter-stack-graphs/src/cli/lsp.rs index 03f1c8060..57ed770bb 100644 --- a/tree-sitter-stack-graphs/src/cli/lsp.rs +++ b/tree-sitter-stack-graphs/src/cli/lsp.rs @@ -560,25 +560,6 @@ impl FromStdError for std::result::Result { } } -trait FromAnyhowError { - #[must_use] - fn from_error(self) -> Result; -} - -impl FromAnyhowError for std::result::Result { - #[must_use] - fn from_error(self) -> Result { - match self { - Ok(value) => Ok(value), - Err(err) => Err(Error { - code: ErrorCode::ServerError(-1), - message: err.to_string(), - data: None, - }), - } - } -} - #[derive(Debug)] pub enum Job { IndexPath(PathBuf), diff --git a/tree-sitter-stack-graphs/src/cli/match.rs b/tree-sitter-stack-graphs/src/cli/match.rs index 108c8450e..889d2374a 100644 --- a/tree-sitter-stack-graphs/src/cli/match.rs +++ b/tree-sitter-stack-graphs/src/cli/match.rs @@ -49,7 +49,7 @@ impl MatchArgs { None => return Err(anyhow!("No stack graph language found")), }; let source = file_reader.get(&self.source_path)?; - let tree = parse(lc.language, &self.source_path, source)?; + let tree = parse(&lc.language, &self.source_path, source)?; if self.stanza.is_empty() { lc.sgl.tsg.try_visit_matches(&tree, source, true, |mat| { print_matches(lc.sgl.tsg_path(), &self.source_path, source, mat) diff --git a/tree-sitter-stack-graphs/src/cli/parse.rs b/tree-sitter-stack-graphs/src/cli/parse.rs index aff7681b1..64275b915 100644 --- a/tree-sitter-stack-graphs/src/cli/parse.rs +++ b/tree-sitter-stack-graphs/src/cli/parse.rs @@ -40,14 +40,14 @@ impl ParseArgs { None => return Err(anyhow!("No stack graph language found")), }; let source = file_reader.get(&self.source_path)?; - let tree = parse(lang, &self.source_path, source)?; + let tree = parse(&lang, &self.source_path, source)?; print_tree(tree); Ok(()) } } pub(super) fn parse( - language: tree_sitter::Language, + language: &tree_sitter::Language, path: &Path, source: &str, ) -> anyhow::Result { diff --git a/tree-sitter-stack-graphs/src/cli/test.rs b/tree-sitter-stack-graphs/src/cli/test.rs index 1bff78a48..e3034cbbf 100644 --- a/tree-sitter-stack-graphs/src/cli/test.rs +++ b/tree-sitter-stack-graphs/src/cli/test.rs @@ -432,7 +432,7 @@ impl TestArgs { .add_from_graph(&lc.builtins) .map_err(|h| anyhow!("Duplicate builtin file {}", &graph[h]))?; let files = files.into_iter().collect::>(); - match cache.entry(lc.language) { + match cache.entry(lc.language.clone()) { Entry::Occupied(o) => { o.get().load_into(graph, partials, db)?; } diff --git a/tree-sitter-stack-graphs/src/lib.rs b/tree-sitter-stack-graphs/src/lib.rs index 717214832..3c560fb56 100644 --- a/tree-sitter-stack-graphs/src/lib.rs +++ b/tree-sitter-stack-graphs/src/lib.rs @@ -324,7 +324,7 @@ //! import sys //! print(sys.path) //! "#; -//! let grammar = tree_sitter_python::language(); +//! let grammar = tree_sitter_python::LANGUAGE.into(); //! let tsg_source = STACK_GRAPH_RULES; //! let mut language = StackGraphLanguage::from_str(grammar, tsg_source)?; //! let mut stack_graph = StackGraph::new(); @@ -479,7 +479,7 @@ impl StackGraphLanguage { language: tree_sitter::Language, tsg_source: &str, ) -> Result { - let tsg = tree_sitter_graph::ast::File::from_str(language, tsg_source)?; + let tsg = tree_sitter_graph::ast::File::from_str(language.clone(), tsg_source)?; Ok(StackGraphLanguage { language, tsg, @@ -518,8 +518,8 @@ impl StackGraphLanguage { &mut self.functions } - pub fn language(&self) -> tree_sitter::Language { - self.language + pub fn language(&self) -> &tree_sitter::Language { + &self.language } /// Returns the original TSG path, if it was provided at construction or set with @@ -624,7 +624,7 @@ impl<'a> Builder<'a> { ) -> Result<(), BuildError> { let tree = { let mut parser = Parser::new(); - parser.set_language(self.sgl.language)?; + parser.set_language(&self.sgl.language)?; let ts_cancellation_flag = TreeSitterCancellationFlag::from(cancellation_flag); // The parser.set_cancellation_flag` is unsafe, because it does not tie the // lifetime of the parser to the lifetime of the cancellation flag in any way. diff --git a/tree-sitter-stack-graphs/src/loader.rs b/tree-sitter-stack-graphs/src/loader.rs index 14aa97916..861e4ff95 100644 --- a/tree-sitter-stack-graphs/src/loader.rs +++ b/tree-sitter-stack-graphs/src/loader.rs @@ -68,13 +68,12 @@ impl LanguageConfiguration { builtins_config: Option<&str>, cancellation_flag: &dyn CancellationFlag, ) -> Result> { - let sgl = StackGraphLanguage::from_source(language, tsg_path.clone(), tsg_source).map_err( - |err| LoadError::SglParse { - inner: err, - tsg_path, - tsg: Cow::from(tsg_source), - }, - )?; + let sgl = StackGraphLanguage::from_source(language.clone(), tsg_path.clone(), tsg_source) + .map_err(|err| LoadError::SglParse { + inner: err, + tsg_path, + tsg: Cow::from(tsg_source), + })?; let mut builtins = StackGraph::new(); if let Some((builtins_path, builtins_source)) = builtins_source { let mut builtins_globals = Variables::new(); @@ -273,7 +272,7 @@ impl Loader { &mut self, path: &Path, content: &mut dyn ContentProvider, - ) -> Result, LoadError<'static>> { + ) -> Result, LoadError<'static>> { match &mut self.0 { LoaderImpl::Paths(loader) => loader.load_tree_sitter_language_for_file(path, content), LoaderImpl::Provided(loader) => { @@ -496,10 +495,10 @@ impl LanguageConfigurationsLoader { &mut self, path: &Path, content: &mut dyn ContentProvider, - ) -> Result, LoadError<'static>> { + ) -> Result, LoadError<'static>> { for configuration in self.configurations.iter() { if configuration.matches_file(path, content)? { - return Ok(Some(configuration.language)); + return Ok(Some(&configuration.language)); } } Ok(None) @@ -567,9 +566,9 @@ impl PathLoader { &mut self, path: &Path, content: &mut dyn ContentProvider, - ) -> Result, LoadError<'static>> { + ) -> Result, LoadError<'static>> { if let Some(selected_language) = self.select_language_for_file(path, content)? { - return Ok(Some(selected_language.language)); + return Ok(Some(&selected_language.language)); } Ok(None) } @@ -591,7 +590,7 @@ impl PathLoader { Some(index) => index, None => { let tsg = self.load_tsg_from_paths(&language)?; - let sgl = StackGraphLanguage::new(language.language, tsg); + let sgl = StackGraphLanguage::new(language.language.clone(), tsg); let mut builtins = StackGraph::new(); self.load_builtins_from_paths_into( @@ -602,7 +601,7 @@ impl PathLoader { )?; let lc = LanguageConfiguration { - language: language.language, + language: language.language.clone(), scope: language.scope, content_regex: language.content_regex, file_types: language.file_types, @@ -696,7 +695,7 @@ impl PathLoader { } if tsg_path.exists() { let tsg_source = std::fs::read_to_string(tsg_path)?; - return Loader::load_tsg(language.language, Cow::from(tsg_source)); + return Loader::load_tsg(language.language.clone(), Cow::from(tsg_source)); } } return Err(LoadError::NoTsgFound); @@ -786,10 +785,11 @@ impl SupplementedTsLoader { .map_err(LoadError::TreeSitter)?; let configurations = self .0 - .find_language_configurations_at_path(&path) + .find_language_configurations_at_path(&path, true) .map_err(LoadError::TreeSitter)?; let languages = languages .into_iter() + .map(|(l, _)| l) .zip(configurations.into_iter()) .map(SupplementedLanguage::from) .filter(|language| scope.map_or(true, |scope| language.matches_scope(scope))) diff --git a/tree-sitter-stack-graphs/tests/it/builder.rs b/tree-sitter-stack-graphs/tests/it/builder.rs index 14476111e..719e25d71 100644 --- a/tree-sitter-stack-graphs/tests/it/builder.rs +++ b/tree-sitter-stack-graphs/tests/it/builder.rs @@ -35,7 +35,7 @@ fn can_support_preexisting_nodes() { .add(FILE_PATH_VAR.into(), file_name.into()) .expect("failed to add file path variable"); - let language = StackGraphLanguage::from_str(tree_sitter_python::language(), tsg).unwrap(); + let language = StackGraphLanguage::from_str(tree_sitter_python::LANGUAGE.into(), tsg).unwrap(); language .build_stack_graph_into(&mut graph, file, python, &globals, &NoCancellation) .expect("Failed to build graph"); @@ -59,7 +59,7 @@ fn can_support_injected_nodes() { let node_id = graph.new_node_id(file); let _preexisting_node = graph.add_scope_node(node_id, true).unwrap(); - let language = StackGraphLanguage::from_str(tree_sitter_python::language(), tsg).unwrap(); + let language = StackGraphLanguage::from_str(tree_sitter_python::LANGUAGE.into(), tsg).unwrap(); let mut builder = language.builder_into_stack_graph(&mut graph, file, python); let mut globals = Variables::new(); diff --git a/tree-sitter-stack-graphs/tests/it/loader.rs b/tree-sitter-stack-graphs/tests/it/loader.rs index 257326952..401af46e5 100644 --- a/tree-sitter-stack-graphs/tests/it/loader.rs +++ b/tree-sitter-stack-graphs/tests/it/loader.rs @@ -9,6 +9,7 @@ use once_cell::sync::Lazy; use pretty_assertions::assert_eq; use stack_graphs::graph::StackGraph; use std::path::PathBuf; +use tree_sitter::Language; use tree_sitter_stack_graphs::loader::FileAnalyzers; use tree_sitter_stack_graphs::loader::LanguageConfiguration; use tree_sitter_stack_graphs::loader::Loader; @@ -25,10 +26,10 @@ static TSG: Lazy = Lazy::new(|| { #[test] fn can_load_from_provided_language_configuration() { - let language = tree_sitter_python::language(); - let sgl = StackGraphLanguage::from_str(language, &TSG).unwrap(); + let language: Language = tree_sitter_python::LANGUAGE.into(); + let sgl = StackGraphLanguage::from_str(language.clone(), &TSG).unwrap(); let lc = LanguageConfiguration { - language: language, + language: language.clone(), scope: Some("source.py".into()), content_regex: None, file_types: vec!["py".into()], @@ -43,10 +44,10 @@ fn can_load_from_provided_language_configuration() { let tsl = loader .load_tree_sitter_language_for_file(&PATH, &mut None) .expect("Expected loading tree-sitter language to succeed"); - assert_eq!(tsl, Some(language)); + assert_eq!(tsl, Some(&language)); let lc = loader .load_for_file(&PATH, &mut None, &NoCancellation) .expect("Expected loading stack graph language to succeed"); - assert_eq!(lc.primary.map(|lc| lc.language), Some(language)); + assert_eq!(lc.primary.map(|lc| &lc.language), Some(&language)); } diff --git a/tree-sitter-stack-graphs/tests/it/main.rs b/tree-sitter-stack-graphs/tests/it/main.rs index 33ee19241..01cfd9754 100644 --- a/tree-sitter-stack-graphs/tests/it/main.rs +++ b/tree-sitter-stack-graphs/tests/it/main.rs @@ -28,7 +28,7 @@ pub(self) fn build_stack_graph( ) -> Result<(StackGraph, Handle), BuildError> { let file_name = "test.py"; let language = - StackGraphLanguage::from_str(tree_sitter_python::language(), tsg_source).unwrap(); + StackGraphLanguage::from_str(tree_sitter_python::LANGUAGE.into(), tsg_source).unwrap(); let mut graph = StackGraph::new(); let file = graph.get_or_create_file(file_name); let mut globals = Variables::new(); diff --git a/tree-sitter-stack-graphs/tests/it/test.rs b/tree-sitter-stack-graphs/tests/it/test.rs index cb1efff4f..fae14fe76 100644 --- a/tree-sitter-stack-graphs/tests/it/test.rs +++ b/tree-sitter-stack-graphs/tests/it/test.rs @@ -73,7 +73,7 @@ fn build_stack_graph_into( globals: &Variables, ) -> Result<(), BuildError> { let language = - StackGraphLanguage::from_str(tree_sitter_python::language(), tsg_source).unwrap(); + StackGraphLanguage::from_str(tree_sitter_python::LANGUAGE.into(), tsg_source).unwrap(); language.build_stack_graph_into(graph, file, python_source, globals, &NoCancellation)?; Ok(()) } From c0ecac035f0905831ee8e328a1658b96c8ed704e Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 10 Dec 2024 19:18:15 +0100 Subject: [PATCH 481/500] Handle additional case --- .../tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg | 4 ++-- .../test/expressions/member_expression.js | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg index a9167c3a1..7ca4eee88 100644 --- a/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-javascript/src/stack-graphs.tsg @@ -2435,7 +2435,7 @@ inherit .containing_class_value [ (primary_expression/identifier)@variable - (member_expression . (identifier)@variable) + (member_expression object:(identifier)@variable) ] { ; value is a lookup, ie a push attr (@variable.value) node_reference = @variable @@ -3189,7 +3189,7 @@ inherit .containing_class_value ;; ##### Member Expressions (member_expression - (_)@object . (_)@property)@member_expr + object:(_)@object property:(_)@property)@member_expr { node member_push diff --git a/languages/tree-sitter-stack-graphs-javascript/test/expressions/member_expression.js b/languages/tree-sitter-stack-graphs-javascript/test/expressions/member_expression.js index b397d747a..438cf9dd6 100644 --- a/languages/tree-sitter-stack-graphs-javascript/test/expressions/member_expression.js +++ b/languages/tree-sitter-stack-graphs-javascript/test/expressions/member_expression.js @@ -15,4 +15,8 @@ let x = 1; // Flow around /**/ x; +// ^ defined: 1 + +// Optional chain +/**/ x?.foo // ^ defined: 1 \ No newline at end of file From ba2117d75ff56dd4adf7032f18d07ed9c1dac26a Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 10 Dec 2024 19:32:18 +0100 Subject: [PATCH 482/500] Fix panic --- stack-graphs/CHANGELOG.md | 6 ++++++ stack-graphs/Cargo.toml | 2 +- stack-graphs/src/graph.rs | 5 ++++- stack-graphs/tests/it/graph.rs | 21 ++++++++++++++++++++- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/stack-graphs/CHANGELOG.md b/stack-graphs/CHANGELOG.md index eeaae0730..aae6a2998 100644 --- a/stack-graphs/CHANGELOG.md +++ b/stack-graphs/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v0.14.1 -- Unpublished + +### Fixed + +- A panic when using `StackGraph::incoming_edge_degree` on some nodes without incoming edges. + ## v0.14.0 -- 2024-07-09 ### Changed diff --git a/stack-graphs/Cargo.toml b/stack-graphs/Cargo.toml index f114fffdb..e542f4163 100644 --- a/stack-graphs/Cargo.toml +++ b/stack-graphs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "stack-graphs" -version = "0.14.0" +version = "0.14.1" description = "Name binding for arbitrary programming languages" homepage = "https://github.com/github/stack-graphs/tree/main/stack-graphs" repository = "https://github.com/github/stack-graphs/" diff --git a/stack-graphs/src/graph.rs b/stack-graphs/src/graph.rs index 686344ee5..d55dfc48a 100644 --- a/stack-graphs/src/graph.rs +++ b/stack-graphs/src/graph.rs @@ -1334,7 +1334,10 @@ impl StackGraph { /// Returns the number of edges that end at a particular sink node. pub fn incoming_edge_degree(&self, sink: Handle) -> Degree { - self.incoming_edges[sink] + self.incoming_edges + .get(sink) + .cloned() + .unwrap_or(Degree::Zero) } } diff --git a/stack-graphs/tests/it/graph.rs b/stack-graphs/tests/it/graph.rs index f19bb2c30..620d066c9 100644 --- a/stack-graphs/tests/it/graph.rs +++ b/stack-graphs/tests/it/graph.rs @@ -8,7 +8,7 @@ use std::collections::HashSet; use maplit::hashset; -use stack_graphs::graph::StackGraph; +use stack_graphs::graph::{Degree, StackGraph}; use crate::test_graphs; use crate::test_graphs::CreateStackGraph; @@ -196,3 +196,22 @@ fn can_add_graph_to_empty_graph() { ); } } + +#[test] +fn can_get_incoming_edges() { + let mut graph = StackGraph::new(); + let file = graph.get_or_create_file("test.py"); + let h1 = graph.internal_scope(file, 0); + let h2 = graph.internal_scope(file, 1); + let h3 = graph.internal_scope(file, 2); + assert_eq!(Degree::Zero, graph.incoming_edge_degree(h1)); + assert_eq!(Degree::Zero, graph.incoming_edge_degree(h2)); + assert_eq!(Degree::Zero, graph.incoming_edge_degree(h3)); + graph.add_edge(h1, h2, 0); + graph.add_edge(h3, h2, 0); + assert_eq!(Degree::Zero, graph.incoming_edge_degree(h1)); + assert_eq!(Degree::Multiple, graph.incoming_edge_degree(h2)); + assert_eq!(Degree::Zero, graph.incoming_edge_degree(h3)); + graph.add_edge(h3, h1, 0); + assert_eq!(Degree::One, graph.incoming_edge_degree(h1)); +} From ba182ad26c0a70b2580070e7c61ca254e1cf9aa4 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Wed, 11 Dec 2024 15:24:54 +0100 Subject: [PATCH 483/500] Fix previously skipped tests --- .../src/stack-graphs.tsg | 235 ++++++++---------- ...e_name.tsx.skip => jsx_namespace_name.tsx} | 0 ...mespace.ts.skip => very-deep-namespace.ts} | 0 ...sted-namespace-by-fully-qualified-name.ts} | 0 ...fied-namespace-by-fully-qualified-name.ts} | 0 5 files changed, 106 insertions(+), 129 deletions(-) rename languages/tree-sitter-stack-graphs-typescript/test/jsx/{jsx_namespace_name.tsx.skip => jsx_namespace_name.tsx} (100%) rename languages/tree-sitter-stack-graphs-typescript/test/modules/{very-deep-namespace.ts.skip => very-deep-namespace.ts} (100%) rename languages/tree-sitter-stack-graphs-typescript/test/statements/{refer-to-interface-in-nested-namespace-by-fully-qualified-name.ts.skip => refer-to-interface-in-nested-namespace-by-fully-qualified-name.ts} (100%) rename languages/tree-sitter-stack-graphs-typescript/test/statements/{refer-to-interface-in-qualified-namespace-by-fully-qualified-name.ts.skip => refer-to-interface-in-qualified-namespace-by-fully-qualified-name.ts} (100%) diff --git a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg index a32c717f5..773abde7c 100644 --- a/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg +++ b/languages/tree-sitter-stack-graphs-typescript/src/stack-graphs.tsg @@ -627,16 +627,6 @@ attribute node_symbol = node => symbol = (source-text node), source_n (import_statement "type"?@is_type (import_clause (named_imports (import_specifier name:(_)@name))@clause)) ] { if none @is_type { - node @name.expr_def - node @name.expr_def__ns - node @name.expr_ref - node @name.expr_ref__ns - - ; expr reference - attr (@name.expr_ref) node_reference = @name - edge @name.expr_ref -> @name.expr_ref__ns - ; - attr (@name.expr_ref__ns) push_symbol = "%E" edge @name.expr_ref__ns -> @clause.lexical_scope } } @@ -646,6 +636,9 @@ if none @is_type { (import_statement "type"?@is_type (import_clause (named_imports (import_specifier name:(_)@name !alias))@clause)) ] { if none @is_type { + node @name.expr_def + node @name.expr_def__ns + ; expr definition edge @clause.defs -> @name.expr_def__ns ; FIXME defs, lexical_defs? ; @@ -664,7 +657,6 @@ if none @is_type { if none @is_type { node @alias.expr_def node @alias.expr_def__ns - node @alias.expr_ref ; expr definition edge @clause.defs -> @alias.expr_def__ns @@ -2340,6 +2332,12 @@ if none @is_async { (ambient_declaration (module name:(string) @name)) ; X._ (nested_identifier object:(identifier)@name) + ; _.X._ + (member_expression object:(identifier)@name) + ; _.X + (nested_identifier property:(_)@name) + ; _._.X + (member_expression property:(_)@name) ] { node @name.expr_def node expr_def_typeof @@ -2362,7 +2360,10 @@ if none @is_async { edge @name.type_def -> @name.type_def_member } -(nested_identifier object:(_)@mod) @nested { +[ + (nested_identifier object:(_)@mod) + (member_expression object:[(member_expression) (identifier)]@mod) +]@nested { node @nested.expr_def node @nested.type_def @@ -2370,12 +2371,18 @@ if none @is_async { edge @nested.type_def -> @mod.type_def } -(nested_identifier object:(_)@mod property:(_)@name) { +[ + (nested_identifier object:(_)@mod property:(_)@name) + (member_expression object:[(member_expression) (identifier)]@mod property:(_)@name) +] { edge @mod.expr_def_member -> @name.expr_def edge @mod.type_def_member -> @name.type_def } -(nested_identifier property:(_)@name)@nested { +[ + (nested_identifier property:(_)@name) + (member_expression property:(_)@name) +]@nested { node @nested.expr_def_member node @nested.type_def_member @@ -2782,105 +2789,13 @@ if none @is_async { ; x; -[ - (primary_expression/identifier)@name - ; FIXME expansion of _lhs_expression/identifier and _augmented_assignment_lhs - (for_in_statement ["var" "let" "const"]?@is_def left:(identifier)@name) - (assignment_expression left:(identifier)@name) - (augmented_assignment_expression left:(identifier)@name) - (asserts (identifier)@name) - (type_predicate name:(identifier)@name) - ; FIXME type_query has its own restricted expression production - ; we need to do this for every (identifier) inside a type query - ; this cannot be expressed, so we manually unroll three levels here - (type_query (identifier)@name) - (type_query (member_expression object:(identifier)@name)) - (type_query (member_expression object:(member_expression object:(identifier)@name))) - (type_query (member_expression object:(member_expression object:(member_expression object:(identifier)@name)))) - (type_query (subscript_expression object:(identifier)@name)) - (type_query (subscript_expression object:(member_expression object:(identifier)@name))) - (type_query (subscript_expression object:(member_expression object:(member_expression object:(identifier)@name)))) - (type_query (call_expression function:(identifier)@name)) - (type_query (call_expression function:(member_expression object:(identifier)@name))) - (type_query (call_expression function:(member_expression object:(member_expression object:(identifier)@name)))) - (type_query (call_expression function:(member_expression object:(member_expression object:(member_expression object:(identifier)@name))))) - (type_query (call_expression function:(subscript_expression object:(identifier)@name))) - (type_query (call_expression function:(subscript_expression object:(member_expression object:(identifier)@name)))) - (type_query (call_expression function:(subscript_expression object:(member_expression object:(member_expression object:(identifier)@name))))) - ; FIXME decorator has its own restricted expression production - ; we need to do this for every (identifier) inside a decorator - ; this cannot be expressed, so we manually unroll three levels here - (decorator (identifier)@name) - (decorator (member_expression object:(identifier)@name)) - (decorator (member_expression object:(member_expression object:(identifier)@name))) - (decorator (member_expression object:(member_expression object:(member_expression object:(identifier)@name)))) - (decorator (call_expression function:(identifier)@name)) - (decorator (call_expression function:(member_expression object:(identifier)@name))) - (decorator (call_expression function:(member_expression object:(member_expression object:(identifier)@name)))) - (decorator (call_expression function:(member_expression object:(member_expression object:(member_expression object:(identifier)@name))))) -; #dialect tsx - (nested_identifier object:(_)@name) - (nested_type_identifier module:(nested_identifier)@name) - (internal_module name:(_)@name) - (jsx_opening_element name: (_)@name) - (jsx_closing_element name: (_)@name) - (jsx_self_closing_element name: (_)@name) -; #end -] { -if none @is_def { +(identifier)@name { node @name.cotype node @name.lexical_defs node @name.lexical_scope node @name.type node @name.var_defs -} -} -[ - (primary_expression/identifier)@name - (decorator (identifier)@name) - ; FIXME expansion of _lhs_expression/identifier and _augmented_assignment_lhs - ; we need to do this for every (identifier) inside a type query - ; this cannot be expressed, so we manually unroll three levels here - (for_in_statement ["var" "let" "const"]?@is_def left:(identifier)@name) - (assignment_expression left:(identifier)@name) - (augmented_assignment_expression left:(identifier)@name) - (asserts (identifier)@name) - (type_predicate name:(identifier)@name) - ; FIXME type_query has its own restricted expression production - (type_query (identifier)@name) - (type_query (member_expression object:(identifier)@name)) - (type_query (member_expression object:(member_expression object:(identifier)@name))) - (type_query (member_expression object:(member_expression object:(member_expression object:(identifier)@name)))) - (type_query (subscript_expression object:(identifier)@name)) - (type_query (subscript_expression object:(member_expression object:(identifier)@name))) - (type_query (subscript_expression object:(member_expression object:(member_expression object:(identifier)@name)))) - (type_query (call_expression function:(identifier)@name)) - (type_query (call_expression function:(member_expression object:(identifier)@name))) - (type_query (call_expression function:(member_expression object:(member_expression object:(identifier)@name)))) - (type_query (call_expression function:(member_expression object:(member_expression object:(member_expression object:(identifier)@name))))) - (type_query (call_expression function:(subscript_expression object:(identifier)@name))) - (type_query (call_expression function:(subscript_expression object:(member_expression object:(identifier)@name)))) - (type_query (call_expression function:(subscript_expression object:(member_expression object:(member_expression object:(identifier)@name))))) - ; FIXME decorator has its own restricted expression production - ; we need to do this for every (identifier) inside a decorator - ; this cannot be expressed, so we manually unroll three levels here - (decorator (identifier)@name) - (decorator (member_expression object:(identifier)@name)) - (decorator (member_expression object:(member_expression object:(identifier)@name))) - (decorator (member_expression object:(member_expression object:(member_expression object:(identifier)@name)))) - (decorator (call_expression function:(identifier)@name)) - (decorator (call_expression function:(member_expression object:(identifier)@name))) - (decorator (call_expression function:(member_expression object:(member_expression object:(identifier)@name)))) - (decorator (call_expression function:(member_expression object:(member_expression object:(member_expression object:(identifier)@name))))) -; #dialect tsx -; (nested_identifier object:(identifier)@name property:(identifier)) ; to pick up foo in JSX: ; FIXME never matched - (jsx_opening_element name: (identifier)@name) - (jsx_closing_element name: (identifier)@name) - (jsx_self_closing_element name: (identifier)@name) -; #end -] { -if none @is_def { node @name.expr_ref node @name.expr_ref__ns node @name.expr_ref__typeof @@ -2898,7 +2813,67 @@ if none @is_def { attr (@name.expr_ref__typeof) push_symbol = ":" edge @name.expr_ref__typeof -> @name.expr_ref } -} + +; [ +; (primary_expression/identifier)@name +; ; FIXME expansion of _lhs_expression/identifier and _augmented_assignment_lhs +; ; we need to do this for every (identifier) inside a type query +; ; this cannot be expressed, so we manually unroll three levels here +; (for_in_statement ["var" "let" "const"]?@is_def left:(identifier)@name) +; (assignment_expression left:(identifier)@name) +; (augmented_assignment_expression left:(identifier)@name) +; (asserts (identifier)@name) +; (type_predicate name:(identifier)@name) +; ; FIXME type_query has its own restricted expression production +; ; we need to do this for every (identifier) inside a type query +; ; this cannot be expressed, so we manually unroll three levels here +; (type_query (identifier)@name) +; (type_query (member_expression object:(identifier)@name)) +; (type_query (member_expression object:(member_expression object:(identifier)@name))) +; (type_query (member_expression object:(member_expression object:(member_expression object:(identifier)@name)))) +; (type_query (subscript_expression object:(identifier)@name)) +; (type_query (subscript_expression object:(member_expression object:(identifier)@name))) +; (type_query (subscript_expression object:(member_expression object:(member_expression object:(identifier)@name)))) +; (type_query (call_expression function:(identifier)@name)) +; (type_query (call_expression function:(member_expression object:(identifier)@name))) +; (type_query (call_expression function:(member_expression object:(member_expression object:(identifier)@name)))) +; (type_query (call_expression function:(member_expression object:(member_expression object:(member_expression object:(identifier)@name))))) +; (type_query (call_expression function:(subscript_expression object:(identifier)@name))) +; (type_query (call_expression function:(subscript_expression object:(member_expression object:(identifier)@name)))) +; (type_query (call_expression function:(subscript_expression object:(member_expression object:(member_expression object:(identifier)@name))))) +; ; FIXME decorator has its own restricted expression production +; ; we need to do this for every (identifier) inside a decorator +; ; this cannot be expressed, so we manually unroll three levels here +; (decorator (identifier)@name) +; (decorator (member_expression object:(identifier)@name)) +; (decorator (member_expression object:(member_expression object:(identifier)@name))) +; (decorator (member_expression object:(member_expression object:(member_expression object:(identifier)@name)))) +; (decorator (call_expression function:(identifier)@name)) +; (decorator (call_expression function:(member_expression object:(identifier)@name))) +; (decorator (call_expression function:(member_expression object:(member_expression object:(identifier)@name)))) +; (decorator (call_expression function:(member_expression object:(member_expression object:(member_expression object:(identifier)@name))))) +; ; FIXME nested_identifier has its own restricted expression production +; ; we need to do this for every (identifier) inside a decorator +; ; this cannot be expressed, so we manually unroll three levels here +; (nested_identifier object:(identifier)@name) +; (nested_identifier object:(member_expression object:(identifier)@name)) +; (nested_identifier object:(member_expression object:(member_expression object:(identifier)@name))) +; (nested_identifier object:(member_expression object:(member_expression object:(member_expression object:(identifier)@name)))) +; ; #dialect tsx +; (jsx_opening_element name: (identifier)@name) +; (jsx_closing_element name: (identifier)@name) +; (jsx_self_closing_element name: (identifier)@name) +; ; #end +; ] { +; if none @is_def { +; ; node @name.cotype +; ; node @name.lexical_defs +; ; node @name.lexical_scope +; ; node @name.type +; ; node @name.var_defs + +; } +; } @@ -3551,12 +3526,10 @@ if none @is_async { ; (member_expression (identifier) (property_identifier)) ; (subscript_expression (identifier) (string)) -[ - (member_expression object:(_)@object property:(_)@prop)@member_expr -; #dialect tsx -; (nested_identifier object:(_)@object property:(identifier)@prop)@member_expr ; FIXME this never matched anything! -; #end - ] { +(member_expression + object:(_)@object + property:(_)@prop +)@member_expr { node @member_expr.member node @prop.expr_ref node @prop.expr_ref__typeof @@ -3578,7 +3551,6 @@ if none @is_async { edge @prop.expr_ref__typeof -> @prop.expr_ref } - (subscript_expression object: (_)@object index: (_)@index @@ -4158,16 +4130,6 @@ if none @is_async { node @pat.defs } -[ ; NOTE these are the ones not also variables - (for_in_statement ["var" "let" "const"] left:(identifier)@name) - (variable_declarator name:(identifier)@name) - (pattern/identifier)@name - (rest_pattern (identifier)@name) -] { - node @name.cotype - node @name.lexical_scope -} - [ (for_in_statement ["var" "let" "const"] left:(identifier)@name) (variable_declarator name:(identifier)@name) @@ -5603,8 +5565,14 @@ if none @is_acc { [ ; X (nested_type_identifier module:(identifier)@name) - ; X._, _.X._ + ; X._ (nested_identifier object:(identifier)@name) + ; _.X._ + (member_expression object:(identifier)@name) + ; _.X + (nested_identifier property:(_)@name) + ; _._.X + (member_expression property:(_)@name) ] { node @name.type_ref attr (@name.type_ref) node_reference = @name @@ -5615,16 +5583,25 @@ if none @is_acc { edge @name.type_ref_member -> @name.type_ref } -(nested_identifier object:(_)@mod) @nested { +[ + (nested_identifier object:(_)@mod) + (member_expression object:[(member_expression) (identifier)]@mod) +]@nested { node @nested.type_ref edge @mod.type_ref -> @nested.type_ref } -(nested_identifier . (_)@mod . (_)@name .) { +[ + (nested_identifier object:(_)@mod property:(_)@name) + (member_expression object:[(member_expression) (identifier)]@mod property:(_)@name) +] { edge @name.type_ref -> @mod.type_ref_member } -(nested_identifier property:(_)@name) @nested { +[ + (nested_identifier property:(_)@name) + (member_expression property:(_)@name) +]@nested { node @nested.type_ref_member edge @nested.type_ref_member -> @name.type_ref_member } diff --git a/languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_namespace_name.tsx.skip b/languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_namespace_name.tsx similarity index 100% rename from languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_namespace_name.tsx.skip rename to languages/tree-sitter-stack-graphs-typescript/test/jsx/jsx_namespace_name.tsx diff --git a/languages/tree-sitter-stack-graphs-typescript/test/modules/very-deep-namespace.ts.skip b/languages/tree-sitter-stack-graphs-typescript/test/modules/very-deep-namespace.ts similarity index 100% rename from languages/tree-sitter-stack-graphs-typescript/test/modules/very-deep-namespace.ts.skip rename to languages/tree-sitter-stack-graphs-typescript/test/modules/very-deep-namespace.ts diff --git a/languages/tree-sitter-stack-graphs-typescript/test/statements/refer-to-interface-in-nested-namespace-by-fully-qualified-name.ts.skip b/languages/tree-sitter-stack-graphs-typescript/test/statements/refer-to-interface-in-nested-namespace-by-fully-qualified-name.ts similarity index 100% rename from languages/tree-sitter-stack-graphs-typescript/test/statements/refer-to-interface-in-nested-namespace-by-fully-qualified-name.ts.skip rename to languages/tree-sitter-stack-graphs-typescript/test/statements/refer-to-interface-in-nested-namespace-by-fully-qualified-name.ts diff --git a/languages/tree-sitter-stack-graphs-typescript/test/statements/refer-to-interface-in-qualified-namespace-by-fully-qualified-name.ts.skip b/languages/tree-sitter-stack-graphs-typescript/test/statements/refer-to-interface-in-qualified-namespace-by-fully-qualified-name.ts similarity index 100% rename from languages/tree-sitter-stack-graphs-typescript/test/statements/refer-to-interface-in-qualified-namespace-by-fully-qualified-name.ts.skip rename to languages/tree-sitter-stack-graphs-typescript/test/statements/refer-to-interface-in-qualified-namespace-by-fully-qualified-name.ts From bba2dc482d1206209837f699f49527895c48619e Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Dec 2024 12:32:35 +0100 Subject: [PATCH 484/500] Try updated runner image to fix valgrind problem --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0d6ec91bb..f217e8140 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,9 @@ concurrency: jobs: test-rust: - runs-on: ubuntu-latest + # We force a newer runner version to fix a problem with Valgrind. + # Currently, ubuntu-latest is set to 22.04. Revert this back to ubuntu-latest once it is set to 24.04. + runs-on: ubuntu-24.04 strategy: matrix: rust: [stable] From aea8b85a19746326c8e707f6b10ea724b6f78c74 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Dec 2024 12:06:30 +0000 Subject: [PATCH 485/500] Ignore Valgrind warnings introduced by Rust 1.83 --- .github/workflows/ci.yml | 4 +++ stack-graphs/valgrind.supp | 74 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 stack-graphs/valgrind.supp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f217e8140..36cab862c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,6 +57,10 @@ jobs: - name: Run test suite under valgrind (default features) # We only need to use valgrind to test the crates that have C bindings. run: cargo valgrind test -p stack-graphs + env: + # Since Rust 1.83, Valgrind reports some possible leaks that cargo-valgrind + # treats as fatal. The given suppressions file makes sure these are ignored. + VALGRINDFLAGS: --suppressions=valgrind.supp - name: Ensure C headers are up to date run: | script/cbindgen diff --git a/stack-graphs/valgrind.supp b/stack-graphs/valgrind.supp new file mode 100644 index 000000000..3986abc5b --- /dev/null +++ b/stack-graphs/valgrind.supp @@ -0,0 +1,74 @@ +{ + rust-1.83-false-positive-1 + Memcheck:Param + statx(file_name) + fun:statx + fun:statx + fun:_ZN3std3sys3pal4unix2fs9try_statx17h2609435043bb8525E + fun:{closure#0} + fun:run_with_cstr_stack + fun:run_with_cstr + fun:run_path_with_cstr + fun:_ZN3std3sys3pal4unix2fs4stat17ha588398797a44835E + fun:metadata<&std::path::PathBuf> + fun:get_dbpath_for_term + fun:from_name + fun:_ZN4test4term8terminfo8TermInfo8from_env17h9b3ad5763ddd396cE + fun:new + fun:_ZN4test4term6stdout17hf274a19176f765bcE + fun:_ZN4test7console17run_tests_console17h3d81643311f50681E + fun:_ZN4test9test_main17h6c0fc3221ed0faa4E + fun:_ZN4test16test_main_static17h897b969e33229363E + fun:_ZN2it4main17hfbc3179ed1c35941E + fun:_ZN4core3ops8function6FnOnce9call_once17h945f64a17647f84cE + fun:_ZN3std3sys9backtrace28__rust_begin_short_backtrace17h41138d0332b09746E + fun:_ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h98fa5fc32f9b0a38E +} +{ + rust-1.83-false-positive-2 + Memcheck:Param + statx(buf) + fun:statx + fun:statx + fun:_ZN3std3sys3pal4unix2fs9try_statx17h2609435043bb8525E + fun:{closure#0} + fun:run_with_cstr_stack + fun:run_with_cstr + fun:run_path_with_cstr + fun:_ZN3std3sys3pal4unix2fs4stat17ha588398797a44835E + fun:metadata<&std::path::PathBuf> + fun:get_dbpath_for_term + fun:from_name + fun:_ZN4test4term8terminfo8TermInfo8from_env17h9b3ad5763ddd396cE + fun:new + fun:_ZN4test4term6stdout17hf274a19176f765bcE + fun:_ZN4test7console17run_tests_console17h3d81643311f50681E + fun:_ZN4test9test_main17h6c0fc3221ed0faa4E + fun:_ZN4test16test_main_static17h897b969e33229363E + fun:_ZN2it4main17hfbc3179ed1c35941E + fun:_ZN4core3ops8function6FnOnce9call_once17h945f64a17647f84cE + fun:_ZN3std3sys9backtrace28__rust_begin_short_backtrace17h41138d0332b09746E + fun:_ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h98fa5fc32f9b0a38E +} +{ + rust-1.83-false-positive-3 + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + fun:alloc + fun:alloc_impl + fun:allocate + fun:{closure#0} + fun:allocate_for_layout, alloc::sync::{impl#14}::new_uninit::{closure_env#0}, fn(*mut u8) -> *mut alloc::sync::ArcInner>> + fun:new_uninit + fun:new_inner + fun:new_main + fun:init + fun:{closure#0} + fun:do_call + fun:try<(), std::rt::lang_start_internal::{closure_env#0}> + fun:catch_unwind + fun:_ZN3std2rt19lang_start_internal17h1c66660c99c8424cE + fun:_ZN3std2rt10lang_start17hb778ad044944e8a4E + fun:main +} From af722227cfdffc9823bb40c39be89cfcc763b5ef Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Dec 2024 13:14:42 +0100 Subject: [PATCH 486/500] Set release dates --- languages/tree-sitter-stack-graphs-java/CHANGELOG.md | 2 +- languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md | 2 +- languages/tree-sitter-stack-graphs-python/CHANGELOG.md | 2 +- lsp-positions/CHANGELOG.md | 2 +- stack-graphs/CHANGELOG.md | 2 +- tree-sitter-stack-graphs/CHANGELOG.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-java/CHANGELOG.md b/languages/tree-sitter-stack-graphs-java/CHANGELOG.md index 23400faf0..d295d8ce0 100644 --- a/languages/tree-sitter-stack-graphs-java/CHANGELOG.md +++ b/languages/tree-sitter-stack-graphs-java/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v0.5.0 -- Unreleased +## v0.5.0 -- 2024-12-12 - The `tree-sitter-stack-graphs` dependency is updated to version 0.10. diff --git a/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md b/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md index 10f85abdd..ae90a2f01 100644 --- a/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md +++ b/languages/tree-sitter-stack-graphs-javascript/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v0.3.0 -- Unreleased +## v0.3.0 -- 2024-12-12 - The `tree-sitter-stack-graphs` dependency is updated to version 0.10. diff --git a/languages/tree-sitter-stack-graphs-python/CHANGELOG.md b/languages/tree-sitter-stack-graphs-python/CHANGELOG.md index 8ec44913d..f21aecc9f 100644 --- a/languages/tree-sitter-stack-graphs-python/CHANGELOG.md +++ b/languages/tree-sitter-stack-graphs-python/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v0.3.0 -- Unreleased +## v0.3.0 -- 2024-12-12 - The `tree-sitter-stack-graphs` dependency is updated to version 0.10. diff --git a/lsp-positions/CHANGELOG.md b/lsp-positions/CHANGELOG.md index 84aa962b4..f80bc5c5d 100644 --- a/lsp-positions/CHANGELOG.md +++ b/lsp-positions/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v0.3.4 -- Unreleased +## v0.3.4 -- 2024-12-12 Upgraded the `tree-sitter` dependency to version 0.24. diff --git a/stack-graphs/CHANGELOG.md b/stack-graphs/CHANGELOG.md index aae6a2998..802275fc2 100644 --- a/stack-graphs/CHANGELOG.md +++ b/stack-graphs/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v0.14.1 -- Unpublished +## v0.14.1 -- 2024-12-12 ### Fixed diff --git a/tree-sitter-stack-graphs/CHANGELOG.md b/tree-sitter-stack-graphs/CHANGELOG.md index b45b69b64..e1df552e4 100644 --- a/tree-sitter-stack-graphs/CHANGELOG.md +++ b/tree-sitter-stack-graphs/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v0.10.0 -- Unreleased +## v0.10.0 -- 2024-12-12 Upgraded `tree-sitter` dependency to version 0.24. From 0bd07ba011ac7ae519e246af395e0c80d85eec8f Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Dec 2024 13:19:48 +0100 Subject: [PATCH 487/500] Update test dependency version --- script/ci-test-init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/ci-test-init b/script/ci-test-init index c58532fd5..0ecc60788 100755 --- a/script/ci-test-init +++ b/script/ci-test-init @@ -7,7 +7,7 @@ cargo run --bin tree-sitter-stack-graphs --features cli -- init \ --language-id init_test \ --language-file-extension it \ --grammar-crate-name tree-sitter-python \ - --grammar-crate-version 0.20.0 \ + --grammar-crate-version 0.23.2 \ --internal \ --non-interactive From 68ce497b225fdccf34347d87b6458aca41b8bb5e Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Dec 2024 13:51:20 +0100 Subject: [PATCH 488/500] Bump actions versions --- .github/workflows/ci.yml | 18 +++++------ .github/workflows/perf.yml | 30 +++++++++---------- .github/workflows/publish-lsp-positions.yml | 4 +-- .github/workflows/publish-stack-graphs.yml | 4 +-- .../publish-tree-sitter-stack-graphs-java.yml | 4 +-- ...sh-tree-sitter-stack-graphs-javascript.yml | 4 +-- ...ublish-tree-sitter-stack-graphs-python.yml | 4 +-- ...sh-tree-sitter-stack-graphs-typescript.yml | 4 +-- .../publish-tree-sitter-stack-graphs.yml | 4 +-- 9 files changed, 38 insertions(+), 38 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 36cab862c..41105a33c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,11 +31,11 @@ jobs: - name: Install cargo-hack run: cargo install cargo-hack - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Check formatting run: cargo fmt --all -- --check - name: Cache dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ~/.cargo @@ -79,9 +79,9 @@ jobs: with: rust-version: ${{ matrix.rust }} - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Cache dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ~/.cargo @@ -99,7 +99,7 @@ jobs: working-directory: languages steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: List languages id: language-list run: echo "languages=$(find -mindepth 1 -maxdepth 1 -type d -printf '%P\n' | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT @@ -122,7 +122,7 @@ jobs: - name: Install cargo-hack run: cargo install cargo-hack - name: Cache dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ~/.cargo @@ -131,7 +131,7 @@ jobs: restore-keys: | ${{ runner.OS }}-cargo- - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build (all feature combinations) run: cargo hack -p ${{ matrix.language }} --feature-powerset build - name: Test (all features) @@ -152,7 +152,7 @@ jobs: with: rust-version: ${{ matrix.rust }} - name: Cache dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ~/.cargo @@ -161,7 +161,7 @@ jobs: restore-keys: | ${{ runner.OS }}-cargo- - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: lfs: true - name: Build diff --git a/.github/workflows/perf.yml b/.github/workflows/perf.yml index 5c4288c84..7da0f9ef8 100644 --- a/.github/workflows/perf.yml +++ b/.github/workflows/perf.yml @@ -37,7 +37,7 @@ jobs: done: ${{ steps.done.outputs.cache-hit }} steps: - name: "Checkout base code" - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ${{ env.BASE_REPO }} ref: ${{ env.BASE_SHA }} @@ -49,7 +49,7 @@ jobs: printf 'BASE_SHA=%s\n' "$(git rev-list -1 ${{ env.BASE_SHA }} -- stack-graphs)" >> $GITHUB_ENV working-directory: ${{ env.BASE_DIR }} - name: "Checkout head code" - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ${{ env.HEAD_REPO }} ref: ${{ env.HEAD_SHA }} @@ -62,7 +62,7 @@ jobs: working-directory: ${{ env.HEAD_DIR }} - name: "Check cached status" id: done - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: done key: ${{ runner.os }}-perf-tested-${{ env.BASE_REPO }}@${{ env.BASE_SHA }}-${{ env.HEAD_REPO }}@${{ env.HEAD_SHA }}-${{ env.TEST_NAME }} @@ -83,7 +83,7 @@ jobs: with: rust-version: stable - name: Cache Rust dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ~/.cargo @@ -94,7 +94,7 @@ jobs: sudo apt-get install -y valgrind - name: "Cache base result" id: cache-base-result - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ${{ env.MASSIF_OUT }} @@ -102,7 +102,7 @@ jobs: key: ${{ runner.os }}-perf-result-${{ env.BASE_REPO }}@${{ env.BASE_SHA }}-${{ env.TEST_NAME }} - name: "Checkout base code" if: steps.cache-base-result.outputs.cache-hit != 'true' - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ${{ env.BASE_REPO }} ref: ${{ env.BASE_SHA }} @@ -130,7 +130,7 @@ jobs: ${{ env.BASE_DIR }}/data/${{ env.TEST_NAME }} ms_print ${{ env.MASSIF_OUT }} > ${{ env.MASSIF_REPORT }} - name: Upload results - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ env.BASE_ARTIFACT }} path: | @@ -152,7 +152,7 @@ jobs: with: rust-version: stable - name: Cache Rust dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ~/.cargo @@ -163,7 +163,7 @@ jobs: sudo apt-get install -y valgrind - name: "Cache head result" id: cache-head-result - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ${{ env.MASSIF_OUT }} @@ -171,7 +171,7 @@ jobs: key: ${{ runner.os }}-perf-result-${{ env.HEAD_REPO }}@${{ env.HEAD_SHA }}-${{ env.TEST_NAME }} - name: "Checkout head code" if: steps.cache-head-result.outputs.cache-hit != 'true' - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ${{ env.HEAD_REPO }} ref: ${{ env.HEAD_SHA }} @@ -199,7 +199,7 @@ jobs: ${{ env.HEAD_DIR }}/data/${{ env.TEST_NAME }} ms_print ${{ env.MASSIF_OUT }} > ${{ env.MASSIF_REPORT }} - name: Upload results - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ env.HEAD_ARTIFACT }} path: | @@ -233,12 +233,12 @@ jobs: # Download results # - name: Download base results - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: ${{ env.BASE_ARTIFACT }} path: ${{ env.BASE_ARTIFACT }} - name: Download head results - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: ${{ env.HEAD_ARTIFACT }} path: ${{ env.HEAD_ARTIFACT }} @@ -246,7 +246,7 @@ jobs: # Create report # - name: "Checkout code" - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: ${{ env.SRC_DIR }} - name: Generate summary @@ -268,7 +268,7 @@ jobs: - name: Create status marker run: touch done - name: "Cache status" - uses: actions/cache/save@v3 + uses: actions/cache/save@v4 with: path: done key: ${{ runner.os }}-perf-tested-${{ env.BASE_REPO }}@${{ env.BASE_SHA }}-${{ env.HEAD_REPO }}@${{ env.HEAD_SHA }}-${{ env.TEST_NAME }} diff --git a/.github/workflows/publish-lsp-positions.yml b/.github/workflows/publish-lsp-positions.yml index 210662a00..dd021646b 100644 --- a/.github/workflows/publish-lsp-positions.yml +++ b/.github/workflows/publish-lsp-positions.yml @@ -16,7 +16,7 @@ jobs: - name: Install Rust environment uses: hecrj/setup-rust-action@v1 - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # TODO Verify the crate version matches the tag - name: Test crate run: cargo test --all-features @@ -36,7 +36,7 @@ jobs: contents: write steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Create GitHub release uses: ncipollo/release-action@v1 with: diff --git a/.github/workflows/publish-stack-graphs.yml b/.github/workflows/publish-stack-graphs.yml index 641a93488..b94e0337f 100644 --- a/.github/workflows/publish-stack-graphs.yml +++ b/.github/workflows/publish-stack-graphs.yml @@ -16,7 +16,7 @@ jobs: - name: Install Rust environment uses: hecrj/setup-rust-action@v1 - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # TODO Verify the crate version matches the tag - name: Test crate run: cargo test --all-features @@ -36,7 +36,7 @@ jobs: contents: write steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Create GitHub release uses: ncipollo/release-action@v1 with: diff --git a/.github/workflows/publish-tree-sitter-stack-graphs-java.yml b/.github/workflows/publish-tree-sitter-stack-graphs-java.yml index 6d7afb769..64e9f3bf2 100644 --- a/.github/workflows/publish-tree-sitter-stack-graphs-java.yml +++ b/.github/workflows/publish-tree-sitter-stack-graphs-java.yml @@ -16,7 +16,7 @@ jobs: - name: Install Rust environment uses: hecrj/setup-rust-action@v1 - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # TODO Verify the crate version matches the tag - name: Test crate run: cargo test --all-features @@ -36,7 +36,7 @@ jobs: contents: write steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Create GitHub release uses: ncipollo/release-action@v1 with: diff --git a/.github/workflows/publish-tree-sitter-stack-graphs-javascript.yml b/.github/workflows/publish-tree-sitter-stack-graphs-javascript.yml index ff6826770..48375d9d4 100644 --- a/.github/workflows/publish-tree-sitter-stack-graphs-javascript.yml +++ b/.github/workflows/publish-tree-sitter-stack-graphs-javascript.yml @@ -16,7 +16,7 @@ jobs: - name: Install Rust environment uses: hecrj/setup-rust-action@v1 - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # TODO Verify the crate version matches the tag - name: Test crate run: cargo test --all-features @@ -36,7 +36,7 @@ jobs: contents: write steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Create GitHub release uses: ncipollo/release-action@v1 with: diff --git a/.github/workflows/publish-tree-sitter-stack-graphs-python.yml b/.github/workflows/publish-tree-sitter-stack-graphs-python.yml index 5d6c83ba2..77804c28e 100644 --- a/.github/workflows/publish-tree-sitter-stack-graphs-python.yml +++ b/.github/workflows/publish-tree-sitter-stack-graphs-python.yml @@ -16,7 +16,7 @@ jobs: - name: Install Rust environment uses: hecrj/setup-rust-action@v1 - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # TODO Verify the crate version matches the tag - name: Test crate run: cargo test --all-features @@ -36,7 +36,7 @@ jobs: contents: write steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Create GitHub release uses: ncipollo/release-action@v1 with: diff --git a/.github/workflows/publish-tree-sitter-stack-graphs-typescript.yml b/.github/workflows/publish-tree-sitter-stack-graphs-typescript.yml index a3409f397..3fdbe17e2 100644 --- a/.github/workflows/publish-tree-sitter-stack-graphs-typescript.yml +++ b/.github/workflows/publish-tree-sitter-stack-graphs-typescript.yml @@ -16,7 +16,7 @@ jobs: - name: Install Rust environment uses: hecrj/setup-rust-action@v1 - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # TODO Verify the crate version matches the tag - name: Test crate run: cargo test --all-features @@ -36,7 +36,7 @@ jobs: contents: write steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Create GitHub release uses: ncipollo/release-action@v1 with: diff --git a/.github/workflows/publish-tree-sitter-stack-graphs.yml b/.github/workflows/publish-tree-sitter-stack-graphs.yml index 031289464..2dfb743a1 100644 --- a/.github/workflows/publish-tree-sitter-stack-graphs.yml +++ b/.github/workflows/publish-tree-sitter-stack-graphs.yml @@ -16,7 +16,7 @@ jobs: - name: Install Rust environment uses: hecrj/setup-rust-action@v1 - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # TODO Verify the crate version matches the tag - name: Test crate run: cargo test --all-features @@ -36,7 +36,7 @@ jobs: contents: write steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Create GitHub release uses: ncipollo/release-action@v1 with: From b3409fca73900d01656d02ddea86084a37b25e8d Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Dec 2024 13:59:37 +0100 Subject: [PATCH 489/500] Revert "Try updated runner image to fix valgrind problem" This reverts commit bba2dc482d1206209837f699f49527895c48619e. --- .github/workflows/ci.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 41105a33c..0b025b26d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,9 +13,7 @@ concurrency: jobs: test-rust: - # We force a newer runner version to fix a problem with Valgrind. - # Currently, ubuntu-latest is set to 22.04. Revert this back to ubuntu-latest once it is set to 24.04. - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest strategy: matrix: rust: [stable] From 11c05cb0b49c9330ad077fdfce13768d016e449d Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Dec 2024 13:19:15 +0000 Subject: [PATCH 490/500] Simplify suppresion traces --- stack-graphs/valgrind.supp | 56 ++++---------------------------------- 1 file changed, 6 insertions(+), 50 deletions(-) diff --git a/stack-graphs/valgrind.supp b/stack-graphs/valgrind.supp index 3986abc5b..dbccaa257 100644 --- a/stack-graphs/valgrind.supp +++ b/stack-graphs/valgrind.supp @@ -3,72 +3,28 @@ Memcheck:Param statx(file_name) fun:statx - fun:statx - fun:_ZN3std3sys3pal4unix2fs9try_statx17h2609435043bb8525E - fun:{closure#0} - fun:run_with_cstr_stack - fun:run_with_cstr - fun:run_path_with_cstr - fun:_ZN3std3sys3pal4unix2fs4stat17ha588398797a44835E - fun:metadata<&std::path::PathBuf> + ... fun:get_dbpath_for_term - fun:from_name - fun:_ZN4test4term8terminfo8TermInfo8from_env17h9b3ad5763ddd396cE - fun:new - fun:_ZN4test4term6stdout17hf274a19176f765bcE - fun:_ZN4test7console17run_tests_console17h3d81643311f50681E - fun:_ZN4test9test_main17h6c0fc3221ed0faa4E - fun:_ZN4test16test_main_static17h897b969e33229363E - fun:_ZN2it4main17hfbc3179ed1c35941E - fun:_ZN4core3ops8function6FnOnce9call_once17h945f64a17647f84cE - fun:_ZN3std3sys9backtrace28__rust_begin_short_backtrace17h41138d0332b09746E - fun:_ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h98fa5fc32f9b0a38E + ... } { rust-1.83-false-positive-2 Memcheck:Param statx(buf) fun:statx - fun:statx - fun:_ZN3std3sys3pal4unix2fs9try_statx17h2609435043bb8525E - fun:{closure#0} - fun:run_with_cstr_stack - fun:run_with_cstr - fun:run_path_with_cstr - fun:_ZN3std3sys3pal4unix2fs4stat17ha588398797a44835E - fun:metadata<&std::path::PathBuf> + ... fun:get_dbpath_for_term - fun:from_name - fun:_ZN4test4term8terminfo8TermInfo8from_env17h9b3ad5763ddd396cE - fun:new - fun:_ZN4test4term6stdout17hf274a19176f765bcE - fun:_ZN4test7console17run_tests_console17h3d81643311f50681E - fun:_ZN4test9test_main17h6c0fc3221ed0faa4E - fun:_ZN4test16test_main_static17h897b969e33229363E - fun:_ZN2it4main17hfbc3179ed1c35941E - fun:_ZN4core3ops8function6FnOnce9call_once17h945f64a17647f84cE - fun:_ZN3std3sys9backtrace28__rust_begin_short_backtrace17h41138d0332b09746E - fun:_ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h98fa5fc32f9b0a38E + ... } { rust-1.83-false-positive-3 Memcheck:Leak match-leak-kinds: possible fun:malloc - fun:alloc - fun:alloc_impl - fun:allocate - fun:{closure#0} - fun:allocate_for_layout, alloc::sync::{impl#14}::new_uninit::{closure_env#0}, fn(*mut u8) -> *mut alloc::sync::ArcInner>> + ... fun:new_uninit fun:new_inner fun:new_main fun:init - fun:{closure#0} - fun:do_call - fun:try<(), std::rt::lang_start_internal::{closure_env#0}> - fun:catch_unwind - fun:_ZN3std2rt19lang_start_internal17h1c66660c99c8424cE - fun:_ZN3std2rt10lang_start17hb778ad044944e8a4E - fun:main + ... } From e3b1afea05c5c32244c5fee06a5bfe649fc4d505 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Dec 2024 14:33:36 +0100 Subject: [PATCH 491/500] Save valgrind logs on failure --- .github/workflows/ci.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0b025b26d..1c2c613d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,7 +58,13 @@ jobs: env: # Since Rust 1.83, Valgrind reports some possible leaks that cargo-valgrind # treats as fatal. The given suppressions file makes sure these are ignored. - VALGRINDFLAGS: --suppressions=valgrind.supp + VALGRINDFLAGS: --suppressions=valgrind.supp --gen-suppressions=all --log-file=${{ runner.temp }}/valgrind.log + - name: Upload valgrind log + if: ${{ failure() }} + uses: actions/upload-artifact@v4 + with: + name: valgrind logs + path: ${{ runner.temp }}/valgrind.log - name: Ensure C headers are up to date run: | script/cbindgen From 9998fbd2f42b1665475aa2cbf71515d4fa8abf2c Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Dec 2024 14:21:27 +0000 Subject: [PATCH 492/500] Custom valgrind runner to allow capturing logs --- .github/workflows/ci.yml | 12 ++++------- script/ci-test-valgrind | 23 +++++++++++++++++++++ stack-graphs/valgrind.supp => valgrind.supp | 0 3 files changed, 27 insertions(+), 8 deletions(-) create mode 100755 script/ci-test-valgrind rename stack-graphs/valgrind.supp => valgrind.supp (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c2c613d9..adc70b3c8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,20 +47,16 @@ jobs: run: ${{ env.CARGO_HACK }} test - name: Run test suite with all optimizations (default features) run: cargo test --release - - name: Install cargo-valgrind + - name: Install valgrind run: | sudo apt-get update sudo apt-get install -y valgrind - cargo install cargo-valgrind - name: Run test suite under valgrind (default features) + id: valgrind # We only need to use valgrind to test the crates that have C bindings. - run: cargo valgrind test -p stack-graphs - env: - # Since Rust 1.83, Valgrind reports some possible leaks that cargo-valgrind - # treats as fatal. The given suppressions file makes sure these are ignored. - VALGRINDFLAGS: --suppressions=valgrind.supp --gen-suppressions=all --log-file=${{ runner.temp }}/valgrind.log + run: script/ci-test-valgrind -p stack-graphs - name: Upload valgrind log - if: ${{ failure() }} + if: ${{ failure() && steps.valgrind.outcome == 'failure' }} uses: actions/upload-artifact@v4 with: name: valgrind logs diff --git a/script/ci-test-valgrind b/script/ci-test-valgrind new file mode 100755 index 000000000..3f5e3dae6 --- /dev/null +++ b/script/ci-test-valgrind @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +set -eu + +# Start by building the test binary, before we try to get its filename +cargo test "$@" --no-run + +# Cargo does not have a clean way to get the test binary, so we do some text processing here to get it +test="$(cargo test "$@" --no-run 2>&1 | grep 'Executable' | head -1 | sed -e 's/[^(]*(\(.*\)).*$/\1/')" +log="${RUNNER_TEMP-.}/valgrind.log" + +# Run the test binary under valgrind +if ! valgrind \ + --leak-check=full \ + --show-leak-kinds=all \ + --error-exitcode=1 \ + --suppressions=valgrind.supp \ + --gen-suppressions=all \ + --log-file="$log" \ + "$test"; then + echo "Valgrind detected errors! See logs: $log" + exit 1 +fi diff --git a/stack-graphs/valgrind.supp b/valgrind.supp similarity index 100% rename from stack-graphs/valgrind.supp rename to valgrind.supp From d2fd2281ef18af9c822e6cdcbc20f971c09be276 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Dec 2024 14:28:15 +0000 Subject: [PATCH 493/500] Update suppressions from CI log --- valgrind.supp | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/valgrind.supp b/valgrind.supp index dbccaa257..19b8bb400 100644 --- a/valgrind.supp +++ b/valgrind.supp @@ -1,30 +1,9 @@ { rust-1.83-false-positive-1 - Memcheck:Param - statx(file_name) - fun:statx - ... - fun:get_dbpath_for_term - ... -} -{ - rust-1.83-false-positive-2 - Memcheck:Param - statx(buf) - fun:statx - ... - fun:get_dbpath_for_term - ... -} -{ - rust-1.83-false-positive-3 Memcheck:Leak match-leak-kinds: possible fun:malloc - ... - fun:new_uninit - fun:new_inner - fun:new_main - fun:init - ... + fun:_ZN3std2rt19lang_start_internal17h1c66660c99c8424cE + fun:_ZN3std2rt10lang_start17hb778ad044944e8a4E + fun:main } From 6223c06da3344bd5336cc61c70633985c4c73860 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Thu, 12 Dec 2024 14:40:17 +0000 Subject: [PATCH 494/500] Remove mangled entries --- valgrind.supp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/valgrind.supp b/valgrind.supp index 19b8bb400..25c3cfbda 100644 --- a/valgrind.supp +++ b/valgrind.supp @@ -3,7 +3,6 @@ Memcheck:Leak match-leak-kinds: possible fun:malloc - fun:_ZN3std2rt19lang_start_internal17h1c66660c99c8424cE - fun:_ZN3std2rt10lang_start17hb778ad044944e8a4E + ... fun:main } From 5d82a0c6f028d1b028319097fbf33261a66fa2dd Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Fri, 13 Dec 2024 13:56:56 +0100 Subject: [PATCH 495/500] Bump tree-sitter-stack-graphs-typescript version --- languages/tree-sitter-stack-graphs-typescript/CHANGELOG.md | 6 ++++++ languages/tree-sitter-stack-graphs-typescript/Cargo.toml | 2 +- languages/tree-sitter-stack-graphs-typescript/README.md | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-typescript/CHANGELOG.md b/languages/tree-sitter-stack-graphs-typescript/CHANGELOG.md index 47539831f..5a3bfa3d4 100644 --- a/languages/tree-sitter-stack-graphs-typescript/CHANGELOG.md +++ b/languages/tree-sitter-stack-graphs-typescript/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v0.4.0 -- 2024-12-13 + +- The `tree-sitter-stack-graphs` dependency is updated to version 0.10. + +- The `tree-sitter-typescript` dependency is updated to version 0.23.2. + ## v0.3.0 -- 2024-07-09 ### Added diff --git a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml index 379d4d3fe..ed14d9112 100644 --- a/languages/tree-sitter-stack-graphs-typescript/Cargo.toml +++ b/languages/tree-sitter-stack-graphs-typescript/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tree-sitter-stack-graphs-typescript" -version = "0.3.0" +version = "0.4.0" description = "Stack graphs definition for TypeScript & TSX using tree-sitter-typescript" readme = "README.md" keywords = ["tree-sitter", "stack-graphs", "typescript", "tsx"] diff --git a/languages/tree-sitter-stack-graphs-typescript/README.md b/languages/tree-sitter-stack-graphs-typescript/README.md index 46079a19a..c83d5849d 100644 --- a/languages/tree-sitter-stack-graphs-typescript/README.md +++ b/languages/tree-sitter-stack-graphs-typescript/README.md @@ -13,7 +13,7 @@ To use this library, add the following to your `Cargo.toml`: ```toml [dependencies] -tree-sitter-stack-graphs-typescript = "0.3" +tree-sitter-stack-graphs-typescript = "0.4" ``` Check out our [documentation](https://docs.rs/tree-sitter-stack-graphs-typescript/*/) for more details on how to use this library. From 7fe3e0dc69ec5ab4054b511814e27e77be4c0b5b Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 4 Mar 2025 13:47:17 +0100 Subject: [PATCH 496/500] Pin thrid party actions to SHA --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/perf.yml | 4 ++-- .github/workflows/publish-lsp-positions.yml | 4 ++-- .github/workflows/publish-stack-graphs.yml | 4 ++-- .../workflows/publish-tree-sitter-stack-graphs-java.yml | 4 ++-- .../publish-tree-sitter-stack-graphs-javascript.yml | 4 ++-- .../workflows/publish-tree-sitter-stack-graphs-python.yml | 4 ++-- .../publish-tree-sitter-stack-graphs-typescript.yml | 4 ++-- .github/workflows/publish-tree-sitter-stack-graphs.yml | 4 ++-- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index adc70b3c8..89be35c39 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Install Rust environment - uses: hecrj/setup-rust-action@v1 + uses: hecrj/setup-rust-action@110f36749599534ca96628b82f52ae67e5d95a3c # v2 with: rust-version: ${{ matrix.rust }} - name: Install cargo-hack @@ -75,7 +75,7 @@ jobs: steps: - name: Install Rust environment - uses: hecrj/setup-rust-action@v1 + uses: hecrj/setup-rust-action@110f36749599534ca96628b82f52ae67e5d95a3c # v2 with: rust-version: ${{ matrix.rust }} - name: Checkout code @@ -116,7 +116,7 @@ jobs: steps: - name: Install Rust environment - uses: hecrj/setup-rust-action@v1 + uses: hecrj/setup-rust-action@110f36749599534ca96628b82f52ae67e5d95a3c # v2 with: rust-version: ${{ matrix.rust }} - name: Install cargo-hack @@ -148,7 +148,7 @@ jobs: steps: - name: Install Rust environment - uses: hecrj/setup-rust-action@v1 + uses: hecrj/setup-rust-action@110f36749599534ca96628b82f52ae67e5d95a3c # v2 with: rust-version: ${{ matrix.rust }} - name: Cache dependencies diff --git a/.github/workflows/perf.yml b/.github/workflows/perf.yml index 7da0f9ef8..1930ff2fb 100644 --- a/.github/workflows/perf.yml +++ b/.github/workflows/perf.yml @@ -79,7 +79,7 @@ jobs: BASE_SHA: ${{ needs.changes.outputs.base-sha }} steps: - name: Install Rust environment - uses: hecrj/setup-rust-action@v1 + uses: hecrj/setup-rust-action@110f36749599534ca96628b82f52ae67e5d95a3c # v2 with: rust-version: stable - name: Cache Rust dependencies @@ -148,7 +148,7 @@ jobs: HEAD_SHA: ${{ needs.changes.outputs.head-sha }} steps: - name: Install Rust environment - uses: hecrj/setup-rust-action@v1 + uses: hecrj/setup-rust-action@110f36749599534ca96628b82f52ae67e5d95a3c # v2 with: rust-version: stable - name: Cache Rust dependencies diff --git a/.github/workflows/publish-lsp-positions.yml b/.github/workflows/publish-lsp-positions.yml index dd021646b..5c48ed71f 100644 --- a/.github/workflows/publish-lsp-positions.yml +++ b/.github/workflows/publish-lsp-positions.yml @@ -14,7 +14,7 @@ jobs: CRATE_DIR: './lsp-positions' steps: - name: Install Rust environment - uses: hecrj/setup-rust-action@v1 + uses: hecrj/setup-rust-action@110f36749599534ca96628b82f52ae67e5d95a3c # v2 - name: Checkout repository uses: actions/checkout@v4 # TODO Verify the crate version matches the tag @@ -38,7 +38,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Create GitHub release - uses: ncipollo/release-action@v1 + uses: ncipollo/release-action@440c8c1cb0ed28b9f43e4d1d670870f059653174 # v1 with: body: | Find more info on all releases at https://crates.io/crates/lsp-positions. diff --git a/.github/workflows/publish-stack-graphs.yml b/.github/workflows/publish-stack-graphs.yml index b94e0337f..cc7b6667b 100644 --- a/.github/workflows/publish-stack-graphs.yml +++ b/.github/workflows/publish-stack-graphs.yml @@ -14,7 +14,7 @@ jobs: CRATE_DIR: './stack-graphs' steps: - name: Install Rust environment - uses: hecrj/setup-rust-action@v1 + uses: hecrj/setup-rust-action@110f36749599534ca96628b82f52ae67e5d95a3c # v2 - name: Checkout repository uses: actions/checkout@v4 # TODO Verify the crate version matches the tag @@ -38,7 +38,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Create GitHub release - uses: ncipollo/release-action@v1 + uses: ncipollo/release-action@440c8c1cb0ed28b9f43e4d1d670870f059653174 # v1 with: body: | Find more info on all releases at https://crates.io/crates/stack-graphs. diff --git a/.github/workflows/publish-tree-sitter-stack-graphs-java.yml b/.github/workflows/publish-tree-sitter-stack-graphs-java.yml index 64e9f3bf2..31196048c 100644 --- a/.github/workflows/publish-tree-sitter-stack-graphs-java.yml +++ b/.github/workflows/publish-tree-sitter-stack-graphs-java.yml @@ -14,7 +14,7 @@ jobs: CRATE_DIR: './languages/tree-sitter-stack-graphs-java' steps: - name: Install Rust environment - uses: hecrj/setup-rust-action@v1 + uses: hecrj/setup-rust-action@110f36749599534ca96628b82f52ae67e5d95a3c # v2 - name: Checkout repository uses: actions/checkout@v4 # TODO Verify the crate version matches the tag @@ -38,7 +38,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Create GitHub release - uses: ncipollo/release-action@v1 + uses: ncipollo/release-action@440c8c1cb0ed28b9f43e4d1d670870f059653174 # v1 with: body: | Find more info on all releases at https://crates.io/crates/tree-sitter-stack-graphs-java. diff --git a/.github/workflows/publish-tree-sitter-stack-graphs-javascript.yml b/.github/workflows/publish-tree-sitter-stack-graphs-javascript.yml index 48375d9d4..f571900b2 100644 --- a/.github/workflows/publish-tree-sitter-stack-graphs-javascript.yml +++ b/.github/workflows/publish-tree-sitter-stack-graphs-javascript.yml @@ -14,7 +14,7 @@ jobs: CRATE_DIR: './languages/tree-sitter-stack-graphs-javascript' steps: - name: Install Rust environment - uses: hecrj/setup-rust-action@v1 + uses: hecrj/setup-rust-action@110f36749599534ca96628b82f52ae67e5d95a3c # v2 - name: Checkout repository uses: actions/checkout@v4 # TODO Verify the crate version matches the tag @@ -38,7 +38,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Create GitHub release - uses: ncipollo/release-action@v1 + uses: ncipollo/release-action@440c8c1cb0ed28b9f43e4d1d670870f059653174 # v1 with: body: | Find more info on all releases at https://crates.io/crates/tree-sitter-stack-graphs-javascript. diff --git a/.github/workflows/publish-tree-sitter-stack-graphs-python.yml b/.github/workflows/publish-tree-sitter-stack-graphs-python.yml index 77804c28e..28d61b11e 100644 --- a/.github/workflows/publish-tree-sitter-stack-graphs-python.yml +++ b/.github/workflows/publish-tree-sitter-stack-graphs-python.yml @@ -14,7 +14,7 @@ jobs: CRATE_DIR: './languages/tree-sitter-stack-graphs-python' steps: - name: Install Rust environment - uses: hecrj/setup-rust-action@v1 + uses: hecrj/setup-rust-action@110f36749599534ca96628b82f52ae67e5d95a3c # v2 - name: Checkout repository uses: actions/checkout@v4 # TODO Verify the crate version matches the tag @@ -38,7 +38,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Create GitHub release - uses: ncipollo/release-action@v1 + uses: ncipollo/release-action@440c8c1cb0ed28b9f43e4d1d670870f059653174 # v1 with: body: | Find more info on all releases at https://crates.io/crates/tree-sitter-stack-graphs-python. diff --git a/.github/workflows/publish-tree-sitter-stack-graphs-typescript.yml b/.github/workflows/publish-tree-sitter-stack-graphs-typescript.yml index 3fdbe17e2..a1f387afd 100644 --- a/.github/workflows/publish-tree-sitter-stack-graphs-typescript.yml +++ b/.github/workflows/publish-tree-sitter-stack-graphs-typescript.yml @@ -14,7 +14,7 @@ jobs: CRATE_DIR: './languages/tree-sitter-stack-graphs-typescript' steps: - name: Install Rust environment - uses: hecrj/setup-rust-action@v1 + uses: hecrj/setup-rust-action@110f36749599534ca96628b82f52ae67e5d95a3c # v2 - name: Checkout repository uses: actions/checkout@v4 # TODO Verify the crate version matches the tag @@ -38,7 +38,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Create GitHub release - uses: ncipollo/release-action@v1 + uses: ncipollo/release-action@440c8c1cb0ed28b9f43e4d1d670870f059653174 # v1 with: body: | Find more info on all releases at https://crates.io/crates/tree-sitter-stack-graphs-typescript. diff --git a/.github/workflows/publish-tree-sitter-stack-graphs.yml b/.github/workflows/publish-tree-sitter-stack-graphs.yml index 2dfb743a1..6e14ab5b1 100644 --- a/.github/workflows/publish-tree-sitter-stack-graphs.yml +++ b/.github/workflows/publish-tree-sitter-stack-graphs.yml @@ -14,7 +14,7 @@ jobs: CRATE_DIR: './tree-sitter-stack-graphs' steps: - name: Install Rust environment - uses: hecrj/setup-rust-action@v1 + uses: hecrj/setup-rust-action@110f36749599534ca96628b82f52ae67e5d95a3c # v2 - name: Checkout repository uses: actions/checkout@v4 # TODO Verify the crate version matches the tag @@ -38,7 +38,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Create GitHub release - uses: ncipollo/release-action@v1 + uses: ncipollo/release-action@440c8c1cb0ed28b9f43e4d1d670870f059653174 # v1 with: body: | Find more info on all releases at https://crates.io/crates/tree-sitter-stack-graphs. From a6b0f7f6af89a3cb8e834866a87c568fcccf02ac Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 4 Mar 2025 13:52:47 +0100 Subject: [PATCH 497/500] Explicit workflow permissions --- .github/workflows/ci.yml | 4 ++++ .github/workflows/perf.yml | 5 +++++ .github/workflows/publish-lsp-positions.yml | 3 +++ .github/workflows/publish-stack-graphs.yml | 3 +++ .github/workflows/publish-tree-sitter-stack-graphs-java.yml | 3 +++ .../publish-tree-sitter-stack-graphs-javascript.yml | 3 +++ .../workflows/publish-tree-sitter-stack-graphs-python.yml | 3 +++ .../publish-tree-sitter-stack-graphs-typescript.yml | 3 +++ .github/workflows/publish-tree-sitter-stack-graphs.yml | 3 +++ 9 files changed, 30 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 89be35c39..e8bb697e7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,5 @@ name: Continuous integration + on: push: branches: [main] @@ -6,6 +7,9 @@ on: schedule: - cron: "0 0 1,15 * *" +permissions: + contents: read + # In the event that there is a new push to the ref, cancel any running jobs because there are now obsolete, and wasting resources. concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/.github/workflows/perf.yml b/.github/workflows/perf.yml index 1930ff2fb..d68ffa75d 100644 --- a/.github/workflows/perf.yml +++ b/.github/workflows/perf.yml @@ -1,9 +1,14 @@ name: Performance testing + on: pull_request: paths: - 'stack-graphs/**' +permissions: + contents: read + pull-requests: write + # In the event that there is a new push to the ref, cancel any running jobs because there are now obsolete, and wasting resources. concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/.github/workflows/publish-lsp-positions.yml b/.github/workflows/publish-lsp-positions.yml index 5c48ed71f..2ca05a133 100644 --- a/.github/workflows/publish-lsp-positions.yml +++ b/.github/workflows/publish-lsp-positions.yml @@ -5,6 +5,9 @@ on: tags: - lsp-positions-v* +permissions: + contents: write + jobs: publish-crate: runs-on: ubuntu-latest diff --git a/.github/workflows/publish-stack-graphs.yml b/.github/workflows/publish-stack-graphs.yml index cc7b6667b..29b21020b 100644 --- a/.github/workflows/publish-stack-graphs.yml +++ b/.github/workflows/publish-stack-graphs.yml @@ -5,6 +5,9 @@ on: tags: - stack-graphs-v* +permissions: + contents: write + jobs: publish-crate: runs-on: ubuntu-latest diff --git a/.github/workflows/publish-tree-sitter-stack-graphs-java.yml b/.github/workflows/publish-tree-sitter-stack-graphs-java.yml index 31196048c..40878de95 100644 --- a/.github/workflows/publish-tree-sitter-stack-graphs-java.yml +++ b/.github/workflows/publish-tree-sitter-stack-graphs-java.yml @@ -5,6 +5,9 @@ on: tags: - tree-sitter-stack-graphs-java-v* +permissions: + contents: write + jobs: publish-crate: runs-on: ubuntu-latest diff --git a/.github/workflows/publish-tree-sitter-stack-graphs-javascript.yml b/.github/workflows/publish-tree-sitter-stack-graphs-javascript.yml index f571900b2..b9fbceec3 100644 --- a/.github/workflows/publish-tree-sitter-stack-graphs-javascript.yml +++ b/.github/workflows/publish-tree-sitter-stack-graphs-javascript.yml @@ -5,6 +5,9 @@ on: tags: - tree-sitter-stack-graphs-javascript-v* +permissions: + contents: write + jobs: publish-crate: runs-on: ubuntu-latest diff --git a/.github/workflows/publish-tree-sitter-stack-graphs-python.yml b/.github/workflows/publish-tree-sitter-stack-graphs-python.yml index 28d61b11e..dc90a6974 100644 --- a/.github/workflows/publish-tree-sitter-stack-graphs-python.yml +++ b/.github/workflows/publish-tree-sitter-stack-graphs-python.yml @@ -5,6 +5,9 @@ on: tags: - tree-sitter-stack-graphs-python-v* +permissions: + contents: write + jobs: publish-crate: runs-on: ubuntu-latest diff --git a/.github/workflows/publish-tree-sitter-stack-graphs-typescript.yml b/.github/workflows/publish-tree-sitter-stack-graphs-typescript.yml index a1f387afd..9eb696e2a 100644 --- a/.github/workflows/publish-tree-sitter-stack-graphs-typescript.yml +++ b/.github/workflows/publish-tree-sitter-stack-graphs-typescript.yml @@ -5,6 +5,9 @@ on: tags: - tree-sitter-stack-graphs-typescript-v* +permissions: + contents: write + jobs: publish-crate: runs-on: ubuntu-latest diff --git a/.github/workflows/publish-tree-sitter-stack-graphs.yml b/.github/workflows/publish-tree-sitter-stack-graphs.yml index 6e14ab5b1..0bf56c143 100644 --- a/.github/workflows/publish-tree-sitter-stack-graphs.yml +++ b/.github/workflows/publish-tree-sitter-stack-graphs.yml @@ -5,6 +5,9 @@ on: tags: - tree-sitter-stack-graphs-v* +permissions: + contents: write + jobs: publish-crate: runs-on: ubuntu-latest From 3a596d8354f1c70f7e18415c10d37aa7b95cff82 Mon Sep 17 00:00:00 2001 From: Hendrik van Antwerpen Date: Tue, 4 Mar 2025 18:02:48 +0100 Subject: [PATCH 498/500] Add Blackbird team to codeowners --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c010ba8c1..a4042b8bc 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @github/semantic-code +* @github/semantic-code @github/blackbird From 4c99b605eea91c28e47e15ce4a0660dc5aa42430 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Jun 2025 21:33:25 +0000 Subject: [PATCH 499/500] Bump brace-expansion Bumps the npm_and_yarn group with 1 update in the /languages/tree-sitter-stack-graphs-typescript/vscode directory: [brace-expansion](https://github.com/juliangruber/brace-expansion). Updates `brace-expansion` from 2.0.1 to 2.0.2 - [Release notes](https://github.com/juliangruber/brace-expansion/releases) - [Commits](https://github.com/juliangruber/brace-expansion/compare/v2.0.1...v2.0.2) --- updated-dependencies: - dependency-name: brace-expansion dependency-version: 2.0.2 dependency-type: indirect dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] --- .../vscode/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/languages/tree-sitter-stack-graphs-typescript/vscode/package-lock.json b/languages/tree-sitter-stack-graphs-typescript/vscode/package-lock.json index 9cc00e7ae..4d95b10b3 100644 --- a/languages/tree-sitter-stack-graphs-typescript/vscode/package-lock.json +++ b/languages/tree-sitter-stack-graphs-typescript/vscode/package-lock.json @@ -38,9 +38,9 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dependencies": { "balanced-match": "^1.0.0" } From a008b75469f70769eeded8771217bd135fabb54c Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Tue, 9 Sep 2025 15:49:58 -0600 Subject: [PATCH 500/500] This repository is no longer being maintained --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index df51b81c6..6ae144656 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +**NOTE:** _This repository is no longer supported or updated by GitHub. If you wish to continue to develop this code yourself, we recommend you fork it._ + # Stack graphs The crates in this repository provide a Rust implementation of _stack graphs_,