diff --git a/rust/ql/.generated.list b/rust/ql/.generated.list index a8450ac3d014..4db40d43f2f0 100644 --- a/rust/ql/.generated.list +++ b/rust/ql/.generated.list @@ -236,10 +236,6 @@ lib/codeql/rust/elements/internal/ForTypeImpl.qll b515639844778d0fbe51e6161a2ec1 lib/codeql/rust/elements/internal/FormatArgsArgConstructor.qll 8bd9b4e035ef8adeb3ac510dd68043934c0140facb933be1f240096d01cdfa11 74e9d3bbd8882ae59a7e88935d468e0a90a6529a4e2af6a3d83e93944470f0ee lib/codeql/rust/elements/internal/FormatArgsArgImpl.qll 601f7715e9a65bcfa7cea1979fa30d694b5bea29650d799d7dd3080b8eea58e9 ecb0800cdb8c0f93277982dad295ac6a5332e42eff4fb5c8ff19f903b9857003 lib/codeql/rust/elements/internal/FormatArgsExprConstructor.qll ce29ff5a839b885b1ab7a02d6a381ae474ab1be3e6ee7dcfd7595bdf28e4b558 63bf957426871905a51ea319662a59e38104c197a1024360aca364dc145b11e8 -lib/codeql/rust/elements/internal/FormatArgumentConstructor.qll dea59a9e64681583b2b57c60b1d71f567af9d490bfd60a4cb118201c0e45e0bd aeeaffa43919ae7fed76c0a4be74547c657dc530c2af0fd94bc0c95cbf5a8194 -lib/codeql/rust/elements/internal/FormatArgumentImpl.qll e8115612cf08af743545e36091c4d06f00eb5ece8da8eee534bf3d269432da1c 88cae5f265f85f20f96ca2fdb7d353463ef16eebc6e86dd2ab023bc4f36f35f7 -lib/codeql/rust/elements/internal/FormatConstructor.qll 21cb51ec160d04cd4539d9c9488a21ac2a5d6a1eb35670429f7da1a6676d7d46 bcb7231ae549ec86d33581f5c89a4c346c190a02ed96fa7acd0ecba77240419e -lib/codeql/rust/elements/internal/FormatImpl.qll 4cebae0a808c68577976f38e45ae4bcb4d31ae3875afc36f560bfa23e5df3a83 67e0afd957254966f874af1137da1f293570f1fec519650a2572c0a932f5258f lib/codeql/rust/elements/internal/FunctionConstructor.qll b50aea579938d03745dfbd8b5fa8498f7f83b967369f63d6875510e09ab7f5d2 19cca32aeaecaf9debc27329e8c39ecec69464bb1d89d7b09908a1d73a8d92a2 lib/codeql/rust/elements/internal/GenericArgImpl.qll 6b1b804c357425c223f926e560a688e81506f5a35b95485cecf704e88cc009ee cc1ccf6a23dadc397e82664f3911d4b385d4c8ca80b1ee16d5275d9c936148dd lib/codeql/rust/elements/internal/GenericArgListConstructor.qll 46859bb3eb09d77987a18642d65ba2e13471a4dc9c0a83a192fddc82e37c335c 2c7d54c876269a88d3461b05745e73b06532b1616cae9b614ac94b28735d8fc4 diff --git a/rust/ql/.gitattributes b/rust/ql/.gitattributes index 2f97b19b0163..13abe120cc73 100644 --- a/rust/ql/.gitattributes +++ b/rust/ql/.gitattributes @@ -238,10 +238,6 @@ /lib/codeql/rust/elements/internal/FormatArgsArgConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/FormatArgsArgImpl.qll linguist-generated /lib/codeql/rust/elements/internal/FormatArgsExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/FormatArgumentConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/FormatArgumentImpl.qll linguist-generated -/lib/codeql/rust/elements/internal/FormatConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/FormatImpl.qll linguist-generated /lib/codeql/rust/elements/internal/FunctionConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/GenericArgImpl.qll linguist-generated /lib/codeql/rust/elements/internal/GenericArgListConstructor.qll linguist-generated diff --git a/rust/ql/lib/codeql/rust/elements/FormatTemplate.qll b/rust/ql/lib/codeql/rust/elements/FormatTemplate.qll deleted file mode 100644 index a2c7138fde28..000000000000 --- a/rust/ql/lib/codeql/rust/elements/FormatTemplate.qll +++ /dev/null @@ -1,248 +0,0 @@ -/** - * This module provides the classes modeling formatting templates. See also https://doc.rust-lang.org/std/fmt - */ - -private import FormatArgsExpr -private import LiteralExpr - -/** - * A regular expression for matching format elements in a formatting template. The - * regular expression is generated from the following python code: - * - * ```python - * identifier = "([A-Za-z_][A-Za-z0-9_]*)" - * integer = "([0-9]+)" - * - * # argument := integer | identifier - * argument = "({integer}|{identifier})".format(integer=integer, identifier=identifier) - * - * # parameter := argument '$' - * parameter = "(({argument})\\$)".format(argument=argument) - * - * # count := parameter | integer - * count = "({parameter}|{integer})".format(integer=integer, parameter=parameter) - * - * # fill := character - * fill = "(.)" - * - * # align := '<' | '^' | '>' - * align = "([<^>])" - * - * # sign := '+' | '-' - * sign = "([+-])" - * - * # width := count - * width = count - * - * # precision := count | '*' - * precision = "({count}|(\\*))".format(count=count) - * - * # type := '' | '?' | 'x?' | 'X?' | identifier - * type = "(|\\?|x\\?|X\\?|{identifier})".format(identifier=identifier) - * - * # format_spec := [[fill]align][sign]['#']['0'][width]['.' precision]type - * format_spec = "({fill}?{align})?{sign}?(#)?(0)?{width}?(\\.{precision})?{type}".format(fill=fill, align=align, sign=sign, width=width, precision=precision, type=type) - * - * # format := '{' [ argument ] [ ':' format_spec ] [ ws ] * '}' - * format = "(\\{{{argument}?(:{format_spec})?\s*}\\})".format(argument=argument, format_spec=format_spec) - * - * ``` - */ -private string formatRegex() { - result = - "(\\{(([0-9]+)|([A-Za-z_][A-Za-z0-9_]*))?(:((.)?([<^>]))?([+-])?(#)?(0)?(((([0-9]+)|([A-Za-z_][A-Za-z0-9_]*))\\$)|([0-9]+))?(\\.((((([0-9]+)|([A-Za-z_][A-Za-z0-9_]*))\\$)|([0-9]+))|(\\*)))?(|\\?|x\\?|X\\?|([A-Za-z_][A-Za-z0-9_]*)))?\\s*\\})" -} - -private string textRegex() { result = "([^{}]|\\{\\{|\\}\\})+" } - -private string part(FormatArgsExpr parent, int occurrenceIndex, int occurrenceOffset) { - result = - parent - .getTemplate() - .(LiteralExpr) - .getTextValue() - // TODO: should also handle surrounding quotes and escaped characters - .regexpFind(textRegex() + "|" + formatRegex(), occurrenceIndex, occurrenceOffset) -} - -private newtype TFormatTemplateElem = - TFormat(FormatArgsExpr parent, string text, int index, int offset) { - text = part(parent, index, offset) and text.regexpMatch(formatRegex()) - } - -private newtype TFormatArgumentKind = - TElement() or - TWidth() or - TPrecision() - -private newtype TFormatArgumentT = - TFormatArgument( - TFormat parent, TFormatArgumentKind kind, string value, boolean positional, int offset - ) { - exists(string text, int formatOffset, int group | - group = [3, 4] and offset = formatOffset + 1 and kind = TElement() - or - group = [15, 16] and - offset = formatOffset + min(text.indexOf(value + "$")) and - kind = TWidth() - or - group = [23, 24] and - offset = formatOffset + max(text.indexOf(value + "$")) and - kind = TPrecision() - | - parent = TFormat(_, text, _, formatOffset) and - value = text.regexpCapture(formatRegex(), group) and - if group % 2 = 1 then positional = true else positional = false - ) - } - -/** - * A format element in a formatting template. For example the `{}` in: - * ```rust - * println!("Hello {}", "world"); - * ``` - */ -class Format extends TFormat { - private FormatArgsExpr parent; - private string text; - private int index; - private int offset; - - Format() { this = TFormat(parent, text, index, offset) } - - /** Gets a textual representation of this element. */ - string toString() { result = text } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Providing locations in CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - parent - .getTemplate() - .getLocation() - .hasLocationInfo(filepath, startline, startcolumn - offset, _, _) and - endline = startline and - endcolumn = startcolumn + text.length() - 1 - } - - /** Gets a the parent of this `Format`. */ - FormatArgsExpr getParent() { result = parent } - - /** Gets the index of this `Format` node. */ - int getIndex() { result = index } - - /** - * Gets the name or position reference of this format, if any. For example `name` and `0` in: - * ```rust - * let name = "Alice"; - * println!("{name} in wonderland"); - * println!("{0} in wonderland", name); - * ``` - */ - FormatArgument getArgumentRef() { - result.getParent() = this and result = TFormatArgument(_, TElement(), _, _, _) - } - - /** - * Gets the name or position reference of the width parameter in this format, if any. For example `width` and `1` in: - * ```rust - * let width = 6; - * println!("{:width$}", PI); - * println!("{:1$}", PI, width); - * ``` - */ - FormatArgument getWidthArgument() { - result.getParent() = this and result = TFormatArgument(_, TWidth(), _, _, _) - } - - /** - * Gets the name or position reference of the width parameter in this format, if any. For example `prec` and `1` in: - * ```rust - * let prec = 6; - * println!("{:.prec$}", PI); - * println!("{:.1$}", PI, prec); - * ``` - */ - FormatArgument getPrecisionArgument() { - result.getParent() = this and result = TFormatArgument(_, TPrecision(), _, _, _) - } -} - -/** - * An argument in a format element in a formatting template. For example the `width`, `precision`, and `value` in: - * ```rust - * println!("Value {value:#width$.precision$}"); - * ``` - * or the `0`, `1` and `2` in: - * ```rust - * println!("Value {0:#1$.2$}", value, width, precision); - * ``` - */ -class FormatArgument extends TFormatArgumentT { - private Format parent; - string name; - private int offset; - - FormatArgument() { this = TFormatArgument(parent, _, name, _, offset) } - - /** Gets a textual representation of this element. */ - string toString() { result = name } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Providing locations in CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - // TODO: handle locations in multi-line comments - // TODO: handle the case where the template is from a nested macro call - parent - .getParent() - .getTemplate() - .getLocation() - .hasLocationInfo(filepath, startline, startcolumn - offset, _, _) and - endline = startline and - endcolumn = startcolumn + name.length() - 1 - } - - /** Gets a the parent of this `FormatArgument`. */ - Format getParent() { result = parent } -} - -/** - * A positional `FormatArgument`. For example `0` in - * ```rust - * let name = "Alice"; - * println!("{0} in wonderland", name); - * ``` - */ -class PositionalFormatArgument extends FormatArgument { - PositionalFormatArgument() { this = TFormatArgument(_, _, _, true, _) } - - /** Gets the index of this positional argument */ - int getIndex() { result = name.toInt() } -} - -/** - * A named `FormatArgument`. For example `name` in - * ```rust - * let name = "Alice"; - * println!("{name} in wonderland"); - * ``` - */ -class NamedFormatArgument extends FormatArgument { - NamedFormatArgument() { this = TFormatArgument(_, _, _, false, _) } - - /** Gets the name of this named argument */ - string getName() { result = name } -} diff --git a/rust/ql/lib/codeql/rust/elements/NamedFormatArgument.qll b/rust/ql/lib/codeql/rust/elements/NamedFormatArgument.qll new file mode 100644 index 000000000000..ff22b6745436 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/NamedFormatArgument.qll @@ -0,0 +1,7 @@ +/** + * This module provides the public class `NamedFormatArgument`. + */ + +private import internal.FormatArgumentImpl + +final class NamedFormatArgument = Impl::NamedFormatArgument; diff --git a/rust/ql/lib/codeql/rust/elements/PositionalFormatArgument.qll b/rust/ql/lib/codeql/rust/elements/PositionalFormatArgument.qll new file mode 100644 index 000000000000..e5fc88b14c4b --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/PositionalFormatArgument.qll @@ -0,0 +1,7 @@ +/** + * This module provides the public class `PositionalFormatArgument`. + */ + +private import internal.FormatArgumentImpl + +final class PositionalFormatArgument = Impl::PositionalFormatArgument; diff --git a/rust/ql/lib/codeql/rust/elements/internal/FormatArgsExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/FormatArgsExprImpl.qll index 7524a385e9ef..667439777b1a 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/FormatArgsExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/FormatArgsExprImpl.qll @@ -5,7 +5,7 @@ */ private import codeql.rust.elements.internal.generated.FormatArgsExpr -private import codeql.rust.elements.FormatTemplate +private import codeql.rust.elements.Format /** * INTERNAL: This module contains the customizable definition of `FormatArgsExpr` and should not diff --git a/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentConstructor.qll b/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentConstructor.qll index 9b72c8086073..d7b801f3dd9d 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentConstructor.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentConstructor.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module defines the hook used internally to tweak the characteristic predicate of * `FormatArgument` synthesized instances. @@ -6,9 +5,33 @@ */ private import codeql.rust.elements.internal.generated.Raw +private import codeql.rust.elements.internal.generated.Synth +private import codeql.rust.elements.internal.FormatConstructor /** * The characteristic predicate of `FormatArgument` synthesized instances. * INTERNAL: Do not use. */ -predicate constructFormatArgument(Raw::FormatArgsExpr parent, int index, int kind) { none() } +predicate constructFormatArgument(Raw::FormatArgsExpr parent, int index, int kind) { + formatArgument(parent, index, kind, _, _, _) +} + +predicate formatArgument( + Raw::FormatArgsExpr parent, int index, int kind, string value, boolean positional, int offset +) { + exists(string text, int formatOffset, int group | + group = [3, 4] and offset = formatOffset + 1 and kind = 0 + or + group = [15, 16] and + offset = formatOffset + min(text.indexOf(value + "$")) and + kind = 1 + or + group = [23, 24] and + offset = formatOffset + max(text.indexOf(value + "$")) and + kind = 2 + | + text = formatElement(parent, index, formatOffset) and + value = text.regexpCapture(formatRegex(), group) and + if group % 2 = 1 then positional = true else positional = false + ) +} diff --git a/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentImpl.qll index c1d6ef1de6f1..6230c394ee5d 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `FormatArgument`. * @@ -8,12 +7,14 @@ private import codeql.rust.elements.internal.generated.FormatArgument private import codeql.rust.elements.internal.generated.Raw private import codeql.rust.elements.internal.generated.Synth +private import codeql.rust.elements.internal.FormatArgumentConstructor /** * INTERNAL: This module contains the customizable definition of `FormatArgument` and should not * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * An argument in a format element in a formatting template. For example the `width`, `precision`, and `value` in: * ```rust @@ -25,15 +26,61 @@ module Impl { * ``` */ class FormatArgument extends Generated::FormatArgument { - cached - private Raw::FormatArgsExpr getUnderlyingParent() { - this = Synth::TFormatArgument(result, _, _) + Raw::FormatArgsExpr parent; + int index; + int kind; + string name; + private int offset; + + FormatArgument() { + this = Synth::TFormatArgument(parent, index, kind) and + formatArgument(parent, index, kind, name, _, offset) } - cached - private int getUnderlyingIndex() { this = Synth::TFormatArgument(_, result, _) } + override string toString() { result = name } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + // TODO: handle locations in multi-line comments + // TODO: handle the case where the template is from a nested macro call + Synth::convertFormatArgsExprFromRaw(parent) + .(FormatArgsExpr) + .getTemplate() + .getLocation() + .hasLocationInfo(filepath, startline, startcolumn - offset, _, _) and + endline = startline and + endcolumn = startcolumn + name.length() - 1 + } + + override Format getParent() { result = Synth::TFormat(parent, index) } + } + + /** + * A positional `FormatArgument`. For example `0` in + * ```rust + * let name = "Alice"; + * println!("{0} in wonderland", name); + * ``` + */ + class PositionalFormatArgument extends FormatArgument { + PositionalFormatArgument() { formatArgument(parent, index, kind, _, true, _) } + + /** Gets the index of this positional argument */ + int getIndex() { result = name.toInt() } + } + + /** + * A named `FormatArgument`. For example `name` in + * ```rust + * let name = "Alice"; + * println!("{name} in wonderland"); + * ``` + */ + class NamedFormatArgument extends FormatArgument { + NamedFormatArgument() { formatArgument(parent, index, kind, _, false, _) } - cached - private int getUnderlyingKind() { this = Synth::TFormatArgument(_, _, result) } + /** Gets the name of this named argument */ + string getName() { result = name } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/FormatConstructor.qll b/rust/ql/lib/codeql/rust/elements/internal/FormatConstructor.qll index e238e69f5546..6ffd3b177f3d 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/FormatConstructor.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/FormatConstructor.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module defines the hook used internally to tweak the characteristic predicate of * `Format` synthesized instances. @@ -11,4 +10,69 @@ private import codeql.rust.elements.internal.generated.Raw * The characteristic predicate of `Format` synthesized instances. * INTERNAL: Do not use. */ -predicate constructFormat(Raw::FormatArgsExpr parent, int index) { none() } +predicate constructFormat(Raw::FormatArgsExpr parent, int index) { + formatElement(parent, index, _).regexpMatch(formatRegex()) +} + +/** + * Match an element of a format string, either text (`Hello`) or a format placeholder (`{}`). + */ +string formatElement(Raw::FormatArgsExpr parent, int occurrenceIndex, int occurrenceOffset) { + result = + parent + .getTemplate() + .(Raw::LiteralExpr) + .getTextValue() + // TODO: should also handle surrounding quotes and escaped characters + .regexpFind(textRegex() + "|" + formatRegex(), occurrenceIndex, occurrenceOffset) +} + +/** + * A regular expression for matching format elements in a formatting template. The + * regular expression is generated from the following python code: + * + * ```python + * identifier = "([A-Za-z_][A-Za-z0-9_]*)" + * integer = "([0-9]+)" + * + * # argument := integer | identifier + * argument = "({integer}|{identifier})".format(integer=integer, identifier=identifier) + * + * # parameter := argument '$' + * parameter = "(({argument})\\$)".format(argument=argument) + * + * # count := parameter | integer + * count = "({parameter}|{integer})".format(integer=integer, parameter=parameter) + * + * # fill := character + * fill = "(.)" + * + * # align := '<' | '^' | '>' + * align = "([<^>])" + * + * # sign := '+' | '-' + * sign = "([+-])" + * + * # width := count + * width = count + * + * # precision := count | '*' + * precision = "({count}|(\\*))".format(count=count) + * + * # type := '' | '?' | 'x?' | 'X?' | identifier + * type = "(|\\?|x\\?|X\\?|{identifier})".format(identifier=identifier) + * + * # format_spec := [[fill]align][sign]['#']['0'][width]['.' precision]type + * format_spec = "({fill}?{align})?{sign}?(#)?(0)?{width}?(\\.{precision})?{type}".format(fill=fill, align=align, sign=sign, width=width, precision=precision, type=type) + * + * # format := '{' [ argument ] [ ':' format_spec ] [ ws ] * '}' + * format = "(\\{{{argument}?(:{format_spec})?\s*}\\})".format(argument=argument, format_spec=format_spec) + * + * ``` + */ +string formatRegex() { + result = + "(\\{(([0-9]+)|([A-Za-z_][A-Za-z0-9_]*))?(:((.)?([<^>]))?([+-])?(#)?(0)?(((([0-9]+)|([A-Za-z_][A-Za-z0-9_]*))\\$)|([0-9]+))?(\\.((((([0-9]+)|([A-Za-z_][A-Za-z0-9_]*))\\$)|([0-9]+))|(\\*)))?(|\\?|x\\?|X\\?|([A-Za-z_][A-Za-z0-9_]*)))?\\s*\\})" +} + +private string textRegex() { result = "([^{}]|\\{\\{|\\}\\})+" } diff --git a/rust/ql/lib/codeql/rust/elements/internal/FormatImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/FormatImpl.qll index 1f41597f61ef..e2ff2ece42c3 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/FormatImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/FormatImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `Format`. * @@ -8,12 +7,15 @@ private import codeql.rust.elements.internal.generated.Format private import codeql.rust.elements.internal.generated.Raw private import codeql.rust.elements.internal.generated.Synth +private import codeql.rust.elements.internal.FormatConstructor +import codeql.rust.elements.FormatArgument /** * INTERNAL: This module contains the customizable definition of `Format` and should not * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A format element in a formatting template. For example the `{}` in: * ```rust @@ -21,10 +23,66 @@ module Impl { * ``` */ class Format extends Generated::Format { - cached - private Raw::FormatArgsExpr getUnderlyingParent() { this = Synth::TFormat(result, _) } + private Raw::FormatArgsExpr parent; + private string text; + private int index; + private int offset; - cached - private int getUnderlyingIndex() { this = Synth::TFormat(_, result) } + Format() { + this = Synth::TFormat(parent, index) and text = formatElement(parent, index, offset) + } + + override string toString() { result = text } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.getParent() + .getTemplate() + .getLocation() + .hasLocationInfo(filepath, startline, startcolumn - offset, _, _) and + endline = startline and + endcolumn = startcolumn + text.length() - 1 + } + + override FormatArgsExpr getParent() { result = Synth::convertFormatArgsExprFromRaw(parent) } + + override int getIndex() { result = index } + + /** + * Gets the name or position reference of this format, if any. For example `name` and `0` in: + * ```rust + * let name = "Alice"; + * println!("{name} in wonderland"); + * println!("{0} in wonderland", name); + * ``` + */ + FormatArgument getArgumentRef() { + result.getParent() = this and result = Synth::TFormatArgument(_, _, 0) + } + + /** + * Gets the name or position reference of the width parameter in this format, if any. For example `width` and `1` in: + * ```rust + * let width = 6; + * println!("{:width$}", PI); + * println!("{:1$}", PI, width); + * ``` + */ + FormatArgument getWidthArgument() { + result.getParent() = this and result = Synth::TFormatArgument(_, _, 1) + } + + /** + * Gets the name or position reference of the width parameter in this format, if any. For example `prec` and `1` in: + * ```rust + * let prec = 6; + * println!("{:.prec$}", PI); + * println!("{:.1$}", PI, prec); + * ``` + */ + FormatArgument getPrecisionArgument() { + result.getParent() = this and result = Synth::TFormatArgument(_, _, 2) + } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessConstructor.qll b/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessConstructor.qll index 9515e1cd82af..0ecf191795c9 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessConstructor.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessConstructor.qll @@ -6,7 +6,8 @@ private import codeql.rust.elements.internal.generated.Raw private import codeql.rust.elements.internal.generated.Synth -private import codeql.rust.elements.FormatTemplate +private import codeql.rust.elements.Format +private import codeql.rust.elements.NamedFormatArgument /** * The characteristic predicate of `ImplicitVariableAccess` synthesized instances. diff --git a/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessImpl.qll index abc74771d6b3..4ab1ee5a5da6 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessImpl.qll @@ -8,7 +8,8 @@ private import codeql.rust.elements.internal.generated.ImplicitVariableAccess private import codeql.rust.elements.internal.ImplicitVariableAccessConstructor private import codeql.rust.elements.internal.generated.Raw private import codeql.rust.elements.internal.generated.Synth -private import codeql.rust.elements.FormatTemplate +private import codeql.rust.elements.Format +private import codeql.rust.elements.NamedFormatArgument /** * INTERNAL: This module contains the customizable definition of `ImplicitVariableAccess` and should not diff --git a/rust/ql/lib/rust.qll b/rust/ql/lib/rust.qll index 45e593ed56e9..c61e177883ea 100644 --- a/rust/ql/lib/rust.qll +++ b/rust/ql/lib/rust.qll @@ -6,4 +6,5 @@ import codeql.files.FileSystem import codeql.rust.elements.AssignmentOperation import codeql.rust.elements.LogicalOperation import codeql.rust.elements.Variable -import codeql.rust.elements.FormatTemplate +import codeql.rust.elements.NamedFormatArgument +import codeql.rust.elements.PositionalFormatArgument