Compare commits

..

9 Commits

Author SHA1 Message Date
Taus
18d4082a5f yeast: Delete the Cursor trait, inline its methods on AstCursor
The trait had a single implementor (`AstCursor`), three type parameters
of which one (`T`) was never used in any method signature, and one
external consumer that needed `use yeast::Cursor;` in scope just to
call methods on the cursor. The abstraction was overhead without a
second implementor to justify it.

Move the six trait methods to an inherent `impl AstCursor` block;
delete `shared/yeast/src/cursor.rs`, the `pub mod cursor;` and
`pub use cursor::Cursor;` lines in `lib.rs`, and the `use yeast::Cursor;`
in `tree-sitter-extractor`'s `traverse_yeast`.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-26 15:18:45 +00:00
Taus
0b3011a041 yeast-macros: Remove unused .map and .reduce_left chain syntax
The `{expr}.map(p -> tpl)` and `{expr}.reduce_left(first -> init, acc,
elem -> fold)` post-fix chains on `{expr}` placeholders had no
remaining users in the codebase: `.map` was never used, and the
4 `.reduce_left` sites in `swift.rs` were rewritten to plain
`Iterator::reduce` via an `and_chain` helper in an earlier commit.

Removes the entire `parse_chain_suffix` function (~90 lines) and the
`has_chain` detection / dispatch branches at the two call sites
(field-position in `parse_direct_node_inner` and body-position in
`parse_direct_list`). The remaining `{expr}` path is the
trait-dispatched one introduced by the splice-syntax cleanup, which
handles single ids and iterables uniformly via `IntoFieldIds`.

Also strips the chain syntax from the `tree!` macro doc comment.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-26 15:09:44 +00:00
Taus
1d75ff81e8 yeast-macros: Add error message to defensive expect_ident in parse_ctx_or_implicit
The empty error string passed to `expect_ident` was dead code (the
preceding lookahead has already confirmed the token is an ident),
but it would have been a confusing message if it ever fired. Replace
with an explicit "unreachable" string that makes the intent
clearer to readers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-26 14:45:57 +00:00
Taus
abc07e995e yeast: Unify Node::kind() and Node::kind_name()
Both accessors returned the same private `kind_name: &'static str`
field; `kind_name()` is widely used (mainly by dump.rs and schema
diagnostics) and `kind()` had only 2 internal callers in lib.rs and
a handful in tests. Pick the more descriptive name and update the
callers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-26 14:45:57 +00:00
Taus
076b2fea77 yeast: Remove dead prepend_field / prepend_field_child
`BuildCtx::prepend_field` and the underlying `Ast::prepend_field_child`
existed to support the create-then-mutate pattern in swift.rs (build
an output node, then prepend modifiers to its `modifier:` field). The
SwiftContext-based refactor on the previous branches eliminated all
such call sites: every emitted declaration now carries its modifiers
from birth, so the in-place prepend operation has no users.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-26 14:04:02 +00:00
Taus
71d7e36473 yeast: Remove dead BuildCtx::translate_opt
`translate_opt` was a convenience for the manual_rule! body code,
collapsing `Option<I>` to `Option<Id>` via `translate`. Since the
`@@` raw-capture migration replaced manual_rule! with rule!, no
callers remain — the auto-translate prefix handles `Option<Id>`
captures directly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-26 14:03:11 +00:00
Taus
616de94ff2 yeast: Remove dead Captures methods
`Captures::map_captures`, `Captures::map_captures_to`, and
`Captures::try_map_all_captures` had no callers. The last one was
subsumed by `try_map_captures_except` (which takes a skip list and
degenerates to the old behaviour when the list is empty).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-26 14:02:25 +00:00
Taus
dd9653877a yeast: Replace {..expr} splice syntax with trait-dispatched {expr}
In the initial implementation of yeast, the splice syntax was needed do
distinguish between splicing multiple nodes or just a single node.
However, this was always an ugly "wart" in the syntax, since the user
shouldn't have to worry about these things.

To fix this, we add an `IntoFieldIds` trait that dispatches on the
value's type: `Id` pushes a single id, and a blanket impl for
`IntoIterator<Item: Into<Id>>` handles `Vec<Id>`, `Option<Id>`, and
arbitrary iterator chains.

