Skip to content

Add Terraform support with new analyzer and symbol extraction#2

Open
xgourmandin wants to merge 3 commits into
scheidydude:mainfrom
xgourmandin:main
Open

Add Terraform support with new analyzer and symbol extraction#2
xgourmandin wants to merge 3 commits into
scheidydude:mainfrom
xgourmandin:main

Conversation

@xgourmandin
Copy link
Copy Markdown

For my personal needs, I tried to add support for Terraform.
This implementation was done with the help of Claude. So feel free to integrate it, or not.

I tested it on a real life Terraform project (multi layer/modules) and it seems to work pretty well.

NOTE : before going further, I only validated this using the visualization. I need to do some more tests with the other commands to see if this is really helpfull or not

Copy link
Copy Markdown
Owner

@scheidydude scheidydude left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution! Tested the analyzer end-to-end — the structure is solid and the symbol extraction works well. Two things to fix before merging:

🐛 Bug: macOS symlink path resolution breaks cross-module links

In terraform_analyzer.py, two places call .resolve().relative_to(root):

  • Phase 1 (~line 213): building module_src_resolved_map
  • Phase 2 (~line 249): generating module source links

On macOS, /var/folders/... resolves through a symlink to /private/var/folders/.... When root is unresolved and the resolved path has the /private prefix, relative_to(root) raises ValueError — which is silently caught, so all cross-module links are silently dropped.

Fix: use root.resolve() instead of root in both relative_to() calls:

# Phase 1
target_dir = str(
    (f_tmp.parent / mod_src).resolve().relative_to(root.resolve())
)

# Phase 2
target_dir = str(
    (f.parent / mod_src).resolve().relative_to(root.resolve())
)

⚠️ Please remove .claude/settings.local.json from the PR

This file contains your local machine paths and personal Claude Code permissions. It's specific to your environment and will conflict with ours. Please add it to .gitignore on your fork or revert the file from the PR.


Everything else looks good — the two-phase directory-scoped analysis, intra-module reference resolution, provider/registry external nodes, and the symbol extractor are all well-implemented. Happy to merge once these two are addressed.

@xgourmandin
Copy link
Copy Markdown
Author

Hey,

Fixed the path resolution as mentioned. I do not have access to a MacOS so I hope this works as expected.

@scheidydude
Copy link
Copy Markdown
Owner

Three issues below. Please review and tell me if they are issues or were intentional.

Issues

  1. Magic 600-char window in _module_sources (terraform_analyzer.py:94)
    window = source[m.start(): m.start() + 600]
    Verbose module blocks (many attributes before source =) will miss the source attribute silently. Should scan the full
    block by finding the matching { ... }.

  2. _LOCALS_BLOCK_RE handles only one nesting level
    r'^locals\s*{((?:[^{}]|{[^{}]}))}'
    Nested objects two levels deep (e.g., for_each = { for k, v in var.x : k => v }) break the match — those locals get
    silently dropped. Real Terraform codebases commonly hit this.

  3. RES_REF_RE will match var., local., data., module.
    r'\b([a-z][a-z0-9]*(?:
    [a-z0-9]+)+).([a-zA-Z0-9_]+)\b'
    The regex requires at least one underscore, but var_something.attr or local_map.key would still match. False hits fail
    silently (not in resource_map), so no crash — but adds noise. Consider explicitly excluding known prefixes:
    (?!var.|local.|data.|module.).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants