diff --git a/Jakefile b/Jakefile
index 09b7e1efba4..059702f214c 100644
--- a/Jakefile
+++ b/Jakefile
@@ -39,6 +39,7 @@ var compilerSources = [
"binder.ts",
"checker.ts",
"emitter.ts",
+ "program.ts",
"commandLineParser.ts",
"tsc.ts",
"diagnosticInformationMap.generated.ts"
@@ -56,6 +57,7 @@ var servicesSources = [
"binder.ts",
"checker.ts",
"emitter.ts",
+ "program.ts",
"diagnosticInformationMap.generated.ts"
].map(function (f) {
return path.join(compilerDirectory, f);
@@ -92,6 +94,7 @@ var definitionsRoots = [
"compiler/scanner.d.ts",
"compiler/parser.d.ts",
"compiler/checker.d.ts",
+ "compiler/program.d.ts",
"services/services.d.ts",
];
diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts
index 6b2dafaa19d..201913a50b4 100644
--- a/src/compiler/binder.ts
+++ b/src/compiler/binder.ts
@@ -1,10 +1,6 @@
-///
-///
-///
///
module ts {
-
export const enum ModuleInstanceState {
NonInstantiated = 0,
Instantiated = 1,
diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index ddf08252a70..b1559f8dd13 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -1,21 +1,11 @@
-///
-///
-///
-///
///
-///
-///
module ts {
var nextSymbolId = 1;
var nextNodeId = 1;
- var nextMergeId = 1;
+ var nextMergeId = 1;
- /// fullTypeCheck denotes if this instance of the typechecker will be used to get semantic diagnostics.
- /// If fullTypeCheck === true, then the typechecker should do every possible check to produce all errors
- /// If fullTypeCheck === false, the typechecker can take shortcuts and skip checks that only produce errors.
- /// NOTE: checks that somehow affect decisions being made during typechecking should be executed in both cases.
- export function createTypeChecker(program: Program, fullTypeCheck: boolean): TypeChecker {
+ export function createTypeChecker(host: TypeCheckerHost, produceDiagnostics: boolean): TypeChecker {
var Symbol = objectAllocator.getSymbolConstructor();
var Type = objectAllocator.getTypeConstructor();
var Signature = objectAllocator.getSignatureConstructor();
@@ -25,19 +15,17 @@ module ts {
var emptyArray: any[] = [];
var emptySymbols: SymbolTable = {};
- var compilerOptions = program.getCompilerOptions();
+ var compilerOptions = host.getCompilerOptions();
+ var emitResolver = createResolver();
var checker: TypeChecker = {
- getProgram: () => program,
- getNodeCount: () => sum(program.getSourceFiles(), "nodeCount"),
- getIdentifierCount: () => sum(program.getSourceFiles(), "identifierCount"),
- getSymbolCount: () => sum(program.getSourceFiles(), "symbolCount"),
+ getNodeCount: () => sum(host.getSourceFiles(), "nodeCount"),
+ getIdentifierCount: () => sum(host.getSourceFiles(), "identifierCount"),
+ getSymbolCount: () => sum(host.getSourceFiles(), "symbolCount"),
getTypeCount: () => typeCount,
isUndefinedSymbol: symbol => symbol === undefinedSymbol,
isArgumentsSymbol: symbol => symbol === argumentsSymbol,
- emitFiles: invokeEmitter,
getDiagnostics,
- getDeclarationDiagnostics,
getGlobalDiagnostics,
getTypeOfSymbolAtLocation,
getDeclaredTypeOfSymbol,
@@ -63,8 +51,7 @@ module ts {
getSignatureFromDeclaration,
isImplementationOfOverload,
getAliasedSymbol: resolveImport,
- hasEarlyErrors,
- isEmitBlocked,
+ getEmitResolver: () => emitResolver,
};
var undefinedSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "undefined");
@@ -284,7 +271,7 @@ module ts {
return true;
}
- var sourceFiles = program.getSourceFiles();
+ var sourceFiles = host.getSourceFiles();
return sourceFiles.indexOf(file1) <= sourceFiles.indexOf(file2);
}
@@ -531,7 +518,7 @@ module ts {
}
while (true) {
var filename = normalizePath(combinePaths(searchPath, moduleName));
- var sourceFile = program.getSourceFile(filename + ".ts") || program.getSourceFile(filename + ".d.ts");
+ var sourceFile = host.getSourceFile(filename + ".ts") || host.getSourceFile(filename + ".d.ts");
if (sourceFile || isRelative) break;
var parentPath = getDirectoryPath(searchPath);
if (parentPath === searchPath) break;
@@ -3435,7 +3422,7 @@ module ts {
if (containingMessageChain) {
errorInfo = concatenateDiagnosticMessageChains(containingMessageChain, errorInfo);
}
- addDiagnostic(createDiagnosticForNodeFromMessageChain(errorNode, errorInfo, program.getCompilerHost().getNewLine()));
+ addDiagnostic(createDiagnosticForNodeFromMessageChain(errorNode, errorInfo, host.getCompilerHost().getNewLine()));
}
return result !== Ternary.False;
@@ -4208,7 +4195,7 @@ module ts {
}
function reportErrorsFromWidening(declaration: Declaration, type: Type) {
- if (fullTypeCheck && compilerOptions.noImplicitAny && type.flags & TypeFlags.Unwidened) {
+ if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & TypeFlags.Unwidened) {
// Report implicit any error within type if possible, otherwise report error on declaration
if (!reportWideningErrorsInType(type)) {
reportImplicitAnyError(declaration, type);
@@ -6038,7 +6025,7 @@ module ts {
// Pick the first candidate that matches the arity. This way we can get a contextual type for cases like:
// declare function f(a: { xa: number; xb: number; });
// f({ |
- if (!fullTypeCheck) {
+ if (!produceDiagnostics) {
for (var i = 0, n = candidates.length; i < n; i++) {
if (hasCorrectArity(node, args, candidates[i])) {
return candidates[i];
@@ -6343,7 +6330,7 @@ module ts {
function checkTypeAssertion(node: TypeAssertion): Type {
var exprType = checkExpression(node.expression);
var targetType = getTypeFromTypeNode(node.type);
- if (fullTypeCheck && targetType !== unknownType) {
+ if (produceDiagnostics && targetType !== unknownType) {
var widenedType = getWidenedType(exprType);
if (!(isTypeAssignableTo(targetType, widenedType))) {
checkTypeAssignableTo(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other);
@@ -6429,7 +6416,7 @@ module ts {
// must have at least one return statement somewhere in its body.
// An exception to this rule is if the function implementation consists of a single 'throw' statement.
function checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(func: FunctionLikeDeclaration, returnType: Type): void {
- if (!fullTypeCheck) {
+ if (!produceDiagnostics) {
return;
}
@@ -6501,7 +6488,7 @@ module ts {
}
}
- if (fullTypeCheck && node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) {
+ if (produceDiagnostics && node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) {
checkCollisionWithCapturedSuperVariable(node, (node).name);
checkCollisionWithCapturedThisVariable(node,(node).name);
}
@@ -6950,7 +6937,7 @@ module ts {
}
function checkAssignmentOperator(valueType: Type): void {
- if (fullTypeCheck && operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) {
+ if (produceDiagnostics && operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) {
// TypeScript 1.0 spec (April 2014): 4.17
// An assignment of the form
// VarExpr = ValueExpr
@@ -7162,7 +7149,7 @@ module ts {
}
checkSourceElement(node.constraint);
- if (fullTypeCheck) {
+ if (produceDiagnostics) {
checkTypeParameterHasIllegalReferencesInConstraint(node);
checkTypeNameIsReserved(node.name, Diagnostics.Type_parameter_name_cannot_be_0);
}
@@ -7212,7 +7199,7 @@ module ts {
if (node.type) {
checkSourceElement(node.type);
}
- if (fullTypeCheck) {
+ if (produceDiagnostics) {
checkCollisionWithArgumentsInGeneratedCode(node);
if (compilerOptions.noImplicitAny && !node.type) {
switch (node.kind) {
@@ -7307,7 +7294,7 @@ module ts {
return;
}
- if (!fullTypeCheck) {
+ if (!produceDiagnostics) {
return;
}
@@ -7375,10 +7362,10 @@ module ts {
}
function checkAccessorDeclaration(node: AccessorDeclaration) {
- // Grammar checking accessors
- checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) || checkGrammarFunctionLikeDeclaration(node) || checkGrammarAccessor(node) || checkGrammarComputedPropertyName(node.name);
+ if (produceDiagnostics) {
+ // Grammar checking accessors
+ checkGrammarFunctionLikeDeclaration(node) || checkGrammarAccessor(node) || checkGrammarComputedPropertyName(node.name);
- if (fullTypeCheck) {
if (node.kind === SyntaxKind.GetAccessor) {
if (!isInAmbientContext(node) && nodeIsPresent(node.body) && !(bodyContainsAReturnStatement(node.body) || bodyContainsSingleThrowStatement(node.body))) {
error(node.name, Diagnostics.A_get_accessor_must_return_a_value_or_consist_of_a_single_throw_statement);
@@ -7424,7 +7411,7 @@ module ts {
for (var i = 0; i < len; i++) {
checkSourceElement(node.typeArguments[i]);
var constraint = getConstraintOfTypeParameter((type).target.typeParameters[i]);
- if (fullTypeCheck && constraint) {
+ if (produceDiagnostics && constraint) {
var typeArgument = (type).typeArguments[i];
checkTypeAssignableTo(typeArgument, constraint, node, Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
}
@@ -7438,7 +7425,7 @@ module ts {
function checkTypeLiteral(node: TypeLiteralNode) {
forEach(node.members, checkSourceElement);
- if (fullTypeCheck) {
+ if (produceDiagnostics) {
var type = getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
checkIndexConstraints(type);
checkTypeForDuplicateIndexSignatures(node);
@@ -7468,7 +7455,7 @@ module ts {
}
function checkSpecializedSignatureDeclaration(signatureDeclarationNode: SignatureDeclaration): void {
- if (!fullTypeCheck) {
+ if (!produceDiagnostics) {
return;
}
var signature = getSignatureFromDeclaration(signatureDeclarationNode);
@@ -7524,7 +7511,7 @@ module ts {
}
function checkFunctionOrConstructorSymbol(symbol: Symbol): void {
- if (!fullTypeCheck) {
+ if (!produceDiagnostics) {
return;
}
@@ -7734,7 +7721,7 @@ module ts {
}
function checkExportsOnMergedDeclarations(node: Node): void {
- if (!fullTypeCheck) {
+ if (!produceDiagnostics) {
return;
}
@@ -7808,13 +7795,12 @@ module ts {
}
function checkFunctionDeclaration(node: FunctionDeclaration): void {
- // Grammar Checking, check signature of function declaration as checkFunctionLikeDeclaration call checkGarmmarFunctionLikeDeclaration
- checkFunctionLikeDeclaration(node);
+ if (produceDiagnostics) {
+ checkFunctionLikeDeclaration(node) ||
+ checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) ||
+ checkGrammarFunctionName(node.name) ||
+ checkGrammarForGenerator(node);
- //Grammar check other component of the functionDeclaration
- checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) || checkGrammarFunctionName(node.name) || checkGrammarForGenerator(node);
-
- if (fullTypeCheck) {
checkCollisionWithCapturedSuperVariable(node, node.name);
checkCollisionWithCapturedThisVariable(node, node.name);
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
@@ -8326,7 +8312,7 @@ module ts {
}
}
- if (fullTypeCheck && clause.kind === SyntaxKind.CaseClause) {
+ if (produceDiagnostics && clause.kind === SyntaxKind.CaseClause) {
var caseClause = clause;
// TypeScript 1.0 spec (April 2014):5.9
// In a 'switch' statement, each 'case' expression must be of a type that is assignable to or from the type of the 'switch' expression.
@@ -8486,7 +8472,7 @@ module ts {
var node = typeParameterDeclarations[i];
checkTypeParameter(node);
- if (fullTypeCheck) {
+ if (produceDiagnostics) {
for (var j = 0; j < i; j++) {
if (typeParameterDeclarations[j].symbol === node.symbol) {
error(node.name, Diagnostics.Duplicate_identifier_0, declarationNameToString(node.name));
@@ -8515,7 +8501,7 @@ module ts {
checkTypeReference(baseTypeNode);
}
if (type.baseTypes.length) {
- if (fullTypeCheck) {
+ if (produceDiagnostics) {
var baseType = type.baseTypes[0];
checkTypeAssignableTo(type, baseType, node.name, Diagnostics.Class_0_incorrectly_extends_base_class_1);
var staticBaseType = getTypeOfSymbol(baseType.symbol);
@@ -8536,7 +8522,7 @@ module ts {
if (implementedTypeNodes) {
forEach(implementedTypeNodes, typeRefNode => {
checkTypeReference(typeRefNode);
- if (fullTypeCheck) {
+ if (produceDiagnostics) {
var t = getTypeFromTypeReferenceNode(typeRefNode);
if (t !== unknownType) {
var declaredType = (t.flags & TypeFlags.Reference) ? (t).target : t;
@@ -8552,7 +8538,7 @@ module ts {
}
forEach(node.members, checkSourceElement);
- if (fullTypeCheck) {
+ if (produceDiagnostics) {
checkIndexConstraints(type);
checkTypeForDuplicateIndexSignatures(node);
}
@@ -8694,7 +8680,7 @@ module ts {
var errorInfo = chainDiagnosticMessages(undefined, Diagnostics.Named_properties_0_of_types_1_and_2_are_not_identical, prop.name, typeName1, typeName2);
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Interface_0_cannot_simultaneously_extend_types_1_and_2, typeToString(type), typeName1, typeName2);
- addDiagnostic(createDiagnosticForNodeFromMessageChain(typeNode, errorInfo, program.getCompilerHost().getNewLine()));
+ addDiagnostic(createDiagnosticForNodeFromMessageChain(typeNode, errorInfo, host.getCompilerHost().getNewLine()));
}
}
}
@@ -8708,7 +8694,7 @@ module ts {
checkGrammarModifiers(node) || checkGrammarInterfaceDeclaration(node);
checkTypeParameters(node.typeParameters);
- if (fullTypeCheck) {
+ if (produceDiagnostics) {
checkTypeNameIsReserved(node.name, Diagnostics.Interface_name_cannot_be_0);
checkExportsOnMergedDeclarations(node);
@@ -8735,7 +8721,7 @@ module ts {
forEach(getInterfaceBaseTypeNodes(node), checkTypeReference);
forEach(node.members, checkSourceElement);
- if (fullTypeCheck) {
+ if (produceDiagnostics) {
checkTypeForDuplicateIndexSignatures(node);
}
}
@@ -8907,13 +8893,13 @@ module ts {
}
function checkEnumDeclaration(node: EnumDeclaration) {
- // Grammar checking
- checkGrammarModifiers(node) || checkGrammarEnumDeclaration(node);
-
- if (!fullTypeCheck) {
+ if (!produceDiagnostics) {
return;
}
+ // Grammar checking
+ checkGrammarModifiers(node) || checkGrammarEnumDeclaration(node);
+
checkTypeNameIsReserved(node.name, Diagnostics.Enum_name_cannot_be_0);
checkCollisionWithCapturedThisVariable(node, node.name);
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
@@ -8977,28 +8963,28 @@ module ts {
}
function checkModuleDeclaration(node: ModuleDeclaration) {
- // Grammar checking
- if (!checkGrammarModifiers(node)) {
- if (!isInAmbientContext(node) && node.name.kind === SyntaxKind.StringLiteral) {
- grammarErrorOnNode(node.name, Diagnostics.Only_ambient_modules_can_use_quoted_names);
- }
- else if (node.name.kind === SyntaxKind.Identifier && node.body.kind === SyntaxKind.ModuleBlock) {
- var statements = (node.body).statements;
- for (var i = 0, n = statements.length; i < n; i++) {
- var statement = statements[i];
+ if (produceDiagnostics) {
+ // Grammar checking
+ if (!checkGrammarModifiers(node)) {
+ if (!isInAmbientContext(node) && node.name.kind === SyntaxKind.StringLiteral) {
+ grammarErrorOnNode(node.name, Diagnostics.Only_ambient_modules_can_use_quoted_names);
+ }
+ else if (node.name.kind === SyntaxKind.Identifier && node.body.kind === SyntaxKind.ModuleBlock) {
+ var statements = (node.body).statements;
+ for (var i = 0, n = statements.length; i < n; i++) {
+ var statement = statements[i];
- if (statement.kind === SyntaxKind.ExportAssignment) {
- // Export assignments are not allowed in an internal module
- grammarErrorOnNode(statement, Diagnostics.An_export_assignment_cannot_be_used_in_an_internal_module);
- }
- else if (isExternalModuleImportDeclaration(statement)) {
- grammarErrorOnNode(getExternalModuleImportDeclarationExpression(statement), Diagnostics.Import_declarations_in_an_internal_module_cannot_reference_an_external_module);
+ if (statement.kind === SyntaxKind.ExportAssignment) {
+ // Export assignments are not allowed in an internal module
+ grammarErrorOnNode(statement, Diagnostics.An_export_assignment_cannot_be_used_in_an_internal_module);
+ }
+ else if (isExternalModuleImportDeclaration(statement)) {
+ grammarErrorOnNode(getExternalModuleImportDeclarationExpression(statement), Diagnostics.Import_declarations_in_an_internal_module_cannot_reference_an_external_module);
+ }
}
}
}
- }
- if (fullTypeCheck) {
checkCollisionWithCapturedThisVariable(node, node.name);
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
checkExportsOnMergedDeclarations(node);
@@ -9338,7 +9324,7 @@ module ts {
}
function getSortedDiagnostics(): Diagnostic[]{
- Debug.assert(fullTypeCheck, "diagnostics are available only in the full typecheck mode");
+ Debug.assert(produceDiagnostics, "diagnostics are available only in the full typecheck mode");
if (diagnosticsModified) {
diagnostics.sort(compareDiagnostics);
@@ -9348,23 +9334,25 @@ module ts {
return diagnostics;
}
- function getDiagnostics(sourceFile?: SourceFile): Diagnostic[]{
+ function getDiagnostics(sourceFile?: SourceFile): Diagnostic[] {
+ throwIfNonDiagnosticsProducing();
if (sourceFile) {
checkSourceFile(sourceFile);
return filter(getSortedDiagnostics(), d => d.file === sourceFile);
}
- forEach(program.getSourceFiles(), checkSourceFile);
+ forEach(host.getSourceFiles(), checkSourceFile);
return getSortedDiagnostics();
}
- function getDeclarationDiagnostics(targetSourceFile: SourceFile): Diagnostic[] {
- var resolver = createResolver();
- checkSourceFile(targetSourceFile);
- return ts.getDeclarationDiagnostics(program, resolver, targetSourceFile);
+ function getGlobalDiagnostics(): Diagnostic[]{
+ throwIfNonDiagnosticsProducing();
+ return filter(getSortedDiagnostics(), d => !d.file);
}
- function getGlobalDiagnostics(): Diagnostic[] {
- return filter(getSortedDiagnostics(), d => !d.file);
+ function throwIfNonDiagnosticsProducing() {
+ if (!produceDiagnostics) {
+ throw new Error("Trying to get diagnostics from a type checker that does not produce them.");
+ }
}
// Language service support
@@ -9869,16 +9857,6 @@ module ts {
return getDiagnostics(sourceFile).length > 0 || getGlobalDiagnostics().length > 0;
}
- function isEmitBlocked(sourceFile?: SourceFile): boolean {
- return program.getDiagnostics(sourceFile).length !== 0 ||
- hasEarlyErrors(sourceFile) ||
- (compilerOptions.noEmitOnError && getDiagnostics(sourceFile).length !== 0);
- }
-
- function hasEarlyErrors(sourceFile?: SourceFile): boolean {
- return forEach(getDiagnostics(sourceFile), d => d.isEarly);
- }
-
function isImportResolvedToValue(symbol: Symbol): boolean {
var target = resolveImport(symbol);
// const enums and modules that contain only const enums are not considered values from the emit perespective
@@ -9966,7 +9944,6 @@ module ts {
function createResolver(): EmitResolver {
return {
- getProgram: () => program,
getLocalNameOfContainer,
getExpressionNamePrefix,
getExportAssignmentName,
@@ -9975,7 +9952,6 @@ module ts {
getEnumMemberValue,
isTopLevelValueImportWithEntityName,
hasSemanticErrors,
- isEmitBlocked,
isDeclarationVisible,
isImplementationOfOverload,
writeTypeOfDeclaration,
@@ -9987,19 +9963,14 @@ module ts {
};
}
- function invokeEmitter(targetSourceFile?: SourceFile) {
- var resolver = createResolver();
- return emitFiles(resolver, targetSourceFile);
- }
-
function initializeTypeChecker() {
// Bind all source files and propagate errors
- forEach(program.getSourceFiles(), file => {
+ forEach(host.getSourceFiles(), file => {
bindSourceFile(file);
forEach(file.semanticDiagnostics, addDiagnostic);
});
// Initialize global symbol table
- forEach(program.getSourceFiles(), file => {
+ forEach(host.getSourceFiles(), file => {
if (!isExternalModule(file)) {
extendSymbolTable(globals, file.locals);
}
diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts
index b713fddf676..237f3ab509a 100644
--- a/src/compiler/emitter.ts
+++ b/src/compiler/emitter.ts
@@ -1,8 +1,4 @@
-///
-///
-///
-///
-///
+///
module ts {
interface EmitTextWriter {
@@ -316,17 +312,16 @@ module ts {
};
}
- function getSourceFilePathInNewDir(sourceFile: SourceFile, program: Program, newDirPath: string) {
- var compilerHost = program.getCompilerHost();
- var sourceFilePath = getNormalizedAbsolutePath(sourceFile.filename, compilerHost.getCurrentDirectory());
- sourceFilePath = sourceFilePath.replace(program.getCommonSourceDirectory(), "");
+ function getSourceFilePathInNewDir(sourceFile: SourceFile, host: EmitHost, newDirPath: string) {
+ var sourceFilePath = getNormalizedAbsolutePath(sourceFile.filename, host.getCurrentDirectory());
+ 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);
@@ -335,16 +330,15 @@ module ts {
return emitOutputFilePathWithoutExtension + extension;
}
- function writeFile(compilerHost: CompilerHost, diagnostics: Diagnostic[], filename: string, data: string, writeByteOrderMark: boolean) {
- compilerHost.writeFile(filename, data, writeByteOrderMark, hostErrorMessage => {
+ function writeFile(host: EmitHost, diagnostics: Diagnostic[], filename: string, data: string, writeByteOrderMark: boolean) {
+ host.writeFile(filename, data, writeByteOrderMark, hostErrorMessage => {
diagnostics.push(createCompilerDiagnostic(Diagnostics.Could_not_write_file_0_Colon_1, filename, hostErrorMessage));
});
}
- 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.getNewLine();
+ var compilerOptions = host.getCompilerOptions();
var write: (s: string) => void;
var writeLine: () => void;
@@ -1400,14 +1394,14 @@ 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)),
declFileName,
- compilerHost.getCurrentDirectory(),
- compilerHost.getCanonicalFileName,
+ host.getCurrentDirectory(),
+ host.getCanonicalFileName,
/*isAbsolutePathAnUrl*/ false);
referencePathsOutput += "/// " + newLine;
@@ -1418,7 +1412,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
@@ -1438,12 +1432,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) &&
@@ -1468,21 +1462,31 @@ module ts {
}
}
- export function getDeclarationDiagnostics(program: Program, resolver: EmitResolver, targetSourceFile: SourceFile): Diagnostic[] {
+ export interface EmitHost extends ScriptReferenceHost {
+ getSourceFiles(): SourceFile[];
+ isEmitBlocked(sourceFile?: SourceFile): boolean;
+
+ getCommonSourceDirectory(): string;
+ getCanonicalFileName(fileName: string): string;
+ getNewLine(): string;
+
+ writeFile(filename: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void): void;
+ }
+
+ export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, targetSourceFile: SourceFile): Diagnostic[] {
var diagnostics: Diagnostic[] = [];
- var jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, program, ".js");
- emitDeclarations(program, resolver, diagnostics, jsFilePath, targetSourceFile);
+ var jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, host, ".js");
+ emitDeclarations(host, resolver, diagnostics, jsFilePath, targetSourceFile);
return diagnostics;
}
// 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 compilerOptions = host.getCompilerOptions();
var sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap ? [] : undefined;
var diagnostics: Diagnostic[] = [];
- var newLine = program.getCompilerHost().getNewLine();
+ var newLine = host.getNewLine();
function emitJavaScript(jsFilePath: string, root?: SourceFile) {
var writer = createTextWriter(newLine);
@@ -1704,12 +1708,12 @@ 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,
- compilerHost.getCurrentDirectory(),
- compilerHost.getCanonicalFileName,
+ host.getCurrentDirectory(),
+ host.getCanonicalFileName,
/*isAbsolutePathAnUrl*/ true));
sourceMapSourceIndex = sourceMapData.sourceMapSources.length - 1;
@@ -1805,7 +1809,7 @@ module ts {
function writeJavaScriptAndSourceMapFile(emitOutput: string, writeByteOrderMark: boolean) {
// Write source map file
encodeLastRecordedSourceMapSpan();
- writeFile(compilerHost, diagnostics, sourceMapData.sourceMapFilePath, serializeSourceMapContents(
+ writeFile(host, diagnostics, sourceMapData.sourceMapFilePath, serializeSourceMapContents(
3,
sourceMapData.sourceMapFile,
sourceMapData.sourceMapSourceRoot,
@@ -1844,17 +1848,17 @@ 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
- compilerHost.getCurrentDirectory(),
- compilerHost.getCanonicalFileName,
+ host.getCurrentDirectory(),
+ host.getCanonicalFileName,
/*isAbsolutePathAnUrl*/ true);
}
else {
@@ -1890,7 +1894,7 @@ module ts {
}
function writeJavaScriptFile(emitOutput: string, writeByteOrderMark: boolean) {
- writeFile(compilerHost, diagnostics, jsFilePath, emitOutput, writeByteOrderMark);
+ writeFile(host, diagnostics, jsFilePath, emitOutput, writeByteOrderMark);
}
// Create a temporary variable with a unique unused name. The forLoopVariable parameter signals that the
@@ -4215,7 +4219,7 @@ module ts {
emit(root);
}
else {
- forEach(program.getSourceFiles(), sourceFile => {
+ forEach(host.getSourceFiles(), sourceFile => {
if (!isExternalModuleOrDeclarationFile(sourceFile)) {
emit(sourceFile);
}
@@ -4227,7 +4231,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) {
@@ -4242,7 +4246,7 @@ module ts {
}
});
declarationOutput += emitDeclarationResult.synchronousDeclarationOutput.substring(appliedSyncOutputPos);
- writeFile(compilerHost, diagnostics, removeFileExtension(jsFilePath) + ".d.ts", declarationOutput, compilerOptions.emitBOM);
+ writeFile(host, diagnostics, removeFileExtension(jsFilePath) + ".d.ts", declarationOutput, compilerOptions.emitBOM);
}
}
@@ -4252,11 +4256,11 @@ module ts {
if (targetSourceFile === undefined) {
// No targetSourceFile is specified (e.g. calling emitter from batch compiler)
hasSemanticErrors = resolver.hasSemanticErrors();
- isEmitBlocked = resolver.isEmitBlocked();
+ isEmitBlocked = host.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);
}
});
@@ -4270,18 +4274,18 @@ module ts {
if (shouldEmitToOwnFile(targetSourceFile, compilerOptions)) {
// If shouldEmitToOwnFile returns true or targetSourceFile is an external module file, then emit targetSourceFile in its own output file
hasSemanticErrors = resolver.hasSemanticErrors(targetSourceFile);
- isEmitBlocked = resolver.isEmitBlocked(targetSourceFile);
+ isEmitBlocked = host.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);
+ isEmitBlocked = isEmitBlocked || host.isEmitBlocked(sourceFile);
}
});
diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts
index 94817f770d7..b9b08087692 100644
--- a/src/compiler/parser.ts
+++ b/src/compiler/parser.ts
@@ -1,5 +1,3 @@
-///
-///
///
///
@@ -261,79 +259,6 @@ module ts {
}
}
- // TODO (drosen, mhegazy): Move to a more appropriate file.
- export function createCompilerHost(options: CompilerOptions): CompilerHost {
- var currentDirectory: string;
- var existingDirectories: Map = {};
-
- function getCanonicalFileName(fileName: string): string {
- // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
- // otherwise use toLowerCase as a canonical form.
- return sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
- }
-
- // returned by CScript sys environment
- var unsupportedFileEncodingErrorCode = -2147024809;
-
- function getSourceFile(filename: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile {
- try {
- var text = sys.readFile(filename, options.charset);
- }
- catch (e) {
- if (onError) {
- onError(e.number === unsupportedFileEncodingErrorCode ?
- createCompilerDiagnostic(Diagnostics.Unsupported_file_encoding).messageText :
- e.message);
- }
- text = "";
- }
-
- return text !== undefined ? createSourceFile(filename, text, languageVersion) : undefined;
- }
-
- function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
- function directoryExists(directoryPath: string): boolean {
- if (hasProperty(existingDirectories, directoryPath)) {
- return true;
- }
- if (sys.directoryExists(directoryPath)) {
- existingDirectories[directoryPath] = true;
- return true;
- }
- return false;
- }
-
- function ensureDirectoriesExist(directoryPath: string) {
- if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
- var parentDirectory = getDirectoryPath(directoryPath);
- ensureDirectoriesExist(parentDirectory);
- sys.createDirectory(directoryPath);
- }
- }
-
- try {
- ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
- sys.writeFile(fileName, data, writeByteOrderMark);
- }
- catch (e) {
- if (onError) {
- onError(e.message);
- }
- }
- }
-
- return {
- getSourceFile,
- getDefaultLibFilename: options => combinePaths(getDirectoryPath(normalizePath(sys.getExecutingFilePath())), options.target === ScriptTarget.ES6 ? "lib.es6.d.ts" : "lib.d.ts"),
- writeFile,
- getCurrentDirectory: () => currentDirectory || (currentDirectory = sys.getCurrentDirectory()),
- useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames,
- getCanonicalFileName,
- getNewLine: () => sys.newLine
- };
- }
-
-
const enum ParsingContext {
SourceElements, // Elements in source file
ModuleElements, // Elements in module declaration
@@ -4852,290 +4777,4 @@ module ts {
export function isAssignmentOperator(token: SyntaxKind): boolean {
return token >= SyntaxKind.FirstAssignment && token <= SyntaxKind.LastAssignment;
}
-
- export function createProgram(rootNames: string[], options: CompilerOptions, host: CompilerHost): Program {
- var program: Program;
- var files: SourceFile[] = [];
- var filesByName: Map = {};
- var errors: Diagnostic[] = [];
- var seenNoDefaultLib = options.noLib;
- var commonSourceDirectory: string;
-
- forEach(rootNames, name => processRootFile(name, false));
- if (!seenNoDefaultLib) {
- processRootFile(host.getDefaultLibFilename(options), true);
- }
- verifyCompilerOptions();
- errors.sort(compareDiagnostics);
- program = {
- getSourceFile: getSourceFile,
- getSourceFiles: () => files,
- getCompilerOptions: () => options,
- getCompilerHost: () => host,
- getDiagnostics: getDiagnostics,
- getGlobalDiagnostics: getGlobalDiagnostics,
- getTypeChecker: fullTypeCheckMode => createTypeChecker(program, fullTypeCheckMode),
- getCommonSourceDirectory: () => commonSourceDirectory,
- };
- return program;
-
- function getSourceFile(filename: string) {
- filename = host.getCanonicalFileName(filename);
- return hasProperty(filesByName, filename) ? filesByName[filename] : undefined;
- }
-
- function getDiagnostics(sourceFile?: SourceFile): Diagnostic[] {
- return sourceFile ? filter(errors, e => e.file === sourceFile) : errors;
- }
-
- function getGlobalDiagnostics(): Diagnostic[] {
- return filter(errors, e => !e.file);
- }
-
- function hasExtension(filename: string): boolean {
- return getBaseFilename(filename).indexOf(".") >= 0;
- }
-
- function processRootFile(filename: string, isDefaultLib: boolean) {
- processSourceFile(normalizePath(filename), isDefaultLib);
- }
-
- function processSourceFile(filename: string, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number) {
- if (refEnd !== undefined && refPos !== undefined) {
- var start = refPos;
- var length = refEnd - refPos;
- }
- var diagnostic: DiagnosticMessage;
- if (hasExtension(filename)) {
- if (!options.allowNonTsExtensions && !fileExtensionIs(filename, ".ts")) {
- diagnostic = Diagnostics.File_0_must_have_extension_ts_or_d_ts;
- }
- else if (!findSourceFile(filename, isDefaultLib, refFile, refPos, refEnd)) {
- diagnostic = Diagnostics.File_0_not_found;
- }
- else if (refFile && host.getCanonicalFileName(filename) === host.getCanonicalFileName(refFile.filename)) {
- diagnostic = Diagnostics.A_file_cannot_have_a_reference_to_itself;
- }
- }
- else {
- if (!(findSourceFile(filename + ".ts", isDefaultLib, refFile, refPos, refEnd) || findSourceFile(filename + ".d.ts", isDefaultLib, refFile, refPos, refEnd))) {
- diagnostic = Diagnostics.File_0_not_found;
- filename += ".ts";
- }
- }
-
- if (diagnostic) {
- if (refFile) {
- errors.push(createFileDiagnostic(refFile, start, length, diagnostic, filename));
- }
- else {
- errors.push(createCompilerDiagnostic(diagnostic, filename));
- }
- }
- }
-
- // Get source file from normalized filename
- function findSourceFile(filename: string, isDefaultLib: boolean, refFile?: SourceFile, refStart?: number, refLength?: number): SourceFile {
- var canonicalName = host.getCanonicalFileName(filename);
- if (hasProperty(filesByName, canonicalName)) {
- // We've already looked for this file, use cached result
- return getSourceFileFromCache(filename, canonicalName, /*useAbsolutePath*/ false);
- }
- else {
- var normalizedAbsolutePath = getNormalizedAbsolutePath(filename, host.getCurrentDirectory());
- var canonicalAbsolutePath = host.getCanonicalFileName(normalizedAbsolutePath);
- if (hasProperty(filesByName, canonicalAbsolutePath)) {
- return getSourceFileFromCache(normalizedAbsolutePath, canonicalAbsolutePath, /*useAbsolutePath*/ true);
- }
-
- // We haven't looked for this file, do so now and cache result
- var file = filesByName[canonicalName] = host.getSourceFile(filename, options.target, hostErrorMessage => {
- if (refFile) {
- errors.push(createFileDiagnostic(refFile, refStart, refLength,
- Diagnostics.Cannot_read_file_0_Colon_1, filename, hostErrorMessage));
- }
- else {
- errors.push(createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, filename, hostErrorMessage));
- }
- });
- if (file) {
- seenNoDefaultLib = seenNoDefaultLib || file.hasNoDefaultLib;
-
- // Set the source file for normalized absolute path
- filesByName[canonicalAbsolutePath] = file;
-
- if (!options.noResolve) {
- var basePath = getDirectoryPath(filename);
- processReferencedFiles(file, basePath);
- processImportedModules(file, basePath);
- }
- if (isDefaultLib) {
- files.unshift(file);
- }
- else {
- files.push(file);
- }
- forEach(file.getSyntacticDiagnostics(), e => {
- errors.push(e);
- });
- }
- }
- return file;
-
- function getSourceFileFromCache(filename: string, canonicalName: string, useAbsolutePath: boolean): SourceFile {
- var file = filesByName[canonicalName];
- if (file && host.useCaseSensitiveFileNames()) {
- var sourceFileName = useAbsolutePath ? getNormalizedAbsolutePath(file.filename, host.getCurrentDirectory()) : file.filename;
- if (canonicalName !== sourceFileName) {
- errors.push(createFileDiagnostic(refFile, refStart, refLength,
- Diagnostics.Filename_0_differs_from_already_included_filename_1_only_in_casing, filename, sourceFileName));
- }
- }
- return file;
- }
- }
-
- function processReferencedFiles(file: SourceFile, basePath: string) {
- forEach(file.referencedFiles, ref => {
- var referencedFilename = isRootedDiskPath(ref.filename) ? ref.filename : combinePaths(basePath, ref.filename);
- processSourceFile(normalizePath(referencedFilename), /* isDefaultLib */ false, file, ref.pos, ref.end);
- });
- }
-
- function processImportedModules(file: SourceFile, basePath: string) {
- forEach(file.statements, node => {
- if (isExternalModuleImportDeclaration(node) &&
- getExternalModuleImportDeclarationExpression(node).kind === SyntaxKind.StringLiteral) {
-
- var nameLiteral = getExternalModuleImportDeclarationExpression(node);
- var moduleName = nameLiteral.text;
- if (moduleName) {
- var searchPath = basePath;
- while (true) {
- var searchName = normalizePath(combinePaths(searchPath, moduleName));
- if (findModuleSourceFile(searchName + ".ts", nameLiteral) || findModuleSourceFile(searchName + ".d.ts", nameLiteral)) {
- break;
- }
-
- var parentPath = getDirectoryPath(searchPath);
- if (parentPath === searchPath) {
- break;
- }
- searchPath = parentPath;
- }
- }
- }
- else if (node.kind === SyntaxKind.ModuleDeclaration && (node).name.kind === SyntaxKind.StringLiteral && (node.flags & NodeFlags.Ambient || isDeclarationFile(file))) {
- // TypeScript 1.0 spec (April 2014): 12.1.6
- // An AmbientExternalModuleDeclaration declares an external module.
- // This type of declaration is permitted only in the global module.
- // The StringLiteral must specify a top - level external module name.
- // Relative external module names are not permitted
- forEachChild((node).body, node => {
- if (isExternalModuleImportDeclaration(node) &&
- getExternalModuleImportDeclarationExpression(node).kind === SyntaxKind.StringLiteral) {
-
- var nameLiteral = getExternalModuleImportDeclarationExpression(node);
- var moduleName = nameLiteral.text;
- if (moduleName) {
- // TypeScript 1.0 spec (April 2014): 12.1.6
- // An ExternalImportDeclaration in anAmbientExternalModuleDeclaration may reference other external modules
- // only through top - level external module names. Relative external module names are not permitted.
- var searchName = normalizePath(combinePaths(basePath, moduleName));
- var tsFile = findModuleSourceFile(searchName + ".ts", nameLiteral);
- if (!tsFile) {
- findModuleSourceFile(searchName + ".d.ts", nameLiteral);
- }
- }
- }
- });
- }
- });
-
- function findModuleSourceFile(filename: string, nameLiteral: LiteralExpression) {
- return findSourceFile(filename, /* isDefaultLib */ false, file, nameLiteral.pos, nameLiteral.end - nameLiteral.pos);
- }
- }
-
- function verifyCompilerOptions() {
- if (!options.sourceMap && (options.mapRoot || options.sourceRoot)) {
- // Error to specify --mapRoot or --sourceRoot without mapSourceFiles
- if (options.mapRoot) {
- errors.push(createCompilerDiagnostic(Diagnostics.Option_mapRoot_cannot_be_specified_without_specifying_sourcemap_option));
- }
- if (options.sourceRoot) {
- errors.push(createCompilerDiagnostic(Diagnostics.Option_sourceRoot_cannot_be_specified_without_specifying_sourcemap_option));
- }
- return;
- }
-
- var firstExternalModule = forEach(files, f => isExternalModule(f) ? f : undefined);
- if (firstExternalModule && options.module === ModuleKind.None) {
- // We cannot use createDiagnosticFromNode because nodes do not have parents yet
- var externalModuleErrorSpan = getErrorSpanForNode(firstExternalModule.externalModuleIndicator);
- var errorStart = skipTrivia(firstExternalModule.text, externalModuleErrorSpan.pos);
- var errorLength = externalModuleErrorSpan.end - errorStart;
- errors.push(createFileDiagnostic(firstExternalModule, errorStart, errorLength, Diagnostics.Cannot_compile_external_modules_unless_the_module_flag_is_provided));
- }
-
- // there has to be common source directory if user specified --outdir || --sourcRoot
- // if user specified --mapRoot, there needs to be common source directory if there would be multiple files being emitted
- if (options.outDir || // there is --outDir specified
- options.sourceRoot || // there is --sourceRoot specified
- (options.mapRoot && // there is --mapRoot Specified and there would be multiple js files generated
- (!options.out || firstExternalModule !== undefined))) {
-
- var commonPathComponents: string[];
- forEach(files, sourceFile => {
- // Each file contributes into common source file path
- if (!(sourceFile.flags & NodeFlags.DeclarationFile)
- && !fileExtensionIs(sourceFile.filename, ".js")) {
- var sourcePathComponents = getNormalizedPathComponents(sourceFile.filename, host.getCurrentDirectory());
- sourcePathComponents.pop(); // FileName is not part of directory
- if (commonPathComponents) {
- for (var i = 0; i < Math.min(commonPathComponents.length, sourcePathComponents.length); i++) {
- if (commonPathComponents[i] !== sourcePathComponents[i]) {
- if (i === 0) {
- errors.push(createCompilerDiagnostic(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files));
- return;
- }
-
- // New common path found that is 0 -> i-1
- commonPathComponents.length = i;
- break;
- }
- }
-
- // If the fileComponent path completely matched and less than already found update the length
- if (sourcePathComponents.length < commonPathComponents.length) {
- commonPathComponents.length = sourcePathComponents.length;
- }
- }
- else {
- // first file
- commonPathComponents = sourcePathComponents;
- }
- }
- });
-
- commonSourceDirectory = getNormalizedPathFromPathComponents(commonPathComponents);
- if (commonSourceDirectory) {
- // Make sure directory path ends with directory separator so this string can directly
- // used to replace with "" to get the relative path of the source file and the relative path doesn't
- // start with / making it rooted path
- commonSourceDirectory += directorySeparator;
- }
- }
-
- if (options.noEmit) {
- if (options.out || options.outDir) {
- errors.push(createCompilerDiagnostic(Diagnostics.Option_noEmit_cannot_be_specified_with_option_out_or_outDir));
- }
-
- if (options.declaration) {
- errors.push(createCompilerDiagnostic(Diagnostics.Option_noEmit_cannot_be_specified_with_option_declaration));
- }
- }
- }
- }
}
diff --git a/src/compiler/program.ts b/src/compiler/program.ts
new file mode 100644
index 00000000000..b506a86786b
--- /dev/null
+++ b/src/compiler/program.ts
@@ -0,0 +1,408 @@
+///
+///
+
+module ts {
+ export function createCompilerHost(options: CompilerOptions): CompilerHost {
+ var currentDirectory: string;
+ var existingDirectories: Map = {};
+
+ function getCanonicalFileName(fileName: string): string {
+ // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
+ // otherwise use toLowerCase as a canonical form.
+ return sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
+ }
+
+ // returned by CScript sys environment
+ var unsupportedFileEncodingErrorCode = -2147024809;
+
+ function getSourceFile(filename: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile {
+ try {
+ var text = sys.readFile(filename, options.charset);
+ }
+ catch (e) {
+ if (onError) {
+ onError(e.number === unsupportedFileEncodingErrorCode ?
+ createCompilerDiagnostic(Diagnostics.Unsupported_file_encoding).messageText :
+ e.message);
+ }
+ text = "";
+ }
+
+ return text !== undefined ? createSourceFile(filename, text, languageVersion) : undefined;
+ }
+
+ function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
+ function directoryExists(directoryPath: string): boolean {
+ if (hasProperty(existingDirectories, directoryPath)) {
+ return true;
+ }
+ if (sys.directoryExists(directoryPath)) {
+ existingDirectories[directoryPath] = true;
+ return true;
+ }
+ return false;
+ }
+
+ function ensureDirectoriesExist(directoryPath: string) {
+ if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
+ var parentDirectory = getDirectoryPath(directoryPath);
+ ensureDirectoriesExist(parentDirectory);
+ sys.createDirectory(directoryPath);
+ }
+ }
+
+ try {
+ ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
+ sys.writeFile(fileName, data, writeByteOrderMark);
+ }
+ catch (e) {
+ if (onError) {
+ onError(e.message);
+ }
+ }
+ }
+
+ return {
+ getSourceFile,
+ getDefaultLibFilename: options => combinePaths(getDirectoryPath(normalizePath(sys.getExecutingFilePath())), options.target === ScriptTarget.ES6 ? "lib.es6.d.ts" : "lib.d.ts"),
+ writeFile,
+ getCurrentDirectory: () => currentDirectory || (currentDirectory = sys.getCurrentDirectory()),
+ useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames,
+ getCanonicalFileName,
+ getNewLine: () => sys.newLine
+ };
+ }
+
+ export function createProgram(rootNames: string[], options: CompilerOptions, host: CompilerHost): Program {
+ var program: Program;
+ var files: SourceFile[] = [];
+ var filesByName: Map = {};
+ var errors: Diagnostic[] = [];
+ var seenNoDefaultLib = options.noLib;
+ var commonSourceDirectory: string;
+
+ forEach(rootNames, name => processRootFile(name, false));
+ if (!seenNoDefaultLib) {
+ processRootFile(host.getDefaultLibFilename(options), true);
+ }
+ verifyCompilerOptions();
+ errors.sort(compareDiagnostics);
+
+
+ var diagnosticsProducingTypeChecker: TypeChecker;
+ var noDiagnosticsTypeChecker: TypeChecker;
+ var emitHost: EmitHost;
+
+ program = {
+ getSourceFile: getSourceFile,
+ getSourceFiles: () => files,
+ getCompilerOptions: () => options,
+ getCompilerHost: () => host,
+ getDiagnostics: getDiagnostics,
+ getGlobalDiagnostics: getGlobalDiagnostics,
+ getDeclarationDiagnostics: getDeclarationDiagnostics,
+ getTypeChecker,
+ getCommonSourceDirectory: () => commonSourceDirectory,
+ emitFiles: invokeEmitter,
+ isEmitBlocked,
+ getCurrentDirectory: host.getCurrentDirectory,
+ };
+ return program;
+
+ function getEmitHost() {
+ return emitHost || (emitHost = createEmitHostFromProgram(program));
+ }
+
+ function hasEarlyErrors(sourceFile?: SourceFile): boolean {
+ return forEach(getDiagnosticsProducingTypeChecker().getDiagnostics(sourceFile), d => d.isEarly);
+ }
+
+ function isEmitBlocked(sourceFile?: SourceFile): boolean {
+ return getDiagnostics(sourceFile).length !== 0 ||
+ hasEarlyErrors(sourceFile) ||
+ (options.noEmitOnError && getDiagnosticsProducingTypeChecker().getDiagnostics(sourceFile).length !== 0);
+ }
+
+ function getDiagnosticsProducingTypeChecker() {
+ return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ true));
+ }
+
+ function getTypeChecker(produceDiagnostics: boolean) {
+ if (produceDiagnostics) {
+ return getDiagnosticsProducingTypeChecker();
+ }
+ else {
+ return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, produceDiagnostics));
+ }
+ }
+
+ function getDeclarationDiagnostics(targetSourceFile: SourceFile): Diagnostic[]{
+ var typeChecker = getDiagnosticsProducingTypeChecker();
+ typeChecker.getDiagnostics(targetSourceFile);
+ var resolver = typeChecker.getEmitResolver();
+ return ts.getDeclarationDiagnostics(getEmitHost(), resolver, targetSourceFile);
+ }
+
+ function invokeEmitter(targetSourceFile?: SourceFile) {
+ var resolver = getDiagnosticsProducingTypeChecker().getEmitResolver();
+ return emitFiles(resolver, getEmitHost(), targetSourceFile);
+ } function getSourceFile(filename: string) {
+ filename = host.getCanonicalFileName(filename);
+ return hasProperty(filesByName, filename) ? filesByName[filename] : undefined;
+ }
+
+ function getDiagnostics(sourceFile?: SourceFile): Diagnostic[] {
+ return sourceFile ? filter(errors, e => e.file === sourceFile) : errors;
+ }
+
+ function getGlobalDiagnostics(): Diagnostic[] {
+ return filter(errors, e => !e.file);
+ }
+
+ function hasExtension(filename: string): boolean {
+ return getBaseFilename(filename).indexOf(".") >= 0;
+ }
+
+ function processRootFile(filename: string, isDefaultLib: boolean) {
+ processSourceFile(normalizePath(filename), isDefaultLib);
+ }
+
+ function processSourceFile(filename: string, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number) {
+ if (refEnd !== undefined && refPos !== undefined) {
+ var start = refPos;
+ var length = refEnd - refPos;
+ }
+ var diagnostic: DiagnosticMessage;
+ if (hasExtension(filename)) {
+ if (!options.allowNonTsExtensions && !fileExtensionIs(filename, ".ts")) {
+ diagnostic = Diagnostics.File_0_must_have_extension_ts_or_d_ts;
+ }
+ else if (!findSourceFile(filename, isDefaultLib, refFile, refPos, refEnd)) {
+ diagnostic = Diagnostics.File_0_not_found;
+ }
+ else if (refFile && host.getCanonicalFileName(filename) === host.getCanonicalFileName(refFile.filename)) {
+ diagnostic = Diagnostics.A_file_cannot_have_a_reference_to_itself;
+ }
+ }
+ else {
+ if (!(findSourceFile(filename + ".ts", isDefaultLib, refFile, refPos, refEnd) || findSourceFile(filename + ".d.ts", isDefaultLib, refFile, refPos, refEnd))) {
+ diagnostic = Diagnostics.File_0_not_found;
+ filename += ".ts";
+ }
+ }
+
+ if (diagnostic) {
+ if (refFile) {
+ errors.push(createFileDiagnostic(refFile, start, length, diagnostic, filename));
+ }
+ else {
+ errors.push(createCompilerDiagnostic(diagnostic, filename));
+ }
+ }
+ }
+
+ // Get source file from normalized filename
+ function findSourceFile(filename: string, isDefaultLib: boolean, refFile?: SourceFile, refStart?: number, refLength?: number): SourceFile {
+ var canonicalName = host.getCanonicalFileName(filename);
+ if (hasProperty(filesByName, canonicalName)) {
+ // We've already looked for this file, use cached result
+ return getSourceFileFromCache(filename, canonicalName, /*useAbsolutePath*/ false);
+ }
+ else {
+ var normalizedAbsolutePath = getNormalizedAbsolutePath(filename, host.getCurrentDirectory());
+ var canonicalAbsolutePath = host.getCanonicalFileName(normalizedAbsolutePath);
+ if (hasProperty(filesByName, canonicalAbsolutePath)) {
+ return getSourceFileFromCache(normalizedAbsolutePath, canonicalAbsolutePath, /*useAbsolutePath*/ true);
+ }
+
+ // We haven't looked for this file, do so now and cache result
+ var file = filesByName[canonicalName] = host.getSourceFile(filename, options.target, hostErrorMessage => {
+ if (refFile) {
+ errors.push(createFileDiagnostic(refFile, refStart, refLength,
+ Diagnostics.Cannot_read_file_0_Colon_1, filename, hostErrorMessage));
+ }
+ else {
+ errors.push(createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, filename, hostErrorMessage));
+ }
+ });
+ if (file) {
+ seenNoDefaultLib = seenNoDefaultLib || file.hasNoDefaultLib;
+
+ // Set the source file for normalized absolute path
+ filesByName[canonicalAbsolutePath] = file;
+
+ if (!options.noResolve) {
+ var basePath = getDirectoryPath(filename);
+ processReferencedFiles(file, basePath);
+ processImportedModules(file, basePath);
+ }
+ if (isDefaultLib) {
+ files.unshift(file);
+ }
+ else {
+ files.push(file);
+ }
+ forEach(file.getSyntacticDiagnostics(), e => {
+ errors.push(e);
+ });
+ }
+ }
+ return file;
+
+ function getSourceFileFromCache(filename: string, canonicalName: string, useAbsolutePath: boolean): SourceFile {
+ var file = filesByName[canonicalName];
+ if (file && host.useCaseSensitiveFileNames()) {
+ var sourceFileName = useAbsolutePath ? getNormalizedAbsolutePath(file.filename, host.getCurrentDirectory()) : file.filename;
+ if (canonicalName !== sourceFileName) {
+ errors.push(createFileDiagnostic(refFile, refStart, refLength,
+ Diagnostics.Filename_0_differs_from_already_included_filename_1_only_in_casing, filename, sourceFileName));
+ }
+ }
+ return file;
+ }
+ }
+
+ function processReferencedFiles(file: SourceFile, basePath: string) {
+ forEach(file.referencedFiles, ref => {
+ var referencedFilename = isRootedDiskPath(ref.filename) ? ref.filename : combinePaths(basePath, ref.filename);
+ processSourceFile(normalizePath(referencedFilename), /* isDefaultLib */ false, file, ref.pos, ref.end);
+ });
+ }
+
+ function processImportedModules(file: SourceFile, basePath: string) {
+ forEach(file.statements, node => {
+ if (isExternalModuleImportDeclaration(node) &&
+ getExternalModuleImportDeclarationExpression(node).kind === SyntaxKind.StringLiteral) {
+
+ var nameLiteral = getExternalModuleImportDeclarationExpression(node);
+ var moduleName = nameLiteral.text;
+ if (moduleName) {
+ var searchPath = basePath;
+ while (true) {
+ var searchName = normalizePath(combinePaths(searchPath, moduleName));
+ if (findModuleSourceFile(searchName + ".ts", nameLiteral) || findModuleSourceFile(searchName + ".d.ts", nameLiteral)) {
+ break;
+ }
+
+ var parentPath = getDirectoryPath(searchPath);
+ if (parentPath === searchPath) {
+ break;
+ }
+ searchPath = parentPath;
+ }
+ }
+ }
+ else if (node.kind === SyntaxKind.ModuleDeclaration && (node).name.kind === SyntaxKind.StringLiteral && (node.flags & NodeFlags.Ambient || isDeclarationFile(file))) {
+ // TypeScript 1.0 spec (April 2014): 12.1.6
+ // An AmbientExternalModuleDeclaration declares an external module.
+ // This type of declaration is permitted only in the global module.
+ // The StringLiteral must specify a top - level external module name.
+ // Relative external module names are not permitted
+ forEachChild((node).body, node => {
+ if (isExternalModuleImportDeclaration(node) &&
+ getExternalModuleImportDeclarationExpression(node).kind === SyntaxKind.StringLiteral) {
+
+ var nameLiteral = getExternalModuleImportDeclarationExpression(node);
+ var moduleName = nameLiteral.text;
+ if (moduleName) {
+ // TypeScript 1.0 spec (April 2014): 12.1.6
+ // An ExternalImportDeclaration in anAmbientExternalModuleDeclaration may reference other external modules
+ // only through top - level external module names. Relative external module names are not permitted.
+ var searchName = normalizePath(combinePaths(basePath, moduleName));
+ var tsFile = findModuleSourceFile(searchName + ".ts", nameLiteral);
+ if (!tsFile) {
+ findModuleSourceFile(searchName + ".d.ts", nameLiteral);
+ }
+ }
+ }
+ });
+ }
+ });
+
+ function findModuleSourceFile(filename: string, nameLiteral: LiteralExpression) {
+ return findSourceFile(filename, /* isDefaultLib */ false, file, nameLiteral.pos, nameLiteral.end - nameLiteral.pos);
+ }
+ }
+
+ function verifyCompilerOptions() {
+ if (!options.sourceMap && (options.mapRoot || options.sourceRoot)) {
+ // Error to specify --mapRoot or --sourceRoot without mapSourceFiles
+ if (options.mapRoot) {
+ errors.push(createCompilerDiagnostic(Diagnostics.Option_mapRoot_cannot_be_specified_without_specifying_sourcemap_option));
+ }
+ if (options.sourceRoot) {
+ errors.push(createCompilerDiagnostic(Diagnostics.Option_sourceRoot_cannot_be_specified_without_specifying_sourcemap_option));
+ }
+ return;
+ }
+
+ var firstExternalModule = forEach(files, f => isExternalModule(f) ? f : undefined);
+ if (firstExternalModule && options.module === ModuleKind.None) {
+ // We cannot use createDiagnosticFromNode because nodes do not have parents yet
+ var externalModuleErrorSpan = getErrorSpanForNode(firstExternalModule.externalModuleIndicator);
+ var errorStart = skipTrivia(firstExternalModule.text, externalModuleErrorSpan.pos);
+ var errorLength = externalModuleErrorSpan.end - errorStart;
+ errors.push(createFileDiagnostic(firstExternalModule, errorStart, errorLength, Diagnostics.Cannot_compile_external_modules_unless_the_module_flag_is_provided));
+ }
+
+ // there has to be common source directory if user specified --outdir || --sourcRoot
+ // if user specified --mapRoot, there needs to be common source directory if there would be multiple files being emitted
+ if (options.outDir || // there is --outDir specified
+ options.sourceRoot || // there is --sourceRoot specified
+ (options.mapRoot && // there is --mapRoot Specified and there would be multiple js files generated
+ (!options.out || firstExternalModule !== undefined))) {
+
+ var commonPathComponents: string[];
+ forEach(files, sourceFile => {
+ // Each file contributes into common source file path
+ if (!(sourceFile.flags & NodeFlags.DeclarationFile)
+ && !fileExtensionIs(sourceFile.filename, ".js")) {
+ var sourcePathComponents = getNormalizedPathComponents(sourceFile.filename, host.getCurrentDirectory());
+ sourcePathComponents.pop(); // FileName is not part of directory
+ if (commonPathComponents) {
+ for (var i = 0; i < Math.min(commonPathComponents.length, sourcePathComponents.length); i++) {
+ if (commonPathComponents[i] !== sourcePathComponents[i]) {
+ if (i === 0) {
+ errors.push(createCompilerDiagnostic(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files));
+ return;
+ }
+
+ // New common path found that is 0 -> i-1
+ commonPathComponents.length = i;
+ break;
+ }
+ }
+
+ // If the fileComponent path completely matched and less than already found update the length
+ if (sourcePathComponents.length < commonPathComponents.length) {
+ commonPathComponents.length = sourcePathComponents.length;
+ }
+ }
+ else {
+ // first file
+ commonPathComponents = sourcePathComponents;
+ }
+ }
+ });
+
+ commonSourceDirectory = getNormalizedPathFromPathComponents(commonPathComponents);
+ if (commonSourceDirectory) {
+ // Make sure directory path ends with directory separator so this string can directly
+ // used to replace with "" to get the relative path of the source file and the relative path doesn't
+ // start with / making it rooted path
+ commonSourceDirectory += directorySeparator;
+ }
+ }
+
+ if (options.noEmit) {
+ if (options.out || options.outDir) {
+ errors.push(createCompilerDiagnostic(Diagnostics.Option_noEmit_cannot_be_specified_with_option_out_or_outDir));
+ }
+
+ if (options.declaration) {
+ errors.push(createCompilerDiagnostic(Diagnostics.Option_noEmit_cannot_be_specified_with_option_declaration));
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts
index 1c4dc094b25..67814c99462 100644
--- a/src/compiler/scanner.ts
+++ b/src/compiler/scanner.ts
@@ -1,4 +1,3 @@
-///
///
///
diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts
index 32725bfe0fc..9d038920693 100644
--- a/src/compiler/tsc.ts
+++ b/src/compiler/tsc.ts
@@ -1,11 +1,4 @@
-///
-///
-///
-///
-///
-///
-///
-///
+///
///
module ts {
@@ -293,7 +286,7 @@ module ts {
var checker = program.getTypeChecker(/*fullTypeCheckMode*/ true);
var checkStart = new Date().getTime();
errors = checker.getDiagnostics();
- if (checker.isEmitBlocked()) {
+ if (program.isEmitBlocked()) {
exitStatus = EmitReturnStatus.AllOutputGenerationSkipped;
}
else if (compilerOptions.noEmit) {
@@ -301,7 +294,7 @@ module ts {
}
else {
var emitStart = new Date().getTime();
- var emitOutput = checker.emitFiles();
+ var emitOutput = program.emitFiles();
var emitErrors = emitOutput.diagnostics;
exitStatus = emitOutput.emitResultStatus;
var reportStart = new Date().getTime();
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index 1e0507ac1e9..cc1b37aef5d 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -1,5 +1,3 @@
-///
-
module ts {
export interface Map {
[index: string]: T;
@@ -248,7 +246,6 @@ module ts {
EnumMember,
// Top-level nodes
SourceFile,
- Program,
// Synthesized list
SyntaxList,
@@ -925,15 +922,33 @@ module ts {
identifiers: Map;
}
- export interface Program {
- getSourceFile(filename: string): SourceFile;
- getSourceFiles(): SourceFile[];
+ export interface ScriptReferenceHost {
getCompilerOptions(): CompilerOptions;
+ getSourceFile(filename: string): SourceFile;
+ getCurrentDirectory(): string;
+ }
+
+ export interface Program extends ScriptReferenceHost {
+ getSourceFiles(): SourceFile[];
getCompilerHost(): CompilerHost;
+
getDiagnostics(sourceFile?: SourceFile): Diagnostic[];
getGlobalDiagnostics(): Diagnostic[];
- getTypeChecker(fullTypeCheckMode: boolean): TypeChecker;
+ getDeclarationDiagnostics(sourceFile: SourceFile): Diagnostic[];
+
+ // Gets a type checker that can be used to semantically analyze source fils in the program.
+ // The 'produceDiagnostics' flag determines if the checker will produce diagnostics while
+ // analyzing the code. It can be set to 'false' to make many type checking operaitons
+ // faster. With this flag set, the checker can avoid codepaths only necessary to produce
+ // diagnostics, but not necessary to answer semantic questions about the code.
+ //
+ // If 'produceDiagnostics' is false, then any calls to get diagnostics from the TypeChecker
+ // will throw an invalid operation exception.
+ getTypeChecker(produceDiagnostics: boolean): TypeChecker;
getCommonSourceDirectory(): string;
+
+ emitFiles(targetSourceFile?: SourceFile): EmitResult;
+ isEmitBlocked(sourceFile?: SourceFile): boolean;
}
export interface SourceMapSpan {
@@ -973,16 +988,22 @@ module ts {
sourceMaps: SourceMapData[]; // Array of sourceMapData if compiler emitted sourcemaps
}
+ export interface TypeCheckerHost {
+ getCompilerOptions(): CompilerOptions;
+ getCompilerHost(): CompilerHost;
+
+ getSourceFiles(): SourceFile[];
+ getSourceFile(filename: string): SourceFile;
+ }
+
export interface TypeChecker {
- getProgram(): Program;
+ getEmitResolver(): EmitResolver;
getDiagnostics(sourceFile?: SourceFile): Diagnostic[];
- getDeclarationDiagnostics(sourceFile: SourceFile): Diagnostic[];
getGlobalDiagnostics(): Diagnostic[];
getNodeCount(): number;
getIdentifierCount(): number;
getSymbolCount(): number;
getTypeCount(): number;
- emitFiles(targetSourceFile?: SourceFile): EmitResult;
getTypeOfSymbolAtLocation(symbol: Symbol, node: Node): Type;
getDeclaredTypeOfSymbol(symbol: Symbol): Type;
getPropertiesOfType(type: Type): Symbol[];
@@ -1006,7 +1027,7 @@ module ts {
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
isUndefinedSymbol(symbol: Symbol): boolean;
isArgumentsSymbol(symbol: Symbol): boolean;
- isEmitBlocked(sourceFile?: SourceFile): boolean;
+
// Returns the constant value of this enum member, or 'undefined' if the enum member has a computed value.
getEnumMemberValue(node: EnumMember): number;
isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean;
@@ -1088,7 +1109,6 @@ module ts {
}
export interface EmitResolver {
- getProgram(): Program;
getLocalNameOfContainer(container: ModuleDeclaration | EnumDeclaration): string;
getExpressionNamePrefix(node: Identifier): string;
getExportAssignmentName(node: SourceFile): string;
@@ -1105,7 +1125,6 @@ module ts {
isEntityNameVisible(entityName: EntityName, enclosingDeclaration: Node): SymbolVisibilityResult;
// Returns the constant value this property access resolves to, or 'undefined' for a non-constant
getConstantValue(node: PropertyAccessExpression | ElementAccessExpression): number;
- isEmitBlocked(sourceFile?: SourceFile): boolean;
isUnknownIdentifier(location: Node, name: string): boolean;
}
diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts
index bbe4d7dbf35..edd8bf156cf 100644
--- a/src/compiler/utilities.ts
+++ b/src/compiler/utilities.ts
@@ -691,11 +691,11 @@ module ts {
return undefined;
}
- export function tryResolveScriptReference(program: Program, sourceFile: SourceFile, reference: FileReference) {
- if (!program.getCompilerOptions().noResolve) {
+ export function tryResolveScriptReference(host: ScriptReferenceHost, 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.getCurrentDirectory());
+ return host.getSourceFile(referenceFileName);
}
}
@@ -790,6 +790,21 @@ module ts {
return false;
}
+ export function createEmitHostFromProgram(program: Program): EmitHost {
+ var compilerHost = program.getCompilerHost();
+ return {
+ getCanonicalFileName: compilerHost.getCanonicalFileName,
+ getCommonSourceDirectory: program.getCommonSourceDirectory,
+ getCompilerOptions: program.getCompilerOptions,
+ getCurrentDirectory: compilerHost.getCurrentDirectory,
+ getNewLine: compilerHost.getNewLine,
+ getSourceFile: program.getSourceFile,
+ getSourceFiles: program.getSourceFiles,
+ isEmitBlocked: program.isEmitBlocked,
+ writeFile: compilerHost.writeFile,
+ };
+ }
+
export function textSpanEnd(span: TextSpan) {
return span.start + span.length
}
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/fourslash.ts b/src/harness/fourslash.ts
index 4f9e6a3f0e9..cfc83af76e5 100644
--- a/src/harness/fourslash.ts
+++ b/src/harness/fourslash.ts
@@ -2201,13 +2201,13 @@ module FourSlash {
ts.sys.useCaseSensitiveFileNames);
// TODO (drosen): We need to enforce checking on these tests.
var program = ts.createProgram([Harness.Compiler.fourslashFilename, fileName], { out: "fourslashTestOutput.js", noResolve: true, target: ts.ScriptTarget.ES3 }, host);
- var checker = ts.createTypeChecker(program, /*fullTypeCheckMode*/ true);
+ var checker = ts.createTypeChecker(program, /*produceDiagnostics*/ true);
var errors = program.getDiagnostics().concat(checker.getDiagnostics());
if (errors.length > 0) {
throw new Error('Error compiling ' + fileName + ': ' + errors.map(e => e.messageText).join('\r\n'));
}
- checker.emitFiles();
+ program.emitFiles();
result = result || ''; // Might have an empty fourslash file
// Compile and execute the test
diff --git a/src/harness/harness.ts b/src/harness/harness.ts
index bc66186d2d7..d0c2db1e8a7 100644
--- a/src/harness/harness.ts
+++ b/src/harness/harness.ts
@@ -16,8 +16,6 @@
///
///
-///
-///
///
///
///
@@ -909,7 +907,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) {
@@ -1068,14 +1066,14 @@ module Harness {
options.target,
useCaseSensitiveFileNames));
- var checker = program.getTypeChecker(/*fullTypeCheckMode*/ true);
+ var checker = program.getTypeChecker(/*produceDiagnostics*/ true);
- var isEmitBlocked = checker.isEmitBlocked();
+ var isEmitBlocked = program.isEmitBlocked();
// only emit if there weren't parse errors
var emitResult: ts.EmitResult;
if (!isEmitBlocked) {
- emitResult = checker.emitFiles();
+ emitResult = program.emitFiles();
}
var errors: HarnessDiagnostic[] = [];
@@ -1086,7 +1084,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/projectsRunner.ts b/src/harness/projectsRunner.ts
index 81791c099d3..52467fdffd6 100644
--- a/src/harness/projectsRunner.ts
+++ b/src/harness/projectsRunner.ts
@@ -130,9 +130,9 @@ class ProjectRunner extends RunnerBase {
var errors = program.getDiagnostics();
var sourceMapData: ts.SourceMapData[] = null;
if (!errors.length) {
- var checker = program.getTypeChecker(/*fullTypeCheck*/ true);
+ var checker = program.getTypeChecker(/*produceDiagnostics:*/ true);
errors = checker.getDiagnostics();
- var emitResult = checker.emitFiles();
+ var emitResult = program.emitFiles();
errors = ts.concatenate(errors, emitResult.diagnostics);
sourceMapData = emitResult.sourceMaps;
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);
diff --git a/src/services/services.ts b/src/services/services.ts
index 249270f187c..4951ff258f6 100644
--- a/src/services/services.ts
+++ b/src/services/services.ts
@@ -1,8 +1,4 @@
-///
-///
-///
-///
-///
+///
///
///
@@ -13,7 +9,6 @@
///
module ts {
-
export var servicesVersion = "0.4"
export interface Node {
@@ -1925,16 +1920,11 @@ module ts {
// this checker is used to answer all LS questions except errors
var typeInfoResolver: TypeChecker;
- // the sole purpose of this checker is to return semantic diagnostics
- // creation is deferred - use getFullTypeCheckChecker to get instance
- var fullTypeCheckChecker_doNotAccessDirectly: TypeChecker;
-
var useCaseSensitivefilenames = false;
var sourceFilesByName: Map = {};
var documentRegistry = documentRegistry;
var cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken());
var activeCompletionSession: CompletionSession; // The current active completion session, used to get the completion entry details
- var writer: (filename: string, data: string, writeByteOrderMark: boolean) => void = undefined;
// Check if the localized messages json is set, otherwise query the host for it
if (!localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) {
@@ -1949,8 +1939,8 @@ module ts {
return lookUp(sourceFilesByName, getCanonicalFileName(filename));
}
- function getFullTypeCheckChecker() {
- return fullTypeCheckChecker_doNotAccessDirectly || (fullTypeCheckChecker_doNotAccessDirectly = program.getTypeChecker(/*fullTypeCheck*/ true));
+ function getDiagnosticsProducingTypeChecker() {
+ return program.getTypeChecker(/*produceDiagnostics:*/ true);
}
function getRuleProvider(options: FormatCodeOptions) {
@@ -1977,7 +1967,6 @@ module ts {
return host.getDefaultLibFilename(options);
},
writeFile: (filename, data, writeByteOrderMark) => {
- writer(filename, data, writeByteOrderMark);
},
getCurrentDirectory: (): string => {
return host.getCurrentDirectory();
@@ -2090,8 +2079,7 @@ module ts {
// Now create a new compiler
program = createProgram(hostfilenames, compilationSettings, createCompilerHost());
- typeInfoResolver = program.getTypeChecker(/*fullTypeCheckMode*/ false);
- fullTypeCheckChecker_doNotAccessDirectly = undefined;
+ typeInfoResolver = program.getTypeChecker(/*produceDiagnostics*/ false);
}
/**
@@ -2101,8 +2089,7 @@ module ts {
*/
function cleanupSemanticCache(): void {
if (program) {
- typeInfoResolver = program.getTypeChecker(/*fullTypeCheckMode*/ false);
- fullTypeCheckChecker_doNotAccessDirectly = undefined;
+ typeInfoResolver = program.getTypeChecker(/*produceDiagnostics*/ false);
}
}
@@ -2131,7 +2118,7 @@ module ts {
filename = normalizeSlashes(filename)
var compilerOptions = program.getCompilerOptions();
- var checker = getFullTypeCheckChecker();
+ var checker = getDiagnosticsProducingTypeChecker();
var targetSourceFile = getSourceFile(filename);
// Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file.
@@ -2140,7 +2127,7 @@ module ts {
var allDiagnostics = checker.getDiagnostics(targetSourceFile);
if (compilerOptions.declaration) {
// If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface
- allDiagnostics = allDiagnostics.concat(checker.getDeclarationDiagnostics(targetSourceFile));
+ allDiagnostics = allDiagnostics.concat(program.getDeclarationDiagnostics(targetSourceFile));
}
return allDiagnostics
}
@@ -4571,7 +4558,7 @@ module ts {
var outputFiles: OutputFile[] = [];
- function getEmitOutputWriter(filename: string, data: string, writeByteOrderMark: boolean) {
+ function writeFile(filename: string, data: string, writeByteOrderMark: boolean) {
outputFiles.push({
name: filename,
writeByteOrderMark: writeByteOrderMark,
@@ -4579,13 +4566,12 @@ module ts {
});
}
- // Initialize writer for CompilerHost.writeFile
- writer = getEmitOutputWriter;
+ // Get an emit host from our program, but override the writeFile functionality to
+ // call our local writer function.
+ var emitHost = createEmitHostFromProgram(program);
+ emitHost.writeFile = writeFile;
- var emitOutput = getFullTypeCheckChecker().emitFiles(sourceFile);
-
- // Reset writer back to undefined to make sure that we produce an error message if CompilerHost.writeFile method is called when we are not in getEmitOutput
- writer = undefined;
+ var emitOutput = emitFiles(getDiagnosticsProducingTypeChecker().getEmitResolver(), emitHost, sourceFile);
return {
outputFiles,
diff --git a/tests/baselines/reference/objectLiteralMemberWithModifiers2.errors.txt b/tests/baselines/reference/objectLiteralMemberWithModifiers2.errors.txt
index 9fe5365f7da..e939725ea6e 100644
--- a/tests/baselines/reference/objectLiteralMemberWithModifiers2.errors.txt
+++ b/tests/baselines/reference/objectLiteralMemberWithModifiers2.errors.txt
@@ -1,10 +1,10 @@
-tests/cases/compiler/objectLiteralMemberWithModifiers2.ts(1,11): error TS1184: Modifiers cannot appear here.
+tests/cases/compiler/objectLiteralMemberWithModifiers2.ts(1,22): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
tests/cases/compiler/objectLiteralMemberWithModifiers2.ts(1,22): error TS2378: A 'get' accessor must return a value or consist of a single 'throw' statement.
==== tests/cases/compiler/objectLiteralMemberWithModifiers2.ts (2 errors) ====
var v = { public get foo() { } }
- ~~~~~~
-!!! error TS1184: Modifiers cannot appear here.
+ ~~~
+!!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
~~~
!!! error TS2378: A 'get' accessor must return a value or consist of a single 'throw' statement.
\ No newline at end of file
diff --git a/tests/baselines/reference/objectLiteralMemberWithModifiers2.js b/tests/baselines/reference/objectLiteralMemberWithModifiers2.js
deleted file mode 100644
index fd8e0a68430..00000000000
--- a/tests/baselines/reference/objectLiteralMemberWithModifiers2.js
+++ /dev/null
@@ -1,6 +0,0 @@
-//// [objectLiteralMemberWithModifiers2.ts]
-var v = { public get foo() { } }
-
-//// [objectLiteralMemberWithModifiers2.js]
-var v = { get foo() {
-} };
diff --git a/tests/baselines/reference/parserAccessors10.errors.txt b/tests/baselines/reference/parserAccessors10.errors.txt
index ac552b55c6a..a5228f47443 100644
--- a/tests/baselines/reference/parserAccessors10.errors.txt
+++ b/tests/baselines/reference/parserAccessors10.errors.txt
@@ -1,12 +1,9 @@
-tests/cases/conformance/parser/ecmascript5/Accessors/parserAccessors10.ts(2,3): error TS1184: Modifiers cannot appear here.
tests/cases/conformance/parser/ecmascript5/Accessors/parserAccessors10.ts(2,14): error TS2378: A 'get' accessor must return a value or consist of a single 'throw' statement.
-==== tests/cases/conformance/parser/ecmascript5/Accessors/parserAccessors10.ts (2 errors) ====
+==== tests/cases/conformance/parser/ecmascript5/Accessors/parserAccessors10.ts (1 errors) ====
var v = {
public get foo() { }
- ~~~~~~
-!!! error TS1184: Modifiers cannot appear here.
~~~
!!! error TS2378: A 'get' accessor must return a value or consist of a single 'throw' statement.
};
\ No newline at end of file