With this, we no longer need to use the special splice syntax, and hence
we can get rid of it.
2026-06-26 13:34:14 +00:00
Taus
2cf88b46e2 yeast: Make Id a newtype, delete NodeRef
Previously, the `Id` type  was a bare usize alias. The `NodeRef` newtype
existed solely to carry the AST-aware `YeastDisplay` /
`YeastSourceRange` impls (so that `#{captured_node}` rendered source
text rather than the numeric id) without colliding with the impls for
raw integer types.

This commit promotes `Id` itself to a (transparent) newtype struct and
moves the AST-aware trait impls directly onto it. With `Id` and `usize`
now being different types, the integer-display impl (for `usize`) and
the source-text impl (for `Id`) coexist without conflict, and `NodeRef`
becomes redundant (and so we remove it).
2026-06-26 13:34:14 +00:00
47 changed files with 119 additions and 313 deletions

View File

@@ -14,9 +14,7 @@ pluginManagement {
repositories {
gradlePluginPortal()
google()
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
mavenCentral()
}
}
dependencyResolutionManagement {
@@ -35,9 +33,7 @@ dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
mavenCentral()
}
}
rootProject.name = "Android Sample"

View File

@@ -14,9 +14,7 @@ pluginManagement {
repositories {
gradlePluginPortal()
google()
maven {
url = uri("https://maven-central.storage-download.googleapis.com/maven2/")
}
mavenCentral()
}
}
dependencyResolutionManagement {
@@ -35,9 +33,7 @@ dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
maven {
url = uri("https://maven-central.storage-download.googleapis.com/maven2/")
}
mavenCentral()
}
}
rootProject.name = "Android Sample"

View File

@@ -14,9 +14,7 @@ pluginManagement {
repositories {
gradlePluginPortal()
google()
maven {
url = uri("https://maven-central.storage-download.googleapis.com/maven2/")
}
mavenCentral()
}
}
dependencyResolutionManagement {
@@ -35,9 +33,7 @@ dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
maven {
url = uri("https://maven-central.storage-download.googleapis.com/maven2/")
}
mavenCentral()
}
}
rootProject.name = "Android Sample"

View File

@@ -14,9 +14,7 @@ pluginManagement {
repositories {
gradlePluginPortal()
google()
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
mavenCentral()
}
}
dependencyResolutionManagement {
@@ -35,9 +33,7 @@ dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
mavenCentral()
}
}
rootProject.name = "Android Sample"

View File

@@ -13,9 +13,7 @@ buildscript {
repositories {
google()
maven {
url = uri("https://maven-central.storage-download.googleapis.com/maven2/")
}
jcenter()
}
/**
@@ -41,8 +39,6 @@ buildscript {
allprojects {
repositories {
google()
maven {
url = uri("https://maven-central.storage-download.googleapis.com/maven2/")
}
jcenter()
}
}

View File

@@ -13,9 +13,7 @@ buildscript {
repositories {
google()
maven {
url = uri("https://maven-central.storage-download.googleapis.com/maven2/")
}
jcenter()
}
/**
@@ -41,8 +39,6 @@ buildscript {
allprojects {
repositories {
google()
maven {
url = uri("https://maven-central.storage-download.googleapis.com/maven2/")
}
jcenter()
}
}

View File

@@ -13,9 +13,7 @@ buildscript {
repositories {
google()
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
jcenter()
}
/**
@@ -41,8 +39,6 @@ buildscript {
allprojects {
repositories {
google()
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
jcenter()
}
}

View File

@@ -13,9 +13,7 @@ buildscript {
repositories {
google()
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
jcenter()
}
/**
@@ -34,15 +32,13 @@ buildscript {
* dependencies used by all modules in your project, such as third-party plugins
* or libraries. However, you should configure module-specific dependencies in
* each module-level build.gradle file. For new projects, Android Studio
* includes Maven Central and Google's Maven repository by default, but it does not
* includes JCenter and Google's Maven repository by default, but it does not
* configure any dependencies (unless you select a template that requires some).
*/
allprojects {
repositories {
google()
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
jcenter()
}
}

View File

@@ -14,9 +14,7 @@ pluginManagement {
repositories {
gradlePluginPortal()
google()
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
mavenCentral()
}
}
dependencyResolutionManagement {
@@ -35,9 +33,7 @@ dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
mavenCentral()
}
}
rootProject.name = "Android Sample"

View File

@@ -8,9 +8,7 @@
apply plugin: 'java-library'
repositories {
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
mavenCentral()
}
dependencies {

View File

@@ -1,5 +1,5 @@
https://maven-central.storage-download.googleapis.com/maven2/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar
https://maven-central.storage-download.googleapis.com/maven2/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar
https://maven-central.storage-download.googleapis.com/maven2/org/junit/jupiter/junit-jupiter-api/5.12.1/junit-jupiter-api-5.12.1.jar
https://maven-central.storage-download.googleapis.com/maven2/org/junit/platform/junit-platform-commons/1.12.1/junit-platform-commons-1.12.1.jar
https://maven-central.storage-download.googleapis.com/maven2/org/opentest4j/opentest4j/1.3.0/opentest4j-1.3.0.jar
https://repo.maven.apache.org/maven2/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar
https://repo.maven.apache.org/maven2/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar
https://repo.maven.apache.org/maven2/org/junit/jupiter/junit-jupiter-api/5.12.1/junit-jupiter-api-5.12.1.jar
https://repo.maven.apache.org/maven2/org/junit/platform/junit-platform-commons/1.12.1/junit-platform-commons-1.12.1.jar
https://repo.maven.apache.org/maven2/org/opentest4j/opentest4j/1.3.0/opentest4j-1.3.0.jar

View File

@@ -8,9 +8,7 @@
apply plugin: 'java-library'
repositories {
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
mavenCentral()
}
dependencies {

View File

@@ -1,2 +1,2 @@
https://maven-central.storage-download.googleapis.com/maven2/joda-time/joda-time/2.12.7/joda-time-2.12.7-no-tzdb.jar
https://maven-central.storage-download.googleapis.com/maven2/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar
https://repo.maven.apache.org/maven2/joda-time/joda-time/2.12.7/joda-time-2.12.7-no-tzdb.jar
https://repo.maven.apache.org/maven2/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar

View File

@@ -12,9 +12,9 @@ apply plugin: 'java'
// In this section you declare where to find the dependencies of your project
repositories {
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
// Use 'jcenter' for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
// In this section you declare the dependencies for your production and test code

View File

@@ -8,9 +8,7 @@
apply plugin: 'java-library'
repositories {
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
mavenCentral()
}
dependencies {

View File

@@ -1 +1 @@
https://maven-central.storage-download.googleapis.com/maven2/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar
https://repo.maven.apache.org/maven2/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar

View File

@@ -8,9 +8,7 @@
apply plugin: 'java-library'
repositories {
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
mavenCentral()
}
dependencies {

View File

@@ -1 +1 @@
https://maven-central.storage-download.googleapis.com/maven2/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar
https://repo.maven.apache.org/maven2/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar

View File

@@ -1,7 +1,6 @@
https://maven-central.storage-download.googleapis.com/maven2/junit/junit/4.11/junit-4.11.jar
https://maven-central.storage-download.googleapis.com/maven2/junit/junit/4.12/junit-4.12.jar
https://maven-central.storage-download.googleapis.com/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar
https://maven-central.storage-download.googleapis.com/maven2/org/slf4j/slf4j-api/1.7.21/slf4j-api-1.7.21.jar
https://jcenter.bintray.com/junit/junit/4.12/junit-4.12.jar
https://jcenter.bintray.com/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar
https://jcenter.bintray.com/org/slf4j/slf4j-api/1.7.21/slf4j-api-1.7.21.jar
https://repo.maven.apache.org/maven2/com/feiniaojin/naaf/naaf-graceful-response-example/1.0/naaf-graceful-response-example-1.0.jar
https://repo.maven.apache.org/maven2/com/github/MoebiusSolutions/avro-registry-in-source/avro-registry-in-source-tests/1.8/avro-registry-in-source-tests-1.8.jar
https://repo.maven.apache.org/maven2/com/github/MoebiusSolutions/avro-registry-in-source/example-project/1.5/example-project-1.5.jar
@@ -13,6 +12,7 @@ https://repo.maven.apache.org/maven2/de/knutwalker/rx-redis-example_2.11/0.1.2/r
https://repo.maven.apache.org/maven2/de/knutwalker/rx-redis-java-example_2.11/0.1.2/rx-redis-java-example_2.11-0.1.2.jar
https://repo.maven.apache.org/maven2/io/github/scrollsyou/example-spring-boot-starter/1.0.0/example-spring-boot-starter-1.0.0.jar
https://repo.maven.apache.org/maven2/io/streamnative/com/example/maven-central-template/server/3.0.0/server-3.0.0.jar
https://repo.maven.apache.org/maven2/junit/junit/4.11/junit-4.11.jar
https://repo.maven.apache.org/maven2/no/nav/security/token-validation-ktor-demo/3.1.0/token-validation-ktor-demo-3.1.0.jar
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-fileupload/0.5.10/minijax-example-fileupload-0.5.10.jar
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-inject/0.5.10/minijax-example-inject-0.5.10.jar

View File

@@ -12,9 +12,9 @@ apply plugin: 'java'
// In this section you declare where to find the dependencies of your project
repositories {
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
// Use 'jcenter' for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
// In this section you declare the dependencies for your production and test code

View File

@@ -12,9 +12,9 @@ apply plugin: 'java'
// In this section you declare where to find the dependencies of your project
repositories {
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
// Use 'jcenter' for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
// In this section you declare the dependencies for your production and test code

View File

@@ -1,10 +0,0 @@
<settings>
<mirrors>
<mirror>
<id>google-maven-central</id>
<name>GCS Maven Central mirror</name>
<url>https://maven-central.storage-download.googleapis.com/maven2/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
</settings>

View File

@@ -26,5 +26,4 @@ maven-project-2/src/main/resources/my-app.properties
maven-project-2/src/main/resources/page.xml
maven-project-2/src/main/resources/struts.xml
maven-project-2/src/test/java/com/example/AppTest4.java
settings.xml
test-db/working/settings.xml

View File

@@ -1,5 +1,3 @@
import os
def test(codeql, use_java_11, java, actions_toolchains_file, check_diagnostics_java):
# The version of gradle used doesn't work on java 17
codeql.database.create(
@@ -7,6 +5,5 @@ def test(codeql, use_java_11, java, actions_toolchains_file, check_diagnostics_j
"CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS": "true",
"CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS_CLASSPATH_FROM_BUILD_FILES": "true",
"LGTM_INDEX_MAVEN_TOOLCHAINS_FILE": str(actions_toolchains_file),
"LGTM_INDEX_MAVEN_SETTINGS_FILE": os.path.join(os.path.dirname(os.path.realpath(__file__)), "settings.xml"),
}
)

View File

@@ -14,9 +14,7 @@ pluginManagement {
repositories {
gradlePluginPortal()
google()
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
mavenCentral()
}
}
dependencyResolutionManagement {
@@ -35,9 +33,7 @@ dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
mavenCentral()
}
}
rootProject.name = "Android Sample"

View File

@@ -12,9 +12,9 @@ apply plugin: 'java'
// In this section you declare where to find the dependencies of your project
repositories {
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
// Use 'jcenter' for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
// In this section you declare the dependencies for your production and test code

View File

@@ -12,9 +12,9 @@ apply plugin: 'java'
// In this section you declare where to find the dependencies of your project
repositories {
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
// Use 'jcenter' for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
// In this section you declare the dependencies for your production and test code

View File

@@ -12,9 +12,8 @@ plugins {
}
repositories {
maven {
url = uri("https://maven-central.storage-download.googleapis.com/maven2/")
}
// Use Maven Central for resolving dependencies.
mavenCentral()
}
dependencies {

View File

@@ -12,9 +12,9 @@ apply plugin: 'java'
// In this section you declare where to find the dependencies of your project
repositories {
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
// Use 'jcenter' for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
// In this section you declare the dependencies for your production and test code

View File

@@ -12,9 +12,9 @@ apply plugin: 'java'
// In this section you declare where to find the dependencies of your project
repositories {
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
// Use 'jcenter' for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
// In this section you declare the dependencies for your production and test code

View File

@@ -12,9 +12,9 @@ apply plugin: 'java'
// In this section you declare where to find the dependencies of your project
repositories {
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
// Use 'jcenter' for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
// In this section you declare the dependencies for your production and test code

View File

@@ -12,9 +12,9 @@ apply plugin: 'java'
// In this section you declare where to find the dependencies of your project
repositories {
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
// Use 'jcenter' for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
// In this section you declare the dependencies for your production and test code

View File

@@ -11,9 +11,7 @@ version = '0.0.1-SNAPSHOT'
// but I omit it to test we recognise the Spring Boot plugin version.
repositories {
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
mavenCentral()
}
dependencies {

View File

@@ -15,9 +15,8 @@ plugins {
}
repositories {
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
// Use Maven Central for resolving dependencies.
mavenCentral()
}
application {

View File

@@ -15,9 +15,8 @@ plugins {
}
repositories {
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
// Use Maven Central for resolving dependencies.
mavenCentral()
}
application {

View File

@@ -4,9 +4,7 @@ plugins {
}
repositories {
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
mavenCentral()
}
dependencies {

View File

@@ -15,9 +15,8 @@ plugins {
}
repositories {
maven {
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
}
// Use Maven Central for resolving dependencies.
mavenCentral()
}
application {

View File

@@ -28,6 +28,8 @@ nodes
| string_flow.rb:227:10:227:10 | a | semmle.label | a |
subpaths
testFailures
| string_flow.rb:85:10:85:10 | a | Unexpected result: hasValueFlow=a |
| string_flow.rb:227:10:227:10 | a | Unexpected result: hasValueFlow=a |
#select
| string_flow.rb:3:10:3:22 | call to new | string_flow.rb:2:9:2:18 | call to source | string_flow.rb:3:10:3:22 | call to new | $@ | string_flow.rb:2:9:2:18 | call to source | call to source |
| string_flow.rb:85:10:85:10 | a | string_flow.rb:83:9:83:18 | call to source | string_flow.rb:85:10:85:10 | a | $@ | string_flow.rb:83:9:83:18 | call to source | call to source |

View File

@@ -82,7 +82,7 @@ end
def m_clear
a = source "a"
a.clear
sink a # $ SPURIOUS: hasValueFlow=a
sink a
end
# concat and prepend omitted because they clash with the summaries for
@@ -224,7 +224,7 @@ def m_replace
b = source "b"
sink a.replace(b) # $ hasTaintFlow=b
# TODO: currently we get value flow for a, because we don't clear content
sink a # $ hasTaintFlow=b SPURIOUS: hasValueFlow=a
sink a # $ hasTaintFlow=b
end
def m_reverse
@@ -316,4 +316,4 @@ def m_upto(i)
a.upto("b", true) { |x| sink x } # $ hasTaintFlow=a
"b".upto(a) { |x| sink x } # $ hasTaintFlow=a
"b".upto(a, true) { |x| sink x }
end
end

View File

@@ -9,7 +9,7 @@ end
class OneController < ActionController::Base
before_action :a
after_action :c
def a
@foo = params[:foo]
end
@@ -18,14 +18,14 @@ class OneController < ActionController::Base
end
def c
sink @foo # $ hasTaintFlow
sink @foo
end
end
class TwoController < ActionController::Base
before_action :a
after_action :c
def a
@foo = params[:foo]
end
@@ -35,14 +35,14 @@ class TwoController < ActionController::Base
end
def c
sink @foo # $ SPURIOUS: hasTaintFlow
sink @foo
end
end
class ThreeController < ActionController::Base
before_action :a
after_action :c
def a
@foo = params[:foo]
@foo = "safe"
@@ -52,14 +52,14 @@ class ThreeController < ActionController::Base
end
def c
sink @foo # $ SPURIOUS: hasTaintFlow
sink @foo
end
end
class FourController < ActionController::Base
before_action :a
after_action :c
def a
@foo.bar = params[:foo]
end
@@ -68,14 +68,14 @@ class FourController < ActionController::Base
end
def c
sink(@foo.bar) # $ hasTaintFlow
sink(@foo.bar)
end
end
class FiveController < ActionController::Base
before_action :a
after_action :c
def a
self.taint_foo
end
@@ -84,10 +84,10 @@ class FiveController < ActionController::Base
end
def c
sink @foo # $ hasTaintFlow
sink @foo
end
def taint_foo
@foo = params[:foo]
end
end
end

View File

@@ -270,6 +270,11 @@ nodes
| params_flow.rb:205:10:205:10 | a | semmle.label | a |
subpaths
testFailures
| filter_flow.rb:21:10:21:13 | @foo | Unexpected result: hasTaintFlow |
| filter_flow.rb:38:10:38:13 | @foo | Unexpected result: hasTaintFlow |
| filter_flow.rb:55:10:55:13 | @foo | Unexpected result: hasTaintFlow |
| filter_flow.rb:71:10:71:17 | call to bar | Unexpected result: hasTaintFlow |
| filter_flow.rb:87:11:87:14 | @foo | Unexpected result: hasTaintFlow |
#select
| filter_flow.rb:21:10:21:13 | @foo | filter_flow.rb:14:12:14:17 | call to params | filter_flow.rb:21:10:21:13 | @foo | $@ | filter_flow.rb:14:12:14:17 | call to params | call to params |
| filter_flow.rb:38:10:38:13 | @foo | filter_flow.rb:30:12:30:17 | call to params | filter_flow.rb:38:10:38:13 | @foo | $@ | filter_flow.rb:30:12:30:17 | call to params | call to params |

View File

@@ -320,7 +320,7 @@ yeast::rule!(
=>
{
// raw_lhs is untranslated: read its original source text.
let text = ctx.ast.source_text(raw_lhs);
let text = ctx.ast.source_text(raw_lhs.into());
// rhs is already translated by the auto-translate prefix.
tree!((call
method: (identifier #{text.as_str()})

View File

@@ -42,7 +42,6 @@ supertypes:
- name_pattern
- tuple_pattern
- constructor_pattern
- or_pattern
- ignore_pattern
- expr_equality_pattern
- bulk_importing_pattern
@@ -360,12 +359,12 @@ named:
case*: switch_case
# A single `case ...:` (or `default:`) entry in a switch.
# An entry with multiple `case p1, p2:` patterns uses an `or_pattern`.
# A `default:` entry has no pattern.
# An entry with multiple `case p1, p2:` patterns has multiple `pattern`s.
# A `default:` entry has no patterns.
# An optional `guard` corresponds to a `where`-clause on the case.
switch_case:
modifier*: modifier
pattern?: pattern
pattern*: pattern
guard?: expr
body: block
@@ -422,11 +421,6 @@ named:
constructor: expr_or_type
element*: pattern_element
# A disjunction pattern that matches if any of its sub-patterns match.
or_pattern:
modifier*: modifier
pattern*: pattern
# A pattern with an optional associated name.
pattern_element:
modifier*: modifier

View File

@@ -637,20 +637,11 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
=>
(switch_expr value: {val} case: {cases})
),
// Switch entry with multiple patterns and body
// Switch entry with patterns and body
rule!(
(switch_entry
pattern: (switch_pattern pattern: @first)
pattern: (switch_pattern pattern: @rest)+
statement: _* @body)
(switch_entry pattern: (switch_pattern pattern: @pats)* statement: _* @body)
=>
(switch_case pattern: (or_pattern pattern: {first} pattern: {rest}) body: (block stmt: {body}))
),
// Switch entry with exactly one pattern and body
rule!(
(switch_entry pattern: (switch_pattern pattern: @pat) statement: _* @body)
=>
(switch_case pattern: {pat} body: (block stmt: {body}))
(switch_case pattern: {pats} body: (block stmt: {body}))
),
// Switch entry: default case (no patterns)
rule!(
@@ -658,13 +649,13 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
=>
(switch_case body: (block stmt: {body}))
),
// if case PATTERN = expr — preserve the pattern directly (no Optional wrapping)
// if case let x = expr — the pattern is taken as-is (no Optional wrapping)
rule!(
(if_let_binding "case" pattern: @pat value: @val)
(if_let_binding "case" (value_binding_pattern) bound_identifier: @name _ @val)
=>
(pattern_guard_expr
value: {val}
pattern: {pat})
pattern: (name_pattern identifier: (identifier #{name})))
),
rule!(
(if_let_binding

View File

@@ -573,12 +573,10 @@ top_level
name_expr
identifier: identifier "print"
pattern:
or_pattern
pattern:
expr_equality_pattern
expr: int_literal "2"
expr_equality_pattern
expr: int_literal "3"
expr_equality_pattern
expr: int_literal "2"
expr_equality_pattern
expr: int_literal "3"
switch_case
body:
block
@@ -594,83 +592,6 @@ top_level
name_expr
identifier: identifier "x"
===
If-case-let with shadowing in condition value
===
if case let x = x + 10 {
print(x)
}
---
source_file
statement:
if_statement
body:
block
statement:
call_expression
function: simple_identifier "print"
suffix:
call_suffix
arguments:
value_arguments
argument:
value_argument
value: simple_identifier "x"
condition:
if_condition
kind:
if_let_binding
pattern:
pattern
kind:
binding_pattern
binding:
value_binding_pattern
mutability: let
pattern:
pattern
bound_identifier: simple_identifier "x"
value:
additive_expression
lhs: simple_identifier "x"
op: +
rhs: integer_literal "10"
---
top_level
body:
block
stmt:
if_expr
condition:
pattern_guard_expr
pattern:
name_pattern
identifier: identifier "x"
value:
binary_expr
operator: infix_operator "+"
left:
name_expr
identifier: identifier "x"
right: int_literal "10"
then:
block
stmt:
call_expr
argument:
argument
value:
name_expr
identifier: identifier "x"
callee:
name_expr
identifier: identifier "print"
===
Switch with binding pattern
===

View File

@@ -978,23 +978,6 @@ module Unified {
}
}
/** A class representing `or_pattern` nodes. */
class OrPattern extends @unified_or_pattern, AstNode {
/** Gets the name of the primary QL class for this element. */
final override string getAPrimaryQlClass() { result = "OrPattern" }
/** Gets the node corresponding to the field `modifier`. */
final Modifier getModifier(int i) { unified_or_pattern_modifier(this, i, result) }
/** Gets the node corresponding to the field `pattern`. */
final Pattern getPattern(int i) { unified_or_pattern_pattern(this, i, result) }
/** Gets a field or child node of this node. */
final override AstNode getAFieldOrChild() {
unified_or_pattern_modifier(this, _, result) or unified_or_pattern_pattern(this, _, result)
}
}
/** A class representing `parameter` nodes. */
class Parameter extends @unified_parameter, AstNode {
/** Gets the name of the primary QL class for this element. */
@@ -1126,14 +1109,14 @@ module Unified {
final Modifier getModifier(int i) { unified_switch_case_modifier(this, i, result) }
/** Gets the node corresponding to the field `pattern`. */
final Pattern getPattern() { unified_switch_case_pattern(this, result) }
final Pattern getPattern(int i) { unified_switch_case_pattern(this, i, result) }
/** Gets a field or child node of this node. */
final override AstNode getAFieldOrChild() {
unified_switch_case_def(this, result) or
unified_switch_case_guard(this, result) or
unified_switch_case_modifier(this, _, result) or
unified_switch_case_pattern(this, result)
unified_switch_case_pattern(this, _, result)
}
}
@@ -1671,10 +1654,6 @@ module Unified {
i = -1 and
name = "getPrecedence"
or
result = node.(OrPattern).getModifier(i) and name = "getModifier"
or
result = node.(OrPattern).getPattern(i) and name = "getPattern"
or
result = node.(Parameter).getDefault() and i = -1 and name = "getDefault"
or
result = node.(Parameter).getExternalName() and i = -1 and name = "getExternalName"
@@ -1703,7 +1682,7 @@ module Unified {
or
result = node.(SwitchCase).getModifier(i) and name = "getModifier"
or
result = node.(SwitchCase).getPattern() and i = -1 and name = "getPattern"
result = node.(SwitchCase).getPattern(i) and name = "getPattern"
or
result = node.(SwitchExpr).getCase(i) and name = "getCase"
or

View File

@@ -716,24 +716,6 @@ unified_operator_syntax_declaration_def(
int name: @unified_token_identifier ref
);
#keyset[unified_or_pattern, index]
unified_or_pattern_modifier(
int unified_or_pattern: @unified_or_pattern ref,
int index: int ref,
unique int modifier: @unified_token_modifier ref
);
#keyset[unified_or_pattern, index]
unified_or_pattern_pattern(
int unified_or_pattern: @unified_or_pattern ref,
int index: int ref,
unique int pattern: @unified_pattern ref
);
unified_or_pattern_def(
unique int id: @unified_or_pattern
);
unified_parameter_default(
unique int unified_parameter: @unified_parameter ref,
unique int default: @unified_expr ref
@@ -765,7 +747,7 @@ unified_parameter_def(
unique int id: @unified_parameter
);
@unified_pattern = @unified_bulk_importing_pattern | @unified_constructor_pattern | @unified_expr_equality_pattern | @unified_name_pattern | @unified_or_pattern | @unified_token_ignore_pattern | @unified_token_unsupported_node | @unified_tuple_pattern
@unified_pattern = @unified_bulk_importing_pattern | @unified_constructor_pattern | @unified_expr_equality_pattern | @unified_name_pattern | @unified_token_ignore_pattern | @unified_token_unsupported_node | @unified_tuple_pattern
unified_pattern_element_key(
unique int unified_pattern_element: @unified_pattern_element ref,
@@ -813,8 +795,10 @@ unified_switch_case_modifier(
unique int modifier: @unified_token_modifier ref
);
#keyset[unified_switch_case, index]
unified_switch_case_pattern(
unique int unified_switch_case: @unified_switch_case ref,
int unified_switch_case: @unified_switch_case ref,
int index: int ref,
unique int pattern: @unified_pattern ref
);
@@ -1072,7 +1056,7 @@ unified_trivia_tokeninfo(
string value: string ref
);
@unified_ast_node = @unified_accessor_declaration | @unified_argument | @unified_array_literal | @unified_assign_expr | @unified_associated_type_declaration | @unified_base_type | @unified_binary_expr | @unified_block | @unified_bound_type_constraint | @unified_break_expr | @unified_bulk_importing_pattern | @unified_call_expr | @unified_catch_clause | @unified_class_like_declaration | @unified_compound_assign_expr | @unified_constructor_declaration | @unified_constructor_pattern | @unified_continue_expr | @unified_destructor_declaration | @unified_do_while_stmt | @unified_equality_type_constraint | @unified_expr_equality_pattern | @unified_for_each_stmt | @unified_function_declaration | @unified_function_expr | @unified_function_type_expr | @unified_generic_type_expr | @unified_guard_if_stmt | @unified_if_expr | @unified_import_declaration | @unified_initializer_declaration | @unified_key_value_pair | @unified_labeled_stmt | @unified_map_literal | @unified_member_access_expr | @unified_name_expr | @unified_name_pattern | @unified_named_type_expr | @unified_operator_syntax_declaration | @unified_or_pattern | @unified_parameter | @unified_pattern_element | @unified_pattern_guard_expr | @unified_return_expr | @unified_switch_case | @unified_switch_expr | @unified_throw_expr | @unified_token | @unified_top_level | @unified_trivia_token | @unified_try_expr | @unified_tuple_expr | @unified_tuple_pattern | @unified_tuple_type_element | @unified_tuple_type_expr | @unified_type_alias_declaration | @unified_type_cast_expr | @unified_type_parameter | @unified_type_test_expr | @unified_type_test_pattern | @unified_unary_expr | @unified_variable_declaration | @unified_while_stmt
@unified_ast_node = @unified_accessor_declaration | @unified_argument | @unified_array_literal | @unified_assign_expr | @unified_associated_type_declaration | @unified_base_type | @unified_binary_expr | @unified_block | @unified_bound_type_constraint | @unified_break_expr | @unified_bulk_importing_pattern | @unified_call_expr | @unified_catch_clause | @unified_class_like_declaration | @unified_compound_assign_expr | @unified_constructor_declaration | @unified_constructor_pattern | @unified_continue_expr | @unified_destructor_declaration | @unified_do_while_stmt | @unified_equality_type_constraint | @unified_expr_equality_pattern | @unified_for_each_stmt | @unified_function_declaration | @unified_function_expr | @unified_function_type_expr | @unified_generic_type_expr | @unified_guard_if_stmt | @unified_if_expr | @unified_import_declaration | @unified_initializer_declaration | @unified_key_value_pair | @unified_labeled_stmt | @unified_map_literal | @unified_member_access_expr | @unified_name_expr | @unified_name_pattern | @unified_named_type_expr | @unified_operator_syntax_declaration | @unified_parameter | @unified_pattern_element | @unified_pattern_guard_expr | @unified_return_expr | @unified_switch_case | @unified_switch_expr | @unified_throw_expr | @unified_token | @unified_top_level | @unified_trivia_token | @unified_try_expr | @unified_tuple_expr | @unified_tuple_pattern | @unified_tuple_type_element | @unified_tuple_type_expr | @unified_type_alias_declaration | @unified_type_cast_expr | @unified_type_parameter | @unified_type_test_expr | @unified_type_test_pattern | @unified_unary_expr | @unified_variable_declaration | @unified_while_stmt
unified_ast_node_location(
unique int node: @unified_ast_node ref,