-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Rust: Rust: add jump to definition for format arguments #17805
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
997a622
Rust: also implement localReferences.ql
aibaars f092594
Rust: add location definitions for format arguments
aibaars 40ef9ad
Rust: make TDef cached
aibaars c4126e4
Rust: add tests for Definitions.qll
aibaars fdf99e2
Rust: filter out definitions that are inside expanded macros
aibaars File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
/** | ||
* Provides classes and predicates related to jump-to-definition links | ||
* in the code viewer. | ||
*/ | ||
|
||
private import codeql.rust.elements.Variable | ||
private import codeql.rust.elements.Locatable | ||
private import codeql.rust.elements.FormatArgsExpr | ||
Check warningCode scanning / CodeQL Redundant import Warning
Redundant import, the module is already imported inside
codeql.rust.elements.Format Error loading related location Loading |
||
private import codeql.rust.elements.FormatArgsArg | ||
Check warningCode scanning / CodeQL Redundant import Warning
Redundant import, the module is already imported inside
codeql.rust.elements.FormatArgsExpr Error loading related location Loading |
||
private import codeql.rust.elements.Format | ||
private import codeql.rust.elements.MacroCall | ||
private import codeql.rust.elements.NamedFormatArgument | ||
private import codeql.rust.elements.PositionalFormatArgument | ||
private import codeql.Locations | ||
|
||
/** An element with an associated definition. */ | ||
abstract class Use extends Locatable { | ||
/** Gets the definition associated with this element. */ | ||
abstract Definition getDefinition(); | ||
|
||
/** | ||
* Gets the type of use. | ||
*/ | ||
abstract string getUseType(); | ||
} | ||
|
||
cached | ||
private module Cached { | ||
cached | ||
newtype TDef = | ||
TVariable(Variable v) or | ||
TFormatArgsArgName(Name name) { name = any(FormatArgsArg a).getName() } or | ||
TFormatArgsArgIndex(Expr e) { e = any(FormatArgsArg a).getExpr() } | ||
|
||
/** | ||
* Gets an element, of kind `kind`, that element `use` uses, if any. | ||
*/ | ||
cached | ||
Definition definitionOf(Use use, string kind) { | ||
result = use.getDefinition() and | ||
kind = use.getUseType() and | ||
not result.getLocation() = any(MacroCall m).getLocation() | ||
} | ||
} | ||
|
||
predicate definitionOf = Cached::definitionOf/2; | ||
|
||
/** A definition */ | ||
class Definition extends Cached::TDef { | ||
/** Gets the location of this variable. */ | ||
Location getLocation() { | ||
result = this.asVariable().getLocation() or | ||
result = this.asName().getLocation() or | ||
result = this.asExpr().getLocation() | ||
} | ||
|
||
/** Gets this definition as a `Variable` */ | ||
Variable asVariable() { this = Cached::TVariable(result) } | ||
|
||
/** Gets this definition as a `Name` */ | ||
Name asName() { this = Cached::TFormatArgsArgName(result) } | ||
|
||
/** Gets this definition as an `Expr` */ | ||
Expr asExpr() { this = Cached::TFormatArgsArgIndex(result) } | ||
|
||
/** Gets the string representation of this element. */ | ||
string toString() { | ||
result = this.asExpr().toString() or | ||
result = this.asVariable().toString() or | ||
result = this.asName().getText() | ||
} | ||
} | ||
|
||
private class LocalVariableUse extends Use instanceof VariableAccess { | ||
private Variable def; | ||
|
||
LocalVariableUse() { this = def.getAnAccess() } | ||
|
||
override Definition getDefinition() { result.asVariable() = def } | ||
|
||
override string getUseType() { result = "local variable" } | ||
} | ||
|
||
private class NamedFormatArgumentUse extends Use instanceof NamedFormatArgument { | ||
private Name def; | ||
|
||
NamedFormatArgumentUse() { | ||
exists(FormatArgsExpr parent | | ||
parent = this.getParent().getParent() and | ||
parent.getAnArg().getName() = def and | ||
this.getName() = def.getText() | ||
) | ||
} | ||
|
||
override Definition getDefinition() { result.asName() = def } | ||
|
||
override string getUseType() { result = "format argument" } | ||
} | ||
|
||
private class PositionalFormatUse extends Use instanceof Format { | ||
PositionalFormatUse() { not exists(this.getArgumentRef()) } | ||
|
||
override Definition getDefinition() { | ||
exists(FormatArgsExpr parent, int index | parent.getFormat(_) = this | | ||
this = rank[index + 1](PositionalFormatUse f, int i | parent.getFormat(i) = f | f order by i) and | ||
result.asExpr() = parent.getArg(index).getExpr() | ||
) | ||
} | ||
|
||
override string getUseType() { result = "format argument" } | ||
} | ||
|
||
private class PositionalFormatArgumentUse extends Use instanceof PositionalFormatArgument { | ||
private Expr def; | ||
|
||
PositionalFormatArgumentUse() { | ||
exists(FormatArgsExpr parent | | ||
parent = this.getParent().getParent() and | ||
def = parent.getArg(this.getIndex()).getExpr() | ||
) | ||
} | ||
|
||
override Definition getDefinition() { result.asExpr() = def } | ||
|
||
override string getUseType() { result = "format argument" } | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/** | ||
* @name Find-references links | ||
* @description Generates use-definition pairs that provide the data | ||
* for find-references in the code viewer. | ||
* @kind definitions | ||
* @id rust/ide-find-references | ||
* @tags ide-contextual-queries/local-references | ||
*/ | ||
|
||
import codeql.IDEContextual | ||
import codeql.rust.internal.Definitions | ||
|
||
external string selectedSourceFile(); | ||
|
||
from Use use, Definition def, string kind | ||
where | ||
def = definitionOf(use, kind) and | ||
def.getLocation().getFile() = getFileBySourceArchiveName(selectedSourceFile()) | ||
select use, def, kind |
19 changes: 19 additions & 0 deletions
19
rust/ql/test/library-tests/definitions/Definitions.expected
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
| main.rs:2:9:2:13 | width | main.rs:5:29:5:33 | width | local variable | | ||
| main.rs:2:9:2:13 | width | main.rs:6:41:6:45 | width | local variable | | ||
| main.rs:2:9:2:13 | width | main.rs:7:36:7:40 | width | local variable | | ||
| main.rs:3:9:3:17 | precision | main.rs:5:36:5:44 | precision | local variable | | ||
| main.rs:3:9:3:17 | precision | main.rs:6:48:6:56 | precision | local variable | | ||
| main.rs:4:9:4:13 | value | main.rs:6:34:6:38 | value | local variable | | ||
| main.rs:4:9:4:13 | value | main.rs:7:29:7:33 | value | local variable | | ||
| main.rs:5:50:5:54 | value | main.rs:5:22:5:26 | value | format argument | | ||
| main.rs:6:34:6:38 | value | main.rs:6:22:6:22 | 0 | format argument | | ||
| main.rs:6:41:6:45 | width | main.rs:6:25:6:25 | 1 | format argument | | ||
| main.rs:6:48:6:56 | precision | main.rs:6:28:6:28 | 2 | format argument | | ||
| main.rs:7:29:7:33 | value | main.rs:7:21:7:22 | {} | format argument | | ||
| main.rs:7:36:7:40 | width | main.rs:7:24:7:25 | {} | format argument | | ||
| main.rs:8:9:8:14 | people | main.rs:9:22:9:27 | people | local variable | | ||
| main.rs:10:31:10:31 | 1 | main.rs:10:19:10:20 | {} | format argument | | ||
| main.rs:10:31:10:31 | 1 | main.rs:10:23:10:23 | 0 | format argument | | ||
| main.rs:10:34:10:34 | 2 | main.rs:10:16:10:16 | 1 | format argument | | ||
| main.rs:10:34:10:34 | 2 | main.rs:10:26:10:27 | {} | format argument | | ||
| main.rs:11:40:11:42 | "x" | main.rs:11:31:11:35 | {:<5} | format argument | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import codeql.rust.internal.Definitions | ||
|
||
from Definition def, Use use, string kind | ||
where def = definitionOf(use, kind) | ||
select def, use, kind |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
fn main() { | ||
let width = 4; | ||
let precision = 2; | ||
let value = 10; | ||
println!("Value {value:#width$.precision$}", value = 10.5); | ||
println!("Value {0:#1$.2$}", value, width, precision); | ||
println!("Value {} {}", value, width); | ||
let people = "Rustaceans"; | ||
println!("Hello {people}!"); | ||
println!("{1} {} {0} {}", 1, 2); | ||
assert_eq!(format!("Hello {:<5}!", "x"), "Hello x !"); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Check warning
Code scanning / CodeQL
Redundant import Warning