Skip to content

Commit

Permalink
{name. ?: "Qute"} doesn't report a validation error
Browse files Browse the repository at this point in the history
Fixes redhat-developer#884

Signed-off-by: azerr <azerr@redhat.com>
  • Loading branch information
angelozerr committed Jul 21, 2023
1 parent 85b64e3 commit 4a2b870
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@ public enum QuteSyntaxErrorCode implements IQuteErrorCode {
/**
* <code>{#if test}Hello {name}</code>
*/
UNTERMINATED_SECTION("Parser error: unterminated section [{0}] detected", ParserError.UNTERMINATED_SECTION);
UNTERMINATED_SECTION("Parser error: unterminated section [{0}] detected", ParserError.UNTERMINATED_SECTION),

UNEXPECTED_TOKEN("Syntax error: `Unexpected ''{0}'' token`.", null);

private static List<ErrorCode> supportedErrorCodes;

private final String rawMessage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,18 @@

import org.eclipse.lsp4j.Range;

import com.redhat.qute.parser.expression.MethodPart;
import com.redhat.qute.parser.expression.ObjectPart;
import com.redhat.qute.parser.expression.Part;
import com.redhat.qute.parser.expression.Parts.PartKind;
import com.redhat.qute.parser.expression.PropertyPart;
import com.redhat.qute.parser.template.ASTVisitor;
import com.redhat.qute.parser.template.Expression;
import com.redhat.qute.parser.template.Node;
import com.redhat.qute.parser.template.NodeKind;
import com.redhat.qute.parser.template.Parameter;
import com.redhat.qute.parser.template.Section;
import com.redhat.qute.parser.template.SectionKind;
import com.redhat.qute.parser.template.Template;
import com.redhat.qute.parser.template.sections.CaseSection;
import com.redhat.qute.parser.template.sections.CustomSection;
import com.redhat.qute.parser.template.sections.EachSection;
Expand Down Expand Up @@ -218,4 +227,62 @@ private void validateSectionSyntax(Section section) {
}
}

@Override
public boolean visit(ObjectPart node) {
validateEndWithDotSyntax(node);
return super.visit(node);
}

public boolean visit(PropertyPart node) {
validateEndWithDotSyntax(node);
return super.visit(node);
}

public boolean visit(MethodPart node) {
// Validate end dot syntax for parameters
for (Parameter parameter : node.getParameters()) {
Expression expression = parameter.getJavaTypeExpression();
if (expression != null) {
expression.accept(this);
}
}
validateEndWithDotSyntax(node);
return super.visit(node);
}

private void validateEndWithDotSyntax(Part node) {
if (!hasFollowingPart(node)) {
Template template = node.getOwnerTemplate();
// It's the last part, check if it is not ended with '.'
int end = node.getPartKind() == PartKind.Method ? node.getEnd() + 1 : node.getEnd();
String text = template.getText();
if (end < text.length()) {
char c = text.charAt(end);
if (c == '.') {
Range range = QutePositionUtility.createRange(end, end + 1, template);
reporter.reportError(range, node,
QuteSyntaxErrorCode.UNEXPECTED_TOKEN, c);
}
}
}
}

