Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,29 @@ public File getGitDir(File basedir) {
return repositoryBuilder.getGitDir();
}

/**
* Returns the current commit hash at HEAD
*
* @return the commit hash as a String, or null if HEAD cannot be resolved
* @throws IOException if an I/O error occurs
*/
public String getCurrentCommitHash() throws IOException {
ObjectId headCommit = gitRepository.resolve("HEAD");
if (headCommit == null) {
return null;
}
return headCommit.getName();
}

/**
* Returns the repository's origin URL
*
* @return the origin URL as a String, or null if not configured
*/
public String getOriginUrl() {
return gitRepository.getConfig().getString("remote", "origin", "url");
}

// log --follow implementation may be worth adopting in the future
// https://github.com/spearce/jgit/blob/master/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevWalkTextBuiltin.java

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.hjug.mavenreport;

import java.util.*;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.maven.doxia.markup.HtmlMarkup;
import org.apache.maven.doxia.sink.Sink;
Expand Down Expand Up @@ -63,6 +65,7 @@ public String getDescription(Locale locale) {
+ " have the highest priority values.";
}

@SneakyThrows
@Override
public void executeReport(Locale locale) {
HtmlReport htmlReport = new HtmlReport();
Expand Down
76 changes: 56 additions & 20 deletions report/src/main/java/org/hjug/refactorfirst/report/HtmlReport.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package org.hjug.refactorfirst.report;

import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.*;
import lombok.extern.slf4j.Slf4j;
import org.hjug.cbc.RankedCycle;
import org.hjug.cbc.RankedDisharmony;
import org.hjug.gdg.GraphDataGenerator;
import org.hjug.graphbuilder.CodebaseGraphDTO;
import org.jgrapht.Graph;
import org.jgrapht.graph.DefaultWeightedEdge;

Expand Down Expand Up @@ -417,6 +415,17 @@ public String printTitle(String projectName, String projectVersion) {
return "<title>Refactor First Report for " + projectName + " " + projectVersion + " </title>\n";
}

@Override
StringBuilder createMenu(
List<DisharmonySpec> disharmonySpecs,
Map<String, List<RankedDisharmony>> rankedDisharmoniesByAnchor,
List<RankedCycle> rankedCycles) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("<li><a href=\"#CLASSMAP\">Class Map</a></li>\n");
stringBuilder.append(super.createMenu(disharmonySpecs, rankedDisharmoniesByAnchor, rankedCycles));
return stringBuilder;
}

