Skip to content

Commit

Permalink
Rearrange tests, fix for "record" as field identifier
Browse files Browse the repository at this point in the history
  • Loading branch information
koppor committed Sep 4, 2021
1 parent a2fe50f commit 23fd73e
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,44 @@ class Java14PreviewValidatorTest {
class Record {

@Nested
class RecordAsIdentifierForbidden {
class RecordAsTypeIdentifierForbidden {
@Test
void recordUsedAsClassName() {
void recordUsedAsClassIdentifier() {
String s = "public class record {}";
ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(s));
TestUtils.assertProblems(result, "(line 1,col 14) 'record' cannot be used as an identifier as it is a keyword.");
TestUtils.assertProblems(result, "(line 1,col 14) 'record' is a restricted identifier and cannot be used for type declarations");
}

@Test
void recordUsedAsFieldName() {
void recordUsedAsEnumIdentifier() {
String s = "public enum record {}";
ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(s));
TestUtils.assertProblems(result, "(line 1,col 13) 'record' is a restricted identifier and cannot be used for type declarations");
}

@Test
void recordUsedAsRecordIdentifier() {
String s = "public record record() {}";
ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(s));
TestUtils.assertProblems(result, "(line 1,col 15) 'record' is a restricted identifier and cannot be used for type declarations");
}
}

@Nested
class RecordUsedAsIdentifierAllowedAsFieldDeclarations {
@Test
void recordUsedAsFieldIdentifierInClass() {
String s = "class X { int record; }";
ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(s));
TestUtils.assertNoProblems(result);
}

@Test
void recordUsedAsFieldIdentifierInInterface() {
String s = "interface X { int record; }";
ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(s));
TestUtils.assertNoProblems(result);
}
}

@Nested
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,45 @@ class Java15PreviewValidatorTest {
class Record {

@Nested
class RecordAsIdentifierForbidden {
class RecordAsTypeIdentifierForbidden {
@Test
void recordUsedAsClassName() {
void recordUsedAsClassIdentifier() {
String s = "public class record {}";
ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(s));
TestUtils.assertProblems(result, "(line 1,col 14) 'record' cannot be used as an identifier as it is a keyword.");
TestUtils.assertProblems(result, "(line 1,col 14) 'record' is a restricted identifier and cannot be used for type declarations");
}

@Test
void recordUsedAsFieldName() {
void recordUsedAsEnumIdentifier() {
String s = "public enum record {}";
ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(s));
TestUtils.assertProblems(result, "(line 1,col 13) 'record' is a restricted identifier and cannot be used for type declarations");
}

@Test
void recordUsedAsRecordIdentifier() {
String s = "public record record() {}";
ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(s));
TestUtils.assertProblems(result, "(line 1,col 15) 'record' is a restricted identifier and cannot be used for type declarations");
}
}

@Nested
class RecordUsedAsIdentifierAllowedAsFieldDeclarations {
@Test
void recordUsedAsFieldIdentifierInClass() {
String s = "class X { int record; }";
ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(s));
TestUtils.assertNoProblems(result);
}
}

@Test
void recordUsedAsFieldIdentifierInInterface() {
String s = "interface X { int record; }";
ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(s));
TestUtils.assertNoProblems(result);
}
}

@Nested
class RecordDeclarationPermitted {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,30 +57,46 @@ void yieldAllowed() {
class Record {

@Nested
class RecordAsIdentifierSometimesForbidden {
class RecordAsTypeIdentifierForbidden {
@Test
void recordUsedAsClassName() {
void recordUsedAsClassIdentifier() {
String s = "public class record {}";
ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(s));
TestUtils.assertProblems(result, "(line 1,col 14) 'record' cannot be used as an identifier as it is a keyword.");
TestUtils.assertProblems(result, "(line 1,col 14) 'record' is a restricted identifier and cannot be used for type declarations");
}

@Test
void recordUsedAsFieldNameInClass() {
void recordUsedAsEnumIdentifier() {
String s = "public enum record {}";
ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(s));
TestUtils.assertProblems(result, "(line 1,col 13) 'record' is a restricted identifier and cannot be used for type declarations");
}

@Test
void recordUsedAsRecordIdentifier() {
String s = "public record record() {}";
ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(s));
TestUtils.assertProblems(result, "(line 1,col 15) 'record' is a restricted identifier and cannot be used for type declarations");
}
}

@Nested
class RecordUsedAsIdentifierAllowedAsFieldDeclarations {
@Test
void recordUsedAsFieldIdentifierInClass() {
String s = "class X { int record; }";
ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(s));
TestUtils.assertNoProblems(result);
}

@Test
void recordUsedAsFieldNameInInterface() {
void recordUsedAsFieldIdentifierInInterface() {
String s = "interface X { int record; }";
ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(s));
TestUtils.assertNoProblems(result);
}
}


@Nested
class RecordDeclarationPermitted {
@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,56 +23,47 @@

import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.EnumDeclaration;
import com.github.javaparser.ast.body.RecordDeclaration;
import com.github.javaparser.ast.body.TypeDeclaration;
import com.github.javaparser.ast.expr.Name;
import com.github.javaparser.ast.expr.SimpleName;

import static com.github.javaparser.utils.CodeGenerationUtils.f;

/**
* Validates that "record" cannot be used as class name.
* Validates that "record" cannot be used as identifier for type declarations (e.g., classes, enums, and records).
* For details, see <a href="https://openjdk.java.net/jeps/395">JEP 395</a>
*/
public class ReservedKeywordValidatorRecord extends VisitorValidator {
private final String keyword;
private final String error;

public ReservedKeywordValidatorRecord() {
this.keyword = "record";
error = f("'%s' cannot be used as an identifier as it is a keyword.", keyword);
error = "'record' is a restricted identifier and cannot be used for type declarations";
}

@Override
public void visit(Name n, ProblemReporter arg) {
if (n.getIdentifier().equals(keyword) && validUsage(n)) {
if (n.getIdentifier().equals("record") && !validUsage(n)) {
arg.report(n, error);
}
super.visit(n, arg);
}

@Override
public void visit(SimpleName n, ProblemReporter arg) {
if (n.getIdentifier().equals(keyword) && validUsage(n)) {
if (n.getIdentifier().equals("record") && !validUsage(n)) {
arg.report(n, error);
}
super.visit(n, arg);
}

private boolean validUsage(Node node) {
if (!node.getParentNode().isPresent()) {
return false;
}
Node parent = node.getParentNode().get();

if (parent instanceof ClassOrInterfaceDeclaration) {
return true;
}
Node parent = node.getParentNode().get();

if (!parent.getParentNode().isPresent()) {
return false;
}
Node grandParent = parent.getParentNode().get();

return (grandParent instanceof ClassOrInterfaceDeclaration);
return !(parent instanceof TypeDeclaration);
}
}

0 comments on commit 23fd73e

Please sign in to comment.