Skip to content
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

Qute validation fails on {config:property} if property contains is a string #1029

Merged
merged 1 commit into from
Nov 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
public class ExpressionScanner extends AbstractScanner<TokenType, ScannerState> {

private static final int[] QUOTE_OR_PAREN = new int[] { '(', ')', '"', '\'', };
private static final int[] SPACE_PERIOD_LBRACKET = new int[] {' ', '.', '['};
private static final int[] SPACE_PERIOD_LBRACKET_LPAREN_COLON = new int[] {' ', '.', '[', '(', ':'};
private static final int[] SPACE_PERIOD_LBRACKET = new int[] { ' ', '.', '[' };
private static final int[] SPACE_PERIOD_LBRACKET_LPAREN_COLON = new int[] { ' ', '.', '[', '(', ':' };

public static ExpressionScanner createScanner(String input, boolean canSupportInfixNotation) {
return createScanner(input, canSupportInfixNotation, 0, input.length());
Expand Down Expand Up @@ -62,97 +62,105 @@ protected TokenType internalScan() {
String errorMessage = null;
switch (state) {

case WithinExpression: {
if (stream.skipWhitespace()) {
return finishToken(offset, TokenType.Whitespace);
}
if (!canSupportInfixNotation) {
if (stream.advanceIfChar('"') || stream.advanceIfChar('\'')) {
state = ScannerState.WithinString;
return finishToken(stream.pos() - 1, TokenType.StartString);
case WithinExpression: {
if (stream.skipWhitespace()) {
return finishToken(offset, TokenType.Whitespace);
}
if (!canSupportInfixNotation) {
if (stream.advanceIfChar('"') || stream.advanceIfChar('\'')) {
state = ScannerState.WithinString;
return finishToken(stream.pos() - 1, TokenType.StartString);
}
}
nextJavaIdentifierPart();
return finishTokenPart(offset);
}
nextJavaIdentifierPart();
return finishTokenPart(offset);
}

case WithinParts:
case AfterNamespace: {
if (stream.skipWhitespace()) {
nbParts++;
return finishToken(offset, TokenType.Whitespace);
}
if (!canSupportInfixNotation) {
if (stream.advanceIfChar('"') || stream.advanceIfChar('\'')) {
state = ScannerState.WithinString;
return finishToken(stream.pos() - 1, TokenType.StartString);
case WithinParts:
case AfterNamespace: {
if (stream.skipWhitespace()) {
nbParts++;
return finishToken(offset, TokenType.Whitespace);
}
}
if (stream.advanceIfChar('.')) {
// item.|
return finishToken(offset, TokenType.Dot);
}
if (stream.advanceIfChar('[')) {
// item[|
if (stream.advanceUntilChar(']')) {
stream.advance(1);
// item['name']|
if (!canSupportInfixNotation) {
if (stream.advanceIfChar('"') || stream.advanceIfChar('\'')) {
state = ScannerState.WithinString;
return finishToken(stream.pos() - 1, TokenType.StartString);
}
}
return finishToken(offset, TokenType.PropertyPart);
}
if (stream.advanceIfChar(':')) {
// data:|
return finishToken(offset, TokenType.ColonSpace);
if (state == ScannerState.AfterNamespace) {
if (stream.peekChar() == '"' || stream.peekChar() == '\'') {
// config:"
stream.advance(1);
state = ScannerState.WithinString;
return finishToken(stream.pos() - 1, TokenType.StartString);
}
}
if (stream.advanceIfChar('.')) {
// item.|
return finishToken(offset, TokenType.Dot);
}
if (stream.advanceIfChar('[')) {
// item[|
if (stream.advanceUntilChar(']')) {
stream.advance(1);
// item['name']|
}
return finishToken(offset, TokenType.PropertyPart);
}
if (stream.advanceIfChar(':')) {
// data:|
return finishToken(offset, TokenType.ColonSpace);
}
nextJavaIdentifierPart();
// item.name|
return finishTokenPart(offset);
}
nextJavaIdentifierPart();
// item.name|
return finishTokenPart(offset);
}

case WithinMethod: {
if (stream.advanceIfChar('(')) {
bracket++;
return finishToken(offset, TokenType.OpenBracket);
}
stream.advanceUntilChar(QUOTE_OR_PAREN);
if (stream.peekChar() == '(') {
stream.advance(1);
bracket++;
return internalScan();
}
if (stream.peekChar() == '"' || stream.peekChar() == '\'') {
stream.advance(1);
state = ScannerState.WithinString;
inMethod = true;
return finishToken(stream.pos() - 1, TokenType.StartString);
} else if (stream.peekChar() == ')') {
stream.advance(1);
bracket--;
if (bracket > 0) {
case WithinMethod: {
if (stream.advanceIfChar('(')) {
bracket++;
return finishToken(offset, TokenType.OpenBracket);
}
stream.advanceUntilChar(QUOTE_OR_PAREN);
if (stream.peekChar() == '(') {
stream.advance(1);
bracket++;
return internalScan();
}
state = ScannerState.WithinParts;
inMethod = false;
return finishToken(stream.pos() - 1, TokenType.CloseBracket);
if (stream.peekChar() == '"' || stream.peekChar() == '\'') {
stream.advance(1);
state = ScannerState.WithinString;
inMethod = true;
return finishToken(stream.pos() - 1, TokenType.StartString);
} else if (stream.peekChar() == ')') {
stream.advance(1);
bracket--;
if (bracket > 0) {
return internalScan();
}
state = ScannerState.WithinParts;
inMethod = false;
return finishToken(stream.pos() - 1, TokenType.CloseBracket);
}
return internalScan();
}
return internalScan();
}

case WithinString: {
if (stream.advanceIfAnyOfChars(QUOTE_C)) {
if (inMethod) {
state = ScannerState.WithinMethod;
} else {
state = ScannerState.WithinExpression;
case WithinString: {
if (stream.advanceIfAnyOfChars(QUOTE_C)) {
if (inMethod) {
state = ScannerState.WithinMethod;
} else {
state = ScannerState.WithinExpression;
}
return finishToken(offset, TokenType.EndString);
}
return finishToken(offset, TokenType.EndString);
stream.advanceUntilChar(QUOTE);
return finishToken(offset, TokenType.String);
}
stream.advanceUntilChar(QUOTE);
return finishToken(offset, TokenType.String);
}

default:
inMethod = false;
default:
inMethod = false;
}
stream.advance(1);
return finishToken(offset, TokenType.Unknown, errorMessage);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public void testObjectAndMethodPartWithParameters() {
assertOffsetAndToken(25, TokenType.CloseBracket, ")");
assertOffsetAndToken(26, TokenType.EOS, "");
}

@Test
public void testNamespaceStartWithObject() {
scanner = createInfixNotationScanner("data:foo");
Expand Down Expand Up @@ -127,6 +127,17 @@ public void testNamespaceWithMethodAndProperty() {
assertOffsetAndToken(18, TokenType.EOS, "");
}

@Test
public void configNamespaceWithString() {
scanner = createInfixNotationScanner("config:\"quarkus.application.name\"");
assertOffsetAndToken(0, TokenType.NamespacePart, "config");
assertOffsetAndToken(6, TokenType.ColonSpace, ":");
assertOffsetAndToken(7, TokenType.StartString, "\"");
assertOffsetAndToken(8, TokenType.String, "quarkus.application.name");
assertOffsetAndToken(32, TokenType.EndString, "\"");
assertOffsetAndToken(33, TokenType.EOS, "");
}

/**
* @see https://quarkus.io/guides/qute-reference#built-in-resolvers
*/
Expand Down Expand Up @@ -155,7 +166,7 @@ public void underscore() {
}

// Infix notation tests

@Test
public void testTwoPartsWithInfixNotation() {
scanner = createInfixNotationScanner("a b");
Expand All @@ -173,7 +184,7 @@ public void testTwoPartsWithoutInfixNotation() {
assertOffsetAndToken(2, TokenType.ObjectPart, "b"); // No infix notation -> object part
assertOffsetAndToken(3, TokenType.EOS, "");
}

@Test
public void testThreePartsWithInfixNotation() {
scanner = createInfixNotationScanner("a b c");
Expand All @@ -184,7 +195,7 @@ public void testThreePartsWithInfixNotation() {
assertOffsetAndToken(4, TokenType.InfixParameter, "c");
assertOffsetAndToken(5, TokenType.EOS, "");
}

@Test
public void testSeveralPartsWithInfixNotation() {
scanner = createInfixNotationScanner("a b c d e");
Expand All @@ -199,7 +210,7 @@ public void testSeveralPartsWithInfixNotation() {
assertOffsetAndToken(8, TokenType.InfixParameter, "e");
assertOffsetAndToken(9, TokenType.EOS, "");
}

@Test
public void testThreePartsWithoutInfixNotation() {
scanner = createNoInfixNotationScanner("a b c");
Expand All @@ -210,7 +221,7 @@ public void testThreePartsWithoutInfixNotation() {
assertOffsetAndToken(4, TokenType.ObjectPart, "c");
assertOffsetAndToken(5, TokenType.EOS, "");
}

@Test
public void testOrInfixNotation() {
scanner = createInfixNotationScanner("person.name or 'John'");
Expand All @@ -223,7 +234,7 @@ public void testOrInfixNotation() {
assertOffsetAndToken(15, TokenType.InfixParameter, "'John'");
assertOffsetAndToken(21, TokenType.EOS, "");
}

@Test
public void testCharAtInfixNotation() {
scanner = createInfixNotationScanner("foo charAt '1'");
Expand All @@ -234,7 +245,7 @@ public void testCharAtInfixNotation() {
assertOffsetAndToken(11, TokenType.InfixParameter, "'1'");
assertOffsetAndToken(14, TokenType.EOS, "");
}

@Test
public void testCharAtNoInfixNotation() {
scanner = createNoInfixNotationScanner("foo charAt '1'");
Expand All @@ -247,7 +258,7 @@ public void testCharAtNoInfixNotation() {
assertOffsetAndToken(13, TokenType.EndString, "'");
assertOffsetAndToken(14, TokenType.EOS, "");
}

@Test
public void testMethodsAndInfixNotation() {
scanner = createInfixNotationScanner("items.get(0) or 1");
Expand All @@ -262,7 +273,7 @@ public void testMethodsAndInfixNotation() {
assertOffsetAndToken(16, TokenType.InfixParameter, "1");
assertOffsetAndToken(17, TokenType.EOS, "");
}

@Test
public void dotSpace() {
scanner = createInfixNotationScanner("items. ");
Expand All @@ -271,7 +282,7 @@ public void dotSpace() {
assertOffsetAndToken(6, TokenType.Whitespace, " ");
assertOffsetAndToken(7, TokenType.EOS, "");
}

@Test
public void twoMethodsWithOr() {
scanner = createInfixNotationScanner("item.name or item.name");
Expand All @@ -284,7 +295,7 @@ public void twoMethodsWithOr() {
assertOffsetAndToken(13, TokenType.InfixParameter, "item.name");
assertOffsetAndToken(22, TokenType.EOS, "");
}

@Test
public void infixNotationWithBracket() {
scanner = createInfixNotationScanner("foo getBytes()");
Expand All @@ -304,7 +315,7 @@ public void elvisOperator() {
assertOffsetAndToken(8, TokenType.InfixParameter, "\"Quarkus Insights\"");
assertOffsetAndToken(26, TokenType.EOS, "");
}

private void assertOffsetAndToken(int tokenOffset, TokenType tokenType, String tokenText) {
TokenType token = scanner.scan();
assertEquals(tokenOffset, scanner.getTokenOffset());
Expand All @@ -315,7 +326,7 @@ private void assertOffsetAndToken(int tokenOffset, TokenType tokenType, String t
private ExpressionScanner createInfixNotationScanner(String input) {
return ExpressionScanner.createScanner(input, true);
}

private ExpressionScanner createNoInfixNotationScanner(String input) {
return ExpressionScanner.createScanner(input, false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -690,4 +690,11 @@ public void escape() throws Exception {
String template = "function gtag()\\{dataLayer.push(arguments);\\}";
testDiagnosticsFor(template);
}

@Test
public void configNamepscaeWithString() throws Exception {
String template = "{config:\"quarkus.application.name\"}";
testDiagnosticsFor(template);
}

}
Loading