Skip to content

Commit a06ce61

Browse files
committed
Merge branch 'master' into es6ImportExportEmit
2 parents 766cb68 + 6155832 commit a06ce61

File tree

65 files changed

+1027
-300
lines changed

Some content is hidden

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

65 files changed

+1027
-300
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.js linguist-language=TypeScript

.travis.yml

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,4 @@ language: node_js
33
node_js:
44
- '0.10'
55

6-
sudo: false
7-
8-
before_script: npm install -g codeclimate-test-reporter
9-
10-
after_script:
11-
- cat coverage/lcov.info | codeclimate
12-
13-
addons:
14-
code_climate:
15-
repo_token: 9852ac5362c8cc38c07ca5adc0f94c20c6c79bd78e17933dc284598a65338656
6+
sudo: false

package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,9 @@
3838
"mocha": "latest",
3939
"chai": "latest",
4040
"browserify": "latest",
41-
"istanbul": "latest",
42-
"codeclimate-test-reporter": "latest"
41+
"istanbul": "latest"
4342
},
4443
"scripts": {
45-
"test": "jake generate-code-coverage"
44+
"test": "jake runtests"
4645
}
4746
}

src/compiler/binder.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -322,13 +322,14 @@ module ts {
322322
}
323323
else {
324324
bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes, /*isBlockScopeContainer*/ true);
325-
if (state === ModuleInstanceState.ConstEnumOnly) {
326-
// mark value module as module that contains only enums
327-
node.symbol.constEnumOnlyModule = true;
325+
let currentModuleIsConstEnumOnly = state === ModuleInstanceState.ConstEnumOnly;
326+
if (node.symbol.constEnumOnlyModule === undefined) {
327+
// non-merged case - use the current state
328+
node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly;
328329
}
329-
else if (node.symbol.constEnumOnlyModule) {
330-
// const only value module was merged with instantiated module - reset flag
331-
node.symbol.constEnumOnlyModule = false;
330+
else {
331+
// merged case: module is const enum only if all its pieces are non-instantiated or const enum
332+
node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly;
332333
}
333334
}
334335
}

src/compiler/checker.ts

Lines changed: 80 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,7 @@ module ts {
7979
let emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
8080
let anyFunctionType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
8181
let noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
82-
let inferenceFailureType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
83-
82+
8483
let anySignature = createSignature(undefined, undefined, emptyArray, anyType, 0, false, false);
8584
let unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, 0, false, false);
8685

