Skip to content

Commit 7fd2a2b

Browse files
Merge branch 'master' into refactorSignatureRelatability
2 parents bae09d5 + 36b3937 commit 7fd2a2b

File tree

109 files changed

+3330
-1071
lines changed

Some content is hidden

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

109 files changed

+3330
-1071
lines changed

Jakefile.js

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -108,17 +108,6 @@ var serverCoreSources = [
108108
return path.join(serverDirectory, f);
109109
});
110110

111-
var scriptSources = [
112-
"tslint/booleanTriviaRule.ts",
113-
"tslint/nextLineRule.ts",
114-
"tslint/noNullRule.ts",
115-
"tslint/preferConstRule.ts",
116-
"tslint/typeOperatorSpacingRule.ts",
117-
"tslint/noInOperatorRule.ts"
118-
].map(function (f) {
119-
return path.join(scriptsDirectory, f);
120-
});
121-
122111
var serverSources = serverCoreSources.concat(servicesSources);
123112

124113
var languageServiceLibrarySources = [
@@ -878,7 +867,8 @@ var tslintRules = ([
878867
"preferConstRule",
879868
"booleanTriviaRule",
880869
"typeOperatorSpacingRule",
881-
"noInOperatorRule"
870+
"noInOperatorRule",
871+
"noIncrementDecrementRule"
882872
]);
883873
var tslintRulesFiles = tslintRules.map(function(p) {
884874
return path.join(tslintRuleDir, p + ".ts");
@@ -921,11 +911,20 @@ function lintFileAsync(options, path, cb) {
921911
});
922912
}
923913

914+
var servicesLintTargets = [
915+
"navigateTo.ts",
916+
"outliningElementsCollector.ts",
917+
"patternMatcher.ts",
918+
"services.ts",
919+
"shims.ts",
920+
].map(function (s) {
921+
return path.join(servicesDirectory, s);
922+
});
924923
var lintTargets = compilerSources
925924
.concat(harnessCoreSources)
926925
.concat(serverCoreSources)
927-
.concat(scriptSources)
928-
.concat([path.join(servicesDirectory, "services.ts")]);
926+
.concat(tslintRulesFiles)
927+
.concat(servicesLintTargets);
929928

930929
desc("Runs tslint on the compiler sources");
931930
task("lint", ["build-rules"], function() {
Binary file not shown.
Binary file not shown.
5.36 KB
Binary file not shown.
58 KB
Binary file not shown.

doc/spec.md

Lines changed: 204 additions & 106 deletions
Large diffs are not rendered by default.

scripts/tslint/booleanTriviaRule.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ class BooleanTriviaWalker extends Lint.RuleWalker {
2626
for (let index = 0; index < targetParameters.length; index++) {
2727
const param = targetParameters[index];
2828
const arg = node.arguments[index];
29-
if (!(arg && param)) continue;
29+
if (!(arg && param)) {
30+
continue;
31+
}
3032

3133
const argType = this.checker.getContextualType(arg);
3234
if (argType && (argType.getFlags() & ts.TypeFlags.Boolean)) {
@@ -38,7 +40,9 @@ class BooleanTriviaWalker extends Lint.RuleWalker {
3840
if (ranges && ranges.length === 1 && ranges[0].kind === ts.SyntaxKind.MultiLineCommentTrivia) {
3941
triviaContent = arg.getFullText().slice(ranges[0].pos + 2, ranges[0].end - 2); // +/-2 to remove /**/
4042
}
41-
if (triviaContent !== param.getName()) {
43+
44+
const paramName = param.getName();
45+
if (triviaContent !== paramName && triviaContent !== paramName + ":") {
4246
this.addFailure(this.createFailure(arg.getStart(source), arg.getWidth(source), Rule.FAILURE_STRING_FACTORY(param.getName(), triviaContent)));
4347
}
4448
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import * as Lint from "tslint/lib/lint";
2+
import * as ts from "typescript";
3+
4+
5+
export class Rule extends Lint.Rules.AbstractRule {
6+
public static POSTFIX_FAILURE_STRING = "Don't use '++' or '--' postfix operators outside statements or for loops.";
7+
public static PREFIX_FAILURE_STRING = "Don't use '++' or '--' prefix operators.";
8+
9+
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
10+
return this.applyWithWalker(new IncrementDecrementWalker(sourceFile, this.getOptions()));
11+
}
12+
}
13+
14+
class IncrementDecrementWalker extends Lint.RuleWalker {
15+
16+
visitPostfixUnaryExpression(node: ts.PostfixUnaryExpression) {
17+
super.visitPostfixUnaryExpression(node);
18+
if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator == ts.SyntaxKind.MinusMinusToken) {
19+
this.visitIncrementDecrement(node);
20+
}
21+
}
22+
23+
visitPrefixUnaryExpression(node: ts.PrefixUnaryExpression) {
24+
super.visitPrefixUnaryExpression(node);
25+
if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator == ts.SyntaxKind.MinusMinusToken) {
26+
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.PREFIX_FAILURE_STRING));
27+
}
28+
}
29+
30+
visitIncrementDecrement(node: ts.UnaryExpression) {
31+
if (node.parent && (node.parent.kind === ts.SyntaxKind.ExpressionStatement ||
32+
node.parent.kind === ts.SyntaxKind.ForStatement)) {
33+
return;
34+
}
35+
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.POSTFIX_FAILURE_STRING));
36+
}
37+
}

src/compiler/checker.ts

Lines changed: 47 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,19 @@ namespace ts {
77
let nextMergeId = 1;
88

99
export function getNodeId(node: Node): number {
10-
if (!node.id) node.id = nextNodeId++;
10+
if (!node.id) {
11+
node.id = nextNodeId;
12+
nextNodeId++;
13+
}
1114
return node.id;
1215
}
1316

1417
export let checkTime = 0;
1518

1619
export function getSymbolId(symbol: Symbol): number {
1720
if (!symbol.id) {
18-
symbol.id = nextSymbolId++;
21+
symbol.id = nextSymbolId;
22+
nextSymbolId++;
1923
}
2024

2125
return symbol.id;
@@ -287,7 +291,10 @@ namespace ts {
287291
}
288292

289293
function recordMergedSymbol(target: Symbol, source: Symbol) {
290-
if (!source.mergeId) source.mergeId = nextMergeId++;
294+
if (!source.mergeId) {
295+
source.mergeId = nextMergeId;
296+
nextMergeId++;
297+
}
291298
mergedSymbols[source.mergeId] = target;
292299
}
293300

@@ -1267,7 +1274,8 @@ namespace ts {
12671274

12681275
function createType(flags: TypeFlags): Type {
12691276
const result = new Type(checker, flags);
1270-
result.id = typeCount++;
1277+
result.id = typeCount;
1278+
typeCount++;
12711279
return result;
12721280
}
12731281

@@ -1823,11 +1831,13 @@ namespace ts {
18231831
}
18241832
if (pos < end) {
18251833
writePunctuation(writer, SyntaxKind.LessThanToken);
1826-
writeType(typeArguments[pos++], TypeFormatFlags.None);
1834+
writeType(typeArguments[pos], TypeFormatFlags.None);
1835+
pos++;
18271836
while (pos < end) {
18281837
writePunctuation(writer, SyntaxKind.CommaToken);
18291838
writeSpace(writer);
1830-
writeType(typeArguments[pos++], TypeFormatFlags.None);
1839+
writeType(typeArguments[pos], TypeFormatFlags.None);
1840+
pos++;
18311841
}
18321842
writePunctuation(writer, SyntaxKind.GreaterThanToken);
18331843
}
@@ -5636,7 +5646,7 @@ namespace ts {
56365646
return Ternary.False;
56375647
}
56385648
let result = Ternary.True;
5639-
for (let i = 0, len = sourceSignatures.length; i < len; ++i) {
5649+
for (let i = 0, len = sourceSignatures.length; i < len; i++) {
56405650
const related = compareSignaturesIdentical(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreReturnTypes*/ false, isRelatedTo);
56415651
if (!related) {
56425652
return Ternary.False;
@@ -7312,6 +7322,12 @@ namespace ts {
73127322
}
73137323
return type;
73147324
}
7325+
else if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.CommaToken) {
7326+
if (node === binaryExpression.right) {
7327+
return getContextualType(binaryExpression);
7328+
}
7329+
}
7330+
73157331
return undefined;
73167332
}
73177333

@@ -7424,24 +7440,22 @@ namespace ts {
74247440
return node === conditional.whenTrue || node === conditional.whenFalse ? getContextualType(conditional) : undefined;
74257441
}
74267442

7427-
function getContextualTypeForJsxExpression(expr: JsxExpression | JsxSpreadAttribute): Type {
7428-
// Contextual type only applies to JSX expressions that are in attribute assignments (not in 'Children' positions)
7429-
if (expr.parent.kind === SyntaxKind.JsxAttribute) {
7430-
const attrib = <JsxAttribute>expr.parent;
7431-
const attrsType = getJsxElementAttributesType(<JsxOpeningLikeElement>attrib.parent);
7443+
function getContextualTypeForJsxAttribute(attribute: JsxAttribute | JsxSpreadAttribute) {
7444+
const kind = attribute.kind;
7445+
const jsxElement = attribute.parent as JsxOpeningLikeElement;
7446+
const attrsType = getJsxElementAttributesType(jsxElement);
7447+
7448+
if (attribute.kind === SyntaxKind.JsxAttribute) {
74327449
if (!attrsType || isTypeAny(attrsType)) {
74337450
return undefined;
74347451
}
7435-
else {
7436-
return getTypeOfPropertyOfType(attrsType, attrib.name.text);
7437-
}
7452+
return getTypeOfPropertyOfType(attrsType, (attribute as JsxAttribute).name.text);
74387453
}
7439-
7440-
if (expr.kind === SyntaxKind.JsxSpreadAttribute) {
7441-
return getJsxElementAttributesType(<JsxOpeningLikeElement>expr.parent);
7454+
else if (attribute.kind === SyntaxKind.JsxSpreadAttribute) {
7455+
return attrsType;
74427456
}
74437457

7444-
return undefined;
7458+
Debug.fail(`Expected JsxAttribute or JsxSpreadAttribute, got ts.SyntaxKind[${kind}]`);
74457459
}
74467460

74477461
// Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily
@@ -7509,8 +7523,10 @@ namespace ts {
75097523
case SyntaxKind.ParenthesizedExpression:
75107524
return getContextualType(<ParenthesizedExpression>parent);
75117525
case SyntaxKind.JsxExpression:
7526+
return getContextualType(<JsxExpression>parent);
7527+
case SyntaxKind.JsxAttribute:
75127528
case SyntaxKind.JsxSpreadAttribute:
7513-
return getContextualTypeForJsxExpression(<JsxExpression>parent);
7529+
return getContextualTypeForJsxAttribute(<JsxAttribute | JsxSpreadAttribute>parent);
75147530
}
75157531
return undefined;
75167532
}
@@ -7898,31 +7914,12 @@ namespace ts {
78987914
return jsxElementType || anyType;
78997915
}
79007916

7901-
function tagNamesAreEquivalent(lhs: EntityName, rhs: EntityName): boolean {
7902-
if (lhs.kind !== rhs.kind) {
7903-
return false;
7904-
}
7905-
7906-
if (lhs.kind === SyntaxKind.Identifier) {
7907-
return (<Identifier>lhs).text === (<Identifier>rhs).text;
7908-
}
7909-
7910-
return (<QualifiedName>lhs).right.text === (<QualifiedName>rhs).right.text &&
7911-
tagNamesAreEquivalent((<QualifiedName>lhs).left, (<QualifiedName>rhs).left);
7912-
}
7913-
79147917
function checkJsxElement(node: JsxElement) {
79157918
// Check attributes
79167919
checkJsxOpeningLikeElement(node.openingElement);
79177920

7918-
// Check that the closing tag matches
7919-
if (!tagNamesAreEquivalent(node.openingElement.tagName, node.closingElement.tagName)) {
7920-
error(node.closingElement, Diagnostics.Expected_corresponding_JSX_closing_tag_for_0, getTextOfNode(node.openingElement.tagName));
7921-
}
7922-
else {
7923-
// Perform resolution on the closing tag so that rename/go to definition/etc work
7924-
getJsxElementTagSymbol(node.closingElement);
7925-
}
7921+
// Perform resolution on the closing tag so that rename/go to definition/etc work
7922+
getJsxElementTagSymbol(node.closingElement);
79267923

79277924
// Check children
79287925
for (const child of node.children) {
@@ -8323,14 +8320,13 @@ namespace ts {
83238320
checkGrammarJsxElement(node);
83248321
checkJsxPreconditions(node);
83258322

8326-
// If we're compiling under --jsx react, the symbol 'React' should
8327-
// be marked as 'used' so we don't incorrectly elide its import. And if there
8328-
// is no 'React' symbol in scope, we should issue an error.
8329-
if (compilerOptions.jsx === JsxEmit.React) {
8330-
const reactSym = resolveName(node.tagName, "React", SymbolFlags.Value, Diagnostics.Cannot_find_name_0, "React");
8331-
if (reactSym) {
8332-
getSymbolLinks(reactSym).referenced = true;
8333-
}
8323+
// The reactNamespace symbol should be marked as 'used' so we don't incorrectly elide its import. And if there
8324+
// is no reactNamespace symbol in scope when targeting React emit, we should issue an error.
8325+
const reactRefErr = compilerOptions.jsx === JsxEmit.React ? Diagnostics.Cannot_find_name_0 : undefined;
8326+
const reactNamespace = compilerOptions.reactNamespace ? compilerOptions.reactNamespace : "React";
8327+
const reactSym = resolveName(node.tagName, reactNamespace, SymbolFlags.Value, reactRefErr, reactNamespace);
8328+
if (reactSym) {
8329+
getSymbolLinks(reactSym).referenced = true;
83348330
}
83358331

83368332
const targetAttributesType = getJsxElementAttributesType(node);
@@ -13801,7 +13797,8 @@ namespace ts {
1380113797
}
1380213798

1380313799
if (autoValue !== undefined) {
13804-
getNodeLinks(member).enumMemberValue = autoValue++;
13800+
getNodeLinks(member).enumMemberValue = autoValue;
13801+
autoValue++;
1380513802
}
1380613803
}
1380713804

src/compiler/commandLineParser.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ namespace ts {
5454
description: Diagnostics.Specify_JSX_code_generation_Colon_preserve_or_react,
5555
error: Diagnostics.Argument_for_jsx_must_be_preserve_or_react
5656
},
57+
{
58+
name: "reactNamespace",
59+
type: "string",
60+
description: Diagnostics.Specifies_the_object_invoked_for_createElement_and_spread_when_targeting_react_JSX_emit
61+
},
5762
{
5863
name: "listFiles",
5964
type: "boolean",
@@ -334,7 +339,8 @@ namespace ts {
334339
function parseStrings(args: string[]) {
335340
let i = 0;
336341
while (i < args.length) {
337-
let s = args[i++];
342+
let s = args[i];
343+
i++;
338344
if (s.charCodeAt(0) === CharacterCodes.at) {
339345
parseResponseFile(s.slice(1));
340346
}
@@ -356,18 +362,21 @@ namespace ts {
356362

357363
switch (opt.type) {
358364
case "number":
359-
options[opt.name] = parseInt(args[i++]);
365+
options[opt.name] = parseInt(args[i]);
366+
i++;
360367
break;
361368
case "boolean":
362369
options[opt.name] = true;
363370
break;
364371
case "string":
365-
options[opt.name] = args[i++] || "";
372+
options[opt.name] = args[i] || "";
373+
i++;
366374
break;
367375
// If not a primitive, the possible types are specified in what is effectively a map of options.
368376
default:
369377
let map = <Map<number>>opt.type;
370-
let key = (args[i++] || "").toLowerCase();
378+
let key = (args[i] || "").toLowerCase();
379+
i++;
371380
if (hasProperty(map, key)) {
372381
options[opt.name] = map[key];
373382
}

src/compiler/core.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,11 @@ namespace ts {
244244
const count = array.length;
245245
if (count > 0) {
246246
let pos = 0;
247-
let result = arguments.length <= 2 ? array[pos++] : initial;
247+
let result = arguments.length <= 2 ? array[pos] : initial;
248+
pos++;
248249
while (pos < count) {
249-
result = f(<U>result, array[pos++]);
250+
result = f(<U>result, array[pos]);
251+
pos++;
250252
}
251253
return <U>result;
252254
}
@@ -260,9 +262,11 @@ namespace ts {
260262
if (array) {
261263
let pos = array.length - 1;
262264
if (pos >= 0) {
263-
let result = arguments.length <= 2 ? array[pos--] : initial;
265+
let result = arguments.length <= 2 ? array[pos] : initial;
266+
pos--;
264267
while (pos >= 0) {
265-
result = f(<U>result, array[pos--]);
268+
result = f(<U>result, array[pos]);
269+
pos--;
266270
}
267271
return <U>result;
268272
}

src/compiler/declarationEmitter.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,8 @@ namespace ts {
501501
}
502502
let count = 0;
503503
while (true) {
504-
const name = baseName + "_" + (++count);
504+
count++;
505+
const name = baseName + "_" + count;
505506
if (!hasProperty(currentIdentifiers, name)) {
506507
return name;
507508
}

0 commit comments

Comments
 (0)