Skip to content

fix: resolve template paths with leading slashes and framework subfolders#74

Open
Swahjak wants to merge 8 commits intomoetelo:masterfrom
toppynl:fix/template-imports-and-namespaces
Open

fix: resolve template paths with leading slashes and framework subfolders#74
Swahjak wants to merge 8 commits intomoetelo:masterfrom
toppynl:fix/template-imports-and-namespaces

Conversation

@Swahjak
Copy link

@Swahjak Swahjak commented Jan 6, 2026

Summary

Fixes #64

This PR addresses the "Template not found" issue that affected users in several scenarios:

  • Leading slash on directory paths: When Symfony's debug:twig returns paths like /templates instead of templates, they were incorrectly treated as absolute filesystem paths, causing the language server to look for templates at the filesystem root instead of the workspace.

  • Workspace is parent of Symfony root: When the workspace is a parent folder (e.g., monorepo with app/composer.json), template paths from Symfony were resolved relative to the workspace instead of the PHP project root.

  • Bundle namespaces not auto-detected: When working inside bundle directories, templates with @BundleName/... namespace weren't automatically found.

Changes

  • Add normalizeTemplatePath.ts utility with:
    • normalizeDirectoryPath(): Handles leading slashes, absolute paths, and composer root resolution
  • Add twiggy.composerRoot config setting for projects in subdirectories
  • Update DocumentCache to normalize paths and try composer root fallback when resolving templates
  • Update CompletionProvider to use normalized template mappings for completions
  • Add twiggy.templatePaths config setting for manual namespace registration
  • Add tests for path normalization utilities

Why composerRoot instead of inferring from console path?

The previous approach inferred the framework root from symfonyConsolePath (e.g., app/bin/consoleapp). We replaced this with an explicit composerRoot setting because:

  1. Explicitness over inference: Users set composerRoot: "app" directly rather than relying on implicit path parsing
  2. Separation of concerns: The console path setting is purely for finding the console, not for determining project structure
  3. Better framework support: Works with Craft CMS and vanilla Twig projects that may not use bin/console but still need subdirectory support
  4. Simpler code: Removes edge-case handling for extracting paths from console path

Configuration Options

Users can now:

1. Use subdirectory PHP installations (monorepo setups):

{
  "twiggy.composerRoot": "app",
  "twiggy.symfonyConsolePath": "bin/console"
}

The console path is resolved relative to composerRoot, so templates resolve correctly.

2. Configure manual template path mappings:

{
  "twiggy.templatePaths": [
    { "namespace": "@MyBundle", "path": "src/MyBundle/templates" },
    { "namespace": "@Components", "path": "components" }
  ]
}

Test plan

  • Build succeeds (pnpm build)
  • Path normalization tests pass
  • Manual testing with Symfony project having leading slash paths
  • Manual testing with monorepo structure (composerRoot: "app")
  • Manual testing with bundle development using @BundleName/... namespace

- Add conditional publishing based on token availability
- Support both VS Code Marketplace and Open VSX registries
- Remove direct vsce dependency in favor of the action
Pass `-d display_errors=stderr` to PHP executable to redirect
deprecation warnings to stderr, keeping stdout clean for JSON output.

Since PHP 8.0, the default error_reporting includes E_DEPRECATED,
causing deprecation notices to pollute stdout and break JSON parsing
in the language server.
…ders

Fixes moetelo#64

This commit addresses the "Template not found" issue that affected users in
several scenarios:

1. Leading slash on directory paths: When Symfony's `debug:twig` returns
   paths like `/templates` instead of `templates`, they were incorrectly
   treated as absolute filesystem paths.

2. Workspace is parent of Symfony root: When the workspace is a parent
   folder (e.g., monorepo with `app/bin/console`), template paths were
   resolved relative to the workspace instead of the Symfony root.

3. Bundle namespaces not auto-detected: When working inside bundle
   directories, templates with `@BundleName/...` namespace weren't found.

Changes:
- Add `normalizeTemplatePath.ts` utility with path normalization logic
- Add `extractFrameworkRoot()` to detect framework subdirectory from console path
- Update `DocumentCache` to normalize paths and try framework root fallback
- Update `CompletionProvider` to use normalized template mappings
- Add `twiggy.templatePaths` config for manual namespace registration
- Add tests for path normalization utilities

Users can now:
- Use `symfonyConsolePath: "app/bin/console"` for monorepo setups
- Configure `templatePaths` for bundle development with custom namespaces
- Have leading slash paths automatically normalized
Move file watching from client-side (VSCode-specific) to server-side
using the LSP standard `client/registerCapability` request.

This makes the extension compatible with other LSP-compliant editors
(Neovim, Sublime, Emacs, etc.) by:

- Removing client-side FileSystemWatcher from extension.ts
- Adding dynamic registration for didChangeWatchedFiles in onInitialized
- Handling file changes via connection.onDidChangeWatchedFiles
- Adding remove() and refresh() methods to DocumentCache

Fixes moetelo#54
…poserRoot setting

Instead of inferring the framework root directory from the Symfony console path
(e.g., `app/bin/console` → `app`), users now explicitly configure the
`composerRoot` setting when their PHP project is in a subdirectory.

This change provides:
- **Explicitness over inference**: Users set `composerRoot: "app"` directly
  rather than relying on implicit path parsing from `symfonyConsolePath`
- **Separation of concerns**: The console path setting is purely for finding
  the console, not for determining project structure
- **Better framework support**: Works with Craft CMS and vanilla Twig projects
  that may not use `bin/console` but still need subdirectory support
- **Simpler code**: Removes the `extractFrameworkRoot()` function and its
  edge-case handling

Configuration example for monorepo setups:
```json
{
  "twiggy.composerRoot": "app",
  "twiggy.symfonyConsolePath": "bin/console"
}
```

The console path is now resolved relative to `composerRoot` when set.
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.

Template not found

1 participant