@@ -3519,6 +3518,7 @@ module ts {
35193518
return t => {
35203519
for (let i = 0; i < context.typeParameters.length; i++) {
35213520
if (t === context.typeParameters[i]) {
3521+
context.inferences[i].isFixed = true;
35223522
return getInferredType(context, i);
35233523
}
35243524
}
@@ -4377,8 +4377,11 @@ module ts {
43774377
}
43784378

43794379
function reportNoCommonSupertypeError(types: Type[], errorLocation: Node, errorMessageChainHead: DiagnosticMessageChain): void {
4380+
// The downfallType/bestSupertypeDownfallType is the first type that caused a particular candidate
4381+
// to not be the common supertype. So if it weren't for this one downfallType (and possibly others),
4382+
// the type in question could have been the common supertype.
43804383
let bestSupertype: Type;
4381-
let bestSupertypeDownfallType: Type; // The type that caused bestSupertype not to be the common supertype
4384+
let bestSupertypeDownfallType: Type;
43824385
let bestSupertypeScore = 0;
43834386

43844387
for (let i = 0; i < types.length; i++) {
@@ -4393,6 +4396,8 @@ module ts {
43934396
}
43944397
}
43954398

4399+
Debug.assert(!!downfallType, "If there is no common supertype, each type should have a downfallType");
4400+
43964401
if (score > bestSupertypeScore) {
43974402
bestSupertype = types[i];
43984403
bestSupertypeDownfallType = downfallType;
@@ -4575,13 +4580,12 @@ module ts {
45754580
function createInferenceContext(typeParameters: TypeParameter[], inferUnionTypes: boolean): InferenceContext {
45764581
let inferences: TypeInferences[] = [];
45774582
for (let unused of typeParameters) {
4578-
inferences.push({ primary: undefined, secondary: undefined });
4583+
inferences.push({ primary: undefined, secondary: undefined, isFixed: false });
45794584
}
45804585
return {
4581-
typeParameters: typeParameters,
4582-
inferUnionTypes: inferUnionTypes,
4583-
inferenceCount: 0,
4584-
inferences: inferences,
4586+
typeParameters,
4587+
inferUnionTypes,
4588+
inferences,
45854589
inferredTypes: new Array(typeParameters.length),
45864590
};
45874591
}
@@ -4627,11 +4631,21 @@ module ts {
46274631
for (let i = 0; i < typeParameters.length; i++) {
46284632
if (target === typeParameters[i]) {
46294633
let inferences = context.inferences[i];
4630-
let candidates = inferiority ?
4631-
inferences.secondary || (inferences.secondary = []) :
4632-
inferences.primary || (inferences.primary = []);
4633-
if (!contains(candidates, source)) candidates.push(source);
4634-
break;
4634+
if (!inferences.isFixed) {
4635+
// Any inferences that are made to a type parameter in a union type are inferior
4636+
// to inferences made to a flat (non-union) type. This is because if we infer to
4637+
// T | string[], we really don't know if we should be inferring to T or not (because
4638+
// the correct constituent on the target side could be string[]). Therefore, we put
4639+
// such inferior inferences into a secondary bucket, and only use them if the primary
4640+
// bucket is empty.
4641+
let candidates = inferiority ?
4642+
inferences.secondary || (inferences.secondary = []) :
4643+
inferences.primary || (inferences.primary = []);
4644+
if (!contains(candidates, source)) {
4645+
candidates.push(source);
4646+
}
4647+
}
4648+
return;
46354649
}
46364650
}
46374651
}
@@ -4737,21 +4751,35 @@ module ts {
47374751

47384752
function getInferredType(context: InferenceContext, index: number): Type {
47394753
let inferredType = context.inferredTypes[index];
4754+
let inferenceSucceeded: boolean;
47404755
if (!inferredType) {
47414756
let inferences = getInferenceCandidates(context, index);
47424757
if (inferences.length) {
4743-
// Infer widened union or supertype, or the undefined type for no common supertype
4758+
// Infer widened union or supertype, or the unknown type for no common supertype
47444759
let unionOrSuperType = context.inferUnionTypes ? getUnionType(inferences) : getCommonSupertype(inferences);
4745-
inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : inferenceFailureType;
4760+
inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : unknownType;
4761+
inferenceSucceeded = !!unionOrSuperType;
47464762
}
47474763
else {
4748-
// Infer the empty object type when no inferences were made
4764+
// Infer the empty object type when no inferences were made. It is important to remember that
4765+
// in this case, inference still succeeds, meaning there is no error for not having inference
4766+
// candidates. An inference error only occurs when there are *conflicting* candidates, i.e.
4767+
// candidates with no common supertype.
47494768
inferredType = emptyObjectType;
4769+
inferenceSucceeded = true;
47504770
}
4751-
if (inferredType !== inferenceFailureType) {
4771+
4772+
// Only do the constraint check if inference succeeded (to prevent cascading errors)
4773+
if (inferenceSucceeded) {
47524774
let constraint = getConstraintOfTypeParameter(context.typeParameters[index]);
47534775
inferredType = constraint && !isTypeAssignableTo(inferredType, constraint) ? constraint : inferredType;
47544776
}
4777+
else if (context.failedTypeParameterIndex === undefined || context.failedTypeParameterIndex > index) {
4778+
// If inference failed, it is necessary to record the index of the failed type parameter (the one we are on).
4779+
// It might be that inference has already failed on a later type parameter on a previous call to inferTypeArguments.
4780+
// So if this failure is on preceding type parameter, this type parameter is the new failure index.
4781+
context.failedTypeParameterIndex = index;
4782+
}
47554783
context.inferredTypes[index] = inferredType;
47564784
}
47574785
return inferredType;
@@ -6348,11 +6376,32 @@ module ts {
63486376
return getSignatureInstantiation(signature, getInferredTypes(context));
63496377
}
63506378

6351-
function inferTypeArguments(signature: Signature, args: Expression[], excludeArgument: boolean[]): InferenceContext {
6379+
function inferTypeArguments(signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): void {
63526380
let typeParameters = signature.typeParameters;
6353-
let context = createInferenceContext(typeParameters, /*inferUnionTypes*/ false);
63546381
let inferenceMapper = createInferenceMapper(context);
63556382

6383+
// Clear out all the inference results from the last time inferTypeArguments was called on this context
6384+
for (let i = 0; i < typeParameters.length; i++) {
6385+
// As an optimization, we don't have to clear (and later recompute) inferred types
6386+
// for type parameters that have already been fixed on the previous call to inferTypeArguments.
6387+
// It would be just as correct to reset all of them. But then we'd be repeating the same work
6388+
// for the type parameters that were fixed, namely the work done by getInferredType.
6389+
if (!context.inferences[i].isFixed) {
6390+
context.inferredTypes[i] = undefined;
6391+
}
6392+
}
6393+
6394+
// On this call to inferTypeArguments, we may get more inferences for certain type parameters that were not
6395+
// fixed last time. This means that a type parameter that failed inference last time may succeed this time,
6396+
// or vice versa. Therefore, the failedTypeParameterIndex is useless if it points to an unfixed type parameter,
6397+
// because it may change. So here we reset it. However, getInferredType will not revisit any type parameters
6398+
// that were previously fixed. So if a fixed type parameter failed previously, it will fail again because
6399+
// it will contain the exact same set of inferences. So if we reset the index from a fixed type parameter,
6400+
// we will lose information that we won't recover this time around.
6401+
if (context.failedTypeParameterIndex !== undefined && !context.inferences[context.failedTypeParameterIndex].isFixed) {
6402+
context.failedTypeParameterIndex = undefined;
6403+
}
6404+
63566405
// We perform two passes over the arguments. In the first pass we infer from all arguments, but use
63576406
// wildcards for all context sensitive function expressions.
63586407
for (let i = 0; i < args.length; i++) {
@@ -6387,18 +6436,7 @@ module ts {
63876436
}
63886437
}
63896438

6390-
let inferredTypes = getInferredTypes(context);
6391-
// Inference has failed if the inferenceFailureType type is in list of inferences
6392-
context.failedTypeParameterIndex = indexOf(inferredTypes, inferenceFailureType);
6393-
6394-
// Wipe out the inferenceFailureType from the array so that error recovery can work properly
6395-
for (let i = 0; i < inferredTypes.length; i++) {
6396-
if (inferredTypes[i] === inferenceFailureType) {
6397-
inferredTypes[i] = unknownType;
6398-
}
6399-
}
6400-
6401-
return context;
6439+
getInferredTypes(context);
64026440
}
64036441

64046442
function checkTypeArguments(signature: Signature, typeArguments: TypeNode[], typeArgumentResultTypes: Type[], reportErrors: boolean): boolean {
@@ -6632,15 +6670,17 @@ module ts {
66326670
return resolveErrorCall(node);
66336671

66346672
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>) {
6635-
for (let current of candidates) {
6636-
if (!hasCorrectArity(node, args, current)) {
6673+
for (let originalCandidate of candidates) {
6674+
if (!hasCorrectArity(node, args, originalCandidate)) {
66376675
continue;
66386676
}
6639-
6640-
let originalCandidate = current;
6641-
let inferenceResult: InferenceContext;
6677+
66426678
let candidate: Signature;
66436679
let typeArgumentsAreValid: boolean;
6680+
let inferenceContext = originalCandidate.typeParameters
6681+
? createInferenceContext(originalCandidate.typeParameters, /*inferUnionTypes*/ false)
6682+
: undefined;
6683+
66446684
while (true) {
66456685
candidate = originalCandidate;
66466686
if (candidate.typeParameters) {
@@ -6650,9 +6690,9 @@ module ts {
66506690
typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false)
66516691
}
66526692
else {
6653-
inferenceResult = inferTypeArguments(candidate, args, excludeArgument);
6654-
typeArgumentsAreValid = inferenceResult.failedTypeParameterIndex < 0;
6655-
typeArgumentTypes = inferenceResult.inferredTypes;
6693+
inferTypeArguments(candidate, args, excludeArgument, inferenceContext);
6694+
typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex === undefined;
6695+
typeArgumentTypes = inferenceContext.inferredTypes;
66566696
}
66576697
if (!typeArgumentsAreValid) {
66586698
break;
@@ -6682,7 +6722,7 @@ module ts {
66826722
else {
66836723
candidateForTypeArgumentError = originalCandidate;
66846724
if (!typeArguments) {
6685-
resultOfFailedInference = inferenceResult;
6725+
resultOfFailedInference = inferenceContext;
66866726
}
66876727
}
66886728
}

src/compiler/emitter.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5516,14 +5516,6 @@ module ts {
55165516
}
55175517
}
55185518

5519-
function getFirstExportAssignment(sourceFile: SourceFile) {
5520-
return forEach(sourceFile.statements, node => {
5521-
if (node.kind === SyntaxKind.ExportAssignment) {
5522-
return <ExportAssignment>node;
5523-
}
5524-
});
5525-
}
5526-
55275519
function sortAMDModules(amdModules: {name: string; path: string}[]) {
55285520
// AMD modules with declared variable names go first
55295521
return amdModules.sort((moduleA, moduleB) => {

src/compiler/program.ts

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
/// <reference path="emitter.ts" />
33

44
module ts {
5+
/* @internal */ export let programTime = 0;
56
/* @internal */ export let emitTime = 0;
67
/* @internal */ export let ioReadTime = 0;
8+
/* @internal */ export let ioWriteTime = 0;
79

810
/** The version of the TypeScript compiler release */
911
export let version = "1.5.0.0";
@@ -36,33 +38,34 @@ module ts {
3638
}
3739
text = "";
3840
}
39-
4041
return text !== undefined ? createSourceFile(fileName, text, languageVersion) : undefined;
4142
}
4243

43-
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
44-
function directoryExists(directoryPath: string): boolean {
45-
if (hasProperty(existingDirectories, directoryPath)) {
46-
return true;
47-
}
48-
if (sys.directoryExists(directoryPath)) {
49-
existingDirectories[directoryPath] = true;
50-
return true;
51-
}
52-
return false;
44+
function directoryExists(directoryPath: string): boolean {
45+
if (hasProperty(existingDirectories, directoryPath)) {
46+
return true;
5347
}
48+
if (sys.directoryExists(directoryPath)) {
49+
existingDirectories[directoryPath] = true;
50+
return true;
51+
}
52+
return false;
53+
}
5454

55-
function ensureDirectoriesExist(directoryPath: string) {
56-
if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
57-
let parentDirectory = getDirectoryPath(directoryPath);
58-
ensureDirectoriesExist(parentDirectory);
59-
sys.createDirectory(directoryPath);
60-
}
55+
function ensureDirectoriesExist(directoryPath: string) {
56+
if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
57+
let parentDirectory = getDirectoryPath(directoryPath);
58+
ensureDirectoriesExist(parentDirectory);
59+
sys.createDirectory(directoryPath);
6160
}
61+
}
6262

63+
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
6364
try {
65+
var start = new Date().getTime();
6466
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
6567
sys.writeFile(fileName, data, writeByteOrderMark);
68+
ioWriteTime += new Date().getTime() - start;
6669
}
6770
catch (e) {
6871
if (onError) {
@@ -120,16 +123,19 @@ module ts {
120123
let diagnostics = createDiagnosticCollection();
121124
let seenNoDefaultLib = options.noLib;
122125
let commonSourceDirectory: string;
123-
host = host || createCompilerHost(options);
126+
let diagnosticsProducingTypeChecker: TypeChecker;
127+
let noDiagnosticsTypeChecker: TypeChecker;
124128

129+
let start = new Date().getTime();
130+
131+
host = host || createCompilerHost(options);
125132
forEach(rootNames, name => processRootFile(name, false));
126133
if (!seenNoDefaultLib) {
127134
processRootFile(host.getDefaultLibFileName(options), true);
128135
}
129136
verifyCompilerOptions();
130137

131-
let diagnosticsProducingTypeChecker: TypeChecker;
132-
let noDiagnosticsTypeChecker: TypeChecker;
138+
programTime += new Date().getTime() - start;
133139

134140
program = {
135141
getSourceFile: getSourceFile,

0 commit comments

Comments
 (0)