LSP: Support filename-based matching (filenameToLanguage) for extensionless files

Resolved 💬 2 comments Opened Apr 14, 2026 by yousiki Closed Jun 8, 2026

Problem

Currently, extensionToLanguage is the only mechanism for routing files to LSP servers. It relies on path.extname() to extract the file extension, then performs a direct lookup in the mapping. This means files without a traditional extension cannot be matched to any LSP server.

Affected files include:

| File | path.extname() result | Can match? |
|------|------------------------|------------|
| Dockerfile | "" (empty) | No |
| Makefile | "" (empty) | No |
| Jenkinsfile | "" (empty) | No |
| Vagrantfile | "" (empty) | No |
| Gemfile | "" (empty) | No |
| docker-compose.yml | .yml | Conflicts with all YAML files |
| compose.yaml | .yaml | Conflicts with all YAML files |

This also relates to #15785 (compound extension matching), which was auto-closed without resolution.

Use Case: Docker LSP

There are mature, widely-used Docker language servers available:

However, none of these can be integrated as Claude Code LSP plugins because Dockerfile has no file extension and docker-compose.yml shares .yml with all YAML files.

Proposed Solution

Add a filenameToLanguage field alongside extensionToLanguage:

{
  "dockerfile": {
    "command": "docker-langserver",
    "args": ["--stdio"],
    "extensionToLanguage": {
      ".dockerfile": "dockerfile"
    },
    "filenameToLanguage": {
      "Dockerfile": "dockerfile",
      "Containerfile": "dockerfile"
    },
    "transport": "stdio"
  }
}

The matching logic would be:

  1. Extract the basename of the file
  2. Check filenameToLanguage for an exact match (higher priority)
  3. Fall back to extensionToLanguage via path.extname() (current behavior)

This is a minimal, backwards-compatible change — existing plugins continue to work unchanged, and new plugins can opt into filename-based matching.

Alternative: Glob Patterns

A more powerful alternative would be globToLanguage supporting glob patterns (e.g., "Dockerfile*": "dockerfile", "docker-compose*.yml": "dockercompose"), but exact filename matching would cover the majority of use cases with much simpler implementation.

Impact

This would unblock LSP support for Docker, Make, and many other tools that use conventional filenames without extensions — a common pattern in the DevOps/infrastructure ecosystem.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