Skip to content

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
microsoft:mainfrom
andrewbranch:content-mapper-include-glob
Draft

Andrew Branch (andrewbranch) wants to merge 2 commits into
microsoft:mainfrom
andrewbranch:content-mapper-include-glob

Conversation

@andrewbranch

Copy link
Copy Markdown
Member

Fixes #64362

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]>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved mapper-filter inconsistencies can misresolve imports, rewrite unclaimed files, and prevent claimed files from receiving editor synchronization.

8 open issues
2 files not reviewed
  • tsc/internal/diagnostics/diagnostics_generated.go: Generated file
  • tsc/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 include globs, 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

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

Labels

Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Content mappers: more granular resolution, and default extensions in the manifest

2 participants