Skip to content

Commit ca72b95

Browse files
committed
Handle project references in a program
1 parent 15a6577 commit ca72b95

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

+1781
-396
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: 36 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,8 @@ 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+
IsSourceFromProjectReference(path tspath.Path) bool
540+
GetSourceAndProjectReference(path tspath.Path) *tsoptions.SourceAndProjectReference
537541
}
538542

539543
type Host interface {
@@ -2081,7 +2085,7 @@ func (c *Checker) getSymbol(symbols ast.SymbolTable, name string, meaning ast.Sy
20812085
}
20822086

20832087
func (c *Checker) CheckSourceFile(ctx context.Context, sourceFile *ast.SourceFile) {
2084-
if SkipTypeChecking(sourceFile, c.compilerOptions) {
2088+
if SkipTypeChecking(sourceFile, c.compilerOptions, c.program) {
20852089
return
20862090
}
20872091
c.checkSourceFile(ctx, sourceFile)
@@ -6444,15 +6448,13 @@ func (c *Checker) checkAliasSymbol(node *ast.Node) {
64446448
// in files that are unambiguously CommonJS in this mode.
64456449
c.error(node, diagnostics.ESM_syntax_is_not_allowed_in_a_CommonJS_module_when_module_is_set_to_preserve)
64466450
}
6447-
// !!!
6448-
6449-
// if c.compilerOptions.VerbatimModuleSyntax.IsTrue() && !ast.IsTypeOnlyImportOrExportDeclaration(node) && node.Flags&ast.NodeFlagsAmbient == 0 && targetFlags&ast.SymbolFlagsConstEnum != 0 {
6450-
// constEnumDeclaration := target.ValueDeclaration
6451-
// redirect := host.getRedirectReferenceForResolutionFromSourceOfProject(ast.GetSourceFileOfNode(constEnumDeclaration).ResolvedPath)
6452-
// if constEnumDeclaration.Flags&ast.NodeFlagsAmbient != 0 && (redirect == nil || !shouldPreserveConstEnums(redirect.commandLine.options)) {
6453-
// c.error(node, diagnostics.Cannot_access_ambient_const_enums_when_0_is_enabled, c.getIsolatedModulesLikeFlagName())
6454-
// }
6455-
// }
6451+
if c.compilerOptions.VerbatimModuleSyntax.IsTrue() && !ast.IsTypeOnlyImportOrExportDeclaration(node) && node.Flags&ast.NodeFlagsAmbient == 0 && targetFlags&ast.SymbolFlagsConstEnum != 0 {
6452+
constEnumDeclaration := target.ValueDeclaration
6453+
redirect := c.program.GetSourceAndProjectReference(ast.GetSourceFileOfNode(constEnumDeclaration).Path())
6454+
if constEnumDeclaration.Flags&ast.NodeFlagsAmbient != 0 && (redirect == nil || !redirect.Resolved.CompilerOptions().ShouldPreserveConstEnums()) {
6455+
c.error(node, diagnostics.Cannot_access_ambient_const_enums_when_0_is_enabled, c.getIsolatedModulesLikeFlagName())
6456+
}
6457+
}
64566458
}
64576459
if ast.IsImportSpecifier(node) {
64586460
targetSymbol := c.resolveAliasWithDeprecationCheck(symbol, node)
@@ -7166,15 +7168,14 @@ func (c *Checker) checkConstEnumAccess(node *ast.Node, t *Type) {
71667168
// --verbatimModuleSyntax only gets checked here when the enum usage does not
71677169
// resolve to an import, because imports of ambient const enums get checked
71687170
// separately in `checkAliasSymbol`.
7169-
// !!!
7170-
// if c.compilerOptions.IsolatedModules.IsTrue() || c.compilerOptions.VerbatimModuleSyntax.IsTrue() && ok && c.resolveName(node, getFirstIdentifier(node).Text(), ast.SymbolFlagsAlias, nil, false, true) == nil {
7171-
// // Debug.assert(t.symbol.Flags&ast.SymbolFlagsConstEnum != 0)
7172-
// constEnumDeclaration := t.symbol.ValueDeclaration
7173-
// redirect := host.getRedirectReferenceForResolutionFromSourceOfProject(ast.GetSourceFileOfNode(constEnumDeclaration).ResolvedPath)
7174-
// if constEnumDeclaration.Flags&ast.NodeFlagsAmbient != 0 && !isValidTypeOnlyAliasUseSite(node) && (redirect == nil || !shouldPreserveConstEnums(redirect.commandLine.options)) {
7175-
// c.error(node, diagnostics.Cannot_access_ambient_const_enums_when_0_is_enabled, c.getIsolatedModulesLikeFlagName())
7176-
// }
7177-
// }
7171+
if c.compilerOptions.IsolatedModules.IsTrue() || c.compilerOptions.VerbatimModuleSyntax.IsTrue() && ok && c.resolveName(node, ast.GetFirstIdentifier(node).Text(), ast.SymbolFlagsAlias, nil, false, true) == nil {
7172+
// Debug.assert(t.symbol.Flags&ast.SymbolFlagsConstEnum != 0)
7173+
constEnumDeclaration := t.symbol.ValueDeclaration
7174+
redirect := c.program.GetSourceAndProjectReference(ast.GetSourceFileOfNode(constEnumDeclaration).Path())
7175+
if constEnumDeclaration.Flags&ast.NodeFlagsAmbient != 0 && !ast.IsValidTypeOnlyAliasUseSite(node) && (redirect == nil || !redirect.Resolved.CompilerOptions().ShouldPreserveConstEnums()) {
7176+
c.error(node, diagnostics.Cannot_access_ambient_const_enums_when_0_is_enabled, c.getIsolatedModulesLikeFlagName())
7177+
}
7178+
}
71787179
}
71797180

71807181
func (c *Checker) instantiateTypeWithSingleGenericCallSignature(node *ast.Node, t *Type, checkMode CheckMode) *Type {
@@ -14433,7 +14434,7 @@ func (c *Checker) resolveExternalModule(location *ast.Node, moduleReference stri
1443314434
var sourceFile *ast.SourceFile
1443414435
resolvedModule := c.program.GetResolvedModule(importingSourceFile, moduleReference, mode)
1443514436
if resolvedModule.IsResolved() {
14436-
sourceFile = c.program.GetSourceFile(resolvedModule.ResolvedFileName)
14437+
sourceFile = c.program.GetSourceFileForResolvedModule(resolvedModule.ResolvedFileName)
1443714438
}
1443814439

1443914440
if sourceFile != nil {
@@ -14539,6 +14540,21 @@ func (c *Checker) resolveExternalModule(location *ast.Node, moduleReference stri
1453914540
}
1454014541

1454114542
if moduleNotFoundError != nil {
14543+
14544+
// See if this was possibly a projectReference redirect
14545+
if resolvedModule.IsResolved() {
14546+
redirect := c.program.GetOutputAndProjectReference(tspath.ToPath(resolvedModule.ResolvedFileName, c.program.GetCurrentDirectory(), c.program.UseCaseSensitiveFileNames()))
14547+
if redirect != nil && redirect.OutputDts != "" {
14548+
c.error(
14549+
errorNode,
14550+
diagnostics.Output_file_0_has_not_been_built_from_source_file_1,
14551+
redirect.OutputDts,
14552+
resolvedModule.ResolvedFileName,
14553+
)
14554+
return nil
14555+
}
14556+
}
14557+
1454214558
// !!!
1454314559
isExtensionlessRelativePathImport := tspath.PathIsRelative(moduleReference) && !tspath.HasExtension(moduleReference)
1454414560
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: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1471,10 +1471,15 @@ 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+
type SkipTypeCheckingHost interface {
1475+
IsSourceFromProjectReference(path tspath.Path) bool
1476+
}
1477+
1478+
func SkipTypeChecking(sourceFile *ast.SourceFile, options *core.CompilerOptions, host SkipTypeCheckingHost) bool {
14751479
return options.NoCheck.IsTrue() ||
14761480
options.SkipLibCheck.IsTrue() && sourceFile.IsDeclarationFile ||
14771481
options.SkipDefaultLibCheck.IsTrue() && sourceFile.HasNoDefaultLib ||
1482+
host.IsSourceFromProjectReference(sourceFile.Path()) ||
14781483
!canIncludeBindAndCheckDiagnostics(sourceFile, options)
14791484
}
14801485

internal/compiler/emitHost.go

Lines changed: 3 additions & 6 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,18 +74,14 @@ 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)
86-
}
87-
8885
func (host *emitHost) GetEffectiveDeclarationFlags(node *ast.Node, flags ast.ModifierFlags) ast.ModifierFlags {
8986
return host.GetEmitResolver(ast.GetSourceFileOfNode(node), true).GetEffectiveDeclarationFlags(node, flags)
9087
}

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)