mirror of
https://github.com/typst/typst
synced 2025-05-17 02:25:27 +08:00
decorator -> annotation
This commit is contained in:
parent
0fb417ddb6
commit
fb77128423
@ -81,33 +81,33 @@ impl<'a> Markup<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
node! {
|
node! {
|
||||||
DecoratorName
|
AnnotationName
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DecoratorName<'a> {
|
impl<'a> AnnotationName<'a> {
|
||||||
/// Get the decorator name.
|
/// Get the annotation name.
|
||||||
pub fn get(self) -> &'a EcoString {
|
pub fn get(self) -> &'a EcoString {
|
||||||
self.0.text()
|
self.0.text()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the decorator name as a string slice.
|
/// Get the annotation name as a string slice.
|
||||||
pub fn as_str(self) -> &'a str {
|
pub fn as_str(self) -> &'a str {
|
||||||
self.get()
|
self.get()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node! {
|
node! {
|
||||||
/// A decorator: `/! allow("warning")`.
|
/// An annotation: `/! allow("warning")`.
|
||||||
Decorator
|
Annotation
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Decorator<'a> {
|
impl<'a> Annotation<'a> {
|
||||||
/// The name of the decorator, e.g. `allow`.
|
/// The name of the annotation, e.g. `allow`.
|
||||||
pub fn name(self) -> DecoratorName<'a> {
|
pub fn name(self) -> AnnotationName<'a> {
|
||||||
self.0.cast_first_match().unwrap_or_default()
|
self.0.cast_first_match().unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The decorator's arguments. Currently, they are always strings.
|
/// The annotation's arguments. Currently, they are always strings.
|
||||||
pub fn arguments(self) -> impl DoubleEndedIterator<Item = Str<'a>> {
|
pub fn arguments(self) -> impl DoubleEndedIterator<Item = Str<'a>> {
|
||||||
self.0.children().filter_map(Str::from_untyped)
|
self.0.children().filter_map(Str::from_untyped)
|
||||||
}
|
}
|
||||||
|
@ -286,9 +286,9 @@ pub fn highlight(node: &LinkedNode) -> Option<Tag> {
|
|||||||
SyntaxKind::Destructuring => None,
|
SyntaxKind::Destructuring => None,
|
||||||
SyntaxKind::DestructAssignment => None,
|
SyntaxKind::DestructAssignment => None,
|
||||||
|
|
||||||
SyntaxKind::Decorator => None,
|
SyntaxKind::Annotation => None,
|
||||||
SyntaxKind::DecoratorMarker => None,
|
SyntaxKind::AnnotationMarker => None,
|
||||||
SyntaxKind::DecoratorName => None,
|
SyntaxKind::AnnotationName => None,
|
||||||
|
|
||||||
SyntaxKind::LineComment => Some(Tag::Comment),
|
SyntaxKind::LineComment => Some(Tag::Comment),
|
||||||
SyntaxKind::BlockComment => Some(Tag::Comment),
|
SyntaxKind::BlockComment => Some(Tag::Comment),
|
||||||
|
@ -13,8 +13,8 @@ pub enum SyntaxKind {
|
|||||||
LineComment,
|
LineComment,
|
||||||
/// A block comment: `/* ... */`.
|
/// A block comment: `/* ... */`.
|
||||||
BlockComment,
|
BlockComment,
|
||||||
/// A decorator: `// @allow("warning")`.
|
/// An annotation: `// @allow("warning")`.
|
||||||
Decorator,
|
Annotation,
|
||||||
|
|
||||||
/// The contents of a file or content block.
|
/// The contents of a file or content block.
|
||||||
Markup,
|
Markup,
|
||||||
@ -281,10 +281,10 @@ pub enum SyntaxKind {
|
|||||||
/// A destructuring assignment expression: `(x, y) = (1, 2)`.
|
/// A destructuring assignment expression: `(x, y) = (1, 2)`.
|
||||||
DestructAssignment,
|
DestructAssignment,
|
||||||
|
|
||||||
/// A decorator's marker: `// @`.
|
/// An annotation's marker: `// @`.
|
||||||
DecoratorMarker,
|
AnnotationMarker,
|
||||||
/// A decorator's name: `allow`.
|
/// An annotation's name: `allow`.
|
||||||
DecoratorName,
|
AnnotationName,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SyntaxKind {
|
impl SyntaxKind {
|
||||||
@ -366,7 +366,7 @@ impl SyntaxKind {
|
|||||||
| Self::BlockComment
|
| Self::BlockComment
|
||||||
| Self::Space
|
| Self::Space
|
||||||
| Self::Parbreak
|
| Self::Parbreak
|
||||||
| Self::Decorator
|
| Self::Annotation
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,7 +382,7 @@ impl SyntaxKind {
|
|||||||
Self::Error => "syntax error",
|
Self::Error => "syntax error",
|
||||||
Self::LineComment => "line comment",
|
Self::LineComment => "line comment",
|
||||||
Self::BlockComment => "block comment",
|
Self::BlockComment => "block comment",
|
||||||
Self::Decorator => "decorator",
|
Self::Annotation => "annotation",
|
||||||
Self::Markup => "markup",
|
Self::Markup => "markup",
|
||||||
Self::Text => "text",
|
Self::Text => "text",
|
||||||
Self::Space => "space",
|
Self::Space => "space",
|
||||||
@ -510,8 +510,8 @@ impl SyntaxKind {
|
|||||||
Self::FuncReturn => "`return` expression",
|
Self::FuncReturn => "`return` expression",
|
||||||
Self::Destructuring => "destructuring pattern",
|
Self::Destructuring => "destructuring pattern",
|
||||||
Self::DestructAssignment => "destructuring assignment expression",
|
Self::DestructAssignment => "destructuring assignment expression",
|
||||||
Self::DecoratorMarker => "decorator marker",
|
Self::AnnotationMarker => "annotation marker",
|
||||||
Self::DecoratorName => "decorator name",
|
Self::AnnotationName => "annotation name",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ impl Lexer<'_> {
|
|||||||
/// syntax node returned might not always be a leaf, but could actually
|
/// syntax node returned might not always be a leaf, but could actually
|
||||||
/// come with a subtree (could be an inner node). This happens when it is
|
/// come with a subtree (could be an inner node). This happens when it is
|
||||||
/// preferred to perform parsing at the character level instead of at the
|
/// preferred to perform parsing at the character level instead of at the
|
||||||
/// token level, as seen, for example, in [`decorator`](Lexer::decorator).
|
/// token level, as seen, for example, in [`annotation`](Lexer::annotation).
|
||||||
pub fn next(&mut self) -> SyntaxNode {
|
pub fn next(&mut self) -> SyntaxNode {
|
||||||
if self.mode == LexMode::Raw {
|
if self.mode == LexMode::Raw {
|
||||||
let Some((kind, end)) = self.raw.pop() else {
|
let Some((kind, end)) = self.raw.pop() else {
|
||||||
@ -120,7 +120,7 @@ impl Lexer<'_> {
|
|||||||
let token = match self.s.eat() {
|
let token = match self.s.eat() {
|
||||||
Some(c) if is_space(c, self.mode) => self.whitespace(start, c),
|
Some(c) if is_space(c, self.mode) => self.whitespace(start, c),
|
||||||
Some('/') if self.s.eat_if('/') => {
|
Some('/') if self.s.eat_if('/') => {
|
||||||
return self.line_comment_or_decorator(start);
|
return self.line_comment_or_annotation(start);
|
||||||
}
|
}
|
||||||
Some('/') if self.s.eat_if('*') => self.block_comment(),
|
Some('/') if self.s.eat_if('*') => self.block_comment(),
|
||||||
Some('*') if self.s.eat_if('/') => {
|
Some('*') if self.s.eat_if('/') => {
|
||||||
@ -185,14 +185,14 @@ impl Lexer<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a decorator if the line comment has the form
|
/// Parses an annotation if the line comment has the form
|
||||||
/// `// @something`
|
/// `// @something`
|
||||||
///
|
///
|
||||||
/// Otherwise, parses a regular line comment.
|
/// Otherwise, parses a regular line comment.
|
||||||
fn line_comment_or_decorator(&mut self, start: usize) -> SyntaxNode {
|
fn line_comment_or_annotation(&mut self, start: usize) -> SyntaxNode {
|
||||||
self.s.eat_while(is_inline_whitespace);
|
self.s.eat_while(is_inline_whitespace);
|
||||||
if self.s.eat_if('@') {
|
if self.s.eat_if('@') {
|
||||||
return self.decorator(start);
|
return self.annotation(start);
|
||||||
}
|
}
|
||||||
self.s.eat_until(is_newline);
|
self.s.eat_until(is_newline);
|
||||||
self.emit_token(SyntaxKind::LineComment, start)
|
self.emit_token(SyntaxKind::LineComment, start)
|
||||||
@ -224,18 +224,18 @@ impl Lexer<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decorator lexing and auxiliary methods.
|
/// Annotation lexing and auxiliary methods.
|
||||||
impl Lexer<'_> {
|
impl Lexer<'_> {
|
||||||
/// Lexes and parses a decorator into a complete syntax subtree.
|
/// Lexes and parses an annotation into a complete syntax subtree.
|
||||||
///
|
///
|
||||||
/// The lexer is fully responsible for the decorator, as it is simpler to
|
/// The lexer is fully responsible for the annotation, as it is simpler to
|
||||||
/// parse them at the character level, given they follow a very simple
|
/// parse them at the character level, given they follow a very simple
|
||||||
/// and rigid structure, in the form
|
/// and rigid structure, in the form
|
||||||
/// `/! decorator-name("string argument1", "string argument2")`
|
/// `/! annotation-name("string argument1", "string argument2")`
|
||||||
/// with optional whitespaces and comments between arguments.
|
/// with optional whitespaces and comments between arguments.
|
||||||
fn decorator(&mut self, start: usize) -> SyntaxNode {
|
fn annotation(&mut self, start: usize) -> SyntaxNode {
|
||||||
// Start by lexing the marker.
|
// Start by lexing the marker.
|
||||||
let marker = self.emit_token(SyntaxKind::DecoratorMarker, start);
|
let marker = self.emit_token(SyntaxKind::AnnotationMarker, start);
|
||||||
let mut subtree = vec![marker];
|
let mut subtree = vec![marker];
|
||||||
|
|
||||||
let current_start = self.s.cursor();
|
let current_start = self.s.cursor();
|
||||||
@ -245,35 +245,35 @@ impl Lexer<'_> {
|
|||||||
subtree.push(self.emit_token(SyntaxKind::Space, current_start));
|
subtree.push(self.emit_token(SyntaxKind::Space, current_start));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lex the decorator name.
|
// Lex the annotation name.
|
||||||
let current_start = self.s.cursor();
|
let current_start = self.s.cursor();
|
||||||
if !self.s.eat_if(is_id_start) {
|
if !self.s.eat_if(is_id_start) {
|
||||||
self.s.eat_until(is_newline);
|
self.s.eat_until(is_newline);
|
||||||
subtree.push(self.emit_error("expected identifier", current_start));
|
subtree.push(self.emit_error("expected identifier", current_start));
|
||||||
|
|
||||||
// Return a single error node until the end of the decorator.
|
// Return a single error node until the end of the annotation.
|
||||||
return SyntaxNode::inner(SyntaxKind::Decorator, subtree);
|
return SyntaxNode::inner(SyntaxKind::Annotation, subtree);
|
||||||
}
|
}
|
||||||
|
|
||||||
let decorator_name = self.decorator_name(current_start);
|
let annotation_name = self.annotation_name(current_start);
|
||||||
subtree.push(self.emit_token(decorator_name, current_start));
|
subtree.push(self.emit_token(annotation_name, current_start));
|
||||||
|
|
||||||
// Left parenthesis before decorator arguments.
|
// Left parenthesis before annotation arguments.
|
||||||
let current_start = self.s.cursor();
|
let current_start = self.s.cursor();
|
||||||
if !self.s.eat_if('(') {
|
if !self.s.eat_if('(') {
|
||||||
self.s.eat_until(is_newline);
|
self.s.eat_until(is_newline);
|
||||||
subtree.push(self.emit_error("expected opening paren", current_start));
|
subtree.push(self.emit_error("expected opening paren", current_start));
|
||||||
|
|
||||||
// Return a single error node until the end of the decorator.
|
// Return a single error node until the end of the annotation.
|
||||||
return SyntaxNode::inner(SyntaxKind::Decorator, subtree);
|
return SyntaxNode::inner(SyntaxKind::Annotation, subtree);
|
||||||
}
|
}
|
||||||
|
|
||||||
subtree.push(self.emit_token(SyntaxKind::LeftParen, current_start));
|
subtree.push(self.emit_token(SyntaxKind::LeftParen, current_start));
|
||||||
|
|
||||||
// Decorator arguments:
|
// Annotation arguments:
|
||||||
// Keep reading until we find a right parenthesis or newline. We have
|
// Keep reading until we find a right parenthesis or newline. We have
|
||||||
// to check the newline before eating (through '.peek()') to ensure it
|
// to check the newline before eating (through '.peek()') to ensure it
|
||||||
// is not considered part of the decorator.
|
// is not considered part of the annotation.
|
||||||
let mut current_start = self.s.cursor();
|
let mut current_start = self.s.cursor();
|
||||||
let mut expecting_comma = false;
|
let mut expecting_comma = false;
|
||||||
let mut finished = false;
|
let mut finished = false;
|
||||||
@ -284,9 +284,9 @@ impl Lexer<'_> {
|
|||||||
SyntaxKind::Space
|
SyntaxKind::Space
|
||||||
}
|
}
|
||||||
Some('/') if self.s.eat_if('/') => {
|
Some('/') if self.s.eat_if('/') => {
|
||||||
let node = self.line_comment_or_decorator(current_start);
|
let node = self.line_comment_or_annotation(current_start);
|
||||||
if node.kind() == SyntaxKind::Decorator {
|
if node.kind() == SyntaxKind::Annotation {
|
||||||
self.error("cannot have multiple decorators per line")
|
self.error("cannot have multiple annotations per line")
|
||||||
} else {
|
} else {
|
||||||
subtree.push(node);
|
subtree.push(node);
|
||||||
current_start = self.s.cursor();
|
current_start = self.s.cursor();
|
||||||
@ -298,7 +298,7 @@ impl Lexer<'_> {
|
|||||||
// After we finished specifying arguments, there must only
|
// After we finished specifying arguments, there must only
|
||||||
// be whitespaces until the line ends.
|
// be whitespaces until the line ends.
|
||||||
self.s.eat_until(char::is_whitespace);
|
self.s.eat_until(char::is_whitespace);
|
||||||
self.error("expected end of decorator")
|
self.error("expected end of annotation")
|
||||||
}
|
}
|
||||||
Some('"') if expecting_comma => {
|
Some('"') if expecting_comma => {
|
||||||
self.s.eat_until(|c| c == ',' || c == ')' || is_newline(c));
|
self.s.eat_until(|c| c == ',' || c == ')' || is_newline(c));
|
||||||
@ -306,7 +306,7 @@ impl Lexer<'_> {
|
|||||||
}
|
}
|
||||||
Some('"') => {
|
Some('"') => {
|
||||||
expecting_comma = true;
|
expecting_comma = true;
|
||||||
self.decorator_string()
|
self.annotation_string()
|
||||||
}
|
}
|
||||||
Some(',') if expecting_comma => {
|
Some(',') if expecting_comma => {
|
||||||
expecting_comma = false;
|
expecting_comma = false;
|
||||||
@ -318,7 +318,7 @@ impl Lexer<'_> {
|
|||||||
SyntaxKind::RightParen
|
SyntaxKind::RightParen
|
||||||
}
|
}
|
||||||
Some(c) => self.error(eco_format!(
|
Some(c) => self.error(eco_format!(
|
||||||
"the character '{c}' is not valid in a decorator"
|
"the character '{c}' is not valid in an annotation"
|
||||||
)),
|
)),
|
||||||
None => break,
|
None => break,
|
||||||
};
|
};
|
||||||
@ -334,34 +334,34 @@ impl Lexer<'_> {
|
|||||||
subtree.push(self.emit_error("expected closing paren", self.s.cursor()));
|
subtree.push(self.emit_error("expected closing paren", self.s.cursor()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SyntaxNode::inner(SyntaxKind::Decorator, subtree)
|
SyntaxNode::inner(SyntaxKind::Annotation, subtree)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lexes a decorator name.
|
/// Lexes an annotation name.
|
||||||
///
|
///
|
||||||
/// A decorator name is an identifier within a specific subset of allowed
|
/// An annotation name is an identifier within a specific subset of allowed
|
||||||
/// identifiers. Currently, `allow` is the only valid decorator name.
|
/// identifiers. Currently, `allow` is the only valid annotation name.
|
||||||
fn decorator_name(&mut self, start: usize) -> SyntaxKind {
|
fn annotation_name(&mut self, start: usize) -> SyntaxKind {
|
||||||
self.s.eat_while(is_id_continue);
|
self.s.eat_while(is_id_continue);
|
||||||
let ident = self.s.from(start);
|
let ident = self.s.from(start);
|
||||||
|
|
||||||
if ident == "allow" {
|
if ident == "allow" {
|
||||||
SyntaxKind::DecoratorName
|
SyntaxKind::AnnotationName
|
||||||
} else {
|
} else {
|
||||||
let error = self.error(eco_format!("invalid decorator name"));
|
let error = self.error(eco_format!("invalid annotation name"));
|
||||||
self.hint("must be 'allow'");
|
self.hint("must be 'allow'");
|
||||||
error
|
error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lexes a string in a decorator.
|
/// Lexes a string in an annotation.
|
||||||
///
|
///
|
||||||
/// Currently, such strings only allow a very restricted set of characters.
|
/// Currently, such strings only allow a very restricted set of characters.
|
||||||
/// These restrictions may be lifted in the future.
|
/// These restrictions may be lifted in the future.
|
||||||
fn decorator_string(&mut self) -> SyntaxKind {
|
fn annotation_string(&mut self) -> SyntaxKind {
|
||||||
// TODO: Allow more characters in decorators' strings, perhaps allowing
|
// TODO: Allow more characters in annotations' strings, perhaps allowing
|
||||||
// newlines somehow.
|
// newlines somehow.
|
||||||
// Could perhaps use one //! per line so we can break a decorator into
|
// Could perhaps use one //! per line so we can break an annotation into
|
||||||
// multiple lines in a sensible way.
|
// multiple lines in a sensible way.
|
||||||
let start = self.s.cursor();
|
let start = self.s.cursor();
|
||||||
self.s.eat_while(|c| !is_newline(c) && c != '"');
|
self.s.eat_while(|c| !is_newline(c) && c != '"');
|
||||||
@ -371,9 +371,9 @@ impl Lexer<'_> {
|
|||||||
return self.error("unclosed string");
|
return self.error("unclosed string");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(c) = content.chars().find(|c| !is_valid_in_decorator_string(*c)) {
|
if let Some(c) = content.chars().find(|c| !is_valid_in_annotation_string(*c)) {
|
||||||
return self
|
return self
|
||||||
.error(eco_format!("invalid character '{c}' in a decorator's string"));
|
.error(eco_format!("invalid character '{c}' in an annotation's string"));
|
||||||
}
|
}
|
||||||
|
|
||||||
SyntaxKind::Str
|
SyntaxKind::Str
|
||||||
@ -1160,9 +1160,9 @@ fn is_valid_in_label_literal(c: char) -> bool {
|
|||||||
is_id_continue(c) || matches!(c, ':' | '.')
|
is_id_continue(c) || matches!(c, ':' | '.')
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether a character can be part of a string in a decorator.
|
/// Whether a character can be part of a string in an annotation.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_valid_in_decorator_string(c: char) -> bool {
|
fn is_valid_in_annotation_string(c: char) -> bool {
|
||||||
is_id_continue(c) || c == '@' || c == '/'
|
is_id_continue(c) || c == '@' || c == '/'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -818,15 +818,15 @@ impl<'a> LinkedNode<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the first sibling decorator node at the line above this node.
|
/// Get the first sibling annotation node at the line above this node.
|
||||||
/// This is done by moving backwards, checking for decorators, until we hit
|
/// This is done by moving backwards, checking for annotations, until we hit
|
||||||
/// a second newline (that is, we only check, at most, the line before this
|
/// a second newline (that is, we only check, at most, the line before this
|
||||||
/// node).
|
/// node).
|
||||||
pub fn prev_attached_decorator(&self) -> Option<Self> {
|
pub fn prev_attached_annotation(&self) -> Option<Self> {
|
||||||
let mut cursor = self.prev_sibling_inner()?;
|
let mut cursor = self.prev_sibling_inner()?;
|
||||||
let mut newlines = cursor.capped_newlines();
|
let mut newlines = cursor.capped_newlines();
|
||||||
while newlines < 2 {
|
while newlines < 2 {
|
||||||
if cursor.kind() == SyntaxKind::Decorator {
|
if cursor.kind() == SyntaxKind::Annotation {
|
||||||
return Some(cursor);
|
return Some(cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -834,8 +834,8 @@ impl<'a> LinkedNode<'a> {
|
|||||||
newlines += cursor.capped_newlines();
|
newlines += cursor.capped_newlines();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decorators are attached if they're in the previous line.
|
// Annotations are attached if they're in the previous line.
|
||||||
// If we counted at least two newlines, no decorators are attached to
|
// If we counted at least two newlines, no annotations are attached to
|
||||||
// this node.
|
// this node.
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ fn markup_expr(p: &mut Parser, at_start: &mut bool) {
|
|||||||
| SyntaxKind::Parbreak
|
| SyntaxKind::Parbreak
|
||||||
| SyntaxKind::LineComment
|
| SyntaxKind::LineComment
|
||||||
| SyntaxKind::BlockComment
|
| SyntaxKind::BlockComment
|
||||||
| SyntaxKind::Decorator => {
|
| SyntaxKind::Annotation => {
|
||||||
p.eat();
|
p.eat();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ pub const MARKUP_EXPR: SyntaxSet = SyntaxSet::new()
|
|||||||
.add(SyntaxKind::Parbreak)
|
.add(SyntaxKind::Parbreak)
|
||||||
.add(SyntaxKind::LineComment)
|
.add(SyntaxKind::LineComment)
|
||||||
.add(SyntaxKind::BlockComment)
|
.add(SyntaxKind::BlockComment)
|
||||||
.add(SyntaxKind::Decorator)
|
.add(SyntaxKind::Annotation)
|
||||||
.add(SyntaxKind::Text)
|
.add(SyntaxKind::Text)
|
||||||
.add(SyntaxKind::Linebreak)
|
.add(SyntaxKind::Linebreak)
|
||||||
.add(SyntaxKind::Escape)
|
.add(SyntaxKind::Escape)
|
||||||
|
@ -542,7 +542,7 @@ pub fn deduplicate_and_suppress_warnings(
|
|||||||
|
|
||||||
/// Checks if a given warning is suppressed given one span it has a tracepoint
|
/// Checks if a given warning is suppressed given one span it has a tracepoint
|
||||||
/// in. If one of the ancestors of the node where the warning occurred has a
|
/// in. If one of the ancestors of the node where the warning occurred has a
|
||||||
/// warning suppression decorator sibling right before it suppressing this
|
/// warning suppression annotation sibling right before it suppressing this
|
||||||
/// particular warning, the warning is considered suppressed.
|
/// particular warning, the warning is considered suppressed.
|
||||||
fn is_warning_suppressed(span: Span, world: &dyn World, identifier: &Identifier) -> bool {
|
fn is_warning_suppressed(span: Span, world: &dyn World, identifier: &Identifier) -> bool {
|
||||||
// Don't suppress detached warnings.
|
// Don't suppress detached warnings.
|
||||||
@ -556,13 +556,13 @@ fn is_warning_suppressed(span: Span, world: &dyn World, identifier: &Identifier)
|
|||||||
// Walk the parent nodes to check for a warning suppression in the
|
// Walk the parent nodes to check for a warning suppression in the
|
||||||
// previous line.
|
// previous line.
|
||||||
while let Some(node) = searched_node {
|
while let Some(node) = searched_node {
|
||||||
let mut searched_decorator = node.prev_attached_decorator();
|
let mut searched_annotation = node.prev_attached_annotation();
|
||||||
while let Some(sibling) = searched_decorator {
|
while let Some(sibling) = searched_annotation {
|
||||||
let decorator = sibling.cast::<ast::Decorator>().unwrap();
|
let annotation = sibling.cast::<ast::Annotation>().unwrap();
|
||||||
if check_decorator_suppresses_warning(decorator, identifier) {
|
if check_annotation_suppresses_warning(annotation, identifier) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
searched_decorator = sibling.prev_attached_decorator();
|
searched_annotation = sibling.prev_attached_annotation();
|
||||||
}
|
}
|
||||||
searched_node = node.parent();
|
searched_node = node.parent();
|
||||||
}
|
}
|
||||||
@ -570,17 +570,17 @@ fn is_warning_suppressed(span: Span, world: &dyn World, identifier: &Identifier)
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if an 'allow' decorator would cause a warning with a particular
|
/// Checks if an 'allow' annotation would cause a warning with a particular
|
||||||
/// identifier to be suppressed.
|
/// identifier to be suppressed.
|
||||||
fn check_decorator_suppresses_warning(
|
fn check_annotation_suppresses_warning(
|
||||||
decorator: ast::Decorator,
|
annotation: ast::Annotation,
|
||||||
warning: &Identifier,
|
warning: &Identifier,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if decorator.name().as_str() != "allow" {
|
if annotation.name().as_str() != "allow" {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for argument in decorator.arguments() {
|
for argument in annotation.arguments() {
|
||||||
if warning.name() == argument.get() {
|
if warning.name() == argument.get() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Test decorators.
|
// Test annotations.
|
||||||
|
|
||||||
--- basic-decorators ---
|
--- basic-annotations ---
|
||||||
|
|
||||||
// @allow()
|
// @allow()
|
||||||
// @allow("A")
|
// @allow("A")
|
||||||
@ -19,7 +19,7 @@
|
|||||||
h(#0em)
|
h(#0em)
|
||||||
$
|
$
|
||||||
|
|
||||||
--- decorator-comments ---
|
--- annotation-comments ---
|
||||||
|
|
||||||
// @allow("abc") // this is ok
|
// @allow("abc") // this is ok
|
||||||
|
|
||||||
@ -31,22 +31,22 @@ $
|
|||||||
this is ok
|
this is ok
|
||||||
*/, "abc")
|
*/, "abc")
|
||||||
|
|
||||||
--- decorator-strings ---
|
--- annotation-strings ---
|
||||||
|
|
||||||
// @allow("@some/thing-there123")
|
// @allow("@some/thing-there123")
|
||||||
|
|
||||||
--- unknown-decorator ---
|
--- unknown-annotation ---
|
||||||
// Error: 2:5-2:13 invalid decorator name
|
// Error: 2:5-2:13 invalid annotation name
|
||||||
// Hint: 2:5-2:13 must be 'allow'
|
// Hint: 2:5-2:13 must be 'allow'
|
||||||
|
|
||||||
// @whatever()
|
// @whatever()
|
||||||
|
|
||||||
--- invalid-decorator-syntax ---
|
--- invalid-annotation-syntax ---
|
||||||
// Error: 2:11-2:12 the character '*' is not valid in a decorator
|
// Error: 2:11-2:12 the character '*' is not valid in an annotation
|
||||||
|
|
||||||
// @allow(*)
|
// @allow(*)
|
||||||
|
|
||||||
// Error: 2:11-2:12 the character '5' is not valid in a decorator
|
// Error: 2:11-2:12 the character '5' is not valid in an annotation
|
||||||
|
|
||||||
// @allow(5)
|
// @allow(5)
|
||||||
|
|
||||||
@ -63,12 +63,12 @@ this is ok
|
|||||||
|
|
||||||
// @allow("abc
|
// @allow("abc
|
||||||
|
|
||||||
// Error: 2:18-2:21 expected end of decorator
|
// Error: 2:18-2:21 expected end of annotation
|
||||||
|
|
||||||
// @allow("abc") abc
|
// @allow("abc") abc
|
||||||
|
|
||||||
// Error: 2:17-2:22 expected comma
|
// Error: 2:17-2:22 expected comma
|
||||||
// Error: 2:24-2:27 expected end of decorator
|
// Error: 2:24-2:27 expected end of annotation
|
||||||
|
|
||||||
// @allow("abc" "abc") abc
|
// @allow("abc" "abc") abc
|
||||||
|
|
||||||
@ -80,23 +80,23 @@ this is ok
|
|||||||
|
|
||||||
// @allow(, "abc", "abc", "abc")
|
// @allow(, "abc", "abc", "abc")
|
||||||
|
|
||||||
--- invalid-decorator-strings ---
|
--- invalid-annotation-strings ---
|
||||||
|
|
||||||
// Error: 2:11-2:16 invalid character ' ' in a decorator's string
|
// Error: 2:11-2:16 invalid character ' ' in an annotation's string
|
||||||
|
|
||||||
// @allow("a b")
|
// @allow("a b")
|
||||||
|
|
||||||
// Error: 2:11-2:19 invalid character '|' in a decorator's string
|
// Error: 2:11-2:19 invalid character '|' in an annotation's string
|
||||||
|
|
||||||
// @allow("aaaaa|")
|
// @allow("aaaaa|")
|
||||||
|
|
||||||
// TODO: Why does this print / instead of \?
|
// TODO: Why does this print / instead of \?
|
||||||
// Error: 2:11-2:19 invalid character '/' in a decorator's string
|
// Error: 2:11-2:19 invalid character '/' in an annotation's string
|
||||||
|
|
||||||
// @allow("aaaaa\")
|
// @allow("aaaaa\")
|
||||||
|
|
||||||
--- invalid-decorator-in-decorator ---
|
--- invalid-annotation-in-annotation ---
|
||||||
// Error: 2:18-2:34 cannot have multiple decorators per line
|
// Error: 2:18-2:34 cannot have multiple annotations per line
|
||||||
|
|
||||||
// @allow("aaa") // @allow("bbb")
|
// @allow("aaa") // @allow("bbb")
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user