Skip to content
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
644 changes: 342 additions & 302 deletions pom.xml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@
import javax.inject.Inject;
import javax.inject.Named;

import io.github.shitikanth.enforcerrules.impl.TLDParserFactories;
import org.apache.maven.enforcer.rule.api.AbstractEnforcerRule;
import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.project.MavenProject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.github.shitikanth.enforcerrules.impl.TLDParserFactories;

@Named("banEmptyJavaFiles")
class BanEmptyJavaFiles extends AbstractEnforcerRule {
class BanEmptyJavaFiles extends AbstractEnforcerRule {
private static final Logger LOGGER = LoggerFactory.getLogger(BanEmptyJavaFiles.class);


private final MavenSession session;

private ExecutorService executor;
Expand Down Expand Up @@ -87,38 +87,44 @@ private void analyzeSourceRoots(List<Path> sourceRoots) throws EnforcerRuleExcep
continue;
}
try {
var sourceFiles = Files.find(sourceRoot, Integer.MAX_VALUE, (path, attr) -> attr.isRegularFile() && path.toFile().getName().endsWith(".java"))
.collect(Collectors.toList());
var sourceFiles = Files.find(
sourceRoot,
Integer.MAX_VALUE,
(path, attr) -> attr.isRegularFile()
&& path.toFile().getName().endsWith(".java"))
.collect(Collectors.toList());
long startTime = System.currentTimeMillis();
LOGGER.info("Analyzing {} files", sourceFiles.size());
executor = Executors.newFixedThreadPool(4);
executor.invokeAll(sourceFiles.stream()
.filter(path -> {
String fileName = null;
if (path.getFileName() != null) {
fileName = path.getFileName().toString();
}
return fileName != null && !fileName.equals("package-info.java") && !fileName.equals("module-info.java");
})
.map(
path -> (Callable<AnalysisResult>) () -> {
boolean isEmpty = analyzer.isEmptyJavaFile(path);
return new AnalysisResult(path, isEmpty);
}).collect(Collectors.toList()))
.forEach(result -> {
if (result.isDone()) {
try {
var analysisResult = result.get();
if (analysisResult.isEmpty()) {
emptyJavaSourceFiles.add(analysisResult.path());
.filter(path -> {
String fileName = null;
if (path.getFileName() != null) {
fileName = path.getFileName().toString();
}
return fileName != null
&& !fileName.equals("package-info.java")
&& !fileName.equals("module-info.java");
})
.map(path -> (Callable<AnalysisResult>) () -> {
boolean isEmpty = analyzer.isEmptyJavaFile(path);
return new AnalysisResult(path, isEmpty);
})
.collect(Collectors.toList()))
.forEach(result -> {
if (result.isDone()) {
try {
var analysisResult = result.get();
if (analysisResult.isEmpty()) {
emptyJavaSourceFiles.add(analysisResult.path());
}
} catch (ExecutionException e) {
LOGGER.error("Task encountered exception: ", e.getCause());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
} catch (ExecutionException e) {
LOGGER.error("Task encountered exception: ", e.getCause());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
});
long endTime = System.currentTimeMillis();
LOGGER.info("Finished in {}ms", endTime - startTime);
} catch (IOException e) {
Expand All @@ -132,7 +138,12 @@ private void analyzeSourceRoots(List<Path> sourceRoots) throws EnforcerRuleExcep
if (!emptyJavaSourceFiles.isEmpty()) {
StringBuilder sb = new StringBuilder("Empty Java source files found:\n");
for (Path path : emptyJavaSourceFiles) {
sb.append("\t- ").append(session.getTopLevelProject().getBasedir().toPath().relativize(path)).append("\n");
sb.append("\t- ")
.append(session.getTopLevelProject()
.getBasedir()
.toPath()
.relativize(path))
.append("\n");
}
throw new EnforcerRuleException(sb.toString());
}
Expand All @@ -142,25 +153,25 @@ static final class AnalysisResult {
private final Path path;
private final boolean isEmpty;

AnalysisResult(
Path path,
boolean isEmpty
) {
AnalysisResult(Path path, boolean isEmpty) {
this.path = path;
this.isEmpty = isEmpty;
}

public Path path() {return path;}
public Path path() {
return path;
}

public boolean isEmpty() {return isEmpty;}
public boolean isEmpty() {
return isEmpty;
}

@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (AnalysisResult) obj;
return Objects.equals(this.path, that.path) &&
this.isEmpty == that.isEmpty;
return Objects.equals(this.path, that.path) && this.isEmpty == that.isEmpty;
}

@Override
Expand All @@ -170,9 +181,7 @@ public int hashCode() {

@Override
public String toString() {
return "AnalysisResult[" +
"path=" + path + ", " +
"isEmpty=" + isEmpty + ']';
return "AnalysisResult[" + "path=" + path + ", " + "isEmpty=" + isEmpty + ']';
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@
import java.util.List;
import java.util.stream.Collectors;

import io.github.shitikanth.enforcerrules.AbstractTLDParser;
import io.github.shitikanth.enforcerrules.JavaTLDLexer;
import io.github.shitikanth.enforcerrules.JavaTLDParser;
import com.google.common.annotations.VisibleForTesting;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;

import io.github.shitikanth.enforcerrules.AbstractTLDParser;
import io.github.shitikanth.enforcerrules.JavaTLDLexer;
import io.github.shitikanth.enforcerrules.JavaTLDParser;

class AntlrTLDParser extends AbstractTLDParser {
public AntlrTLDParser(Path path) {
super(path);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.github.javaparser.JavaParserAdapter;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.TypeDeclaration;

import io.github.shitikanth.enforcerrules.AbstractTLDParser;

class JavaParserTLDParser extends AbstractTLDParser {
Expand All @@ -22,7 +23,7 @@ public JavaParserTLDParser(JavaParser javaParser, Path path) {
}

@Override
public List<String> parse() {
public List<String> parse() {
CompilationUnit compilationUnit = null;
try (BufferedReader reader = this.getReader()) {
compilationUnit = parser.parse(reader);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@

import javax.annotation.Nullable;

import io.github.shitikanth.enforcerrules.AbstractTLDParser;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.github.shitikanth.enforcerrules.AbstractTLDParser;

class RecursiveDescentTLDParser extends AbstractTLDParser {
static final Logger LOGGER = LoggerFactory.getLogger(RecursiveDescentTLDParser.class);
private String input;
private State state;
private int start=0;
private int pos=0;
private int start = 0;
private int pos = 0;
private final List<String> collector = new ArrayList<>();

public RecursiveDescentTLDParser(Path path) {
Expand Down Expand Up @@ -60,7 +60,7 @@ private void next() {
}

private char cur() {
return input.charAt(pos-1);
return input.charAt(pos - 1);
}

private char peek() {
Expand Down Expand Up @@ -97,7 +97,7 @@ private boolean lookingAt(Pattern pattern) {
}

private void skipWs() {
while(!eof() && Character.isWhitespace(peek())) {
while (!eof() && Character.isWhitespace(peek())) {
next();
}
skip();
Expand Down Expand Up @@ -143,30 +143,23 @@ class InitialState implements State {
@Override
public State runState() {
Pattern classKeyword = Pattern.compile("(class|record|@?interface|enum)\\b");
while(!eof()) {
while (!eof()) {
skipWs();
if (lookingAt("\"\"\"")) {
return new InsideTextState(this);
}
else if (lookingAt("\"")) {
} else if (lookingAt("\"")) {
return new InsideStringState(this);
}
else if (lookingAt("(")) {
} else if (lookingAt("(")) {
return new SkipParentheticalBlockState(this, '(', ')');
}
else if (lookingAt("//")) {
} else if (lookingAt("//")) {
return new LineCommentState(this);
}
else if (lookingAt("/*")) {
} else if (lookingAt("/*")) {
return new BlockCommentState(this);
}
else if (lookingAt("package") || lookingAt("import")) {
} else if (lookingAt("package") || lookingAt("import")) {
return new PackageOrImportState();
}
else if (lookingAt(classKeyword)) {
} else if (lookingAt(classKeyword)) {
return new TypeDeclarationState();
}
else {
} else {
skipWord();
}
}
Expand Down Expand Up @@ -212,7 +205,7 @@ public InsideStringState(State parent) {
public State runState() {
LOGGER.debug("{}\tinside string: {}", pos, input.substring(pos, Math.min(pos + 10, input.length())));
boolean escaped = false;
while(!eof()) {
while (!eof()) {
char c = peek();
next();
if (c == '\"' && !escaped) {
Expand All @@ -226,10 +219,8 @@ public State runState() {
}
return parent;
}

}


class InsideCharacterLiteralState implements State {
private final State parent;

Expand All @@ -240,9 +231,10 @@ public InsideCharacterLiteralState(State parent) {
@Nullable
@Override
public State runState() {
LOGGER.debug("{}\tinside character literal: {}", pos, input.substring(pos, Math.min(pos + 10, input.length())));
LOGGER.debug(
"{}\tinside character literal: {}", pos, input.substring(pos, Math.min(pos + 10, input.length())));
boolean escaped = false;
while(!eof()) {
while (!eof()) {
char c = peek();
next();
if (c == '\'' && !escaped) {
Expand Down Expand Up @@ -324,18 +316,16 @@ public SkipParentheticalBlockState(State nextState, char startMarker, char endMa
@Override
public State runState() {
char c;
while(!eof()) {
while (!eof()) {
skipWs();
if (lookingAt("\"\"\"")) {
return new InsideTextState(this);
}
else if (lookingAt("\"")) {
} else if (lookingAt("\"")) {
return new InsideStringState(this);
}
if (lookingAt("//")) {
return new LineCommentState(this);
}
else if (lookingAt("/*")) {
} else if (lookingAt("/*")) {
return new BlockCommentState(this);
} else if (lookingAt("'")) {
return new InsideCharacterLiteralState(this);
Expand All @@ -356,5 +346,4 @@ else if (lookingAt("/*")) {
throw new RuntimeException("Failed to parse: " + getPath());
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import io.github.shitikanth.enforcerrules.AbstractTLDParser;
import com.google.common.annotations.VisibleForTesting;

import io.github.shitikanth.enforcerrules.AbstractTLDParser;

class RegexBasedTLDParser extends AbstractTLDParser {
private Pattern pattern = Pattern.compile("^((public|protected|private|static|abstract|final|sealed|non_sealed)\\s+)*(class|interface|@interface|enum|record)\\s+(\\w+)");
private Pattern pattern = Pattern.compile(
"^((public|protected|private|static|abstract|final|sealed|non_sealed)\\s+)*(class|interface|@interface|enum|record)\\s+(\\w+)");

public RegexBasedTLDParser(Path path) {
super(path);
Expand All @@ -25,7 +27,7 @@ public RegexBasedTLDParser(BufferedReader reader) {

@Override
public List<String> parse() {
try(var bufferedReader = getReader()) {
try (var bufferedReader = getReader()) {
return parse(bufferedReader);
} catch (IOException e) {
throw new UncheckedIOException(e);
Expand All @@ -44,6 +46,4 @@ public List<String> parse(BufferedReader bufferedReader) {
});
return types;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@

import com.github.javaparser.JavaParser;
import com.github.javaparser.ParserConfiguration;

import io.github.shitikanth.enforcerrules.TLDParser;
import io.github.shitikanth.enforcerrules.TLDParserFactory;

public class TLDParserFactories {
static String DEFAULT = "default";
static Map<String, TLDParserFactory> factories = Map.of(
DEFAULT, TLDParserFactories::recursiveDescentParser,
"java-parser", TLDParserFactories::javaParser,
"regex", TLDParserFactories::regexBasedParser
);

private TLDParserFactories() {
}
DEFAULT,
TLDParserFactories::recursiveDescentParser,
"java-parser",
TLDParserFactories::javaParser,
"regex",
TLDParserFactories::regexBasedParser);

private TLDParserFactories() {}

public static TLDParserFactory getParserFactory(String parserId) {
if (parserId == null) {
Expand Down
Loading
Loading