From b418be96cd69b6fd8341d8e5f83558f668620828 Mon Sep 17 00:00:00 2001 From: Eric Le Goff Date: Fri, 25 Jun 2021 14:50:48 +0200 Subject: [PATCH 1/3] The equal part of a constant item is optional --- rust-frontend/src/main/java/org/sonar/rust/RustGrammar.java | 2 +- rust-frontend/src/test/java/org/sonar/rust/RustLexerTest.java | 2 +- .../test/java/org/sonar/rust/parser/items/ConstantTest.java | 1 + .../src/test/java/org/sonar/rust/parser/items/TraitTest.java | 3 +++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/rust-frontend/src/main/java/org/sonar/rust/RustGrammar.java b/rust-frontend/src/main/java/org/sonar/rust/RustGrammar.java index 353f9496..467f83d0 100644 --- a/rust-frontend/src/main/java/org/sonar/rust/RustGrammar.java +++ b/rust-frontend/src/main/java/org/sonar/rust/RustGrammar.java @@ -690,7 +690,7 @@ private static void constantsItem(LexerlessGrammarBuilder b) { b.rule(CONSTANT_ITEM).is( RustKeyword.KW_CONST, SPC, b.firstOf(IDENTIFIER, RustPunctuator.UNDERSCORE),SPC, RustPunctuator.COLON, SPC, TYPE, - SPC, RustPunctuator.EQ, SPC, EXPRESSION, RustPunctuator.SEMI + SPC, b.optional(RustPunctuator.EQ, SPC, EXPRESSION), RustPunctuator.SEMI ); } diff --git a/rust-frontend/src/test/java/org/sonar/rust/RustLexerTest.java b/rust-frontend/src/test/java/org/sonar/rust/RustLexerTest.java index 5c145207..60bc6a27 100644 --- a/rust-frontend/src/test/java/org/sonar/rust/RustLexerTest.java +++ b/rust-frontend/src/test/java/org/sonar/rust/RustLexerTest.java @@ -69,7 +69,7 @@ public void testTokens() { public void testParsing() { - String sexpr = "let prior = false_prior;"; + String sexpr = "const MAX: i32;"; diff --git a/rust-frontend/src/test/java/org/sonar/rust/parser/items/ConstantTest.java b/rust-frontend/src/test/java/org/sonar/rust/parser/items/ConstantTest.java index a6ee9434..9b5954d6 100644 --- a/rust-frontend/src/test/java/org/sonar/rust/parser/items/ConstantTest.java +++ b/rust-frontend/src/test/java/org/sonar/rust/parser/items/ConstantTest.java @@ -34,6 +34,7 @@ public void testConstant() { .matches("const BITS: [u32; 2] = [BIT1, BIT2];") .matches("const STRING: &'static str = \"bitstring\";") .matches("const WHITE: Color = Color(255, 255, 255);") + .matches("const MAX: Self;") ; } diff --git a/rust-frontend/src/test/java/org/sonar/rust/parser/items/TraitTest.java b/rust-frontend/src/test/java/org/sonar/rust/parser/items/TraitTest.java index 1517012c..1d78a835 100644 --- a/rust-frontend/src/test/java/org/sonar/rust/parser/items/TraitTest.java +++ b/rust-frontend/src/test/java/org/sonar/rust/parser/items/TraitTest.java @@ -35,6 +35,9 @@ public void testTrait() { " fn elt_at(&self, n: u32) -> T;\n" + " fn iter(&self, f:F) where F: Fn(T);\n" + "}") + .matches("trait Thing {\n" + + " const FIELD : Self;\n" + + "}") ; From ba1f2fe45f818264a39d10a56a6871c777bec42c Mon Sep 17 00:00:00 2001 From: Eric Le Goff Date: Fri, 25 Jun 2021 17:34:25 +0200 Subject: [PATCH 2/3] fix when semi colon is preceded by space --- .../main/java/org/sonar/rust/RustGrammar.java | 22 +++++++++---------- .../main/java/org/sonar/rust/RustLexer.java | 2 +- .../rust/metrics/LinesOfCodeVisitor.java | 6 ++++- .../java/org/sonar/rust/RustLexerTest.java | 2 +- .../rust/parser/CompilationUnitTest.java | 3 +++ .../expressions/LoopExpressionTest.java | 4 ++++ .../rust/parser/statements/StatementTest.java | 1 + 7 files changed, 26 insertions(+), 14 deletions(-) diff --git a/rust-frontend/src/main/java/org/sonar/rust/RustGrammar.java b/rust-frontend/src/main/java/org/sonar/rust/RustGrammar.java index 467f83d0..ff457858 100644 --- a/rust-frontend/src/main/java/org/sonar/rust/RustGrammar.java +++ b/rust-frontend/src/main/java/org/sonar/rust/RustGrammar.java @@ -593,13 +593,13 @@ private static void aliasItem(LexerlessGrammarBuilder b) { RustKeyword.KW_TYPE, SPC, IDENTIFIER, SPC, b.optional(GENERIC_PARAMS), SPC, b.optional(WHERE_CLAUSE, SPC), b.optional(RustPunctuator.EQ, SPC, TYPE, SPC), - b.optional(RustPunctuator.COLON, b.optional(TYPE_PARAM_BOUNDS)), + b.optional(RustPunctuator.COLON, b.optional(SPC, TYPE_PARAM_BOUNDS,SPC)), RustPunctuator.SEMI ); } private static void useItem(LexerlessGrammarBuilder b) { - b.rule(USE_DECLARATION).is("use", SPC, USE_TREE, ";"); + b.rule(USE_DECLARATION).is(RustKeyword.KW_USE, SPC, USE_TREE,SPC, RustPunctuator.SEMI); b.rule(USE_TREE).is(b.firstOf( b.sequence(b.optional(b.optional(SIMPLE_PATH), RustPunctuator.PATHSEP), RustPunctuator.STAR), @@ -690,7 +690,7 @@ private static void constantsItem(LexerlessGrammarBuilder b) { b.rule(CONSTANT_ITEM).is( RustKeyword.KW_CONST, SPC, b.firstOf(IDENTIFIER, RustPunctuator.UNDERSCORE),SPC, RustPunctuator.COLON, SPC, TYPE, - SPC, b.optional(RustPunctuator.EQ, SPC, EXPRESSION), RustPunctuator.SEMI + SPC, b.optional(RustPunctuator.EQ, SPC, EXPRESSION,SPC), RustPunctuator.SEMI ); } @@ -700,7 +700,7 @@ private static void staticItem(LexerlessGrammarBuilder b) { b.rule(STATIC_ITEM).is( RustKeyword.KW_STATIC, SPC, b.optional(RustKeyword.KW_MUT, SPC), IDENTIFIER, SPC, RustPunctuator.COLON, SPC, TYPE, SPC, b.optional(RustPunctuator.EQ, SPC, - EXPRESSION), RustPunctuator.SEMI + EXPRESSION,SPC), RustPunctuator.SEMI ); } @@ -828,7 +828,7 @@ private static void visibilityItem(LexerlessGrammarBuilder b) { private static void externcrates(LexerlessGrammarBuilder b) { b.rule(EXTERN_CRATE).is( - RustKeyword.KW_EXTERN, SPC, RustKeyword.KW_CRATE, SPC, CRATE_REF, b.optional(SPC, AS_CLAUSE), RustPunctuator.SEMI + RustKeyword.KW_EXTERN, SPC, RustKeyword.KW_CRATE, SPC, CRATE_REF, SPC, b.optional(SPC, AS_CLAUSE,SPC), RustPunctuator.SEMI ); b.rule(CRATE_REF).is(b.firstOf(RustKeyword.KW_SELFVALUE, IDENTIFIER)); b.rule(AS_CLAUSE).is(RustKeyword.KW_AS, SPC, b.firstOf(RustPunctuator.UNDERSCORE, IDENTIFIER)); @@ -886,8 +886,8 @@ private static void macrosByExample(LexerlessGrammarBuilder b) { "macro_rules!", SPC, IDENTIFIER, SPC, MACRO_RULES_DEF ); b.rule(MACRO_RULES_DEF).is(b.firstOf( - b.sequence("(", SPC, MACRO_RULES, SPC, ")", RustPunctuator.SEMI), - b.sequence("[", SPC, MACRO_RULES, SPC, "]", RustPunctuator.SEMI), + b.sequence("(", SPC, MACRO_RULES, SPC, ")", SPC, RustPunctuator.SEMI), + b.sequence("[", SPC, MACRO_RULES, SPC, "]", SPC, RustPunctuator.SEMI), b.sequence("{", SPC, MACRO_RULES, SPC, "}") )); b.rule(MACRO_RULES).is( @@ -1142,7 +1142,7 @@ public static void statement(LexerlessGrammarBuilder b) { b.rule(STATEMENT).is(b.firstOf( RustPunctuator.SEMI, b.sequence(EXPRESSION_WITHOUT_BLOCK, SPC, RustPunctuator.SEMI), - b.sequence(EXPRESSION_WITH_BLOCK, b.optional(SPC, RustPunctuator.SEMI)), + b.sequence(EXPRESSION_WITH_BLOCK, SPC, b.optional(SPC, RustPunctuator.SEMI)), ITEM, LET_STATEMENT, MACRO_INVOCATION_SEMI @@ -1632,7 +1632,7 @@ private static void array(LexerlessGrammarBuilder b) { "]"); b.rule(ARRAY_ELEMENTS).is(b.firstOf( - b.sequence(SPC, EXPRESSION, RustPunctuator.SEMI, SPC, EXPRESSION), + b.sequence(SPC, EXPRESSION, SPC, RustPunctuator.SEMI, SPC, EXPRESSION), b.sequence(SPC, EXPRESSION, SPC, b.zeroOrMore(RustPunctuator.COMMA, SPC, EXPRESSION), b.optional(RustPunctuator.COMMA, SPC)) )); @@ -1785,7 +1785,7 @@ private static void block(LexerlessGrammarBuilder b) { b.firstOf( b.sequence(RustPunctuator.SEMI, SPC), b.sequence(EXPRESSION_WITHOUT_BLOCK, SPC, RustPunctuator.SEMI, SPC), - b.sequence(EXPRESSION_WITH_BLOCK, b.nextNot(SPC, RustPunctuator.DOT), b.optional(RustPunctuator.SEMI), SPC), + b.sequence(EXPRESSION_WITH_BLOCK, b.nextNot(SPC, RustPunctuator.DOT), b.optional(SPC, RustPunctuator.SEMI), SPC), b.sequence(ITEM, SPC), b.sequence(LET_STATEMENT, SPC), b.sequence(MACRO_INVOCATION_SEMI, SPC) @@ -1801,7 +1801,7 @@ private static void block(LexerlessGrammarBuilder b) { b.firstOf( b.sequence(RustPunctuator.SEMI, SPC), b.sequence(EXPRESSION_WITHOUT_BLOCK, SPC, RustPunctuator.SEMI, SPC), - b.sequence(EXPRESSION_WITH_BLOCK, b.nextNot(SPC, RustPunctuator.DOT), b.optional(RustPunctuator.SEMI), SPC), + b.sequence(EXPRESSION_WITH_BLOCK, b.nextNot(SPC, RustPunctuator.DOT), b.optional(SPC, RustPunctuator.SEMI), SPC), b.sequence(ITEM, SPC), b.sequence(LET_STATEMENT, SPC), b.sequence(MACRO_INVOCATION_SEMI, SPC) diff --git a/rust-frontend/src/main/java/org/sonar/rust/RustLexer.java b/rust-frontend/src/main/java/org/sonar/rust/RustLexer.java index a5c45d78..a36071ea 100644 --- a/rust-frontend/src/main/java/org/sonar/rust/RustLexer.java +++ b/rust-frontend/src/main/java/org/sonar/rust/RustLexer.java @@ -32,7 +32,7 @@ public enum RustLexer implements GrammarRuleKey { public static LexerlessGrammarBuilder create() { LexerlessGrammarBuilder b =RustGrammar.create(); - b.rule(TOKENS).is(RustGrammar.SPC, b.zeroOrMore(RustGrammar.ANY_TOKEN,b.optional(RustPunctuator.SEMI),RustGrammar.SPC), RustGrammar.EOF); + b.rule(TOKENS).is(RustGrammar.SPC, b.zeroOrMore(RustGrammar.ANY_TOKEN,b.optional(RustGrammar.SPC, RustPunctuator.SEMI),RustGrammar.SPC), RustGrammar.EOF); b.setRootRule(TOKENS); diff --git a/rust-frontend/src/main/java/org/sonar/rust/metrics/LinesOfCodeVisitor.java b/rust-frontend/src/main/java/org/sonar/rust/metrics/LinesOfCodeVisitor.java index 412d77dc..04272928 100644 --- a/rust-frontend/src/main/java/org/sonar/rust/metrics/LinesOfCodeVisitor.java +++ b/rust-frontend/src/main/java/org/sonar/rust/metrics/LinesOfCodeVisitor.java @@ -27,6 +27,7 @@ import org.sonar.sslr.parser.ParserAdapter; import java.util.HashSet; +import java.util.List; import java.util.Set; public class LinesOfCodeVisitor extends RustVisitor { @@ -41,7 +42,10 @@ public LinesOfCodeVisitor(ParserAdapter parser) { @Override public void visitFile(AstNode node) { linesOfCode.clear(); - for (AstNode token : lexer.parse(getContext().file().content()).getChildren(RustGrammar.ANY_TOKEN)) { + List tokens = lexer.parse(getContext().file().content()).getChildren(RustGrammar.ANY_TOKEN); + + + for (AstNode token : tokens) { String[] tokenLines = token.getTokenValue().split("(\r)?\n|\r", -1); for (int lineOffset = 0; lineOffset < tokenLines.length; lineOffset++) { diff --git a/rust-frontend/src/test/java/org/sonar/rust/RustLexerTest.java b/rust-frontend/src/test/java/org/sonar/rust/RustLexerTest.java index 60bc6a27..3c99d24f 100644 --- a/rust-frontend/src/test/java/org/sonar/rust/RustLexerTest.java +++ b/rust-frontend/src/test/java/org/sonar/rust/RustLexerTest.java @@ -69,7 +69,7 @@ public void testTokens() { public void testParsing() { - String sexpr = "const MAX: i32;"; + String sexpr = "test() ;"; diff --git a/rust-frontend/src/test/java/org/sonar/rust/parser/CompilationUnitTest.java b/rust-frontend/src/test/java/org/sonar/rust/parser/CompilationUnitTest.java index 384f651b..00e792c1 100644 --- a/rust-frontend/src/test/java/org/sonar/rust/parser/CompilationUnitTest.java +++ b/rust-frontend/src/test/java/org/sonar/rust/parser/CompilationUnitTest.java @@ -35,6 +35,7 @@ public void testAnyTokens() { .notMatches("use") .matches("foo") .matches("fnac") + .matches("test") ; } @@ -65,6 +66,8 @@ public void testCompilationUnit() { "}") .matches("mod foobar{#![crate_type = \"lib\"]\n" + "}") + .matches("test();") + .matches("test() ;") ; } } diff --git a/rust-frontend/src/test/java/org/sonar/rust/parser/expressions/LoopExpressionTest.java b/rust-frontend/src/test/java/org/sonar/rust/parser/expressions/LoopExpressionTest.java index d1f1e528..443b2c27 100644 --- a/rust-frontend/src/test/java/org/sonar/rust/parser/expressions/LoopExpressionTest.java +++ b/rust-frontend/src/test/java/org/sonar/rust/parser/expressions/LoopExpressionTest.java @@ -74,6 +74,10 @@ public void testLoopExpression() { " println!(\"hello\");\n" + " i = i + 1;\n" + "}") + .matches("for (i, n) in hist.normalized_bins().enumerate() {\n" + + " let bin = (n as f64) / (N_SAMPLES as f64) ;\n" + + " diff[i] = (bin - expected[i]).abs();\n" + + " }") ; } } diff --git a/rust-frontend/src/test/java/org/sonar/rust/parser/statements/StatementTest.java b/rust-frontend/src/test/java/org/sonar/rust/parser/statements/StatementTest.java index 61032b36..b85aefb2 100644 --- a/rust-frontend/src/test/java/org/sonar/rust/parser/statements/StatementTest.java +++ b/rust-frontend/src/test/java/org/sonar/rust/parser/statements/StatementTest.java @@ -168,6 +168,7 @@ public void testStatements() { .matches("unsafe {}\n" + "assert_eq!(state.borrow::().value, 110);") .matches("mystruct{};") + .matches("test() ;") From 8c7c6c02875afe7762e5aa9b44dc55907dd70110 Mon Sep 17 00:00:00 2001 From: Eric Le Goff Date: Sat, 26 Jun 2021 15:51:36 +0200 Subject: [PATCH 3/3] Add forgotten path expressions to expressions --- .../main/java/org/sonar/rust/RustGrammar.java | 45 ++++++++++--------- .../java/org/sonar/rust/RustLexerTest.java | 2 +- .../expressions/CallExpressionTest.java | 1 + .../parser/expressions/ExpressionTest.java | 2 + .../expressions/PathExpressionTest.java | 1 + .../org/sonar/rust/parser/lexer/PathTest.java | 35 +++++++++++---- .../rust/parser/statements/StatementTest.java | 2 + .../org/sonar/rust/parser/types/TypeTest.java | 1 + 8 files changed, 59 insertions(+), 30 deletions(-) diff --git a/rust-frontend/src/main/java/org/sonar/rust/RustGrammar.java b/rust-frontend/src/main/java/org/sonar/rust/RustGrammar.java index ff457858..eb570ec7 100644 --- a/rust-frontend/src/main/java/org/sonar/rust/RustGrammar.java +++ b/rust-frontend/src/main/java/org/sonar/rust/RustGrammar.java @@ -2,17 +2,17 @@ * Sonar Rust Plugin (Community) * Copyright (C) 2021 Eric Le Goff * http://github.com/elegoff/sonar-rust - * + *

* This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. - * + *

* This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + *

* You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -593,13 +593,13 @@ private static void aliasItem(LexerlessGrammarBuilder b) { RustKeyword.KW_TYPE, SPC, IDENTIFIER, SPC, b.optional(GENERIC_PARAMS), SPC, b.optional(WHERE_CLAUSE, SPC), b.optional(RustPunctuator.EQ, SPC, TYPE, SPC), - b.optional(RustPunctuator.COLON, b.optional(SPC, TYPE_PARAM_BOUNDS,SPC)), + b.optional(RustPunctuator.COLON, b.optional(SPC, TYPE_PARAM_BOUNDS, SPC)), RustPunctuator.SEMI ); } private static void useItem(LexerlessGrammarBuilder b) { - b.rule(USE_DECLARATION).is(RustKeyword.KW_USE, SPC, USE_TREE,SPC, RustPunctuator.SEMI); + b.rule(USE_DECLARATION).is(RustKeyword.KW_USE, SPC, USE_TREE, SPC, RustPunctuator.SEMI); b.rule(USE_TREE).is(b.firstOf( b.sequence(b.optional(b.optional(SIMPLE_PATH), RustPunctuator.PATHSEP), RustPunctuator.STAR), @@ -688,9 +688,9 @@ private static void unionsItem(LexerlessGrammarBuilder b) { /* https://doc.rust-lang.org/reference/items/constant-items.html */ private static void constantsItem(LexerlessGrammarBuilder b) { b.rule(CONSTANT_ITEM).is( - RustKeyword.KW_CONST, SPC, b.firstOf(IDENTIFIER, RustPunctuator.UNDERSCORE),SPC, + RustKeyword.KW_CONST, SPC, b.firstOf(IDENTIFIER, RustPunctuator.UNDERSCORE), SPC, RustPunctuator.COLON, SPC, TYPE, - SPC, b.optional(RustPunctuator.EQ, SPC, EXPRESSION,SPC), RustPunctuator.SEMI + SPC, b.optional(RustPunctuator.EQ, SPC, EXPRESSION, SPC), RustPunctuator.SEMI ); } @@ -700,7 +700,7 @@ private static void staticItem(LexerlessGrammarBuilder b) { b.rule(STATIC_ITEM).is( RustKeyword.KW_STATIC, SPC, b.optional(RustKeyword.KW_MUT, SPC), IDENTIFIER, SPC, RustPunctuator.COLON, SPC, TYPE, SPC, b.optional(RustPunctuator.EQ, SPC, - EXPRESSION,SPC), RustPunctuator.SEMI + EXPRESSION, SPC), RustPunctuator.SEMI ); } @@ -828,7 +828,7 @@ private static void visibilityItem(LexerlessGrammarBuilder b) { private static void externcrates(LexerlessGrammarBuilder b) { b.rule(EXTERN_CRATE).is( - RustKeyword.KW_EXTERN, SPC, RustKeyword.KW_CRATE, SPC, CRATE_REF, SPC, b.optional(SPC, AS_CLAUSE,SPC), RustPunctuator.SEMI + RustKeyword.KW_EXTERN, SPC, RustKeyword.KW_CRATE, SPC, CRATE_REF, SPC, b.optional(SPC, AS_CLAUSE, SPC), RustPunctuator.SEMI ); b.rule(CRATE_REF).is(b.firstOf(RustKeyword.KW_SELFVALUE, IDENTIFIER)); b.rule(AS_CLAUSE).is(RustKeyword.KW_AS, SPC, b.firstOf(RustPunctuator.UNDERSCORE, IDENTIFIER)); @@ -962,7 +962,7 @@ private static void macrosByExample(LexerlessGrammarBuilder b) { RustPunctuator.FATARROW, RustPunctuator.POUND, RustPunctuator.DOLLAR - )); // Token except delimiters and repetition operators + )); // Token except delimiters and repetition operators b.rule(MACRO_REP_OP).is(b.firstOf(RustPunctuator.STAR, RustPunctuator.PLUS, RustPunctuator.QUESTION)); b.rule(MACRO_TRANSCRIBER).is(DELIM_TOKEN_TREE); @@ -978,7 +978,6 @@ private static void patterns(LexerlessGrammarBuilder b) { MACRO_INVOCATION, - //unambigous PATH_PATTERN, b.firstOf( b.sequence(b.optional(RustPunctuator.PATHSEP), @@ -1000,7 +999,7 @@ private static void patterns(LexerlessGrammarBuilder b) { STRING_LITERAL, - b.sequence(b.optional("-"), INTEGER_LITERAL, b.nextNot(RustPunctuator.DOTDOT)), + b.sequence(b.optional("-"), INTEGER_LITERAL, b.nextNot(RustPunctuator.DOTDOT)), b.sequence(b.optional("-"), FLOAT_LITERAL), WILDCARD_PATTERN, @@ -1116,7 +1115,7 @@ private static void types(LexerlessGrammarBuilder b) { private static void functionpointer(LexerlessGrammarBuilder b) { b.rule(BARE_FUNCTION_TYPE).is( b.optional(FOR_LIFETIMES), FUNCTION_QUALIFIERS, SPC, RustKeyword.KW_FN, - "(", SPC, b.optional(FUNCTION_PARAMETERS_MAYBE_NAMED_VARIADIC),SPC, ")",SPC, + "(", SPC, b.optional(FUNCTION_PARAMETERS_MAYBE_NAMED_VARIADIC), SPC, ")", SPC, b.optional(BARE_FUNCTION_RETURN_TYPE) ); b.rule(BARE_FUNCTION_RETURN_TYPE).is(RustPunctuator.RARROW, SPC, TYPE_NO_BOUNDS); @@ -1197,6 +1196,7 @@ public static void expressions(LexerlessGrammarBuilder b) { b.firstOf( b.sequence(LITERAL_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM)), b.sequence(BREAK_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM)), + b.sequence(BOX_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM)), b.sequence(RustPunctuator.DOTDOT, b.next(b.firstOf(")", "]", "}"))), b.sequence(RANGE_TO_INCLUSIVE_EXPR, b.zeroOrMore(SPC, EXPRESSION_TERM)), @@ -1217,6 +1217,7 @@ public static void expressions(LexerlessGrammarBuilder b) { b.sequence(MACRO_INVOCATION, b.zeroOrMore(SPC, EXPRESSION_TERM)), b.sequence(RETURN_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM)), b.sequence(STRUCT_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM)), + b.sequence(PATH_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM)), b.sequence(GROUPED_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM)), b.sequence(ARRAY_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM)), b.sequence(TUPLE_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM)), @@ -1252,7 +1253,7 @@ public static void expressions(LexerlessGrammarBuilder b) { b.sequence(RETURN_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM_EXCEPT_STRUCT)), b.sequence(PATH_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM_EXCEPT_STRUCT)), b.sequence(STRUCT_EXPRESSION, b.oneOrMore(SPC, EXPRESSION_TERM_EXCEPT_STRUCT)), //NB : one or more - + b.sequence(PATH_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM_EXCEPT_STRUCT)), b.sequence(GROUPED_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM_EXCEPT_STRUCT)), b.sequence(ARRAY_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM_EXCEPT_STRUCT)), b.sequence(TUPLE_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM_EXCEPT_STRUCT)), @@ -1917,10 +1918,9 @@ public static void closure(LexerlessGrammarBuilder b) { /* https://doc.rust-lang.org/reference/types.html#type-expressions */ public static void type(LexerlessGrammarBuilder b) { b.rule(TYPE).is(b.firstOf( - IMPL_TRAIT_TYPE - ,BARE_FUNCTION_TYPE - ,TRAIT_OBJECT_TYPE, - + IMPL_TRAIT_TYPE, + BARE_FUNCTION_TYPE, + TRAIT_OBJECT_TYPE, PARENTHESIZED_TYPE, IMPL_TRAIT_TYPE_ONE_BOUND, TRAIT_OBJECT_TYPE_ONE_BOUND, @@ -1933,11 +1933,9 @@ public static void type(LexerlessGrammarBuilder b) { SLICE_TYPE, INFERRED_TYPE, QUALIFIED_PATH_IN_TYPE, - MACRO_INVOCATION - )); b.rule(TYPE_NO_BOUNDS).is(b.firstOf( BARE_FUNCTION_TYPE, @@ -2024,8 +2022,13 @@ public static void lexicalpath(LexerlessGrammarBuilder b) { b.rule(PATH_EXPR_SEGMENT).is( PATH_IDENT_SEGMENT, b.optional(b.sequence(RustPunctuator.PATHSEP, GENERIC_ARGS)) ); + b.rule(PATH_IDENT_SEGMENT).is(b.firstOf( - RustKeyword.KW_SUPER, b.regexp("^[sS]elf$"), RustKeyword.KW_CRATE, b.regexp(DOLLAR_CRATE_REGEX), IDENTIFIER + RustKeyword.KW_SUPER, + b.regexp("^[sS]elf$"), + RustKeyword.KW_CRATE, + b.regexp(DOLLAR_CRATE_REGEX), + IDENTIFIER )); b.rule(GENERIC_ARGS).is(b.firstOf( diff --git a/rust-frontend/src/test/java/org/sonar/rust/RustLexerTest.java b/rust-frontend/src/test/java/org/sonar/rust/RustLexerTest.java index 3c99d24f..0fe02e13 100644 --- a/rust-frontend/src/test/java/org/sonar/rust/RustLexerTest.java +++ b/rust-frontend/src/test/java/org/sonar/rust/RustLexerTest.java @@ -69,7 +69,7 @@ public void testTokens() { public void testParsing() { - String sexpr = "test() ;"; + String sexpr = "let zero = 0;"; diff --git a/rust-frontend/src/test/java/org/sonar/rust/parser/expressions/CallExpressionTest.java b/rust-frontend/src/test/java/org/sonar/rust/parser/expressions/CallExpressionTest.java index 75cc97fe..0a99a496 100644 --- a/rust-frontend/src/test/java/org/sonar/rust/parser/expressions/CallExpressionTest.java +++ b/rust-frontend/src/test/java/org/sonar/rust/parser/expressions/CallExpressionTest.java @@ -82,6 +82,7 @@ public void testCallExpression() { .matches("Ok(2)") .matches("Ok(())") .matches("f(stdout[..40])") + .matches("::default()") ; } diff --git a/rust-frontend/src/test/java/org/sonar/rust/parser/expressions/ExpressionTest.java b/rust-frontend/src/test/java/org/sonar/rust/parser/expressions/ExpressionTest.java index c06b1dca..ebd511d5 100644 --- a/rust-frontend/src/test/java/org/sonar/rust/parser/expressions/ExpressionTest.java +++ b/rust-frontend/src/test/java/org/sonar/rust/parser/expressions/ExpressionTest.java @@ -58,6 +58,7 @@ public void testExpression() { .matches("3+2") .matches("1 << 1") .matches("foo") + .matches("u8") .matches("Some(42)") .matches("panic!()") .notMatches("== b") @@ -113,6 +114,7 @@ public void testExpression() { .matches("break 42") .matches("break Ok(Poll::Pending)") .matches("true_prior") + .matches("::default()") ; } diff --git a/rust-frontend/src/test/java/org/sonar/rust/parser/expressions/PathExpressionTest.java b/rust-frontend/src/test/java/org/sonar/rust/parser/expressions/PathExpressionTest.java index bdc7b526..6d551c82 100644 --- a/rust-frontend/src/test/java/org/sonar/rust/parser/expressions/PathExpressionTest.java +++ b/rust-frontend/src/test/java/org/sonar/rust/parser/expressions/PathExpressionTest.java @@ -37,6 +37,7 @@ public void testPathExpression() { .matches("Identifier::Numeric") .matches("Vec::new") .matches("StepPosition::JumpEnd") + .matches("::default") ; } diff --git a/rust-frontend/src/test/java/org/sonar/rust/parser/lexer/PathTest.java b/rust-frontend/src/test/java/org/sonar/rust/parser/lexer/PathTest.java index d9188bac..a0044bb8 100644 --- a/rust-frontend/src/test/java/org/sonar/rust/parser/lexer/PathTest.java +++ b/rust-frontend/src/test/java/org/sonar/rust/parser/lexer/PathTest.java @@ -2,17 +2,17 @@ * Sonar Rust Plugin (Community) * Copyright (C) 2021 Eric Le Goff * http://github.com/elegoff/sonar-rust - * + *

* This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. - * + *

* This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + *

* You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -49,6 +49,17 @@ public void testSimplePath() { ; } + @Test + public void testPathExprSegment() { + assertThat(RustGrammar.create().build().rule(RustGrammar.PATH_EXPR_SEGMENT)) + .matches("f") + .matches("f::<>") + .matches("f::") + + + ; + } + @Test public void testPathInExpression() { assertThat(RustGrammar.create().build().rule(RustGrammar.PATH_IN_EXPRESSION)) @@ -61,11 +72,11 @@ public void testPathInExpression() { .notMatches("match") .matches("Token::BackQuote") + ; } - @Test public void testGenericArgsBinding() { assertThat(RustGrammar.create().build().rule(RustGrammar.GENERIC_ARGS_BINDING)) @@ -75,8 +86,6 @@ public void testGenericArgsBinding() { } - - @Test public void testGenericArgs() { assertThat(RustGrammar.create().build().rule(RustGrammar.GENERIC_ARGS)) @@ -98,8 +107,6 @@ public void testGenericArgs() { .matches(">)>>>") - - ; } @@ -108,6 +115,7 @@ public void testQualifiedPathType() { assertThat(RustGrammar.create().build().rule(RustGrammar.QUALIFIED_PATH_TYPE)) .matches("") .matches("") + .matches("") ; } @@ -116,6 +124,17 @@ public void testQualifiedPathType() { public void testQualifiedPathInExpression() { assertThat(RustGrammar.create().build().rule(RustGrammar.QUALIFIED_PATH_IN_EXPRESSION)) .matches("::f") + .matches("::default") + + + ; + } + + @Test + public void testQualifiedPathInType() { + assertThat(RustGrammar.create().build().rule(RustGrammar.QUALIFIED_PATH_IN_TYPE)) + .matches("::f") + .matches("::default()") ; diff --git a/rust-frontend/src/test/java/org/sonar/rust/parser/statements/StatementTest.java b/rust-frontend/src/test/java/org/sonar/rust/parser/statements/StatementTest.java index b85aefb2..a0180e84 100644 --- a/rust-frontend/src/test/java/org/sonar/rust/parser/statements/StatementTest.java +++ b/rust-frontend/src/test/java/org/sonar/rust/parser/statements/StatementTest.java @@ -59,6 +59,8 @@ public void testLetStatement() { .matches("let ref ref5 = fut5.await;") .matches("let mut mut6 = fut6.await;") .matches("let ref mut refmut = fut.await;") + .matches("let x = i32;") + .matches("let zero = ::default();") ; diff --git a/rust-frontend/src/test/java/org/sonar/rust/parser/types/TypeTest.java b/rust-frontend/src/test/java/org/sonar/rust/parser/types/TypeTest.java index 9229a9ac..55be4096 100644 --- a/rust-frontend/src/test/java/org/sonar/rust/parser/types/TypeTest.java +++ b/rust-frontend/src/test/java/org/sonar/rust/parser/types/TypeTest.java @@ -181,6 +181,7 @@ public void testType() { " + 'static\n" + " + Send") .matches("impl FnOnce()") + .matches("::default()")