Skip to content

Commit 4ccf630

Browse files
committed
merge with master
2 parents d57ceb1 + c05297c commit 4ccf630

File tree

1,072 files changed

+16372
-8288
lines changed

Some content is hidden

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

1,072 files changed

+16372
-8288
lines changed

.gitignore

+5-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ tests/services/baselines/local/*
2121
tests/baselines/prototyping/local/*
2222
tests/baselines/rwc/*
2323
tests/baselines/test262/*
24-
tests/baselines/reference/projectOutput/*
24+
tests/baselines/reference/projectOutput/*
2525
tests/baselines/local/projectOutput/*
2626
tests/services/baselines/prototyping/local/*
2727
tests/services/browser/typescriptServices.js
@@ -30,6 +30,7 @@ scripts/processDiagnosticMessages.d.ts
3030
scripts/processDiagnosticMessages.js
3131
scripts/importDefinitelyTypedTests/importDefinitelyTypedTests.js
3232
src/harness/*.js
33+
src/compiler/diagnosticInformationMap.generated.ts
3334
rwc-report.html
3435
*.swp
3536
build.json
@@ -49,5 +50,6 @@ scripts/typings/
4950
coverage/
5051
internal/
5152
**/.DS_Store
52-
.settings/*
53-
!.settings/tasks.json
53+
.settings
54+
.vscode/*
55+
!.vscode/tasks.json

.npmignore

+7-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ doc
33
scripts
44
src
55
tests
6-
Jakefile
6+
internal
7+
tslint.json
8+
Jakefile.js
9+
.editorconfig
10+
.gitattributes
11+
.settings/
712
.travis.yml
8-
.settings/
13+
.vscode/

.vscode/tasks.json

+19
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,25 @@
1818
"problemMatcher": [
1919
"$tsc"
2020
]
21+
},
22+
{
23+
"taskName": "lint-server",
24+
"args": [],
25+
"problemMatcher": {
26+
"owner": "typescript",
27+
"fileLocation": ["relative", "${workspaceRoot}"],
28+
"pattern": {
29+
"regexp": "^(warning|error)\\s+([^(]+)\\s+\\((\\d+|\\d+,\\d+|\\d+,\\d+,\\d+,\\d+)\\):\\s+(.*)$",
30+
"severity": 1,
31+
"file": 2,
32+
"location": 3,
33+
"message": 4
34+
},
35+
"watchedTaskBeginsRegExp": "^\\*\\*\\*Lint failure\\*\\*\\*$",
36+
"watchedTaskEndsRegExp": "^\\*\\*\\* Total \\d+ failures\\.$"
37+
},
38+
"showOutput": "always",
39+
"isWatching": true
2140
}
2241
]
2342
}

CONTRIBUTING.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Design changes will not be accepted at this time. If you have a design change pr
99
## Legal
1010
You will need to complete a Contributor License Agreement (CLA). Briefly, this agreement testifies that you are granting us permission to use the submitted change according to the terms of the project's license, and that the work being submitted is under appropriate copyright.
1111

12-
Please submit a Contributor License Agreement (CLA) before submitting a pull request. You may visit https://cla.microsoft.com to sign digitally. Alternatively, download the agreement ([Microsoft Contribution License Agreement.docx](https://www.codeplex.com/Download?ProjectName=typescript&DownloadId=822190) or [Microsoft Contribution License Agreement.pdf](https://www.codeplex.com/Download?ProjectName=typescript&DownloadId=921298)), sign, scan, and email it back to <[email protected]>. Be sure to include your github user name along with the agreement. Once we have received the signed CLA, we'll review the request. Please note that we're currently only accepting pull requests of bug fixes rather than new features.
12+
Please submit a Contributor License Agreement (CLA) before submitting a pull request. You may visit https://cla.microsoft.com to sign digitally. Alternatively, download the agreement ([Microsoft Contribution License Agreement.docx](https://www.codeplex.com/Download?ProjectName=typescript&DownloadId=822190) or [Microsoft Contribution License Agreement.pdf](https://www.codeplex.com/Download?ProjectName=typescript&DownloadId=921298)), sign, scan, and email it back to <[email protected]>. Be sure to include your github user name along with the agreement. Once we have received the signed CLA, we'll review the request.
1313

1414
## Housekeeping
1515
Your pull request should:

Jakefile.js

+96-16
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ var fs = require("fs");
44
var os = require("os");
55
var path = require("path");
66
var child_process = require("child_process");
7+
var Linter = require("tslint");
78

89
// Variables
910
var compilerDirectory = "src/compiler/";
@@ -627,10 +628,9 @@ function deleteTemporaryProjectOutput() {
627628

628629
var testTimeout = 20000;
629630
desc("Runs the tests using the built run.js file. Syntax is jake runtests. Optional parameters 'host=', 'tests=[regex], reporter=[list|spec|json|<more>]', debug=true.");
630-
task("runtests", ["tests", builtLocalDirectory], function() {
631+
task("runtests", ["build-rules", "tests", builtLocalDirectory], function() {
631632
cleanTestDirs();
632633
var debug = process.env.debug || process.env.d;
633-
host = "mocha"
634634
tests = process.env.test || process.env.tests || process.env.t;
635635
var light = process.env.light || false;
636636
var testConfigFile = 'test.config';
@@ -652,9 +652,16 @@ task("runtests", ["tests", builtLocalDirectory], function() {
652652
reporter = process.env.reporter || process.env.r || 'mocha-fivemat-progress-reporter';
653653
// timeout normally isn't necessary but Travis-CI has been timing out on compiler baselines occasionally
654654
// default timeout is 2sec which really should be enough, but maybe we just need a small amount longer
655-
var cmd = host + (debug ? " --debug-brk" : "") + " -R " + reporter + tests + colors + ' -t ' + testTimeout + ' ' + run;
655+
var cmd = "mocha" + (debug ? " --debug-brk" : "") + " -R " + reporter + tests + colors + ' -t ' + testTimeout + ' ' + run;
656656
console.log(cmd);
657-
exec(cmd, deleteTemporaryProjectOutput);
657+
exec(cmd, function() {
658+
deleteTemporaryProjectOutput();
659+
var lint = jake.Task['lint'];
660+
lint.addListener('complete', function () {
661+
complete();
662+
});
663+
lint.invoke();
664+
});
658665
}, {async: true});
659666

660667
desc("Generates code coverage data via instanbul");
@@ -812,7 +819,6 @@ task("update-sublime", ["local", serverFile], function() {
812819
var tslintRuleDir = "scripts/tslint";
813820
var tslintRules = ([
814821
"nextLineRule",
815-
"noInferrableTypesRule",
816822
"noNullRule",
817823
"booleanTriviaRule"
818824
]);
@@ -825,20 +831,94 @@ var tslintRulesOutFiles = tslintRules.map(function(p) {
825831
desc("Compiles tslint rules to js");
826832
task("build-rules", tslintRulesOutFiles);
827833
tslintRulesFiles.forEach(function(ruleFile, i) {
828-
compileFile(tslintRulesOutFiles[i], [ruleFile], [ruleFile], [], /*useBuiltCompiler*/ true, /*noOutFile*/ true, /*generateDeclarations*/ false, path.join(builtLocalDirectory, "tslint"));
834+
compileFile(tslintRulesOutFiles[i], [ruleFile], [ruleFile], [], /*useBuiltCompiler*/ false, /*noOutFile*/ true, /*generateDeclarations*/ false, path.join(builtLocalDirectory, "tslint"));
829835
});
830836

831-
// if the codebase were free of linter errors we could make jake runtests
832-
// run this task automatically
837+
function getLinterOptions() {
838+
return {
839+
configuration: require("./tslint.json"),
840+
formatter: "prose",
841+
formattersDirectory: undefined,
842+
rulesDirectory: "built/local/tslint"
843+
};
844+
}
845+
846+
function lintFileContents(options, path, contents) {
847+
var ll = new Linter(path, contents, options);
848+
return ll.lint();
849+
}
850+
851+
function lintFile(options, path) {
852+
var contents = fs.readFileSync(path, "utf8");
853+
return lintFileContents(options, path, contents);
854+
}
855+
856+
function lintFileAsync(options, path, cb) {
857+
fs.readFile(path, "utf8", function(err, contents) {
858+
if (err) {
859+
return cb(err);
860+
}
861+
var result = lintFileContents(options, path, contents);
862+
cb(undefined, result);
863+
});
864+
}
865+
866+
var lintTargets = compilerSources.concat(harnessCoreSources);
867+
833868
desc("Runs tslint on the compiler sources");
834869
task("lint", ["build-rules"], function() {
835-
function success(f) { return function() { console.log('SUCCESS: No linter errors in ' + f + '\n'); }};
836-
function failure(f) { return function() { console.log('FAILURE: Please fix linting errors in ' + f + '\n') }};
837-
838-
var lintTargets = compilerSources.concat(harnessCoreSources);
870+
var lintOptions = getLinterOptions();
839871
for (var i in lintTargets) {
840-
var f = lintTargets[i];
841-
var cmd = 'tslint --rules-dir built/local/tslint -c tslint.json ' + f;
842-
exec(cmd, success(f), failure(f));
872+
var result = lintFile(lintOptions, lintTargets[i]);
873+
if (result.failureCount > 0) {
874+
console.log(result.output);
875+
fail('Linter errors.', result.failureCount);
876+
}
843877
}
844-
}, { async: true });
878+
});
879+
880+
/**
881+
* This is required because file watches on Windows get fires _twice_
882+
* when a file changes on some node/windows version configuations
883+
* (node v4 and win 10, for example). By not running a lint for a file
884+
* which already has a pending lint, we avoid duplicating our work.
885+
* (And avoid printing duplicate results!)
886+
*/
887+
var lintSemaphores = {};
888+
889+
function lintWatchFile(filename) {
890+
fs.watch(filename, {persistent: true}, function(event) {
891+
if (event !== "change") {
892+
return;
893+
}
894+
895+
if (!lintSemaphores[filename]) {
896+
lintSemaphores[filename] = true;
897+
lintFileAsync(getLinterOptions(), filename, function(err, result) {
898+
delete lintSemaphores[filename];
899+
if (err) {
900+
console.log(err);
901+
return;
902+
}
903+
if (result.failureCount > 0) {
904+
console.log("***Lint failure***");
905+
for (var i = 0; i < result.failures.length; i++) {
906+
var failure = result.failures[i];
907+
var start = failure.startPosition.lineAndCharacter;
908+
var end = failure.endPosition.lineAndCharacter;
909+
console.log("warning " + filename + " (" + (start.line + 1) + "," + (start.character + 1) + "," + (end.line + 1) + "," + (end.character + 1) + "): " + failure.failure);
910+
}
911+
console.log("*** Total " + result.failureCount + " failures.");
912+
}
913+
});
914+
}
915+
});
916+
}
917+
918+
desc("Watches files for changes to rerun a lint pass");
919+
task("lint-server", ["build-rules"], function() {
920+
console.log("Watching ./src for changes to linted files");
921+
for (var i = 0; i < lintTargets.length; i++) {
922+
lintWatchFile(lintTargets[i]);
923+
}
924+
});

