Generating an aerial view of your project with OpenRewrite — DeepSeek Blog | Neura Market
    Neura MarketNeura Market/DeepSeek
    ChatGPTChatGPTClaudeClaudeGeminiGeminiCursorCursorGrokGrokPerplexityPerplexityDeepSeekDeepSeek
    CoPilotCoPilotStable DiffusionStable DiffusionMidjourneyMidjourney
    View All Directories
    OverviewRulesPromptsMCPsAgentsBlogVideosGuidesCoursesCommunityTrendingGenerate
    DeepSeekBlogGenerating an aerial view of your project with OpenRewrite
    Back to Blog
    Generating an aerial view of your project with OpenRewrite
    java

    Generating an aerial view of your project with OpenRewrite

    Kosmik March 25, 2026
    0 views

    Read it in french here In the previous article, we discussed (well, I wrote, you read) Scanning...

    --- title: Generating an aerial view of your project with OpenRewrite tags: java, jreleaser, openrewrite, graph cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t1ybqf9x4vz6tgj47kkn.webp canonical_url: https://jtama.github.io/posts/en/generating-an-aerial-view-of-your-project-with-openrewrite/ series: Openrewrite published: true --- > Read it in [french here](https://jtama.github.io/posts/g-n-rer-une-vue-a-rienne-de-votre-projet-avec-openrewrite/) In the previous article, we discussed (well, _I wrote, you read_) [Scanning Recipes](https://jtama.github.io/posts/technique-avanc-e-d-openrewrite-orchestrer-des-refactorings-complexes-avec-les-scanningrecipe/) when you need complete information to make a decision, or to generate code _ex nihilo_. I promised you a little toy at the end... The time has come for the reveal: the **Project Graph Generator**. ![Aerial view of the architecture generated by the tool](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5u8t7btttr934mtnn9l2.gif) ## The Need: Mapping Your Code It’s sometimes difficult to get a global view of the dependencies within your own code. Is this package too tightly coupled to others? What is the central class of my domain? Has my wonderful initial design withstood the ravages of time? Since [OpenRewrite](https://docs.openrewrite.org/) already knows how to build the complete **LST** of your codebase, it’s not _exactly_ complicated to traverse it to deduce relationships. This is exactly the goal of the [project-graph-generator](https://github.com/jtama/project-graph-generator) project: scanning your sources to deduce a dependency graph and produce a simple HTML page using [D3.js](https://d3js.org/) to display it. ## TL;DR; > Oh thou, who doesn’t want to know more, but only wants to play with the graph, go no further than this chapter, you might gain some knowledge! The project is easily usable via the `rewrite-maven-plugin` [or any other way to trigger an OpenRewrite recipe](https://docs.openrewrite.org/running-recipes). Here is the command to launch a complete analysis of your project: ```console mvn -U org.openrewrite.maven:rewrite-maven-plugin:run \ -Drewrite.recipeArtifactCoordinates=io.github.jtama:project-graph-generator:RELEASE \ ① -Drewrite.activeRecipes=io.github.jtama.openrewrite.ProjectAerialViewGenerator \ -Drewrite.exportDatatables=true ``` 1. `RELEASE` = `latest` Once the analysis is complete, the plugin generates a standalone HTML file containing the data AND the visualization. Simply open the `class-diagram.html` file at the root of your project in your browser to explore the web of your architecture. You can also pass additional options to filter the nodes according to your needs: * **`maxNodes=20`**\ Filters for classes with the highest number of incoming connections. * **`basePackages=com.mycompany`**\ Forces the target base package * **`includeTests=true`**\ Also include test classes. To learn more 👉 [Here is the project repository](https://github.com/jtama/project-graph-generator). Go ahead, it’s open source, use it, fork it, make issues and pull requests! ![please](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oswdgbdxowhh4oeounsq.gif) ## The Mechanics: Analysis Without Modification Under the hood, the tool is based on the **ScanningRecipe** concept we saw previously. The major difference here is that the **generation** phase generates ***HTML****, and the *modification** phase (`visit`) does nothing, nada, zilch. The ~~entire goal~~ of the recipe is concentrated in the first pass: scanning the **LST**. Well, no, not the goal, rather the intelligence (not the A.I. kind). It all starts with an accumulator - our famous graph - which will store the classes (Nodes) and their relationships (Links) as the scan progresses: ```java public static class GraphScanAccumulator { public List<Node> nodes = new ArrayList<>(); // ① public List<Link> links = new ArrayList<>(); // ... search methods findNode() and findLink() } ``` 1. Did you seriously think I was going to explain this line? To fill this graph, we will traverse the **LST** using a `JavaIsoVisitor`. First, we identify each component of our architecture by overriding the `visitClassDeclaration` method. Each new class encountered becomes a "Node": ```java @Override public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, ExecutionContext ctx) { if (includeTests() || not(isTestClass()).test(getCursor())) { // ① if (classDecl.getType() != null) { String fqn = classDecl.getType().getFullyQualifiedName(); graph.findNode(fqn).orElseGet(() -> { // ② Node newNode = new Node(fqn, classDecl.getType().getPackageName()); graph.nodes.add(newNode); return newNode; }); } return super.visitClassDeclaration(classDecl, ctx); // ③ } return classDecl; } ``` 1. We only look at test classes if explicitly requested. 2. We use our `graph` accumulator to register the current class if it hasn’t been seen already. 3. We don’t forget to call `super` so that the visitor continues to descend into the tree. **_If and only if_** the class is of interest to us, otherwise, we don’t waste our time. Next, we must weave the web. How do we know that class `A` depends on class `B`? We simply capture type usages (method calls, fields access, instantiations). For example, here’s how we proceed for method invocations: ```java @Override public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) { var mi = super.visitMethodInvocation(method, ctx); // ① JavaType.FullyQualified targetType = mi.getMethodType() != null ? mi.getMethodType().getDeclaringType() : null; // ② if (targetType != null) { addLink(targetType); // ③ } return mi; } ``` 1. Let the visitor visit. 2. Extract the type information (`JavaType`) carried by the invoked method to know which class it belongs to. The type can be `null`, particularly if OpenRewrite failed to determine it. 3. Invoke the `addLink` method. The `addLink` method contains all the logic allowing us to determine if the `targetType` interests us, that is to say if it is part of the target packages. If so, we create a new link or strengthen an existing one. The same logic is obviously applied [to member references, class fields, constructor invocations, etc](https://github.com/jtama/project-graph-generator/blob/main/src/main/java/io/github/jtama/openrewrite/ProjectAerialViewGenerator.java#L118). This is the beauty of OpenRewrite’s model: the LST is already perfectly typed by the compiler during _parsing_. We don’t need to guess who an invoked method belongs to, the type information tells us with certainty. ## Going Further: Raw Export with Datatables Generating an HTML page is nice. But what if you want to cross-reference this data, render it yourself in a tool like [Gephi](https://gephi.org/), or even provide it as context to an LLM to audit your architecture? This is where OpenRewrite’s [Datatables](https://docs.openrewrite.org/authoring-recipes/data-tables) come in. In addition to the view, `project-graph-generator` can export metadata in the form of easily usable CSV files: * *`target/rewrite/datatables/io.github.jtama.openrewrite.model.NodesReport.csv` *\ Contains all the classes found with their package and their number of incoming/outgoing connections. * *`target/rewrite/datatables/io.github.jtama.openrewrite.model.LinksReport.csv` *\ Exhaustive list of links between classes with an associated weight. * *`target/rewrite/datatables/io.github.jtama.openrewrite.model.JavaSourceFileExcludedReport.csv` *\ All classes that were excluded from the final result (often due to package filtering). Now, it’s your turn. Run the scanner on your _legacy_, and contemplate (or be frightened by) the extent of the web! --- **P.S.**: As you may have noticed, this plugin is distributed on Maven Central (`io.github.jtama:project-graph-generator`). If you’re wondering how to easily automate the entire publication chain without tearing your hair out, I recommend you take a look at [my JReleaser tutorial](https://jtama.github.io/posts/en/release-everything-with-jreleaser/).

    Tags

    javajreleaseropenrewritegraph

    Comments

    More Blog

    View all
    How I'm using ASTs and Gemini to solve the "Codebase Onboarding" problem 🧠ai

    How I'm using ASTs and Gemini to solve the "Codebase Onboarding" problem 🧠

    Hi everyone! 👋 I’m Tara, a Senior Software Engineer and Consultant. Over the years, I've jumped...

    T
    tworrell
    Local AI Will Save Us All (The Math Says So, Trust Me)ai

    Local AI Will Save Us All (The Math Says So, Trust Me)

    Every few weeks a take goes viral in tech circles making the case for ditching cloud AI and running...

    S
    Sebastian Schürmann
    Lost in the AI Hype, I Started Smallai

    Lost in the AI Hype, I Started Small

    And it helped me get back into tech without drowning TL;DR at the end Coming back to...

    R
    Rohini Gaonkar
    Building a Replay-Tested Interactive Brokers Client in Gogo

    Building a Replay-Tested Interactive Brokers Client in Go

    I wanted an IBKR library that felt like Go and had testing I could trust. So I wrote one.

    T
    Thomas Marcelis
    Playwright in Pictures: Fully Parallel Modeplaywright

    Playwright in Pictures: Fully Parallel Mode

    Playwright’s fullyParallel mode is often treated as a simple performance switch. In practice, it...

    V
    Vitaliy Potapov
    Designing a CLI for Both Humans and Agentscli

    Designing a CLI for Both Humans and Agents

    Learn how Alpic designed its CLI for both human developers and AI agents — covering tradeoffs like polling, context windows, interactivity, and statelessness.

    J
    Julien Vallini

    Stay up to date

    Get the latest DeepSeek prompts, rules, and resources delivered to your inbox weekly.

    Neura Market LogoNeura Market

    Discover the best AI prompts, plugins, and resources for DeepSeek and more.

    Content Types

    • Rules
    • Prompts
    • MCPs
    • Agents
    • Guides

    Platforms

    • ChatGPT Directory
    • Claude Directory
    • Gemini Directory
    • Cursor Directory
    • Grok Directory
    • Perplexity Directory
    • DeepSeek Directory
    • CoPilot Directory
    • Stable Diffusion Directory
    • Midjourney Directory
    • All Directories

    Resources

    • Blog
    • Documentation
    • Help Center
    • Marketplace

    Legal

    • Privacy Policy
    • Terms of Service

    © 2026 Neura Market. All rights reserved.

    |

    Not affiliated with any AI platform vendors.