private boolean hasFollowingPart(Part node) {
Node next = node.getNextSibling();
if (next == null) {
// - {name.}
// - {name.size().}
return false;
}
if (next.getKind() == NodeKind.ExpressionPart) {
Part nextPart = (Part) next;
if (nextPart.getPartKind() == PartKind.Method) {
// - {name.or(10)} <-- valid
// - {name. ?: 10} <-- invaid: infix notation
MethodPart methodPart = (MethodPart) nextPart;
return !methodPart.isInfixNotation();
}
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -597,21 +597,6 @@ private ResolvedJavaTypeInfo validateExpressionParts(Parts parts, Section ownerS
for (int i = 0; i < parts.getChildCount(); i++) {
Part current = parts.getChild(i);

if (current.isLast()) {
// It's the last part, check if it is not ended with '.'
int end = current.getEnd();
String text = template.getText();
if (end < text.length()) {
char c = text.charAt(end);
if (c == '.') {
Range range = QutePositionUtility.createRange(end, end + 1, template);
Diagnostic diagnostic = createDiagnostic(range, DiagnosticSeverity.Error,
QuteErrorCode.SyntaxError, "Unexpected '.' token.");
diagnostics.add(diagnostic);
}
}
}

switch (current.getPartKind()) {

case Namespace: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -365,22 +365,6 @@ public void undefineNamespace() throws Exception {
d)));
}

@Test
public void objectPartEndsWithDot() {
String template = "{@java.util.List<org.acme.Item> items}\r\n" + //
"{items.}";
testDiagnosticsFor(template, d(1, 6, 1, 7, QuteErrorCode.SyntaxError, //
"Syntax error: `Unexpected '.' token.`.", DiagnosticSeverity.Error));
}

@Test
public void propertyPartEndsWithDot() {
String template = "{@java.util.List<org.acme.Item> items}\r\n" + //
"{items.size.}";
testDiagnosticsFor(template, d(1, 11, 1, 12, QuteErrorCode.SyntaxError, //
"Syntax error: `Unexpected '.' token.`.", DiagnosticSeverity.Error));
}

@Test
public void invalidMethodVoid() {
String template = "{@java.lang.String string}\r\n" + //
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*******************************************************************************
* Copyright (c) 2023 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.qute.services.diagnostics.syntax;

import static com.redhat.qute.QuteAssert.d;
import static com.redhat.qute.QuteAssert.testDiagnosticsFor;

import org.eclipse.lsp4j.DiagnosticSeverity;
import org.junit.jupiter.api.Test;

import com.redhat.qute.parser.validator.QuteSyntaxErrorCode;

/**
* Syntax error with end dot.
*
* @author Angelo ZERR
*
*/
public class QuteDiagnosticsEndDotSyntaxErrorTest {

@Test
public void objectPartEndsWithDot() {
String template = "{@java.util.List<org.acme.Item> items}\r\n" + //
"{items.}";
testDiagnosticsFor(template, d(1, 6, 1, 7, QuteSyntaxErrorCode.UNEXPECTED_TOKEN, //
"Syntax error: `Unexpected '.' token`.", DiagnosticSeverity.Error));
}

@Test
public void objectPartInInfixNotationEndsWithDot() {
String template = "{@java.lang.String name}\r\n" + //
"{name. ?: \"Qute\"}";
testDiagnosticsFor(template, d(1, 5, 1, 6, QuteSyntaxErrorCode.UNEXPECTED_TOKEN, //
"Syntax error: `Unexpected '.' token`.", DiagnosticSeverity.Error));
}

@Test
public void objectPartInInfixNotationEndsWithDot2() {
String template = "{@java.lang.String name}\r\n" + //
"{name ?: name.}";
testDiagnosticsFor(template, d(1, 13, 1, 14, QuteSyntaxErrorCode.UNEXPECTED_TOKEN, //
"Syntax error: `Unexpected '.' token`.", DiagnosticSeverity.Error));
}

@Test
public void objectPartInMethodParamEndsWithDot() {
String template = "{@java.util.List<org.acme.Item> items}\r\n" + //
"{@int index}\r\n" + //
"{items.get(index.)}";
testDiagnosticsFor(template, d(2, 16, 2, 17, QuteSyntaxErrorCode.UNEXPECTED_TOKEN, //
"Syntax error: `Unexpected '.' token`.", DiagnosticSeverity.Error));
}

@Test
public void propertyPartEndsWithDot() {
String template = "{@java.util.List<org.acme.Item> items}\r\n" + //
"{items.size.}";
testDiagnosticsFor(template, d(1, 11, 1, 12, QuteSyntaxErrorCode.UNEXPECTED_TOKEN, //
"Syntax error: `Unexpected '.' token`.", DiagnosticSeverity.Error));
}

@Test
public void propertyPartInMethodParamEndsWithDot() {
String template = "{@java.util.List<org.acme.Item> items}\r\n" + //
"{items.get(items.size.)}";
testDiagnosticsFor(template, d(1, 21, 1, 22, QuteSyntaxErrorCode.UNEXPECTED_TOKEN, //
"Syntax error: `Unexpected '.' token`.", DiagnosticSeverity.Error));
}

@Test
public void methodPartEndsWithDot() {
String template = "{@java.util.List<org.acme.Item> items}\r\n" + //
"{items.size().}";
testDiagnosticsFor(template, d(1, 13, 1, 14, QuteSyntaxErrorCode.UNEXPECTED_TOKEN, //
"Syntax error: `Unexpected '.' token`.", DiagnosticSeverity.Error));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.qute.services.diagnostics.syntax;
package com.redhat.qute.services.diagnostics.syntax.overrided;

import static com.redhat.qute.QuteAssert.ca;
import static com.redhat.qute.QuteAssert.d;
Expand All @@ -25,12 +25,13 @@
import com.redhat.qute.services.diagnostics.QuteErrorCode;

/**
* Syntax error which improves the error of the real Qute parser.
* Syntax error which improves the error with sections from the real Qute
* parser.
*
* @author Angelo ZERR
*
*/
public class QuteDiagnosticsOverridedSyntaxErrorTest {
public class QuteDiagnosticsSectionSyntaxErrorTest {

@Test
public void UNTERMINATED_SECTION_with_let() throws Exception {
Expand Down

0 comments on commit 4a2b870

Please sign in to comment.