All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openrewrite.LanguageComposition Maven / Gradle / Ivy

Go to download

Rewrite recipes which have dependencies on many other rewrite recipes or language parsers.

There is a newer version: 1.8.2
Show newest version
/*
 * Copyright 2021 the original author or authors.
 * 

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *

* https://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.openrewrite; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.Value; import org.openrewrite.binary.Binary; import org.openrewrite.groovy.tree.G; import org.openrewrite.hcl.tree.Hcl; import org.openrewrite.internal.lang.Nullable; import org.openrewrite.java.tree.J; import org.openrewrite.json.tree.Json; import org.openrewrite.kotlin.tree.K; import org.openrewrite.properties.tree.Properties; import org.openrewrite.protobuf.tree.Proto; import org.openrewrite.python.tree.Py; import org.openrewrite.quark.Quark; import org.openrewrite.remote.Remote; import org.openrewrite.table.LanguageCompositionPerFile; import org.openrewrite.table.LanguageCompositionPerFolder; import org.openrewrite.table.LanguageCompositionPerRepository; import org.openrewrite.text.PlainText; import org.openrewrite.tree.ParseError; import org.openrewrite.xml.tree.Xml; import org.openrewrite.yaml.tree.Yaml; import java.util.*; @Value @EqualsAndHashCode(callSuper = true) public class LanguageComposition extends ScanningRecipe { transient LanguageCompositionPerRepository perRepositoryReport = new LanguageCompositionPerRepository(this); transient LanguageCompositionPerFolder perFolderReport = new LanguageCompositionPerFolder(this); transient LanguageCompositionPerFile perFileReport = new LanguageCompositionPerFile(this); @Override public String getDisplayName() { return "Language composition report"; } @Override public String getDescription() { //language=markdown return "Counts the number of lines of the various kinds of source code and data formats parsed by OpenRewrite. " + "Comments are not included in line counts. " + "This recipe emits its results as two data tables, making no changes to any source file. " + "One data table is per-file, the other is per-repository."; } @Data public static class Accumulator { Map> folderToLanguageToCounts = new HashMap<>(); } private static String containingFolderPath(SourceFile s) { String sourcePath = PathUtils.separatorsToUnix(s.getSourcePath().toString()); int lastSlash = sourcePath.lastIndexOf('/'); if (lastSlash == -1) { return ""; } return s.getSourcePath().toString().substring(0, lastSlash); } @Override public Accumulator getInitialValue(ExecutionContext ctx) { return new Accumulator(); } @Override public TreeVisitor getScanner(Accumulator acc) { return new TreeVisitor() { @Override public @Nullable Tree visit(@Nullable Tree tree, ExecutionContext ctx) { if (!(tree instanceof SourceFile)) { return tree; } SourceFile s = (SourceFile) tree; String folderPath = containingFolderPath(s); // Parse failures *should* only ever appear on PlainText sources, but always checking finds a parser bug boolean hasParseFailure = s.getMarkers().findFirst(ParseExceptionResult.class).isPresent(); if (s instanceof Quark || s instanceof Binary || s instanceof Remote) { Counts quarkCounts = acc.getFolderToLanguageToCounts() .computeIfAbsent(folderPath, k -> new HashMap<>()) .computeIfAbsent("Other/unknown/unparseable", k -> new Counts()); quarkCounts.fileCount++; perFileReport.insertRow(ctx, new LanguageCompositionPerFile.Row( s.getSourcePath().toString(), "Other/unknown/unparseable", s.getClass().getName(), 0, hasParseFailure)); } else { int genericLineCount = genericLineCount(s); if (s.getClass().getName().startsWith("org.openrewrite.cobol.tree.CobolPreprocessor$Copybook")) { Counts copybookCounts = acc.getFolderToLanguageToCounts() .computeIfAbsent(folderPath, k -> new HashMap<>()) .computeIfAbsent("Copybook", k -> new Counts()); copybookCounts.fileCount++; copybookCounts.lineCount += genericLineCount; perFileReport.insertRow(ctx, new LanguageCompositionPerFile.Row( s.getSourcePath().toString(), "Copybook", s.getClass().getName(), genericLineCount, hasParseFailure)); } else if (s.getClass().getName().startsWith("org.openrewrite.cobol.tree.Cobol")) { Counts cobolCounts = acc.getFolderToLanguageToCounts() .computeIfAbsent(folderPath, k -> new HashMap<>()) .computeIfAbsent("Cobol", k -> new Counts()); cobolCounts.fileCount++; cobolCounts.lineCount += genericLineCount; perFileReport.insertRow(ctx, new LanguageCompositionPerFile.Row( s.getSourcePath().toString(), "Cobol", s.getClass().getName(), genericLineCount, hasParseFailure)); } else if (s instanceof K) { Counts kotlinCounts = acc.getFolderToLanguageToCounts() .computeIfAbsent(folderPath, k -> new HashMap<>()) .computeIfAbsent("Kotlin", k -> new Counts()); kotlinCounts.fileCount++; // Don't have a kotlin-specific counter yet and Java count should be very close kotlinCounts.lineCount += org.openrewrite.java.CountLinesVisitor.countLines(s); perFileReport.insertRow(ctx, new LanguageCompositionPerFile.Row( s.getSourcePath().toString(), "Kotlin", s.getClass().getName(), genericLineCount, hasParseFailure)); } else if (s instanceof G) { Counts groovyCounts = acc.getFolderToLanguageToCounts() .computeIfAbsent(folderPath, k -> new HashMap<>()) .computeIfAbsent("Groovy", k -> new Counts()); groovyCounts.fileCount++; groovyCounts.lineCount += org.openrewrite.groovy.CountLinesVisitor.countLines(s); perFileReport.insertRow(ctx, new LanguageCompositionPerFile.Row( s.getSourcePath().toString(), "Groovy", s.getClass().getName(), genericLineCount, hasParseFailure)); } else if (s instanceof Py) { Counts pythonCounts = acc.getFolderToLanguageToCounts() .computeIfAbsent(folderPath, k -> new HashMap<>()) .computeIfAbsent("Python", k -> new Counts()); pythonCounts.fileCount++; pythonCounts.lineCount += genericLineCount; perFileReport.insertRow(ctx, new LanguageCompositionPerFile.Row( s.getSourcePath().toString(), "Python", s.getClass().getName(), genericLineCount, hasParseFailure)); } else if (s instanceof J) { Counts javaCounts = acc.getFolderToLanguageToCounts() .computeIfAbsent(folderPath, k -> new HashMap<>()) .computeIfAbsent("Java", k -> new Counts()); javaCounts.fileCount++; javaCounts.lineCount += org.openrewrite.java.CountLinesVisitor.countLines(s); perFileReport.insertRow(ctx, new LanguageCompositionPerFile.Row( s.getSourcePath().toString(), "Java", s.getClass().getName(), genericLineCount, hasParseFailure)); } else if (s instanceof Json) { Counts jsonCounts = acc.getFolderToLanguageToCounts() .computeIfAbsent(folderPath, k -> new HashMap<>()) .computeIfAbsent("Json", k -> new Counts()); jsonCounts.fileCount++; jsonCounts.lineCount += org.openrewrite.json.CountLinesVisitor.countLines(s); perFileReport.insertRow(ctx, new LanguageCompositionPerFile.Row( s.getSourcePath().toString(), "Json", s.getClass().getName(), genericLineCount, hasParseFailure)); } else if (s instanceof Hcl) { Counts hclCounts = acc.getFolderToLanguageToCounts() .computeIfAbsent(folderPath, k -> new HashMap<>()) .computeIfAbsent("Hcl", k -> new Counts()); hclCounts.fileCount++; hclCounts.lineCount += org.openrewrite.hcl.CountLinesVisitor.countLines(s); perFileReport.insertRow(ctx, new LanguageCompositionPerFile.Row( s.getSourcePath().toString(), "Hcl", s.getClass().getName(), genericLineCount, hasParseFailure)); } else if (s instanceof Properties) { Counts propertiesCounts = acc.getFolderToLanguageToCounts() .computeIfAbsent(folderPath, k -> new HashMap<>()) .computeIfAbsent("Properties", k -> new Counts()); propertiesCounts.fileCount++; propertiesCounts.lineCount += org.openrewrite.properties.CountLinesVisitor.countLines(s); perFileReport.insertRow(ctx, new LanguageCompositionPerFile.Row( s.getSourcePath().toString(), "Properties", s.getClass().getName(), genericLineCount, hasParseFailure)); } else if (s instanceof Proto) { Counts protobufCounts = acc.getFolderToLanguageToCounts() .computeIfAbsent(folderPath, k -> new HashMap<>()) .computeIfAbsent("Protobuf", k -> new Counts()); protobufCounts.fileCount++; protobufCounts.lineCount += org.openrewrite.protobuf.CountLinesVisitor.countLines(s); perFileReport.insertRow(ctx, new LanguageCompositionPerFile.Row( s.getSourcePath().toString(), "Protobuf", s.getClass().getName(), genericLineCount, hasParseFailure)); } else if (s instanceof Xml) { Counts xmlCounts = acc.getFolderToLanguageToCounts() .computeIfAbsent(folderPath, k -> new HashMap<>()) .computeIfAbsent("Xml", k -> new Counts()); xmlCounts.fileCount++; xmlCounts.lineCount += org.openrewrite.xml.CountLinesVisitor.countLines(s); perFileReport.insertRow(ctx, new LanguageCompositionPerFile.Row( s.getSourcePath().toString(), "Xml", s.getClass().getName(), genericLineCount, hasParseFailure)); } else if (s instanceof Yaml) { Counts yamlCounts = acc.getFolderToLanguageToCounts() .computeIfAbsent(folderPath, k -> new HashMap<>()) .computeIfAbsent("Yaml", k -> new Counts()); yamlCounts.fileCount++; yamlCounts.lineCount += org.openrewrite.yaml.CountLinesVisitor.countLines(s); perFileReport.insertRow(ctx, new LanguageCompositionPerFile.Row( s.getSourcePath().toString(), "Yaml", s.getClass().getName(), genericLineCount, hasParseFailure)); } else if (s instanceof PlainText) { Counts plainTextCounts = acc.getFolderToLanguageToCounts() .computeIfAbsent(folderPath, k -> new HashMap<>()) .computeIfAbsent("Plain text", k -> new Counts()); plainTextCounts.fileCount++; plainTextCounts.lineCount += genericLineCount; perFileReport.insertRow(ctx, new LanguageCompositionPerFile.Row( s.getSourcePath().toString(), "Plain text", s.getClass().getName(), genericLineCount, hasParseFailure)); } else if (s instanceof ParseError) { Counts parseErrorCounts = acc.getFolderToLanguageToCounts() .computeIfAbsent(folderPath, k -> new HashMap<>()) .computeIfAbsent("Parse error", k -> new Counts()); parseErrorCounts.fileCount++; parseErrorCounts.lineCount += genericLineCount; perFileReport.insertRow(ctx, new LanguageCompositionPerFile.Row( s.getSourcePath().toString(), "Parse error", s.getClass().getName(), genericLineCount, hasParseFailure)); } else { Counts unknownCounts = acc.getFolderToLanguageToCounts() .computeIfAbsent(folderPath, k -> new HashMap<>()) .computeIfAbsent("Unknown", k -> new Counts()); unknownCounts.fileCount++; unknownCounts.lineCount += genericLineCount; perFileReport.insertRow(ctx, new LanguageCompositionPerFile.Row( s.getSourcePath().toString(), "Unknown", s.getClass().getName(), genericLineCount, hasParseFailure)); } } return tree; } }; } @Override public Collection generate(Accumulator acc, ExecutionContext ctx) { Map languageToCount = new HashMap<>(); for (Map.Entry> entry : acc.getFolderToLanguageToCounts().entrySet()) { for (Map.Entry languageEntry : entry.getValue().entrySet()) { perFolderReport.insertRow(ctx, new LanguageCompositionPerFolder.Row(entry.getKey(), languageEntry.getKey(), languageEntry.getValue().fileCount, languageEntry.getValue().lineCount)); Counts counts = languageToCount.computeIfAbsent(languageEntry.getKey(), k -> new Counts()); counts.fileCount += languageEntry.getValue().fileCount; counts.lineCount += languageEntry.getValue().lineCount; } } for (Map.Entry entry : languageToCount.entrySet()) { perRepositoryReport.insertRow(ctx, new LanguageCompositionPerRepository.Row(entry.getKey(), entry.getValue().fileCount, entry.getValue().lineCount)); } return Collections.emptyList(); } private static class Counts { int lineCount; int fileCount; } private static int genericLineCount(SourceFile s) { LineCounter counter = new LineCounter(); s.printAll(counter); return counter.getLineCount(); } private static class LineCounter extends PrintOutputCapture { private int count; public LineCounter() { super(0); } @Override public PrintOutputCapture append(char c) { if (c == '\n') { count++; } return this; } @Override public PrintOutputCapture append(@Nullable String text) { if (text == null) { return this; } if (text.contains("\n")) { count += text.split("([\r\n]+)").length; } return this; } int getLineCount() { return count; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy