diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b9fb09a361c..b01c2df68ee 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -23,7 +23,6 @@ module ts { var emitResolver = createResolver(); var checker: TypeChecker = { - getProgram: () => program, getNodeCount: () => sum(program.getSourceFiles(), "nodeCount"), getIdentifierCount: () => sum(program.getSourceFiles(), "identifierCount"), getSymbolCount: () => sum(program.getSourceFiles(), "symbolCount"), @@ -9549,7 +9548,6 @@ module ts { function createResolver(): EmitResolver { return { - getProgram: () => program, getLocalNameOfContainer, getExpressionNamePrefix, getExportAssignmentName, diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 1dd0e4cd09f..b18881684d4 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -312,17 +312,17 @@ module ts { }; } - function getSourceFilePathInNewDir(sourceFile: SourceFile, program: Program, newDirPath: string) { - var compilerHost = program.getCompilerHost(); + function getSourceFilePathInNewDir(sourceFile: SourceFile, host: EmitHost, newDirPath: string) { + var compilerHost = host.getCompilerHost(); var sourceFilePath = getNormalizedAbsolutePath(sourceFile.filename, compilerHost.getCurrentDirectory()); - sourceFilePath = sourceFilePath.replace(program.getCommonSourceDirectory(), ""); + sourceFilePath = sourceFilePath.replace(host.getCommonSourceDirectory(), ""); return combinePaths(newDirPath, sourceFilePath); } - function getOwnEmitOutputFilePath(sourceFile: SourceFile, program: Program, extension: string){ - var compilerOptions = program.getCompilerOptions(); + function getOwnEmitOutputFilePath(sourceFile: SourceFile, host: EmitHost, extension: string){ + var compilerOptions = host.getCompilerOptions(); if (compilerOptions.outDir) { - var emitOutputFilePathWithoutExtension = removeFileExtension(getSourceFilePathInNewDir(sourceFile, program, compilerOptions.outDir)); + var emitOutputFilePathWithoutExtension = removeFileExtension(getSourceFilePathInNewDir(sourceFile, host, compilerOptions.outDir)); } else { var emitOutputFilePathWithoutExtension = removeFileExtension(sourceFile.filename); @@ -337,10 +337,10 @@ module ts { }); } - function emitDeclarations(program: Program, resolver: EmitResolver, diagnostics: Diagnostic[], jsFilePath: string, root?: SourceFile): DeclarationEmit { - var newLine = program.getCompilerHost().getNewLine(); - var compilerOptions = program.getCompilerOptions(); - var compilerHost = program.getCompilerHost(); + function emitDeclarations(host: EmitHost, resolver: EmitResolver, diagnostics: Diagnostic[], jsFilePath: string, root?: SourceFile): DeclarationEmit { + var newLine = host.getCompilerHost().getNewLine(); + var compilerOptions = host.getCompilerOptions(); + var compilerHost = host.getCompilerHost(); var write: (s: string) => void; var writeLine: () => void; @@ -1396,8 +1396,8 @@ module ts { var declFileName = referencedFile.flags & NodeFlags.DeclarationFile ? referencedFile.filename // Declaration file, use declaration file name : shouldEmitToOwnFile(referencedFile, compilerOptions) - ? getOwnEmitOutputFilePath(referencedFile, program, ".d.ts") // Own output file so get the .d.ts file - : removeFileExtension(compilerOptions.out) + ".d.ts";// Global out file + ? getOwnEmitOutputFilePath(referencedFile, host, ".d.ts") // Own output file so get the .d.ts file + : removeFileExtension(compilerOptions.out) + ".d.ts";// Global out file declFileName = getRelativePathToDirectoryOrUrl( getDirectoryPath(normalizeSlashes(jsFilePath)), @@ -1414,7 +1414,7 @@ module ts { if (!compilerOptions.noResolve) { var addedGlobalFileReference = false; forEach(root.referencedFiles, fileReference => { - var referencedFile = tryResolveScriptReference(program, root, fileReference); + var referencedFile = tryResolveScriptReference(host, root, fileReference); // All the references that are not going to be part of same file if (referencedFile && ((referencedFile.flags & NodeFlags.DeclarationFile) || // This is a declare file reference @@ -1434,12 +1434,12 @@ module ts { else { // Emit references corresponding to this file var emittedReferencedFiles: SourceFile[] = []; - forEach(program.getSourceFiles(), sourceFile => { + forEach(host.getSourceFiles(), sourceFile => { if (!isExternalModuleOrDeclarationFile(sourceFile)) { // Check what references need to be added if (!compilerOptions.noResolve) { forEach(sourceFile.referencedFiles, fileReference => { - var referencedFile = tryResolveScriptReference(program, sourceFile, fileReference); + var referencedFile = tryResolveScriptReference(host, sourceFile, fileReference); // If the reference file is a declaration file or an external module, emit that reference if (referencedFile && (isExternalModuleOrDeclarationFile(referencedFile) && @@ -1472,13 +1472,13 @@ module ts { } // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compilerOnSave feature - export function emitFiles(resolver: EmitResolver, targetSourceFile?: SourceFile): EmitResult { - var program = resolver.getProgram(); - var compilerHost = program.getCompilerHost(); - var compilerOptions = program.getCompilerOptions(); + export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile?: SourceFile): EmitResult { + // var program = resolver.getProgram(); + var compilerHost = host.getCompilerHost(); + var compilerOptions = host.getCompilerOptions(); var sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap ? [] : undefined; var diagnostics: Diagnostic[] = []; - var newLine = program.getCompilerHost().getNewLine(); + var newLine = compilerHost.getNewLine(); function emitJavaScript(jsFilePath: string, root?: SourceFile) { var writer = createTextWriter(newLine); @@ -1700,7 +1700,7 @@ module ts { // Add the file to tsFilePaths // If sourceroot option: Use the relative path corresponding to the common directory path // otherwise source locations relative to map file location - var sourcesDirectoryPath = compilerOptions.sourceRoot ? program.getCommonSourceDirectory() : sourceMapDir; + var sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir; sourceMapData.sourceMapSources.push(getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, node.filename, @@ -1840,12 +1840,12 @@ module ts { if (root) { // emitting single module file // For modules or multiple emit files the mapRoot will have directory structure like the sources // So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map - sourceMapDir = getDirectoryPath(getSourceFilePathInNewDir(root, program, sourceMapDir)); + sourceMapDir = getDirectoryPath(getSourceFilePathInNewDir(root, host, sourceMapDir)); } if (!isRootedDiskPath(sourceMapDir) && !isUrl(sourceMapDir)) { // The relative paths are relative to the common directory - sourceMapDir = combinePaths(program.getCommonSourceDirectory(), sourceMapDir); + sourceMapDir = combinePaths(host.getCommonSourceDirectory(), sourceMapDir); sourceMapData.jsSourceMappingURL = getRelativePathToDirectoryOrUrl( getDirectoryPath(normalizePath(jsFilePath)), // get the relative sourceMapDir path based on jsFilePath combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), // this is where user expects to see sourceMap @@ -4101,7 +4101,7 @@ module ts { emit(root); } else { - forEach(program.getSourceFiles(), sourceFile => { + forEach(host.getSourceFiles(), sourceFile => { if (!isExternalModuleOrDeclarationFile(sourceFile)) { emit(sourceFile); } @@ -4113,7 +4113,7 @@ module ts { } function writeDeclarationFile(jsFilePath: string, sourceFile: SourceFile) { - var emitDeclarationResult = emitDeclarations(program, resolver, diagnostics, jsFilePath, sourceFile); + var emitDeclarationResult = emitDeclarations(host, resolver, diagnostics, jsFilePath, sourceFile); // TODO(shkamat): Should we not write any declaration file if any of them can produce error, // or should we just not write this file like we are doing now if (!emitDeclarationResult.reportedDeclarationError) { @@ -4140,9 +4140,9 @@ module ts { hasSemanticErrors = resolver.hasSemanticErrors(); isEmitBlocked = resolver.isEmitBlocked(); - forEach(program.getSourceFiles(), sourceFile => { + forEach(host.getSourceFiles(), sourceFile => { if (shouldEmitToOwnFile(sourceFile, compilerOptions)) { - var jsFilePath = getOwnEmitOutputFilePath(sourceFile, program, ".js"); + var jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, ".js"); emitFile(jsFilePath, sourceFile); } }); @@ -4158,13 +4158,13 @@ module ts { hasSemanticErrors = resolver.hasSemanticErrors(targetSourceFile); isEmitBlocked = resolver.isEmitBlocked(targetSourceFile); - var jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, program, ".js"); + var jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, host, ".js"); emitFile(jsFilePath, targetSourceFile); } else if (!isDeclarationFile(targetSourceFile) && compilerOptions.out) { // Otherwise, if --out is specified and targetSourceFile is not a declaration file, // Emit all, non-external-module file, into one single output file - forEach(program.getSourceFiles(), sourceFile => { + forEach(host.getSourceFiles(), sourceFile => { if (!shouldEmitToOwnFile(sourceFile, compilerOptions)) { hasSemanticErrors = hasSemanticErrors || resolver.hasSemanticErrors(sourceFile); isEmitBlocked = isEmitBlocked || resolver.isEmitBlocked(sourceFile); diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 897b9d104bb..b1537da21c9 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -92,15 +92,6 @@ module ts { var diagnosticsProducingTypeChecker: TypeChecker; var noDiagnosticsTypeChecker: TypeChecker; - function getTypeChecker(produceDiagnostics: boolean) { - if (produceDiagnostics) { - return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = createTypeChecker(program, produceDiagnostics)); - } - else { - return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, produceDiagnostics)); - } - } - program = { getSourceFile: getSourceFile, getSourceFiles: () => files, @@ -115,6 +106,15 @@ module ts { }; return program; + function getTypeChecker(produceDiagnostics: boolean) { + if (produceDiagnostics) { + return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = createTypeChecker(program, produceDiagnostics)); + } + else { + return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, produceDiagnostics)); + } + } + function getDeclarationDiagnostics(targetSourceFile: SourceFile): Diagnostic[]{ var fullTypeChecker = getTypeChecker(/*produceDiagnostics:*/true); fullTypeChecker.getDiagnostics(targetSourceFile); @@ -124,7 +124,7 @@ module ts { function invokeEmitter(targetSourceFile?: SourceFile) { var resolver = getTypeChecker(/*produceDiagnostics:*/true).getEmitResolver(); - return emitFiles(resolver, targetSourceFile); + return emitFiles(resolver, program, targetSourceFile); } function getSourceFile(filename: string) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 7189db3781b..f8cf9a8c838 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -246,7 +246,6 @@ module ts { EnumMember, // Top-level nodes SourceFile, - Program, // Synthesized list SyntaxList, @@ -968,7 +967,6 @@ module ts { } export interface TypeChecker { - getProgram(): Program; getEmitResolver(): EmitResolver; getDiagnostics(sourceFile?: SourceFile): Diagnostic[]; getGlobalDiagnostics(): Diagnostic[]; @@ -1076,8 +1074,15 @@ module ts { errorModuleName?: string // If the symbol is not visible from module, module's name } + export interface EmitHost { + getSourceFile(filename: string): SourceFile; + getSourceFiles(): SourceFile[]; + getCompilerHost(): CompilerHost; + getCompilerOptions(): CompilerOptions; + getCommonSourceDirectory(): string; + } + export interface EmitResolver { - getProgram(): Program; getLocalNameOfContainer(container: ModuleDeclaration | EnumDeclaration): string; getExpressionNamePrefix(node: Identifier): string; getExportAssignmentName(node: SourceFile): string; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 8e0a02b2be6..8aa04811143 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -636,11 +636,11 @@ module ts { return undefined; } - export function tryResolveScriptReference(program: Program, sourceFile: SourceFile, reference: FileReference) { - if (!program.getCompilerOptions().noResolve) { + export function tryResolveScriptReference(host: EmitHost, sourceFile: SourceFile, reference: FileReference) { + if (!host.getCompilerOptions().noResolve) { var referenceFileName = isRootedDiskPath(reference.filename) ? reference.filename : combinePaths(getDirectoryPath(sourceFile.filename), reference.filename); - referenceFileName = getNormalizedAbsolutePath(referenceFileName, program.getCompilerHost().getCurrentDirectory()); - return program.getSourceFile(referenceFileName); + referenceFileName = getNormalizedAbsolutePath(referenceFileName, host.getCompilerHost().getCurrentDirectory()); + return host.getSourceFile(referenceFileName); } } diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index fd49078d041..29861d3e556 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -53,7 +53,7 @@ class CompilerBaselineRunner extends RunnerBase { var rootDir: string; var result: Harness.Compiler.CompilerResult; - var checker: ts.TypeChecker; + var program: ts.Program; var options: ts.CompilerOptions; // equivalent to the files that will be passed on the command line var toBeCompiled: { unitName: string; content: string }[]; @@ -97,10 +97,10 @@ class CompilerBaselineRunner extends RunnerBase { }); } - options = harnessCompiler.compileFiles(toBeCompiled, otherFiles, function (compileResult, _checker) { + options = harnessCompiler.compileFiles(toBeCompiled, otherFiles, function (compileResult, _program) { result = compileResult; - // The checker will be used by typeWriter - checker = _checker; + // The program will be used by typeWriter + program = _program; }, function (settings) { harnessCompiler.setCompilerSettings(tcSettings); }); @@ -138,7 +138,7 @@ class CompilerBaselineRunner extends RunnerBase { lastUnit = undefined; rootDir = undefined; result = undefined; - checker = undefined; + program = undefined; options = undefined; toBeCompiled = undefined; otherFiles = undefined; @@ -267,10 +267,10 @@ class CompilerBaselineRunner extends RunnerBase { // NEWTODO: Type baselines if (result.errors.length === 0) { Harness.Baseline.runBaseline('Correct expression types for ' + fileName, justName.replace(/\.ts/, '.types'), () => { - var allFiles = toBeCompiled.concat(otherFiles).filter(file => !!checker.getProgram().getSourceFile(file.unitName)); + var allFiles = toBeCompiled.concat(otherFiles).filter(file => !!program.getSourceFile(file.unitName)); var typeLines: string[] = []; var typeMap: { [fileName: string]: { [lineNum: number]: string[]; } } = {}; - var walker = new TypeWriterWalker(checker); + var walker = new TypeWriterWalker(program); allFiles.forEach(file => { var codeLines = file.content.split('\n'); walker.getTypes(file.unitName).forEach(result => { diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 2885045a362..0696003c82c 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -885,7 +885,7 @@ module Harness { public compileFiles(inputFiles: { unitName: string; content: string }[], otherFiles: { unitName: string; content: string }[], - onComplete: (result: CompilerResult, checker: ts.TypeChecker) => void, + onComplete: (result: CompilerResult, program: ts.Program) => void, settingsCallback?: (settings: ts.CompilerOptions) => void, options?: ts.CompilerOptions) { @@ -1062,7 +1062,7 @@ module Harness { this.lastErrors = errors; var result = new CompilerResult(fileOutputs, errors, program, ts.sys.getCurrentDirectory(), emitResult ? emitResult.sourceMaps : undefined); - onComplete(result, checker); + onComplete(result, program); // reset what newline means in case the last test changed it ts.sys.newLine = '\r\n'; diff --git a/src/harness/test262Runner.ts b/src/harness/test262Runner.ts index 7e5bafde228..24be77922f9 100644 --- a/src/harness/test262Runner.ts +++ b/src/harness/test262Runner.ts @@ -29,7 +29,7 @@ class Test262BaselineRunner extends RunnerBase { filename: string; compilerResult: Harness.Compiler.CompilerResult; inputFiles: { unitName: string; content: string }[]; - checker: ts.TypeChecker; + program: ts.Program; }; before(() => { @@ -46,12 +46,12 @@ class Test262BaselineRunner extends RunnerBase { filename: testFilename, inputFiles: inputFiles, compilerResult: undefined, - checker: undefined, + program: undefined, }; - Harness.Compiler.getCompiler().compileFiles([Test262BaselineRunner.helperFile].concat(inputFiles), /*otherFiles*/ [], (compilerResult, checker) => { + Harness.Compiler.getCompiler().compileFiles([Test262BaselineRunner.helperFile].concat(inputFiles), /*otherFiles*/ [], (compilerResult, program) => { testState.compilerResult = compilerResult; - testState.checker = checker; + testState.program = program; }, /*settingsCallback*/ undefined, Test262BaselineRunner.options); }); @@ -78,13 +78,13 @@ class Test262BaselineRunner extends RunnerBase { }); it('satisfies invariants', () => { - var sourceFile = testState.checker.getProgram().getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); + var sourceFile = testState.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); Utils.assertInvariants(sourceFile, /*parent:*/ undefined); }); it('has the expected AST',() => { Harness.Baseline.runBaseline('has the expected AST', testState.filename + '.AST.txt',() => { - var sourceFile = testState.checker.getProgram().getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); + var sourceFile = testState.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); return Utils.sourceFileToJSON(sourceFile); }, false, Test262BaselineRunner.baselineOptions); }); diff --git a/src/harness/typeWriter.ts b/src/harness/typeWriter.ts index 44888059ff3..332173d218f 100644 --- a/src/harness/typeWriter.ts +++ b/src/harness/typeWriter.ts @@ -10,11 +10,16 @@ class TypeWriterWalker { results: TypeWriterResult[]; currentSourceFile: ts.SourceFile; - constructor(public checker: ts.TypeChecker) { + private checker: ts.TypeChecker; + + constructor(private program: ts.Program) { + // Consider getting both the diagnostics checker and the non-diagnostics checker to verify + // they are consistent. + this.checker = program.getTypeChecker(/*produceDiagnostics:*/ true); } public getTypes(fileName: string): TypeWriterResult[] { - var sourceFile = this.checker.getProgram().getSourceFile(fileName); + var sourceFile = this.program.getSourceFile(fileName); this.currentSourceFile = sourceFile; this.results = []; this.visitNode(sourceFile);