From 3880f49b42278929445bfabe827ec38a5fde6f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Thu, 12 Nov 2026 19:17:45 +0100 Subject: [PATCH 1/3] feat: add console output options, sorting and debug summary Print the Config/Cache header, the file count and a progress line on a terminal. Render one table per class or a single table, with the columns chosen by the show* settings, colored by their thresholds. Add --sort-by, --sort-order and --debug with per-stage timings and statistics. --- README.md | 39 ++ docs/Configuration.md | 24 +- .../application/AnalyseCommand.java | 88 +++- .../application/ConsoleRenderer.java | 81 ++++ .../application/ExecutionSummary.java | 45 ++ .../application/MetricFormatter.java | 70 +++ .../application/ProgressIndicator.java | 33 ++ .../application/ResultTableBuilder.java | 88 +++- .../application/TextTable.java | 20 +- .../domain/AnalysisStatistics.java | 48 ++ .../domain/CognitiveMetricsFacade.java | 34 +- .../domain/MetricsCollection.java | 19 + .../domain/MetricsSorter.java | 92 ++++ .../domain/ScoredMethod.java | 9 + .../application/AnalyseCommandE2ETest.java | 26 +- ...AndMethodsInStableSortedOrder.approved.txt | 49 +- ...tsOneTablePerFileToTheConsole.approved.txt | 22 +- ...heMetricsOfEveryJavaConstruct.approved.txt | 285 +++++++----- .../application/ConsoleOutputE2ETest.java | 426 ++++++++++++++++++ ...utputE2ETest.printsAllMetrics.approved.txt | 48 ++ ...rintsCyclomaticComplexityOnly.approved.txt | 48 ++ ....printsHalsteadComplexityOnly.approved.txt | 48 ++ ...SingleTableWithTheClassColumn.approved.txt | 26 ++ ...eMethodsExceedingTheThreshold.approved.txt | 15 + ...2ETest.printsTheDefaultTables.approved.txt | 48 ++ ...etricsWithoutTheDetailColumns.approved.txt | 48 ++ ...ETest.printsTheMinimalColumns.approved.txt | 48 ++ ...ETest.printsUnderstandability.approved.txt | 48 ++ ...dsByScoreDescendingInOneTable.approved.txt | 26 ++ .../application/MetricFormatterTest.java | 82 ++++ ...icAndUnderstandabilityColumns.approved.txt | 8 + .../application/ResultTableBuilderTest.java | 149 ++++-- ...ClassWhenTheTableMixesClasses.approved.txt | 8 + ...ColumnsWhenTheyAreSwitchedOff.approved.txt | 8 + ...odWithTheWeightNextToTheCount.approved.txt | 8 + ...heHeaderWhenThereAreNoMethods.approved.txt | 4 + .../churn/ChurnCommandE2ETest.java | 8 +- ...yChurnWithoutZeroScoreClasses.approved.txt | 14 +- .../domain/MetricsCollectionTest.java | 44 ++ .../domain/MetricsSorterTest.java | 179 ++++++++ .../fixtures/console/all-metrics.yaml | 6 + .../fixtures/console/cyclomatic-only.yaml | 4 + .../fixtures/console/halstead-only.yaml | 4 + .../resources/fixtures/console/minimal.yaml | 4 + .../console/nothing-exceeds-single.yaml | 6 + .../fixtures/console/nothing-exceeds.yaml | 5 + .../fixtures/console/single-table.yaml | 6 + .../resources/fixtures/console/threshold.yaml | 5 + .../fixtures/console/understandability.yaml | 4 + .../fixtures/console/without-detailed.yaml | 7 + 50 files changed, 2216 insertions(+), 248 deletions(-) create mode 100644 src/main/java/net/floriankraemer/cognitive_analysis/application/ConsoleRenderer.java create mode 100644 src/main/java/net/floriankraemer/cognitive_analysis/application/ExecutionSummary.java create mode 100644 src/main/java/net/floriankraemer/cognitive_analysis/application/MetricFormatter.java create mode 100644 src/main/java/net/floriankraemer/cognitive_analysis/application/ProgressIndicator.java create mode 100644 src/main/java/net/floriankraemer/cognitive_analysis/domain/AnalysisStatistics.java create mode 100644 src/main/java/net/floriankraemer/cognitive_analysis/domain/MetricsSorter.java create mode 100644 src/main/java/net/floriankraemer/cognitive_analysis/domain/ScoredMethod.java create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.java create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsAllMetrics.approved.txt create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsCyclomaticComplexityOnly.approved.txt create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsHalsteadComplexityOnly.approved.txt create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsOneSingleTableWithTheClassColumn.approved.txt create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsOnlyTheMethodsExceedingTheThreshold.approved.txt create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheDefaultTables.approved.txt create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheMetricsWithoutTheDetailColumns.approved.txt create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheMinimalColumns.approved.txt create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsUnderstandability.approved.txt create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.sortsAllMethodsByScoreDescendingInOneTable.approved.txt create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/application/MetricFormatterTest.java create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.addsTheHalsteadCyclomaticAndUnderstandabilityColumns.approved.txt create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.leadsWithTheClassWhenTheTableMixesClasses.approved.txt create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.leavesOutTheDetailColumnsWhenTheyAreSwitchedOff.approved.txt create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.rendersOneRowPerMethodWithTheWeightNextToTheCount.approved.txt create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.rendersOnlyTheHeaderWhenThereAreNoMethods.approved.txt create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/domain/MetricsCollectionTest.java create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/domain/MetricsSorterTest.java create mode 100644 src/test/resources/fixtures/console/all-metrics.yaml create mode 100644 src/test/resources/fixtures/console/cyclomatic-only.yaml create mode 100644 src/test/resources/fixtures/console/halstead-only.yaml create mode 100644 src/test/resources/fixtures/console/minimal.yaml create mode 100644 src/test/resources/fixtures/console/nothing-exceeds-single.yaml create mode 100644 src/test/resources/fixtures/console/nothing-exceeds.yaml create mode 100644 src/test/resources/fixtures/console/single-table.yaml create mode 100644 src/test/resources/fixtures/console/threshold.yaml create mode 100644 src/test/resources/fixtures/console/understandability.yaml create mode 100644 src/test/resources/fixtures/console/without-detailed.yaml diff --git a/README.md b/README.md index 5eab639..ff941c1 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,45 @@ java -jar target/cognitive-analysis.jar analyse src/main/java,tools/Generator.ja Directories are searched recursively for `.java` files, skipping hidden directories. A file that cannot be parsed is reported and skipped, and the analysis goes on. +The console output starts with the configuration in use and the cache state, then one table per class: + +```text +Config: built-in +Cache: enabled + +Found 1 files. Starting analysis. + +Class: test.testcode.ClassToAnalyze +File: src/test/resources/fixtures/sample/ClassToAnalyze.java +┌────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ simpleMethod │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ +└────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +``` + +A cell of the detail columns reads `count (weight)`. +The score is red above `scoreThreshold` and green otherwise, Halstead values and risk levels are yellow or red from their thresholds. +Colors are used only on a terminal, and `NO_COLOR` switches them off. +The settings that choose the columns and the grouping are described in [Configuration](./docs/Configuration.md#console-output). + +Order the methods with `--sort-by ` and `--sort-order asc|desc` (default `asc`): + +```bash +java -jar target/cognitive-analysis.jar analyse src/main/java --sort-by score --sort-order desc +``` + +The fields are `score`, `halstead`, `cyclomatic`, `understandability`, `class`, `method`, `file`, the raw counts `lineCount`, `argCount`, `returnCount`, `variableCount`, `propertyCallCount`, `ifCount`, `ifNestingLevel`, `elseCount`, and the weight of each count as `Weight`, for example `ifCountWeight`. +Numbers are compared as numbers and text without regard to letter case; methods with an equal value stay in order of class and method. +Reports follow the same order. +Within a class table the methods keep the sort order, and the class tables themselves are always ordered by class name. + +Use `--debug` to print the time of each stage (`config`, `discovery`, `analysis`, `sorting`, `output`) and the counters `filesFound`, `filesAnalysed`, `filesFailed`, `methodsAnalysed`, `cacheHits` and `cacheMisses` after the run. +On a terminal, a progress line on the error stream shows how many files are analysed. + Write an HTML, CSV or JSON report instead: ```bash diff --git a/docs/Configuration.md b/docs/Configuration.md index 0c4a321..f34573e 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -52,8 +52,9 @@ Options: ## Settings -`metrics`, `excludeFilePatterns`, `excludePatterns` and `cache` affect the analysis today. -The other settings (`scoreThreshold`, `show*`, `groupByClass`, `customReporters`) are parsed and validated, and are applied from a later release. +`metrics`, `excludeFilePatterns`, `excludePatterns` and `cache` affect the analysis. +`scoreThreshold`, `show*` and `groupByClass` shape the console output, see [Console output](#console-output). +`customReporters` is parsed and validated, and is applied from a later release. ```yaml cognitive: @@ -107,6 +108,25 @@ cognitive: Use single quotes in YAML, so a backslash reaches the regular expression unchanged. +## Console output + +These settings change only what the console prints, never the score or the reports. + +| Setting | Effect | +|---|---| +| `scoreThreshold` | A score above it is red, any other score is green. | +| `showOnlyMethodsExceedingThreshold` | Hides the methods whose score is at or below `scoreThreshold`. A class or table without any remaining method is not printed. | +| `groupByClass` | `true` prints `Class:` and `File:` lines and one table per class, ordered by class name. `false` prints `All Methods (N total)` and one table with a leading `Class` column. | +| `showDetailedCognitiveMetrics` | Adds the columns Lines, Arguments, Returns, Variables, Property Accesses, If, If Nesting Level and Else, each as `count (weight)`. | +| `showHalsteadComplexity` | Adds Halstead Volume, Difficulty and Effort with two decimals. Volume is yellow from 100 and red from 1000, difficulty from 10 and 50, effort from 500 and 5000. | +| `showCyclomaticComplexity` | Adds the Cyclomatic Complexity as `n (risk)`. | +| `showUnderstandability` | Adds the Understandability as `n (risk)`. | + +The risk level is yellow for `medium` and red for `high` and `very_high`. +The Cognitive Complexity column is always shown. + +The first lines of the output name the configuration file, relative to the working directory when it lies below it, or `built-in`, and say whether the cache is `enabled` or `disabled`. + ## Cache The analysis caches the metrics of each file, so a file that did not change is not parsed again. diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommand.java b/src/main/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommand.java index c1afe15..05a490a 100644 --- a/src/main/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommand.java +++ b/src/main/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommand.java @@ -3,10 +3,12 @@ import java.io.PrintWriter; import java.nio.file.Path; import java.util.Arrays; +import java.util.Iterator; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.concurrent.Callable; +import java.util.function.BooleanSupplier; +import java.util.function.LongSupplier; import net.floriankraemer.cognitive_analysis.CognitiveAnalysisException; import net.floriankraemer.cognitive_analysis.application.report.CsvReportBuilder; import net.floriankraemer.cognitive_analysis.application.report.HtmlReportBuilder; @@ -15,9 +17,11 @@ import net.floriankraemer.cognitive_analysis.application.report.ReportBuilder.ReportType; import net.floriankraemer.cognitive_analysis.config.CognitiveConfig; import net.floriankraemer.cognitive_analysis.config.ConfigLoader; -import net.floriankraemer.cognitive_analysis.domain.CognitiveMetrics; import net.floriankraemer.cognitive_analysis.domain.CognitiveMetricsFacade; import net.floriankraemer.cognitive_analysis.domain.MetricsCollection; +import net.floriankraemer.cognitive_analysis.domain.MetricsSorter; +import net.floriankraemer.cognitive_analysis.domain.ScoredMethod; +import picocli.CommandLine.Help.Ansi; import picocli.CommandLine.Command; import picocli.CommandLine.Model.CommandSpec; import picocli.CommandLine.Option; @@ -46,6 +50,14 @@ public ReportType convert(final String value) { } } + /** The values of {@code --sort-by}, for the help text. */ + static final class SortFields implements Iterable { + @Override + public Iterator iterator() { + return MetricsSorter.FIELDS.iterator(); + } + } + @Spec CommandSpec spec; @@ -69,7 +81,32 @@ public ReportType convert(final String value) { @Option(names = {"-f", "--report-file"}, description = "File the report is written to. Requires --report-type.") String reportFile; - private final ResultTableBuilder resultTableBuilder = new ResultTableBuilder(); + @Option( + names = "--sort-by", + paramLabel = "", + completionCandidates = SortFields.class, + description = "Sort the methods by a field. Available fields: ${COMPLETION-CANDIDATES}." + ) + String sortBy; + + @Option( + names = "--sort-order", + paramLabel = "", + defaultValue = "asc", + description = "Sort order: asc or desc. Default: ${DEFAULT-VALUE}." + ) + String sortOrder; + + @Option(names = "--debug", description = "Print the time of each stage and statistics after the run.") + boolean debug; + + /** Replaceable by tests: the clock of the stage timings, the colors and the terminal check. */ + LongSupplier ticker = System::nanoTime; + Ansi ansi = Ansi.AUTO; + // Approximation: System.console() is null when stdin or stdout is redirected, so progress may stay off with + // only stderr on a terminal; Java 22 has Console.isTerminal() to check stderr alone. + BooleanSupplier stderrIsTerminal = () -> System.console() != null; + private final ReportBuilder reportBuilder = new ReportBuilder( new HtmlReportBuilder(), new CsvReportBuilder(), new JsonReportBuilder()); @@ -83,17 +120,41 @@ public Integer call() { } try { + final ExecutionSummary summary = new ExecutionSummary(ticker); + final MetricsSorter sorter = new MetricsSorter(sortBy, sortOrder); + final PrintWriter out = spec.commandLine().getOut(); + final CognitiveConfig config = new ConfigLoader(Path.of("")).load(configFile == null ? null : Path.of(configFile)); - final MetricsCollection metrics = - new CognitiveMetricsFacade(config, err, Path.of("")).calculateCognitiveMetrics(paths()); - final PrintWriter out = spec.commandLine().getOut(); + final ConsoleRenderer console = new ConsoleRenderer(config, ansi); + summary.endStage("config"); + + final CognitiveMetricsFacade facade = new CognitiveMetricsFacade(config, err, Path.of("")); + final List files = facade.findFiles(paths()); + console.renderHeader(out, Path.of("")); + out.println("Found " + files.size() + " files. Starting analysis."); + summary.endStage("discovery"); + + final ProgressIndicator progress = new ProgressIndicator(err, stderrIsTerminal.getAsBoolean(), files.size()); + final MetricsCollection analysed = facade.analyse(files, file -> progress.advance()); + progress.finish(); + summary.endStage("analysis"); + + final List methods = sorter.sort(analysed.methods()); + summary.endStage("sorting"); if (reportType != null) { - reportBuilder.build(reportType, reportFile, metrics); + reportBuilder.build(reportType, reportFile, MetricsCollection.of(methods)); out.println("Report generated at: " + reportFile); } else { - renderConsoleOutput(out, metrics); + console.renderMethods(out, methods); + out.println(); + out.println("Cognitive metrics calculated for " + path); + } + summary.endStage("output"); + + if (debug) { + summary.print(out, facade.statistics().asMap()); } return 0; } catch (CognitiveAnalysisException | RuntimeException e) { @@ -115,15 +176,4 @@ private List paths() throws CognitiveAnalysisException { static String describe(final Exception e) { return e.getMessage() != null ? e.getMessage() : e.getClass().getSimpleName(); } - - private void renderConsoleOutput(final PrintWriter out, final MetricsCollection metrics) { - for (Map.Entry> entry : metrics.entrySet()) { - out.println(); - out.println("File: " + entry.getKey()); - out.println(resultTableBuilder.build(entry.getValue())); - } - - out.println(); - out.println("Cognitive metrics calculated for " + path); - } } diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/application/ConsoleRenderer.java b/src/main/java/net/floriankraemer/cognitive_analysis/application/ConsoleRenderer.java new file mode 100644 index 0000000..bb52dcf --- /dev/null +++ b/src/main/java/net/floriankraemer/cognitive_analysis/application/ConsoleRenderer.java @@ -0,0 +1,81 @@ +package net.floriankraemer.cognitive_analysis.application; + +import java.io.PrintWriter; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import net.floriankraemer.cognitive_analysis.config.CognitiveConfig; +import net.floriankraemer.cognitive_analysis.domain.CognitiveMetrics; +import net.floriankraemer.cognitive_analysis.domain.ScoredMethod; +import picocli.CommandLine.Help.Ansi; + +/** Prints the run header and the method tables to the console. */ +final class ConsoleRenderer { + + private final CognitiveConfig config; + private final ResultTableBuilder tables; + + ConsoleRenderer(final CognitiveConfig config, final Ansi ansi) { + this.config = config; + this.tables = new ResultTableBuilder(config, ansi); + } + + /** The configuration in use and the cache state, followed by a blank line. */ + void renderHeader(final PrintWriter out, final Path workingDirectory) { + out.println("Config: " + config.source().map(source -> displayPath(source, workingDirectory)).orElse("built-in")); + out.println("Cache: " + (config.cache().enabled() ? "enabled" : "disabled")); + out.println(); + } + + /** The methods in the given order, grouped by class or in one table, as the configuration says. */ + void renderMethods(final PrintWriter out, final List methods) { + final List shown = methods.stream().filter(this::isShown).toList(); + if (shown.isEmpty()) { + return; + } + if (config.groupByClass()) { + renderByClass(out, shown); + return; + } + out.println(); + out.println("All Methods (" + shown.size() + " total)"); + out.println(tables.buildWithClass(metricsOf(shown))); + } + + private boolean isShown(final ScoredMethod method) { + return !config.showOnlyMethodsExceedingThreshold() + || method.metrics().getCognitiveComplexity() > config.scoreThreshold(); + } + + /** A class is listed once per file, so the same class name in two source roots gets a table for each. */ + private record ClassInFile(String className, String file) {} + + private void renderByClass(final PrintWriter out, final List methods) { + final Map> byClass = new TreeMap<>( + Comparator.comparing(ClassInFile::className).thenComparing(ClassInFile::file)); + for (final ScoredMethod method : methods) { + final ClassInFile key = new ClassInFile(method.metrics().getClassName(), method.file()); + byClass.computeIfAbsent(key, k -> new ArrayList<>()).add(method); + } + byClass.forEach((group, classMethods) -> { + out.println(); + out.println("Class: " + group.className()); + out.println("File: " + group.file()); + out.println(tables.build(metricsOf(classMethods))); + }); + } + + private static List metricsOf(final List methods) { + return methods.stream().map(ScoredMethod::metrics).toList(); + } + + /** Relative to the working directory when the file lies below it, else absolute. */ + private static String displayPath(final Path file, final Path workingDirectory) { + final Path absolute = file.toAbsolutePath().normalize(); + final Path base = workingDirectory.toAbsolutePath().normalize(); + return absolute.startsWith(base) ? base.relativize(absolute).toString() : absolute.toString(); + } +} diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/application/ExecutionSummary.java b/src/main/java/net/floriankraemer/cognitive_analysis/application/ExecutionSummary.java new file mode 100644 index 0000000..0166168 --- /dev/null +++ b/src/main/java/net/floriankraemer/cognitive_analysis/application/ExecutionSummary.java @@ -0,0 +1,45 @@ +package net.floriankraemer.cognitive_analysis.application; + +import java.io.PrintWriter; +import java.util.LinkedHashMap; +import java.util.Locale; +import java.util.Map; +import java.util.function.LongSupplier; + +/** Measures the stages of a run and prints the {@code --debug} summary. */ +final class ExecutionSummary { + + private static final double NANOS_PER_SECOND = 1_000_000_000.0; + + private final LongSupplier ticker; + private final long start; + private long lastMark; + private final Map stages = new LinkedHashMap<>(); + + /** @param ticker the current time in nanoseconds; only differences are used */ + ExecutionSummary(final LongSupplier ticker) { + this.ticker = ticker; + this.start = ticker.getAsLong(); + this.lastMark = start; + } + + /** Ends the stage that began where the previous one ended. */ + void endStage(final String name) { + final long now = ticker.getAsLong(); + stages.put(name, now - lastMark); + lastMark = now; + } + + void print(final PrintWriter out, final Map statistics) { + out.println("Execution Summary:"); + out.println(" Total execution time: " + seconds(lastMark - start)); + out.println("Stage timings:"); + stages.forEach((name, nanos) -> out.println(" " + name + ": " + seconds(nanos))); + out.println("Statistics:"); + statistics.forEach((name, value) -> out.println(" " + name + ": " + value)); + } + + private static String seconds(final long nanos) { + return String.format(Locale.ROOT, "%.3fs", nanos / NANOS_PER_SECOND); + } +} diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/application/MetricFormatter.java b/src/main/java/net/floriankraemer/cognitive_analysis/application/MetricFormatter.java new file mode 100644 index 0000000..6ccfd14 --- /dev/null +++ b/src/main/java/net/floriankraemer/cognitive_analysis/application/MetricFormatter.java @@ -0,0 +1,70 @@ +package net.floriankraemer.cognitive_analysis.application; + +import java.util.Locale; +import picocli.CommandLine.Help.Ansi; + +/** Formats metric values as table cells and colors them by their thresholds. */ +final class MetricFormatter { + + private static final String RED = "red"; + private static final String YELLOW = "yellow"; + private static final String GREEN = "green"; + + private static final double VOLUME_HIGH = 1000; + private static final double VOLUME_MEDIUM = 100; + private static final double DIFFICULTY_HIGH = 50; + private static final double DIFFICULTY_MEDIUM = 10; + private static final double EFFORT_HIGH = 5000; + private static final double EFFORT_MEDIUM = 500; + + private final double scoreThreshold; + private final Ansi ansi; + + /** @param ansi decides whether the colors are emitted or dropped */ + MetricFormatter(final double scoreThreshold, final Ansi ansi) { + this.scoreThreshold = scoreThreshold; + this.ansi = ansi; + } + + String weighted(final int count, final double weight) { + return String.format(Locale.ROOT, "%d (%.3f)", count, weight); + } + + String score(final double score) { + return paint(score > scoreThreshold ? RED : GREEN, String.format(Locale.ROOT, "%.3f", score)); + } + + String halsteadVolume(final double volume) { + return halstead(volume, VOLUME_HIGH, VOLUME_MEDIUM); + } + + String halsteadDifficulty(final double difficulty) { + return halstead(difficulty, DIFFICULTY_HIGH, DIFFICULTY_MEDIUM); + } + + String halsteadEffort(final double effort) { + return halstead(effort, EFFORT_HIGH, EFFORT_MEDIUM); + } + + /** The complexity followed by its risk level in parentheses, e.g. {@code 7 (medium)}. */ + String withRisk(final int complexity, final String riskLevel) { + final String color = switch (riskLevel) { + case "medium" -> YELLOW; + case "high", "very_high" -> RED; + default -> null; + }; + return complexity + " (" + (color == null ? riskLevel : paint(color, riskLevel)) + ")"; + } + + private String halstead(final double value, final double high, final double medium) { + final String text = String.format(Locale.ROOT, "%.2f", value); + if (value >= high) { + return paint(RED, text); + } + return value >= medium ? paint(YELLOW, text) : text; + } + + private String paint(final String color, final String text) { + return ansi.string("@|" + color + " " + text + "|@"); + } +} diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/application/ProgressIndicator.java b/src/main/java/net/floriankraemer/cognitive_analysis/application/ProgressIndicator.java new file mode 100644 index 0000000..0467d3d --- /dev/null +++ b/src/main/java/net/floriankraemer/cognitive_analysis/application/ProgressIndicator.java @@ -0,0 +1,33 @@ +package net.floriankraemer.cognitive_analysis.application; + +import java.io.PrintWriter; + +/** Rewrites one line on the error stream with the number of analysed files; silent when disabled. */ +final class ProgressIndicator { + + private final PrintWriter err; + private final boolean enabled; + private final int total; + private int done; + + ProgressIndicator(final PrintWriter err, final boolean enabled, final int total) { + this.err = err; + this.enabled = enabled; + this.total = total; + } + + void advance() { + done++; + if (enabled) { + err.print("\rAnalysing " + done + "/" + total); + err.flush(); + } + } + + /** Ends the progress line, so later output starts on a fresh one. */ + void finish() { + if (enabled && done > 0) { + err.println(); + } + } +} diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilder.java b/src/main/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilder.java index e441971..d5369e1 100644 --- a/src/main/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilder.java +++ b/src/main/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilder.java @@ -2,41 +2,85 @@ import java.util.ArrayList; import java.util.List; -import java.util.Locale; import java.util.Map; +import java.util.function.Function; +import net.floriankraemer.cognitive_analysis.config.CognitiveConfig; import net.floriankraemer.cognitive_analysis.config.MetricName; import net.floriankraemer.cognitive_analysis.domain.CognitiveMetrics; +import picocli.CommandLine.Help.Ansi; +/** Builds the method table: one row per method, the columns selected by the {@code show*} settings. */ public class ResultTableBuilder { - /** Class, Method, one column per metric in {@link MetricName} order, and the score. */ - private static final List HEADERS = List.of( - "Class", "Method", "Lines", "Arguments", "Returns", "Variables", "Property\nAccesses", - "If", "If Nesting\nLevel", "Else", "Cognitive\nComplexity" - ); + private static final Map DETAIL_HEADERS = Map.of( + MetricName.LINE_COUNT, "Lines", + MetricName.ARG_COUNT, "Arguments", + MetricName.RETURN_COUNT, "Returns", + MetricName.VARIABLE_COUNT, "Variables", + MetricName.PROPERTY_CALL_COUNT, "Property\nAccesses", + MetricName.IF_COUNT, "If", + MetricName.IF_NESTING_LEVEL, "If Nesting\nLevel", + MetricName.ELSE_COUNT, "Else"); - /** Class and Method are left-aligned, all metric columns centered. */ - private static final int FIRST_CENTERED_COLUMN = 2; + private record Column(String header, Function cell) {} - private final TextTable table = new TextTable(FIRST_CENTERED_COLUMN); + private final CognitiveConfig config; + private final MetricFormatter formatter; - public String build(final Map methodMetrics) { - final List> rows = methodMetrics.values().stream().map(this::buildRow).toList(); - return table.render(HEADERS, rows); + public ResultTableBuilder(final CognitiveConfig config, final Ansi ansi) { + this.config = config; + this.formatter = new MetricFormatter(config.scoreThreshold(), ansi); } - private List buildRow(final CognitiveMetrics metrics) { - final List row = new ArrayList<>(); - row.add(metrics.getClassName()); - row.add(metrics.getMethodName()); - for (final MetricName name : MetricName.values()) { - row.add(formatValue(metrics.value(name), metrics.weight(name))); + /** A table of the methods of one class: the method name leads. */ + public String build(final List methods) { + return render(methods, false); + } + + /** A table of methods of several classes: the class name leads and the rows name their class. */ + public String buildWithClass(final List methods) { + return render(methods, true); + } + + private String render(final List methods, final boolean withClass) { + final List columns = new ArrayList<>(); + if (withClass) { + columns.add(new Column("Class", CognitiveMetrics::getClassName)); } - row.add(String.format(Locale.ROOT, "%.3f", metrics.getCognitiveComplexity())); - return row; + columns.addAll(columns()); + + final List> rows = + methods.stream().map(metrics -> columns.stream().map(column -> column.cell().apply(metrics)).toList()).toList(); + // Class and method name are left-aligned, all metric columns centered. + final int firstCenteredColumn = withClass ? 2 : 1; + return new TextTable(firstCenteredColumn).render(columns.stream().map(Column::header).toList(), rows); } - private String formatValue(final int value, final double weight) { - return (weight != 0.0) ? value + "\n" + String.format(Locale.ROOT, "%.3f", weight) : String.valueOf(value); + private List columns() { + final List columns = new ArrayList<>(); + columns.add(new Column("Method Name", CognitiveMetrics::getMethodName)); + if (config.showDetailedCognitiveMetrics()) { + for (final MetricName name : MetricName.values()) { + columns.add(new Column( + DETAIL_HEADERS.get(name), metrics -> formatter.weighted(metrics.value(name), metrics.weight(name)))); + } + } + columns.add(new Column("Cognitive\nComplexity", metrics -> formatter.score(metrics.getCognitiveComplexity()))); + if (config.showHalsteadComplexity()) { + columns.add(new Column("Halstead\nVolume", metrics -> formatter.halsteadVolume(metrics.getHalstead().volume()))); + columns.add(new Column( + "Halstead\nDifficulty", metrics -> formatter.halsteadDifficulty(metrics.getHalstead().difficulty()))); + columns.add(new Column("Halstead\nEffort", metrics -> formatter.halsteadEffort(metrics.getHalstead().effort()))); + } + if (config.showCyclomaticComplexity()) { + columns.add(new Column("Cyclomatic\nComplexity", metrics -> + formatter.withRisk(metrics.getCyclomatic().complexity(), metrics.getCyclomatic().riskLevel()))); + } + if (config.showUnderstandability()) { + columns.add(new Column("Understandability", metrics -> + formatter.withRisk(metrics.getUnderstandability().complexity(), metrics.getUnderstandability().riskLevel()))); + } + // Hook: the baseline delta columns and the coverage column are appended here, after the metric columns. + return columns; } } diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/application/TextTable.java b/src/main/java/net/floriankraemer/cognitive_analysis/application/TextTable.java index 26f5d49..45072b0 100644 --- a/src/main/java/net/floriankraemer/cognitive_analysis/application/TextTable.java +++ b/src/main/java/net/floriankraemer/cognitive_analysis/application/TextTable.java @@ -2,13 +2,19 @@ import java.util.ArrayList; import java.util.List; +import java.util.regex.Pattern; /** * Renders rows of (possibly multi-line) cells as a box-drawing table. - * Column widths follow the widest line of each column. + * Column widths follow the widest line of each column, ANSI color codes not counted. */ public final class TextTable { + private static final Pattern ANSI_CODE = Pattern.compile("\u001B\\[[0-9;]*m"); + + /** Spaces between the border and the text of a cell, on each side. */ + private static final int PADDING = 1; + /** Columns from this index on are centered; earlier ones are left-aligned. */ private final int firstCenteredColumn; @@ -41,7 +47,7 @@ private int[] columnWidths(final List> rows, final int columns) { for (List row : rows) { for (int c = 0; c < columns; c++) { for (String line : row.get(c).split("\n", -1)) { - widths[c] = Math.max(widths[c], line.length()); + widths[c] = Math.max(widths[c], visibleLength(line)); } } } @@ -63,17 +69,21 @@ private void appendRow(final StringBuilder out, final List row, final in } private String pad(final String text, final int width, final boolean center) { - final int space = width - text.length(); + final int space = width - visibleLength(text); final int left = center ? space / 2 : 0; - return " ".repeat(left) + text + " ".repeat(space - left); + return " ".repeat(PADDING + left) + text + " ".repeat(PADDING + space - left); } private String border(final char left, final char middle, final char right, final int[] widths) { final StringBuilder line = new StringBuilder().append(left); for (int c = 0; c < widths.length; c++) { - line.append("─".repeat(widths[c])); + line.append("─".repeat(widths[c] + 2 * PADDING)); line.append(c < widths.length - 1 ? middle : right); } return line.toString(); } + + private static int visibleLength(final String text) { + return ANSI_CODE.matcher(text).replaceAll("").length(); + } } diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/domain/AnalysisStatistics.java b/src/main/java/net/floriankraemer/cognitive_analysis/domain/AnalysisStatistics.java new file mode 100644 index 0000000..4bfcd40 --- /dev/null +++ b/src/main/java/net/floriankraemer/cognitive_analysis/domain/AnalysisStatistics.java @@ -0,0 +1,48 @@ +package net.floriankraemer.cognitive_analysis.domain; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** Counters of the analysis runs of one facade, for the {@code --debug} summary. */ +public final class AnalysisStatistics { + + private int filesFound; + private int filesAnalysed; + private int filesFailed; + private int methodsAnalysed; + private int cacheHits; + private int cacheMisses; + + void filesFound(final int count) { + filesFound = count; + } + + void fileAnalysed(final int methods) { + filesAnalysed++; + methodsAnalysed += methods; + } + + void fileFailed() { + filesFailed++; + } + + void cacheHit() { + cacheHits++; + } + + void cacheMiss() { + cacheMisses++; + } + + /** The counters by name, in the order to print them. */ + public Map asMap() { + final Map counters = new LinkedHashMap<>(); + counters.put("filesFound", filesFound); + counters.put("filesAnalysed", filesAnalysed); + counters.put("filesFailed", filesFailed); + counters.put("methodsAnalysed", methodsAnalysed); + counters.put("cacheHits", cacheHits); + counters.put("cacheMisses", cacheMisses); + return counters; + } +} diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/domain/CognitiveMetricsFacade.java b/src/main/java/net/floriankraemer/cognitive_analysis/domain/CognitiveMetricsFacade.java index 8ef5c42..9409aa0 100644 --- a/src/main/java/net/floriankraemer/cognitive_analysis/domain/CognitiveMetricsFacade.java +++ b/src/main/java/net/floriankraemer/cognitive_analysis/domain/CognitiveMetricsFacade.java @@ -11,6 +11,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.function.Consumer; import net.floriankraemer.cognitive_analysis.CognitiveAnalysisException; import net.floriankraemer.cognitive_analysis.config.CognitiveConfig; @@ -23,6 +24,7 @@ public class CognitiveMetricsFacade { private final CognitiveMetricsCollector collector = new CognitiveMetricsCollector(); private final ComplexityCalculator calculator; private final MetricsCache cache; + private final AnalysisStatistics statistics = new AnalysisStatistics(); /** * @param warnings receives a line per file that cannot be parsed, and one line when the cache cannot be written @@ -49,14 +51,38 @@ public CognitiveMetricsFacade( */ public MetricsCollection calculateCognitiveMetrics(final List paths) throws CognitiveAnalysisException { + return analyse(findFiles(paths), file -> { }); + } + + /** The Java files of the given paths, each once and sorted, without the excluded ones. */ + public List findFiles(final List paths) throws CognitiveAnalysisException { + final List files = fileFinder.findJavaFiles(paths, config.excludeFilePatterns()); + statistics.filesFound(files.size()); + return files; + } + + /** The counters of the runs of this facade. */ + public AnalysisStatistics statistics() { + return statistics; + } + + /** + * Analyses the given files, see {@link #calculateCognitiveMetrics}. + * + * @param processed called after each file, also after one that cannot be parsed + */ + public MetricsCollection analyse(final List files, final Consumer processed) + throws CognitiveAnalysisException { final MetricsCollection result = new MetricsCollection(); - for (final Path file : fileFinder.findJavaFiles(paths, config.excludeFilePatterns())) { + for (final Path file : files) { final Map collected; try { collected = collect(file); } catch (SourceParseException e) { + statistics.fileFailed(); warnings.println("Parser failed for file " + file + ": " + e.getMessage()); + processed.accept(file); continue; } @@ -67,9 +93,11 @@ public MetricsCollection calculateCognitiveMetrics(final List paths) methods.put(key, metrics); } }); + statistics.fileAnalysed(methods.size()); if (!methods.isEmpty()) { result.put(file.toString(), methods); } + processed.accept(file); } return result; } @@ -85,8 +113,12 @@ private Map collect(final Path file) final Optional key = cache.keyOf(file, content); final Optional> cached = key.flatMap(cache::load); if (cached.isPresent()) { + statistics.cacheHit(); return cached.get(); } + if (key.isPresent()) { + statistics.cacheMiss(); + } final Map collected = collector.collect(decode(file, content)); key.ifPresent(cacheKey -> cache.store(cacheKey, file, collected)); return collected; diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/domain/MetricsCollection.java b/src/main/java/net/floriankraemer/cognitive_analysis/domain/MetricsCollection.java index 7bf713c..4b94e15 100644 --- a/src/main/java/net/floriankraemer/cognitive_analysis/domain/MetricsCollection.java +++ b/src/main/java/net/floriankraemer/cognitive_analysis/domain/MetricsCollection.java @@ -1,9 +1,28 @@ package net.floriankraemer.cognitive_analysis.domain; +import java.util.ArrayList; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; public class MetricsCollection extends LinkedHashMap> { private static final long serialVersionUID = 1L; + + /** All methods, file by file in collection order. */ + public List methods() { + final List methods = new ArrayList<>(); + forEach((file, fileMethods) -> + fileMethods.forEach((key, metrics) -> methods.add(new ScoredMethod(file, key, metrics)))); + return methods; + } + + /** Groups the methods by file; files and the methods in them keep the order of their first appearance. */ + public static MetricsCollection of(final List methods) { + final MetricsCollection collection = new MetricsCollection(); + for (final ScoredMethod method : methods) { + collection.computeIfAbsent(method.file(), file -> new LinkedHashMap<>()).put(method.key(), method.metrics()); + } + return collection; + } } diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/domain/MetricsSorter.java b/src/main/java/net/floriankraemer/cognitive_analysis/domain/MetricsSorter.java new file mode 100644 index 0000000..59e64dd --- /dev/null +++ b/src/main/java/net/floriankraemer/cognitive_analysis/domain/MetricsSorter.java @@ -0,0 +1,92 @@ +package net.floriankraemer.cognitive_analysis.domain; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.function.Function; +import java.util.function.ToDoubleFunction; +import net.floriankraemer.cognitive_analysis.CognitiveAnalysisException; +import net.floriankraemer.cognitive_analysis.config.MetricName; + +/** + * Orders methods by one field. Numbers are compared numerically, text ignoring the letter case. Methods with + * an equal value stay in ascending order of class and then method, in either direction. + */ +public final class MetricsSorter { + + private static final Map> COMPARATORS = comparators(); + + /** The names accepted by {@code --sort-by}, in the order to list them. */ + public static final List FIELDS = List.copyOf(COMPARATORS.keySet()); + + private static final Comparator TIE_BREAK = + text(method -> method.metrics().getClassName()).thenComparing(text(method -> method.metrics().getMethodName())); + + private final Comparator comparator; + + /** + * @param field one of {@link #FIELDS}, or null to keep the given order + * @param order {@code asc} or {@code desc}, in any letter case + * @throws CognitiveAnalysisException for an unknown field or order; the order is checked without a field too + */ + public MetricsSorter(final String field, final String order) throws CognitiveAnalysisException { + if (field != null && !COMPARATORS.containsKey(field)) { + throw new CognitiveAnalysisException( + "Invalid sort field \"" + field + "\". Available fields: " + String.join(", ", FIELDS)); + } + final boolean descending = isDescending(order); + if (field == null) { + comparator = null; + return; + } + final Comparator primary = COMPARATORS.get(field); + comparator = (descending ? primary.reversed() : primary).thenComparing(TIE_BREAK); + } + + /** @return a new list in the requested order; the given list itself when there is no field to sort by */ + public List sort(final List methods) { + if (comparator == null) { + return methods; + } + final List sorted = new ArrayList<>(methods); + sorted.sort(comparator); + return sorted; + } + + private static boolean isDescending(final String order) throws CognitiveAnalysisException { + final String normalized = order.toLowerCase(Locale.ROOT); + if (!normalized.equals("asc") && !normalized.equals("desc")) { + throw new CognitiveAnalysisException("Sort order must be \"asc\" or \"desc\", got \"" + order + "\""); + } + return normalized.equals("desc"); + } + + private static Map> comparators() { + final Map> fields = new LinkedHashMap<>(); + fields.put("score", numeric(method -> method.metrics().getCognitiveComplexity())); + fields.put("halstead", numeric(method -> method.metrics().getHalstead().volume())); + fields.put("cyclomatic", numeric(method -> method.metrics().getCyclomatic().complexity())); + fields.put("understandability", numeric(method -> method.metrics().getUnderstandability().complexity())); + fields.put("class", text(method -> method.metrics().getClassName())); + fields.put("method", text(method -> method.metrics().getMethodName())); + fields.put("file", text(ScoredMethod::file)); + for (final MetricName name : MetricName.values()) { + fields.put(name.key(), numeric(method -> method.metrics().value(name))); + } + for (final MetricName name : MetricName.values()) { + fields.put(name.key() + "Weight", numeric(method -> method.metrics().weight(name))); + } + return fields; + } + + private static Comparator numeric(final ToDoubleFunction value) { + return Comparator.comparingDouble(value); + } + + private static Comparator text(final Function value) { + return Comparator.comparing(value, String.CASE_INSENSITIVE_ORDER); + } +} diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/domain/ScoredMethod.java b/src/main/java/net/floriankraemer/cognitive_analysis/domain/ScoredMethod.java new file mode 100644 index 0000000..98361f5 --- /dev/null +++ b/src/main/java/net/floriankraemer/cognitive_analysis/domain/ScoredMethod.java @@ -0,0 +1,9 @@ +package net.floriankraemer.cognitive_analysis.domain; + +/** + * One analysed method with the file it was found in. + * + * @param file the path of the file as it was discovered + * @param key the method key {@code pkg.Class::method} + */ +public record ScoredMethod(String file, String key, CognitiveMetrics metrics) {} diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.java b/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.java index 56b4b39..1f586dc 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.java +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.java @@ -81,7 +81,7 @@ void failsWhenAFileCannotBeRead() throws Exception { int exitCode = run("analyse", tempDir.toString()); assertThat(exitCode).isEqualTo(1); - assertThat(out.toString()).isEmpty(); + assertThat(out.toString()).doesNotContain("┌").doesNotContain("Cognitive metrics calculated"); assertThat(err.toString()).isEqualTo("Error reading file: " + broken + System.lineSeparator()); } @@ -156,6 +156,7 @@ void analysesACommaSeparatedListOfFilesAndDirectoriesOnceEachInPathOrder() { .containsExactly( "File: src/test/resources/fixtures/multi/Alpha.java", "File: src/test/resources/fixtures/multi/Beta.java", + "File: src/test/resources/fixtures/multi/Alpha.java", "File: " + FIXTURE_DIR + "/ClassToAnalyze.java"); } @@ -167,12 +168,12 @@ void reportsTheSameClassAndMethodInDifferentFilesForEachFile() { assertThat(exitCode).isZero(); assertThat(err.toString()).isEmpty(); - assertThat(out.toString().lines().filter(line -> line.startsWith("File: ") || line.startsWith("│Main"))) + assertThat(out.toString().lines().filter(line -> line.startsWith("File: ") || line.startsWith("│ main"))) .containsExactly( "File: " + dir + "/m1/Main.java", - "│Main │main │ 3 │ 1 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │", + "│ main │ 3 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │", "File: " + dir + "/m2/Main.java", - "│Main │main │ 5 │ 1 │ 0 │ 0 │ 1 │1 │ 1 │ 0 │ 0.000 │"); + "│ main │ 5 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │"); } @Test @@ -199,8 +200,14 @@ void printsOnlyTheSummaryForAnEmptyDirectory() { assertThat(exitCode).isZero(); assertThat(err.toString()).isEmpty(); - assertThat(out.toString()).isEqualTo( - System.lineSeparator() + "Cognitive metrics calculated for " + tempDir + System.lineSeparator()); + assertThat(out.toString()).isEqualTo(""" + Config: src/test/resources/fixtures/no-cache.yaml + Cache: disabled + + Found 0 files. Starting analysis. + + Cognitive metrics calculated for %s + """.formatted(tempDir)); } @Test @@ -211,9 +218,9 @@ void appliesTheFileAndMethodExcludePatternsOfTheConfig() { assertThat(err.toString()).isEmpty(); assertThat(out.toString()) .contains("File: src/test/resources/fixtures/multi/Alpha.java") - .contains("│second") + .contains("│ second") .doesNotContain("Beta.java") - .doesNotContain("│first") + .doesNotContain("│ first") .doesNotContain("multi.Helper"); } @@ -333,7 +340,8 @@ void writesAnHtmlReport() throws Exception { int exitCode = run("analyse", FIXTURE_DIR, "-r", "html", "-f", report.toString()); assertThat(exitCode).isZero(); - assertThat(out.toString()).isEqualTo("Report generated at: " + report + System.lineSeparator()); + assertThat(out.toString()).endsWith("Report generated at: " + report + System.lineSeparator()); + assertThat(out.toString()).doesNotContain("┌"); assertThat(Files.readString(report)) .startsWith("") .contains("test.testcode.ClassToAnalyze") diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsFilesAndMethodsInStableSortedOrder.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsFilesAndMethodsInStableSortedOrder.approved.txt index 9e7d4f2..866bf41 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsFilesAndMethodsInStableSortedOrder.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsFilesAndMethodsInStableSortedOrder.approved.txt @@ -1,24 +1,37 @@ +Config: src/test/resources/fixtures/no-cache.yaml +Cache: disabled +Found 2 files. Starting analysis. + +Class: multi.Alpha File: src/test/resources/fixtures/multi/Alpha.java -┌────────────┬──────┬─────┬─────────┬───────┬─────────┬────────┬──┬──────────┬────┬──────────┐ -│Class │Method│Lines│Arguments│Returns│Variables│Property│If│If Nesting│Else│Cognitive │ -│ │ │ │ │ │ │Accesses│ │ Level │ │Complexity│ -├────────────┼──────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│multi.Alpha │second│ 3 │ 0 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────┼──────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│multi.Alpha │first │ 3 │ 0 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────┼──────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│multi.Helper│run │ 5 │ 2 │ 0 │ 0 │ 0 │1 │ 1 │ 0 │ 0.000 │ -└────────────┴──────┴─────┴─────────┴───────┴─────────┴────────┴──┴──────────┴────┴──────────┘ +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ second │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ first │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +Class: multi.Beta File: src/test/resources/fixtures/multi/Beta.java -┌──────────┬──────┬─────┬─────────┬───────┬─────────┬────────┬──┬──────────┬────┬──────────┐ -│Class │Method│Lines│Arguments│Returns│Variables│Property│If│If Nesting│Else│Cognitive │ -│ │ │ │ │ │ │Accesses│ │ Level │ │Complexity│ -├──────────┼──────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│multi.Beta│zulu │ 3 │ 0 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├──────────┼──────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│multi.Beta│alpha │ 3 │ 0 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -└──────────┴──────┴─────┴─────────┴───────┴─────────┴────────┴──┴──────────┴────┴──────────┘ +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ zulu │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ alpha │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ + +Class: multi.Helper +File: src/test/resources/fixtures/multi/Alpha.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ run │ 5 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ Cognitive metrics calculated for src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsOneTablePerFileToTheConsole.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsOneTablePerFileToTheConsole.approved.txt index 579833a..b6d4b73 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsOneTablePerFileToTheConsole.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsOneTablePerFileToTheConsole.approved.txt @@ -1,13 +1,17 @@ +Config: src/test/resources/fixtures/no-cache.yaml +Cache: disabled +Found 1 files. Starting analysis. + +Class: test.testcode.ClassToAnalyze File: src/test/resources/fixtures/sample/ClassToAnalyze.java -┌────────────────────────────┬──────────────────────┬─────┬─────────┬───────┬─────────┬────────┬──┬──────────┬─────┬──────────┐ -│Class │Method │Lines│Arguments│Returns│Variables│Property│If│If Nesting│Else │Cognitive │ -│ │ │ │ │ │ │Accesses│ │ Level │ │Complexity│ -├────────────────────────────┼──────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼─────┼──────────┤ -│test.testcode.ClassToAnalyze│simpleMethod │ 3 │ 0 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────┼──────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼─────┼──────────┤ -│test.testcode.ClassToAnalyze│methodWithTwoArguments│ 16 │ 2 │ 0 │ 0 │ 0 │3 │ 3 │ 3 │ 2.197 │ -│ │ │ │ │ │ │ │ │ 1.099 │1.099│ │ -└────────────────────────────┴──────────────────────┴─────┴─────────┴───────┴─────────┴────────┴──┴──────────┴─────┴──────────┘ +┌────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ simpleMethod │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ +└────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ Cognitive metrics calculated for src/test/resources/fixtures/sample diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsTheMetricsOfEveryJavaConstruct.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsTheMetricsOfEveryJavaConstruct.approved.txt index f66a9db..1428c68 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsTheMetricsOfEveryJavaConstruct.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsTheMetricsOfEveryJavaConstruct.approved.txt @@ -1,130 +1,181 @@ +Config: src/test/resources/fixtures/no-cache.yaml +Cache: disabled +Found 6 files. Starting analysis. + +Class: fixtures.cognitive.IfStatements File: src/test/resources/fixtures/cognitive/IfStatements.java -┌───────────────────────────────┬────────────────────────────┬─────┬─────────┬───────┬─────────┬────────┬─────┬──────────┬─────┬──────────┐ -│Class │Method │Lines│Arguments│Returns│Variables│Property│ If │If Nesting│Else │Cognitive │ -│ │ │ │ │ │ │Accesses│ │ Level │ │Complexity│ -├───────────────────────────────┼────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼─────┼──────────┼─────┼──────────┤ -│fixtures.cognitive.IfStatements│chain │ 11 │ 1 │ 4 │ 0 │ 0 │ 1 │ 1 │ 3 │ 1.435 │ -│ │ │ │ │ 0.336 │ │ │ │ │1.099│ │ -├───────────────────────────────┼────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼─────┼──────────┼─────┼──────────┤ -│fixtures.cognitive.IfStatements│nestedInThenAndElse │ 15 │ 3 │ 0 │ 0 │ 0 │ 4 │ 3 │ 2 │ 2.485 │ -│ │ │ │ │ │ │ │0.693│ 1.099 │0.693│ │ -├───────────────────────────────┼────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼─────┼──────────┼─────┼──────────┤ -│fixtures.cognitive.IfStatements│elseIfBodyNests │ 9 │ 1 │ 0 │ 0 │ 0 │ 2 │ 2 │ 1 │ 0.693 │ -│ │ │ │ │ │ │ │ │ 0.693 │ │ │ -├───────────────────────────────┼────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼─────┼──────────┼─────┼──────────┤ -│fixtures.cognitive.IfStatements│braceElseIf │ 9 │ 1 │ 0 │ 0 │ 0 │ 2 │ 2 │ 1 │ 0.693 │ -│ │ │ │ │ │ │ │ │ 0.693 │ │ │ -├───────────────────────────────┼────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼─────┼──────────┼─────┼──────────┤ -│fixtures.cognitive.IfStatements│ifsInLoopsTrySwitchAndLambda│ 39 │ 1 │ 0 │ 3 │ 0 │ 7 │ 1 │ 0 │ 1.609 │ -│ │ │ │ │ │ │ │1.609│ │ │ │ -├───────────────────────────────┼────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼─────┼──────────┼─────┼──────────┤ -│fixtures.cognitive.IfStatements│ternariesDoNotCount │ 4 │ 1 │ 1 │ 1 │ 0 │ 0 │ 0 │ 0 │ 0.000 │ -├───────────────────────────────┼────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼─────┼──────────┼─────┼──────────┤ -│fixtures.cognitive.IfStatements│ifInsideLambdaInsideIf │ 9 │ 1 │ 0 │ 1 │ 0 │ 2 │ 2 │ 0 │ 0.693 │ -│ │ │ │ │ │ │ │ │ 0.693 │ │ │ -├───────────────────────────────┼────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼─────┼──────────┼─────┼──────────┤ -│fixtures.cognitive.IfStatements│log │ 3 │ 1 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0.000 │ -└───────────────────────────────┴────────────────────────────┴─────┴─────────┴───────┴─────────┴────────┴─────┴──────────┴─────┴──────────┘ +┌──────────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├──────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ chain │ 11 (0.000) │ 1 (0.000) │ 4 (0.336) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 3 (1.099) │ 1.435 │ +├──────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ nestedInThenAndElse │ 15 (0.000) │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 4 (0.693) │ 3 (1.099) │ 2 (0.693) │ 2.485 │ +├──────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ elseIfBodyNests │ 9 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 2 (0.000) │ 2 (0.693) │ 1 (0.000) │ 0.693 │ +├──────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ braceElseIf │ 9 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 2 (0.000) │ 2 (0.693) │ 1 (0.000) │ 0.693 │ +├──────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ ifsInLoopsTrySwitchAndLambda │ 39 (0.000) │ 1 (0.000) │ 0 (0.000) │ 3 (0.000) │ 0 (0.000) │ 7 (1.609) │ 1 (0.000) │ 0 (0.000) │ 1.609 │ +├──────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ ternariesDoNotCount │ 4 (0.000) │ 1 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├──────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ ifInsideLambdaInsideIf │ 9 (0.000) │ 1 (0.000) │ 0 (0.000) │ 1 (0.000) │ 0 (0.000) │ 2 (0.000) │ 2 (0.693) │ 0 (0.000) │ 0.693 │ +├──────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ log │ 3 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +└──────────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ + +Class: fixtures.cognitive.ModernJava +File: src/test/resources/fixtures/cognitive/ModernJava.java +┌───────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├───────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ switchExpression │ 13 (0.000) │ 1 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ +├───────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ patternInstanceof │ 8 (0.000) │ 1 (0.000) │ 3 (0.182) │ 2 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0.182 │ +├───────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ patternSwitch │ 7 (0.000) │ 1 (0.000) │ 1 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├───────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ textBlock │ 7 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├───────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ unnamedVariables │ 9 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ +└───────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +Class: fixtures.cognitive.PartiallyIgnored File: src/test/resources/fixtures/cognitive/Ignored.java -┌──────────────────────────────────────────────┬──────┬─────┬─────────┬───────┬─────────┬────────┬──┬──────────┬────┬──────────┐ -│Class │Method│Lines│Arguments│Returns│Variables│Property│If│If Nesting│Else│Cognitive │ -│ │ │ │ │ │ │Accesses│ │ Level │ │Complexity│ -├──────────────────────────────────────────────┼──────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.PartiallyIgnored │kept │ 3 │ 0 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├──────────────────────────────────────────────┼──────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.PartiallyIgnored.KeptNested│kept │ 2 │ 0 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -└──────────────────────────────────────────────┴──────┴─────┴─────────┴───────┴─────────┴────────┴──┴──────────┴────┴──────────┘ +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ kept │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ -File: src/test/resources/fixtures/cognitive/ModernJava.java -┌─────────────────────────────┬─────────────────┬─────┬─────────┬───────┬─────────┬────────┬──┬──────────┬────┬──────────┐ -│Class │Method │Lines│Arguments│Returns│Variables│Property│If│If Nesting│Else│Cognitive │ -│ │ │ │ │ │ │Accesses│ │ Level │ │Complexity│ -├─────────────────────────────┼─────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.ModernJava│switchExpression │ 13 │ 1 │ 1 │ 1 │ 0 │1 │ 1 │ 0 │ 0.000 │ -├─────────────────────────────┼─────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.ModernJava│patternInstanceof│ 8 │ 1 │ 3 │ 2 │ 0 │1 │ 1 │ 1 │ 0.182 │ -│ │ │ │ │ 0.182 │ │ │ │ │ │ │ -├─────────────────────────────┼─────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.ModernJava│patternSwitch │ 7 │ 1 │ 1 │ 2 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├─────────────────────────────┼─────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.ModernJava│textBlock │ 7 │ 0 │ 1 │ 1 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├─────────────────────────────┼─────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.ModernJava│unnamedVariables │ 9 │ 1 │ 0 │ 0 │ 0 │1 │ 1 │ 0 │ 0.000 │ -└─────────────────────────────┴─────────────────┴─────┴─────────┴───────┴─────────┴────────┴──┴──────────┴────┴──────────┘ +Class: fixtures.cognitive.PartiallyIgnored.KeptNested +File: src/test/resources/fixtures/cognitive/Ignored.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ kept │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +Class: fixtures.cognitive.Returns File: src/test/resources/fixtures/cognitive/Returns.java -┌──────────────────────────┬───────────────────────┬─────┬─────────┬───────┬─────────┬────────┬──┬──────────┬────┬──────────┐ -│Class │Method │Lines│Arguments│Returns│Variables│Property│If│If Nesting│Else│Cognitive │ -│ │ │ │ │ │ │Accesses│ │ Level │ │Complexity│ -├──────────────────────────┼───────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Returns│returnsInLambdas │ 10 │ 0 │ 3 │ 3 │ 0 │1 │ 1 │ 0 │ 0.182 │ -│ │ │ │ │ 0.182 │ │ │ │ │ │ │ -├──────────────────────────┼───────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Returns│anonymousClassIsSkipped│ 15 │ 1 │ 1 │ 2 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├──────────────────────────┼───────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Returns│localClassIsSkipped │ 18 │ 1 │ 1 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -└──────────────────────────┴───────────────────────┴─────┴─────────┴───────┴─────────┴────────┴──┴──────────┴────┴──────────┘ +┌─────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ returnsInLambdas │ 10 (0.000) │ 0 (0.000) │ 3 (0.182) │ 3 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.182 │ +├─────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ anonymousClassIsSkipped │ 15 (0.000) │ 1 (0.000) │ 1 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├─────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ localClassIsSkipped │ 18 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +└─────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ + +Class: fixtures.cognitive.Units +File: src/test/resources/fixtures/cognitive/Units.java +┌──────────────────────────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├──────────────────────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ Units() │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├──────────────────────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ Units(int) │ 3 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├──────────────────────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ abstractMethod │ 1 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├──────────────────────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ overloaded() │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├──────────────────────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ overloaded(List,Map) │ 2 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├──────────────────────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ overloaded(String...) │ 2 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├──────────────────────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ overloaded(int[],java.util.List) │ 2 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├──────────────────────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ generic │ 3 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +└──────────────────────────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ + +Class: fixtures.cognitive.Units.Color +File: src/test/resources/fixtures/cognitive/Units.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ code │ 3 (0.000) │ 0 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ + +Class: fixtures.cognitive.Units.Inner +File: src/test/resources/fixtures/cognitive/Units.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ Inner │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ + +Class: fixtures.cognitive.Units.Point +File: src/test/resources/fixtures/cognitive/Units.java +┌────────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ Point(int,int) │ 5 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ +├────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ Point(int) │ 3 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ sum │ 3 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +└────────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ + +Class: fixtures.cognitive.Units.Shape +File: src/test/resources/fixtures/cognitive/Units.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ describe │ 3 (0.000) │ 0 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ unit │ 3 (0.000) │ 0 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ helper │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ + +Class: fixtures.cognitive.Units.StaticNested +File: src/test/resources/fixtures/cognitive/Units.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ inStatic │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +Class: fixtures.cognitive.Units.StaticNested.Deeper File: src/test/resources/fixtures/cognitive/Units.java -┌────────────────────────────────────────────┬────────────────────────────────┬─────┬─────────┬───────┬─────────┬────────┬──┬──────────┬────┬──────────┐ -│Class │Method │Lines│Arguments│Returns│Variables│Property│If│If Nesting│Else│Cognitive │ -│ │ │ │ │ │ │Accesses│ │ Level │ │Complexity│ -├────────────────────────────────────────────┼────────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Units │Units() │ 2 │ 0 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────────────────────┼────────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Units │Units(int) │ 3 │ 1 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────────────────────┼────────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Units │abstractMethod │ 1 │ 2 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────────────────────┼────────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Units │overloaded() │ 2 │ 0 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────────────────────┼────────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Units │overloaded(List,Map) │ 2 │ 2 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────────────────────┼────────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Units │overloaded(String...) │ 2 │ 1 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────────────────────┼────────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Units │overloaded(int[],java.util.List)│ 2 │ 2 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────────────────────┼────────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Units │generic │ 3 │ 1 │ 1 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────────────────────┼────────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Units.StaticNested │inStatic │ 2 │ 0 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────────────────────┼────────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Units.StaticNested.Deeper│inDeeper │ 2 │ 0 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────────────────────┼────────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Units.Inner │Inner │ 2 │ 0 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────────────────────┼────────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Units.Color │code │ 3 │ 0 │ 1 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────────────────────┼────────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Units.Point │Point(int,int) │ 5 │ 2 │ 0 │ 0 │ 0 │1 │ 1 │ 0 │ 0.000 │ -├────────────────────────────────────────────┼────────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Units.Point │Point(int) │ 3 │ 1 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────────────────────┼────────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Units.Point │sum │ 3 │ 0 │ 1 │ 1 │ 2 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────────────────────┼────────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Units.Shape │describe │ 3 │ 0 │ 1 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────────────────────┼────────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Units.Shape │unit │ 3 │ 0 │ 1 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────────────────────┼────────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Units.Shape │helper │ 2 │ 0 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -└────────────────────────────────────────────┴────────────────────────────────┴─────┴─────────┴───────┴─────────┴────────┴──┴──────────┴────┴──────────┘ +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ inDeeper │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +Class: fixtures.cognitive.Variables File: src/test/resources/fixtures/cognitive/Variables.java -┌────────────────────────────┬──────────────────────────────┬─────┬─────────┬───────┬─────────┬────────┬──┬──────────┬────┬──────────┐ -│Class │Method │Lines│Arguments│Returns│Variables│Property│If│If Nesting│Else│Cognitive │ -│ │ │ │ │ │ │Accesses│ │ Level │ │Complexity│ -├────────────────────────────┼──────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Variables│distinctNames │ 12 │ 1 │ 1 │ 3 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────┼──────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Variables│lambdaCatchAndForEachVariables│ 17 │ 1 │ 0 │ 4 │ 0 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────┼──────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Variables│fieldAccess │ 6 │ 1 │ 1 │ 2 │ 4 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────┼──────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Variables│thisCountsOnce │ 6 │ 0 │ 0 │ 1 │ 1 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────┼──────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Variables│shadowsField │ 4 │ 0 │ 1 │ 2 │ 1 │0 │ 0 │ 0 │ 0.000 │ -├────────────────────────────┼──────────────────────────────┼─────┼─────────┼───────┼─────────┼────────┼──┼──────────┼────┼──────────┤ -│fixtures.cognitive.Variables│helper │ 2 │ 1 │ 0 │ 0 │ 0 │0 │ 0 │ 0 │ 0.000 │ -└────────────────────────────┴──────────────────────────────┴─────┴─────────┴───────┴─────────┴────────┴──┴──────────┴────┴──────────┘ +┌────────────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├────────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ distinctNames │ 12 (0.000) │ 1 (0.000) │ 1 (0.000) │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├────────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ lambdaCatchAndForEachVariables │ 17 (0.000) │ 1 (0.000) │ 0 (0.000) │ 4 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├────────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ fieldAccess │ 6 (0.000) │ 1 (0.000) │ 1 (0.000) │ 2 (0.000) │ 4 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├────────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ thisCountsOnce │ 6 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├────────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ shadowsField │ 4 (0.000) │ 0 (0.000) │ 1 (0.000) │ 2 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├────────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ helper │ 2 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +└────────────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ Cognitive metrics calculated for src/test/resources/fixtures/cognitive diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.java b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.java new file mode 100644 index 0000000..ad4e1df --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.java @@ -0,0 +1,426 @@ +package net.floriankraemer.cognitive_analysis.application; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; +import net.floriankraemer.cognitive_analysis.App; +import net.floriankraemer.cognitive_analysis.domain.MetricsSorter; +import org.approvaltests.Approvals; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import picocli.CommandLine; +import picocli.CommandLine.Help.Ansi; + +/** The console output of {@code analyse}: header, tables per option combination, sorting, progress and debug. */ +class ConsoleOutputE2ETest { + + private static final String FIXTURES = "src/test/resources/fixtures"; + private static final String SOURCES = FIXTURES + "/sample," + FIXTURES + "/multi"; + private static final String NO_CACHE = FIXTURES + "/no-cache.yaml"; + private static final String PARSE_ERROR = FIXTURES + "/parse-error"; + + @TempDir + Path tempDir; + + private final StringWriter out = new StringWriter(); + private final StringWriter err = new StringWriter(); + private Ansi ansi = Ansi.OFF; + private boolean terminal; + private AtomicLong now; + + // --- golden files, one per combination of the console options --- + + @Test + void printsTheDefaultTables() { + verifyGolden(NO_CACHE); + } + + @Test + void printsAllMetrics() { + verifyGolden(config("all-metrics")); + } + + @Test + void printsCyclomaticComplexityOnly() { + verifyGolden(config("cyclomatic-only")); + } + + @Test + void printsHalsteadComplexityOnly() { + verifyGolden(config("halstead-only")); + } + + @Test + void printsUnderstandability() { + verifyGolden(config("understandability")); + } + + @Test + void printsTheMinimalColumns() { + verifyGolden(config("minimal")); + } + + @Test + void printsTheMetricsWithoutTheDetailColumns() { + verifyGolden(config("without-detailed")); + } + + @Test + void printsOneSingleTableWithTheClassColumn() { + verifyGolden(config("single-table")); + } + + @Test + void printsOnlyTheMethodsExceedingTheThreshold() { + verifyGolden(config("threshold")); + } + + @Test + void printsNoTableWhenNoMethodExceedsTheThreshold() { + assertThat(run("analyse", SOURCES, "-c", config("nothing-exceeds"))).isZero(); + + assertThat(out.toString()).doesNotContain("Class:").doesNotContain("┌"); + assertThat(out.toString()).contains("Found 3 files. Starting analysis."); + } + + @Test + void printsNoSingleTableWhenNoMethodExceedsTheThreshold() { + assertThat(run("analyse", SOURCES, "-c", config("nothing-exceeds-single"))).isZero(); + + assertThat(out.toString()).doesNotContain("All Methods").doesNotContain("┌"); + } + + @Test + void countsOnlyTheShownMethodsInTheSingleTableTitle() { + assertThat(run("analyse", SOURCES, "-c", config("single-table"))).isZero(); + + assertThat(out.toString()).contains("All Methods (7 total)"); + } + + @Test + void sortsTheClassesByNameAndKeepsTheCollectionOrderInsideThem() { + assertThat(run("analyse", SOURCES, "-c", NO_CACHE)).isZero(); + + List classes = out.toString().lines().filter(line -> line.startsWith("Class: ")).toList(); + assertThat(classes).containsExactly( + "Class: multi.Alpha", "Class: multi.Beta", "Class: multi.Helper", "Class: test.testcode.ClassToAnalyze"); + } + + // --- header, progress and colors --- + + @Test + void namesTheBuiltInConfigurationAndAnEnabledCache() { + assertThat(run("analyse", tempDir.toString())).isZero(); + + assertThat(out.toString()).startsWith("Config: built-in\nCache: enabled\n\nFound 0 files. Starting analysis.\n"); + } + + @Test + void namesAConfigurationBelowTheWorkingDirectoryByItsRelativePath() { + assertThat(run("analyse", tempDir.toString(), "-c", NO_CACHE)).isZero(); + + assertThat(out.toString()).startsWith("Config: " + NO_CACHE + "\nCache: disabled\n\n"); + } + + @Test + void namesAConfigurationOutsideTheWorkingDirectoryByItsAbsolutePath() throws Exception { + Path config = Files.writeString(tempDir.resolve("outside.yaml"), "cognitive:\n cache:\n enabled: false\n"); + + assertThat(run("analyse", tempDir.toString(), "-c", config.toString())).isZero(); + + assertThat(out.toString()).startsWith("Config: " + config.toAbsolutePath().normalize() + "\nCache: disabled\n"); + } + + @Test + void printsNothingBeforeAFailingConfigurationIsLoaded() { + assertThat(run("analyse", SOURCES, "-c", "missing.yaml")).isEqualTo(1); + + assertThat(out.toString()).isEmpty(); + } + + @Test + void printsNoProgressWhenTheErrorStreamIsNotATerminal() { + assertThat(run("analyse", SOURCES, "-c", NO_CACHE)).isZero(); + + assertThat(err.toString()).isEmpty(); + assertThat(out.toString()).doesNotContain("Analysing").doesNotContain("\r"); + } + + @Test + void printsProgressOnTheErrorStreamWhenItIsATerminal() { + terminal = true; + + assertThat(run("analyse", SOURCES, "-c", NO_CACHE)).isZero(); + + assertThat(err.toString()).isEqualTo("\rAnalysing 1/3\rAnalysing 2/3\rAnalysing 3/3\n"); + assertThat(out.toString()).doesNotContain("Analysing"); + } + + @Test + void countsAFileThatCannotBeParsedAsProcessedAndKeepsTheParserMessage() { + terminal = true; + + assertThat(run("analyse", PARSE_ERROR, "-c", NO_CACHE)).isZero(); + + assertThat(err.toString()) + .contains("\rAnalysing 1/1\n") + .contains("Parser failed for file " + PARSE_ERROR + "/Broken.java: "); + } + + @Test + void printsNoProgressLineForAnEmptyDirectory() { + terminal = true; + + assertThat(run("analyse", tempDir.toString(), "-c", NO_CACHE)).isZero(); + + assertThat(err.toString()).isEmpty(); + } + + @Test + void decidesAboutColorsByTheTerminalByDefault() { + AnalyseCommand command = (AnalyseCommand) new CommandLine(new App()).getSubcommands().get("analyse").getCommand(); + + assertThat(command.ansi).isSameAs(Ansi.AUTO); + } + + @Test + void printsNoColorCodesWhenAnsiIsOff() { + assertThat(run("analyse", FIXTURES + "/sample", "-c", NO_CACHE)).isZero(); + + assertThat(out.toString()).doesNotContain("\u001B"); + } + + @Test + void colorsTheScoresWhenAnsiIsForcedOn() { + ansi = Ansi.ON; + + assertThat(run("analyse", FIXTURES + "/sample", "-c", NO_CACHE)).isZero(); + + // threshold 0.5: the score 2.197 is red, the score 0 is green + assertThat(out.toString()) + .contains("\u001B[31m2.197\u001B[39m") + .contains("\u001B[32m0.000\u001B[39m"); + } + + // --- sorting --- + + @Test + void sortsAllMethodsByScoreDescendingInOneTable() { + assertThat(run("analyse", SOURCES, "-c", config("single-table"), "--sort-by", "score", "--sort-order", "desc")) + .isZero(); + + Approvals.verify(out.toString()); + } + + @Test + void sortsAscendingByDefaultAndTheOrderIsCaseInsensitive() { + run("analyse", SOURCES, "-c", config("single-table"), "--sort-by", "method"); + String ascending = out.toString(); + out.getBuffer().setLength(0); + + assertThat(run("analyse", SOURCES, "-c", config("single-table"), "--sort-by", "method", "--sort-order", "ASC")) + .isZero(); + assertThat(out.toString()).isEqualTo(ascending); + assertThat(methodsOfSingleTable(ascending)).containsExactly("alpha", "first", "methodWithTwoArguments", "run", "second", + "simpleMethod", "zulu"); + out.getBuffer().setLength(0); + + assertThat(run("analyse", SOURCES, "-c", config("single-table"), "--sort-by", "method", "--sort-order", "Desc")) + .isZero(); + assertThat(methodsOfSingleTable(out.toString())).containsExactly("zulu", "simpleMethod", "second", "run", + "methodWithTwoArguments", "first", "alpha"); + } + + @ParameterizedTest + @ValueSource(strings = {"score", "halstead", "cyclomatic", "understandability", "class", "method", "file", + "lineCount", "argCount", "returnCount", "variableCount", "propertyCallCount", "ifCount", "ifNestingLevel", + "elseCount", "lineCountWeight", "argCountWeight", "returnCountWeight", "variableCountWeight", + "propertyCallCountWeight", "ifCountWeight", "ifNestingLevelWeight", "elseCountWeight"}) + void acceptsEverySortField(final String field) { + assertThat(run("analyse", SOURCES, "-c", config("single-table"), "--sort-by", field)).isZero(); + + assertThat(err.toString()).isEmpty(); + assertThat(methodsOfSingleTable(out.toString())).hasSize(7).containsExactlyInAnyOrder( + "alpha", "first", "methodWithTwoArguments", "run", "second", "simpleMethod", "zulu"); + } + + @Test + void sortsTheMethodsOfAClassByTheGivenField() { + assertThat(run("analyse", FIXTURES + "/sample", "-c", NO_CACHE, "--sort-by", "score", "--sort-order", "desc")) + .isZero(); + + assertThat(methods(out.toString())).containsExactly("methodWithTwoArguments", "simpleMethod"); + } + + @Test + void rejectsAnUnknownSortField() { + assertThat(run("analyse", SOURCES, "-c", NO_CACHE, "--sort-by", "bogus")).isEqualTo(1); + + assertThat(out.toString()).isEmpty(); + assertThat(err.toString()).isEqualTo( + "Invalid sort field \"bogus\". Available fields: " + String.join(", ", MetricsSorter.FIELDS) + "\n"); + } + + @Test + void rejectsAnUnknownSortOrder() { + assertThat(run("analyse", SOURCES, "-c", NO_CACHE, "--sort-by", "score", "--sort-order", "up")).isEqualTo(1); + + assertThat(out.toString()).isEmpty(); + assertThat(err.toString()).isEqualTo("Sort order must be \"asc\" or \"desc\", got \"up\"\n"); + } + + @Test + void rejectsAnUnknownSortOrderWithoutASortField() { + assertThat(run("analyse", SOURCES, "-c", NO_CACHE, "--sort-order", "up")).isEqualTo(1); + + assertThat(err.toString()).isEqualTo("Sort order must be \"asc\" or \"desc\", got \"up\"\n"); + } + + @Test + void passesTheSortedOrderOnToTheReport() throws Exception { + Path report = tempDir.resolve("report.csv"); + + assertThat(run("analyse", SOURCES, "-c", NO_CACHE, "-r", "csv", "-f", report.toString(), + "--sort-by", "method", "--sort-order", "desc")).isZero(); + + List lines = Files.readAllLines(report); + // zulu is the first method of all, so its file comes first + assertThat(lines.get(1)).contains("zulu"); + assertThat(lines.stream().filter(line -> line.contains("Alpha")).findFirst().orElseThrow()) + .isNotEqualTo(lines.get(1)); + assertThat(out.toString()).contains("Report generated at: " + report); + } + + // --- --debug --- + + @Test + void printsTheExecutionSummaryWithTheStageTimingsAndStatistics() { + now = new AtomicLong(); + + assertThat(run("analyse", SOURCES, "-c", NO_CACHE, "--debug")).isZero(); + + String output = out.toString(); + assertThat(output.substring(output.indexOf("Execution Summary:"))).isEqualTo(""" + Execution Summary: + Total execution time: 1.250s + Stage timings: + config: 0.250s + discovery: 0.250s + analysis: 0.250s + sorting: 0.250s + output: 0.250s + Statistics: + filesFound: 3 + filesAnalysed: 3 + filesFailed: 0 + methodsAnalysed: 7 + cacheHits: 0 + cacheMisses: 0 + """); + } + + @Test + void printsTheSummaryAfterTheReportToo() { + now = new AtomicLong(); + + assertThat(run("analyse", SOURCES, "-c", NO_CACHE, "--debug", "-r", "json", "-f", + tempDir.resolve("r.json").toString())).isZero(); + + assertThat(out.toString()).contains("Report generated at: ").contains("Execution Summary:"); + assertThat(out.toString().indexOf("Execution Summary:")).isGreaterThan(out.toString().indexOf("Report generated")); + } + + @Test + void printsNoSummaryWithoutTheDebugFlag() { + assertThat(run("analyse", SOURCES, "-c", NO_CACHE)).isZero(); + + assertThat(out.toString()).doesNotContain("Execution Summary").doesNotContain("Stage timings"); + } + + @Test + void printsNoSummaryWhenTheRunFails() { + assertThat(run("analyse", "does/not/exist", "-c", NO_CACHE, "--debug")).isEqualTo(1); + + assertThat(out.toString()).doesNotContain("Execution Summary"); + } + + @Test + void countsFailedFilesInTheStatistics() { + assertThat(run("analyse", PARSE_ERROR, "-c", NO_CACHE, "--debug")).isZero(); + + assertThat(out.toString()).contains("filesFound: 1").contains("filesAnalysed: 0").contains("filesFailed: 1") + .contains("methodsAnalysed: 0"); + } + + @Test + void countsCacheMissesOnTheFirstRunAndCacheHitsOnTheSecond() throws Exception { + Path config = Files.writeString(tempDir.resolve("cache.yaml"), + "cognitive:\n cache:\n directory: '" + tempDir.resolve("cache") + "'\n"); + + run("analyse", SOURCES, "-c", config.toString(), "--debug"); + assertThat(out.toString()).contains("cacheHits: 0").contains("cacheMisses: 3"); + out.getBuffer().setLength(0); + + run("analyse", SOURCES, "-c", config.toString(), "--debug"); + assertThat(out.toString()).contains("cacheHits: 3").contains("cacheMisses: 0"); + } + + @Test + void documentsTheNewOptionsInTheHelp() { + assertThat(run("analyse", "--help")).isZero(); + + assertThat(out.toString()).contains("--sort-by=", "--sort-order=", "--debug", "halstead", + "elseCountWeight"); + } + + // --- helpers --- + + private void verifyGolden(final String configFile) { + assertThat(run("analyse", SOURCES, "-c", configFile)).isZero(); + assertThat(err.toString()).isEmpty(); + Approvals.verify(out.toString()); + } + + private static String config(final String name) { + return FIXTURES + "/console/" + name + ".yaml"; + } + + /** The method names of the rows of a table without a class column. */ + private static List methods(final String output) { + return column(output, 0); + } + + /** The method names of the rows of the single table, whose first column is the class. */ + private static List methodsOfSingleTable(final String output) { + return column(output, 1); + } + + private static List column(final String output, final int index) { + return output.lines() + .filter(line -> line.startsWith("│")) + .map(line -> line.substring(1).split("│")[index].trim()) + .filter(cell -> !cell.isEmpty() && !cell.equals("Method Name")) + .toList(); + } + + private int run(final String... args) { + CommandLine commandLine = new CommandLine(new App()); + AnalyseCommand command = (AnalyseCommand) commandLine.getSubcommands().get("analyse").getCommand(); + command.ansi = ansi; + command.stderrIsTerminal = () -> terminal; + if (now != null) { + final long step = 250_000_000L; + command.ticker = () -> now.getAndAdd(step); + } + commandLine.setOut(new PrintWriter(out, true)); + commandLine.setErr(new PrintWriter(err, true)); + return commandLine.execute(args); + } +} diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsAllMetrics.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsAllMetrics.approved.txt new file mode 100644 index 0000000..bf5d1a9 --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsAllMetrics.approved.txt @@ -0,0 +1,48 @@ +Config: src/test/resources/fixtures/console/all-metrics.yaml +Cache: disabled + +Found 3 files. Starting analysis. + +Class: multi.Alpha +File: src/test/resources/fixtures/multi/Alpha.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┬────────────┬───────────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ Understandability │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ second │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ first │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ + +Class: multi.Beta +File: src/test/resources/fixtures/multi/Beta.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┬────────────┬───────────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ Understandability │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ zulu │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ alpha │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ + +Class: multi.Helper +File: src/test/resources/fixtures/multi/Alpha.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┬────────────┬───────────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ Understandability │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ run │ 5 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ 19.65 │ 1.00 │ 19.65 │ 2 (low) │ 1 (low) │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ + +Class: test.testcode.ClassToAnalyze +File: src/test/resources/fixtures/sample/ClassToAnalyze.java +┌────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┬────────────┬───────────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ Understandability │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ +├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ simpleMethod │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ +├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ 106.30 │ 2.88 │ 305.62 │ 5 (low) │ 9 (medium) │ +└────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ + +Cognitive metrics calculated for src/test/resources/fixtures/sample,src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsCyclomaticComplexityOnly.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsCyclomaticComplexityOnly.approved.txt new file mode 100644 index 0000000..4174eb4 --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsCyclomaticComplexityOnly.approved.txt @@ -0,0 +1,48 @@ +Config: src/test/resources/fixtures/console/cyclomatic-only.yaml +Cache: disabled + +Found 3 files. Starting analysis. + +Class: multi.Alpha +File: src/test/resources/fixtures/multi/Alpha.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Cyclomatic │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Complexity │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼────────────┤ +│ second │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 1 (low) │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼────────────┤ +│ first │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 1 (low) │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴────────────┘ + +Class: multi.Beta +File: src/test/resources/fixtures/multi/Beta.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Cyclomatic │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Complexity │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼────────────┤ +│ zulu │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 1 (low) │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼────────────┤ +│ alpha │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 1 (low) │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴────────────┘ + +Class: multi.Helper +File: src/test/resources/fixtures/multi/Alpha.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Cyclomatic │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Complexity │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼────────────┤ +│ run │ 5 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ 2 (low) │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴────────────┘ + +Class: test.testcode.ClassToAnalyze +File: src/test/resources/fixtures/sample/ClassToAnalyze.java +┌────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Cyclomatic │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Complexity │ +├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼────────────┤ +│ simpleMethod │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 1 (low) │ +├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼────────────┤ +│ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ 5 (low) │ +└────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴────────────┘ + +Cognitive metrics calculated for src/test/resources/fixtures/sample,src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsHalsteadComplexityOnly.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsHalsteadComplexityOnly.approved.txt new file mode 100644 index 0000000..eb40c9f --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsHalsteadComplexityOnly.approved.txt @@ -0,0 +1,48 @@ +Config: src/test/resources/fixtures/console/halstead-only.yaml +Cache: disabled + +Found 3 files. Starting analysis. + +Class: multi.Alpha +File: src/test/resources/fixtures/multi/Alpha.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┤ +│ second │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┤ +│ first │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┘ + +Class: multi.Beta +File: src/test/resources/fixtures/multi/Beta.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┤ +│ zulu │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┤ +│ alpha │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┘ + +Class: multi.Helper +File: src/test/resources/fixtures/multi/Alpha.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┤ +│ run │ 5 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ 19.65 │ 1.00 │ 19.65 │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┘ + +Class: test.testcode.ClassToAnalyze +File: src/test/resources/fixtures/sample/ClassToAnalyze.java +┌────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ +├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┤ +│ simpleMethod │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ +├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┤ +│ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ 106.30 │ 2.88 │ 305.62 │ +└────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┘ + +Cognitive metrics calculated for src/test/resources/fixtures/sample,src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsOneSingleTableWithTheClassColumn.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsOneSingleTableWithTheClassColumn.approved.txt new file mode 100644 index 0000000..61d4589 --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsOneSingleTableWithTheClassColumn.approved.txt @@ -0,0 +1,26 @@ +Config: src/test/resources/fixtures/console/single-table.yaml +Cache: disabled + +Found 3 files. Starting analysis. + +All Methods (7 total) +┌──────────────────────────────┬────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┬────────────┐ +│ Class │ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ +│ │ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ +├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ +│ multi.Alpha │ second │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ +│ multi.Alpha │ first │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ +│ multi.Helper │ run │ 5 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ 19.65 │ 1.00 │ 19.65 │ 2 (low) │ +├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ +│ multi.Beta │ zulu │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ +│ multi.Beta │ alpha │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ +│ test.testcode.ClassToAnalyze │ simpleMethod │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ +│ test.testcode.ClassToAnalyze │ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ 106.30 │ 2.88 │ 305.62 │ 5 (low) │ +└──────────────────────────────┴────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┴────────────┘ + +Cognitive metrics calculated for src/test/resources/fixtures/sample,src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsOnlyTheMethodsExceedingTheThreshold.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsOnlyTheMethodsExceedingTheThreshold.approved.txt new file mode 100644 index 0000000..be5f024 --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsOnlyTheMethodsExceedingTheThreshold.approved.txt @@ -0,0 +1,15 @@ +Config: src/test/resources/fixtures/console/threshold.yaml +Cache: disabled + +Found 3 files. Starting analysis. + +Class: test.testcode.ClassToAnalyze +File: src/test/resources/fixtures/sample/ClassToAnalyze.java +┌────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ +└────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ + +Cognitive metrics calculated for src/test/resources/fixtures/sample,src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheDefaultTables.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheDefaultTables.approved.txt new file mode 100644 index 0000000..2b495f6 --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheDefaultTables.approved.txt @@ -0,0 +1,48 @@ +Config: src/test/resources/fixtures/no-cache.yaml +Cache: disabled + +Found 3 files. Starting analysis. + +Class: multi.Alpha +File: src/test/resources/fixtures/multi/Alpha.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ second │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ first │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ + +Class: multi.Beta +File: src/test/resources/fixtures/multi/Beta.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ zulu │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ alpha │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ + +Class: multi.Helper +File: src/test/resources/fixtures/multi/Alpha.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ run │ 5 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ + +Class: test.testcode.ClassToAnalyze +File: src/test/resources/fixtures/sample/ClassToAnalyze.java +┌────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ simpleMethod │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ +├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ +└────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ + +Cognitive metrics calculated for src/test/resources/fixtures/sample,src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheMetricsWithoutTheDetailColumns.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheMetricsWithoutTheDetailColumns.approved.txt new file mode 100644 index 0000000..71f95b8 --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheMetricsWithoutTheDetailColumns.approved.txt @@ -0,0 +1,48 @@ +Config: src/test/resources/fixtures/console/without-detailed.yaml +Cache: disabled + +Found 3 files. Starting analysis. + +Class: multi.Alpha +File: src/test/resources/fixtures/multi/Alpha.java +┌─────────────┬────────────┬──────────┬────────────┬──────────┬────────────┬───────────────────┐ +│ Method Name │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ Understandability │ +│ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ +├─────────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ second │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ +├─────────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ first │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ +└─────────────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ + +Class: multi.Beta +File: src/test/resources/fixtures/multi/Beta.java +┌─────────────┬────────────┬──────────┬────────────┬──────────┬────────────┬───────────────────┐ +│ Method Name │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ Understandability │ +│ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ +├─────────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ zulu │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ +├─────────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ alpha │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ +└─────────────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ + +Class: multi.Helper +File: src/test/resources/fixtures/multi/Alpha.java +┌─────────────┬────────────┬──────────┬────────────┬──────────┬────────────┬───────────────────┐ +│ Method Name │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ Understandability │ +│ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ +├─────────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ run │ 0.000 │ 19.65 │ 1.00 │ 19.65 │ 2 (low) │ 1 (low) │ +└─────────────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ + +Class: test.testcode.ClassToAnalyze +File: src/test/resources/fixtures/sample/ClassToAnalyze.java +┌────────────────────────┬────────────┬──────────┬────────────┬──────────┬────────────┬───────────────────┐ +│ Method Name │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ Understandability │ +│ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ +├────────────────────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ simpleMethod │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ +├────────────────────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ methodWithTwoArguments │ 2.197 │ 106.30 │ 2.88 │ 305.62 │ 5 (low) │ 9 (medium) │ +└────────────────────────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ + +Cognitive metrics calculated for src/test/resources/fixtures/sample,src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheMinimalColumns.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheMinimalColumns.approved.txt new file mode 100644 index 0000000..7be35c4 --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheMinimalColumns.approved.txt @@ -0,0 +1,48 @@ +Config: src/test/resources/fixtures/console/minimal.yaml +Cache: disabled + +Found 3 files. Starting analysis. + +Class: multi.Alpha +File: src/test/resources/fixtures/multi/Alpha.java +┌─────────────┬────────────┐ +│ Method Name │ Cognitive │ +│ │ Complexity │ +├─────────────┼────────────┤ +│ second │ 0.000 │ +├─────────────┼────────────┤ +│ first │ 0.000 │ +└─────────────┴────────────┘ + +Class: multi.Beta +File: src/test/resources/fixtures/multi/Beta.java +┌─────────────┬────────────┐ +│ Method Name │ Cognitive │ +│ │ Complexity │ +├─────────────┼────────────┤ +│ zulu │ 0.000 │ +├─────────────┼────────────┤ +│ alpha │ 0.000 │ +└─────────────┴────────────┘ + +Class: multi.Helper +File: src/test/resources/fixtures/multi/Alpha.java +┌─────────────┬────────────┐ +│ Method Name │ Cognitive │ +│ │ Complexity │ +├─────────────┼────────────┤ +│ run │ 0.000 │ +└─────────────┴────────────┘ + +Class: test.testcode.ClassToAnalyze +File: src/test/resources/fixtures/sample/ClassToAnalyze.java +┌────────────────────────┬────────────┐ +│ Method Name │ Cognitive │ +│ │ Complexity │ +├────────────────────────┼────────────┤ +│ simpleMethod │ 0.000 │ +├────────────────────────┼────────────┤ +│ methodWithTwoArguments │ 2.197 │ +└────────────────────────┴────────────┘ + +Cognitive metrics calculated for src/test/resources/fixtures/sample,src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsUnderstandability.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsUnderstandability.approved.txt new file mode 100644 index 0000000..791b9de --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsUnderstandability.approved.txt @@ -0,0 +1,48 @@ +Config: src/test/resources/fixtures/console/understandability.yaml +Cache: disabled + +Found 3 files. Starting analysis. + +Class: multi.Alpha +File: src/test/resources/fixtures/multi/Alpha.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬───────────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Understandability │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼───────────────────┤ +│ second │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 0 (low) │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼───────────────────┤ +│ first │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 0 (low) │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴───────────────────┘ + +Class: multi.Beta +File: src/test/resources/fixtures/multi/Beta.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬───────────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Understandability │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼───────────────────┤ +│ zulu │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 0 (low) │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼───────────────────┤ +│ alpha │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 0 (low) │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴───────────────────┘ + +Class: multi.Helper +File: src/test/resources/fixtures/multi/Alpha.java +┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬───────────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Understandability │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ │ +├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼───────────────────┤ +│ run │ 5 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ 1 (low) │ +└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴───────────────────┘ + +Class: test.testcode.ClassToAnalyze +File: src/test/resources/fixtures/sample/ClassToAnalyze.java +┌────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬───────────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Understandability │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ │ +├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼───────────────────┤ +│ simpleMethod │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 0 (low) │ +├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼───────────────────┤ +│ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ 9 (medium) │ +└────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴───────────────────┘ + +Cognitive metrics calculated for src/test/resources/fixtures/sample,src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.sortsAllMethodsByScoreDescendingInOneTable.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.sortsAllMethodsByScoreDescendingInOneTable.approved.txt new file mode 100644 index 0000000..b9321af --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.sortsAllMethodsByScoreDescendingInOneTable.approved.txt @@ -0,0 +1,26 @@ +Config: src/test/resources/fixtures/console/single-table.yaml +Cache: disabled + +Found 3 files. Starting analysis. + +All Methods (7 total) +┌──────────────────────────────┬────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┬────────────┐ +│ Class │ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ +│ │ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ +├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ +│ test.testcode.ClassToAnalyze │ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ 106.30 │ 2.88 │ 305.62 │ 5 (low) │ +├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ +│ multi.Alpha │ first │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ +│ multi.Alpha │ second │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ +│ multi.Beta │ alpha │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ +│ multi.Beta │ zulu │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ +│ multi.Helper │ run │ 5 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ 19.65 │ 1.00 │ 19.65 │ 2 (low) │ +├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ +│ test.testcode.ClassToAnalyze │ simpleMethod │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +└──────────────────────────────┴────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┴────────────┘ + +Cognitive metrics calculated for src/test/resources/fixtures/sample,src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/MetricFormatterTest.java b/src/test/java/net/floriankraemer/cognitive_analysis/application/MetricFormatterTest.java new file mode 100644 index 0000000..543420f --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/MetricFormatterTest.java @@ -0,0 +1,82 @@ +package net.floriankraemer.cognitive_analysis.application; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Locale; +import org.junit.jupiter.api.Test; +import picocli.CommandLine.Help.Ansi; + +class MetricFormatterTest { + + private static final String RED = "\u001B[31m"; + private static final String YELLOW = "\u001B[33m"; + private static final String GREEN = "\u001B[32m"; + + private final MetricFormatter colors = new MetricFormatter(0.5, Ansi.ON); + private final MetricFormatter plain = new MetricFormatter(0.5, Ansi.OFF); + + @Test + void showsTheWeightWithThreeDecimalsRegardlessOfTheLocale() { + Locale original = Locale.getDefault(); + Locale.setDefault(Locale.GERMANY); + try { + assertThat(plain.weighted(4, 1.0986)).isEqualTo("4 (1.099)"); + assertThat(plain.weighted(0, 0)).isEqualTo("0 (0.000)"); + } finally { + Locale.setDefault(original); + } + } + + @Test + void colorsTheScoreRedOnlyAboveTheThreshold() { + assertThat(colors.score(0.501)).startsWith(RED); + assertThat(colors.score(0.5)).startsWith(GREEN); + assertThat(colors.score(0)).startsWith(GREEN); + } + + @Test + void colorsTheHalsteadVolumeFromOneHundredAndOneThousand() { + assertThat(colors.halsteadVolume(99.99)).doesNotContain("\u001B"); + assertThat(colors.halsteadVolume(100)).startsWith(YELLOW); + assertThat(colors.halsteadVolume(999.99)).startsWith(YELLOW); + assertThat(colors.halsteadVolume(1000)).startsWith(RED); + } + + @Test + void colorsTheHalsteadDifficultyFromTenAndFifty() { + assertThat(colors.halsteadDifficulty(9.99)).doesNotContain("\u001B"); + assertThat(colors.halsteadDifficulty(10)).startsWith(YELLOW); + assertThat(colors.halsteadDifficulty(49.99)).startsWith(YELLOW); + assertThat(colors.halsteadDifficulty(50)).startsWith(RED); + } + + @Test + void colorsTheHalsteadEffortFromFiveHundredAndFiveThousand() { + assertThat(colors.halsteadEffort(499.99)).doesNotContain("\u001B"); + assertThat(colors.halsteadEffort(500)).startsWith(YELLOW); + assertThat(colors.halsteadEffort(4999.99)).startsWith(YELLOW); + assertThat(colors.halsteadEffort(5000)).startsWith(RED); + } + + @Test + void showsTheHalsteadValuesWithTwoDecimals() { + assertThat(plain.halsteadVolume(7.5)).isEqualTo("7.50"); + assertThat(plain.halsteadDifficulty(1)).isEqualTo("1.00"); + assertThat(plain.halsteadEffort(0)).isEqualTo("0.00"); + } + + @Test + void colorsOnlyTheRiskLevelAndLeavesLowUncolored() { + assertThat(colors.withRisk(3, "low")).isEqualTo("3 (low)"); + assertThat(colors.withRisk(7, "medium")).startsWith("7 (" + YELLOW + "medium"); + assertThat(colors.withRisk(12, "high")).startsWith("12 (" + RED + "high"); + assertThat(colors.withRisk(20, "very_high")).startsWith("20 (" + RED + "very_high"); + } + + @Test + void dropsTheColorsWhenAnsiIsOff() { + assertThat(plain.score(9)).isEqualTo("9.000"); + assertThat(plain.withRisk(20, "very_high")).isEqualTo("20 (very_high)"); + assertThat(plain.halsteadVolume(5000)).isEqualTo("5000.00"); + } +} diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.addsTheHalsteadCyclomaticAndUnderstandabilityColumns.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.addsTheHalsteadCyclomaticAndUnderstandabilityColumns.approved.txt new file mode 100644 index 0000000..4d36fd6 --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.addsTheHalsteadCyclomaticAndUnderstandabilityColumns.approved.txt @@ -0,0 +1,8 @@ +┌──────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┬────────────┬───────────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ Understandability │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ +├──────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ method1 │ 1 (0.000) │ 2 (0.000) │ 3 (0.000) │ 4 (0.000) │ 5 (0.000) │ 6 (0.693) │ 7 (0.000) │ 8 (0.000) │ 5.000 │ 58.95 │ 3.38 │ 198.97 │ 3 (low) │ 2 (low) │ +├──────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ method2(int) │ 15 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 2 (0.406) │ 7.500 │ 0.00 │ 0.00 │ 0.00 │ 1 (low) │ 0 (low) │ +└──────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ \ No newline at end of file diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.java b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.java index dc75e0e..fd40178 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.java +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.java @@ -2,55 +2,134 @@ import static org.assertj.core.api.Assertions.assertThat; -import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; +import net.floriankraemer.cognitive_analysis.config.CognitiveConfig; import net.floriankraemer.cognitive_analysis.config.MetricName; +import net.floriankraemer.cognitive_analysis.config.TestConfigs; import net.floriankraemer.cognitive_analysis.domain.CognitiveMetrics; +import net.floriankraemer.cognitive_analysis.domain.CyclomaticComplexity; +import net.floriankraemer.cognitive_analysis.domain.HalsteadMetrics; +import net.floriankraemer.cognitive_analysis.domain.Understandability; +import org.approvaltests.Approvals; import org.junit.jupiter.api.Test; +import picocli.CommandLine.Help.Ansi; class ResultTableBuilderTest { - private final ResultTableBuilder resultTableBuilder = new ResultTableBuilder(); + private static final String ALL_COLUMNS = """ + cognitive: + scoreThreshold: 6 + showHalsteadComplexity: true + showCyclomaticComplexity: true + showUnderstandability: true + """; + + private final CognitiveConfig defaults = TestConfigs.defaults(); @Test - void rendersOneRowPerMethodWithWeightsBelowTheCounts() { - CognitiveMetrics metrics1 = new CognitiveMetrics("a.TestClass1", "method1", 3); - int value = 1; - for (MetricName name : MetricName.values()) { - metrics1.setValue(name, value++); - } - metrics1.setWeight(MetricName.IF_COUNT, 0.693); - metrics1.setCognitiveComplexity(5.0); + void rendersOneRowPerMethodWithTheWeightNextToTheCount() { + Approvals.verify(new ResultTableBuilder(defaults, Ansi.OFF).build(List.of(first(), second()))); + } - CognitiveMetrics metrics2 = new CognitiveMetrics("a.TestClass2", "method2(int)", 9); - metrics2.setValue(MetricName.LINE_COUNT, 15); - metrics2.setValue(MetricName.ELSE_COUNT, 2); - metrics2.setWeight(MetricName.ELSE_COUNT, 0.4055); - metrics2.setCognitiveComplexity(7.5); + @Test + void leadsWithTheClassWhenTheTableMixesClasses() { + Approvals.verify(new ResultTableBuilder(defaults, Ansi.OFF).buildWithClass(List.of(first(), second()))); + } - Map methodMetrics = new LinkedHashMap<>(); - methodMetrics.put("a.TestClass1::method1", metrics1); - methodMetrics.put("a.TestClass2::method2(int)", metrics2); + @Test + void rendersOnlyTheHeaderWhenThereAreNoMethods() { + Approvals.verify(new ResultTableBuilder(defaults, Ansi.OFF).build(List.of())); + } - assertThat(resultTableBuilder.build(methodMetrics)).isEqualTo(""" - ┌────────────┬────────────┬─────┬─────────┬───────┬─────────┬────────┬─────┬──────────┬─────┬──────────┐ - │Class │Method │Lines│Arguments│Returns│Variables│Property│ If │If Nesting│Else │Cognitive │ - │ │ │ │ │ │ │Accesses│ │ Level │ │Complexity│ - ├────────────┼────────────┼─────┼─────────┼───────┼─────────┼────────┼─────┼──────────┼─────┼──────────┤ - │a.TestClass1│method1 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 5.000 │ - │ │ │ │ │ │ │ │0.693│ │ │ │ - ├────────────┼────────────┼─────┼─────────┼───────┼─────────┼────────┼─────┼──────────┼─────┼──────────┤ - │a.TestClass2│method2(int)│ 15 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 2 │ 7.500 │ - │ │ │ │ │ │ │ │ │ │0.406│ │ - └────────────┴────────────┴─────┴─────────┴───────┴─────────┴────────┴─────┴──────────┴─────┴──────────┘"""); + @Test + void leavesOutTheDetailColumnsWhenTheyAreSwitchedOff() { + CognitiveConfig config = TestConfigs.load("cognitive:\n showDetailedCognitiveMetrics: false\n"); + + Approvals.verify(new ResultTableBuilder(config, Ansi.OFF).build(List.of(first(), second()))); } @Test - void rendersOnlyTheHeaderWhenThereAreNoMethods() { - assertThat(resultTableBuilder.build(Map.of())).isEqualTo(""" - ┌─────┬──────┬─────┬─────────┬───────┬─────────┬────────┬──┬──────────┬────┬──────────┐ - │Class│Method│Lines│Arguments│Returns│Variables│Property│If│If Nesting│Else│Cognitive │ - │ │ │ │ │ │ │Accesses│ │ Level │ │Complexity│ - └─────┴──────┴─────┴─────────┴───────┴─────────┴────────┴──┴──────────┴────┴──────────┘"""); + void addsTheHalsteadCyclomaticAndUnderstandabilityColumns() { + CognitiveConfig config = TestConfigs.load(ALL_COLUMNS); + + Approvals.verify(new ResultTableBuilder(config, Ansi.OFF).build(List.of(withAllMetrics(), second()))); + } + + @Test + void keepsTheColumnsAlignedWhenTheCellsAreColored() { + CognitiveConfig config = TestConfigs.load(ALL_COLUMNS); + List methods = List.of(withAllMetrics(), second()); + + String plain = new ResultTableBuilder(config, Ansi.OFF).build(methods); + String colored = new ResultTableBuilder(config, Ansi.ON).build(methods); + + assertThat(colored).isNotEqualTo(plain); + assertThat(colored.replaceAll("\u001B\\[[0-9;]*m", "")).isEqualTo(plain); + } + + @Test + void colorsTheScoreRedAboveTheThresholdAndGreenAtOrBelowIt() { + CognitiveConfig config = TestConfigs.load(ALL_COLUMNS); + + String table = new ResultTableBuilder(config, Ansi.ON).build(List.of(withAllMetrics(), second())); + + assertThat(table) + .contains("\u001B[32m5.000\u001B[39m") + .contains("\u001B[31m7.500\u001B[39m"); + } + + @Test + void colorsTheHalsteadValuesAndRiskLevelsByTheirBands() { + CognitiveConfig config = TestConfigs.load(ALL_COLUMNS); + CognitiveMetrics metrics = second(); + // volume 1080.48 (red), difficulty 10.00 (yellow), effort 10804.82 (red), the risk levels medium and high + metrics.setHalstead(new HalsteadMetrics(10, 10, 230, 20)); + metrics.setCyclomatic(new CyclomaticComplexity(7, Map.of())); + metrics.setUnderstandability(new Understandability(12, Map.of())); + + String table = new ResultTableBuilder(config, Ansi.ON).build(List.of(metrics)); + + assertThat(table) + .contains("\u001B[31m1080.48\u001B[39m") + .contains("\u001B[33m10.00\u001B[39m") + .contains("\u001B[31m10804.82\u001B[39m") + .contains("7 (\u001B[33mmedium\u001B[39m\u001B[0m)") + .contains("12 (\u001B[31mhigh\u001B[39m\u001B[0m)"); + } + + @Test + void printsNoEscapeCodesWhenAnsiIsOff() { + CognitiveConfig config = TestConfigs.load(ALL_COLUMNS); + + assertThat(new ResultTableBuilder(config, Ansi.OFF).build(List.of(withAllMetrics()))).doesNotContain("\u001B"); + } + + private static CognitiveMetrics first() { + CognitiveMetrics metrics = new CognitiveMetrics("a.TestClass1", "method1", 3); + int value = 1; + for (MetricName name : MetricName.values()) { + metrics.setValue(name, value++); + } + metrics.setWeight(MetricName.IF_COUNT, 0.693); + metrics.setCognitiveComplexity(5.0); + return metrics; + } + + private static CognitiveMetrics second() { + CognitiveMetrics metrics = new CognitiveMetrics("a.TestClass2", "method2(int)", 9); + metrics.setValue(MetricName.LINE_COUNT, 15); + metrics.setValue(MetricName.ELSE_COUNT, 2); + metrics.setWeight(MetricName.ELSE_COUNT, 0.4055); + metrics.setCognitiveComplexity(7.5); + return metrics; + } + + private static CognitiveMetrics withAllMetrics() { + CognitiveMetrics metrics = first(); + metrics.setHalstead(new HalsteadMetrics(3, 4, 12, 9)); + metrics.setCyclomatic(new CyclomaticComplexity(3, Map.of())); + metrics.setUnderstandability(new Understandability(2, Map.of())); + return metrics; } } diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.leadsWithTheClassWhenTheTableMixesClasses.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.leadsWithTheClassWhenTheTableMixesClasses.approved.txt new file mode 100644 index 0000000..7a47a8d --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.leadsWithTheClassWhenTheTableMixesClasses.approved.txt @@ -0,0 +1,8 @@ +┌──────────────┬──────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Class │ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├──────────────┼──────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ a.TestClass1 │ method1 │ 1 (0.000) │ 2 (0.000) │ 3 (0.000) │ 4 (0.000) │ 5 (0.000) │ 6 (0.693) │ 7 (0.000) │ 8 (0.000) │ 5.000 │ +├──────────────┼──────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ a.TestClass2 │ method2(int) │ 15 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 2 (0.406) │ 7.500 │ +└──────────────┴──────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ \ No newline at end of file diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.leavesOutTheDetailColumnsWhenTheyAreSwitchedOff.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.leavesOutTheDetailColumnsWhenTheyAreSwitchedOff.approved.txt new file mode 100644 index 0000000..840862f --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.leavesOutTheDetailColumnsWhenTheyAreSwitchedOff.approved.txt @@ -0,0 +1,8 @@ +┌──────────────┬────────────┐ +│ Method Name │ Cognitive │ +│ │ Complexity │ +├──────────────┼────────────┤ +│ method1 │ 5.000 │ +├──────────────┼────────────┤ +│ method2(int) │ 7.500 │ +└──────────────┴────────────┘ \ No newline at end of file diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.rendersOneRowPerMethodWithTheWeightNextToTheCount.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.rendersOneRowPerMethodWithTheWeightNextToTheCount.approved.txt new file mode 100644 index 0000000..45f3dc3 --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.rendersOneRowPerMethodWithTheWeightNextToTheCount.approved.txt @@ -0,0 +1,8 @@ +┌──────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├──────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ method1 │ 1 (0.000) │ 2 (0.000) │ 3 (0.000) │ 4 (0.000) │ 5 (0.000) │ 6 (0.693) │ 7 (0.000) │ 8 (0.000) │ 5.000 │ +├──────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ +│ method2(int) │ 15 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 2 (0.406) │ 7.500 │ +└──────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ \ No newline at end of file diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.rendersOnlyTheHeaderWhenThereAreNoMethods.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.rendersOnlyTheHeaderWhenThereAreNoMethods.approved.txt new file mode 100644 index 0000000..cd889b4 --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.rendersOnlyTheHeaderWhenThereAreNoMethods.approved.txt @@ -0,0 +1,4 @@ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬────┬────────────┬──────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴────┴────────────┴──────┴────────────┘ \ No newline at end of file diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/churn/ChurnCommandE2ETest.java b/src/test/java/net/floriankraemer/cognitive_analysis/churn/ChurnCommandE2ETest.java index 7761943..584f8bf 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/churn/ChurnCommandE2ETest.java +++ b/src/test/java/net/floriankraemer/cognitive_analysis/churn/ChurnCommandE2ETest.java @@ -64,8 +64,8 @@ void countsChangesOfTheFilesInTheRepository() throws Exception { assertThat(run("churn", repo.toString())).isZero(); assertThat(table(out.toString())).containsExactly( - "│churn.Busy │2.197│6.591│ 3 │", - "│churn.Light│0.693│1.386│ 2 │"); + "│ churn.Busy │ 2.197 │ 6.591 │ 3 │", + "│ churn.Light │ 0.693 │ 1.386 │ 2 │"); } @Test @@ -75,8 +75,8 @@ void sinceLimitsTheCountedChanges() throws Exception { assertThat(run("churn", repo.toString(), "-s", "2024-03-01")).isZero(); assertThat(table(out.toString())).containsExactly( - "│churn.Busy │2.197│2.197│ 1 │", - "│churn.Light│0.693│0.693│ 1 │"); + "│ churn.Busy │ 2.197 │ 2.197 │ 1 │", + "│ churn.Light │ 0.693 │ 0.693 │ 1 │"); } @Test diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/churn/ChurnCommandE2ETest.printsAChurnTableSortedByChurnWithoutZeroScoreClasses.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/churn/ChurnCommandE2ETest.printsAChurnTableSortedByChurnWithoutZeroScoreClasses.approved.txt index 4bbc8b1..58460ff 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/churn/ChurnCommandE2ETest.printsAChurnTableSortedByChurnWithoutZeroScoreClasses.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/churn/ChurnCommandE2ETest.printsAChurnTableSortedByChurnWithoutZeroScoreClasses.approved.txt @@ -1,7 +1,7 @@ -┌───────────┬─────┬─────┬─────────────┐ -│Class │Score│Churn│Times Changed│ -├───────────┼─────┼─────┼─────────────┤ -│churn.Busy │2.197│6.591│ 3 │ -├───────────┼─────┼─────┼─────────────┤ -│churn.Light│0.693│1.386│ 2 │ -└───────────┴─────┴─────┴─────────────┘ +┌─────────────┬───────┬───────┬───────────────┐ +│ Class │ Score │ Churn │ Times Changed │ +├─────────────┼───────┼───────┼───────────────┤ +│ churn.Busy │ 2.197 │ 6.591 │ 3 │ +├─────────────┼───────┼───────┼───────────────┤ +│ churn.Light │ 0.693 │ 1.386 │ 2 │ +└─────────────┴───────┴───────┴───────────────┘ diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/domain/MetricsCollectionTest.java b/src/test/java/net/floriankraemer/cognitive_analysis/domain/MetricsCollectionTest.java new file mode 100644 index 0000000..153b612 --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/domain/MetricsCollectionTest.java @@ -0,0 +1,44 @@ +package net.floriankraemer.cognitive_analysis.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.Test; + +class MetricsCollectionTest { + + private final CognitiveMetrics one = new CognitiveMetrics("p.A", "one", 1); + private final CognitiveMetrics two = new CognitiveMetrics("p.A", "two", 2); + private final CognitiveMetrics three = new CognitiveMetrics("p.B", "three", 3); + + @Test + void listsTheMethodsFileByFileInCollectionOrder() { + MetricsCollection collection = new MetricsCollection(); + collection.put("A.java", Map.of("p.A::one", one)); + collection.put("B.java", new LinkedHashMap<>(Map.of("p.B::three", three))); + + assertThat(collection.methods()).containsExactly( + new ScoredMethod("A.java", "p.A::one", one), new ScoredMethod("B.java", "p.B::three", three)); + } + + @Test + void isEmptyWithoutMethods() { + assertThat(new MetricsCollection().methods()).isEmpty(); + assertThat(MetricsCollection.of(List.of())).isEmpty(); + } + + @Test + void groupsMethodsByFileInTheOrderOfTheirFirstAppearance() { + MetricsCollection collection = MetricsCollection.of(List.of( + new ScoredMethod("B.java", "p.B::three", three), + new ScoredMethod("A.java", "p.A::two", two), + new ScoredMethod("B.java", "p.B::more", three), + new ScoredMethod("A.java", "p.A::one", one))); + + assertThat(collection.keySet()).containsExactly("B.java", "A.java"); + assertThat(collection.get("B.java").keySet()).containsExactly("p.B::three", "p.B::more"); + assertThat(collection.get("A.java").keySet()).containsExactly("p.A::two", "p.A::one"); + } +} diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/domain/MetricsSorterTest.java b/src/test/java/net/floriankraemer/cognitive_analysis/domain/MetricsSorterTest.java new file mode 100644 index 0000000..da4db4c --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/domain/MetricsSorterTest.java @@ -0,0 +1,179 @@ +package net.floriankraemer.cognitive_analysis.domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import net.floriankraemer.cognitive_analysis.CognitiveAnalysisException; +import net.floriankraemer.cognitive_analysis.config.MetricName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +class MetricsSorterTest { + + /** Three methods whose rank differs in every field: a is lowest, c is highest, in the order b, a, c. */ + private final ScoredMethod a = method("z/A.java", "p.Alpha", "one", m -> { + m.setCognitiveComplexity(1); + m.setHalstead(new HalsteadMetrics(1, 1, 1, 1)); + m.setCyclomatic(new CyclomaticComplexity(1, Map.of())); + m.setUnderstandability(new Understandability(1, Map.of())); + for (MetricName name : MetricName.values()) { + m.setValue(name, 1); + m.setWeight(name, 0.1); + } + }); + private final ScoredMethod b = method("y/B.java", "p.beta", "Two", m -> { + m.setCognitiveComplexity(2); + m.setHalstead(new HalsteadMetrics(2, 2, 2, 2)); + m.setCyclomatic(new CyclomaticComplexity(2, Map.of())); + m.setUnderstandability(new Understandability(2, Map.of())); + for (MetricName name : MetricName.values()) { + m.setValue(name, 2); + m.setWeight(name, 0.2); + } + }); + private final ScoredMethod c = method("x/C.java", "p.Gamma", "three", m -> { + m.setCognitiveComplexity(10); + m.setHalstead(new HalsteadMetrics(3, 3, 3, 3)); + m.setCyclomatic(new CyclomaticComplexity(11, Map.of())); + m.setUnderstandability(new Understandability(12, Map.of())); + for (MetricName name : MetricName.values()) { + m.setValue(name, 10); + m.setWeight(name, 1.5); + } + }); + + static List numericFields() { + return MetricsSorter.FIELDS.stream().filter(field -> !List.of("class", "method", "file").contains(field)).toList(); + } + + @ParameterizedTest + @MethodSource("numericFields") + void sortsNumbersByValueAscendingAndDescending(final String field) throws Exception { + List shuffled = List.of(c, a, b); + + assertThat(new MetricsSorter(field, "asc").sort(shuffled)).containsExactly(a, b, c); + assertThat(new MetricsSorter(field, "desc").sort(shuffled)).containsExactly(c, b, a); + } + + @Test + void comparesNumbersNumericallyAndNotAsText() throws Exception { + // as text "10" sorts before "2" + assertThat(new MetricsSorter("score", "asc").sort(List.of(c, b, a))).containsExactly(a, b, c); + } + + @Test + void sortsClassNamesIgnoringTheLetterCase() throws Exception { + // p.Alpha, p.beta, p.Gamma; a case-sensitive order would put p.beta last + assertThat(new MetricsSorter("class", "asc").sort(List.of(c, b, a))).containsExactly(a, b, c); + assertThat(new MetricsSorter("class", "desc").sort(List.of(a, b, c))).containsExactly(c, b, a); + } + + @Test + void sortsMethodNamesIgnoringTheLetterCase() throws Exception { + // one, Two, three: a case-sensitive order would put "Two" first + assertThat(new MetricsSorter("method", "asc").sort(List.of(b, c, a))).containsExactly(a, c, b); + } + + @Test + void sortsFilesByPath() throws Exception { + // x/C.java, y/B.java, z/A.java + assertThat(new MetricsSorter("file", "asc").sort(List.of(a, b, c))).containsExactly(c, b, a); + } + + @Test + void breaksTiesByClassAndThenMethodInBothDirections() throws Exception { + ScoredMethod sameScoreB = method("f", "p.B", "m", m -> m.setCognitiveComplexity(5)); + ScoredMethod sameScoreA2 = method("f", "p.A", "z", m -> m.setCognitiveComplexity(5)); + ScoredMethod sameScoreA1 = method("f", "p.A", "y", m -> m.setCognitiveComplexity(5)); + List input = List.of(sameScoreB, sameScoreA2, sameScoreA1); + + assertThat(new MetricsSorter("score", "asc").sort(input)).containsExactly(sameScoreA1, sameScoreA2, sameScoreB); + assertThat(new MetricsSorter("score", "desc").sort(input)).containsExactly(sameScoreA1, sameScoreA2, sameScoreB); + } + + @Test + void keepsTheGivenOrderOfMethodsThatAreEqualInEveryRespect() throws Exception { + ScoredMethod first = method("f1", "p.A", "m", m -> { }); + ScoredMethod second = method("f2", "p.A", "m", m -> { }); + + assertThat(new MetricsSorter("score", "asc").sort(List.of(second, first))).containsExactly(second, first); + } + + @Test + void acceptsTheOrderInAnyLetterCase() throws Exception { + assertThat(new MetricsSorter("score", "DESC").sort(List.of(a, c, b))).containsExactly(c, b, a); + assertThat(new MetricsSorter("score", "Asc").sort(List.of(c, b, a))).containsExactly(a, b, c); + } + + @Test + void leavesTheInputUntouchedAndReturnsANewList() throws Exception { + List input = List.of(c, a, b); + + List sorted = new MetricsSorter("score", "asc").sort(input); + + assertThat(sorted).isNotSameAs(input); + assertThat(input).containsExactly(c, a, b); + } + + @Test + void keepsTheGivenOrderWithoutAField() throws Exception { + List input = List.of(c, a, b); + + assertThat(new MetricsSorter(null, "desc").sort(input)).containsExactly(c, a, b); + } + + @Test + void listsTheFieldsInTheDocumentedOrder() { + assertThat(MetricsSorter.FIELDS).containsExactly( + "score", "halstead", "cyclomatic", "understandability", "class", "method", "file", + "lineCount", "argCount", "returnCount", "variableCount", "propertyCallCount", "ifCount", + "ifNestingLevel", "elseCount", + "lineCountWeight", "argCountWeight", "returnCountWeight", "variableCountWeight", + "propertyCallCountWeight", "ifCountWeight", "ifNestingLevelWeight", "elseCountWeight"); + } + + @Test + void rejectsAnUnknownField() { + assertThatThrownBy(() -> new MetricsSorter("bogus", "asc")) + .isInstanceOf(CognitiveAnalysisException.class) + .hasMessage("Invalid sort field \"bogus\". Available fields: " + String.join(", ", MetricsSorter.FIELDS)); + } + + @Test + void rejectsAFieldInTheWrongLetterCase() { + assertThatThrownBy(() -> new MetricsSorter("Score", "asc")) + .isInstanceOf(CognitiveAnalysisException.class) + .hasMessageStartingWith("Invalid sort field \"Score\""); + } + + @Test + void rejectsAnUnknownOrderNamingIt() { + assertThatThrownBy(() -> new MetricsSorter("score", "up")) + .isInstanceOf(CognitiveAnalysisException.class) + .hasMessage("Sort order must be \"asc\" or \"desc\", got \"up\""); + } + + @Test + void rejectsAnUnknownOrderWithoutAField() { + assertThatThrownBy(() -> new MetricsSorter(null, "")) + .isInstanceOf(CognitiveAnalysisException.class) + .hasMessage("Sort order must be \"asc\" or \"desc\", got \"\""); + } + + @Test + void reportsTheUnknownFieldBeforeTheUnknownOrder() { + assertThatThrownBy(() -> new MetricsSorter("bogus", "up")) + .hasMessageStartingWith("Invalid sort field"); + } + + private static ScoredMethod method( + final String file, final String className, final String methodName, final Consumer setup) { + CognitiveMetrics metrics = new CognitiveMetrics(className, methodName, 1); + setup.accept(metrics); + return new ScoredMethod(file, className + "::" + methodName, metrics); + } +} diff --git a/src/test/resources/fixtures/console/all-metrics.yaml b/src/test/resources/fixtures/console/all-metrics.yaml new file mode 100644 index 0000000..1a462e3 --- /dev/null +++ b/src/test/resources/fixtures/console/all-metrics.yaml @@ -0,0 +1,6 @@ +cognitive: + cache: + enabled: false + showHalsteadComplexity: true + showCyclomaticComplexity: true + showUnderstandability: true diff --git a/src/test/resources/fixtures/console/cyclomatic-only.yaml b/src/test/resources/fixtures/console/cyclomatic-only.yaml new file mode 100644 index 0000000..28738d9 --- /dev/null +++ b/src/test/resources/fixtures/console/cyclomatic-only.yaml @@ -0,0 +1,4 @@ +cognitive: + cache: + enabled: false + showCyclomaticComplexity: true diff --git a/src/test/resources/fixtures/console/halstead-only.yaml b/src/test/resources/fixtures/console/halstead-only.yaml new file mode 100644 index 0000000..71af127 --- /dev/null +++ b/src/test/resources/fixtures/console/halstead-only.yaml @@ -0,0 +1,4 @@ +cognitive: + cache: + enabled: false + showHalsteadComplexity: true diff --git a/src/test/resources/fixtures/console/minimal.yaml b/src/test/resources/fixtures/console/minimal.yaml new file mode 100644 index 0000000..bf29233 --- /dev/null +++ b/src/test/resources/fixtures/console/minimal.yaml @@ -0,0 +1,4 @@ +cognitive: + cache: + enabled: false + showDetailedCognitiveMetrics: false diff --git a/src/test/resources/fixtures/console/nothing-exceeds-single.yaml b/src/test/resources/fixtures/console/nothing-exceeds-single.yaml new file mode 100644 index 0000000..b87e9c7 --- /dev/null +++ b/src/test/resources/fixtures/console/nothing-exceeds-single.yaml @@ -0,0 +1,6 @@ +cognitive: + cache: + enabled: false + showOnlyMethodsExceedingThreshold: true + scoreThreshold: 100 + groupByClass: false diff --git a/src/test/resources/fixtures/console/nothing-exceeds.yaml b/src/test/resources/fixtures/console/nothing-exceeds.yaml new file mode 100644 index 0000000..5d4bd90 --- /dev/null +++ b/src/test/resources/fixtures/console/nothing-exceeds.yaml @@ -0,0 +1,5 @@ +cognitive: + cache: + enabled: false + showOnlyMethodsExceedingThreshold: true + scoreThreshold: 100 diff --git a/src/test/resources/fixtures/console/single-table.yaml b/src/test/resources/fixtures/console/single-table.yaml new file mode 100644 index 0000000..482dc21 --- /dev/null +++ b/src/test/resources/fixtures/console/single-table.yaml @@ -0,0 +1,6 @@ +cognitive: + cache: + enabled: false + groupByClass: false + showHalsteadComplexity: true + showCyclomaticComplexity: true diff --git a/src/test/resources/fixtures/console/threshold.yaml b/src/test/resources/fixtures/console/threshold.yaml new file mode 100644 index 0000000..245267c --- /dev/null +++ b/src/test/resources/fixtures/console/threshold.yaml @@ -0,0 +1,5 @@ +cognitive: + cache: + enabled: false + showOnlyMethodsExceedingThreshold: true + scoreThreshold: 0.5 diff --git a/src/test/resources/fixtures/console/understandability.yaml b/src/test/resources/fixtures/console/understandability.yaml new file mode 100644 index 0000000..c3b54ff --- /dev/null +++ b/src/test/resources/fixtures/console/understandability.yaml @@ -0,0 +1,4 @@ +cognitive: + cache: + enabled: false + showUnderstandability: true diff --git a/src/test/resources/fixtures/console/without-detailed.yaml b/src/test/resources/fixtures/console/without-detailed.yaml new file mode 100644 index 0000000..0b9d2f5 --- /dev/null +++ b/src/test/resources/fixtures/console/without-detailed.yaml @@ -0,0 +1,7 @@ +cognitive: + cache: + enabled: false + showDetailedCognitiveMetrics: false + showHalsteadComplexity: true + showCyclomaticComplexity: true + showUnderstandability: true From 3fceade0b03b7fc51845fac5d522bbd22ce76588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Thu, 12 Nov 2026 19:24:42 +0100 Subject: [PATCH 2/3] style: align console tables consistently and shorten weights Strip trailing zeros from weights, draw row separators only for tables with multi-line body cells, and share the terminal check between the init and analyse commands. --- README.md | 17 +- .../application/AnalyseCommand.java | 4 +- .../application/InitCommand.java | 36 +-- .../application/MetricFormatter.java | 3 +- .../application/Terminal.java | 47 ++++ .../application/TextTable.java | 6 +- .../application/AnalyseCommandE2ETest.java | 4 +- ...AndMethodsInStableSortedOrder.approved.txt | 42 ++- ...tsOneTablePerFileToTheConsole.approved.txt | 15 +- ...heMetricsOfEveryJavaConstruct.approved.txt | 243 ++++++++---------- ...utputE2ETest.printsAllMetrics.approved.txt | 57 ++-- ...rintsCyclomaticComplexityOnly.approved.txt | 57 ++-- ....printsHalsteadComplexityOnly.approved.txt | 57 ++-- ...SingleTableWithTheClassColumn.approved.txt | 30 +-- ...eMethodsExceedingTheThreshold.approved.txt | 12 +- ...2ETest.printsTheDefaultTables.approved.txt | 57 ++-- ...etricsWithoutTheDetailColumns.approved.txt | 3 - ...ETest.printsTheMinimalColumns.approved.txt | 3 - ...ETest.printsUnderstandability.approved.txt | 57 ++-- ...dsByScoreDescendingInOneTable.approved.txt | 30 +-- .../application/InitCommandTest.java | 8 +- .../application/MetricFormatterTest.java | 7 +- ...icAndUnderstandabilityColumns.approved.txt | 15 +- ...ClassWhenTheTableMixesClasses.approved.txt | 15 +- ...ColumnsWhenTheyAreSwitchedOff.approved.txt | 1 - ...odWithTheWeightNextToTheCount.approved.txt | 15 +- .../application/TextTableTest.java | 57 ++++ ...yChurnWithoutZeroScoreClasses.approved.txt | 1 - 28 files changed, 451 insertions(+), 448 deletions(-) create mode 100644 src/main/java/net/floriankraemer/cognitive_analysis/application/Terminal.java create mode 100644 src/test/java/net/floriankraemer/cognitive_analysis/application/TextTableTest.java diff --git a/README.md b/README.md index ff941c1..ec773e8 100644 --- a/README.md +++ b/README.md @@ -39,17 +39,16 @@ Found 1 files. Starting analysis. Class: test.testcode.ClassToAnalyze File: src/test/resources/fixtures/sample/ClassToAnalyze.java -┌────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ simpleMethod │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ -└────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌────────────────────────┬────────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├────────────────────────┼────────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────────┼────────────┤ +│ simpleMethod │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ methodWithTwoArguments │ 16 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 3 (0) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ +└────────────────────────┴────────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────────┴────────────┘ ``` -A cell of the detail columns reads `count (weight)`. +A cell of the detail columns reads `count (weight)`, with the weight shown with up to three decimals. The score is red above `scoreThreshold` and green otherwise, Halstead values and risk levels are yellow or red from their thresholds. Colors are used only on a terminal, and `NO_COLOR` switches them off. The settings that choose the columns and the grouping are described in [Configuration](./docs/Configuration.md#console-output). diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommand.java b/src/main/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommand.java index 05a490a..4ff93ff 100644 --- a/src/main/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommand.java +++ b/src/main/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommand.java @@ -103,9 +103,7 @@ public Iterator iterator() { /** Replaceable by tests: the clock of the stage timings, the colors and the terminal check. */ LongSupplier ticker = System::nanoTime; Ansi ansi = Ansi.AUTO; - // Approximation: System.console() is null when stdin or stdout is redirected, so progress may stay off with - // only stderr on a terminal; Java 22 has Console.isTerminal() to check stderr alone. - BooleanSupplier stderrIsTerminal = () -> System.console() != null; + BooleanSupplier stderrIsTerminal = Terminal::isAttached; private final ReportBuilder reportBuilder = new ReportBuilder( new HtmlReportBuilder(), new CsvReportBuilder(), new JsonReportBuilder()); diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/application/InitCommand.java b/src/main/java/net/floriankraemer/cognitive_analysis/application/InitCommand.java index 396e4b2..f9b72a5 100644 --- a/src/main/java/net/floriankraemer/cognitive_analysis/application/InitCommand.java +++ b/src/main/java/net/floriankraemer/cognitive_analysis/application/InitCommand.java @@ -1,11 +1,9 @@ package net.floriankraemer.cognitive_analysis.application; import java.io.BufferedReader; -import java.io.Console; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; -import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; import java.nio.file.AccessDeniedException; import java.nio.file.FileAlreadyExistsException; @@ -15,7 +13,6 @@ import java.nio.file.Path; import java.util.concurrent.Callable; import java.util.function.BooleanSupplier; -import java.util.function.Predicate; import net.floriankraemer.cognitive_analysis.CognitiveAnalysisException; import net.floriankraemer.cognitive_analysis.config.ConfigInitializer; import net.floriankraemer.cognitive_analysis.config.ConfigInitializer.Settings; @@ -33,8 +30,6 @@ ) public class InitCommand implements Callable { - private static final Predicate CONSOLE_IS_TERMINAL = consoleTerminalCheck(); - @Spec CommandSpec spec; @@ -59,7 +54,7 @@ public class InitCommand implements Callable { public InitCommand() { this( new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8)), - () -> isInteractive(System.console(), CONSOLE_IS_TERMINAL)); + Terminal::isAttached); } InitCommand(final BufferedReader input, final BooleanSupplier terminal) { @@ -129,33 +124,4 @@ static String reason(final IOException e) { private boolean asksQuestions() { return !silent && terminal.getAsBoolean(); } - - /** Questions need a console, and the console has to be a terminal rather than a redirected stream. */ - static boolean isInteractive(final C console, final Predicate isTerminal) { - return console != null && isTerminal.test(console); - } - - /** - * On JDK 22 and later {@code System.console()} is non-null even when the streams are redirected, and - * {@code Console.isTerminal()} tells the two cases apart. - * - *

ponytail: the compile release is 21, so {@code isTerminal} is looked up by reflection. Call it directly and - * drop the lookup once the release is 22 or later. - */ - static Predicate consoleTerminalCheck() { - final Method isTerminal; - try { - isTerminal = Console.class.getMethod("isTerminal"); - } catch (NoSuchMethodException e) { - // JDK 21: System.console() is only non-null when stdin and stdout are both terminals. - return console -> true; - } - return console -> { - try { - return (Boolean) isTerminal.invoke(console); - } catch (ReflectiveOperationException e) { - return false; - } - }; - } } diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/application/MetricFormatter.java b/src/main/java/net/floriankraemer/cognitive_analysis/application/MetricFormatter.java index 6ccfd14..9c35e2e 100644 --- a/src/main/java/net/floriankraemer/cognitive_analysis/application/MetricFormatter.java +++ b/src/main/java/net/floriankraemer/cognitive_analysis/application/MetricFormatter.java @@ -1,5 +1,6 @@ package net.floriankraemer.cognitive_analysis.application; +import java.math.BigDecimal; import java.util.Locale; import picocli.CommandLine.Help.Ansi; @@ -27,7 +28,7 @@ final class MetricFormatter { } String weighted(final int count, final double weight) { - return String.format(Locale.ROOT, "%d (%.3f)", count, weight); + return count + " (" + new BigDecimal(String.format(Locale.ROOT, "%.3f", weight)).stripTrailingZeros().toPlainString() + ")"; } String score(final double score) { diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/application/Terminal.java b/src/main/java/net/floriankraemer/cognitive_analysis/application/Terminal.java new file mode 100644 index 0000000..709f15b --- /dev/null +++ b/src/main/java/net/floriankraemer/cognitive_analysis/application/Terminal.java @@ -0,0 +1,47 @@ +package net.floriankraemer.cognitive_analysis.application; + +import java.io.Console; +import java.lang.reflect.Method; +import java.util.function.Predicate; + +/** Tells whether the process runs on a terminal rather than with redirected streams. */ +final class Terminal { + + private static final Predicate CONSOLE_IS_TERMINAL = consoleTerminalCheck(); + + private Terminal() {} + + /** True when the process has a console that is a terminal. */ + static boolean isAttached() { + return isInteractive(System.console(), CONSOLE_IS_TERMINAL); + } + + /** Input or output needs a console, and the console has to be a terminal rather than a redirected stream. */ + static boolean isInteractive(final C console, final Predicate isTerminal) { + return console != null && isTerminal.test(console); + } + + /** + * On JDK 22 and later {@code System.console()} is non-null even when the streams are redirected, and + * {@code Console.isTerminal()} tells the two cases apart. + * + *

ponytail: the compile release is 21, so {@code isTerminal} is looked up by reflection. Call it directly and + * drop the lookup once the release is 22 or later. + */ + static Predicate consoleTerminalCheck() { + final Method isTerminal; + try { + isTerminal = Console.class.getMethod("isTerminal"); + } catch (NoSuchMethodException e) { + // JDK 21: System.console() is only non-null when stdin and stdout are both terminals. + return console -> true; + } + return console -> { + try { + return (Boolean) isTerminal.invoke(console); + } catch (ReflectiveOperationException e) { + return false; + } + }; + } +} diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/application/TextTable.java b/src/main/java/net/floriankraemer/cognitive_analysis/application/TextTable.java index 45072b0..4b06cdb 100644 --- a/src/main/java/net/floriankraemer/cognitive_analysis/application/TextTable.java +++ b/src/main/java/net/floriankraemer/cognitive_analysis/application/TextTable.java @@ -6,7 +6,8 @@ /** * Renders rows of (possibly multi-line) cells as a box-drawing table. - * Column widths follow the widest line of each column, ANSI color codes not counted. + * Rows sit directly under each other unless a body cell spans several lines, which draws a line between + * the rows. Column widths follow the widest line of each column, ANSI color codes not counted. */ public final class TextTable { @@ -29,10 +30,11 @@ public String render(final List header, final List> rows) { final int[] widths = columnWidths(all, header.size()); final StringBuilder out = new StringBuilder(); + final boolean separateRows = rows.stream().anyMatch(row -> row.stream().anyMatch(cell -> cell.contains("\n"))); out.append(border('┌', '┬', '┐', widths)).append('\n'); for (int i = 0; i < all.size(); i++) { - if (i > 0) { + if (i == 1 || (i > 1 && separateRows)) { out.append(border('├', '┼', '┤', widths)).append('\n'); } appendRow(out, all.get(i), widths); diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.java b/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.java index 1f586dc..91f8252 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.java +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.java @@ -171,9 +171,9 @@ void reportsTheSameClassAndMethodInDifferentFilesForEachFile() { assertThat(out.toString().lines().filter(line -> line.startsWith("File: ") || line.startsWith("│ main"))) .containsExactly( "File: " + dir + "/m1/Main.java", - "│ main │ 3 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │", + "│ main │ 3 (0) │ 1 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │", "File: " + dir + "/m2/Main.java", - "│ main │ 5 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │"); + "│ main │ 5 (0) │ 1 (0) │ 0 (0) │ 0 (0) │ 1 (0) │ 1 (0) │ 1 (0) │ 0 (0) │ 0.000 │"); } @Test diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsFilesAndMethodsInStableSortedOrder.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsFilesAndMethodsInStableSortedOrder.approved.txt index 866bf41..42cf39c 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsFilesAndMethodsInStableSortedOrder.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsFilesAndMethodsInStableSortedOrder.approved.txt @@ -5,33 +5,31 @@ Found 2 files. Starting analysis. Class: multi.Alpha File: src/test/resources/fixtures/multi/Alpha.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ second │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ first │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┤ +│ second │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ first │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┘ Class: multi.Beta File: src/test/resources/fixtures/multi/Beta.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ zulu │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ alpha │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┤ +│ zulu │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ alpha │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┘ Class: multi.Helper File: src/test/resources/fixtures/multi/Alpha.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ run │ 5 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┤ +│ run │ 5 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 1 (0) │ 1 (0) │ 0 (0) │ 0.000 │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┘ Cognitive metrics calculated for src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsOneTablePerFileToTheConsole.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsOneTablePerFileToTheConsole.approved.txt index b6d4b73..ae656ec 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsOneTablePerFileToTheConsole.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsOneTablePerFileToTheConsole.approved.txt @@ -5,13 +5,12 @@ Found 1 files. Starting analysis. Class: test.testcode.ClassToAnalyze File: src/test/resources/fixtures/sample/ClassToAnalyze.java -┌────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ simpleMethod │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ -└────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌────────────────────────┬────────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├────────────────────────┼────────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────────┼────────────┤ +│ simpleMethod │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ methodWithTwoArguments │ 16 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 3 (0) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ +└────────────────────────┴────────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────────┴────────────┘ Cognitive metrics calculated for src/test/resources/fixtures/sample diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsTheMetricsOfEveryJavaConstruct.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsTheMetricsOfEveryJavaConstruct.approved.txt index 1428c68..979363e 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsTheMetricsOfEveryJavaConstruct.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommandE2ETest.printsTheMetricsOfEveryJavaConstruct.approved.txt @@ -5,177 +5,148 @@ Found 6 files. Starting analysis. Class: fixtures.cognitive.IfStatements File: src/test/resources/fixtures/cognitive/IfStatements.java -┌──────────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├──────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ chain │ 11 (0.000) │ 1 (0.000) │ 4 (0.336) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 3 (1.099) │ 1.435 │ -├──────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ nestedInThenAndElse │ 15 (0.000) │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 4 (0.693) │ 3 (1.099) │ 2 (0.693) │ 2.485 │ -├──────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ elseIfBodyNests │ 9 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 2 (0.000) │ 2 (0.693) │ 1 (0.000) │ 0.693 │ -├──────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ braceElseIf │ 9 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 2 (0.000) │ 2 (0.693) │ 1 (0.000) │ 0.693 │ -├──────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ ifsInLoopsTrySwitchAndLambda │ 39 (0.000) │ 1 (0.000) │ 0 (0.000) │ 3 (0.000) │ 0 (0.000) │ 7 (1.609) │ 1 (0.000) │ 0 (0.000) │ 1.609 │ -├──────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ ternariesDoNotCount │ 4 (0.000) │ 1 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├──────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ ifInsideLambdaInsideIf │ 9 (0.000) │ 1 (0.000) │ 0 (0.000) │ 1 (0.000) │ 0 (0.000) │ 2 (0.000) │ 2 (0.693) │ 0 (0.000) │ 0.693 │ -├──────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ log │ 3 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -└──────────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌──────────────────────────────┬────────┬───────────┬───────────┬───────────┬──────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├──────────────────────────────┼────────┼───────────┼───────────┼───────────┼──────────┼───────────┼────────────┼───────────┼────────────┤ +│ chain │ 11 (0) │ 1 (0) │ 4 (0.336) │ 0 (0) │ 0 (0) │ 1 (0) │ 1 (0) │ 3 (1.099) │ 1.435 │ +│ nestedInThenAndElse │ 15 (0) │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 4 (0.693) │ 3 (1.099) │ 2 (0.693) │ 2.485 │ +│ elseIfBodyNests │ 9 (0) │ 1 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 2 (0) │ 2 (0.693) │ 1 (0) │ 0.693 │ +│ braceElseIf │ 9 (0) │ 1 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 2 (0) │ 2 (0.693) │ 1 (0) │ 0.693 │ +│ ifsInLoopsTrySwitchAndLambda │ 39 (0) │ 1 (0) │ 0 (0) │ 3 (0) │ 0 (0) │ 7 (1.609) │ 1 (0) │ 0 (0) │ 1.609 │ +│ ternariesDoNotCount │ 4 (0) │ 1 (0) │ 1 (0) │ 1 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ ifInsideLambdaInsideIf │ 9 (0) │ 1 (0) │ 0 (0) │ 1 (0) │ 0 (0) │ 2 (0) │ 2 (0.693) │ 0 (0) │ 0.693 │ +│ log │ 3 (0) │ 1 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +└──────────────────────────────┴────────┴───────────┴───────────┴───────────┴──────────┴───────────┴────────────┴───────────┴────────────┘ Class: fixtures.cognitive.ModernJava File: src/test/resources/fixtures/cognitive/ModernJava.java -┌───────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├───────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ switchExpression │ 13 (0.000) │ 1 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ -├───────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ patternInstanceof │ 8 (0.000) │ 1 (0.000) │ 3 (0.182) │ 2 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0.182 │ -├───────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ patternSwitch │ 7 (0.000) │ 1 (0.000) │ 1 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├───────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ textBlock │ 7 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├───────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ unnamedVariables │ 9 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ -└───────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌───────────────────┬────────┬───────────┬───────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├───────────────────┼────────┼───────────┼───────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┤ +│ switchExpression │ 13 (0) │ 1 (0) │ 1 (0) │ 1 (0) │ 0 (0) │ 1 (0) │ 1 (0) │ 0 (0) │ 0.000 │ +│ patternInstanceof │ 8 (0) │ 1 (0) │ 3 (0.182) │ 2 (0) │ 0 (0) │ 1 (0) │ 1 (0) │ 1 (0) │ 0.182 │ +│ patternSwitch │ 7 (0) │ 1 (0) │ 1 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ textBlock │ 7 (0) │ 0 (0) │ 1 (0) │ 1 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ unnamedVariables │ 9 (0) │ 1 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 1 (0) │ 1 (0) │ 0 (0) │ 0.000 │ +└───────────────────┴────────┴───────────┴───────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┘ Class: fixtures.cognitive.PartiallyIgnored File: src/test/resources/fixtures/cognitive/Ignored.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ kept │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┤ +│ kept │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┘ Class: fixtures.cognitive.PartiallyIgnored.KeptNested File: src/test/resources/fixtures/cognitive/Ignored.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ kept │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┤ +│ kept │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┘ Class: fixtures.cognitive.Returns File: src/test/resources/fixtures/cognitive/Returns.java -┌─────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├─────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ returnsInLambdas │ 10 (0.000) │ 0 (0.000) │ 3 (0.182) │ 3 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.182 │ -├─────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ anonymousClassIsSkipped │ 15 (0.000) │ 1 (0.000) │ 1 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├─────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ localClassIsSkipped │ 18 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -└─────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌─────────────────────────┬────────┬───────────┬───────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────────────────┼────────┼───────────┼───────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┤ +│ returnsInLambdas │ 10 (0) │ 0 (0) │ 3 (0.182) │ 3 (0) │ 0 (0) │ 1 (0) │ 1 (0) │ 0 (0) │ 0.182 │ +│ anonymousClassIsSkipped │ 15 (0) │ 1 (0) │ 1 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ localClassIsSkipped │ 18 (0) │ 1 (0) │ 1 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +└─────────────────────────┴────────┴───────────┴───────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┘ Class: fixtures.cognitive.Units File: src/test/resources/fixtures/cognitive/Units.java -┌──────────────────────────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├──────────────────────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ Units() │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├──────────────────────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ Units(int) │ 3 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├──────────────────────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ abstractMethod │ 1 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├──────────────────────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ overloaded() │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├──────────────────────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ overloaded(List,Map) │ 2 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├──────────────────────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ overloaded(String...) │ 2 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├──────────────────────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ overloaded(int[],java.util.List) │ 2 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├──────────────────────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ generic │ 3 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -└──────────────────────────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌──────────────────────────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├──────────────────────────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┤ +│ Units() │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ Units(int) │ 3 (0) │ 1 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ abstractMethod │ 1 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ overloaded() │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ overloaded(List,Map) │ 2 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ overloaded(String...) │ 2 (0) │ 1 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ overloaded(int[],java.util.List) │ 2 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ generic │ 3 (0) │ 1 (0) │ 1 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +└──────────────────────────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┘ Class: fixtures.cognitive.Units.Color File: src/test/resources/fixtures/cognitive/Units.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ code │ 3 (0.000) │ 0 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┤ +│ code │ 3 (0) │ 0 (0) │ 1 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┘ Class: fixtures.cognitive.Units.Inner File: src/test/resources/fixtures/cognitive/Units.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ Inner │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┤ +│ Inner │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┘ Class: fixtures.cognitive.Units.Point File: src/test/resources/fixtures/cognitive/Units.java -┌────────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ Point(int,int) │ 5 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ -├────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ Point(int) │ 3 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├────────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ sum │ 3 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -└────────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌────────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├────────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┤ +│ Point(int,int) │ 5 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 1 (0) │ 1 (0) │ 0 (0) │ 0.000 │ +│ Point(int) │ 3 (0) │ 1 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ sum │ 3 (0) │ 0 (0) │ 1 (0) │ 1 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +└────────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┘ Class: fixtures.cognitive.Units.Shape File: src/test/resources/fixtures/cognitive/Units.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ describe │ 3 (0.000) │ 0 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ unit │ 3 (0.000) │ 0 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ helper │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┤ +│ describe │ 3 (0) │ 0 (0) │ 1 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ unit │ 3 (0) │ 0 (0) │ 1 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ helper │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┘ Class: fixtures.cognitive.Units.StaticNested File: src/test/resources/fixtures/cognitive/Units.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ inStatic │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┤ +│ inStatic │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┘ Class: fixtures.cognitive.Units.StaticNested.Deeper File: src/test/resources/fixtures/cognitive/Units.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ inDeeper │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┤ +│ inDeeper │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┘ Class: fixtures.cognitive.Variables File: src/test/resources/fixtures/cognitive/Variables.java -┌────────────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├────────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ distinctNames │ 12 (0.000) │ 1 (0.000) │ 1 (0.000) │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├────────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ lambdaCatchAndForEachVariables │ 17 (0.000) │ 1 (0.000) │ 0 (0.000) │ 4 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├────────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ fieldAccess │ 6 (0.000) │ 1 (0.000) │ 1 (0.000) │ 2 (0.000) │ 4 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├────────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ thisCountsOnce │ 6 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├────────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ shadowsField │ 4 (0.000) │ 0 (0.000) │ 1 (0.000) │ 2 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├────────────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ helper │ 2 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -└────────────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌────────────────────────────────┬────────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├────────────────────────────────┼────────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┤ +│ distinctNames │ 12 (0) │ 1 (0) │ 1 (0) │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ lambdaCatchAndForEachVariables │ 17 (0) │ 1 (0) │ 0 (0) │ 4 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ fieldAccess │ 6 (0) │ 1 (0) │ 1 (0) │ 2 (0) │ 4 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ thisCountsOnce │ 6 (0) │ 0 (0) │ 0 (0) │ 1 (0) │ 1 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ shadowsField │ 4 (0) │ 0 (0) │ 1 (0) │ 2 (0) │ 1 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ helper │ 2 (0) │ 1 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +└────────────────────────────────┴────────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┘ Cognitive metrics calculated for src/test/resources/fixtures/cognitive diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsAllMetrics.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsAllMetrics.approved.txt index bf5d1a9..a108078 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsAllMetrics.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsAllMetrics.approved.txt @@ -5,44 +5,41 @@ Found 3 files. Starting analysis. Class: multi.Alpha File: src/test/resources/fixtures/multi/Alpha.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┬────────────┬───────────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ Understandability │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ -│ second │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ -│ first │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┬──────────┬────────────┬──────────┬────────────┬───────────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ Understandability │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ second │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ +│ first │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ Class: multi.Beta File: src/test/resources/fixtures/multi/Beta.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┬────────────┬───────────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ Understandability │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ -│ zulu │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ -│ alpha │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┬──────────┬────────────┬──────────┬────────────┬───────────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ Understandability │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ zulu │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ +│ alpha │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ Class: multi.Helper File: src/test/resources/fixtures/multi/Alpha.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┬────────────┬───────────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ Understandability │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ -│ run │ 5 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ 19.65 │ 1.00 │ 19.65 │ 2 (low) │ 1 (low) │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┬──────────┬────────────┬──────────┬────────────┬───────────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ Understandability │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ run │ 5 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 1 (0) │ 1 (0) │ 0 (0) │ 0.000 │ 19.65 │ 1.00 │ 19.65 │ 2 (low) │ 1 (low) │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ Class: test.testcode.ClassToAnalyze File: src/test/resources/fixtures/sample/ClassToAnalyze.java -┌────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┬────────────┬───────────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ Understandability │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ -├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ -│ simpleMethod │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ -├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ -│ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ 106.30 │ 2.88 │ 305.62 │ 5 (low) │ 9 (medium) │ -└────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ +┌────────────────────────┬────────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┬────────────┬───────────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ Understandability │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ +├────────────────────────┼────────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ simpleMethod │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ +│ methodWithTwoArguments │ 16 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 3 (0) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ 106.30 │ 2.88 │ 305.62 │ 5 (low) │ 9 (medium) │ +└────────────────────────┴────────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ Cognitive metrics calculated for src/test/resources/fixtures/sample,src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsCyclomaticComplexityOnly.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsCyclomaticComplexityOnly.approved.txt index 4174eb4..0eef2f9 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsCyclomaticComplexityOnly.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsCyclomaticComplexityOnly.approved.txt @@ -5,44 +5,41 @@ Found 3 files. Starting analysis. Class: multi.Alpha File: src/test/resources/fixtures/multi/Alpha.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Cyclomatic │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Complexity │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼────────────┤ -│ second │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 1 (low) │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼────────────┤ -│ first │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 1 (low) │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Cyclomatic │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Complexity │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┼────────────┤ +│ second │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 1 (low) │ +│ first │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 1 (low) │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┴────────────┘ Class: multi.Beta File: src/test/resources/fixtures/multi/Beta.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Cyclomatic │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Complexity │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼────────────┤ -│ zulu │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 1 (low) │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼────────────┤ -│ alpha │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 1 (low) │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Cyclomatic │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Complexity │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┼────────────┤ +│ zulu │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 1 (low) │ +│ alpha │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 1 (low) │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┴────────────┘ Class: multi.Helper File: src/test/resources/fixtures/multi/Alpha.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Cyclomatic │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Complexity │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼────────────┤ -│ run │ 5 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ 2 (low) │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Cyclomatic │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Complexity │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┼────────────┤ +│ run │ 5 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 1 (0) │ 1 (0) │ 0 (0) │ 0.000 │ 2 (low) │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┴────────────┘ Class: test.testcode.ClassToAnalyze File: src/test/resources/fixtures/sample/ClassToAnalyze.java -┌────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Cyclomatic │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Complexity │ -├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼────────────┤ -│ simpleMethod │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 1 (low) │ -├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼────────────┤ -│ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ 5 (low) │ -└────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴────────────┘ +┌────────────────────────┬────────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────────┬────────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Cyclomatic │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Complexity │ +├────────────────────────┼────────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────────┼────────────┼────────────┤ +│ simpleMethod │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 1 (low) │ +│ methodWithTwoArguments │ 16 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 3 (0) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ 5 (low) │ +└────────────────────────┴────────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────────┴────────────┴────────────┘ Cognitive metrics calculated for src/test/resources/fixtures/sample,src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsHalsteadComplexityOnly.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsHalsteadComplexityOnly.approved.txt index eb40c9f..f84455b 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsHalsteadComplexityOnly.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsHalsteadComplexityOnly.approved.txt @@ -5,44 +5,41 @@ Found 3 files. Starting analysis. Class: multi.Alpha File: src/test/resources/fixtures/multi/Alpha.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┤ -│ second │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┤ -│ first │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┬──────────┬────────────┬──────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┼──────────┼────────────┼──────────┤ +│ second │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ +│ first │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┴──────────┴────────────┴──────────┘ Class: multi.Beta File: src/test/resources/fixtures/multi/Beta.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┤ -│ zulu │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┤ -│ alpha │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┬──────────┬────────────┬──────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┼──────────┼────────────┼──────────┤ +│ zulu │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ +│ alpha │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┴──────────┴────────────┴──────────┘ Class: multi.Helper File: src/test/resources/fixtures/multi/Alpha.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┤ -│ run │ 5 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ 19.65 │ 1.00 │ 19.65 │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┬──────────┬────────────┬──────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┼──────────┼────────────┼──────────┤ +│ run │ 5 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 1 (0) │ 1 (0) │ 0 (0) │ 0.000 │ 19.65 │ 1.00 │ 19.65 │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┴──────────┴────────────┴──────────┘ Class: test.testcode.ClassToAnalyze File: src/test/resources/fixtures/sample/ClassToAnalyze.java -┌────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ -├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┤ -│ simpleMethod │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ -├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┤ -│ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ 106.30 │ 2.88 │ 305.62 │ -└────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┘ +┌────────────────────────┬────────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ +├────────────────────────┼────────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┤ +│ simpleMethod │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ +│ methodWithTwoArguments │ 16 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 3 (0) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ 106.30 │ 2.88 │ 305.62 │ +└────────────────────────┴────────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┘ Cognitive metrics calculated for src/test/resources/fixtures/sample,src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsOneSingleTableWithTheClassColumn.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsOneSingleTableWithTheClassColumn.approved.txt index 61d4589..d3244cd 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsOneSingleTableWithTheClassColumn.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsOneSingleTableWithTheClassColumn.approved.txt @@ -4,23 +4,17 @@ Cache: disabled Found 3 files. Starting analysis. All Methods (7 total) -┌──────────────────────────────┬────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┬────────────┐ -│ Class │ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ -│ │ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ -├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ -│ multi.Alpha │ second │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ -├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ -│ multi.Alpha │ first │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ -├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ -│ multi.Helper │ run │ 5 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ 19.65 │ 1.00 │ 19.65 │ 2 (low) │ -├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ -│ multi.Beta │ zulu │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ -├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ -│ multi.Beta │ alpha │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ -├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ -│ test.testcode.ClassToAnalyze │ simpleMethod │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ -├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ -│ test.testcode.ClassToAnalyze │ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ 106.30 │ 2.88 │ 305.62 │ 5 (low) │ -└──────────────────────────────┴────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┴────────────┘ +┌──────────────────────────────┬────────────────────────┬────────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┬────────────┐ +│ Class │ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ +│ │ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ +├──────────────────────────────┼────────────────────────┼────────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ +│ multi.Alpha │ second │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +│ multi.Alpha │ first │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +│ multi.Helper │ run │ 5 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 1 (0) │ 1 (0) │ 0 (0) │ 0.000 │ 19.65 │ 1.00 │ 19.65 │ 2 (low) │ +│ multi.Beta │ zulu │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +│ multi.Beta │ alpha │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +│ test.testcode.ClassToAnalyze │ simpleMethod │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +│ test.testcode.ClassToAnalyze │ methodWithTwoArguments │ 16 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 3 (0) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ 106.30 │ 2.88 │ 305.62 │ 5 (low) │ +└──────────────────────────────┴────────────────────────┴────────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┴────────────┘ Cognitive metrics calculated for src/test/resources/fixtures/sample,src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsOnlyTheMethodsExceedingTheThreshold.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsOnlyTheMethodsExceedingTheThreshold.approved.txt index be5f024..7c2bb3a 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsOnlyTheMethodsExceedingTheThreshold.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsOnlyTheMethodsExceedingTheThreshold.approved.txt @@ -5,11 +5,11 @@ Found 3 files. Starting analysis. Class: test.testcode.ClassToAnalyze File: src/test/resources/fixtures/sample/ClassToAnalyze.java -┌────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ -└────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌────────────────────────┬────────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├────────────────────────┼────────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────────┼────────────┤ +│ methodWithTwoArguments │ 16 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 3 (0) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ +└────────────────────────┴────────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────────┴────────────┘ Cognitive metrics calculated for src/test/resources/fixtures/sample,src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheDefaultTables.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheDefaultTables.approved.txt index 2b495f6..c5358de 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheDefaultTables.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheDefaultTables.approved.txt @@ -5,44 +5,41 @@ Found 3 files. Starting analysis. Class: multi.Alpha File: src/test/resources/fixtures/multi/Alpha.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ second │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ first │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┤ +│ second │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ first │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┘ Class: multi.Beta File: src/test/resources/fixtures/multi/Beta.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ zulu │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ alpha │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┤ +│ zulu │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ alpha │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┘ Class: multi.Helper File: src/test/resources/fixtures/multi/Alpha.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ run │ 5 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┤ +│ run │ 5 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 1 (0) │ 1 (0) │ 0 (0) │ 0.000 │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┘ Class: test.testcode.ClassToAnalyze File: src/test/resources/fixtures/sample/ClassToAnalyze.java -┌────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ simpleMethod │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ -├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ -└────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ +┌────────────────────────┬────────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├────────────────────────┼────────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────────┼────────────┤ +│ simpleMethod │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ +│ methodWithTwoArguments │ 16 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 3 (0) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ +└────────────────────────┴────────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────────┴────────────┘ Cognitive metrics calculated for src/test/resources/fixtures/sample,src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheMetricsWithoutTheDetailColumns.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheMetricsWithoutTheDetailColumns.approved.txt index 71f95b8..301441d 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheMetricsWithoutTheDetailColumns.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheMetricsWithoutTheDetailColumns.approved.txt @@ -10,7 +10,6 @@ File: src/test/resources/fixtures/multi/Alpha.java │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ ├─────────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ │ second │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ -├─────────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ │ first │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ └─────────────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ @@ -21,7 +20,6 @@ File: src/test/resources/fixtures/multi/Beta.java │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ ├─────────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ │ zulu │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ -├─────────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ │ alpha │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ └─────────────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ @@ -41,7 +39,6 @@ File: src/test/resources/fixtures/sample/ClassToAnalyze.java │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ ├────────────────────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ │ simpleMethod │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ 0 (low) │ -├────────────────────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ │ methodWithTwoArguments │ 2.197 │ 106.30 │ 2.88 │ 305.62 │ 5 (low) │ 9 (medium) │ └────────────────────────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheMinimalColumns.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheMinimalColumns.approved.txt index 7be35c4..a1638ff 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheMinimalColumns.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsTheMinimalColumns.approved.txt @@ -10,7 +10,6 @@ File: src/test/resources/fixtures/multi/Alpha.java │ │ Complexity │ ├─────────────┼────────────┤ │ second │ 0.000 │ -├─────────────┼────────────┤ │ first │ 0.000 │ └─────────────┴────────────┘ @@ -21,7 +20,6 @@ File: src/test/resources/fixtures/multi/Beta.java │ │ Complexity │ ├─────────────┼────────────┤ │ zulu │ 0.000 │ -├─────────────┼────────────┤ │ alpha │ 0.000 │ └─────────────┴────────────┘ @@ -41,7 +39,6 @@ File: src/test/resources/fixtures/sample/ClassToAnalyze.java │ │ Complexity │ ├────────────────────────┼────────────┤ │ simpleMethod │ 0.000 │ -├────────────────────────┼────────────┤ │ methodWithTwoArguments │ 2.197 │ └────────────────────────┴────────────┘ diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsUnderstandability.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsUnderstandability.approved.txt index 791b9de..1471cf6 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsUnderstandability.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.printsUnderstandability.approved.txt @@ -5,44 +5,41 @@ Found 3 files. Starting analysis. Class: multi.Alpha File: src/test/resources/fixtures/multi/Alpha.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬───────────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Understandability │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼───────────────────┤ -│ second │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 0 (low) │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼───────────────────┤ -│ first │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 0 (low) │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴───────────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┬───────────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Understandability │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┼───────────────────┤ +│ second │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 0 (low) │ +│ first │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 0 (low) │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┴───────────────────┘ Class: multi.Beta File: src/test/resources/fixtures/multi/Beta.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬───────────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Understandability │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼───────────────────┤ -│ zulu │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 0 (low) │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼───────────────────┤ -│ alpha │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 0 (low) │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴───────────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┬───────────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Understandability │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┼───────────────────┤ +│ zulu │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 0 (low) │ +│ alpha │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 0 (low) │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┴───────────────────┘ Class: multi.Helper File: src/test/resources/fixtures/multi/Alpha.java -┌─────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬───────────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Understandability │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ │ -├─────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼───────────────────┤ -│ run │ 5 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ 1 (low) │ -└─────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴───────────────────┘ +┌─────────────┬───────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────┬────────────┬───────────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Understandability │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ │ +├─────────────┼───────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────┼────────────┼───────────────────┤ +│ run │ 5 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 1 (0) │ 1 (0) │ 0 (0) │ 0.000 │ 1 (low) │ +└─────────────┴───────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────┴────────────┴───────────────────┘ Class: test.testcode.ClassToAnalyze File: src/test/resources/fixtures/sample/ClassToAnalyze.java -┌────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬───────────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Understandability │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ │ -├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼───────────────────┤ -│ simpleMethod │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 0 (low) │ -├────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼───────────────────┤ -│ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ 9 (medium) │ -└────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴───────────────────┘ +┌────────────────────────┬────────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────────┬────────────┬───────────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Understandability │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ │ +├────────────────────────┼────────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────────┼────────────┼───────────────────┤ +│ simpleMethod │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 0 (low) │ +│ methodWithTwoArguments │ 16 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 3 (0) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ 9 (medium) │ +└────────────────────────┴────────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────────┴────────────┴───────────────────┘ Cognitive metrics calculated for src/test/resources/fixtures/sample,src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.sortsAllMethodsByScoreDescendingInOneTable.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.sortsAllMethodsByScoreDescendingInOneTable.approved.txt index b9321af..fbd91f7 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.sortsAllMethodsByScoreDescendingInOneTable.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.sortsAllMethodsByScoreDescendingInOneTable.approved.txt @@ -4,23 +4,17 @@ Cache: disabled Found 3 files. Starting analysis. All Methods (7 total) -┌──────────────────────────────┬────────────────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┬────────────┐ -│ Class │ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ -│ │ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ -├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ -│ test.testcode.ClassToAnalyze │ methodWithTwoArguments │ 16 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 3 (0.000) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ 106.30 │ 2.88 │ 305.62 │ 5 (low) │ -├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ -│ multi.Alpha │ first │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ -├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ -│ multi.Alpha │ second │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ -├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ -│ multi.Beta │ alpha │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ -├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ -│ multi.Beta │ zulu │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ -├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ -│ multi.Helper │ run │ 5 (0.000) │ 2 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 1 (0.000) │ 1 (0.000) │ 0 (0.000) │ 0.000 │ 19.65 │ 1.00 │ 19.65 │ 2 (low) │ -├──────────────────────────────┼────────────────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ -│ test.testcode.ClassToAnalyze │ simpleMethod │ 3 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ -└──────────────────────────────┴────────────────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┴────────────┘ +┌──────────────────────────────┬────────────────────────┬────────┬───────────┬─────────┬───────────┬──────────┬───────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┬────────────┐ +│ Class │ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ +│ │ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ +├──────────────────────────────┼────────────────────────┼────────┼───────────┼─────────┼───────────┼──────────┼───────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┤ +│ test.testcode.ClassToAnalyze │ methodWithTwoArguments │ 16 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 3 (0) │ 3 (1.099) │ 3 (1.099) │ 2.197 │ 106.30 │ 2.88 │ 305.62 │ 5 (low) │ +│ multi.Alpha │ first │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +│ multi.Alpha │ second │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +│ multi.Beta │ alpha │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +│ multi.Beta │ zulu │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +│ multi.Helper │ run │ 5 (0) │ 2 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 1 (0) │ 1 (0) │ 0 (0) │ 0.000 │ 19.65 │ 1.00 │ 19.65 │ 2 (low) │ +│ test.testcode.ClassToAnalyze │ simpleMethod │ 3 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0.000 │ 8.00 │ 0.50 │ 4.00 │ 1 (low) │ +└──────────────────────────────┴────────────────────────┴────────┴───────────┴─────────┴───────────┴──────────┴───────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┴────────────┘ Cognitive metrics calculated for src/test/resources/fixtures/sample,src/test/resources/fixtures/multi diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/InitCommandTest.java b/src/test/java/net/floriankraemer/cognitive_analysis/application/InitCommandTest.java index 922fe73..8c60dc7 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/InitCommandTest.java +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/InitCommandTest.java @@ -377,14 +377,14 @@ void theInteractiveDefaultsAreTheBundledDefaults() throws Exception { @Test void aConsoleThatIsNotATerminalAsksNoQuestions() { - assertThat(InitCommand.isInteractive(null, console -> true)).isFalse(); - assertThat(InitCommand.isInteractive("console", console -> false)).isFalse(); - assertThat(InitCommand.isInteractive("console", console -> true)).isTrue(); + assertThat(Terminal.isInteractive(null, console -> true)).isFalse(); + assertThat(Terminal.isInteractive("console", console -> false)).isFalse(); + assertThat(Terminal.isInteractive("console", console -> true)).isTrue(); } @Test void theTerminalCheckIsNotConsultedWithoutAConsole() { - assertThat(InitCommand.isInteractive(null, console -> { + assertThat(Terminal.isInteractive(null, console -> { throw new AssertionError("no console to check"); })).isFalse(); } diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/MetricFormatterTest.java b/src/test/java/net/floriankraemer/cognitive_analysis/application/MetricFormatterTest.java index 543420f..1646262 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/MetricFormatterTest.java +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/MetricFormatterTest.java @@ -16,12 +16,15 @@ class MetricFormatterTest { private final MetricFormatter plain = new MetricFormatter(0.5, Ansi.OFF); @Test - void showsTheWeightWithThreeDecimalsRegardlessOfTheLocale() { + void showsTheWeightWithUpToThreeDecimalsRegardlessOfTheLocale() { Locale original = Locale.getDefault(); Locale.setDefault(Locale.GERMANY); try { assertThat(plain.weighted(4, 1.0986)).isEqualTo("4 (1.099)"); - assertThat(plain.weighted(0, 0)).isEqualTo("0 (0.000)"); + assertThat(plain.weighted(0, 0)).isEqualTo("0 (0)"); + assertThat(plain.weighted(7, 1.5)).isEqualTo("7 (1.5)"); + assertThat(plain.weighted(5, 0.6931)).isEqualTo("5 (0.693)"); + assertThat(plain.weighted(5, 2.0004)).isEqualTo("5 (2)"); } finally { Locale.setDefault(original); } diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.addsTheHalsteadCyclomaticAndUnderstandabilityColumns.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.addsTheHalsteadCyclomaticAndUnderstandabilityColumns.approved.txt index 4d36fd6..4c7c194 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.addsTheHalsteadCyclomaticAndUnderstandabilityColumns.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.addsTheHalsteadCyclomaticAndUnderstandabilityColumns.approved.txt @@ -1,8 +1,7 @@ -┌──────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┬────────────┬───────────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ Understandability │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ -├──────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ -│ method1 │ 1 (0.000) │ 2 (0.000) │ 3 (0.000) │ 4 (0.000) │ 5 (0.000) │ 6 (0.693) │ 7 (0.000) │ 8 (0.000) │ 5.000 │ 58.95 │ 3.38 │ 198.97 │ 3 (low) │ 2 (low) │ -├──────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ -│ method2(int) │ 15 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 2 (0.406) │ 7.500 │ 0.00 │ 0.00 │ 0.00 │ 1 (low) │ 0 (low) │ -└──────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ \ No newline at end of file +┌──────────────┬────────┬───────────┬─────────┬───────────┬──────────┬───────────┬────────────┬───────────┬────────────┬──────────┬────────────┬──────────┬────────────┬───────────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ Halstead │ Halstead │ Halstead │ Cyclomatic │ Understandability │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ Volume │ Difficulty │ Effort │ Complexity │ │ +├──────────────┼────────┼───────────┼─────────┼───────────┼──────────┼───────────┼────────────┼───────────┼────────────┼──────────┼────────────┼──────────┼────────────┼───────────────────┤ +│ method1 │ 1 (0) │ 2 (0) │ 3 (0) │ 4 (0) │ 5 (0) │ 6 (0.693) │ 7 (0) │ 8 (0) │ 5.000 │ 58.95 │ 3.38 │ 198.97 │ 3 (low) │ 2 (low) │ +│ method2(int) │ 15 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 2 (0.406) │ 7.500 │ 0.00 │ 0.00 │ 0.00 │ 1 (low) │ 0 (low) │ +└──────────────┴────────┴───────────┴─────────┴───────────┴──────────┴───────────┴────────────┴───────────┴────────────┴──────────┴────────────┴──────────┴────────────┴───────────────────┘ \ No newline at end of file diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.leadsWithTheClassWhenTheTableMixesClasses.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.leadsWithTheClassWhenTheTableMixesClasses.approved.txt index 7a47a8d..8d96b1c 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.leadsWithTheClassWhenTheTableMixesClasses.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.leadsWithTheClassWhenTheTableMixesClasses.approved.txt @@ -1,8 +1,7 @@ -┌──────────────┬──────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Class │ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├──────────────┼──────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ a.TestClass1 │ method1 │ 1 (0.000) │ 2 (0.000) │ 3 (0.000) │ 4 (0.000) │ 5 (0.000) │ 6 (0.693) │ 7 (0.000) │ 8 (0.000) │ 5.000 │ -├──────────────┼──────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ a.TestClass2 │ method2(int) │ 15 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 2 (0.406) │ 7.500 │ -└──────────────┴──────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ \ No newline at end of file +┌──────────────┬──────────────┬────────┬───────────┬─────────┬───────────┬──────────┬───────────┬────────────┬───────────┬────────────┐ +│ Class │ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├──────────────┼──────────────┼────────┼───────────┼─────────┼───────────┼──────────┼───────────┼────────────┼───────────┼────────────┤ +│ a.TestClass1 │ method1 │ 1 (0) │ 2 (0) │ 3 (0) │ 4 (0) │ 5 (0) │ 6 (0.693) │ 7 (0) │ 8 (0) │ 5.000 │ +│ a.TestClass2 │ method2(int) │ 15 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 2 (0.406) │ 7.500 │ +└──────────────┴──────────────┴────────┴───────────┴─────────┴───────────┴──────────┴───────────┴────────────┴───────────┴────────────┘ \ No newline at end of file diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.leavesOutTheDetailColumnsWhenTheyAreSwitchedOff.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.leavesOutTheDetailColumnsWhenTheyAreSwitchedOff.approved.txt index 840862f..1b4aa92 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.leavesOutTheDetailColumnsWhenTheyAreSwitchedOff.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.leavesOutTheDetailColumnsWhenTheyAreSwitchedOff.approved.txt @@ -3,6 +3,5 @@ │ │ Complexity │ ├──────────────┼────────────┤ │ method1 │ 5.000 │ -├──────────────┼────────────┤ │ method2(int) │ 7.500 │ └──────────────┴────────────┘ \ No newline at end of file diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.rendersOneRowPerMethodWithTheWeightNextToTheCount.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.rendersOneRowPerMethodWithTheWeightNextToTheCount.approved.txt index 45f3dc3..aad841e 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.rendersOneRowPerMethodWithTheWeightNextToTheCount.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ResultTableBuilderTest.rendersOneRowPerMethodWithTheWeightNextToTheCount.approved.txt @@ -1,8 +1,7 @@ -┌──────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┬────────────┬───────────┬────────────┐ -│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ -│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ -├──────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ method1 │ 1 (0.000) │ 2 (0.000) │ 3 (0.000) │ 4 (0.000) │ 5 (0.000) │ 6 (0.693) │ 7 (0.000) │ 8 (0.000) │ 5.000 │ -├──────────────┼────────────┼───────────┼───────────┼───────────┼───────────┼───────────┼────────────┼───────────┼────────────┤ -│ method2(int) │ 15 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 0 (0.000) │ 2 (0.406) │ 7.500 │ -└──────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┴────────────┴───────────┴────────────┘ \ No newline at end of file +┌──────────────┬────────┬───────────┬─────────┬───────────┬──────────┬───────────┬────────────┬───────────┬────────────┐ +│ Method Name │ Lines │ Arguments │ Returns │ Variables │ Property │ If │ If Nesting │ Else │ Cognitive │ +│ │ │ │ │ │ Accesses │ │ Level │ │ Complexity │ +├──────────────┼────────┼───────────┼─────────┼───────────┼──────────┼───────────┼────────────┼───────────┼────────────┤ +│ method1 │ 1 (0) │ 2 (0) │ 3 (0) │ 4 (0) │ 5 (0) │ 6 (0.693) │ 7 (0) │ 8 (0) │ 5.000 │ +│ method2(int) │ 15 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 0 (0) │ 2 (0.406) │ 7.500 │ +└──────────────┴────────┴───────────┴─────────┴───────────┴──────────┴───────────┴────────────┴───────────┴────────────┘ \ No newline at end of file diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/TextTableTest.java b/src/test/java/net/floriankraemer/cognitive_analysis/application/TextTableTest.java new file mode 100644 index 0000000..31cf235 --- /dev/null +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/TextTableTest.java @@ -0,0 +1,57 @@ +package net.floriankraemer.cognitive_analysis.application; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import org.junit.jupiter.api.Test; + +class TextTableTest { + + private final TextTable table = new TextTable(1); + + @Test + void putsSingleLineRowsDirectlyUnderEachOtherBelowTheHeaderLine() { + assertThat(table.render(List.of("Name", "N"), List.of(List.of("a", "1"), List.of("b", "2")))).isEqualTo(""" + ┌──────┬───┐ + │ Name │ N │ + ├──────┼───┤ + │ a │ 1 │ + │ b │ 2 │ + └──────┴───┘"""); + } + + @Test + void drawsALineBetweenTheRowsWhenABodyCellHasSeveralLines() { + assertThat(table.render(List.of("Name", "N"), List.of(List.of("a", "1\nΔ +1"), List.of("b", "2")))).isEqualTo(""" + ┌──────┬──────┐ + │ Name │ N │ + ├──────┼──────┤ + │ a │ 1 │ + │ │ Δ +1 │ + ├──────┼──────┤ + │ b │ 2 │ + └──────┴──────┘"""); + } + + @Test + void ignoresMultiLineHeadersWhenDecidingOnRowLines() { + assertThat(table.render(List.of("Na\nme", "N"), List.of(List.of("a", "1"), List.of("b", "2")))).isEqualTo(""" + ┌────┬───┐ + │ Na │ N │ + │ me │ │ + ├────┼───┤ + │ a │ 1 │ + │ b │ 2 │ + └────┴───┘"""); + } + + @Test + void measuresTheWidthWithoutColorCodes() { + assertThat(table.render(List.of("N"), List.of(List.of("\u001B[31m1\u001B[39m")))).isEqualTo(""" + ┌───┐ + │ N │ + ├───┤ + │ \u001B[31m1\u001B[39m │ + └───┘"""); + } +} diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/churn/ChurnCommandE2ETest.printsAChurnTableSortedByChurnWithoutZeroScoreClasses.approved.txt b/src/test/java/net/floriankraemer/cognitive_analysis/churn/ChurnCommandE2ETest.printsAChurnTableSortedByChurnWithoutZeroScoreClasses.approved.txt index 58460ff..e106cc0 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/churn/ChurnCommandE2ETest.printsAChurnTableSortedByChurnWithoutZeroScoreClasses.approved.txt +++ b/src/test/java/net/floriankraemer/cognitive_analysis/churn/ChurnCommandE2ETest.printsAChurnTableSortedByChurnWithoutZeroScoreClasses.approved.txt @@ -2,6 +2,5 @@ │ Class │ Score │ Churn │ Times Changed │ ├─────────────┼───────┼───────┼───────────────┤ │ churn.Busy │ 2.197 │ 6.591 │ 3 │ -├─────────────┼───────┼───────┼───────────────┤ │ churn.Light │ 0.693 │ 1.386 │ 2 │ └─────────────┴───────┴───────┴───────────────┘ From 97a673c204b8e47d471f92c299f0e1e36affe58c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Thu, 12 Nov 2026 19:32:28 +0100 Subject: [PATCH 3/3] fix: keep progress off redirected streams and measure wide characters Write the progress line to the terminal itself, only when interactive, and clear it before warnings and failures. Count East Asian wide characters as two columns and combining marks as none when aligning tables. --- README.md | 2 +- .../application/AnalyseCommand.java | 12 +-- .../application/ProgressIndicator.java | 73 +++++++++++++++---- .../application/TextTable.java | 42 ++++++++++- .../application/ConsoleOutputE2ETest.java | 58 +++++++++++---- .../application/TextTableTest.java | 49 +++++++++++++ 6 files changed, 201 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index ec773e8..5b3629a 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ Reports follow the same order. Within a class table the methods keep the sort order, and the class tables themselves are always ordered by class name. Use `--debug` to print the time of each stage (`config`, `discovery`, `analysis`, `sorting`, `output`) and the counters `filesFound`, `filesAnalysed`, `filesFailed`, `methodsAnalysed`, `cacheHits` and `cacheMisses` after the run. -On a terminal, a progress line on the error stream shows how many files are analysed. +On a terminal, a progress line written to the terminal itself shows how many files are analysed; it never reaches redirected output. Write an HTML, CSV or JSON report instead: diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommand.java b/src/main/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommand.java index 4ff93ff..e8d303d 100644 --- a/src/main/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommand.java +++ b/src/main/java/net/floriankraemer/cognitive_analysis/application/AnalyseCommand.java @@ -7,7 +7,7 @@ import java.util.List; import java.util.Locale; import java.util.concurrent.Callable; -import java.util.function.BooleanSupplier; +import java.util.function.Supplier; import java.util.function.LongSupplier; import net.floriankraemer.cognitive_analysis.CognitiveAnalysisException; import net.floriankraemer.cognitive_analysis.application.report.CsvReportBuilder; @@ -103,14 +103,16 @@ public Iterator iterator() { /** Replaceable by tests: the clock of the stage timings, the colors and the terminal check. */ LongSupplier ticker = System::nanoTime; Ansi ansi = Ansi.AUTO; - BooleanSupplier stderrIsTerminal = Terminal::isAttached; + /** The terminal the progress goes to, or null when the process is not interactive. */ + Supplier terminalWriter = () -> Terminal.isAttached() ? System.console().writer() : null; private final ReportBuilder reportBuilder = new ReportBuilder( new HtmlReportBuilder(), new CsvReportBuilder(), new JsonReportBuilder()); @Override public Integer call() { - final PrintWriter err = spec.commandLine().getErr(); + final ProgressIndicator progress = new ProgressIndicator(terminalWriter.get(), ansi.enabled()); + final PrintWriter err = progress.clearingBefore(spec.commandLine().getErr()); if ((reportType == null) != (reportFile == null)) { err.println("Both report type and file must be provided."); @@ -133,9 +135,9 @@ public Integer call() { out.println("Found " + files.size() + " files. Starting analysis."); summary.endStage("discovery"); - final ProgressIndicator progress = new ProgressIndicator(err, stderrIsTerminal.getAsBoolean(), files.size()); + progress.start(files.size()); final MetricsCollection analysed = facade.analyse(files, file -> progress.advance()); - progress.finish(); + progress.clear(); summary.endStage("analysis"); final List methods = sorter.sort(analysed.methods()); diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/application/ProgressIndicator.java b/src/main/java/net/floriankraemer/cognitive_analysis/application/ProgressIndicator.java index 0467d3d..2c3e13b 100644 --- a/src/main/java/net/floriankraemer/cognitive_analysis/application/ProgressIndicator.java +++ b/src/main/java/net/floriankraemer/cognitive_analysis/application/ProgressIndicator.java @@ -1,33 +1,76 @@ package net.floriankraemer.cognitive_analysis.application; +import java.io.IOException; import java.io.PrintWriter; +import java.io.Writer; -/** Rewrites one line on the error stream with the number of analysed files; silent when disabled. */ +/** + * Rewrites one line with the number of analysed files. It writes to the terminal itself, never to the output + * or error stream, so redirected streams stay free of it. Without a terminal it does nothing. + */ final class ProgressIndicator { - private final PrintWriter err; - private final boolean enabled; - private final int total; + private static final String ERASE_TO_END = "\u001B[K"; + + private final PrintWriter terminal; + private final boolean ansi; + private int total; private int done; + private int lineLength; + + /** + * @param terminal the writer of the terminal, or null when the process is not interactive + * @param ansi whether the terminal takes control sequences; else the line is cleared with spaces + */ + ProgressIndicator(final PrintWriter terminal, final boolean ansi) { + this.terminal = terminal; + this.ansi = ansi; + } - ProgressIndicator(final PrintWriter err, final boolean enabled, final int total) { - this.err = err; - this.enabled = enabled; - this.total = total; + void start(final int fileCount) { + total = fileCount; + done = 0; } void advance() { done++; - if (enabled) { - err.print("\rAnalysing " + done + "/" + total); - err.flush(); + if (terminal == null) { + return; } + final String line = "Analysing " + done + "/" + total; + terminal.print("\r" + line); + terminal.flush(); + lineLength = line.length(); } - /** Ends the progress line, so later output starts on a fresh one. */ - void finish() { - if (enabled && done > 0) { - err.println(); + /** Removes the progress line, so the next output starts on a clean line. Does nothing when none is shown. */ + void clear() { + if (terminal == null || lineLength == 0) { + return; } + terminal.print("\r" + (ansi ? ERASE_TO_END : " ".repeat(lineLength) + "\r")); + terminal.flush(); + lineLength = 0; + } + + /** A writer that clears the progress line before it passes anything on to the target. */ + PrintWriter clearingBefore(final PrintWriter target) { + return new PrintWriter(new Writer() { + @Override + public void write(final char[] buffer, final int offset, final int length) { + clear(); + target.write(buffer, offset, length); + } + + @Override + public void flush() { + target.flush(); + } + + @Override + public void close() throws IOException { + target.close(); + } + }, true); } } diff --git a/src/main/java/net/floriankraemer/cognitive_analysis/application/TextTable.java b/src/main/java/net/floriankraemer/cognitive_analysis/application/TextTable.java index 4b06cdb..92e068d 100644 --- a/src/main/java/net/floriankraemer/cognitive_analysis/application/TextTable.java +++ b/src/main/java/net/floriankraemer/cognitive_analysis/application/TextTable.java @@ -16,6 +16,8 @@ public final class TextTable { /** Spaces between the border and the text of a cell, on each side. */ private static final int PADDING = 1; + private static final int ZERO_WIDTH_JOINER = 0x200D; + /** Columns from this index on are centered; earlier ones are left-aligned. */ private final int firstCenteredColumn; @@ -85,7 +87,45 @@ private String border(final char left, final char middle, final char right, fina return line.toString(); } + /** + * The number of terminal columns of a text: color codes take none, combining marks take none, and wide + * characters take two. + * + *

ponytail: the wide ranges are an approximate East Asian Width table (CJK, Hiragana, Katakana, Hangul, + * fullwidth forms and the common emoji blocks). Characters outside it count as one column; take a full + * Unicode table if exact widths of rare scripts matter. + */ private static int visibleLength(final String text) { - return ANSI_CODE.matcher(text).replaceAll("").length(); + final String plain = ANSI_CODE.matcher(text).replaceAll(""); + int width = 0; + for (int i = 0; i < plain.length(); ) { + final int codePoint = plain.codePointAt(i); + width += columns(codePoint); + i += Character.charCount(codePoint); + } + return width; + } + + private static int columns(final int codePoint) { + final int type = Character.getType(codePoint); + if (type == Character.NON_SPACING_MARK || type == Character.ENCLOSING_MARK + || codePoint == ZERO_WIDTH_JOINER || (codePoint >= 0xFE00 && codePoint <= 0xFE0F)) { + return 0; + } + return isWide(codePoint) ? 2 : 1; + } + + private static boolean isWide(final int c) { + return (c >= 0x1100 && c <= 0x115F) + || (c >= 0x2E80 && c <= 0xA4CF) + || (c >= 0xAC00 && c <= 0xD7A3) + || (c >= 0xF900 && c <= 0xFAFF) + || (c >= 0xFE30 && c <= 0xFE6F) + || (c >= 0xFF00 && c <= 0xFF60) + || (c >= 0xFFE0 && c <= 0xFFE6) + || (c >= 0x1F300 && c <= 0x1F64F) + || (c >= 0x1F680 && c <= 0x1F6FF) + || (c >= 0x1F900 && c <= 0x1F9FF) + || (c >= 0x20000 && c <= 0x3FFFD); } } diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.java b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.java index ad4e1df..0f38f0d 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.java +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/ConsoleOutputE2ETest.java @@ -32,7 +32,8 @@ class ConsoleOutputE2ETest { private final StringWriter out = new StringWriter(); private final StringWriter err = new StringWriter(); private Ansi ansi = Ansi.OFF; - private boolean terminal; + /** The terminal the progress goes to; null when the process is not interactive. */ + private StringWriter terminal; private AtomicLong now; // --- golden files, one per combination of the console options --- @@ -146,7 +147,7 @@ void printsNothingBeforeAFailingConfigurationIsLoaded() { } @Test - void printsNoProgressWhenTheErrorStreamIsNotATerminal() { + void printsNoProgressWhenTheProcessIsNotInteractive() { assertThat(run("analyse", SOURCES, "-c", NO_CACHE)).isZero(); assertThat(err.toString()).isEmpty(); @@ -154,32 +155,63 @@ void printsNoProgressWhenTheErrorStreamIsNotATerminal() { } @Test - void printsProgressOnTheErrorStreamWhenItIsATerminal() { - terminal = true; + void printsProgressOnlyToTheTerminalAndClearsItWithSpacesWithoutAnsi() { + terminal = new StringWriter(); assertThat(run("analyse", SOURCES, "-c", NO_CACHE)).isZero(); - assertThat(err.toString()).isEqualTo("\rAnalysing 1/3\rAnalysing 2/3\rAnalysing 3/3\n"); - assertThat(out.toString()).doesNotContain("Analysing"); + assertThat(terminal.toString()) + .isEqualTo("\rAnalysing 1/3\rAnalysing 2/3\rAnalysing 3/3\r" + " ".repeat(13) + "\r"); + assertThat(err.toString()).isEmpty(); + assertThat(out.toString()).doesNotContain("Analysing").doesNotContain("\r"); + } + + @Test + void clearsTheProgressLineWithAnEraseSequenceOnAnAnsiTerminal() { + terminal = new StringWriter(); + ansi = Ansi.ON; + + assertThat(run("analyse", SOURCES, "-c", NO_CACHE)).isZero(); + + assertThat(terminal.toString()).endsWith("\rAnalysing 3/3\r\u001B[K"); } @Test - void countsAFileThatCannotBeParsedAsProcessedAndKeepsTheParserMessage() { - terminal = true; + void clearsTheProgressLineBeforeAParserWarningSoItStartsOnACleanLine() { + terminal = err; // one stream, to see the order in which the two writers are used - assertThat(run("analyse", PARSE_ERROR, "-c", NO_CACHE)).isZero(); + assertThat(run("analyse", FIXTURES + "/multi," + PARSE_ERROR, "-c", NO_CACHE)).isZero(); assertThat(err.toString()) - .contains("\rAnalysing 1/1\n") - .contains("Parser failed for file " + PARSE_ERROR + "/Broken.java: "); + .contains("\rAnalysing 2/3\r" + " ".repeat(13) + "\rParser failed for file " + PARSE_ERROR + "/Broken.java: ") + .endsWith("\rAnalysing 3/3\r" + " ".repeat(13) + "\r"); + } + + @Test + void keepsTheParserMessageAloneOnTheErrorStreamWhenItIsNotATerminal() { + assertThat(run("analyse", FIXTURES + "/multi," + PARSE_ERROR, "-c", NO_CACHE)).isZero(); + + assertThat(err.toString()).startsWith("Parser failed for file " + PARSE_ERROR + "/Broken.java: ").doesNotContain("\r"); + } + + @Test + void clearsTheProgressLineBeforeAFailureIsReported() throws Exception { + terminal = err; + Files.write(tempDir.resolve("Broken.java"), new byte[] {(byte) 0xC3, (byte) 0x28}); + Files.writeString(tempDir.resolve("A.java"), "class A { void a() {} }"); + + assertThat(run("analyse", tempDir.toString(), "-c", NO_CACHE)).isEqualTo(1); + + assertThat(err.toString()).contains("\rAnalysing 1/2\r" + " ".repeat(13) + "\rError reading file: "); } @Test void printsNoProgressLineForAnEmptyDirectory() { - terminal = true; + terminal = new StringWriter(); assertThat(run("analyse", tempDir.toString(), "-c", NO_CACHE)).isZero(); + assertThat(terminal.toString()).isEmpty(); assertThat(err.toString()).isEmpty(); } @@ -414,7 +446,7 @@ private int run(final String... args) { CommandLine commandLine = new CommandLine(new App()); AnalyseCommand command = (AnalyseCommand) commandLine.getSubcommands().get("analyse").getCommand(); command.ansi = ansi; - command.stderrIsTerminal = () -> terminal; + command.terminalWriter = () -> terminal == null ? null : new PrintWriter(terminal, true); if (now != null) { final long step = 250_000_000L; command.ticker = () -> now.getAndAdd(step); diff --git a/src/test/java/net/floriankraemer/cognitive_analysis/application/TextTableTest.java b/src/test/java/net/floriankraemer/cognitive_analysis/application/TextTableTest.java index 31cf235..18da7b3 100644 --- a/src/test/java/net/floriankraemer/cognitive_analysis/application/TextTableTest.java +++ b/src/test/java/net/floriankraemer/cognitive_analysis/application/TextTableTest.java @@ -54,4 +54,53 @@ void measuresTheWidthWithoutColorCodes() { │ \u001B[31m1\u001B[39m │ └───┘"""); } + + @Test + void countsWideCharactersAsTwoColumns() { + assertThat(table.render(List.of("Name", "N"), List.of(List.of("メソッド", "1"), List.of("日本", "2")))).isEqualTo(""" + ┌──────────┬───┐ + │ Name │ N │ + ├──────────┼───┤ + │ メソッド │ 1 │ + │ 日本 │ 2 │ + └──────────┴───┘"""); + } + + @Test + void countsHangulFullwidthFormsAndEmojiAsTwoColumns() { + assertThat(table.render(List.of("N"), List.of(List.of("한글"), List.of("A"), List.of("🙂"), List.of("abcd")))) + .isEqualTo(""" + ┌──────┐ + │ N │ + ├──────┤ + │ 한글 │ + │ A │ + │ 🙂 │ + │ abcd │ + └──────┘"""); + } + + @Test + void countsCombiningMarksJoinersAndVariationSelectorsAsZeroColumns() { + // "e" + combining acute, and a heart with a variation selector, which is one column wide here + assertThat(table.render(List.of("N"), List.of(List.of("e\u0301"), List.of("ab"), List.of("\u2764\uFE0F")))) + .isEqualTo(""" + ┌────┐ + │ N │ + ├────┤ + │ e\u0301 │ + │ ab │ + │ \u2764\uFE0F │ + └────┘"""); + } + + @Test + void countsAZeroWidthJoinerAsZeroColumns() { + assertThat(table.render(List.of("N"), List.of(List.of("a\u200Db")))).isEqualTo(""" + ┌────┐ + │ N │ + ├────┤ + │ a\u200Db │ + └────┘"""); + } }