Repository navigation
Allow content mapper registrations to filter their files with an include glob, inherit default extension from manifest - #65047
Draft
Andrew Branch (andrewbranch) wants to merge 2 commits into
Conversation
Use manifest extensions when a registration omits them, while preserving explicit overrides. Carry these defaults through extension contributions, validation, and config schemas. Co-authored-by: Copilot <[email protected]>
Narrow mapper claims with tsconfig-style include patterns. Use the winning mapper consistently for discovery, resolution, language services, and output naming, and reject incompatible output mappings. Co-authored-by: Copilot <[email protected]>
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved mapper-filter inconsistencies can misresolve imports, rewrite unclaimed files, and prevent claimed files from receiving editor synchronization.
8 open issues
Use the resolved target mapper for specifier rewrites · New Fall back when RelativePattern support is unavailable · New Apply mapper filters after module suffix expansion · New Avoid narrowing selectors for non-terminal extension wildcards · New Escape literal brackets and braces in LSP selectors · New Normalize dot includes before generating selectors · New Ignore conflicting mapping pairs within one mapper · New Honor filtered mappings for dynamic import rewrites · New
2 files not reviewed
tsc/internal/diagnostics/diagnostics_generated.go: Generated filetsc/internal/lsp/lsproto/lsp_generated.go: Generated file
What changed in this PR
This PR addresses #64362 by adding path-based content mapper selection and manifest-provided default extensions across the native compiler, language server, and VS Code integration.
Changes:
- Adds optional
includeglobs, extension defaults, and validation for conflicting output mappings. - Applies mapper selection to file discovery, module resolution, import rewriting, output paths, and editor registrations.
- Updates schemas, protocol types, tests, and baselines for the new behavior.
| File | Description |
|---|---|
tsc/testdata/baselines/reference/tsc/contentMapperInclusion/manifest-extensions-with-a-narrowing-include-and-declaration-fallback.js |
Records filtered mapping and declaration fallback. |
tsc/testdata/baselines/reference/tsc/contentMapperInclusion/filtered-files-rewrite-but-unclaimed-imports-keep-their-extension.js |
Records selective import rewriting. |
tsc/internal/vfs/vfsmatch/vfsmatch.go |
Adds mapper-specific glob matching. |
tsc/internal/vfs/vfsmatch/stringer_generated.go |
Names the new matching mode. |
tsc/internal/vfs/vfsmatch/MATCHING_ALGORITHM.md |
Documents mapper glob semantics. |
tsc/internal/tsoptions/tsconfigparsing.go |
Parses, inherits, validates, and applies mapper filters. |
tsc/internal/tsoptions/tsconfigparsing_test.go |
Tests updated registration validation. |
tsc/internal/tsoptions/parsinghelpers.go |
Parses optional extensions and includes. |
tsc/internal/tsoptions/parsedoptions_test.go |
Tests equality of new mapper fields. |
tsc/internal/tsoptions/parsedcommandline.go |
Caches and exposes file-specific mapper selection. |
tsc/internal/tsoptions/contentmappers.go |
Reads manifest extension defaults. |
tsc/internal/tsoptions/contentmappers_test.go |
Tests filters, inheritance, defaults, and output consistency. |
tsc/internal/transformers/tstransforms/importelision_test.go |
Updates the test host interface. |
tsc/internal/transformers/moduletransforms/utilities.go |
Filters import rewrites by mapper selection. |
tsc/internal/transformers/moduletransforms/esmodule.go |
Passes mapper context through ES module rewriting. |
tsc/internal/transformers/moduletransforms/commonjsmodule.go |
Passes mapper context through CommonJS rewriting. |
tsc/internal/transformers/declarations/transform.go |
Applies mapper selection to declaration imports. |
tsc/internal/transformers/chain.go |
Adds a file-specific mapper callback. |
tsc/internal/testutil/projecttestutil/clientmock_generated.go |
Updates mocks for selector registration. |
tsc/internal/testutil/harnessutil/harnessutil.go |
Uses source paths for declaration naming. |
tsc/internal/project/session.go |
Synchronizes selectors and handles mapped-file changes. |
tsc/internal/project/extendedconfigcache_test.go |
Updates the no-op client interface. |
tsc/internal/project/contentmapper_test.go |
Tests selector registration and watch refreshes. |
tsc/internal/project/configfileregistry.go |
Converts mapper includes into client selectors. |
tsc/internal/project/configfileregistry_test.go |
Tests selector patterns and base directories. |
tsc/internal/project/client.go |
Defines the selector registration interface. |
tsc/internal/printer/emithost.go |
Exposes file-specific mapper extensions. |
tsc/internal/packagejson/packagejson.go |
Adds manifest extension fields. |
tsc/internal/outputpaths/outputpaths.go |
Derives output names from the selected mapper. |
tsc/internal/outputpaths/outputpaths_test.go |
Updates the output-path test host. |
tsc/internal/modulespecifiers/types.go |
Updates the module-specifier host contract. |
tsc/internal/modulespecifiers/specifiers_test.go |
Updates the module-specifier test host. |
tsc/internal/module/resolver.go |
Applies mapper filters during module resolution. |
tsc/internal/module/resolver_test.go |
Tests filtered resolution and declaration fallback. |
tsc/internal/module/cache.go |
Preserves mapper matching in resolver data. |
tsc/internal/lsp/server.go |
Registers document selectors and reads contribution defaults. |
tsc/internal/lsp/server_contentmapper_test.go |
Tests filtered client registrations. |
tsc/internal/lsp/server_contentmapper_internal_test.go |
Tests document patterns and manifest defaults. |
tsc/internal/lsp/lsproto/lsp_generated.go |
Updates generated contribution protocol types. |
tsc/internal/ls/string_completions.go |
Filters unclaimed files while preserving ambient matches. |
tsc/internal/ls/sourcedefinition.go |
Supplies mapper filters to source-definition resolution. |
tsc/internal/ls/autoimport/aliasresolver.go |
Updates the alias resolver interface. |
tsc/internal/fourslash/tests/contentMapperInclusion_test.go |
Tests filtered import completions. |
tsc/internal/execute/tsctests/contentmapper_inclusion_test.go |
Adds end-to-end inclusion and rewrite cases. |
tsc/internal/diagnostics/diagnostics_generated.go |
Adds generated mapper diagnostics. |
tsc/internal/diagnostics/diagnosticMessages.json |
Defines default-extension and conflict messages. |
tsc/internal/diagnostics/diagnosticMessages.generated.json |
Updates generated diagnostic text. |
tsc/internal/contentmapper/filematcher.go |
Implements mapper selection and rewrite filtering. |
tsc/internal/contentmapper/contentmapper.go |
Adds include and default-extension metadata. |
tsc/internal/compiler/program.go |
Exposes per-file mapper extensions. |
tsc/internal/compiler/fileloader.go |
Uses mapper claims when loading files. |
tsc/internal/compiler/emitter.go |
Supplies mapper selection to transformers. |
tsc/internal/compiler/emitHost.go |
Forwards file-specific mapper queries. |
tsc/internal/compiler/contentmapper_test.go |
Tests filtered mappings through symlinks. |
tsc/internal/checker/nodebuilderimpl.go |
Filters generated module-specifier rewrites. |
tsc/internal/checker/checker.go |
Uses mapper selection when checking rewrites. |
tsc/internal/api/session_module_resolution_test.go |
Tests project-specific resolver context. |
tsc/internal/api/module_resolution.go |
Applies the selected config’s mapper filters. |
tools/scripts/tsc/options.test.ts |
Tests schema acceptance and rejection. |
tools/scripts/tsc/options-schema.ts |
Generates updated mapper configuration schemas. |
tools/scripts/lsp/generate.mts |
Defines optional protocol extension fields. |
packages/vscode-typescript/test/contentMapperContributions.test.ts |
Tests manifest-default contribution serialization. |
packages/vscode-typescript/src/contentMapperContributions.ts |
Validates, serializes, and matches extension defaults. |
packages/typescript/src/vscode/extensionApi.ts |
Exposes optional contribution extensions. |
packages/typescript/schemas/tsconfig.schema.json |
Updates the generated tsconfig mapper schema. |
packages/typescript/schemas/jsconfig.schema.json |
Updates the generated jsconfig mapper schema. |
Review effort: Balanced
Comment on lines
+77
to
+78
| path := importingFile.Directory().ResolveFile(specifier.AsString()) | ||
| return FilterExtensionRewrites(rewrites, extensionForFileName(path), caseSensitivity) |
| filters = append(filters, lsproto.TextDocumentFilterLanguageOrSchemeOrPattern{ | ||
| Pattern: &lsproto.TextDocumentFilterPattern{ | ||
| Pattern: lsproto.PatternOrRelativePattern{Pattern: new("**/*" + ext)}, | ||
| Pattern: contentMapperDocumentPattern(selector), |
Comment on lines
+1783
to
+1784
| if matcher := r.resolver.contentMapperFileMatcher; matcher != nil { | ||
| isExtraExtension = r.contentMapperExtensionForFileName(fileName) == originalExtension |
Comment on lines
+52
to
+54
| if !strings.Contains(last[:len(last)-1], ".") { | ||
| return pattern + extension, true | ||
| } |
| base = base.ResolveDirectory(pattern[:baseLength]) | ||
| pattern = strings.TrimPrefix(pattern[baseLength:], "/") | ||
| } | ||
| return ContentMapperSelector{Base: base, Pattern: pattern, Extension: extension} |
| } | ||
| for _, include := range mapper.Definition.Include { | ||
| for _, extension := range mapper.Definition.Extensions { | ||
| if pattern, ok := contentMapperSelectorPattern(include, extension); ok { |
| if len(longer.extension) < len(shorter.extension) { | ||
| longer, shorter = shorter, longer | ||
| } | ||
| if !strings.HasSuffix(longer.extension, shorter.extension) || longer.mapper.Include == nil && shorter.mapper.Include == nil { |
Comment on lines
+1501
to
+1504
| if !strings.HasSuffix(longer.extension, shorter.extension) || longer.mapper.Include == nil && shorter.mapper.Include == nil { | ||
| continue | ||
| } | ||
| // A runtime rewrite cannot select an include filter. Compare resulting names: |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Fixes #64362