package.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@
4444
"build": "npm run build:compiler && npm run build:tests",
4545
"build:compiler": "jake local",
4646
"build:tests": "jake tests",
47-
"clean": "jake clean"
47+
"clean": "jake clean",
48+
"jake": "jake",
49+
"lint": "jake lint",
50+
"setup-hooks": "node scripts/link-hooks.js"
4851
},
4952
"browser": {
5053
"buffer": false,

scripts/hooks/post-checkout

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/sh
2+
npm run jake -- generate-diagnostics

scripts/link-hooks.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
var fs = require("fs");
2+
var path = require("path");
3+
4+
var hooks = [
5+
"post-checkout"
6+
];
7+
8+
hooks.forEach(function (hook) {
9+
var hookInSourceControl = path.resolve(__dirname, "hooks", hook);
10+
11+
if (fs.existsSync(hookInSourceControl)) {
12+
var hookInHiddenDirectory = path.resolve(__dirname, "..", ".git", "hooks", hook);
13+
14+
if (fs.existsSync(hookInHiddenDirectory)) {
15+
fs.unlinkSync(hookInHiddenDirectory);
16+
}
17+
18+
fs.linkSync(hookInSourceControl, hookInHiddenDirectory);
19+
}
20+
});

scripts/processDiagnosticMessages.ts

+36-12
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ interface InputDiagnosticMessageTable {
1010
[msg: string]: DiagnosticDetails;
1111
}
1212

13-
interface IIndexable<V> {
14-
[key: string]: V;
15-
}
16-
1713
function main(): void {
1814
var sys = ts.sys;
1915
if (sys.args.length < 1) {
@@ -25,21 +21,49 @@ function main(): void {
2521
var inputFilePath = sys.args[0].replace(/\\/g, "/");
2622
var inputStr = sys.readFile(inputFilePath);
2723

28-
var diagnosticMesages: InputDiagnosticMessageTable = JSON.parse(inputStr);
24+
var diagnosticMessages: InputDiagnosticMessageTable = JSON.parse(inputStr);
2925

30-
var names = Utilities.getObjectKeys(diagnosticMesages);
26+
var names = Utilities.getObjectKeys(diagnosticMessages);
3127
var nameMap = buildUniqueNameMap(names);
3228

33-
var infoFileOutput = buildInfoFileOutput(diagnosticMesages, nameMap);
34-
29+
var infoFileOutput = buildInfoFileOutput(diagnosticMessages, nameMap);
30+
checkForUniqueCodes(names, diagnosticMessages);
31+
3532
// TODO: Fix path joining
3633
var inputDirectory = inputFilePath.substr(0,inputFilePath.lastIndexOf("/"));
3734
var fileOutputPath = inputDirectory + "/diagnosticInformationMap.generated.ts";
3835
sys.writeFile(fileOutputPath, infoFileOutput);
3936
}
4037

41-
function buildUniqueNameMap(names: string[]): IIndexable<string> {
42-
var nameMap: IIndexable<string> = {};
38+
function checkForUniqueCodes(messages: string[], diagnosticTable: InputDiagnosticMessageTable) {
39+
const originalMessageForCode: string[] = [];
40+
let numConflicts = 0;
41+
42+
for (const currentMessage of messages) {
43+
const code = diagnosticTable[currentMessage].code;
44+
45+
if (code in originalMessageForCode) {
46+
const originalMessage = originalMessageForCode[code];
47+
ts.sys.write("\x1b[91m"); // High intensity red.
48+
ts.sys.write("Error");
49+
ts.sys.write("\x1b[0m"); // Reset formatting.
50+
ts.sys.write(`: Diagnostic code '${code}' conflicts between "${originalMessage}" and "${currentMessage}".`);
51+
ts.sys.write(ts.sys.newLine + ts.sys.newLine);
52+
53+
numConflicts++;
54+
}
55+
else {
56+
originalMessageForCode[code] = currentMessage;
57+
}
58+
}
59+
60+
if (numConflicts > 0) {
61+
throw new Error(`Found ${numConflicts} conflict(s) in diagnostic codes.`);
62+
}
63+
}
64+
65+
function buildUniqueNameMap(names: string[]): ts.Map<string> {
66+
var nameMap: ts.Map<string> = {};
4367

4468
var uniqueNames = NameGenerator.ensureUniqueness(names, /* isCaseSensitive */ false, /* isFixed */ undefined);
4569

@@ -50,7 +74,7 @@ function buildUniqueNameMap(names: string[]): IIndexable<string> {
5074
return nameMap;
5175
}
5276

53-
function buildInfoFileOutput(messageTable: InputDiagnosticMessageTable, nameMap: IIndexable<string>): string {
77+
function buildInfoFileOutput(messageTable: InputDiagnosticMessageTable, nameMap: ts.Map<string>): string {
5478
var result =
5579
'// <auto-generated />\r\n' +
5680
'/// <reference path="types.ts" />\r\n' +
@@ -172,7 +196,7 @@ module Utilities {
172196
}
173197

174198
// Like Object.keys
175-
export function getObjectKeys(obj: any): string[]{
199+
export function getObjectKeys(obj: any): string[] {
176200
var result: string[] = [];
177201

178202
for (var name in obj) {

scripts/tslint/nextLineRule.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ const OPTION_CATCH = "check-catch";
55
const OPTION_ELSE = "check-else";
66

77
export class Rule extends Lint.Rules.AbstractRule {
8-
public static CATCH_FAILURE_STRING = "'catch' should be on the line following the previous block's ending curly brace";
9-
public static ELSE_FAILURE_STRING = "'else' should be on the line following the previous block's ending curly brace";
8+
public static CATCH_FAILURE_STRING = "'catch' should not be on the same line as the preceeding block's curly brace";
9+
public static ELSE_FAILURE_STRING = "'else' should not be on the same line as the preceeding block's curly brace";
1010

1111
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
1212
return this.applyWithWalker(new NextLineWalker(sourceFile, this.getOptions()));
@@ -25,7 +25,7 @@ class NextLineWalker extends Lint.RuleWalker {
2525
if (this.hasOption(OPTION_ELSE) && !!elseKeyword) {
2626
const thenStatementEndLoc = sourceFile.getLineAndCharacterOfPosition(thenStatement.getEnd());
2727
const elseKeywordLoc = sourceFile.getLineAndCharacterOfPosition(elseKeyword.getStart(sourceFile));
28-
if (thenStatementEndLoc.line !== (elseKeywordLoc.line - 1)) {
28+
if (thenStatementEndLoc.line === elseKeywordLoc.line) {
2929
const failure = this.createFailure(elseKeyword.getStart(sourceFile), elseKeyword.getWidth(sourceFile), Rule.ELSE_FAILURE_STRING);
3030
this.addFailure(failure);
3131
}
@@ -47,7 +47,7 @@ class NextLineWalker extends Lint.RuleWalker {
4747
const catchKeyword = catchClause.getFirstToken(sourceFile);
4848
const tryClosingBraceLoc = sourceFile.getLineAndCharacterOfPosition(tryClosingBrace.getEnd());
4949
const catchKeywordLoc = sourceFile.getLineAndCharacterOfPosition(catchKeyword.getStart(sourceFile));
50-
if (tryClosingBraceLoc.line !== (catchKeywordLoc.line - 1)) {
50+
if (tryClosingBraceLoc.line === catchKeywordLoc.line) {
5151
const failure = this.createFailure(catchKeyword.getStart(sourceFile), catchKeyword.getWidth(sourceFile), Rule.CATCH_FAILURE_STRING);
5252
this.addFailure(failure);
5353
}
@@ -58,4 +58,4 @@ class NextLineWalker extends Lint.RuleWalker {
5858

5959
function getFirstChildOfKind(node: ts.Node, kind: ts.SyntaxKind) {
6060
return node.getChildren().filter((child) => child.kind === kind)[0];
61-
}
61+
}

0 commit comments

Comments
 (0)