@Override
String renderGithubButtons() {
return "<div align=\"center\">\n" + "Show RefactorFirst some &#10084;&#65039;\n"
Expand Down Expand Up @@ -465,8 +474,8 @@ String renderDisharmonyChart(String anchorId, String title, List<RankedDisharmon
}

@Override
public String renderClassGraphVisuals() {
String dot = buildClassGraphDot(classGraph);
public String renderClassGraphVisuals(String repoUrl, CodebaseGraphDTO codebaseGraphDTO) {
String dot = buildClassGraphDot(classGraph, repoUrl, codebaseGraphDTO);
String classGraphName = "classGraph";

StringBuilder stringBuilder = new StringBuilder();
Expand All @@ -491,7 +500,7 @@ public String renderClassGraphVisuals() {

private StringBuilder generateGraphButtons(String graphName, String dot) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("<h1 align=\"center\">Class Map</h1>");
stringBuilder.append("<h1 align=\"center\"><a id=\"CLASSMAP\">Class Map</a></h1>");
stringBuilder.append("<script>\n");
stringBuilder.append("const " + graphName + "_dot = " + dot + "\n");
stringBuilder.append("</script>\n");
Expand All @@ -501,7 +510,9 @@ private StringBuilder generateGraphButtons(String graphName, String dot) {

stringBuilder.append("<div align=\"center\">\nRed lines represent relationships to remove.<br>\n");
stringBuilder.append("Red nodes represent classes to remove.<br>\n");
stringBuilder.append("Zoom in / out with your mouse wheel and click/move to drag the image.\n");
stringBuilder.append("Zoom in / out with your mouse wheel and click/move to drag the image.<br>\n");
stringBuilder.append(
"Clicking on a node in the DOT graph (if present below) will open its source file in the repo. It will not open a new browser window.\n");
stringBuilder.append("</div>\n");
return stringBuilder;
}
Expand All @@ -511,7 +522,7 @@ private static String generateDotImage(String graphName) {
return "<div id=\"" + graphName
+ "\" style=\"width: 95%; height: 70vh; margin: auto; border: thin solid black\"></div>\n"
+ "<script type=\"module\">\n"
+ "import init, { DotParser } from \"https://esm.run/@vizdom/vizdom-ts-web\";\n"
+ "import init, { DotParser } from \"https://cdn.jsdelivr.net/npm/@vizdom/vizdom-ts-web@0.1.19/vizdom_ts.min.js\";\n"
+ " if(DotParser) {\n"
+ " // Wait for the WASM binary to be compiled and the 'wasm' object to be populated\n"
+ " await init();\n"
Expand All @@ -534,7 +545,8 @@ private static String generateDotImage(String graphName) {
+ " }\n" + "</script>\n";
}

String buildClassGraphDot(Graph<String, DefaultWeightedEdge> classGraph) {
String buildClassGraphDot(
Graph<String, DefaultWeightedEdge> classGraph, String repoUrl, CodebaseGraphDTO codebaseGraphDTO) {
StringBuilder dot = new StringBuilder();
dot.append("`strict digraph G {\n");

Expand Down Expand Up @@ -563,17 +575,26 @@ String buildClassGraphDot(Graph<String, DefaultWeightedEdge> classGraph) {

dot.append(className.replace("$", "_"));

dot.append(" [");
dot.append(hyperlinkClassForDot(vertex, repoUrl, codebaseGraphDTO));

if (vertexesToRemove.contains(vertex)) {
dot.append(" [color=red style=filled]\n");
dot.append(" color=red style=filled");
}

dot.append(";\n");
dot.append("];\n");
}

dot.append("}`;");
return dot.toString();
}

String hyperlinkClassForDot(String fqClassName, String repoUrl, CodebaseGraphDTO codebaseGraphDTO) {
StringBuilder sb = new StringBuilder();
String path = codebaseGraphDTO.getClassToSourceFilePathMapping().get(fqClassName);
return sb.append("URL=\"" + repoUrl + path + "\" target=\"_blank\"").toString();
}

private void renderEdge(
Graph<String, DefaultWeightedEdge> classGraph, DefaultWeightedEdge edge, StringBuilder dot) {
// render edge
Expand Down Expand Up @@ -622,8 +643,8 @@ private void renderEdge(
}

@Override
public String renderCycleVisuals(RankedCycle cycle) {
String dot = buildCycleDot(classGraph, cycle);
public String renderCycleVisuals(RankedCycle cycle, String repoUrl, CodebaseGraphDTO codebaseGraphDTO) {
String dot = buildCycleDot(classGraph, cycle, repoUrl, codebaseGraphDTO);

String cycleName = getClassName(cycle.getCycleName()).replace("$", "_");

Expand All @@ -643,7 +664,11 @@ public String renderCycleVisuals(RankedCycle cycle) {
return stringBuilder.toString();
}

String buildCycleDot(Graph<String, DefaultWeightedEdge> classGraph, RankedCycle cycle) {
String buildCycleDot(
Graph<String, DefaultWeightedEdge> classGraph,
RankedCycle cycle,
String repoUrl,
CodebaseGraphDTO codebaseGraphDTO) {
StringBuilder dot = new StringBuilder();
dot.append("`strict digraph G {\n");

Expand All @@ -653,18 +678,29 @@ String buildCycleDot(Graph<String, DefaultWeightedEdge> classGraph, RankedCycle

// render vertices
for (String vertex : cycle.getVertexSet()) {
dot.append(getClassName(vertex).replace("$", "_"));
String className = getClassName(vertex);

// if the vertex is a nested class and has no outgoing edges, skip it
if (className.contains("$")
&& className.split("\\$")[className.split("\\$").length - 1].matches("\\d+")
&& classGraph.outDegreeOf(vertex) == 0) {
continue;
}

dot.append(className.replace("$", "_"));

dot.append(" [");
dot.append(hyperlinkClassForDot(vertex, repoUrl, codebaseGraphDTO));

if (vertexesToRemove.contains(vertex)) {
dot.append(" [color=red style=filled]\n");
dot.append(" color=red style=filled");
}

dot.append(";\n");
dot.append("];\n");
}

dot.append("}`;");

return dot.toString().replace("$", "_");
return dot.toString();
}

String generate2DPopup(String cycleName) {
Expand Down
Loading
Loading