Skip to content

Commit f828bc3

Browse files
author
Andy Hanson
committed
Merge branch 'master' into map4
2 parents 7292f9f + 97e90b5 commit f828bc3

File tree

91 files changed

+1568
-334
lines changed

Some content is hidden

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

91 files changed

+1568
-334
lines changed

CONTRIBUTING.md

-2
Original file line numberDiff line numberDiff line change
@@ -183,5 +183,3 @@ jake baseline-accept
183183
```
184184

185185
to establish the new baselines as the desired behavior. This will change the files in `tests\baselines\reference`, which should be included as part of your commit. It's important to carefully validate changes in the baselines.
186-
187-
**Note** that `baseline-accept` should only be run after a full test run! Accepting baselines after running a subset of tests will delete baseline files for the tests that didn't run.

Jakefile.js

+3
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ var compilerSources = [
7979
"transformers/es2016.ts",
8080
"transformers/es2015.ts",
8181
"transformers/generators.ts",
82+
"transformers/es5.ts",
8283
"transformer.ts",
8384
"sourcemap.ts",
8485
"comments.ts",
@@ -115,6 +116,7 @@ var servicesSources = [
115116
"transformers/es2016.ts",
116117
"transformers/es2015.ts",
117118
"transformers/generators.ts",
119+
"transformers/es5.ts",
118120
"transformer.ts",
119121
"sourcemap.ts",
120122
"comments.ts",
@@ -357,6 +359,7 @@ function concatenateFiles(destinationFile, sourceFiles) {
357359
if (!fs.existsSync(sourceFiles[i])) {
358360
fail(sourceFiles[i] + " does not exist!");
359361
}
362+
fs.appendFileSync(temp, "\n\n");
360363
fs.appendFileSync(temp, fs.readFileSync(sourceFiles[i]));
361364
}
362365
// Move the file to the final destination

scripts/buildProtocol.ts

+52-17
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,27 @@ function endsWith(s: string, suffix: string) {
1010
class DeclarationsWalker {
1111
private visitedTypes: ts.Type[] = [];
1212
private text = "";
13+
private removedTypes: ts.Type[] = [];
14+
1315
private constructor(private typeChecker: ts.TypeChecker, private protocolFile: ts.SourceFile) {
1416
}
1517

1618
static getExtraDeclarations(typeChecker: ts.TypeChecker, protocolFile: ts.SourceFile): string {
1719
let text = "declare namespace ts.server.protocol {\n";
1820
var walker = new DeclarationsWalker(typeChecker, protocolFile);
1921
walker.visitTypeNodes(protocolFile);
20-
return walker.text
22+
text = walker.text
2123
? `declare namespace ts.server.protocol {\n${walker.text}}`
2224
: "";
25+
if (walker.removedTypes) {
26+
text += "\ndeclare namespace ts {\n";
27+
text += " // these types are empty stubs for types from services and should not be used directly\n"
28+
for (const type of walker.removedTypes) {
29+
text += ` export type ${type.symbol.name} = never;\n`;
30+
}
31+
text += "}"
32+
}
33+
return text;
2334
}
2435

2536
private processType(type: ts.Type): void {
@@ -41,19 +52,18 @@ class DeclarationsWalker {
4152
if (sourceFile === this.protocolFile || path.basename(sourceFile.fileName) === "lib.d.ts") {
4253
return;
4354
}
44-
// splice declaration in final d.ts file
45-
let text = decl.getFullText();
46-
if (decl.kind === ts.SyntaxKind.EnumDeclaration && !(decl.flags & ts.NodeFlags.Const)) {
47-
// patch enum declaration to make them constan
48-
const declStart = decl.getStart() - decl.getFullStart();
49-
const prefix = text.substring(0, declStart);
50-
const suffix = text.substring(declStart + "enum".length, decl.getEnd() - decl.getFullStart());
51-
text = prefix + "const enum" + suffix;
55+
if (decl.kind === ts.SyntaxKind.EnumDeclaration) {
56+
this.removedTypes.push(type);
57+
return;
5258
}
53-
this.text += `${text}\n`;
59+
else {
60+
// splice declaration in final d.ts file
61+
let text = decl.getFullText();
62+
this.text += `${text}\n`;
63+
// recursively pull all dependencies into result dts file
5464

55-
// recursively pull all dependencies into result dts file
56-
this.visitTypeNodes(decl);
65+
this.visitTypeNodes(decl);
66+
}
5767
}
5868
}
5969
}
@@ -69,15 +79,37 @@ class DeclarationsWalker {
6979
case ts.SyntaxKind.Parameter:
7080
case ts.SyntaxKind.IndexSignature:
7181
if (((<ts.VariableDeclaration | ts.MethodDeclaration | ts.PropertyDeclaration | ts.ParameterDeclaration | ts.PropertySignature | ts.MethodSignature | ts.IndexSignatureDeclaration>node.parent).type) === node) {
72-
const type = this.typeChecker.getTypeAtLocation(node);
73-
if (type && !(type.flags & ts.TypeFlags.TypeParameter)) {
74-
this.processType(type);
75-
}
82+
this.processTypeOfNode(node);
7683
}
7784
break;
85+
case ts.SyntaxKind.InterfaceDeclaration:
86+
const heritageClauses = (<ts.InterfaceDeclaration>node.parent).heritageClauses;
87+
if (heritageClauses) {
88+
if (heritageClauses[0].token !== ts.SyntaxKind.ExtendsKeyword) {
89+
throw new Error(`Unexpected kind of heritage clause: ${ts.SyntaxKind[heritageClauses[0].kind]}`);
90+
}
91+
for (const type of heritageClauses[0].types) {
92+
this.processTypeOfNode(type);
93+
}
94+
}
95+
break;
7896
}
7997
}
8098
ts.forEachChild(node, n => this.visitTypeNodes(n));
99+
}
100+
101+
private processTypeOfNode(node: ts.Node): void {
102+
if (node.kind === ts.SyntaxKind.UnionType) {
103+
for (const t of (<ts.UnionTypeNode>node).types) {
104+
this.processTypeOfNode(t);
105+
}
106+
}
107+
else {
108+
const type = this.typeChecker.getTypeAtLocation(node);
109+
if (type && !(type.flags & (ts.TypeFlags.TypeParameter))) {
110+
this.processType(type);
111+
}
112+
}
81113
}
82114
}
83115

@@ -128,9 +160,12 @@ function generateProtocolFile(protocolTs: string, typeScriptServicesDts: string)
128160
if (extraDeclarations) {
129161
protocolDts += extraDeclarations;
130162
}
163+
protocolDts += "\nimport protocol = ts.server.protocol;";
164+
protocolDts += "\nexport = protocol;";
165+
protocolDts += "\nexport as namespace protocol;";
131166
// do sanity check and try to compile generated text as standalone program
132167
const sanityCheckProgram = getProgramWithProtocolText(protocolDts, /*includeTypeScriptServices*/ false);
133-
const diagnostics = [...program.getSyntacticDiagnostics(), ...program.getSemanticDiagnostics(), ...program.getGlobalDiagnostics()];
168+
const diagnostics = [...sanityCheckProgram.getSyntacticDiagnostics(), ...sanityCheckProgram.getSemanticDiagnostics(), ...sanityCheckProgram.getGlobalDiagnostics()];
134169
if (diagnostics.length) {
135170
const flattenedDiagnostics = diagnostics.map(d => ts.flattenDiagnosticMessageText(d.messageText, "\n")).join("\n");
136171
throw new Error(`Unexpected errors during sanity check: ${flattenedDiagnostics}`);

src/compiler/binder.ts

+31-9
Original file line numberDiff line numberDiff line change
@@ -984,24 +984,44 @@ namespace ts {
984984
}
985985

986986
function bindTryStatement(node: TryStatement): void {
987-
const postFinallyLabel = createBranchLabel();
987+
const preFinallyLabel = createBranchLabel();
988988
const preTryFlow = currentFlow;
989989
// TODO: Every statement in try block is potentially an exit point!
990990
bind(node.tryBlock);
991-
addAntecedent(postFinallyLabel, currentFlow);
991+
addAntecedent(preFinallyLabel, currentFlow);
992+
993+
const flowAfterTry = currentFlow;
994+
let flowAfterCatch = unreachableFlow;
995+
992996
if (node.catchClause) {
993997
currentFlow = preTryFlow;
994998
bind(node.catchClause);
995-
addAntecedent(postFinallyLabel, currentFlow);
999+
addAntecedent(preFinallyLabel, currentFlow);
1000+
1001+
flowAfterCatch = currentFlow;
9961002
}
9971003
if (node.finallyBlock) {
998-
currentFlow = preTryFlow;
1004+
// in finally flow is combined from pre-try/flow from try/flow from catch
1005+
// pre-flow is necessary to make sure that finally is reachable even if finally flows in both try and finally blocks are unreachable
1006+
addAntecedent(preFinallyLabel, preTryFlow);
1007+
currentFlow = finishFlowLabel(preFinallyLabel);
9991008
bind(node.finallyBlock);
1009+
// if flow after finally is unreachable - keep it
1010+
// otherwise check if flows after try and after catch are unreachable
1011+
// if yes - convert current flow to unreachable
1012+
// i.e.
1013+
// try { return "1" } finally { console.log(1); }
1014+
// console.log(2); // this line should be unreachable even if flow falls out of finally block
1015+
if (!(currentFlow.flags & FlowFlags.Unreachable)) {
1016+
if ((flowAfterTry.flags & FlowFlags.Unreachable) && (flowAfterCatch.flags & FlowFlags.Unreachable)) {
1017+
currentFlow = flowAfterTry === reportedUnreachableFlow || flowAfterCatch === reportedUnreachableFlow
1018+
? reportedUnreachableFlow
1019+
: unreachableFlow;
1020+
}
1021+
}
10001022
}
1001-
// if try statement has finally block and flow after finally block is unreachable - keep it
1002-
// otherwise use whatever flow was accumulated at postFinallyLabel
1003-
if (!node.finallyBlock || !(currentFlow.flags & FlowFlags.Unreachable)) {
1004-
currentFlow = finishFlowLabel(postFinallyLabel);
1023+
else {
1024+
currentFlow = finishFlowLabel(preFinallyLabel);
10051025
}
10061026
}
10071027

@@ -2051,7 +2071,9 @@ namespace ts {
20512071
function setCommonJsModuleIndicator(node: Node) {
20522072
if (!file.commonJsModuleIndicator) {
20532073
file.commonJsModuleIndicator = node;
2054-
bindSourceFileAsExternalModule();
2074+
if (!file.externalModuleIndicator) {
2075+
bindSourceFileAsExternalModule();
2076+
}
20552077
}
20562078
}
20572079

src/compiler/checker.ts

+51-20
Original file line numberDiff line numberDiff line change
@@ -3152,8 +3152,7 @@ namespace ts {
31523152
// Use contextual parameter type if one is available
31533153
let type: Type;
31543154
if (declaration.symbol.name === "this") {
3155-
const thisParameter = getContextualThisParameter(func);
3156-
type = thisParameter ? getTypeOfSymbol(thisParameter) : undefined;
3155+
type = getContextualThisParameterType(func);
31573156
}
31583157
else {
31593158
type = getContextuallyTypedParameterType(<ParameterDeclaration>declaration);
@@ -4785,9 +4784,6 @@ namespace ts {
47854784
if (isJSConstructSignature) {
47864785
minArgumentCount--;
47874786
}
4788-
if (!thisParameter && isObjectLiteralMethod(declaration)) {
4789-
thisParameter = getContextualThisParameter(declaration);
4790-
}
47914787

47924788
const classType = declaration.kind === SyntaxKind.Constructor ?
47934789
getDeclaredTypeOfClassOrInterface(getMergedSymbol((<ClassDeclaration>declaration.parent).symbol))
@@ -6096,9 +6092,24 @@ namespace ts {
60966092
}
60976093

60986094
function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration) {
6099-
const areAllParametersUntyped = !forEach(node.parameters, p => p.type);
6100-
const isNullaryArrow = node.kind === SyntaxKind.ArrowFunction && !node.parameters.length;
6101-
return !node.typeParameters && areAllParametersUntyped && !isNullaryArrow;
6095+
// Functions with type parameters are not context sensitive.
6096+
if (node.typeParameters) {
6097+
return false;
6098+
}
6099+
// Functions with any parameters that lack type annotations are context sensitive.
6100+
if (forEach(node.parameters, p => !p.type)) {
6101+
return true;
6102+
}
6103+
// For arrow functions we now know we're not context sensitive.
6104+
if (node.kind === SyntaxKind.ArrowFunction) {
6105+
return false;
6106+
}
6107+
// If the first parameter is not an explicit 'this' parameter, then the function has
6108+
// an implicit 'this' parameter which is subject to contextual typing. Otherwise we
6109+
// know that all parameters (including 'this') have type annotations and nothing is
6110+
// subject to contextual typing.
6111+
const parameter = firstOrUndefined(node.parameters);
6112+
return !(parameter && parameterIsThisKeyword(parameter));
61026113
}
61036114

61046115
function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | ArrowFunction | MethodDeclaration {
@@ -9641,7 +9652,7 @@ namespace ts {
96419652
}
96429653
}
96439654

9644-
const thisType = getThisTypeOfDeclaration(container);
9655+
const thisType = getThisTypeOfDeclaration(container) || getContextualThisParameterType(container);
96459656
if (thisType) {
96469657
return thisType;
96479658
}
@@ -9881,14 +9892,16 @@ namespace ts {
98819892
}
98829893
}
98839894

9884-
function getContextualThisParameter(func: FunctionLikeDeclaration): Symbol {
9895+
function getContextualThisParameterType(func: FunctionLikeDeclaration): Type {
98859896
if (isContextSensitiveFunctionOrObjectLiteralMethod(func) && func.kind !== SyntaxKind.ArrowFunction) {
98869897
const contextualSignature = getContextualSignature(func);
98879898
if (contextualSignature) {
9888-
return contextualSignature.thisParameter;
9899+
const thisParameter = contextualSignature.thisParameter;
9900+
if (thisParameter) {
9901+
return getTypeOfSymbol(thisParameter);
9902+
}
98899903
}
98909904
}
9891-
98929905
return undefined;
98939906
}
98949907

@@ -12804,7 +12817,10 @@ namespace ts {
1280412817
}
1280512818

1280612819
// In JavaScript files, calls to any identifier 'require' are treated as external module imports
12807-
if (isInJavaScriptFile(node) && isRequireCall(node, /*checkArgumentIsStringLiteral*/true)) {
12820+
if (isInJavaScriptFile(node) &&
12821+
isRequireCall(node, /*checkArgumentIsStringLiteral*/true) &&
12822+
// Make sure require is not a local function
12823+
!resolveName(node.expression, (<Identifier>node.expression).text, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined)) {
1280812824
return resolveExternalModuleTypeByLiteral(<StringLiteral>node.arguments[0]);
1280912825
}
1281012826

@@ -12853,21 +12869,36 @@ namespace ts {
1285312869

1285412870
function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper) {
1285512871
const len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
12872+
if (isInferentialContext(mapper)) {
12873+
for (let i = 0; i < len; i++) {
12874+
const declaration = <ParameterDeclaration>signature.parameters[i].valueDeclaration;
12875+
if (declaration.type) {
12876+
inferTypes(mapper.context, getTypeFromTypeNode(declaration.type), getTypeAtPosition(context, i));
12877+
}
12878+
}
12879+
}
1285612880
if (context.thisParameter) {
12857-
if (!signature.thisParameter) {
12858-
signature.thisParameter = createTransientSymbol(context.thisParameter, undefined);
12881+
const parameter = signature.thisParameter;
12882+
if (!parameter || parameter.valueDeclaration && !(<ParameterDeclaration>parameter.valueDeclaration).type) {
12883+
if (!parameter) {
12884+
signature.thisParameter = createTransientSymbol(context.thisParameter, undefined);
12885+
}
12886+
assignTypeToParameterAndFixTypeParameters(signature.thisParameter, getTypeOfSymbol(context.thisParameter), mapper);
1285912887
}
12860-
assignTypeToParameterAndFixTypeParameters(signature.thisParameter, getTypeOfSymbol(context.thisParameter), mapper);
1286112888
}
1286212889
for (let i = 0; i < len; i++) {
1286312890
const parameter = signature.parameters[i];
12864-
const contextualParameterType = getTypeAtPosition(context, i);
12865-
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
12891+
if (!(<ParameterDeclaration>parameter.valueDeclaration).type) {
12892+
const contextualParameterType = getTypeAtPosition(context, i);
12893+
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
12894+
}
1286612895
}
1286712896
if (signature.hasRestParameter && isRestParameterIndex(context, signature.parameters.length - 1)) {
1286812897
const parameter = lastOrUndefined(signature.parameters);
12869-
const contextualParameterType = getTypeOfSymbol(lastOrUndefined(context.parameters));
12870-
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
12898+
if (!(<ParameterDeclaration>parameter.valueDeclaration).type) {
12899+
const contextualParameterType = getTypeOfSymbol(lastOrUndefined(context.parameters));
12900+
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
12901+
}
1287112902
}
1287212903
}
1287312904

src/compiler/transformer.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
/// <reference path="transformers/es2016.ts" />
66
/// <reference path="transformers/es2015.ts" />
77
/// <reference path="transformers/generators.ts" />
8+
/// <reference path="transformers/es5.ts" />
89
/// <reference path="transformers/module/module.ts" />
910
/// <reference path="transformers/module/system.ts" />
1011
/// <reference path="transformers/module/es2015.ts" />
@@ -129,6 +130,10 @@ namespace ts {
129130
transformers.push(transformGenerators);
130131
}
131132

133+
if (languageVersion < ScriptTarget.ES5) {
134+
transformers.push(transformES5);
135+
}
136+
132137
return transformers;
133138
}
134139

@@ -346,4 +351,4 @@ namespace ts {
346351
return statements;
347352
}
348353
}
349-
}
354+
}

0 commit comments

Comments
 (0)