chore: fix PMD warnings and improve code quality
This commit is contained in:
11
build.gradle
11
build.gradle
@@ -12,6 +12,17 @@ configurations {
|
|||||||
mockitoAgent
|
mockitoAgent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pmd {
|
||||||
|
consoleOutput = true
|
||||||
|
toolVersion = '7.20.0'
|
||||||
|
sourceSets = [sourceSets.main]
|
||||||
|
ruleSetFiles = files(rootProject.file(".ruleset"))
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(Pmd) {
|
||||||
|
maxHeapSize = "16g"
|
||||||
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
toolchain {
|
toolchain {
|
||||||
languageVersion = JavaLanguageVersion.of(21)
|
languageVersion = JavaLanguageVersion.of(21)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import java.nio.file.Paths;
|
|||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@@ -25,6 +26,7 @@ import com.github.javaparser.ParserConfiguration;
|
|||||||
import com.github.javaparser.ParserConfiguration.LanguageLevel;
|
import com.github.javaparser.ParserConfiguration.LanguageLevel;
|
||||||
import com.github.javaparser.StaticJavaParser;
|
import com.github.javaparser.StaticJavaParser;
|
||||||
import com.github.javaparser.ast.CompilationUnit;
|
import com.github.javaparser.ast.CompilationUnit;
|
||||||
|
import com.github.javaparser.ast.PackageDeclaration;
|
||||||
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
|
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
|
||||||
import com.github.javaparser.ast.body.MethodDeclaration;
|
import com.github.javaparser.ast.body.MethodDeclaration;
|
||||||
import com.github.javaparser.ast.expr.AnnotationExpr;
|
import com.github.javaparser.ast.expr.AnnotationExpr;
|
||||||
@@ -145,7 +147,7 @@ import com.github.javaparser.ast.expr.MemberValuePair;
|
|||||||
* @see org.egothor.methodatlas.ai.AiSuggestionEngine
|
* @see org.egothor.methodatlas.ai.AiSuggestionEngine
|
||||||
* @see #main(String[])
|
* @see #main(String[])
|
||||||
*/
|
*/
|
||||||
public class MethodAtlasApp {
|
public class MethodAtlasApp { // NOPMD
|
||||||
|
|
||||||
private static final Logger LOG = Logger.getLogger(MethodAtlasApp.class.getName());
|
private static final Logger LOG = Logger.getLogger(MethodAtlasApp.class.getName());
|
||||||
|
|
||||||
@@ -296,8 +298,8 @@ public class MethodAtlasApp {
|
|||||||
private static void processFile(Path path, OutputMode mode, AiOptions aiOptions, AiSuggestionEngine aiEngine) {
|
private static void processFile(Path path, OutputMode mode, AiOptions aiOptions, AiSuggestionEngine aiEngine) {
|
||||||
try {
|
try {
|
||||||
CompilationUnit compilationUnit = StaticJavaParser.parse(path);
|
CompilationUnit compilationUnit = StaticJavaParser.parse(path);
|
||||||
String packageName = compilationUnit.getPackageDeclaration()
|
String packageName = compilationUnit.getPackageDeclaration().map(PackageDeclaration::getNameAsString)
|
||||||
.map(packageDeclaration -> packageDeclaration.getNameAsString()).orElse("");
|
.orElse("");
|
||||||
|
|
||||||
compilationUnit.findAll(ClassOrInterfaceDeclaration.class).forEach(clazz -> {
|
compilationUnit.findAll(ClassOrInterfaceDeclaration.class).forEach(clazz -> {
|
||||||
String className = clazz.getNameAsString();
|
String className = clazz.getNameAsString();
|
||||||
@@ -317,8 +319,9 @@ public class MethodAtlasApp {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.log(Level.WARNING, "Failed to parse: {0}", path);
|
if (LOG.isLoggable(Level.WARNING)) {
|
||||||
e.printStackTrace();
|
LOG.log(Level.WARNING, "Failed to parse: {0} due to {1}", new Object[] { path, e.getMessage() });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,8 +349,10 @@ public class MethodAtlasApp {
|
|||||||
|
|
||||||
String classSource = clazz.toString();
|
String classSource = clazz.toString();
|
||||||
if (classSource.length() > aiOptions.maxClassChars()) {
|
if (classSource.length() > aiOptions.maxClassChars()) {
|
||||||
LOG.log(Level.INFO, "Skipping AI for {0}: class source too large ({1} chars)",
|
if (LOG.isLoggable(Level.INFO)) {
|
||||||
new Object[] { fqcn, classSource.length() });
|
LOG.log(Level.INFO, "Skipping AI for {0}: class source too large ({1} chars)",
|
||||||
|
new Object[] { fqcn, classSource.length() });
|
||||||
|
}
|
||||||
return SuggestionLookup.from(null);
|
return SuggestionLookup.from(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,7 +360,10 @@ public class MethodAtlasApp {
|
|||||||
AiClassSuggestion aiClassSuggestion = aiEngine.suggestForClass(fqcn, classSource);
|
AiClassSuggestion aiClassSuggestion = aiEngine.suggestForClass(fqcn, classSource);
|
||||||
return SuggestionLookup.from(aiClassSuggestion);
|
return SuggestionLookup.from(aiClassSuggestion);
|
||||||
} catch (AiSuggestionException e) {
|
} catch (AiSuggestionException e) {
|
||||||
LOG.log(Level.WARNING, "AI suggestion failed for class " + fqcn + ": " + e.getMessage());
|
if (LOG.isLoggable(Level.WARNING)) {
|
||||||
|
LOG.log(Level.WARNING, "AI suggestion failed for class {0}: {1}",
|
||||||
|
new Object[] { fqcn, e.getMessage() });
|
||||||
|
}
|
||||||
return SuggestionLookup.from(null);
|
return SuggestionLookup.from(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -523,7 +531,8 @@ public class MethodAtlasApp {
|
|||||||
* @throws IllegalArgumentException if an option value is missing, malformed, or
|
* @throws IllegalArgumentException if an option value is missing, malformed, or
|
||||||
* unsupported
|
* unsupported
|
||||||
*/
|
*/
|
||||||
private static CliConfig parseArgs(String[] args) {
|
@SuppressWarnings("PMD.AvoidReassigningLoopVariables")
|
||||||
|
private static CliConfig parseArgs(String... args) {
|
||||||
OutputMode outputMode = OutputMode.CSV;
|
OutputMode outputMode = OutputMode.CSV;
|
||||||
List<Path> paths = new ArrayList<>();
|
List<Path> paths = new ArrayList<>();
|
||||||
AiOptions.Builder aiBuilder = AiOptions.builder();
|
AiOptions.Builder aiBuilder = AiOptions.builder();
|
||||||
@@ -534,14 +543,15 @@ public class MethodAtlasApp {
|
|||||||
switch (arg) {
|
switch (arg) {
|
||||||
case "-plain" -> outputMode = OutputMode.PLAIN;
|
case "-plain" -> outputMode = OutputMode.PLAIN;
|
||||||
case "-ai" -> aiBuilder.enabled(true);
|
case "-ai" -> aiBuilder.enabled(true);
|
||||||
case "-ai-provider" -> aiBuilder.provider(AiProvider.valueOf(nextArg(args, ++i, arg).toUpperCase()));
|
case "-ai-provider" ->
|
||||||
|
aiBuilder.provider(AiProvider.valueOf(nextArg(args, ++i, arg).toUpperCase(Locale.ROOT)));
|
||||||
case "-ai-model" -> aiBuilder.modelName(nextArg(args, ++i, arg));
|
case "-ai-model" -> aiBuilder.modelName(nextArg(args, ++i, arg));
|
||||||
case "-ai-base-url" -> aiBuilder.baseUrl(nextArg(args, ++i, arg));
|
case "-ai-base-url" -> aiBuilder.baseUrl(nextArg(args, ++i, arg));
|
||||||
case "-ai-api-key" -> aiBuilder.apiKey(nextArg(args, ++i, arg));
|
case "-ai-api-key" -> aiBuilder.apiKey(nextArg(args, ++i, arg));
|
||||||
case "-ai-api-key-env" -> aiBuilder.apiKeyEnv(nextArg(args, ++i, arg));
|
case "-ai-api-key-env" -> aiBuilder.apiKeyEnv(nextArg(args, ++i, arg));
|
||||||
case "-ai-taxonomy" -> aiBuilder.taxonomyFile(Paths.get(nextArg(args, ++i, arg)));
|
case "-ai-taxonomy" -> aiBuilder.taxonomyFile(Paths.get(nextArg(args, ++i, arg)));
|
||||||
case "-ai-taxonomy-mode" ->
|
case "-ai-taxonomy-mode" -> aiBuilder
|
||||||
aiBuilder.taxonomyMode(AiOptions.TaxonomyMode.valueOf(nextArg(args, ++i, arg).toUpperCase()));
|
.taxonomyMode(AiOptions.TaxonomyMode.valueOf(nextArg(args, ++i, arg).toUpperCase(Locale.ROOT)));
|
||||||
case "-ai-max-class-chars" -> aiBuilder.maxClassChars(Integer.parseInt(nextArg(args, ++i, arg)));
|
case "-ai-max-class-chars" -> aiBuilder.maxClassChars(Integer.parseInt(nextArg(args, ++i, arg)));
|
||||||
case "-ai-timeout-sec" ->
|
case "-ai-timeout-sec" ->
|
||||||
aiBuilder.timeout(Duration.ofSeconds(Long.parseLong(nextArg(args, ++i, arg))));
|
aiBuilder.timeout(Duration.ofSeconds(Long.parseLong(nextArg(args, ++i, arg))));
|
||||||
@@ -635,9 +645,9 @@ public class MethodAtlasApp {
|
|||||||
for (AnnotationExpr annotation : method.getAnnotations()) {
|
for (AnnotationExpr annotation : method.getAnnotations()) {
|
||||||
String name = annotation.getNameAsString();
|
String name = annotation.getNameAsString();
|
||||||
|
|
||||||
if ("Tag".equals(name)) {
|
if ("Tag".equals(name)) { // NOPMD
|
||||||
extractTagValue(annotation).ifPresent(tagValues::add);
|
extractTagValue(annotation).ifPresent(tagValues::add);
|
||||||
} else if ("Tags".equals(name)) {
|
} else if ("Tags".equals(name)) { // NOPMD
|
||||||
extractTagsContainerValues(annotation, tagValues);
|
extractTagsContainerValues(annotation, tagValues);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -665,7 +675,7 @@ public class MethodAtlasApp {
|
|||||||
|
|
||||||
if (annotation.isNormalAnnotationExpr()) {
|
if (annotation.isNormalAnnotationExpr()) {
|
||||||
for (MemberValuePair pair : annotation.asNormalAnnotationExpr().getPairs()) {
|
for (MemberValuePair pair : annotation.asNormalAnnotationExpr().getPairs()) {
|
||||||
if ("value".equals(pair.getNameAsString())) {
|
if ("value".equals(pair.getNameAsString())) { // NOPMD
|
||||||
extractTagsFromContainerValue(pair.getValue(), tagValues);
|
extractTagsFromContainerValue(pair.getValue(), tagValues);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ package org.egothor.methodatlas.ai;
|
|||||||
* @see AiProviderClient
|
* @see AiProviderClient
|
||||||
* @see org.egothor.methodatlas.MethodAtlasApp
|
* @see org.egothor.methodatlas.MethodAtlasApp
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.ImplicitFunctionalInterface")
|
||||||
public interface AiSuggestionEngine {
|
public interface AiSuggestionEngine {
|
||||||
/**
|
/**
|
||||||
* Requests AI-generated security classification for a single parsed test class.
|
* Requests AI-generated security classification for a single parsed test class.
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ public final class AnthropicClient implements AiProviderClient {
|
|||||||
AiClassSuggestion suggestion = httpSupport.objectMapper().readValue(json, AiClassSuggestion.class);
|
AiClassSuggestion suggestion = httpSupport.objectMapper().readValue(json, AiClassSuggestion.class);
|
||||||
return normalize(suggestion);
|
return normalize(suggestion);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) { // NOPMD
|
||||||
throw new AiSuggestionException("Anthropic suggestion failed for " + fqcn, e);
|
throw new AiSuggestionException("Anthropic suggestion failed for " + fqcn, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ public final class OllamaClient implements AiProviderClient {
|
|||||||
AiClassSuggestion suggestion = httpSupport.objectMapper().readValue(json, AiClassSuggestion.class);
|
AiClassSuggestion suggestion = httpSupport.objectMapper().readValue(json, AiClassSuggestion.class);
|
||||||
return normalize(suggestion);
|
return normalize(suggestion);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) { // NOPMD
|
||||||
throw new AiSuggestionException("Ollama suggestion failed for " + fqcn, e);
|
throw new AiSuggestionException("Ollama suggestion failed for " + fqcn, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ public final class OpenAiCompatibleClient implements AiProviderClient {
|
|||||||
AiClassSuggestion suggestion = httpSupport.objectMapper().readValue(json, AiClassSuggestion.class);
|
AiClassSuggestion suggestion = httpSupport.objectMapper().readValue(json, AiClassSuggestion.class);
|
||||||
return normalize(suggestion);
|
return normalize(suggestion);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) { // NOPMD
|
||||||
throw new AiSuggestionException("OpenAI-compatible suggestion failed for " + fqcn, e);
|
throw new AiSuggestionException("OpenAI-compatible suggestion failed for " + fqcn, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user