Skip to content

Commit 6c749d9

Browse files
committed
Handle project references in a program
1 parent dbda6ba commit 6c749d9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1770
-394
lines changed

internal/api/api.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ func (api *API) DocumentRegistry() *project.DocumentRegistry {
8383
return api.documentRegistry
8484
}
8585

86+
func (api *API) GetResolvedProjectReference(fileName string, path tspath.Path) *tsoptions.ParsedCommandLine {
87+
commandLine, _ := tsoptions.GetParsedCommandLineOfConfigFilePath(fileName, path, nil, api.host, nil)
88+
return commandLine
89+
}
90+
8691
// FS implements ProjectHost.
8792
func (api *API) FS() vfs.FS {
8893
return api.host.FS()

internal/ast/utilities.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3569,3 +3569,23 @@ func IsTrivia(token Kind) bool {
35693569
func HasDecorators(node *Node) bool {
35703570
return HasSyntacticModifier(node, ModifierFlagsDecorator)
35713571
}
3572+
3573+
type HasFileNameImpl struct {
3574+
fileName string
3575+
path tspath.Path
3576+
}
3577+
3578+
func NewHasFileName(fileName string, path tspath.Path) HasFileName {
3579+
return &HasFileNameImpl{
3580+
fileName: fileName,
3581+
path: path,
3582+
}
3583+
}
3584+
3585+
func (h *HasFileNameImpl) FileName() string {
3586+
return h.fileName
3587+
}
3588+
3589+
func (h *HasFileNameImpl) Path() tspath.Path {
3590+
return h.path
3591+
}

internal/checker/checker.go

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/microsoft/typescript-go/internal/printer"
2626
"github.com/microsoft/typescript-go/internal/scanner"
2727
"github.com/microsoft/typescript-go/internal/stringutil"
28+
"github.com/microsoft/typescript-go/internal/tsoptions"
2829
"github.com/microsoft/typescript-go/internal/tspath"
2930
)
3031

@@ -526,6 +527,7 @@ type Program interface {
526527
BindSourceFiles()
527528
FileExists(fileName string) bool
528529
GetSourceFile(fileName string) *ast.SourceFile
530+
GetSourceFileForResolvedModule(fileName string) *ast.SourceFile
529531
GetEmitModuleFormatOfFile(sourceFile ast.HasFileName) core.ModuleKind
530532
GetEmitSyntaxForUsageLocation(sourceFile ast.HasFileName, usageLocation *ast.StringLiteralLike) core.ResolutionMode
531533
GetImpliedNodeFormatForEmit(sourceFile ast.HasFileName) core.ModuleKind
@@ -534,6 +536,7 @@ type Program interface {
534536
GetSourceFileMetaData(path tspath.Path) *ast.SourceFileMetaData
535537
GetJSXRuntimeImportSpecifier(path tspath.Path) (moduleReference string, specifier *ast.Node)
536538
GetImportHelpersImportSpecifier(path tspath.Path) *ast.Node
539+
GetSourceAndProjectReference(path tspath.Path) *tsoptions.SourceAndProjectReference
537540
}
538541

539542
type Host interface {
@@ -2081,7 +2084,7 @@ func (c *Checker) getSymbol(symbols ast.SymbolTable, name string, meaning ast.Sy
20812084
}
20822085

20832086
func (c *Checker) CheckSourceFile(ctx context.Context, sourceFile *ast.SourceFile) {
2084-
if SkipTypeChecking(sourceFile, c.compilerOptions) {
2087+
if SkipTypeChecking(sourceFile, c.compilerOptions, c.program.IsSourceFromProjectReference) {
20852088
return
20862089
}
20872090
c.checkSourceFile(ctx, sourceFile)
@@ -6426,15 +6429,13 @@ func (c *Checker) checkAliasSymbol(node *ast.Node) {
64266429
// in files that are unambiguously CommonJS in this mode.
64276430
c.error(node, diagnostics.ESM_syntax_is_not_allowed_in_a_CommonJS_module_when_module_is_set_to_preserve)
64286431
}
6429-
// !!!
6430-
6431-
// if c.compilerOptions.VerbatimModuleSyntax.IsTrue() && !ast.IsTypeOnlyImportOrExportDeclaration(node) && node.Flags&ast.NodeFlagsAmbient == 0 && targetFlags&ast.SymbolFlagsConstEnum != 0 {
6432-
// constEnumDeclaration := target.ValueDeclaration
6433-
// redirect := host.getRedirectReferenceForResolutionFromSourceOfProject(ast.GetSourceFileOfNode(constEnumDeclaration).ResolvedPath)
6434-
// if constEnumDeclaration.Flags&ast.NodeFlagsAmbient != 0 && (redirect == nil || !shouldPreserveConstEnums(redirect.commandLine.options)) {
6435-
// c.error(node, diagnostics.Cannot_access_ambient_const_enums_when_0_is_enabled, c.getIsolatedModulesLikeFlagName())
6436-
// }
6437-
// }
6432+
if c.compilerOptions.VerbatimModuleSyntax.IsTrue() && !ast.IsTypeOnlyImportOrExportDeclaration(node) && node.Flags&ast.NodeFlagsAmbient == 0 && targetFlags&ast.SymbolFlagsConstEnum != 0 {
6433+
constEnumDeclaration := target.ValueDeclaration
6434+
redirect := c.program.GetSourceAndProjectReference(ast.GetSourceFileOfNode(constEnumDeclaration).Path())
6435+
if constEnumDeclaration.Flags&ast.NodeFlagsAmbient != 0 && (redirect == nil || !redirect.Resolved.CompilerOptions().ShouldPreserveConstEnums()) {
6436+
c.error(node, diagnostics.Cannot_access_ambient_const_enums_when_0_is_enabled, c.getIsolatedModulesLikeFlagName())
6437+
}
6438+
}
64386439
}
64396440
if ast.IsImportSpecifier(node) {
64406441
targetSymbol := c.resolveAliasWithDeprecationCheck(symbol, node)
@@ -7148,15 +7149,14 @@ func (c *Checker) checkConstEnumAccess(node *ast.Node, t *Type) {
71487149
// --verbatimModuleSyntax only gets checked here when the enum usage does not
71497150
// resolve to an import, because imports of ambient const enums get checked
71507151
// separately in `checkAliasSymbol`.
7151-
// !!!
7152-
// if c.compilerOptions.IsolatedModules.IsTrue() || c.compilerOptions.VerbatimModuleSyntax.IsTrue() && ok && c.resolveName(node, getFirstIdentifier(node).Text(), ast.SymbolFlagsAlias, nil, false, true) == nil {
7153-
// // Debug.assert(t.symbol.Flags&ast.SymbolFlagsConstEnum != 0)
7154-
// constEnumDeclaration := t.symbol.ValueDeclaration
7155-
// redirect := host.getRedirectReferenceForResolutionFromSourceOfProject(ast.GetSourceFileOfNode(constEnumDeclaration).ResolvedPath)
7156-
// if constEnumDeclaration.Flags&ast.NodeFlagsAmbient != 0 && !isValidTypeOnlyAliasUseSite(node) && (redirect == nil || !shouldPreserveConstEnums(redirect.commandLine.options)) {
7157-
// c.error(node, diagnostics.Cannot_access_ambient_const_enums_when_0_is_enabled, c.getIsolatedModulesLikeFlagName())
7158-
// }
7159-
// }
7152+
if c.compilerOptions.IsolatedModules.IsTrue() || c.compilerOptions.VerbatimModuleSyntax.IsTrue() && ok && c.resolveName(node, ast.GetFirstIdentifier(node).Text(), ast.SymbolFlagsAlias, nil, false, true) == nil {
7153+
// Debug.assert(t.symbol.Flags&ast.SymbolFlagsConstEnum != 0)
7154+
constEnumDeclaration := t.symbol.ValueDeclaration
7155+
redirect := c.program.GetSourceAndProjectReference(ast.GetSourceFileOfNode(constEnumDeclaration).Path())
7156+
if constEnumDeclaration.Flags&ast.NodeFlagsAmbient != 0 && !ast.IsValidTypeOnlyAliasUseSite(node) && (redirect == nil || !redirect.Resolved.CompilerOptions().ShouldPreserveConstEnums()) {
7157+
c.error(node, diagnostics.Cannot_access_ambient_const_enums_when_0_is_enabled, c.getIsolatedModulesLikeFlagName())
7158+
}
7159+
}
71607160
}
71617161

71627162
func (c *Checker) instantiateTypeWithSingleGenericCallSignature(node *ast.Node, t *Type, checkMode CheckMode) *Type {
@@ -14421,7 +14421,7 @@ func (c *Checker) resolveExternalModule(location *ast.Node, moduleReference stri
1442114421
var sourceFile *ast.SourceFile
1442214422
resolvedModule := c.program.GetResolvedModule(importingSourceFile, moduleReference, mode)
1442314423
if resolvedModule.IsResolved() {
14424-
sourceFile = c.program.GetSourceFile(resolvedModule.ResolvedFileName)
14424+
sourceFile = c.program.GetSourceFileForResolvedModule(resolvedModule.ResolvedFileName)
1442514425
}
1442614426

1442714427
if sourceFile != nil {
@@ -14527,6 +14527,21 @@ func (c *Checker) resolveExternalModule(location *ast.Node, moduleReference stri
1452714527
}
1452814528

1452914529
if moduleNotFoundError != nil {
14530+
14531+
// See if this was possibly a projectReference redirect
14532+
if resolvedModule.IsResolved() {
14533+
redirect := c.program.GetOutputAndProjectReference(tspath.ToPath(resolvedModule.ResolvedFileName, c.program.GetCurrentDirectory(), c.program.UseCaseSensitiveFileNames()))
14534+
if redirect != nil && redirect.OutputDts != "" {
14535+
c.error(
14536+
errorNode,
14537+
diagnostics.Output_file_0_has_not_been_built_from_source_file_1,
14538+
redirect.OutputDts,
14539+
resolvedModule.ResolvedFileName,
14540+
)
14541+
return nil
14542+
}
14543+
}
14544+
1453014545
// !!!
1453114546
isExtensionlessRelativePathImport := tspath.PathIsRelative(moduleReference) && !tspath.HasExtension(moduleReference)
1453214547
resolutionIsNode16OrNext := c.moduleResolutionKind == core.ModuleResolutionKindNode16 || c.moduleResolutionKind == core.ModuleResolutionKindNodeNext

internal/checker/checker_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ foo.bar;`
3636
fs = bundled.WrapFS(fs)
3737

3838
cd := "/"
39-
host := compiler.NewCompilerHost(nil, cd, fs, bundled.LibPath())
39+
host := compiler.NewCompilerHost(nil, cd, fs, bundled.LibPath(), nil)
4040

4141
parsed, errors := tsoptions.GetParsedCommandLineOfConfigFile("/tsconfig.json", &core.CompilerOptions{}, host, nil)
4242
assert.Equal(t, len(errors), 0, "Expected no errors in parsed command line")
@@ -70,7 +70,7 @@ func TestCheckSrcCompiler(t *testing.T) {
7070

7171
rootPath := tspath.CombinePaths(tspath.NormalizeSlashes(repo.TypeScriptSubmodulePath), "src", "compiler")
7272

73-
host := compiler.NewCompilerHost(nil, rootPath, fs, bundled.LibPath())
73+
host := compiler.NewCompilerHost(nil, rootPath, fs, bundled.LibPath(), nil)
7474
parsed, errors := tsoptions.GetParsedCommandLineOfConfigFile(tspath.CombinePaths(rootPath, "tsconfig.json"), &core.CompilerOptions{}, host, nil)
7575
assert.Equal(t, len(errors), 0, "Expected no errors in parsed command line")
7676
p := compiler.NewProgram(compiler.ProgramOptions{
@@ -87,7 +87,7 @@ func BenchmarkNewChecker(b *testing.B) {
8787

8888
rootPath := tspath.CombinePaths(tspath.NormalizeSlashes(repo.TypeScriptSubmodulePath), "src", "compiler")
8989

90-
host := compiler.NewCompilerHost(nil, rootPath, fs, bundled.LibPath())
90+
host := compiler.NewCompilerHost(nil, rootPath, fs, bundled.LibPath(), nil)
9191
parsed, errors := tsoptions.GetParsedCommandLineOfConfigFile(tspath.CombinePaths(rootPath, "tsconfig.json"), &core.CompilerOptions{}, host, nil)
9292
assert.Equal(b, len(errors), 0, "Expected no errors in parsed command line")
9393
p := compiler.NewProgram(compiler.ProgramOptions{

internal/checker/utilities.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1471,10 +1471,11 @@ func forEachYieldExpression(body *ast.Node, visitor func(expr *ast.Node)) {
14711471
traverse(body)
14721472
}
14731473

1474-
func SkipTypeChecking(sourceFile *ast.SourceFile, options *core.CompilerOptions) bool {
1474+
func SkipTypeChecking(sourceFile *ast.SourceFile, options *core.CompilerOptions, isSourceFromProjectReference func(path tspath.Path) bool) bool {
14751475
return options.NoCheck.IsTrue() ||
14761476
options.SkipLibCheck.IsTrue() && sourceFile.IsDeclarationFile ||
14771477
options.SkipDefaultLibCheck.IsTrue() && sourceFile.HasNoDefaultLib ||
1478+
isSourceFromProjectReference(sourceFile.Path()) ||
14781479
!canIncludeBindAndCheckDiagnostics(sourceFile, options)
14791480
}
14801481

internal/compiler/emitHost.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/microsoft/typescript-go/internal/outputpaths"
1111
"github.com/microsoft/typescript-go/internal/printer"
1212
"github.com/microsoft/typescript-go/internal/transformers/declarations"
13+
"github.com/microsoft/typescript-go/internal/tsoptions"
1314
"github.com/microsoft/typescript-go/internal/tspath"
1415
)
1516

@@ -73,16 +74,16 @@ func (host *emitHost) GetPackageJsonInfo(pkgJsonPath string) modulespecifiers.Pa
7374
return host.program.GetPackageJsonInfo(pkgJsonPath)
7475
}
7576

76-
func (host *emitHost) GetProjectReferenceRedirect(path string) string {
77-
return host.program.GetProjectReferenceRedirect(path)
77+
func (host *emitHost) GetOutputAndProjectReference(path tspath.Path) *tsoptions.OutputDtsAndProjectReference {
78+
return host.program.GetOutputAndProjectReference(path)
7879
}
7980

8081
func (host *emitHost) GetRedirectTargets(path tspath.Path) []string {
8182
return host.program.GetRedirectTargets(path)
8283
}
8384

84-
func (host *emitHost) IsSourceOfProjectReferenceRedirect(path string) bool {
85-
return host.program.IsSourceOfProjectReferenceRedirect(path)
85+
func (host *emitHost) IsSourceFromProjectReference(path tspath.Path) bool {
86+
return host.program.IsSourceFromProjectReference(path)
8687
}
8788

8889
func (host *emitHost) GetEffectiveDeclarationFlags(node *ast.Node, flags ast.ModifierFlags) ast.ModifierFlags {

internal/compiler/emitter.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,10 @@ func sourceFileMayBeEmitted(sourceFile *ast.SourceFile, host printer.EmitHost, f
317317
return true
318318
}
319319

320-
// !!! Source files from referenced projects are not emitted
320+
// Source files from referenced projects are not emitted
321+
if host.GetOutputAndProjectReference(sourceFile.Path()) != nil {
322+
return false
323+
}
321324

322325
// Any non json file should be emitted
323326
if !ast.IsJsonSourceFile(sourceFile) {

0 commit comments

Comments
 (0)