Skip to content

Commit

Permalink
Make validator library and put the first validation in it.
Browse files Browse the repository at this point in the history
  • Loading branch information
matozoid committed Mar 5, 2017
1 parent bac6007 commit d3c236f
Show file tree
Hide file tree
Showing 13 changed files with 190 additions and 14 deletions.
Expand Up @@ -35,6 +35,10 @@
import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt;
import com.github.javaparser.ast.stmt.Statement;
import com.github.javaparser.ast.type.ClassOrInterfaceType;
import com.github.javaparser.ast.validator.DefaultValidator;
import com.github.javaparser.ast.validator.NoProblemsValidator;
import com.github.javaparser.ast.validator.ProblemReporter;
import com.github.javaparser.ast.validator.Validator;
import com.github.javaparser.javadoc.Javadoc;

import java.io.*;
Expand Down Expand Up @@ -86,6 +90,13 @@ private GeneratedJavaParser getParserForProvider(Provider provider) {
return astParser;
}

/**
* @deprecated use the other parse method.
*/
public <N extends Node> ParseResult<N> parse(ParseStart<N> start, Provider provider) {
return parse(start, provider, new DefaultValidator());
}

/**
* Parses source code.
* It takes the source code from a Provider.
Expand All @@ -96,7 +107,7 @@ private GeneratedJavaParser getParserForProvider(Provider provider) {
* @param <N> the subclass of Node that is the result of parsing in the start.
* @return the parse result, a collection of encountered problems, and some extra data.
*/
public <N extends Node> ParseResult<N> parse(ParseStart<N> start, Provider provider) {
public <N extends Node> ParseResult<N> parse(ParseStart<N> start, Provider provider, Validator validator) {
assertNotNull(start);
assertNotNull(provider);
final GeneratedJavaParser parser = getParserForProvider(provider);
Expand All @@ -106,6 +117,8 @@ public <N extends Node> ParseResult<N> parse(ParseStart<N> start, Provider provi
final CommentsCollection comments = parser.getCommentsCollection();
commentsInserter.insertComments(resultNode, comments.copy().getComments());
}

validator.validate(resultNode, new ProblemReporter(parser.problems));

return new ParseResult<>(resultNode, parser.problems, parser.getTokens(),
parser.getCommentsCollection());
Expand Down Expand Up @@ -361,8 +374,11 @@ public static Statement parseStatement(final String statement) {
}

private static <T extends Node> T simplifiedParse(ParseStart<T> context, Provider provider) {
ParseResult<T> result = new JavaParser(new ParserConfiguration()).parse(context, provider);
return result.getResult().orElseThrow(() -> new ParseProblemException(result.getProblems()));
ParseResult<T> result = new JavaParser(new ParserConfiguration()).parse(context, provider, new DefaultValidator());
if (result.isSuccessful()) {
return result.getResult().get();
}
throw new ParseProblemException(result.getProblems());
}

/**
Expand Down
Expand Up @@ -29,7 +29,6 @@
import com.github.javaparser.metamodel.MarkerAnnotationExprMetaModel;
import com.github.javaparser.metamodel.JavaParserMetaModel;
import static com.github.javaparser.JavaParser.parseName;

import static com.github.javaparser.JavaParser.parseName;

/**
Expand Down
@@ -0,0 +1,21 @@
package com.github.javaparser.ast.validator;

import com.github.javaparser.ast.stmt.TryStmt;

/**
* The validator that is used by default by the static JavaParser methods.
*/
public class DefaultValidator extends Validators {
public DefaultValidator() {
super(new VisitorValidator() {
@Override
public void visit(TryStmt n, ProblemReporter reporter) {
if (n.getCatchClauses().isEmpty()
&& n.getResources().isEmpty()
&& !n.getFinallyBlock().isPresent()) {
reporter.report("Try has no finally, no catch, and no resources", n);
}
}
});
}
}
@@ -0,0 +1,12 @@
package com.github.javaparser.ast.validator;

import com.github.javaparser.ast.Node;

/**
* Stub validator for when no validation is wanted.
*/
public class NoProblemsValidator implements Validator {
@Override
public void validate(Node node, ProblemReporter problemReporter) {
}
}
@@ -0,0 +1,32 @@
package com.github.javaparser.ast.validator;

import com.github.javaparser.Problem;
import com.github.javaparser.Range;
import com.github.javaparser.ast.Node;

import java.util.List;

/**
* A simple interface where validators can report found problems.
*/
public class ProblemReporter {
private final List<Problem> problems;

public ProblemReporter(List<Problem> problems) {
this.problems = problems;
}

/**
* Report a problem.
*
* @param message description of the problem
* @param node the node in which the problem occurred, used to find the Range of the problem.
*/
public void report(String message, Node node) {
report(message, node.getRange().orElse(null));
}

public void report(String message, Range range) {
problems.add(new Problem(message, range, null));
}
}
@@ -0,0 +1,15 @@
package com.github.javaparser.ast.validator;

import com.github.javaparser.ast.Node;

/**
* A validator that can be run on a node to check for semantic errors.
* It is fully up to the implementor how to do this.
*/
public interface Validator {
/**
* @param node the node that wants to be validated
* @param problemReporter when found, validation errors can be reported here
*/
void validate(Node node, ProblemReporter problemReporter);
}
@@ -0,0 +1,27 @@
package com.github.javaparser.ast.validator;

import com.github.javaparser.ast.Node;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
* A validator that will call a collection of validators.
*/
public class Validators implements Validator {
private final List<Validator> validators = new ArrayList<>();

public Validators(Validator... validators) {
this.validators.addAll(Arrays.asList(validators));
}

public List<Validator> getValidators() {
return validators;
}

@Override
public void validate(Node node, ProblemReporter problemReporter) {
validators.forEach(v -> v.validate(node, problemReporter));
}
}
@@ -0,0 +1,16 @@
package com.github.javaparser.ast.validator;

import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;

/**
* A validator that uses a visitor for validation.
* This class is the visitor too.
* Implement the "visit" methods you want to use for validation.
*/
public abstract class VisitorValidator extends VoidVisitorAdapter<ProblemReporter> implements Validator {
@Override
public void validate(Node node, ProblemReporter problemReporter) {
node.accept(this, problemReporter);
}
}
Expand Up @@ -563,10 +563,10 @@ private static void initializePropertyMetaModels() {
unaryExprMetaModel.getDeclaredPropertyMetaModels().add(unaryExprMetaModel.expressionPropertyMetaModel);
unaryExprMetaModel.operatorPropertyMetaModel = new PropertyMetaModel(unaryExprMetaModel, "operator", com.github.javaparser.ast.expr.UnaryExpr.Operator.class, Optional.empty(), false, false, false, false, false);
unaryExprMetaModel.getDeclaredPropertyMetaModels().add(unaryExprMetaModel.operatorPropertyMetaModel);
unaryExprMetaModel.postfixPropertyMetaModel = new PropertyMetaModel(unaryExprMetaModel, "postfix", boolean.class, Optional.empty(), false, true, false, false, false);
unaryExprMetaModel.getDerivedPropertyMetaModels().add(unaryExprMetaModel.postfixPropertyMetaModel);
unaryExprMetaModel.prefixPropertyMetaModel = new PropertyMetaModel(unaryExprMetaModel, "prefix", boolean.class, Optional.empty(), false, true, false, false, false);
unaryExprMetaModel.getDerivedPropertyMetaModels().add(unaryExprMetaModel.prefixPropertyMetaModel);
unaryExprMetaModel.postfixPropertyMetaModel = new PropertyMetaModel(unaryExprMetaModel, "postfix", boolean.class, Optional.empty(), false, true, false, false, false);
unaryExprMetaModel.getDerivedPropertyMetaModels().add(unaryExprMetaModel.postfixPropertyMetaModel);
variableDeclarationExprMetaModel.annotationsPropertyMetaModel = new PropertyMetaModel(variableDeclarationExprMetaModel, "annotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false, false);
variableDeclarationExprMetaModel.getDeclaredPropertyMetaModels().add(variableDeclarationExprMetaModel.annotationsPropertyMetaModel);
variableDeclarationExprMetaModel.modifiersPropertyMetaModel = new PropertyMetaModel(variableDeclarationExprMetaModel, "modifiers", com.github.javaparser.ast.Modifier.class, Optional.empty(), false, false, false, true, false);
Expand Down
Expand Up @@ -12,8 +12,8 @@ public class UnaryExprMetaModel extends ExpressionMetaModel {

public PropertyMetaModel operatorPropertyMetaModel;

public PropertyMetaModel postfixPropertyMetaModel;

public PropertyMetaModel prefixPropertyMetaModel;

public PropertyMetaModel postfixPropertyMetaModel;
}

7 changes: 1 addition & 6 deletions javaparser-core/src/main/javacc/java.jj
Expand Up @@ -3193,12 +3193,7 @@ TryStmt TryStatement():
|
"finally" finallyBlock = Block()
)
{
if (finallyBlock == null && catchs.isEmpty() && resources.isEmpty()) {
addProblem("Try has no finally, no catch, and no resources");
}
return new TryStmt(range(begin, tokenEnd()), resources, tryBlock, catchs, finallyBlock);
}
{ return new TryStmt(range(begin, tokenEnd()), resources, tryBlock, catchs, finallyBlock); }
}


Expand Down
@@ -0,0 +1,24 @@
package com.github.javaparser.ast.validator;

import com.github.javaparser.JavaParser;
import com.github.javaparser.ParseResult;
import com.github.javaparser.ParseStart;
import com.github.javaparser.ast.stmt.Statement;
import org.junit.Test;

import static com.github.javaparser.Providers.provider;
import static org.junit.Assert.assertEquals;

public class DefaultValidatorTest {
@Test
public void tryWithoutAnything() {
ParseResult<Statement> result = new JavaParser().parse(ParseStart.STATEMENT, provider("try{}"), new DefaultValidator());
assertEquals("[(line 1,col 1) Try has no finally, no catch, and no resources]", result.getProblems().toString());
}
@Test
public void classExtendingMoreThanOne() {
ParseResult<Statement> result = new JavaParser().parse(ParseStart.STATEMENT, provider("try{}"), new DefaultValidator());
assertEquals("[(line 1,col 1) Try has no finally, no catch, and no resources]", result.getProblems().toString());
}

}
@@ -0,0 +1,19 @@
package com.github.javaparser.ast.validator;

import com.github.javaparser.JavaParser;
import com.github.javaparser.ParseResult;
import com.github.javaparser.ast.CompilationUnit;
import org.junit.Test;

import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
import static com.github.javaparser.Providers.provider;
import static org.junit.Assert.assertEquals;

public class ValidatorTest {
@Test
public void noProblemsHere() {
ParseResult<CompilationUnit> result = new JavaParser().parse(COMPILATION_UNIT, provider("class X{}"), new NoProblemsValidator());
assertEquals(true, result.isSuccessful());
}

}

0 comments on commit d3c236f

Please sign in to comment.