mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge remote-tracking branch 'refs/remotes/Microsoft/master'
This commit is contained in:
+2
-1
@@ -1 +1,2 @@
|
||||
*.js linguist-language=TypeScript
|
||||
*.js linguist-language=TypeScript
|
||||
* -text
|
||||
|
||||
+9
-11
@@ -1,15 +1,5 @@
|
||||
node_modules/
|
||||
built/*
|
||||
tests/cases/*.js
|
||||
tests/cases/*/*.js
|
||||
tests/cases/*/*/*.js
|
||||
tests/cases/*/*/*/*.js
|
||||
tests/cases/*/*/*/*/*.js
|
||||
tests/cases/*.js.map
|
||||
tests/cases/*/*.js.map
|
||||
tests/cases/*/*/*.js.map
|
||||
tests/cases/*/*/*/*.js.map
|
||||
tests/cases/*/*/*/*/*.js.map
|
||||
tests/cases/rwc/*
|
||||
tests/cases/test262/*
|
||||
tests/cases/perf/*
|
||||
@@ -21,13 +11,17 @@ tests/services/baselines/local/*
|
||||
tests/baselines/prototyping/local/*
|
||||
tests/baselines/rwc/*
|
||||
tests/baselines/test262/*
|
||||
tests/baselines/reference/projectOutput/*
|
||||
tests/baselines/local/projectOutput/*
|
||||
tests/services/baselines/prototyping/local/*
|
||||
tests/services/browser/typescriptServices.js
|
||||
scripts/configureNightly.js
|
||||
scripts/processDiagnosticMessages.d.ts
|
||||
scripts/processDiagnosticMessages.js
|
||||
scripts/importDefinitelyTypedTests.js
|
||||
scripts/importDefinitelyTypedTests/importDefinitelyTypedTests.js
|
||||
src/harness/*.js
|
||||
src/compiler/diagnosticInformationMap.generated.ts
|
||||
src/compiler/diagnosticMessages.generated.json
|
||||
rwc-report.html
|
||||
*.swp
|
||||
build.json
|
||||
@@ -43,6 +37,10 @@ scripts/run.bat
|
||||
scripts/word2md.js
|
||||
scripts/ior.js
|
||||
scripts/*.js.map
|
||||
scripts/typings/
|
||||
coverage/
|
||||
internal/
|
||||
**/.DS_Store
|
||||
.settings
|
||||
.vscode/*
|
||||
!.vscode/tasks.json
|
||||
|
||||
+9
-2
@@ -1,7 +1,14 @@
|
||||
built
|
||||
doc
|
||||
lib/README.md
|
||||
scripts
|
||||
src
|
||||
tests
|
||||
Jakefile
|
||||
.travis.yml
|
||||
internal
|
||||
tslint.json
|
||||
Jakefile.js
|
||||
.editorconfig
|
||||
.gitattributes
|
||||
.settings/
|
||||
.travis.yml
|
||||
.vscode/
|
||||
+3
-1
@@ -1,6 +1,8 @@
|
||||
language: node_js
|
||||
|
||||
node_js:
|
||||
- 'stable'
|
||||
- '4'
|
||||
- '0.10'
|
||||
|
||||
sudo: false
|
||||
sudo: false
|
||||
|
||||
Vendored
+42
@@ -0,0 +1,42 @@
|
||||
// Available variables which can be used inside of strings.
|
||||
// ${workspaceRoot}: the root folder of the team
|
||||
// ${file}: the current opened file
|
||||
// ${fileBasename}: the current opened file's basename
|
||||
// ${fileDirname}: the current opened file's dirname
|
||||
// ${fileExtname}: the current opened file's extension
|
||||
// ${cwd}: the current working directory of the spawned process
|
||||
{
|
||||
"version": "0.1.0",
|
||||
"command": "jake",
|
||||
"isShellCommand": true,
|
||||
"showOutput": "silent",
|
||||
"tasks": [
|
||||
{
|
||||
"taskName": "local",
|
||||
"isBuildCommand": true,
|
||||
"showOutput": "silent",
|
||||
"problemMatcher": [
|
||||
"$tsc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"taskName": "lint-server",
|
||||
"args": [],
|
||||
"problemMatcher": {
|
||||
"owner": "typescript",
|
||||
"fileLocation": ["relative", "${workspaceRoot}"],
|
||||
"pattern": {
|
||||
"regexp": "^(warning|error)\\s+([^(]+)\\s+\\((\\d+|\\d+,\\d+|\\d+,\\d+,\\d+,\\d+)\\):\\s+(.*)$",
|
||||
"severity": 1,
|
||||
"file": 2,
|
||||
"location": 3,
|
||||
"message": 4
|
||||
},
|
||||
"watchedTaskBeginsRegExp": "^\\*\\*\\*Lint failure\\*\\*\\*$",
|
||||
"watchedTaskEndsRegExp": "^\\*\\*\\* Total \\d+ failures\\.$"
|
||||
},
|
||||
"showOutput": "always",
|
||||
"isWatching": true
|
||||
}
|
||||
]
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
TypeScript is authored by:
|
||||
|
||||
* Adam Freidin
|
||||
* Ahmad Farid
|
||||
* Anders Hejlsberg
|
||||
* Arnav Singh
|
||||
* Arthur Ozga
|
||||
* Basarat Ali Syed
|
||||
* Ben Duffield
|
||||
* Bill Ticehurst
|
||||
* Brett Mayen
|
||||
* Bryan Forbes
|
||||
* Caitlin Potter
|
||||
* Chris Bubernak
|
||||
* Colby Russell
|
||||
* Colin Snover
|
||||
* Cyrus Najmabadi
|
||||
* Dan Quirk
|
||||
* Daniel Rosenwasser
|
||||
* David Li
|
||||
* Denis Nedelyaev
|
||||
* Dick van den Brink
|
||||
* Dirk Bäumer
|
||||
* Eyas Sharaiha
|
||||
* Frank Wallis
|
||||
* Gabriel Isenberg
|
||||
* Gilad Peleg
|
||||
* Graeme Wicksted
|
||||
* Guillaume Salles
|
||||
* Harald Niesche
|
||||
* Ingvar Stepanyan
|
||||
* Ivo Gabe de Wolff
|
||||
* James Whitney
|
||||
* Jason Freeman
|
||||
* Jason Ramsay
|
||||
* Jed Mao
|
||||
* Johannes Rieken
|
||||
* John Vilk
|
||||
* Jonathan Bond-Caron
|
||||
* Jonathan Park
|
||||
* Jonathan Turner
|
||||
* Josh Kalderimis
|
||||
* Julian Williams
|
||||
* Kagami Sascha Rosylight
|
||||
* Keith Mashinter
|
||||
* Ken Howard
|
||||
* Kenji Imamula
|
||||
* Lorant Pinter
|
||||
* Martin Všetička
|
||||
* Masahiro Wakame
|
||||
* Max Deepfield
|
||||
* Micah Zoltu
|
||||
* Mohamed Hegazy
|
||||
* Nathan Shively-Sanders
|
||||
* Oleg Mihailik
|
||||
* Oleksandr Chekhovskyi
|
||||
* Paul van Brenk
|
||||
* Pedro Maltez
|
||||
* Philip Bulley
|
||||
* piloopin
|
||||
* @progre
|
||||
* Punya Biswal
|
||||
* Ron Buckton
|
||||
* Ryan Cavanaugh
|
||||
* Ryohei Ikegami
|
||||
* Sébastien Arod
|
||||
* Sheetal Nandi
|
||||
* Shengping Zhong
|
||||
* Shyyko Serhiy
|
||||
* Simon Hürlimann
|
||||
* Solal Pirelli
|
||||
* Stan Thomas
|
||||
* Steve Lucco
|
||||
* Tien Hoanhtien
|
||||
* Tingan Ho
|
||||
* togru
|
||||
* Tomas Grubliauskas
|
||||
* TruongSinh Tran-Nguyen
|
||||
* Viliv Vane
|
||||
* Vladimir Matveev
|
||||
* Wesley Wigham
|
||||
* York Yao
|
||||
* Yui Tanglertsampan
|
||||
* Zev Spitz
|
||||
* Zhengbo Li
|
||||
+133
-20
@@ -1,17 +1,63 @@
|
||||
# Instructions for Logging Issues
|
||||
|
||||
## 1. Read the FAQ
|
||||
|
||||
Please [read the FAQ](https://github.com/Microsoft/TypeScript/wiki/FAQ) before logging new issues, even if you think you have found a bug.
|
||||
|
||||
Issues that ask questions answered in the FAQ will be closed without elaboration.
|
||||
|
||||
## 2. Search for Duplicates
|
||||
|
||||
[Search the existing issues](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=is%3Aissue) before logging a new one.
|
||||
|
||||
## 3. Do you have a question?
|
||||
|
||||
The issue tracker is for **issues**, in other words, bugs and suggestions.
|
||||
If you have a *question*, please use [http://stackoverflow.com/questions/tagged/typescript](Stack Overflow), [https://gitter.im/Microsoft/TypeScript](Gitter), your favorite search engine, or other resources.
|
||||
Due to increased traffic, we can no longer answer questions in the issue tracker.
|
||||
|
||||
## 4. Did you find a bug?
|
||||
|
||||
When logging a bug, please be sure to include the following:
|
||||
* What version of TypeScript you're using (run `tsc --v`)
|
||||
* If at all possible, an *isolated* way to reproduce the behavior
|
||||
* The behavior you expect to see, and the actual behavior
|
||||
|
||||
You can try out the nightly build of TypeScript (`npm install typescript@next`) to see if the bug has already been fixed.
|
||||
|
||||
## 5. Do you have a suggestion?
|
||||
|
||||
We also accept suggestions in the issue tracker.
|
||||
Be sure to [check the FAQ](https://github.com/Microsoft/TypeScript/wiki/FAQ) and [search](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=is%3Aissue) first.
|
||||
|
||||
In general, things we find useful when reviewing suggestins are:
|
||||
* A description of the problem you're trying to solve
|
||||
* An overview of the suggested solution
|
||||
* Examples of how the suggestion would work in various places
|
||||
* Code examples showing e.g. "this would be an error, this wouldn't"
|
||||
* Code examples showing the generated JavaScript (if applicable)
|
||||
* If relevant, precedent in other languages can be useful for establishing context and expected behavior
|
||||
|
||||
# Instructions for Contributing Code
|
||||
|
||||
## Contributing bug fixes
|
||||
|
||||
TypeScript is currently accepting contributions in the form of bug fixes. A bug must have an issue tracking it in the issue tracker that has been approved ("Milestone == Community") by the TypeScript team. Your pull request should include a link to the bug that you are fixing. If you've submitted a PR for a bug, please post a comment in the bug to avoid duplication of effort.
|
||||
|
||||
## Contributing features
|
||||
|
||||
Features (things that add new or improved functionality to TypeScript) may be accepted, but will need to first be approved (marked as "Milestone == Community" by a TypeScript coordinator with the message "Approved") in the suggestion issue. Features with language design impact, or that are adequately satisfied with external tools, will not be accepted.
|
||||
|
||||
Design changes will not be accepted at this time. If you have a design change proposal, please log a suggestion issue.
|
||||
|
||||
## Legal
|
||||
|
||||
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.
|
||||
|
||||
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 <cla@microsoft.com>. 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.
|
||||
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 <cla@microsoft.com>. Be sure to include your github user name along with the agreement. Once we have received the signed CLA, we'll review the request.
|
||||
|
||||
## Housekeeping
|
||||
|
||||
Your pull request should:
|
||||
|
||||
* Include a description of what your change intends to do
|
||||
@@ -28,47 +74,114 @@ Your pull request should:
|
||||
* Follow the code conventions descriped in [Coding guidelines](https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines)
|
||||
* To avoid line ending issues, set `autocrlf = input` and `whitespace = cr-at-eol` in your git configuration
|
||||
|
||||
## Running the Tests
|
||||
To run all tests, invoke the runtests target using jake:
|
||||
## Contributing `lib.d.ts` fixes
|
||||
|
||||
The library sources are in: [src/lib](https://github.com/Microsoft/TypeScript/tree/master/src/lib)
|
||||
|
||||
`jake runtests`
|
||||
Library files in `built/local/` are updated by running
|
||||
```Shell
|
||||
jake
|
||||
```
|
||||
|
||||
The files in `lib/` are used to bootstrap compilation and usually do not need to be updated.
|
||||
|
||||
#### `src/lib/dom.generated.d.ts` and `src/lib/webworker.generated.d.ts`
|
||||
|
||||
These two files represent the DOM typings and are auto-generated. To make any modifications to them, please submit a PR to https://github.com/Microsoft/TSJS-lib-generator
|
||||
|
||||
## Running the Tests
|
||||
|
||||
To run all tests, invoke the `runtests` target using jake:
|
||||
|
||||
```Shell
|
||||
jake runtests
|
||||
```
|
||||
|
||||
This run will all tests; to run only a specific subset of tests, use:
|
||||
|
||||
`jake runtests tests=<regex>`
|
||||
```Shell
|
||||
jake runtests tests=<regex>
|
||||
```
|
||||
|
||||
e.g. to run all compiler baseline tests:
|
||||
|
||||
`jake runtests tests=compiler`
|
||||
```Shell
|
||||
jake runtests tests=compiler
|
||||
```
|
||||
|
||||
or to run specifc test:tests\cases\compiler\2dArrays.ts
|
||||
or to run a specific test: `tests\cases\compiler\2dArrays.ts`
|
||||
|
||||
`jake runtests tests=2dArrays`
|
||||
```Shell
|
||||
jake runtests tests=2dArrays
|
||||
```
|
||||
|
||||
## Debugging the tests
|
||||
|
||||
To debug the tests, invoke the `runtests-browser` task from jake.
|
||||
You will probably only want to debug one test at a time:
|
||||
|
||||
```Shell
|
||||
jake runtests-browser tests=2dArrays
|
||||
```
|
||||
|
||||
You can specify which browser to use for debugging. Currently Chrome and IE are supported:
|
||||
|
||||
```Shell
|
||||
jake runtests-browser tests=2dArrays browser=chrome
|
||||
```
|
||||
|
||||
You can debug with VS Code or Node instead with `jake runtests debug=true`:
|
||||
|
||||
```Shell
|
||||
jake runtests tests=2dArrays debug=true
|
||||
```
|
||||
|
||||
## Adding a Test
|
||||
To add a new testcase, simply place a .ts file in tests\cases\compiler containing code that exemplifies the bugfix or change you are making.
|
||||
|
||||
These files support metadata tags in the format // @name: value . The supported names and values are:
|
||||
To add a new test case, simply place a `.ts` file in `tests\cases\compiler` containing code that exemplifies the bugfix or change you are making.
|
||||
|
||||
* comments, sourcemap, noimplicitany, declaration: true or false (corresponds to the compiler command-line options of the same name)
|
||||
* target: ES3 or ES5 (same as compiler)
|
||||
* out, outDir: path (same as compiler)
|
||||
* module: local, commonjs, or amd (local corresponds to not passing any compiler --module flag)
|
||||
These files support metadata tags in the format `// @metaDataName: value`.
|
||||
The supported names and values are the same as those supported in the compiler itself, with the addition of the `fileName` flag.
|
||||
`fileName` tags delimit sections of a file to be used as separate compilation units.
|
||||
They are useful for tests relating to modules.
|
||||
See below for examples.
|
||||
|
||||
**Note** that if you have a test corresponding to a specific spec compliance item, you can place it in tests\cases\conformance in an appropriately-named subfolder.
|
||||
**Note** that if you have a test corresponding to a specific spec compliance item, you can place it in `tests\cases\conformance` in an appropriately-named subfolder.
|
||||
**Note** that filenames here must be distinct from all other compiler testcase names, so you may have to work a bit to find a unique name if it's something common.
|
||||
|
||||
### Tests for multiple files
|
||||
|
||||
When one needs to test for scenarios which require multiple files, it is useful to use the `fileName` metadata tag as such:
|
||||
|
||||
```TypeScript
|
||||
// @fileName: file1.ts
|
||||
export function f() {
|
||||
}
|
||||
|
||||
// @fileName: file2.ts
|
||||
import { f as g } from "file1";
|
||||
|
||||
var x = g();
|
||||
```
|
||||
|
||||
One can also write a project test, but it is slightly more involved.
|
||||
|
||||
## Managing the Baselines
|
||||
Compiler testcases generate baselines that track the emitted .js, the errors produced by the compiler, and the type of each expression in the file. Additionally, some testcases opt in to baselining the source map output.
|
||||
|
||||
Compiler testcases generate baselines that track the emitted `.js`, the errors produced by the compiler, and the type of each expression in the file. Additionally, some testcases opt in to baselining the source map output.
|
||||
|
||||
When a change in the baselines is detected, the test will fail. To inspect changes vs the expected baselines, use
|
||||
|
||||
`jake diff`
|
||||
```Shell
|
||||
jake diff
|
||||
```
|
||||
|
||||
After verifying that the changes in the baselines are correct, run
|
||||
|
||||
`jake baseline-accept`
|
||||
```Shell
|
||||
jake baseline-accept
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
**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.
|
||||
**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.
|
||||
|
||||
@@ -1,690 +0,0 @@
|
||||
// This file contains the build logic for the public repo
|
||||
|
||||
var fs = require("fs");
|
||||
var os = require("os");
|
||||
var path = require("path");
|
||||
var child_process = require("child_process");
|
||||
|
||||
// Variables
|
||||
var compilerDirectory = "src/compiler/";
|
||||
var servicesDirectory = "src/services/";
|
||||
var serverDirectory = "src/server/";
|
||||
var harnessDirectory = "src/harness/";
|
||||
var libraryDirectory = "src/lib/";
|
||||
var scriptsDirectory = "scripts/";
|
||||
var unittestsDirectory = "tests/cases/unittests/";
|
||||
var docDirectory = "doc/";
|
||||
|
||||
var builtDirectory = "built/";
|
||||
var builtLocalDirectory = "built/local/";
|
||||
var LKGDirectory = "bin/";
|
||||
|
||||
var copyright = "CopyrightNotice.txt";
|
||||
var thirdParty = "ThirdPartyNoticeText.txt";
|
||||
|
||||
// add node_modules to path so we don't need global modules, prefer the modules by adding them first
|
||||
var nodeModulesPathPrefix = path.resolve("./node_modules/.bin/") + path.delimiter;
|
||||
if (process.env.path !== undefined) {
|
||||
process.env.path = nodeModulesPathPrefix + process.env.path;
|
||||
} else if (process.env.PATH !== undefined) {
|
||||
process.env.PATH = nodeModulesPathPrefix + process.env.PATH;
|
||||
}
|
||||
|
||||
var compilerSources = [
|
||||
"core.ts",
|
||||
"sys.ts",
|
||||
"types.ts",
|
||||
"scanner.ts",
|
||||
"parser.ts",
|
||||
"utilities.ts",
|
||||
"binder.ts",
|
||||
"checker.ts",
|
||||
"declarationEmitter.ts",
|
||||
"emitter.ts",
|
||||
"program.ts",
|
||||
"commandLineParser.ts",
|
||||
"tsc.ts",
|
||||
"diagnosticInformationMap.generated.ts"
|
||||
].map(function (f) {
|
||||
return path.join(compilerDirectory, f);
|
||||
});
|
||||
|
||||
var servicesSources = [
|
||||
"core.ts",
|
||||
"sys.ts",
|
||||
"types.ts",
|
||||
"scanner.ts",
|
||||
"parser.ts",
|
||||
"utilities.ts",
|
||||
"binder.ts",
|
||||
"checker.ts",
|
||||
"declarationEmitter.ts",
|
||||
"emitter.ts",
|
||||
"program.ts",
|
||||
"commandLineParser.ts",
|
||||
"diagnosticInformationMap.generated.ts"
|
||||
].map(function (f) {
|
||||
return path.join(compilerDirectory, f);
|
||||
}).concat([
|
||||
"breakpoints.ts",
|
||||
"navigateTo.ts",
|
||||
"navigationBar.ts",
|
||||
"outliningElementsCollector.ts",
|
||||
"patternMatcher.ts",
|
||||
"services.ts",
|
||||
"shims.ts",
|
||||
"signatureHelp.ts",
|
||||
"utilities.ts",
|
||||
"formatting/formatting.ts",
|
||||
"formatting/formattingContext.ts",
|
||||
"formatting/formattingRequestKind.ts",
|
||||
"formatting/formattingScanner.ts",
|
||||
"formatting/references.ts",
|
||||
"formatting/rule.ts",
|
||||
"formatting/ruleAction.ts",
|
||||
"formatting/ruleDescriptor.ts",
|
||||
"formatting/ruleFlag.ts",
|
||||
"formatting/ruleOperation.ts",
|
||||
"formatting/ruleOperationContext.ts",
|
||||
"formatting/rules.ts",
|
||||
"formatting/rulesMap.ts",
|
||||
"formatting/rulesProvider.ts",
|
||||
"formatting/smartIndenter.ts",
|
||||
"formatting/tokenRange.ts"
|
||||
].map(function (f) {
|
||||
return path.join(servicesDirectory, f);
|
||||
}));
|
||||
|
||||
var serverSources = [
|
||||
"node.d.ts",
|
||||
"editorServices.ts",
|
||||
"protocol.d.ts",
|
||||
"session.ts",
|
||||
"server.ts"
|
||||
].map(function (f) {
|
||||
return path.join(serverDirectory, f);
|
||||
});
|
||||
|
||||
var harnessSources = [
|
||||
"harness.ts",
|
||||
"sourceMapRecorder.ts",
|
||||
"harnessLanguageService.ts",
|
||||
"fourslash.ts",
|
||||
"runnerbase.ts",
|
||||
"compilerRunner.ts",
|
||||
"typeWriter.ts",
|
||||
"fourslashRunner.ts",
|
||||
"projectsRunner.ts",
|
||||
"loggedIO.ts",
|
||||
"rwcRunner.ts",
|
||||
"test262Runner.ts",
|
||||
"runner.ts"
|
||||
].map(function (f) {
|
||||
return path.join(harnessDirectory, f);
|
||||
}).concat([
|
||||
"incrementalParser.ts",
|
||||
"services/colorization.ts",
|
||||
"services/documentRegistry.ts",
|
||||
"services/preProcessFile.ts",
|
||||
"services/patternMatcher.ts",
|
||||
"versionCache.ts"
|
||||
].map(function (f) {
|
||||
return path.join(unittestsDirectory, f);
|
||||
})).concat([
|
||||
"protocol.d.ts",
|
||||
"session.ts",
|
||||
"client.ts",
|
||||
"editorServices.ts",
|
||||
].map(function (f) {
|
||||
return path.join(serverDirectory, f);
|
||||
}));
|
||||
|
||||
var librarySourceMap = [
|
||||
{ target: "lib.core.d.ts", sources: ["core.d.ts"] },
|
||||
{ target: "lib.dom.d.ts", sources: ["importcore.d.ts", "extensions.d.ts", "intl.d.ts", "dom.generated.d.ts"], },
|
||||
{ target: "lib.webworker.d.ts", sources: ["importcore.d.ts", "extensions.d.ts", "intl.d.ts", "webworker.generated.d.ts"], },
|
||||
{ target: "lib.scriptHost.d.ts", sources: ["importcore.d.ts", "scriptHost.d.ts"], },
|
||||
{ target: "lib.d.ts", sources: ["core.d.ts", "extensions.d.ts", "intl.d.ts", "dom.generated.d.ts", "webworker.importscripts.d.ts", "scriptHost.d.ts"], },
|
||||
{ target: "lib.core.es6.d.ts", sources: ["core.d.ts", "es6.d.ts"]},
|
||||
{ target: "lib.es6.d.ts", sources: ["core.d.ts", "es6.d.ts", "intl.d.ts", "dom.generated.d.ts", "webworker.importscripts.d.ts", "scriptHost.d.ts"]},
|
||||
];
|
||||
|
||||
var libraryTargets = librarySourceMap.map(function (f) {
|
||||
return path.join(builtLocalDirectory, f.target);
|
||||
});
|
||||
|
||||
// Prepends the contents of prefixFile to destinationFile
|
||||
function prependFile(prefixFile, destinationFile) {
|
||||
if (!fs.existsSync(prefixFile)) {
|
||||
fail(prefixFile + " does not exist!");
|
||||
}
|
||||
if (!fs.existsSync(destinationFile)) {
|
||||
fail(destinationFile + " failed to be created!");
|
||||
}
|
||||
var temp = "temptemp";
|
||||
jake.cpR(prefixFile, temp, {silent: true});
|
||||
fs.appendFileSync(temp, fs.readFileSync(destinationFile));
|
||||
fs.renameSync(temp, destinationFile);
|
||||
}
|
||||
|
||||
// concatenate a list of sourceFiles to a destinationFile
|
||||
function concatenateFiles(destinationFile, sourceFiles) {
|
||||
var temp = "temptemp";
|
||||
// Copy the first file to temp
|
||||
if (!fs.existsSync(sourceFiles[0])) {
|
||||
fail(sourceFiles[0] + " does not exist!");
|
||||
}
|
||||
jake.cpR(sourceFiles[0], temp, {silent: true});
|
||||
// append all files in sequence
|
||||
for (var i = 1; i < sourceFiles.length; i++) {
|
||||
if (!fs.existsSync(sourceFiles[i])) {
|
||||
fail(sourceFiles[i] + " does not exist!");
|
||||
}
|
||||
fs.appendFileSync(temp, fs.readFileSync(sourceFiles[i]));
|
||||
}
|
||||
// Move the file to the final destination
|
||||
fs.renameSync(temp, destinationFile);
|
||||
}
|
||||
|
||||
var useDebugMode = true;
|
||||
var host = (process.env.host || process.env.TYPESCRIPT_HOST || "node");
|
||||
var compilerFilename = "tsc.js";
|
||||
/* Compiles a file from a list of sources
|
||||
* @param outFile: the target file name
|
||||
* @param sources: an array of the names of the source files
|
||||
* @param prereqs: prerequisite tasks to compiling the file
|
||||
* @param prefixes: a list of files to prepend to the target file
|
||||
* @param useBuiltCompiler: true to use the built compiler, false to use the LKG
|
||||
* @param noOutFile: true to compile without using --out
|
||||
* @param generateDeclarations: true to compile using --declaration
|
||||
* @param outDir: true to compile using --outDir
|
||||
* @param keepComments: false to compile using --removeComments
|
||||
* @param callback: a function to execute after the compilation process ends
|
||||
*/
|
||||
function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOutFile, generateDeclarations, outDir, preserveConstEnums, keepComments, noResolve, stripInternal, callback) {
|
||||
file(outFile, prereqs, function() {
|
||||
var dir = useBuiltCompiler ? builtLocalDirectory : LKGDirectory;
|
||||
var options = "--module commonjs -noImplicitAny";
|
||||
|
||||
// Keep comments when specifically requested
|
||||
// or when in debug mode.
|
||||
if (!(keepComments || useDebugMode)) {
|
||||
options += " --removeComments";
|
||||
}
|
||||
|
||||
if (generateDeclarations) {
|
||||
options += " --declaration";
|
||||
}
|
||||
|
||||
if (preserveConstEnums || useDebugMode) {
|
||||
options += " --preserveConstEnums";
|
||||
}
|
||||
|
||||
if (outDir) {
|
||||
options += " --outDir " + outDir;
|
||||
}
|
||||
|
||||
if (!noOutFile) {
|
||||
options += " --out " + outFile;
|
||||
}
|
||||
|
||||
if(noResolve) {
|
||||
options += " --noResolve";
|
||||
}
|
||||
|
||||
if (useDebugMode) {
|
||||
options += " -sourcemap -mapRoot file:///" + path.resolve(path.dirname(outFile));
|
||||
}
|
||||
|
||||
if (stripInternal) {
|
||||
options += " --stripInternal"
|
||||
}
|
||||
|
||||
var cmd = host + " " + dir + compilerFilename + " " + options + " ";
|
||||
cmd = cmd + sources.join(" ");
|
||||
console.log(cmd + "\n");
|
||||
|
||||
var ex = jake.createExec([cmd]);
|
||||
// Add listeners for output and error
|
||||
ex.addListener("stdout", function(output) {
|
||||
process.stdout.write(output);
|
||||
});
|
||||
ex.addListener("stderr", function(error) {
|
||||
process.stderr.write(error);
|
||||
});
|
||||
ex.addListener("cmdEnd", function() {
|
||||
if (!useDebugMode && prefixes && fs.existsSync(outFile)) {
|
||||
for (var i in prefixes) {
|
||||
prependFile(prefixes[i], outFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
|
||||
complete();
|
||||
});
|
||||
ex.addListener("error", function() {
|
||||
fs.unlinkSync(outFile);
|
||||
fail("Compilation of " + outFile + " unsuccessful");
|
||||
});
|
||||
ex.run();
|
||||
}, {async: true});
|
||||
}
|
||||
|
||||
// Prerequisite task for built directory and library typings
|
||||
directory(builtLocalDirectory);
|
||||
|
||||
for (var i in libraryTargets) {
|
||||
(function (i) {
|
||||
var entry = librarySourceMap[i];
|
||||
var target = libraryTargets[i];
|
||||
var sources = [copyright].concat(entry.sources.map(function (s) {
|
||||
return path.join(libraryDirectory, s);
|
||||
}));
|
||||
file(target, [builtLocalDirectory].concat(sources), function() {
|
||||
concatenateFiles(target, sources);
|
||||
});
|
||||
})(i);
|
||||
}
|
||||
|
||||
// Lib target to build the library files
|
||||
desc("Builds the library targets");
|
||||
task("lib", libraryTargets);
|
||||
|
||||
|
||||
// Generate diagnostics
|
||||
var processDiagnosticMessagesJs = path.join(scriptsDirectory, "processDiagnosticMessages.js");
|
||||
var processDiagnosticMessagesTs = path.join(scriptsDirectory, "processDiagnosticMessages.ts");
|
||||
var diagnosticMessagesJson = path.join(compilerDirectory, "diagnosticMessages.json");
|
||||
var diagnosticInfoMapTs = path.join(compilerDirectory, "diagnosticInformationMap.generated.ts");
|
||||
|
||||
file(processDiagnosticMessagesTs)
|
||||
|
||||
// processDiagnosticMessages script
|
||||
compileFile(processDiagnosticMessagesJs,
|
||||
[processDiagnosticMessagesTs],
|
||||
[processDiagnosticMessagesTs],
|
||||
[],
|
||||
/*useBuiltCompiler*/ false);
|
||||
|
||||
// The generated diagnostics map; built for the compiler and for the 'generate-diagnostics' task
|
||||
file(diagnosticInfoMapTs, [processDiagnosticMessagesJs, diagnosticMessagesJson], function () {
|
||||
var cmd = "node " + processDiagnosticMessagesJs + " " + diagnosticMessagesJson;
|
||||
console.log(cmd);
|
||||
var ex = jake.createExec([cmd]);
|
||||
// Add listeners for output and error
|
||||
ex.addListener("stdout", function(output) {
|
||||
process.stdout.write(output);
|
||||
});
|
||||
ex.addListener("stderr", function(error) {
|
||||
process.stderr.write(error);
|
||||
});
|
||||
ex.addListener("cmdEnd", function() {
|
||||
complete();
|
||||
});
|
||||
ex.run();
|
||||
}, {async: true})
|
||||
|
||||
desc("Generates a diagnostic file in TypeScript based on an input JSON file");
|
||||
task("generate-diagnostics", [diagnosticInfoMapTs])
|
||||
|
||||
|
||||
// Local target to build the compiler and services
|
||||
var tscFile = path.join(builtLocalDirectory, compilerFilename);
|
||||
compileFile(tscFile, compilerSources, [builtLocalDirectory, copyright].concat(compilerSources), [copyright], /*useBuiltCompiler:*/ false);
|
||||
|
||||
var servicesFile = path.join(builtLocalDirectory, "typescriptServices.js");
|
||||
var standaloneDefinitionsFile = path.join(builtLocalDirectory, "typescriptServices.d.ts");
|
||||
var nodePackageFile = path.join(builtLocalDirectory, "typescript.js");
|
||||
var nodeDefinitionsFile = path.join(builtLocalDirectory, "typescript.d.ts");
|
||||
|
||||
compileFile(servicesFile, servicesSources,[builtLocalDirectory, copyright].concat(servicesSources),
|
||||
/*prefixes*/ [copyright],
|
||||
/*useBuiltCompiler*/ true,
|
||||
/*noOutFile*/ false,
|
||||
/*generateDeclarations*/ true,
|
||||
/*outDir*/ undefined,
|
||||
/*preserveConstEnums*/ true,
|
||||
/*keepComments*/ true,
|
||||
/*noResolve*/ false,
|
||||
/*stripInternal*/ true,
|
||||
/*callback*/ function () {
|
||||
jake.cpR(servicesFile, nodePackageFile, {silent: true});
|
||||
|
||||
prependFile(copyright, standaloneDefinitionsFile);
|
||||
|
||||
// Create the node definition file by replacing 'ts' module with '"typescript"' as a module.
|
||||
jake.cpR(standaloneDefinitionsFile, nodeDefinitionsFile, {silent: true});
|
||||
var definitionFileContents = fs.readFileSync(nodeDefinitionsFile).toString();
|
||||
definitionFileContents = definitionFileContents.replace(/declare module ts/g, 'declare module "typescript"');
|
||||
fs.writeFileSync(nodeDefinitionsFile, definitionFileContents);
|
||||
});
|
||||
|
||||
|
||||
var serverFile = path.join(builtLocalDirectory, "tsserver.js");
|
||||
compileFile(serverFile, serverSources,[builtLocalDirectory, copyright].concat(serverSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true);
|
||||
|
||||
// Local target to build the compiler and services
|
||||
desc("Builds the full compiler and services");
|
||||
task("local", ["generate-diagnostics", "lib", tscFile, servicesFile, nodeDefinitionsFile, serverFile]);
|
||||
|
||||
// Local target to build only tsc.js
|
||||
desc("Builds only the compiler");
|
||||
task("tsc", ["generate-diagnostics", "lib", tscFile]);
|
||||
|
||||
// Local target to build the compiler and services
|
||||
desc("Sets release mode flag");
|
||||
task("release", function() {
|
||||
useDebugMode = false;
|
||||
});
|
||||
|
||||
// Set the default task to "local"
|
||||
task("default", ["local"]);
|
||||
|
||||
|
||||
// Cleans the built directory
|
||||
desc("Cleans the compiler output, declare files, and tests");
|
||||
task("clean", function() {
|
||||
jake.rmRf(builtDirectory);
|
||||
});
|
||||
|
||||
// Generate Markdown spec
|
||||
var word2mdJs = path.join(scriptsDirectory, "word2md.js");
|
||||
var word2mdTs = path.join(scriptsDirectory, "word2md.ts");
|
||||
var specWord = path.join(docDirectory, "TypeScript Language Specification.docx");
|
||||
var specMd = path.join(docDirectory, "spec.md");
|
||||
|
||||
file(word2mdTs);
|
||||
|
||||
// word2md script
|
||||
compileFile(word2mdJs,
|
||||
[word2mdTs],
|
||||
[word2mdTs],
|
||||
[],
|
||||
/*useBuiltCompiler*/ false);
|
||||
|
||||
// The generated spec.md; built for the 'generate-spec' task
|
||||
file(specMd, [word2mdJs, specWord], function () {
|
||||
var specWordFullPath = path.resolve(specWord);
|
||||
var cmd = "cscript //nologo " + word2mdJs + ' "' + specWordFullPath + '" ' + specMd;
|
||||
console.log(cmd);
|
||||
child_process.exec(cmd, function () {
|
||||
complete();
|
||||
});
|
||||
}, {async: true})
|
||||
|
||||
|
||||
desc("Generates a Markdown version of the Language Specification");
|
||||
task("generate-spec", [specMd])
|
||||
|
||||
|
||||
// Makes a new LKG. This target does not build anything, but errors if not all the outputs are present in the built/local directory
|
||||
desc("Makes a new LKG out of the built js files");
|
||||
task("LKG", ["clean", "release", "local"].concat(libraryTargets), function() {
|
||||
var expectedFiles = [tscFile, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile].concat(libraryTargets);
|
||||
var missingFiles = expectedFiles.filter(function (f) {
|
||||
return !fs.existsSync(f);
|
||||
});
|
||||
if (missingFiles.length > 0) {
|
||||
fail("Cannot replace the LKG unless all built targets are present in directory " + builtLocalDirectory +
|
||||
". The following files are missing:\n" + missingFiles.join("\n"));
|
||||
}
|
||||
// Copy all the targets into the LKG directory
|
||||
jake.mkdirP(LKGDirectory);
|
||||
for (i in expectedFiles) {
|
||||
jake.cpR(expectedFiles[i], LKGDirectory);
|
||||
}
|
||||
//var resourceDirectories = fs.readdirSync(builtLocalResourcesDirectory).map(function(p) { return path.join(builtLocalResourcesDirectory, p); });
|
||||
//resourceDirectories.map(function(d) {
|
||||
// jake.cpR(d, LKGResourcesDirectory);
|
||||
//});
|
||||
});
|
||||
|
||||
// Test directory
|
||||
directory(builtLocalDirectory);
|
||||
|
||||
// Task to build the tests infrastructure using the built compiler
|
||||
var run = path.join(builtLocalDirectory, "run.js");
|
||||
compileFile(run, harnessSources, [builtLocalDirectory, tscFile].concat(libraryTargets).concat(harnessSources), [], /*useBuiltCompiler:*/ true);
|
||||
|
||||
var internalTests = "internal/"
|
||||
|
||||
var localBaseline = "tests/baselines/local/";
|
||||
var refBaseline = "tests/baselines/reference/";
|
||||
|
||||
var localRwcBaseline = path.join(internalTests, "baselines/rwc/local");
|
||||
var refRwcBaseline = path.join(internalTests, "baselines/rwc/reference");
|
||||
|
||||
var localTest262Baseline = path.join(internalTests, "baselines/test262/local");
|
||||
var refTest262Baseline = path.join(internalTests, "baselines/test262/reference");
|
||||
|
||||
desc("Builds the test infrastructure using the built compiler");
|
||||
task("tests", ["local", run].concat(libraryTargets));
|
||||
|
||||
function exec(cmd, completeHandler) {
|
||||
var ex = jake.createExec([cmd], {windowsVerbatimArguments: true});
|
||||
// Add listeners for output and error
|
||||
ex.addListener("stdout", function(output) {
|
||||
process.stdout.write(output);
|
||||
});
|
||||
ex.addListener("stderr", function(error) {
|
||||
process.stderr.write(error);
|
||||
});
|
||||
ex.addListener("cmdEnd", function() {
|
||||
if (completeHandler) {
|
||||
completeHandler();
|
||||
}
|
||||
complete();
|
||||
});
|
||||
ex.addListener("error", function(e, status) {
|
||||
fail("Process exited with code " + status);
|
||||
})
|
||||
|
||||
ex.run();
|
||||
}
|
||||
|
||||
function cleanTestDirs() {
|
||||
// Clean the local baselines directory
|
||||
if (fs.existsSync(localBaseline)) {
|
||||
jake.rmRf(localBaseline);
|
||||
}
|
||||
|
||||
// Clean the local Rwc baselines directory
|
||||
if (fs.existsSync(localRwcBaseline)) {
|
||||
jake.rmRf(localRwcBaseline);
|
||||
}
|
||||
|
||||
jake.mkdirP(localRwcBaseline);
|
||||
jake.mkdirP(localTest262Baseline);
|
||||
jake.mkdirP(localBaseline);
|
||||
}
|
||||
|
||||
// used to pass data from jake command line directly to run.js
|
||||
function writeTestConfigFile(tests, testConfigFile) {
|
||||
console.log('Running test(s): ' + tests);
|
||||
var testConfigContents = '{\n' + '\ttest: [\'' + tests + '\']\n}';
|
||||
fs.writeFileSync('test.config', testConfigContents);
|
||||
}
|
||||
|
||||
function deleteTemporaryProjectOutput() {
|
||||
if (fs.existsSync(path.join(localBaseline, "projectOutput/"))) {
|
||||
jake.rmRf(path.join(localBaseline, "projectOutput/"));
|
||||
}
|
||||
}
|
||||
|
||||
var testTimeout = 20000;
|
||||
desc("Runs the tests using the built run.js file. Syntax is jake runtests. Optional parameters 'host=', 'tests=[regex], reporter=[list|spec|json|<more>]'.");
|
||||
task("runtests", ["tests", builtLocalDirectory], function() {
|
||||
cleanTestDirs();
|
||||
host = "mocha"
|
||||
tests = process.env.test || process.env.tests || process.env.t;
|
||||
var testConfigFile = 'test.config';
|
||||
if(fs.existsSync(testConfigFile)) {
|
||||
fs.unlinkSync(testConfigFile);
|
||||
}
|
||||
|
||||
if(tests) {
|
||||
writeTestConfigFile(tests, testConfigFile);
|
||||
}
|
||||
|
||||
if (tests && tests.toLocaleLowerCase() === "rwc") {
|
||||
testTimeout = 100000;
|
||||
}
|
||||
|
||||
colors = process.env.colors || process.env.color
|
||||
colors = colors ? ' --no-colors ' : ' --colors ';
|
||||
tests = tests ? ' -g ' + tests : '';
|
||||
reporter = process.env.reporter || process.env.r || 'dot';
|
||||
// timeout normally isn't necessary but Travis-CI has been timing out on compiler baselines occasionally
|
||||
// default timeout is 2sec which really should be enough, but maybe we just need a small amount longer
|
||||
var cmd = host + " -R " + reporter + tests + colors + ' -t ' + testTimeout + ' ' + run;
|
||||
console.log(cmd);
|
||||
exec(cmd, deleteTemporaryProjectOutput);
|
||||
}, {async: true});
|
||||
|
||||
desc("Generates code coverage data via instanbul")
|
||||
task("generate-code-coverage", ["tests", builtLocalDirectory], function () {
|
||||
var cmd = 'istanbul cover node_modules/mocha/bin/_mocha -- -R min -t ' + testTimeout + ' ' + run;
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
}, { async: true });
|
||||
|
||||
// Browser tests
|
||||
var nodeServerOutFile = 'tests/webTestServer.js'
|
||||
var nodeServerInFile = 'tests/webTestServer.ts'
|
||||
compileFile(nodeServerOutFile, [nodeServerInFile], [builtLocalDirectory, tscFile], [], /*useBuiltCompiler:*/ true, /*noOutFile*/ true);
|
||||
|
||||
desc("Runs browserify on run.js to produce a file suitable for running tests in the browser");
|
||||
task("browserify", ["tests", builtLocalDirectory, nodeServerOutFile], function() {
|
||||
var cmd = 'browserify built/local/run.js -o built/local/bundle.js';
|
||||
exec(cmd);
|
||||
}, {async: true});
|
||||
|
||||
desc("Runs the tests using the built run.js file like 'jake runtests'. Syntax is jake runtests-browser. Additional optional parameters tests=[regex], port=, browser=[chrome|IE]");
|
||||
task("runtests-browser", ["tests", "browserify", builtLocalDirectory], function() {
|
||||
cleanTestDirs();
|
||||
host = "node"
|
||||
port = process.env.port || process.env.p || '8888';
|
||||
browser = process.env.browser || process.env.b || "IE";
|
||||
tests = process.env.test || process.env.tests || process.env.t;
|
||||
var testConfigFile = 'test.config';
|
||||
if(fs.existsSync(testConfigFile)) {
|
||||
fs.unlinkSync(testConfigFile);
|
||||
}
|
||||
if(tests) {
|
||||
writeTestConfigFile(tests, testConfigFile);
|
||||
}
|
||||
|
||||
tests = tests ? tests : '';
|
||||
var cmd = host + " tests/webTestServer.js " + port + " " + browser + " " + tests
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
}, {async: true});
|
||||
|
||||
function getDiffTool() {
|
||||
var program = process.env['DIFF']
|
||||
if (!program) {
|
||||
fail("Add the 'DIFF' environment variable to the path of the program you want to use.")
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
// Baseline Diff
|
||||
desc("Diffs the compiler baselines using the diff tool specified by the 'DIFF' environment variable");
|
||||
task('diff', function () {
|
||||
var cmd = '"' + getDiffTool() + '" ' + refBaseline + ' ' + localBaseline;
|
||||
console.log(cmd)
|
||||
exec(cmd);
|
||||
}, {async: true});
|
||||
|
||||
desc("Diffs the RWC baselines using the diff tool specified by the 'DIFF' environment variable");
|
||||
task('diff-rwc', function () {
|
||||
var cmd = '"' + getDiffTool() + '" ' + refRwcBaseline + ' ' + localRwcBaseline;
|
||||
console.log(cmd)
|
||||
exec(cmd);
|
||||
}, {async: true});
|
||||
|
||||
desc("Builds the test sources and automation in debug mode");
|
||||
task("tests-debug", ["setDebugMode", "tests"]);
|
||||
|
||||
|
||||
// Makes the test results the new baseline
|
||||
desc("Makes the most recent test results the new baseline, overwriting the old baseline");
|
||||
task("baseline-accept", function(hardOrSoft) {
|
||||
if (!hardOrSoft || hardOrSoft == "hard") {
|
||||
jake.rmRf(refBaseline);
|
||||
fs.renameSync(localBaseline, refBaseline);
|
||||
}
|
||||
else if (hardOrSoft == "soft") {
|
||||
var files = jake.readdirR(localBaseline);
|
||||
for (var i in files) {
|
||||
jake.cpR(files[i], refBaseline);
|
||||
}
|
||||
jake.rmRf(path.join(refBaseline, "local"));
|
||||
}
|
||||
});
|
||||
|
||||
desc("Makes the most recent rwc test results the new baseline, overwriting the old baseline");
|
||||
task("baseline-accept-rwc", function() {
|
||||
jake.rmRf(refRwcBaseline);
|
||||
fs.renameSync(localRwcBaseline, refRwcBaseline);
|
||||
});
|
||||
|
||||
desc("Makes the most recent test262 test results the new baseline, overwriting the old baseline");
|
||||
task("baseline-accept-test262", function() {
|
||||
jake.rmRf(refTest262Baseline);
|
||||
fs.renameSync(localTest262Baseline, refTest262Baseline);
|
||||
});
|
||||
|
||||
|
||||
// Webhost
|
||||
var webhostPath = "tests/webhost/webtsc.ts";
|
||||
var webhostJsPath = "tests/webhost/webtsc.js";
|
||||
compileFile(webhostJsPath, [webhostPath], [tscFile, webhostPath].concat(libraryTargets), [], /*useBuiltCompiler*/true);
|
||||
|
||||
desc("Builds the tsc web host");
|
||||
task("webhost", [webhostJsPath], function() {
|
||||
jake.cpR(path.join(builtLocalDirectory, "lib.d.ts"), "tests/webhost/", {silent: true});
|
||||
});
|
||||
|
||||
// Perf compiler
|
||||
var perftscPath = "tests/perftsc.ts";
|
||||
var perftscJsPath = "built/local/perftsc.js";
|
||||
compileFile(perftscJsPath, [perftscPath], [tscFile, perftscPath, "tests/perfsys.ts"].concat(libraryTargets), [], /*useBuiltCompiler*/ true);
|
||||
desc("Builds augmented version of the compiler for perf tests");
|
||||
task("perftsc", [perftscJsPath]);
|
||||
|
||||
// Instrumented compiler
|
||||
var loggedIOpath = harnessDirectory + 'loggedIO.ts';
|
||||
var loggedIOJsPath = builtLocalDirectory + 'loggedIO.js';
|
||||
file(loggedIOJsPath, [builtLocalDirectory, loggedIOpath], function() {
|
||||
var temp = builtLocalDirectory + 'temp';
|
||||
jake.mkdirP(temp);
|
||||
var options = "--outdir " + temp + ' ' + loggedIOpath;
|
||||
var cmd = host + " " + LKGDirectory + compilerFilename + " " + options + " ";
|
||||
console.log(cmd + "\n");
|
||||
var ex = jake.createExec([cmd]);
|
||||
ex.addListener("cmdEnd", function() {
|
||||
fs.renameSync(temp + '/harness/loggedIO.js', loggedIOJsPath);
|
||||
jake.rmRf(temp);
|
||||
complete();
|
||||
});
|
||||
ex.run();
|
||||
}, {async: true});
|
||||
|
||||
var instrumenterPath = harnessDirectory + 'instrumenter.ts';
|
||||
var instrumenterJsPath = builtLocalDirectory + 'instrumenter.js';
|
||||
compileFile(instrumenterJsPath, [instrumenterPath], [tscFile, instrumenterPath].concat(libraryTargets), [], /*useBuiltCompiler*/ true);
|
||||
|
||||
desc("Builds an instrumented tsc.js");
|
||||
task('tsc-instrumented', [loggedIOJsPath, instrumenterJsPath, tscFile], function() {
|
||||
var cmd = host + ' ' + instrumenterJsPath + ' record iocapture ' + builtLocalDirectory + compilerFilename;
|
||||
console.log(cmd);
|
||||
var ex = jake.createExec([cmd]);
|
||||
ex.addListener("cmdEnd", function() {
|
||||
complete();
|
||||
});
|
||||
ex.run();
|
||||
}, { async: true });
|
||||
+992
@@ -0,0 +1,992 @@
|
||||
// This file contains the build logic for the public repo
|
||||
|
||||
var fs = require("fs");
|
||||
var os = require("os");
|
||||
var path = require("path");
|
||||
var child_process = require("child_process");
|
||||
var Linter = require("tslint");
|
||||
|
||||
// Variables
|
||||
var compilerDirectory = "src/compiler/";
|
||||
var servicesDirectory = "src/services/";
|
||||
var serverDirectory = "src/server/";
|
||||
var harnessDirectory = "src/harness/";
|
||||
var libraryDirectory = "src/lib/";
|
||||
var scriptsDirectory = "scripts/";
|
||||
var unittestsDirectory = "tests/cases/unittests/";
|
||||
var docDirectory = "doc/";
|
||||
|
||||
var builtDirectory = "built/";
|
||||
var builtLocalDirectory = "built/local/";
|
||||
var LKGDirectory = "lib/";
|
||||
|
||||
var copyright = "CopyrightNotice.txt";
|
||||
var thirdParty = "ThirdPartyNoticeText.txt";
|
||||
|
||||
// add node_modules to path so we don't need global modules, prefer the modules by adding them first
|
||||
var nodeModulesPathPrefix = path.resolve("./node_modules/.bin/") + path.delimiter;
|
||||
if (process.env.path !== undefined) {
|
||||
process.env.path = nodeModulesPathPrefix + process.env.path;
|
||||
} else if (process.env.PATH !== undefined) {
|
||||
process.env.PATH = nodeModulesPathPrefix + process.env.PATH;
|
||||
}
|
||||
|
||||
var compilerSources = [
|
||||
"core.ts",
|
||||
"sys.ts",
|
||||
"types.ts",
|
||||
"scanner.ts",
|
||||
"parser.ts",
|
||||
"utilities.ts",
|
||||
"binder.ts",
|
||||
"checker.ts",
|
||||
"sourcemap.ts",
|
||||
"declarationEmitter.ts",
|
||||
"emitter.ts",
|
||||
"program.ts",
|
||||
"commandLineParser.ts",
|
||||
"tsc.ts",
|
||||
"diagnosticInformationMap.generated.ts"
|
||||
].map(function (f) {
|
||||
return path.join(compilerDirectory, f);
|
||||
});
|
||||
|
||||
var servicesSources = [
|
||||
"core.ts",
|
||||
"sys.ts",
|
||||
"types.ts",
|
||||
"scanner.ts",
|
||||
"parser.ts",
|
||||
"utilities.ts",
|
||||
"binder.ts",
|
||||
"checker.ts",
|
||||
"sourcemap.ts",
|
||||
"declarationEmitter.ts",
|
||||
"emitter.ts",
|
||||
"program.ts",
|
||||
"commandLineParser.ts",
|
||||
"diagnosticInformationMap.generated.ts"
|
||||
].map(function (f) {
|
||||
return path.join(compilerDirectory, f);
|
||||
}).concat([
|
||||
"breakpoints.ts",
|
||||
"navigateTo.ts",
|
||||
"navigationBar.ts",
|
||||
"outliningElementsCollector.ts",
|
||||
"patternMatcher.ts",
|
||||
"services.ts",
|
||||
"shims.ts",
|
||||
"signatureHelp.ts",
|
||||
"utilities.ts",
|
||||
"formatting/formatting.ts",
|
||||
"formatting/formattingContext.ts",
|
||||
"formatting/formattingRequestKind.ts",
|
||||
"formatting/formattingScanner.ts",
|
||||
"formatting/references.ts",
|
||||
"formatting/rule.ts",
|
||||
"formatting/ruleAction.ts",
|
||||
"formatting/ruleDescriptor.ts",
|
||||
"formatting/ruleFlag.ts",
|
||||
"formatting/ruleOperation.ts",
|
||||
"formatting/ruleOperationContext.ts",
|
||||
"formatting/rules.ts",
|
||||
"formatting/rulesMap.ts",
|
||||
"formatting/rulesProvider.ts",
|
||||
"formatting/smartIndenter.ts",
|
||||
"formatting/tokenRange.ts"
|
||||
].map(function (f) {
|
||||
return path.join(servicesDirectory, f);
|
||||
}));
|
||||
|
||||
var serverCoreSources = [
|
||||
"node.d.ts",
|
||||
"editorServices.ts",
|
||||
"protocol.d.ts",
|
||||
"session.ts",
|
||||
"server.ts"
|
||||
].map(function (f) {
|
||||
return path.join(serverDirectory, f);
|
||||
});
|
||||
|
||||
var serverSources = serverCoreSources.concat(servicesSources);
|
||||
|
||||
var languageServiceLibrarySources = [
|
||||
"editorServices.ts",
|
||||
"protocol.d.ts",
|
||||
"session.ts"
|
||||
].map(function (f) {
|
||||
return path.join(serverDirectory, f);
|
||||
}).concat(servicesSources);
|
||||
|
||||
var harnessCoreSources = [
|
||||
"harness.ts",
|
||||
"sourceMapRecorder.ts",
|
||||
"harnessLanguageService.ts",
|
||||
"fourslash.ts",
|
||||
"runnerbase.ts",
|
||||
"compilerRunner.ts",
|
||||
"typeWriter.ts",
|
||||
"fourslashRunner.ts",
|
||||
"projectsRunner.ts",
|
||||
"loggedIO.ts",
|
||||
"rwcRunner.ts",
|
||||
"test262Runner.ts",
|
||||
"runner.ts"
|
||||
].map(function (f) {
|
||||
return path.join(harnessDirectory, f);
|
||||
});
|
||||
|
||||
var harnessSources = harnessCoreSources.concat([
|
||||
"incrementalParser.ts",
|
||||
"jsDocParsing.ts",
|
||||
"services/colorization.ts",
|
||||
"services/documentRegistry.ts",
|
||||
"services/preProcessFile.ts",
|
||||
"services/patternMatcher.ts",
|
||||
"session.ts",
|
||||
"versionCache.ts",
|
||||
"convertToBase64.ts",
|
||||
"transpile.ts",
|
||||
"reuseProgramStructure.ts",
|
||||
"cachingInServerLSHost.ts",
|
||||
"moduleResolution.ts",
|
||||
"tsconfigParsing.ts"
|
||||
].map(function (f) {
|
||||
return path.join(unittestsDirectory, f);
|
||||
})).concat([
|
||||
"protocol.d.ts",
|
||||
"session.ts",
|
||||
"client.ts",
|
||||
"editorServices.ts",
|
||||
].map(function (f) {
|
||||
return path.join(serverDirectory, f);
|
||||
}));
|
||||
|
||||
var librarySourceMap = [
|
||||
{ target: "lib.core.d.ts", sources: ["header.d.ts", "core.d.ts"] },
|
||||
{ target: "lib.dom.d.ts", sources: ["importcore.d.ts", "intl.d.ts", "dom.generated.d.ts"], },
|
||||
{ target: "lib.webworker.d.ts", sources: ["importcore.d.ts", "intl.d.ts", "webworker.generated.d.ts"], },
|
||||
{ target: "lib.scriptHost.d.ts", sources: ["importcore.d.ts", "scriptHost.d.ts"], },
|
||||
{ target: "lib.d.ts", sources: ["header.d.ts", "core.d.ts", "intl.d.ts", "dom.generated.d.ts", "webworker.importscripts.d.ts", "scriptHost.d.ts"], },
|
||||
{ target: "lib.core.es6.d.ts", sources: ["header.d.ts", "core.d.ts", "es6.d.ts"]},
|
||||
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es6.d.ts", "core.d.ts", "intl.d.ts", "dom.generated.d.ts", "dom.es6.d.ts", "webworker.importscripts.d.ts", "scriptHost.d.ts"] },
|
||||
{ target: "lib.core.es7.d.ts", sources: ["header.d.ts", "core.d.ts", "es6.d.ts", "es7.d.ts"]},
|
||||
{ target: "lib.es7.d.ts", sources: ["header.d.ts", "es6.d.ts", "es7.d.ts", "core.d.ts", "intl.d.ts", "dom.generated.d.ts", "dom.es6.d.ts", "webworker.importscripts.d.ts", "scriptHost.d.ts"] }
|
||||
];
|
||||
|
||||
var libraryTargets = librarySourceMap.map(function (f) {
|
||||
return path.join(builtLocalDirectory, f.target);
|
||||
});
|
||||
|
||||
// Prepends the contents of prefixFile to destinationFile
|
||||
function prependFile(prefixFile, destinationFile) {
|
||||
if (!fs.existsSync(prefixFile)) {
|
||||
fail(prefixFile + " does not exist!");
|
||||
}
|
||||
if (!fs.existsSync(destinationFile)) {
|
||||
fail(destinationFile + " failed to be created!");
|
||||
}
|
||||
var temp = "temptemp";
|
||||
jake.cpR(prefixFile, temp, {silent: true});
|
||||
fs.appendFileSync(temp, fs.readFileSync(destinationFile));
|
||||
fs.renameSync(temp, destinationFile);
|
||||
}
|
||||
|
||||
// concatenate a list of sourceFiles to a destinationFile
|
||||
function concatenateFiles(destinationFile, sourceFiles) {
|
||||
var temp = "temptemp";
|
||||
// Copy the first file to temp
|
||||
if (!fs.existsSync(sourceFiles[0])) {
|
||||
fail(sourceFiles[0] + " does not exist!");
|
||||
}
|
||||
jake.cpR(sourceFiles[0], temp, {silent: true});
|
||||
// append all files in sequence
|
||||
for (var i = 1; i < sourceFiles.length; i++) {
|
||||
if (!fs.existsSync(sourceFiles[i])) {
|
||||
fail(sourceFiles[i] + " does not exist!");
|
||||
}
|
||||
fs.appendFileSync(temp, fs.readFileSync(sourceFiles[i]));
|
||||
}
|
||||
// Move the file to the final destination
|
||||
fs.renameSync(temp, destinationFile);
|
||||
}
|
||||
|
||||
var useDebugMode = true;
|
||||
var host = (process.env.host || process.env.TYPESCRIPT_HOST || "node");
|
||||
var compilerFilename = "tsc.js";
|
||||
var LKGCompiler = path.join(LKGDirectory, compilerFilename);
|
||||
var builtLocalCompiler = path.join(builtLocalDirectory, compilerFilename);
|
||||
|
||||
/* Compiles a file from a list of sources
|
||||
* @param outFile: the target file name
|
||||
* @param sources: an array of the names of the source files
|
||||
* @param prereqs: prerequisite tasks to compiling the file
|
||||
* @param prefixes: a list of files to prepend to the target file
|
||||
* @param useBuiltCompiler: true to use the built compiler, false to use the LKG
|
||||
* @param noOutFile: true to compile without using --out
|
||||
* @param generateDeclarations: true to compile using --declaration
|
||||
* @param outDir: true to compile using --outDir
|
||||
* @param keepComments: false to compile using --removeComments
|
||||
* @param callback: a function to execute after the compilation process ends
|
||||
*/
|
||||
function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOutFile, generateDeclarations, outDir, preserveConstEnums, keepComments, noResolve, stripInternal, callback) {
|
||||
file(outFile, prereqs, function() {
|
||||
var compilerPath = useBuiltCompiler ? builtLocalCompiler : LKGCompiler;
|
||||
var options = "--noImplicitAny --noEmitOnError --pretty";
|
||||
|
||||
// Keep comments when specifically requested
|
||||
// or when in debug mode.
|
||||
if (!(keepComments || useDebugMode)) {
|
||||
options += " --removeComments";
|
||||
}
|
||||
|
||||
if (generateDeclarations) {
|
||||
options += " --declaration";
|
||||
}
|
||||
|
||||
if (preserveConstEnums || useDebugMode) {
|
||||
options += " --preserveConstEnums";
|
||||
}
|
||||
|
||||
if (outDir) {
|
||||
options += " --outDir " + outDir;
|
||||
}
|
||||
|
||||
if (!noOutFile) {
|
||||
options += " --out " + outFile;
|
||||
}
|
||||
else {
|
||||
options += " --module commonjs"
|
||||
}
|
||||
|
||||
if(noResolve) {
|
||||
options += " --noResolve";
|
||||
}
|
||||
|
||||
if (useDebugMode) {
|
||||
options += " -sourcemap -mapRoot file:///" + path.resolve(path.dirname(outFile));
|
||||
}
|
||||
|
||||
if (stripInternal) {
|
||||
options += " --stripInternal"
|
||||
}
|
||||
|
||||
var cmd = host + " " + compilerPath + " " + options + " ";
|
||||
cmd = cmd + sources.join(" ");
|
||||
console.log(cmd + "\n");
|
||||
|
||||
var ex = jake.createExec([cmd]);
|
||||
// Add listeners for output and error
|
||||
ex.addListener("stdout", function(output) {
|
||||
process.stdout.write(output);
|
||||
});
|
||||
ex.addListener("stderr", function(error) {
|
||||
process.stderr.write(error);
|
||||
});
|
||||
ex.addListener("cmdEnd", function() {
|
||||
if (!useDebugMode && prefixes && fs.existsSync(outFile)) {
|
||||
for (var i in prefixes) {
|
||||
prependFile(prefixes[i], outFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
|
||||
complete();
|
||||
});
|
||||
ex.addListener("error", function() {
|
||||
fs.unlinkSync(outFile);
|
||||
fail("Compilation of " + outFile + " unsuccessful");
|
||||
});
|
||||
ex.run();
|
||||
}, {async: true});
|
||||
}
|
||||
|
||||
// Prerequisite task for built directory and library typings
|
||||
directory(builtLocalDirectory);
|
||||
|
||||
for (var i in libraryTargets) {
|
||||
(function (i) {
|
||||
var entry = librarySourceMap[i];
|
||||
var target = libraryTargets[i];
|
||||
var sources = [copyright].concat(entry.sources.map(function (s) {
|
||||
return path.join(libraryDirectory, s);
|
||||
}));
|
||||
file(target, [builtLocalDirectory].concat(sources), function() {
|
||||
concatenateFiles(target, sources);
|
||||
});
|
||||
})(i);
|
||||
}
|
||||
|
||||
// Lib target to build the library files
|
||||
desc("Builds the library targets");
|
||||
task("lib", libraryTargets);
|
||||
|
||||
|
||||
// Generate diagnostics
|
||||
var processDiagnosticMessagesJs = path.join(scriptsDirectory, "processDiagnosticMessages.js");
|
||||
var processDiagnosticMessagesTs = path.join(scriptsDirectory, "processDiagnosticMessages.ts");
|
||||
var diagnosticMessagesJson = path.join(compilerDirectory, "diagnosticMessages.json");
|
||||
var diagnosticInfoMapTs = path.join(compilerDirectory, "diagnosticInformationMap.generated.ts");
|
||||
var generatedDiagnosticMessagesJSON = path.join(compilerDirectory, "diagnosticMessages.generated.json");
|
||||
var builtGeneratedDiagnosticMessagesJSON = path.join(builtLocalDirectory, "diagnosticMessages.generated.json");
|
||||
|
||||
file(processDiagnosticMessagesTs);
|
||||
|
||||
// processDiagnosticMessages script
|
||||
compileFile(processDiagnosticMessagesJs,
|
||||
[processDiagnosticMessagesTs],
|
||||
[processDiagnosticMessagesTs],
|
||||
[],
|
||||
/*useBuiltCompiler*/ false);
|
||||
|
||||
// The generated diagnostics map; built for the compiler and for the 'generate-diagnostics' task
|
||||
file(diagnosticInfoMapTs, [processDiagnosticMessagesJs, diagnosticMessagesJson], function () {
|
||||
var cmd = host + " " + processDiagnosticMessagesJs + " " + diagnosticMessagesJson;
|
||||
console.log(cmd);
|
||||
var ex = jake.createExec([cmd]);
|
||||
// Add listeners for output and error
|
||||
ex.addListener("stdout", function(output) {
|
||||
process.stdout.write(output);
|
||||
});
|
||||
ex.addListener("stderr", function(error) {
|
||||
process.stderr.write(error);
|
||||
});
|
||||
ex.addListener("cmdEnd", function() {
|
||||
complete();
|
||||
});
|
||||
ex.run();
|
||||
}, {async: true});
|
||||
|
||||
file(builtGeneratedDiagnosticMessagesJSON,[generatedDiagnosticMessagesJSON], function() {
|
||||
if (fs.existsSync(builtLocalDirectory)) {
|
||||
jake.cpR(generatedDiagnosticMessagesJSON, builtGeneratedDiagnosticMessagesJSON);
|
||||
}
|
||||
});
|
||||
|
||||
desc("Generates a diagnostic file in TypeScript based on an input JSON file");
|
||||
task("generate-diagnostics", [diagnosticInfoMapTs]);
|
||||
|
||||
// Publish nightly
|
||||
var configureNightlyJs = path.join(scriptsDirectory, "configureNightly.js");
|
||||
var configureNightlyTs = path.join(scriptsDirectory, "configureNightly.ts");
|
||||
var packageJson = "package.json";
|
||||
var programTs = path.join(compilerDirectory, "program.ts");
|
||||
|
||||
file(configureNightlyTs);
|
||||
|
||||
compileFile(/*outfile*/configureNightlyJs,
|
||||
/*sources*/ [configureNightlyTs],
|
||||
/*prereqs*/ [configureNightlyTs],
|
||||
/*prefixes*/ [],
|
||||
/*useBuiltCompiler*/ false,
|
||||
/*noOutFile*/ false,
|
||||
/*generateDeclarations*/ false,
|
||||
/*outDir*/ undefined,
|
||||
/*preserveConstEnums*/ undefined,
|
||||
/*keepComments*/ false,
|
||||
/*noResolve*/ false,
|
||||
/*stripInternal*/ false);
|
||||
|
||||
task("setDebugMode", function() {
|
||||
useDebugMode = true;
|
||||
});
|
||||
|
||||
task("configure-nightly", [configureNightlyJs], function() {
|
||||
var cmd = host + " " + configureNightlyJs + " " + packageJson + " " + programTs;
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
}, { async: true });
|
||||
|
||||
desc("Configure, build, test, and publish the nightly release.");
|
||||
task("publish-nightly", ["configure-nightly", "LKG", "clean", "setDebugMode", "runtests"], function () {
|
||||
var cmd = "npm publish --tag next";
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
});
|
||||
|
||||
var scriptsTsdJson = path.join(scriptsDirectory, "tsd.json");
|
||||
file(scriptsTsdJson);
|
||||
|
||||
task("tsd-scripts", [scriptsTsdJson], function () {
|
||||
var cmd = "tsd --config " + scriptsTsdJson + " install";
|
||||
console.log(cmd)
|
||||
exec(cmd);
|
||||
}, { async: true })
|
||||
|
||||
var importDefinitelyTypedTestsDirectory = path.join(scriptsDirectory, "importDefinitelyTypedTests");
|
||||
var importDefinitelyTypedTestsJs = path.join(importDefinitelyTypedTestsDirectory, "importDefinitelyTypedTests.js");
|
||||
var importDefinitelyTypedTestsTs = path.join(importDefinitelyTypedTestsDirectory, "importDefinitelyTypedTests.ts");
|
||||
|
||||
file(importDefinitelyTypedTestsTs);
|
||||
file(importDefinitelyTypedTestsJs, ["tsd-scripts", importDefinitelyTypedTestsTs], function () {
|
||||
var cmd = host + " " + LKGCompiler + " -p " + importDefinitelyTypedTestsDirectory;
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
}, { async: true });
|
||||
|
||||
task("importDefinitelyTypedTests", [importDefinitelyTypedTestsJs], function () {
|
||||
var cmd = host + " " + importDefinitelyTypedTestsJs + " ./ ../DefinitelyTyped";
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
}, { async: true });
|
||||
|
||||
// Local target to build the compiler and services
|
||||
var tscFile = path.join(builtLocalDirectory, compilerFilename);
|
||||
compileFile(tscFile, compilerSources, [builtLocalDirectory, copyright].concat(compilerSources), [copyright], /*useBuiltCompiler:*/ false);
|
||||
|
||||
var servicesFile = path.join(builtLocalDirectory, "typescriptServices.js");
|
||||
var standaloneDefinitionsFile = path.join(builtLocalDirectory, "typescriptServices.d.ts");
|
||||
var nodePackageFile = path.join(builtLocalDirectory, "typescript.js");
|
||||
var nodeDefinitionsFile = path.join(builtLocalDirectory, "typescript.d.ts");
|
||||
var nodeStandaloneDefinitionsFile = path.join(builtLocalDirectory, "typescript_standalone.d.ts");
|
||||
|
||||
compileFile(servicesFile, servicesSources,[builtLocalDirectory, copyright].concat(servicesSources),
|
||||
/*prefixes*/ [copyright],
|
||||
/*useBuiltCompiler*/ true,
|
||||
/*noOutFile*/ false,
|
||||
/*generateDeclarations*/ true,
|
||||
/*outDir*/ undefined,
|
||||
/*preserveConstEnums*/ true,
|
||||
/*keepComments*/ true,
|
||||
/*noResolve*/ false,
|
||||
/*stripInternal*/ true,
|
||||
/*callback*/ function () {
|
||||
jake.cpR(servicesFile, nodePackageFile, {silent: true});
|
||||
|
||||
prependFile(copyright, standaloneDefinitionsFile);
|
||||
|
||||
// Stanalone/web definition file using global 'ts' namespace
|
||||
jake.cpR(standaloneDefinitionsFile, nodeDefinitionsFile, {silent: true});
|
||||
var definitionFileContents = fs.readFileSync(nodeDefinitionsFile).toString();
|
||||
definitionFileContents = definitionFileContents.replace(/^(\s*)(export )?const enum (\S+) {(\s*)$/gm, '$1$2enum $3 {$4');
|
||||
fs.writeFileSync(standaloneDefinitionsFile, definitionFileContents);
|
||||
|
||||
// Official node package definition file, pointed to by 'typings' in package.json
|
||||
// Created by appending 'export = ts;' at the end of the standalone file to turn it into an external module
|
||||
var nodeDefinitionsFileContents = definitionFileContents + "\r\nexport = ts;";
|
||||
fs.writeFileSync(nodeDefinitionsFile, nodeDefinitionsFileContents);
|
||||
|
||||
// Node package definition file to be distributed without the package. Created by replacing
|
||||
// 'ts' namespace with '"typescript"' as a module.
|
||||
var nodeStandaloneDefinitionsFileContents = definitionFileContents.replace(/declare (namespace|module) ts/g, 'declare module "typescript"');
|
||||
fs.writeFileSync(nodeStandaloneDefinitionsFile, nodeStandaloneDefinitionsFileContents);
|
||||
});
|
||||
|
||||
|
||||
var serverFile = path.join(builtLocalDirectory, "tsserver.js");
|
||||
compileFile(serverFile, serverSources,[builtLocalDirectory, copyright].concat(serverSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true);
|
||||
|
||||
var lsslFile = path.join(builtLocalDirectory, "tslssl.js");
|
||||
compileFile(
|
||||
lsslFile,
|
||||
languageServiceLibrarySources,
|
||||
[builtLocalDirectory, copyright].concat(languageServiceLibrarySources),
|
||||
/*prefixes*/ [copyright],
|
||||
/*useBuiltCompiler*/ true,
|
||||
/*noOutFile*/ false,
|
||||
/*generateDeclarations*/ true);
|
||||
|
||||
// Local target to build the language service server library
|
||||
desc("Builds language service server library");
|
||||
task("lssl", [lsslFile]);
|
||||
|
||||
// Local target to build the compiler and services
|
||||
desc("Builds the full compiler and services");
|
||||
task("local", ["generate-diagnostics", "lib", tscFile, servicesFile, nodeDefinitionsFile, serverFile, builtGeneratedDiagnosticMessagesJSON]);
|
||||
|
||||
// Local target to build only tsc.js
|
||||
desc("Builds only the compiler");
|
||||
task("tsc", ["generate-diagnostics", "lib", tscFile]);
|
||||
|
||||
// Local target to build the compiler and services
|
||||
desc("Sets release mode flag");
|
||||
task("release", function() {
|
||||
useDebugMode = false;
|
||||
});
|
||||
|
||||
// Set the default task to "local"
|
||||
task("default", ["local"]);
|
||||
|
||||
|
||||
// Cleans the built directory
|
||||
desc("Cleans the compiler output, declare files, and tests");
|
||||
task("clean", function() {
|
||||
jake.rmRf(builtDirectory);
|
||||
});
|
||||
|
||||
// Generate Markdown spec
|
||||
var word2mdJs = path.join(scriptsDirectory, "word2md.js");
|
||||
var word2mdTs = path.join(scriptsDirectory, "word2md.ts");
|
||||
var specWord = path.join(docDirectory, "TypeScript Language Specification.docx");
|
||||
var specMd = path.join(docDirectory, "spec.md");
|
||||
|
||||
file(word2mdTs);
|
||||
|
||||
// word2md script
|
||||
compileFile(word2mdJs,
|
||||
[word2mdTs],
|
||||
[word2mdTs],
|
||||
[],
|
||||
/*useBuiltCompiler*/ false);
|
||||
|
||||
// The generated spec.md; built for the 'generate-spec' task
|
||||
file(specMd, [word2mdJs, specWord], function () {
|
||||
var specWordFullPath = path.resolve(specWord);
|
||||
var specMDFullPath = path.resolve(specMd);
|
||||
var cmd = "cscript //nologo " + word2mdJs + ' "' + specWordFullPath + '" ' + '"' + specMDFullPath + '"';
|
||||
console.log(cmd);
|
||||
child_process.exec(cmd, function () {
|
||||
complete();
|
||||
});
|
||||
}, {async: true});
|
||||
|
||||
|
||||
desc("Generates a Markdown version of the Language Specification");
|
||||
task("generate-spec", [specMd]);
|
||||
|
||||
|
||||
// Makes a new LKG. This target does not build anything, but errors if not all the outputs are present in the built/local directory
|
||||
desc("Makes a new LKG out of the built js files");
|
||||
task("LKG", ["clean", "release", "local"].concat(libraryTargets), function() {
|
||||
var expectedFiles = [tscFile, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile].concat(libraryTargets);
|
||||
var missingFiles = expectedFiles.filter(function (f) {
|
||||
return !fs.existsSync(f);
|
||||
});
|
||||
if (missingFiles.length > 0) {
|
||||
fail("Cannot replace the LKG unless all built targets are present in directory " + builtLocalDirectory +
|
||||
". The following files are missing:\n" + missingFiles.join("\n"));
|
||||
}
|
||||
// Copy all the targets into the LKG directory
|
||||
jake.mkdirP(LKGDirectory);
|
||||
for (i in expectedFiles) {
|
||||
jake.cpR(expectedFiles[i], LKGDirectory);
|
||||
}
|
||||
//var resourceDirectories = fs.readdirSync(builtLocalResourcesDirectory).map(function(p) { return path.join(builtLocalResourcesDirectory, p); });
|
||||
//resourceDirectories.map(function(d) {
|
||||
// jake.cpR(d, LKGResourcesDirectory);
|
||||
//});
|
||||
});
|
||||
|
||||
// Test directory
|
||||
directory(builtLocalDirectory);
|
||||
|
||||
// Task to build the tests infrastructure using the built compiler
|
||||
var run = path.join(builtLocalDirectory, "run.js");
|
||||
compileFile(run, harnessSources, [builtLocalDirectory, tscFile].concat(libraryTargets).concat(harnessSources), [], /*useBuiltCompiler:*/ true);
|
||||
|
||||
var internalTests = "internal/"
|
||||
|
||||
var localBaseline = "tests/baselines/local/";
|
||||
var refBaseline = "tests/baselines/reference/";
|
||||
|
||||
var localRwcBaseline = path.join(internalTests, "baselines/rwc/local");
|
||||
var refRwcBaseline = path.join(internalTests, "baselines/rwc/reference");
|
||||
|
||||
var localTest262Baseline = path.join(internalTests, "baselines/test262/local");
|
||||
var refTest262Baseline = path.join(internalTests, "baselines/test262/reference");
|
||||
|
||||
desc("Builds the test infrastructure using the built compiler");
|
||||
task("tests", ["local", run].concat(libraryTargets));
|
||||
|
||||
function exec(cmd, completeHandler, errorHandler) {
|
||||
var ex = jake.createExec([cmd], {windowsVerbatimArguments: true});
|
||||
// Add listeners for output and error
|
||||
ex.addListener("stdout", function(output) {
|
||||
process.stdout.write(output);
|
||||
});
|
||||
ex.addListener("stderr", function(error) {
|
||||
process.stderr.write(error);
|
||||
});
|
||||
ex.addListener("cmdEnd", function() {
|
||||
if (completeHandler) {
|
||||
completeHandler();
|
||||
}
|
||||
complete();
|
||||
});
|
||||
ex.addListener("error", function(e, status) {
|
||||
if(errorHandler) {
|
||||
errorHandler(e, status);
|
||||
} else {
|
||||
fail("Process exited with code " + status);
|
||||
}
|
||||
});
|
||||
|
||||
ex.run();
|
||||
}
|
||||
|
||||
function cleanTestDirs() {
|
||||
// Clean the local baselines directory
|
||||
if (fs.existsSync(localBaseline)) {
|
||||
jake.rmRf(localBaseline);
|
||||
}
|
||||
|
||||
// Clean the local Rwc baselines directory
|
||||
if (fs.existsSync(localRwcBaseline)) {
|
||||
jake.rmRf(localRwcBaseline);
|
||||
}
|
||||
|
||||
jake.mkdirP(localRwcBaseline);
|
||||
jake.mkdirP(localTest262Baseline);
|
||||
jake.mkdirP(localBaseline);
|
||||
}
|
||||
|
||||
// used to pass data from jake command line directly to run.js
|
||||
function writeTestConfigFile(tests, light, testConfigFile) {
|
||||
console.log('Running test(s): ' + tests);
|
||||
var testConfigContents = JSON.stringify({ test: [tests], light: light });
|
||||
fs.writeFileSync('test.config', testConfigContents);
|
||||
}
|
||||
|
||||
function deleteTemporaryProjectOutput() {
|
||||
if (fs.existsSync(path.join(localBaseline, "projectOutput/"))) {
|
||||
jake.rmRf(path.join(localBaseline, "projectOutput/"));
|
||||
}
|
||||
}
|
||||
|
||||
function runConsoleTests(defaultReporter, defaultSubsets, postLint) {
|
||||
cleanTestDirs();
|
||||
var debug = process.env.debug || process.env.d;
|
||||
tests = process.env.test || process.env.tests || process.env.t;
|
||||
var light = process.env.light || false;
|
||||
var testConfigFile = 'test.config';
|
||||
if(fs.existsSync(testConfigFile)) {
|
||||
fs.unlinkSync(testConfigFile);
|
||||
}
|
||||
|
||||
if (tests || light) {
|
||||
writeTestConfigFile(tests, light, testConfigFile);
|
||||
}
|
||||
|
||||
if (tests && tests.toLocaleLowerCase() === "rwc") {
|
||||
testTimeout = 100000;
|
||||
}
|
||||
|
||||
colors = process.env.colors || process.env.color
|
||||
colors = colors ? ' --no-colors ' : ' --colors ';
|
||||
reporter = process.env.reporter || process.env.r || defaultReporter;
|
||||
|
||||
// timeout normally isn't necessary but Travis-CI has been timing out on compiler baselines occasionally
|
||||
// default timeout is 2sec which really should be enough, but maybe we just need a small amount longer
|
||||
var subsetRegexes;
|
||||
if(defaultSubsets.length === 0) {
|
||||
subsetRegexes = [tests]
|
||||
}
|
||||
else {
|
||||
var subsets = tests ? tests.split("|") : defaultSubsets;
|
||||
subsetRegexes = subsets.map(function (sub) { return "^" + sub + ".*$"; });
|
||||
subsetRegexes.push("^(?!" + subsets.join("|") + ").*$");
|
||||
}
|
||||
subsetRegexes.forEach(function (subsetRegex) {
|
||||
tests = subsetRegex ? ' -g "' + subsetRegex + '"' : '';
|
||||
var cmd = "mocha" + (debug ? " --debug-brk" : "") + " -R " + reporter + tests + colors + ' -t ' + testTimeout + ' ' + run;
|
||||
console.log(cmd);
|
||||
exec(cmd, function () {
|
||||
deleteTemporaryProjectOutput();
|
||||
if (postLint) {
|
||||
var lint = jake.Task['lint'];
|
||||
lint.addListener('complete', function () {
|
||||
complete();
|
||||
});
|
||||
lint.invoke();
|
||||
}
|
||||
else {
|
||||
complete();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var testTimeout = 20000;
|
||||
desc("Runs all the tests in parallel using the built run.js file. Optional arguments are: t[ests]=category1|category2|... d[ebug]=true.");
|
||||
task("runtests-parallel", ["build-rules", "tests", builtLocalDirectory], function() {
|
||||
runConsoleTests('min', ['compiler', 'conformance', 'Projects', 'fourslash']);
|
||||
}, {async: true});
|
||||
|
||||
desc("Runs the tests using the built run.js file. Optional arguments are: t[ests]=regex r[eporter]=[list|spec|json|<more>] d[ebug]=true color[s]=false.");
|
||||
task("runtests", ["build-rules", "tests", builtLocalDirectory], function() {
|
||||
runConsoleTests('mocha-fivemat-progress-reporter', [], /*postLint*/ true);
|
||||
}, {async: true});
|
||||
|
||||
desc("Generates code coverage data via instanbul");
|
||||
task("generate-code-coverage", ["tests", builtLocalDirectory], function () {
|
||||
var cmd = 'istanbul cover node_modules/mocha/bin/_mocha -- -R min -t ' + testTimeout + ' ' + run;
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
}, { async: true });
|
||||
|
||||
// Browser tests
|
||||
var nodeServerOutFile = 'tests/webTestServer.js'
|
||||
var nodeServerInFile = 'tests/webTestServer.ts'
|
||||
compileFile(nodeServerOutFile, [nodeServerInFile], [builtLocalDirectory, tscFile], [], /*useBuiltCompiler:*/ true, /*noOutFile*/ true);
|
||||
|
||||
desc("Runs browserify on run.js to produce a file suitable for running tests in the browser");
|
||||
task("browserify", ["tests", builtLocalDirectory, nodeServerOutFile], function() {
|
||||
var cmd = 'browserify built/local/run.js -o built/local/bundle.js';
|
||||
exec(cmd);
|
||||
}, {async: true});
|
||||
|
||||
desc("Runs the tests using the built run.js file like 'jake runtests'. Syntax is jake runtests-browser. Additional optional parameters tests=[regex], port=, browser=[chrome|IE]");
|
||||
task("runtests-browser", ["tests", "browserify", builtLocalDirectory], function() {
|
||||
cleanTestDirs();
|
||||
host = "node"
|
||||
port = process.env.port || process.env.p || '8888';
|
||||
browser = process.env.browser || process.env.b || "IE";
|
||||
tests = process.env.test || process.env.tests || process.env.t;
|
||||
var light = process.env.light || false;
|
||||
var testConfigFile = 'test.config';
|
||||
if(fs.existsSync(testConfigFile)) {
|
||||
fs.unlinkSync(testConfigFile);
|
||||
}
|
||||
if(tests || light) {
|
||||
writeTestConfigFile(tests, light, testConfigFile);
|
||||
}
|
||||
|
||||
tests = tests ? tests : '';
|
||||
var cmd = host + " tests/webTestServer.js " + port + " " + browser + " " + tests
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
}, {async: true});
|
||||
|
||||
function getDiffTool() {
|
||||
var program = process.env['DIFF']
|
||||
if (!program) {
|
||||
fail("Add the 'DIFF' environment variable to the path of the program you want to use.");
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
// Baseline Diff
|
||||
desc("Diffs the compiler baselines using the diff tool specified by the 'DIFF' environment variable");
|
||||
task('diff', function () {
|
||||
var cmd = '"' + getDiffTool() + '" ' + refBaseline + ' ' + localBaseline;
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
}, {async: true});
|
||||
|
||||
desc("Diffs the RWC baselines using the diff tool specified by the 'DIFF' environment variable");
|
||||
task('diff-rwc', function () {
|
||||
var cmd = '"' + getDiffTool() + '" ' + refRwcBaseline + ' ' + localRwcBaseline;
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
}, {async: true});
|
||||
|
||||
desc("Builds the test sources and automation in debug mode");
|
||||
task("tests-debug", ["setDebugMode", "tests"]);
|
||||
|
||||
|
||||
// Makes the test results the new baseline
|
||||
desc("Makes the most recent test results the new baseline, overwriting the old baseline");
|
||||
task("baseline-accept", function(hardOrSoft) {
|
||||
if (!hardOrSoft || hardOrSoft == "hard") {
|
||||
jake.rmRf(refBaseline);
|
||||
fs.renameSync(localBaseline, refBaseline);
|
||||
}
|
||||
else if (hardOrSoft == "soft") {
|
||||
var files = jake.readdirR(localBaseline);
|
||||
for (var i in files) {
|
||||
jake.cpR(files[i], refBaseline);
|
||||
}
|
||||
jake.rmRf(path.join(refBaseline, "local"));
|
||||
}
|
||||
});
|
||||
|
||||
desc("Makes the most recent rwc test results the new baseline, overwriting the old baseline");
|
||||
task("baseline-accept-rwc", function() {
|
||||
jake.rmRf(refRwcBaseline);
|
||||
fs.renameSync(localRwcBaseline, refRwcBaseline);
|
||||
});
|
||||
|
||||
desc("Makes the most recent test262 test results the new baseline, overwriting the old baseline");
|
||||
task("baseline-accept-test262", function() {
|
||||
jake.rmRf(refTest262Baseline);
|
||||
fs.renameSync(localTest262Baseline, refTest262Baseline);
|
||||
});
|
||||
|
||||
|
||||
// Webhost
|
||||
var webhostPath = "tests/webhost/webtsc.ts";
|
||||
var webhostJsPath = "tests/webhost/webtsc.js";
|
||||
compileFile(webhostJsPath, [webhostPath], [tscFile, webhostPath].concat(libraryTargets), [], /*useBuiltCompiler*/true);
|
||||
|
||||
desc("Builds the tsc web host");
|
||||
task("webhost", [webhostJsPath], function() {
|
||||
jake.cpR(path.join(builtLocalDirectory, "lib.d.ts"), "tests/webhost/", {silent: true});
|
||||
});
|
||||
|
||||
// Perf compiler
|
||||
var perftscPath = "tests/perftsc.ts";
|
||||
var perftscJsPath = "built/local/perftsc.js";
|
||||
compileFile(perftscJsPath, [perftscPath], [tscFile, perftscPath, "tests/perfsys.ts"].concat(libraryTargets), [], /*useBuiltCompiler*/ true);
|
||||
desc("Builds augmented version of the compiler for perf tests");
|
||||
task("perftsc", [perftscJsPath]);
|
||||
|
||||
// Instrumented compiler
|
||||
var loggedIOpath = harnessDirectory + 'loggedIO.ts';
|
||||
var loggedIOJsPath = builtLocalDirectory + 'loggedIO.js';
|
||||
file(loggedIOJsPath, [builtLocalDirectory, loggedIOpath], function() {
|
||||
var temp = builtLocalDirectory + 'temp';
|
||||
jake.mkdirP(temp);
|
||||
var options = "--outdir " + temp + ' ' + loggedIOpath;
|
||||
var cmd = host + " " + LKGDirectory + compilerFilename + " " + options + " ";
|
||||
console.log(cmd + "\n");
|
||||
var ex = jake.createExec([cmd]);
|
||||
ex.addListener("cmdEnd", function() {
|
||||
fs.renameSync(temp + '/harness/loggedIO.js', loggedIOJsPath);
|
||||
jake.rmRf(temp);
|
||||
complete();
|
||||
});
|
||||
ex.run();
|
||||
}, {async: true});
|
||||
|
||||
var instrumenterPath = harnessDirectory + 'instrumenter.ts';
|
||||
var instrumenterJsPath = builtLocalDirectory + 'instrumenter.js';
|
||||
compileFile(instrumenterJsPath, [instrumenterPath], [tscFile, instrumenterPath].concat(libraryTargets), [], /*useBuiltCompiler*/ true);
|
||||
|
||||
desc("Builds an instrumented tsc.js");
|
||||
task('tsc-instrumented', [loggedIOJsPath, instrumenterJsPath, tscFile], function() {
|
||||
var cmd = host + ' ' + instrumenterJsPath + ' record iocapture ' + builtLocalDirectory + compilerFilename;
|
||||
console.log(cmd);
|
||||
var ex = jake.createExec([cmd]);
|
||||
ex.addListener("cmdEnd", function() {
|
||||
complete();
|
||||
});
|
||||
ex.run();
|
||||
}, { async: true });
|
||||
|
||||
desc("Updates the sublime plugin's tsserver");
|
||||
task("update-sublime", ["local", serverFile], function() {
|
||||
jake.cpR(serverFile, "../TypeScript-Sublime-Plugin/tsserver/");
|
||||
jake.cpR(serverFile + ".map", "../TypeScript-Sublime-Plugin/tsserver/");
|
||||
});
|
||||
|
||||
var tslintRuleDir = "scripts/tslint";
|
||||
var tslintRules = ([
|
||||
"nextLineRule",
|
||||
"noNullRule",
|
||||
"preferConstRule",
|
||||
"booleanTriviaRule",
|
||||
"typeOperatorSpacingRule",
|
||||
"noInOperatorRule",
|
||||
"noIncrementDecrementRule"
|
||||
]);
|
||||
var tslintRulesFiles = tslintRules.map(function(p) {
|
||||
return path.join(tslintRuleDir, p + ".ts");
|
||||
});
|
||||
var tslintRulesOutFiles = tslintRules.map(function(p) {
|
||||
return path.join(builtLocalDirectory, "tslint", p + ".js");
|
||||
});
|
||||
desc("Compiles tslint rules to js");
|
||||
task("build-rules", tslintRulesOutFiles);
|
||||
tslintRulesFiles.forEach(function(ruleFile, i) {
|
||||
compileFile(tslintRulesOutFiles[i], [ruleFile], [ruleFile], [], /*useBuiltCompiler*/ false, /*noOutFile*/ true, /*generateDeclarations*/ false, path.join(builtLocalDirectory, "tslint"));
|
||||
});
|
||||
|
||||
function getLinterOptions() {
|
||||
return {
|
||||
configuration: require("./tslint.json"),
|
||||
formatter: "prose",
|
||||
formattersDirectory: undefined,
|
||||
rulesDirectory: "built/local/tslint"
|
||||
};
|
||||
}
|
||||
|
||||
function lintFileContents(options, path, contents) {
|
||||
var ll = new Linter(path, contents, options);
|
||||
console.log("Linting '" + path + "'.")
|
||||
return ll.lint();
|
||||
}
|
||||
|
||||
function lintFile(options, path) {
|
||||
var contents = fs.readFileSync(path, "utf8");
|
||||
return lintFileContents(options, path, contents);
|
||||
}
|
||||
|
||||
function lintFileAsync(options, path, cb) {
|
||||
fs.readFile(path, "utf8", function(err, contents) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
var result = lintFileContents(options, path, contents);
|
||||
cb(undefined, result);
|
||||
});
|
||||
}
|
||||
|
||||
var servicesLintTargets = [
|
||||
"navigateTo.ts",
|
||||
"outliningElementsCollector.ts",
|
||||
"patternMatcher.ts",
|
||||
"services.ts",
|
||||
"shims.ts",
|
||||
].map(function (s) {
|
||||
return path.join(servicesDirectory, s);
|
||||
});
|
||||
var lintTargets = compilerSources
|
||||
.concat(harnessCoreSources)
|
||||
.concat(serverCoreSources)
|
||||
.concat(tslintRulesFiles)
|
||||
.concat(servicesLintTargets);
|
||||
|
||||
desc("Runs tslint on the compiler sources");
|
||||
task("lint", ["build-rules"], function() {
|
||||
var lintOptions = getLinterOptions();
|
||||
var failed = 0;
|
||||
for (var i in lintTargets) {
|
||||
var result = lintFile(lintOptions, lintTargets[i]);
|
||||
if (result.failureCount > 0) {
|
||||
console.log(result.output);
|
||||
failed += result.failureCount;
|
||||
}
|
||||
}
|
||||
if (failed > 0) {
|
||||
fail('Linter errors.', failed);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* This is required because file watches on Windows get fires _twice_
|
||||
* when a file changes on some node/windows version configuations
|
||||
* (node v4 and win 10, for example). By not running a lint for a file
|
||||
* which already has a pending lint, we avoid duplicating our work.
|
||||
* (And avoid printing duplicate results!)
|
||||
*/
|
||||
var lintSemaphores = {};
|
||||
|
||||
function lintWatchFile(filename) {
|
||||
fs.watch(filename, {persistent: true}, function(event) {
|
||||
if (event !== "change") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!lintSemaphores[filename]) {
|
||||
lintSemaphores[filename] = true;
|
||||
lintFileAsync(getLinterOptions(), filename, function(err, result) {
|
||||
delete lintSemaphores[filename];
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
if (result.failureCount > 0) {
|
||||
console.log("***Lint failure***");
|
||||
for (var i = 0; i < result.failures.length; i++) {
|
||||
var failure = result.failures[i];
|
||||
var start = failure.startPosition.lineAndCharacter;
|
||||
var end = failure.endPosition.lineAndCharacter;
|
||||
console.log("warning " + filename + " (" + (start.line + 1) + "," + (start.character + 1) + "," + (end.line + 1) + "," + (end.character + 1) + "): " + failure.failure);
|
||||
}
|
||||
console.log("*** Total " + result.failureCount + " failures.");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
desc("Watches files for changes to rerun a lint pass");
|
||||
task("lint-server", ["build-rules"], function() {
|
||||
console.log("Watching ./src for changes to linted files");
|
||||
for (var i = 0; i < lintTargets.length; i++) {
|
||||
lintWatchFile(lintTargets[i]);
|
||||
}
|
||||
});
|
||||
@@ -1,13 +1,26 @@
|
||||
[](https://travis-ci.org/Microsoft/TypeScript)
|
||||
[](http://issuestats.com/github/microsoft/typescript)
|
||||
[](http://issuestats.com/github/microsoft/typescript)
|
||||
[](http://badge.fury.io/js/typescript)
|
||||
[](https://npmjs.org/package/typescript)
|
||||
[](https://www.npmjs.com/package/typescript)
|
||||
[](https://www.npmjs.com/package/typescript)
|
||||
|
||||
# TypeScript
|
||||
|
||||
[TypeScript](http://www.typescriptlang.org/) is a language for application-scale JavaScript. TypeScript adds optional types, classes, and modules to JavaScript. TypeScript supports tools for large-scale JavaScript applications for any browser, for any host, on any OS. TypeScript compiles to readable, standards-based JavaScript. Try it out at the [playground](http://www.typescriptlang.org/Playground), and stay up to date via [our blog](http://blogs.msdn.com/typescript) and [twitter account](https://twitter.com/typescriptlang).
|
||||
[](https://gitter.im/Microsoft/TypeScript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
[TypeScript](http://www.typescriptlang.org/) is a language for application-scale JavaScript. TypeScript adds optional types, classes, and modules to JavaScript. TypeScript supports tools for large-scale JavaScript applications for any browser, for any host, on any OS. TypeScript compiles to readable, standards-based JavaScript. Try it out at the [playground](http://www.typescriptlang.org/Playground), and stay up to date via [our blog](http://blogs.msdn.com/typescript) and [Twitter account](https://twitter.com/typescriptlang).
|
||||
|
||||
## Installing
|
||||
|
||||
For the latest stable version:
|
||||
|
||||
```
|
||||
npm install -g typescript
|
||||
```
|
||||
|
||||
For our nightly builds:
|
||||
|
||||
```
|
||||
npm install -g typescript@next
|
||||
```
|
||||
|
||||
## Contribute
|
||||
|
||||
@@ -17,7 +30,7 @@ There are many ways to [contribute](https://github.com/Microsoft/TypeScript/blob
|
||||
* Engage with other TypeScript users and developers on [StackOverflow](http://stackoverflow.com/questions/tagged/typescript).
|
||||
* Join the [#typescript](http://twitter.com/#!/search/realtime/%23typescript) discussion on Twitter.
|
||||
* [Contribute bug fixes](https://github.com/Microsoft/TypeScript/blob/master/CONTRIBUTING.md).
|
||||
* Read the language specification ([docx](http://go.microsoft.com/fwlink/?LinkId=267121), [pdf](http://go.microsoft.com/fwlink/?LinkId=267238)).
|
||||
* Read the language specification ([docx](https://github.com/Microsoft/TypeScript/blob/master/doc/TypeScript%20Language%20Specification.docx?raw=true), [pdf](https://github.com/Microsoft/TypeScript/blob/master/doc/TypeScript%20Language%20Specification.pdf?raw=true), [md](https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md)).
|
||||
|
||||
|
||||
## Documentation
|
||||
@@ -63,7 +76,8 @@ jake runtests # Run tests using the built compiler and test infrastructu
|
||||
# Use host=<hostName> or tests=<testPath>.
|
||||
jake runtests-browser # Runs the tests using the built run.js file. Syntax is jake runtests. Optional
|
||||
parameters 'host=', 'tests=[regex], reporter=[list|spec|json|<more>]'.
|
||||
jake baseline-accept # This replaces the baseline test results with the results obtained from jake runtests.
|
||||
jake baseline-accept # This replaces the baseline test results with the results obtained from jake runtests.
|
||||
jake lint # Runs tslint on the TypeScript source.
|
||||
jake -T # List the above commands.
|
||||
```
|
||||
|
||||
|
||||
Vendored
-1186
File diff suppressed because it is too large
Load Diff
Vendored
-16771
File diff suppressed because it is too large
Load Diff
Vendored
-3221
File diff suppressed because it is too large
Load Diff
@@ -1,2 +1,2 @@
|
||||
#!/usr/bin/env node
|
||||
require('./tsc.js')
|
||||
require('../lib/tsc.js')
|
||||
|
||||
-25497
File diff suppressed because one or more lines are too long
Regular → Executable
+1
-1
@@ -1,2 +1,2 @@
|
||||
#!/usr/bin/env node
|
||||
require('./tsserver.js')
|
||||
require('../lib/tsserver.js')
|
||||
|
||||
-37111
File diff suppressed because one or more lines are too long
Vendored
-1769
File diff suppressed because it is too large
Load Diff
-41175
File diff suppressed because one or more lines are too long
Vendored
-1769
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,7 @@
|
||||
This directory contains miscellaneous documentation such as the TypeScript language specification and logo.
|
||||
If you are looking for more introductory material, you might want to take a look at the [TypeScript Handbook](https://github.com/Microsoft/TypeScript-Handbook).
|
||||
|
||||
# Spec Contributions
|
||||
|
||||
The specification is first authored as a Microsoft Word (docx) file and then generated into Markdown and PDF formats.
|
||||
Due to the binary format of docx files, and the merging difficulties that may come with it, it is preferred that any suggestions or problems found in the spec should be [filed as issues](https://github.com/Microsoft/TypeScript/issues/new) rather than sent as pull requests.
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.9 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
+1893
-1267
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
# Read this!
|
||||
|
||||
These files are not meant to be edited by hand.
|
||||
If you need to make modifications, the respective files should be changed within the repository's top-level `src` directory. Running `jake LKG` will then appropriately update the files in this directory.
|
||||
Vendored
+3839
File diff suppressed because it is too large
Load Diff
+1313
-977
File diff suppressed because it is too large
Load Diff
Vendored
+17308
File diff suppressed because it is too large
Load Diff
Vendored
+292
-2408
File diff suppressed because it is too large
Load Diff
Vendored
+1728
-1325
File diff suppressed because it is too large
Load Diff
Vendored
+1210
File diff suppressed because it is too large
Load Diff
+34096
File diff suppressed because one or more lines are too long
+47363
File diff suppressed because one or more lines are too long
Vendored
+2319
File diff suppressed because it is too large
Load Diff
+53338
File diff suppressed because one or more lines are too long
Vendored
+2317
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
+24
-11
@@ -2,13 +2,8 @@
|
||||
"name": "typescript",
|
||||
"author": "Microsoft Corp.",
|
||||
"homepage": "http://typescriptlang.org/",
|
||||
"version": "1.5.0",
|
||||
"licenses": [
|
||||
{
|
||||
"type": "Apache License 2.0",
|
||||
"url": "https://github.com/Microsoft/TypeScript/blob/master/LICENSE.txt"
|
||||
}
|
||||
],
|
||||
"version": "1.8.0",
|
||||
"license": "Apache-2.0",
|
||||
"description": "TypeScript is a language for application scale JavaScript development",
|
||||
"keywords": [
|
||||
"TypeScript",
|
||||
@@ -24,8 +19,8 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/Microsoft/TypeScript.git"
|
||||
},
|
||||
"preferGlobal": true,
|
||||
"main": "./bin/typescript.js",
|
||||
"main": "./lib/typescript.js",
|
||||
"typings": "./lib/typescript.d.ts",
|
||||
"bin": {
|
||||
"tsc": "./bin/tsc",
|
||||
"tsserver": "./bin/tsserver"
|
||||
@@ -38,9 +33,27 @@
|
||||
"mocha": "latest",
|
||||
"chai": "latest",
|
||||
"browserify": "latest",
|
||||
"istanbul": "latest"
|
||||
"istanbul": "latest",
|
||||
"mocha-fivemat-progress-reporter": "latest",
|
||||
"tslint": "next",
|
||||
"typescript": "next",
|
||||
"tsd": "latest"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "jake runtests"
|
||||
"pretest": "jake tests",
|
||||
"test": "jake runtests",
|
||||
"build": "npm run build:compiler && npm run build:tests",
|
||||
"build:compiler": "jake local",
|
||||
"build:tests": "jake tests",
|
||||
"clean": "jake clean",
|
||||
"jake": "jake",
|
||||
"lint": "jake lint",
|
||||
"setup-hooks": "node scripts/link-hooks.js"
|
||||
},
|
||||
"browser": {
|
||||
"buffer": false,
|
||||
"fs": false,
|
||||
"os": false,
|
||||
"path": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/// <reference path="../src/compiler/sys.ts" />
|
||||
|
||||
/**
|
||||
* A minimal description for a parsed package.json object.
|
||||
*/
|
||||
interface PackageJson {
|
||||
name: string;
|
||||
version: string;
|
||||
keywords: string[];
|
||||
}
|
||||
|
||||
function main(): void {
|
||||
const sys = ts.sys;
|
||||
if (sys.args.length < 2) {
|
||||
sys.write("Usage:" + sys.newLine)
|
||||
sys.write("\tnode configureNightly.js <package.json location> <file containing version>" + sys.newLine);
|
||||
return;
|
||||
}
|
||||
|
||||
// Acquire the version from the package.json file and modify it appropriately.
|
||||
const packageJsonFilePath = ts.normalizePath(sys.args[0]);
|
||||
const packageJsonContents = sys.readFile(packageJsonFilePath);
|
||||
const packageJsonValue: PackageJson = JSON.parse(packageJsonContents);
|
||||
|
||||
const nightlyVersion = getNightlyVersionString(packageJsonValue.version);
|
||||
|
||||
// Modify the package.json structure
|
||||
packageJsonValue.version = nightlyVersion;
|
||||
|
||||
// Acquire and modify the source file that exposes the version string.
|
||||
const tsFilePath = ts.normalizePath(sys.args[1]);
|
||||
const tsFileContents = sys.readFile(tsFilePath);
|
||||
const versionAssignmentRegExp = /export\s+const\s+version\s+=\s+".*";/;
|
||||
const modifiedTsFileContents = tsFileContents.replace(versionAssignmentRegExp, `export const version = "${nightlyVersion}";`);
|
||||
|
||||
// Ensure we are actually changing something - the user probably wants to know that the update failed.
|
||||
if (tsFileContents === modifiedTsFileContents) {
|
||||
let err = `\n '${tsFilePath}' was not updated while configuring for a nightly publish.\n `;
|
||||
|
||||
if (tsFileContents.match(versionAssignmentRegExp)) {
|
||||
err += `Ensure that you have not already run this script; otherwise, erase your changes using 'git checkout -- "${tsFilePath}"'.`;
|
||||
}
|
||||
else {
|
||||
err += `The file seems to no longer have a string matching '${versionAssignmentRegExp}'.`;
|
||||
}
|
||||
|
||||
throw err + "\n";
|
||||
}
|
||||
|
||||
// Finally write the changes to disk.
|
||||
sys.writeFile(packageJsonFilePath, JSON.stringify(packageJsonValue, /*replacer:*/ undefined, /*space:*/ 4))
|
||||
sys.writeFile(tsFilePath, modifiedTsFileContents);
|
||||
}
|
||||
|
||||
function getNightlyVersionString(versionString: string): string {
|
||||
// If the version string already contains "-nightly",
|
||||
// then get the base string and update based on that.
|
||||
const dashNightlyPos = versionString.indexOf("-dev");
|
||||
if (dashNightlyPos >= 0) {
|
||||
versionString = versionString.slice(0, dashNightlyPos);
|
||||
}
|
||||
|
||||
// We're going to append a representation of the current time at the end of the current version.
|
||||
// String.prototype.toISOString() returns a 24-character string formatted as 'YYYY-MM-DDTHH:mm:ss.sssZ',
|
||||
// but we'd prefer to just remove separators and limit ourselves to YYYYMMDD.
|
||||
// UTC time will always be implicit here.
|
||||
const now = new Date();
|
||||
const timeStr = now.toISOString().replace(/:|T|\.|-/g, "").slice(0, 8);
|
||||
|
||||
return `${versionString}-dev.${timeStr}`;
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,124 @@
|
||||
/// <reference path="../src/harness/external/node.d.ts" />
|
||||
/// <reference path="../built/local/typescript.d.ts" />
|
||||
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import * as typescript from "typescript";
|
||||
declare var ts: typeof typescript;
|
||||
|
||||
var tsSourceDir = "../src";
|
||||
var tsBuildDir = "../built/local";
|
||||
var testOutputDir = "../built/benchmark";
|
||||
var sourceFiles = [
|
||||
"compiler/types.ts",
|
||||
"compiler/core.ts",
|
||||
"compiler/sys.ts",
|
||||
"compiler/diagnosticInformationMap.generated.ts",
|
||||
"compiler/scanner.ts",
|
||||
"compiler/binder.ts",
|
||||
"compiler/utilities.ts",
|
||||
"compiler/parser.ts",
|
||||
"compiler/checker.ts",
|
||||
"compiler/declarationEmitter.ts",
|
||||
"compiler/emitter.ts",
|
||||
"compiler/program.ts",
|
||||
"compiler/commandLineParser.ts",
|
||||
"compiler/tsc.ts"];
|
||||
|
||||
// .ts sources for the compiler, used as a test input
|
||||
var rawCompilerSources = "";
|
||||
sourceFiles.forEach(f=> {
|
||||
rawCompilerSources += "\r\n" + fs.readFileSync(path.join(tsSourceDir, f)).toString();
|
||||
});
|
||||
var compilerSoruces = `var compilerSources = ${JSON.stringify(rawCompilerSources) };`;
|
||||
|
||||
// .js code for the compiler, what we are actuallty testing
|
||||
var rawCompilerJavaScript = fs.readFileSync(path.join(tsBuildDir, "tsc.js")).toString();
|
||||
rawCompilerJavaScript = rawCompilerJavaScript.replace("ts.executeCommandLine(ts.sys.args);", "");
|
||||
|
||||
// lib.d.ts sources
|
||||
var rawLibSources = fs.readFileSync(path.join(tsBuildDir, "lib.d.ts")).toString();
|
||||
var libSoruces = `var libSources = ${JSON.stringify(rawLibSources) };`;
|
||||
|
||||
// write test output
|
||||
if (!fs.existsSync(testOutputDir)) {
|
||||
fs.mkdirSync(testOutputDir);
|
||||
}
|
||||
|
||||
// 1. compiler ts sources, used to test
|
||||
fs.writeFileSync(
|
||||
path.join(testOutputDir, "compilerSources.js"),
|
||||
`${ compilerSoruces } \r\n ${ libSoruces }`);
|
||||
|
||||
// 2. the compiler js sources + a call the compiler
|
||||
fs.writeFileSync(
|
||||
path.join(testOutputDir, "benchmarktsc.js"),
|
||||
`${ rawCompilerJavaScript }\r\n${ compile.toString() }\r\ncompile(compilerSources, libSources);`);
|
||||
|
||||
// 3. test html file to drive the test
|
||||
fs.writeFileSync(
|
||||
path.join(testOutputDir, "benchmarktsc.html"),
|
||||
`<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
|
||||
<title>Typescript 1.1 Compiler</title>
|
||||
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
|
||||
</head>
|
||||
<body>
|
||||
<div><span>Status: </span><span id="status">Running</span></div>
|
||||
<div id="main"><span>End-to-End Time: </span><span id="totalTime">N/A</span></div>
|
||||
<script>
|
||||
var startTime = performance.now();
|
||||
</script>
|
||||
<script src="compilerSources.js"></script>
|
||||
<script src="benchmarktsc.js"></script>
|
||||
<script>
|
||||
var endTime = performance.now();
|
||||
document.getElementById("totalTime").innerHTML = parseInt(endTime - startTime, 10);
|
||||
document.getElementById("status").innerHTML = "DONE";
|
||||
</script>
|
||||
</body>
|
||||
</html>`);
|
||||
|
||||
function compile(compilerSources, librarySources) {
|
||||
var program = ts.createProgram(
|
||||
["lib.d.ts", "compiler.ts"],
|
||||
{
|
||||
noResolve: true,
|
||||
out: "compiler.js",
|
||||
removeComments: true,
|
||||
target: ts.ScriptTarget.ES3
|
||||
}, {
|
||||
getDefaultLibFileName: () => "lib.d.ts",
|
||||
getSourceFile: (filename, languageVersion) => {
|
||||
var source: string;
|
||||
if (filename === "lib.d.ts") source = librarySources;
|
||||
else if (filename === "compiler.ts") source = compilerSources;
|
||||
else console.error("Unexpected read file request: " + filename);
|
||||
|
||||
return ts.createSourceFile(filename, source, languageVersion);
|
||||
},
|
||||
writeFile: (filename, data, writeByteOrderMark) => {
|
||||
if (filename !== "compiler.js")
|
||||
console.error("Unexpected write file request: " + filename);
|
||||
// console.log(data);
|
||||
},
|
||||
getCurrentDirectory: () => "",
|
||||
getCanonicalFileName: (filename) => filename,
|
||||
useCaseSensitiveFileNames: () => false,
|
||||
getNewLine: () => "\r\n"
|
||||
});
|
||||
|
||||
var emitOutput = program.emit();
|
||||
|
||||
var errors = program.getSyntacticDiagnostics()
|
||||
.concat(program.getSemanticDiagnostics())
|
||||
.concat(program.getGlobalDiagnostics())
|
||||
.concat(emitOutput.diagnostics);
|
||||
|
||||
if (errors.length) {
|
||||
console.error("Unexpected errors.");
|
||||
errors.forEach(e=> console.log(`${e.code}: ${e.messageText}`))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
declare var require: any;
|
||||
let fs = require('fs');
|
||||
let async = require('async');
|
||||
let glob = require('glob');
|
||||
|
||||
fs.readFile('src/compiler/diagnosticMessages.json', 'utf-8', (err, data) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
let messages = JSON.parse(data);
|
||||
let keys = Object.keys(messages);
|
||||
console.log('Loaded ' + keys.length + ' errors');
|
||||
|
||||
for (let k of keys) {
|
||||
messages[k]['seen'] = false;
|
||||
}
|
||||
|
||||
let errRegex = /\(\d+,\d+\): error TS([^:]+):/g;
|
||||
|
||||
let baseDir = 'tests/baselines/reference/';
|
||||
fs.readdir(baseDir, (err, files) => {
|
||||
files = files.filter(f => f.indexOf('.errors.txt') > 0);
|
||||
let tasks: Array<(callback: () => void) => void> = [];
|
||||
files.forEach(f => tasks.push(done => {
|
||||
fs.readFile(baseDir + f, 'utf-8', (err, baseline) => {
|
||||
if (err) throw err;
|
||||
|
||||
let g: string[];
|
||||
while (g = errRegex.exec(baseline)) {
|
||||
var errCode = +g[1];
|
||||
let msg = keys.filter(k => messages[k].code === errCode)[0];
|
||||
messages[msg]['seen'] = true;
|
||||
}
|
||||
|
||||
done();
|
||||
});
|
||||
}));
|
||||
|
||||
async.parallelLimit(tasks, 25, done => {
|
||||
console.log('== List of errors not present in baselines ==');
|
||||
let count = 0;
|
||||
for (let k of keys) {
|
||||
if (messages[k]['seen'] !== true) {
|
||||
console.log(k);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
console.log(count + ' of ' + keys.length + ' errors are not in baselines');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
fs.readFile('src/compiler/diagnosticInformationMap.generated.ts', 'utf-8', (err, data) => {
|
||||
let errorRegexp = /\s(\w+): \{ code/g;
|
||||
let errorNames: string[] = [];
|
||||
let errMatch: string[];
|
||||
while (errMatch = errorRegexp.exec(data)) {
|
||||
errorNames.push(errMatch[1]);
|
||||
}
|
||||
|
||||
let allSrc: string = '';
|
||||
glob('./src/**/*.ts', {}, (err, files) => {
|
||||
console.log('Reading ' + files.length + ' source files');
|
||||
for (let file of files) {
|
||||
if (file.indexOf('diagnosticInformationMap.generated.ts') > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let src = fs.readFileSync(file, 'utf-8');
|
||||
allSrc = allSrc + src;
|
||||
}
|
||||
|
||||
console.log('Consumed ' + allSrc.length + ' characters of source');
|
||||
|
||||
let count = 0;
|
||||
console.log('== List of errors not used in source ==');
|
||||
for (let errName of errorNames) {
|
||||
if (allSrc.indexOf(errName) < 0) {
|
||||
console.log(errName);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
console.log(count + ' of ' + errorNames.length + ' errors are not used in source');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
npm run jake -- generate-diagnostics
|
||||
@@ -1,125 +0,0 @@
|
||||
declare var require: any, process: any;
|
||||
declare var __dirname: any;
|
||||
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
var child_process = require('child_process');
|
||||
|
||||
var tscRoot = path.join(__dirname, "..\\");
|
||||
var tscPath = path.join(tscRoot, "built", "instrumented", "tsc.js");
|
||||
var rwcTestPath = path.join(tscRoot, "tests", "cases", "rwc", "dt");
|
||||
var definitelyTypedRoot = process.argv[2];
|
||||
|
||||
function fileExtensionIs(path: string, extension: string): boolean {
|
||||
var pathLen = path.length;
|
||||
var extLen = extension.length;
|
||||
return pathLen > extLen && path.substr(pathLen - extLen, extLen).toLocaleLowerCase() === extension.toLocaleLowerCase();
|
||||
}
|
||||
|
||||
function copyFileSync(source, destination) {
|
||||
var text = fs.readFileSync(source);
|
||||
fs.writeFileSync(destination, text);
|
||||
}
|
||||
|
||||
function importDefinitelyTypedTest(testCaseName: string, testFiles: string[], responseFile: string ) {
|
||||
var cmd = "node " + tscPath + " --module commonjs " + testFiles.join(" ");
|
||||
if (responseFile) cmd += " @" + responseFile;
|
||||
|
||||
var testDirectoryName = testCaseName + "_" + Math.floor((Math.random() * 10000) + 1);
|
||||
var testDirectoryPath = path.join(process.env["temp"], testDirectoryName);
|
||||
if (fs.existsSync(testDirectoryPath)) {
|
||||
throw new Error("Could not create test directory");
|
||||
}
|
||||
fs.mkdirSync(testDirectoryPath);
|
||||
|
||||
child_process.exec(cmd, {
|
||||
maxBuffer: 1 * 1024 * 1024,
|
||||
cwd: testDirectoryPath
|
||||
}, (error, stdout, stderr) => {
|
||||
console.log("importing " + testCaseName + " ...");
|
||||
console.log(cmd);
|
||||
|
||||
if (error) {
|
||||
console.log("importing " + testCaseName + " ...");
|
||||
console.log(cmd);
|
||||
console.log("==> error " + JSON.stringify(error));
|
||||
console.log("==> stdout " + String(stdout));
|
||||
console.log("==> stderr " + String(stderr));
|
||||
console.log("\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// copy generated file to output location
|
||||
var outputFilePath = path.join(testDirectoryPath, "iocapture0.json");
|
||||
var testCasePath = path.join(rwcTestPath, "DefinitelyTyped_" + testCaseName + ".json");
|
||||
copyFileSync(outputFilePath, testCasePath);
|
||||
|
||||
//console.log("output generated at: " + outputFilePath);
|
||||
|
||||
if (!fs.existsSync(testCasePath)) {
|
||||
throw new Error("could not find test case at: " + testCasePath);
|
||||
}
|
||||
else {
|
||||
fs.unlinkSync(outputFilePath);
|
||||
fs.rmdirSync(testDirectoryPath);
|
||||
//console.log("testcase generated at: " + testCasePath);
|
||||
//console.log("Done.");
|
||||
}
|
||||
//console.log("\r\n");
|
||||
|
||||
})
|
||||
.on('error', function (error) {
|
||||
console.log("==> error " + JSON.stringify(error));
|
||||
console.log("\r\n");
|
||||
});
|
||||
}
|
||||
|
||||
function importDefinitelyTypedTests(definitelyTypedRoot: string): void {
|
||||
fs.readdir(definitelyTypedRoot, (err, subDirectorys) => {
|
||||
if (err) throw err;
|
||||
|
||||
subDirectorys
|
||||
.filter(d => ["_infrastructure", "node_modules", ".git"].indexOf(d) < 0)
|
||||
.filter(i => i.indexOf("sipml") >=0 )
|
||||
.filter(i => fs.statSync(path.join(definitelyTypedRoot, i)).isDirectory())
|
||||
.forEach(d => {
|
||||
var directoryPath = path.join(definitelyTypedRoot, d);
|
||||
fs.readdir(directoryPath, function (err, files) {
|
||||
if (err) throw err;
|
||||
|
||||
var tsFiles = [];
|
||||
var testFiles = [];
|
||||
var paramFile;
|
||||
|
||||
files
|
||||
.map(f => path.join(directoryPath, f))
|
||||
.forEach(f => {
|
||||
if (fileExtensionIs(f, ".ts")) tsFiles.push(f);
|
||||
else if (fileExtensionIs(f, ".tscparams")) paramFile = f;
|
||||
|
||||
if (fileExtensionIs(f, "-tests.ts")) testFiles.push(f);
|
||||
});
|
||||
|
||||
if (testFiles.length === 0) {
|
||||
// no test files but multiple d.ts's, e.g. winjs
|
||||
var regexp = new RegExp(d + "(([-][0-9])|([\.]d[\.]ts))");
|
||||
if (tsFiles.length > 1 && tsFiles.every(t => fileExtensionIs(t, ".d.ts") && regexp.test(t))) {
|
||||
tsFiles.forEach(filename => {
|
||||
importDefinitelyTypedTest(path.basename(filename, ".d.ts"), [filename], paramFile);
|
||||
});
|
||||
}
|
||||
else {
|
||||
importDefinitelyTypedTest(d, tsFiles, paramFile);
|
||||
}
|
||||
}
|
||||
else {
|
||||
testFiles.forEach(filename => {
|
||||
importDefinitelyTypedTest(path.basename(filename, "-tests.ts"), [filename], paramFile);
|
||||
});
|
||||
}
|
||||
});
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
importDefinitelyTypedTests(definitelyTypedRoot);
|
||||
@@ -0,0 +1,161 @@
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import * as child_process from "child_process";
|
||||
|
||||
|
||||
interface Map<T> {
|
||||
[key: string]: T;
|
||||
}
|
||||
|
||||
declare var process: {
|
||||
argv: string[];
|
||||
env: Map<string>;
|
||||
exit(exitCode?: number): void;
|
||||
}
|
||||
|
||||
main();
|
||||
function main() {
|
||||
const [, progName, tscRoot, definitelyTypedRoot] = process.argv;
|
||||
if (process.argv.length !== 4) {
|
||||
if (process.argv.length < 2) {
|
||||
throw "Expected at least 2 argv elements."
|
||||
}
|
||||
console.log("Usage:")
|
||||
console.log(` node ${path.relative(__dirname, progName)} [TypeScript Repo Root] [DefinitelyTyped Repo Root]`);
|
||||
return;
|
||||
}
|
||||
|
||||
const tscPath = path.resolve(tscRoot, "built", "local", "tsc.js");
|
||||
const rwcTestPath = path.resolve(tscRoot, "internal", "cases", "rwc");
|
||||
const resolvedDefinitelyTypedRoot = path.resolve(definitelyTypedRoot);
|
||||
|
||||
console.log(`Resolved TypeScript Compiler Path: '${tscPath}'.`);
|
||||
console.log(`Resolved TypeScript RWC Path: '${rwcTestPath}'.`);
|
||||
console.log(`Resolved DefinitelyTyped Repo Root: '${resolvedDefinitelyTypedRoot}'.`);
|
||||
importDefinitelyTypedTests(tscPath, rwcTestPath, resolvedDefinitelyTypedRoot);
|
||||
}
|
||||
|
||||
function filePathEndsWith(path: string, endingString: string): boolean {
|
||||
const pathLen = path.length;
|
||||
const extLen = endingString.length;
|
||||
return pathLen > extLen && path.substr(pathLen - extLen, extLen).toLocaleLowerCase() === endingString.toLocaleLowerCase();
|
||||
}
|
||||
|
||||
function copyFileSync(source: string, destination: string) {
|
||||
let text = fs.readFileSync(source);
|
||||
fs.writeFileSync(destination, text);
|
||||
}
|
||||
|
||||
function importDefinitelyTypedTest(tscPath: string, rwcTestPath: string, testCaseName: string, testFiles: string[], responseFile: string ) {
|
||||
let cmd = "node " + tscPath + " --module commonjs " + testFiles.join(" ");
|
||||
if (responseFile) {
|
||||
cmd += " @" + responseFile;
|
||||
}
|
||||
|
||||
let testDirectoryName = testCaseName + "_" + Math.floor((Math.random() * 10000) + 1);
|
||||
let testDirectoryPath = path.join(process.env["temp"], testDirectoryName);
|
||||
if (fs.existsSync(testDirectoryPath)) {
|
||||
throw new Error("Could not create test directory");
|
||||
}
|
||||
fs.mkdirSync(testDirectoryPath);
|
||||
|
||||
child_process.exec(cmd, {
|
||||
maxBuffer: 1 * 1024 * 1024,
|
||||
cwd: testDirectoryPath
|
||||
}, (error, stdout, stderr) => {
|
||||
console.log("importing " + testCaseName + " ...");
|
||||
console.log(cmd);
|
||||
|
||||
if (error) {
|
||||
console.log("importing " + testCaseName + " ...");
|
||||
console.log(cmd);
|
||||
console.log("==> error " + JSON.stringify(error));
|
||||
console.log("==> stdout " + String(stdout));
|
||||
console.log("==> stderr " + String(stderr));
|
||||
console.log("\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// copy generated file to output location
|
||||
let outputFilePath = path.join(testDirectoryPath, "iocapture0.json");
|
||||
let testCasePath = path.join(rwcTestPath, "DefinitelyTyped_" + testCaseName + ".json");
|
||||
copyFileSync(outputFilePath, testCasePath);
|
||||
|
||||
//console.log("output generated at: " + outputFilePath);
|
||||
|
||||
if (!fs.existsSync(testCasePath)) {
|
||||
throw new Error("could not find test case at: " + testCasePath);
|
||||
}
|
||||
else {
|
||||
fs.unlinkSync(outputFilePath);
|
||||
fs.rmdirSync(testDirectoryPath);
|
||||
//console.log("testcase generated at: " + testCasePath);
|
||||
//console.log("Done.");
|
||||
}
|
||||
//console.log("\r\n");
|
||||
|
||||
})
|
||||
.on('error', (error: any) => {
|
||||
console.log("==> error " + JSON.stringify(error));
|
||||
console.log("\r\n");
|
||||
});
|
||||
}
|
||||
|
||||
function importDefinitelyTypedTests(tscPath: string, rwcTestPath: string, definitelyTypedRoot: string): void {
|
||||
fs.readdir(definitelyTypedRoot, (err, subDirectories) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
// When you just want to test the script out on one or two files,
|
||||
// just add a line like the following:
|
||||
//
|
||||
// .filter(d => d.indexOf("sipml") >= 0 )
|
||||
subDirectories
|
||||
.filter(d => ["_infrastructure", "node_modules", ".git"].indexOf(d) < 0)
|
||||
.filter(i => fs.statSync(path.join(definitelyTypedRoot, i)).isDirectory())
|
||||
.forEach(d => {
|
||||
const directoryPath = path.join(definitelyTypedRoot, d);
|
||||
fs.readdir(directoryPath, function (err, files) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
let tsFiles: string[] = [];
|
||||
let testFiles: string[] = [];
|
||||
let paramFile: string;
|
||||
|
||||
for (const filePath of files.map(f => path.join(directoryPath, f))) {
|
||||
if (filePathEndsWith(filePath, ".ts")) {
|
||||
tsFiles.push(filePath);
|
||||
|
||||
if (filePathEndsWith(filePath, "-tests.ts")) {
|
||||
testFiles.push(filePath);
|
||||
}
|
||||
}
|
||||
else if (filePathEndsWith(filePath, ".tscparams")) {
|
||||
paramFile = filePath;
|
||||
}
|
||||
}
|
||||
|
||||
if (testFiles.length === 0) {
|
||||
// no test files but multiple d.ts's, e.g. winjs
|
||||
const regexp = new RegExp(d + "(([-][0-9])|([\.]d[\.]ts))");
|
||||
if (tsFiles.length > 1 && tsFiles.every(t => filePathEndsWith(t, ".d.ts") && regexp.test(t))) {
|
||||
for (const fileName of tsFiles) {
|
||||
importDefinitelyTypedTest(tscPath, rwcTestPath, path.basename(fileName, ".d.ts"), [fileName], paramFile);
|
||||
}
|
||||
}
|
||||
else {
|
||||
importDefinitelyTypedTest(tscPath, rwcTestPath, d, tsFiles, paramFile);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const fileName of tsFiles) {
|
||||
importDefinitelyTypedTest(tscPath, rwcTestPath, path.basename(fileName, "-tests.ts"), [fileName], paramFile);
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "ES5",
|
||||
"noImplicitAny": true,
|
||||
"outDir": "./",
|
||||
"rootDir": ".",
|
||||
"sourceMap": false
|
||||
},
|
||||
"files": [
|
||||
"../typings/node/node.d.ts",
|
||||
"importDefinitelyTypedTests.ts"
|
||||
],
|
||||
"exclude": [
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
|
||||
var hooks = [
|
||||
"post-checkout"
|
||||
];
|
||||
|
||||
hooks.forEach(function (hook) {
|
||||
var hookInSourceControl = path.resolve(__dirname, "hooks", hook);
|
||||
|
||||
if (fs.existsSync(hookInSourceControl)) {
|
||||
var hookInHiddenDirectory = path.resolve(__dirname, "..", ".git", "hooks", hook);
|
||||
|
||||
if (fs.existsSync(hookInHiddenDirectory)) {
|
||||
fs.unlinkSync(hookInHiddenDirectory);
|
||||
}
|
||||
|
||||
fs.linkSync(hookInSourceControl, hookInHiddenDirectory);
|
||||
}
|
||||
});
|
||||
@@ -10,10 +10,6 @@ interface InputDiagnosticMessageTable {
|
||||
[msg: string]: DiagnosticDetails;
|
||||
}
|
||||
|
||||
interface IIndexable<V> {
|
||||
[key: string]: V;
|
||||
}
|
||||
|
||||
function main(): void {
|
||||
var sys = ts.sys;
|
||||
if (sys.args.length < 1) {
|
||||
@@ -22,24 +18,58 @@ function main(): void {
|
||||
return;
|
||||
}
|
||||
|
||||
function writeFile(fileName: string, contents: string) {
|
||||
// TODO: Fix path joining
|
||||
var inputDirectory = inputFilePath.substr(0,inputFilePath.lastIndexOf("/"));
|
||||
var fileOutputPath = inputDirectory + "/" + fileName;
|
||||
sys.writeFile(fileOutputPath, contents);
|
||||
}
|
||||
|
||||
var inputFilePath = sys.args[0].replace(/\\/g, "/");
|
||||
var inputStr = sys.readFile(inputFilePath);
|
||||
|
||||
var diagnosticMesages: InputDiagnosticMessageTable = JSON.parse(inputStr);
|
||||
var diagnosticMessages: InputDiagnosticMessageTable = JSON.parse(inputStr);
|
||||
|
||||
var names = Utilities.getObjectKeys(diagnosticMesages);
|
||||
var names = Utilities.getObjectKeys(diagnosticMessages);
|
||||
var nameMap = buildUniqueNameMap(names);
|
||||
|
||||
var infoFileOutput = buildInfoFileOutput(diagnosticMesages, nameMap);
|
||||
|
||||
// TODO: Fix path joining
|
||||
var inputDirectory = inputFilePath.substr(0,inputFilePath.lastIndexOf("/"));
|
||||
var fileOutputPath = inputDirectory + "/diagnosticInformationMap.generated.ts";
|
||||
sys.writeFile(fileOutputPath, infoFileOutput);
|
||||
var infoFileOutput = buildInfoFileOutput(diagnosticMessages, nameMap);
|
||||
checkForUniqueCodes(names, diagnosticMessages);
|
||||
writeFile("diagnosticInformationMap.generated.ts", infoFileOutput);
|
||||
|
||||
var messageOutput = buildDiagnosticMessageOutput(diagnosticMessages, nameMap);
|
||||
writeFile("diagnosticMessages.generated.json", messageOutput);
|
||||
}
|
||||
|
||||
function buildUniqueNameMap(names: string[]): IIndexable<string> {
|
||||
var nameMap: IIndexable<string> = {};
|
||||
function checkForUniqueCodes(messages: string[], diagnosticTable: InputDiagnosticMessageTable) {
|
||||
const originalMessageForCode: string[] = [];
|
||||
let numConflicts = 0;
|
||||
|
||||
for (const currentMessage of messages) {
|
||||
const code = diagnosticTable[currentMessage].code;
|
||||
|
||||
if (code in originalMessageForCode) {
|
||||
const originalMessage = originalMessageForCode[code];
|
||||
ts.sys.write("\x1b[91m"); // High intensity red.
|
||||
ts.sys.write("Error");
|
||||
ts.sys.write("\x1b[0m"); // Reset formatting.
|
||||
ts.sys.write(`: Diagnostic code '${code}' conflicts between "${originalMessage}" and "${currentMessage}".`);
|
||||
ts.sys.write(ts.sys.newLine + ts.sys.newLine);
|
||||
|
||||
numConflicts++;
|
||||
}
|
||||
else {
|
||||
originalMessageForCode[code] = currentMessage;
|
||||
}
|
||||
}
|
||||
|
||||
if (numConflicts > 0) {
|
||||
throw new Error(`Found ${numConflicts} conflict(s) in diagnostic codes.`);
|
||||
}
|
||||
}
|
||||
|
||||
function buildUniqueNameMap(names: string[]): ts.Map<string> {
|
||||
var nameMap: ts.Map<string> = {};
|
||||
|
||||
var uniqueNames = NameGenerator.ensureUniqueness(names, /* isCaseSensitive */ false, /* isFixed */ undefined);
|
||||
|
||||
@@ -50,23 +80,25 @@ function buildUniqueNameMap(names: string[]): IIndexable<string> {
|
||||
return nameMap;
|
||||
}
|
||||
|
||||
function buildInfoFileOutput(messageTable: InputDiagnosticMessageTable, nameMap: IIndexable<string>): string {
|
||||
function buildInfoFileOutput(messageTable: InputDiagnosticMessageTable, nameMap: ts.Map<string>): string {
|
||||
var result =
|
||||
'// <auto-generated />\r\n' +
|
||||
'/// <reference path="types.ts" />\r\n' +
|
||||
'/* @internal */\r\n' +
|
||||
'module ts {\r\n' +
|
||||
'namespace ts {\r\n' +
|
||||
' export var Diagnostics = {\r\n';
|
||||
var names = Utilities.getObjectKeys(messageTable);
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
var name = names[i];
|
||||
var diagnosticDetails = messageTable[name];
|
||||
var propName = convertPropertyName(nameMap[name]);
|
||||
|
||||
result +=
|
||||
' ' + convertPropertyName(nameMap[name]) +
|
||||
' ' + propName +
|
||||
': { code: ' + diagnosticDetails.code +
|
||||
', category: DiagnosticCategory.' + diagnosticDetails.category +
|
||||
', key: "' + name.replace(/[\"]/g, '\\"') + '"' +
|
||||
', key: "' + createKey(propName, diagnosticDetails.code) + '"' +
|
||||
', message: "' + name.replace(/[\"]/g, '\\"') + '"' +
|
||||
' },\r\n';
|
||||
}
|
||||
|
||||
@@ -75,6 +107,30 @@ function buildInfoFileOutput(messageTable: InputDiagnosticMessageTable, nameMap:
|
||||
return result;
|
||||
}
|
||||
|
||||
function buildDiagnosticMessageOutput(messageTable: InputDiagnosticMessageTable, nameMap: ts.Map<string>): string {
|
||||
var result =
|
||||
'{';
|
||||
var names = Utilities.getObjectKeys(messageTable);
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
var name = names[i];
|
||||
var diagnosticDetails = messageTable[name];
|
||||
var propName = convertPropertyName(nameMap[name]);
|
||||
|
||||
result += '\r\n "' + createKey(propName, diagnosticDetails.code) + '"' + ' : "' + name.replace(/[\"]/g, '\\"') + '"';
|
||||
if (i !== names.length - 1) {
|
||||
result += ',';
|
||||
}
|
||||
}
|
||||
|
||||
result += '\r\n}';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function createKey(name: string, code: number) : string {
|
||||
return name.slice(0, 100) + '_' + code;
|
||||
}
|
||||
|
||||
function convertPropertyName(origName: string): string {
|
||||
var result = origName.split("").map(char => {
|
||||
if (char === '*') { return "_Asterisk"; }
|
||||
@@ -172,7 +228,7 @@ module Utilities {
|
||||
}
|
||||
|
||||
// Like Object.keys
|
||||
export function getObjectKeys(obj: any): string[]{
|
||||
export function getObjectKeys(obj: any): string[] {
|
||||
var result: string[] = [];
|
||||
|
||||
for (var name in obj) {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"version": "v4",
|
||||
"repo": "borisyankov/DefinitelyTyped",
|
||||
"ref": "master",
|
||||
"path": "typings",
|
||||
"bundle": "typings/tsd.d.ts",
|
||||
"installed": {
|
||||
"node/node.d.ts": {
|
||||
"commit": "5f480287834a2615274eea31574b713e64decf17"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import * as Lint from "tslint/lib/lint";
|
||||
import * as ts from "typescript";
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static FAILURE_STRING_FACTORY = (name: string, currently: string) => `Tag boolean argument as '${name}' (currently '${currently}')`;
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
const program = ts.createProgram([sourceFile.fileName], Lint.createCompilerOptions());
|
||||
const checker = program.getTypeChecker();
|
||||
return this.applyWithWalker(new BooleanTriviaWalker(checker, program.getSourceFile(sourceFile.fileName), this.getOptions()));
|
||||
}
|
||||
}
|
||||
|
||||
class BooleanTriviaWalker extends Lint.RuleWalker {
|
||||
constructor(private checker: ts.TypeChecker, file: ts.SourceFile, opts: Lint.IOptions) {
|
||||
super(file, opts);
|
||||
}
|
||||
|
||||
visitCallExpression(node: ts.CallExpression) {
|
||||
super.visitCallExpression(node);
|
||||
if (node.arguments) {
|
||||
const targetCallSignature = this.checker.getResolvedSignature(node);
|
||||
if (!!targetCallSignature) {
|
||||
const targetParameters = targetCallSignature.getParameters();
|
||||
const source = this.getSourceFile();
|
||||
for (let index = 0; index < targetParameters.length; index++) {
|
||||
const param = targetParameters[index];
|
||||
const arg = node.arguments[index];
|
||||
if (!(arg && param)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const argType = this.checker.getContextualType(arg);
|
||||
if (argType && (argType.getFlags() & ts.TypeFlags.Boolean)) {
|
||||
if (arg.kind !== ts.SyntaxKind.TrueKeyword && arg.kind !== ts.SyntaxKind.FalseKeyword) {
|
||||
continue;
|
||||
}
|
||||
let triviaContent: string;
|
||||
const ranges = ts.getLeadingCommentRanges(arg.getFullText(), 0);
|
||||
if (ranges && ranges.length === 1 && ranges[0].kind === ts.SyntaxKind.MultiLineCommentTrivia) {
|
||||
triviaContent = arg.getFullText().slice(ranges[0].pos + 2, ranges[0].end - 2); // +/-2 to remove /**/
|
||||
}
|
||||
|
||||
const paramName = param.getName();
|
||||
if (triviaContent !== paramName && triviaContent !== paramName + ":") {
|
||||
this.addFailure(this.createFailure(arg.getStart(source), arg.getWidth(source), Rule.FAILURE_STRING_FACTORY(param.getName(), triviaContent)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
import * as Lint from "tslint/lib/lint";
|
||||
import * as ts from "typescript";
|
||||
|
||||
const OPTION_CATCH = "check-catch";
|
||||
const OPTION_ELSE = "check-else";
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static CATCH_FAILURE_STRING = "'catch' should not be on the same line as the preceeding block's curly brace";
|
||||
public static ELSE_FAILURE_STRING = "'else' should not be on the same line as the preceeding block's curly brace";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new NextLineWalker(sourceFile, this.getOptions()));
|
||||
}
|
||||
}
|
||||
|
||||
class NextLineWalker extends Lint.RuleWalker {
|
||||
public visitIfStatement(node: ts.IfStatement) {
|
||||
const sourceFile = node.getSourceFile();
|
||||
const thenStatement = node.thenStatement;
|
||||
|
||||
const elseStatement = node.elseStatement;
|
||||
if (!!elseStatement) {
|
||||
// find the else keyword
|
||||
const elseKeyword = getFirstChildOfKind(node, ts.SyntaxKind.ElseKeyword);
|
||||
if (this.hasOption(OPTION_ELSE) && !!elseKeyword) {
|
||||
const thenStatementEndLoc = sourceFile.getLineAndCharacterOfPosition(thenStatement.getEnd());
|
||||
const elseKeywordLoc = sourceFile.getLineAndCharacterOfPosition(elseKeyword.getStart(sourceFile));
|
||||
if (thenStatementEndLoc.line === elseKeywordLoc.line) {
|
||||
const failure = this.createFailure(elseKeyword.getStart(sourceFile), elseKeyword.getWidth(sourceFile), Rule.ELSE_FAILURE_STRING);
|
||||
this.addFailure(failure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.visitIfStatement(node);
|
||||
}
|
||||
|
||||
public visitTryStatement(node: ts.TryStatement) {
|
||||
const sourceFile = node.getSourceFile();
|
||||
const catchClause = node.catchClause;
|
||||
|
||||
// "visit" try block
|
||||
const tryBlock = node.tryBlock;
|
||||
|
||||
if (this.hasOption(OPTION_CATCH) && !!catchClause) {
|
||||
const tryClosingBrace = tryBlock.getLastToken(sourceFile);
|
||||
const catchKeyword = catchClause.getFirstToken(sourceFile);
|
||||
const tryClosingBraceLoc = sourceFile.getLineAndCharacterOfPosition(tryClosingBrace.getEnd());
|
||||
const catchKeywordLoc = sourceFile.getLineAndCharacterOfPosition(catchKeyword.getStart(sourceFile));
|
||||
if (tryClosingBraceLoc.line === catchKeywordLoc.line) {
|
||||
const failure = this.createFailure(catchKeyword.getStart(sourceFile), catchKeyword.getWidth(sourceFile), Rule.CATCH_FAILURE_STRING);
|
||||
this.addFailure(failure);
|
||||
}
|
||||
}
|
||||
super.visitTryStatement(node);
|
||||
}
|
||||
}
|
||||
|
||||
function getFirstChildOfKind(node: ts.Node, kind: ts.SyntaxKind) {
|
||||
return node.getChildren().filter((child) => child.kind === kind)[0];
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import * as Lint from "tslint/lib/lint";
|
||||
import * as ts from "typescript";
|
||||
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static FAILURE_STRING = "Don't use the 'in' keyword - use 'hasProperty' to check for key presence instead";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new InWalker(sourceFile, this.getOptions()));
|
||||
}
|
||||
}
|
||||
|
||||
class InWalker extends Lint.RuleWalker {
|
||||
visitNode(node: ts.Node) {
|
||||
super.visitNode(node);
|
||||
if (node.kind === ts.SyntaxKind.InKeyword && node.parent && node.parent.kind === ts.SyntaxKind.BinaryExpression) {
|
||||
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.FAILURE_STRING));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import * as Lint from "tslint/lib/lint";
|
||||
import * as ts from "typescript";
|
||||
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static POSTFIX_FAILURE_STRING = "Don't use '++' or '--' postfix operators outside statements or for loops.";
|
||||
public static PREFIX_FAILURE_STRING = "Don't use '++' or '--' prefix operators.";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new IncrementDecrementWalker(sourceFile, this.getOptions()));
|
||||
}
|
||||
}
|
||||
|
||||
class IncrementDecrementWalker extends Lint.RuleWalker {
|
||||
|
||||
visitPostfixUnaryExpression(node: ts.PostfixUnaryExpression) {
|
||||
super.visitPostfixUnaryExpression(node);
|
||||
if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator == ts.SyntaxKind.MinusMinusToken) {
|
||||
this.visitIncrementDecrement(node);
|
||||
}
|
||||
}
|
||||
|
||||
visitPrefixUnaryExpression(node: ts.PrefixUnaryExpression) {
|
||||
super.visitPrefixUnaryExpression(node);
|
||||
if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator == ts.SyntaxKind.MinusMinusToken) {
|
||||
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.PREFIX_FAILURE_STRING));
|
||||
}
|
||||
}
|
||||
|
||||
visitIncrementDecrement(node: ts.UnaryExpression) {
|
||||
if (node.parent && (node.parent.kind === ts.SyntaxKind.ExpressionStatement ||
|
||||
node.parent.kind === ts.SyntaxKind.ForStatement)) {
|
||||
return;
|
||||
}
|
||||
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.POSTFIX_FAILURE_STRING));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import * as Lint from "tslint/lib/lint";
|
||||
import * as ts from "typescript";
|
||||
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static FAILURE_STRING = "Don't use the 'null' keyword - use 'undefined' for missing values instead";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new NullWalker(sourceFile, this.getOptions()));
|
||||
}
|
||||
}
|
||||
|
||||
class NullWalker extends Lint.RuleWalker {
|
||||
visitNode(node: ts.Node) {
|
||||
super.visitNode(node);
|
||||
if (node.kind === ts.SyntaxKind.NullKeyword) {
|
||||
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.FAILURE_STRING));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
import * as Lint from "tslint/lib/lint";
|
||||
import * as ts from "typescript";
|
||||
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static FAILURE_STRING_FACTORY = (identifier: string) => `Identifier '${identifier}' never appears on the LHS of an assignment - use const instead of let for its declaration.`;
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new PreferConstWalker(sourceFile, this.getOptions()));
|
||||
}
|
||||
}
|
||||
|
||||
function isBindingPattern(node: ts.Node): node is ts.BindingPattern {
|
||||
return !!node && (node.kind === ts.SyntaxKind.ArrayBindingPattern || node.kind === ts.SyntaxKind.ObjectBindingPattern);
|
||||
}
|
||||
|
||||
function walkUpBindingElementsAndPatterns(node: ts.Node): ts.Node {
|
||||
while (node && (node.kind === ts.SyntaxKind.BindingElement || isBindingPattern(node))) {
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
function getCombinedNodeFlags(node: ts.Node): ts.NodeFlags {
|
||||
node = walkUpBindingElementsAndPatterns(node);
|
||||
|
||||
let flags = node.flags;
|
||||
if (node.kind === ts.SyntaxKind.VariableDeclaration) {
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
if (node && node.kind === ts.SyntaxKind.VariableDeclarationList) {
|
||||
flags |= node.flags;
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
if (node && node.kind === ts.SyntaxKind.VariableStatement) {
|
||||
flags |= node.flags;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
function isLet(node: ts.Node) {
|
||||
return !!(getCombinedNodeFlags(node) & ts.NodeFlags.Let);
|
||||
}
|
||||
|
||||
function isExported(node: ts.Node) {
|
||||
return !!(getCombinedNodeFlags(node) & ts.NodeFlags.Export);
|
||||
}
|
||||
|
||||
function isAssignmentOperator(token: ts.SyntaxKind): boolean {
|
||||
return token >= ts.SyntaxKind.FirstAssignment && token <= ts.SyntaxKind.LastAssignment;
|
||||
}
|
||||
|
||||
function isBindingLiteralExpression(node: ts.Node): node is (ts.ArrayLiteralExpression | ts.ObjectLiteralExpression) {
|
||||
return (!!node) && (node.kind === ts.SyntaxKind.ObjectLiteralExpression || node.kind === ts.SyntaxKind.ArrayLiteralExpression);
|
||||
}
|
||||
|
||||
interface DeclarationUsages {
|
||||
declaration: ts.VariableDeclaration;
|
||||
usages: number;
|
||||
}
|
||||
|
||||
class PreferConstWalker extends Lint.RuleWalker {
|
||||
private inScopeLetDeclarations: ts.Map<DeclarationUsages>[] = [];
|
||||
private errors: Lint.RuleFailure[] = [];
|
||||
private markAssignment(identifier: ts.Identifier) {
|
||||
const name = identifier.text;
|
||||
for (let i = this.inScopeLetDeclarations.length - 1; i >= 0; i--) {
|
||||
const declarations = this.inScopeLetDeclarations[i];
|
||||
if (declarations[name]) {
|
||||
declarations[name].usages++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visitSourceFile(node: ts.SourceFile) {
|
||||
super.visitSourceFile(node);
|
||||
// Sort errors by position because tslint doesn't
|
||||
this.errors.sort((a, b) => a.getStartPosition().getPosition() - b.getStartPosition().getPosition()).forEach(e => this.addFailure(e));
|
||||
}
|
||||
|
||||
visitBinaryExpression(node: ts.BinaryExpression) {
|
||||
if (isAssignmentOperator(node.operatorToken.kind)) {
|
||||
this.visitLeftHandSideExpression(node.left);
|
||||
}
|
||||
super.visitBinaryExpression(node);
|
||||
}
|
||||
|
||||
private visitLeftHandSideExpression(node: ts.Expression) {
|
||||
while (node.kind === ts.SyntaxKind.ParenthesizedExpression) {
|
||||
node = (node as ts.ParenthesizedExpression).expression;
|
||||
}
|
||||
if (node.kind === ts.SyntaxKind.Identifier) {
|
||||
this.markAssignment(node as ts.Identifier);
|
||||
}
|
||||
else if (isBindingLiteralExpression(node)) {
|
||||
this.visitBindingLiteralExpression(node as (ts.ArrayLiteralExpression | ts.ObjectLiteralExpression));
|
||||
}
|
||||
}
|
||||
|
||||
private visitBindingLiteralExpression(node: ts.ArrayLiteralExpression | ts.ObjectLiteralExpression) {
|
||||
if (node.kind === ts.SyntaxKind.ObjectLiteralExpression) {
|
||||
const pattern = node as ts.ObjectLiteralExpression;
|
||||
for (const element of pattern.properties) {
|
||||
const kind = element.kind;
|
||||
|
||||
if (kind === ts.SyntaxKind.ShorthandPropertyAssignment) {
|
||||
this.markAssignment((element as ts.ShorthandPropertyAssignment).name);
|
||||
}
|
||||
else if (kind === ts.SyntaxKind.PropertyAssignment) {
|
||||
this.visitLeftHandSideExpression((element as ts.PropertyAssignment).initializer);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (node.kind === ts.SyntaxKind.ArrayLiteralExpression) {
|
||||
const pattern = node as ts.ArrayLiteralExpression;
|
||||
for (const element of pattern.elements) {
|
||||
this.visitLeftHandSideExpression(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private visitBindingPatternIdentifiers(pattern: ts.BindingPattern) {
|
||||
for (const element of pattern.elements) {
|
||||
if (element.name.kind === ts.SyntaxKind.Identifier) {
|
||||
this.markAssignment(element.name as ts.Identifier);
|
||||
}
|
||||
else {
|
||||
this.visitBindingPatternIdentifiers(element.name as ts.BindingPattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visitPrefixUnaryExpression(node: ts.PrefixUnaryExpression) {
|
||||
this.visitAnyUnaryExpression(node);
|
||||
super.visitPrefixUnaryExpression(node);
|
||||
}
|
||||
|
||||
visitPostfixUnaryExpression(node: ts.PostfixUnaryExpression) {
|
||||
this.visitAnyUnaryExpression(node);
|
||||
super.visitPostfixUnaryExpression(node);
|
||||
}
|
||||
|
||||
private visitAnyUnaryExpression(node: ts.PrefixUnaryExpression | ts.PostfixUnaryExpression) {
|
||||
if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator === ts.SyntaxKind.MinusMinusToken) {
|
||||
this.visitLeftHandSideExpression(node.operand);
|
||||
}
|
||||
}
|
||||
|
||||
visitModuleDeclaration(node: ts.ModuleDeclaration) {
|
||||
if (node.body.kind === ts.SyntaxKind.ModuleBlock) {
|
||||
// For some reason module blocks are left out of the visit block traversal
|
||||
this.visitBlock(node.body as ts.ModuleBlock);
|
||||
}
|
||||
super.visitModuleDeclaration(node);
|
||||
}
|
||||
|
||||
visitForOfStatement(node: ts.ForOfStatement) {
|
||||
this.visitAnyForStatement(node);
|
||||
super.visitForOfStatement(node);
|
||||
this.popDeclarations();
|
||||
}
|
||||
|
||||
visitForInStatement(node: ts.ForInStatement) {
|
||||
this.visitAnyForStatement(node);
|
||||
super.visitForInStatement(node);
|
||||
this.popDeclarations();
|
||||
}
|
||||
|
||||
private visitAnyForStatement(node: ts.ForOfStatement | ts.ForInStatement) {
|
||||
const names: ts.Map<DeclarationUsages> = {};
|
||||
if (isLet(node.initializer)) {
|
||||
if (node.initializer.kind === ts.SyntaxKind.VariableDeclarationList) {
|
||||
this.collectLetIdentifiers(node.initializer as ts.VariableDeclarationList, names);
|
||||
}
|
||||
}
|
||||
this.inScopeLetDeclarations.push(names);
|
||||
}
|
||||
|
||||
private popDeclarations() {
|
||||
const completed = this.inScopeLetDeclarations.pop();
|
||||
for (const name in completed) {
|
||||
if (Object.hasOwnProperty.call(completed, name)) {
|
||||
const element = completed[name];
|
||||
if (element.usages === 0) {
|
||||
this.errors.push(this.createFailure(element.declaration.getStart(this.getSourceFile()), element.declaration.getWidth(this.getSourceFile()), Rule.FAILURE_STRING_FACTORY(name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visitBlock(node: ts.Block) {
|
||||
const names: ts.Map<DeclarationUsages> = {};
|
||||
for (const statement of node.statements) {
|
||||
if (statement.kind === ts.SyntaxKind.VariableStatement) {
|
||||
this.collectLetIdentifiers((statement as ts.VariableStatement).declarationList, names);
|
||||
}
|
||||
}
|
||||
this.inScopeLetDeclarations.push(names);
|
||||
super.visitBlock(node);
|
||||
this.popDeclarations();
|
||||
}
|
||||
|
||||
private collectLetIdentifiers(list: ts.VariableDeclarationList, ret: ts.Map<DeclarationUsages>) {
|
||||
for (const node of list.declarations) {
|
||||
if (isLet(node) && !isExported(node)) {
|
||||
this.collectNameIdentifiers(node, node.name, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private collectNameIdentifiers(declaration: ts.VariableDeclaration, node: ts.Identifier | ts.BindingPattern, table: ts.Map<DeclarationUsages>) {
|
||||
if (node.kind === ts.SyntaxKind.Identifier) {
|
||||
table[(node as ts.Identifier).text] = { declaration, usages: 0 };
|
||||
}
|
||||
else {
|
||||
this.collectBindingPatternIdentifiers(declaration, node as ts.BindingPattern, table);
|
||||
}
|
||||
}
|
||||
|
||||
private collectBindingPatternIdentifiers(value: ts.VariableDeclaration, pattern: ts.BindingPattern, table: ts.Map<DeclarationUsages>) {
|
||||
for (const element of pattern.elements) {
|
||||
this.collectNameIdentifiers(value, element.name, table);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"noImplicitAny": true,
|
||||
"module": "commonjs",
|
||||
"outDir": "../../built/local/tslint"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import * as Lint from "tslint/lib/lint";
|
||||
import * as ts from "typescript";
|
||||
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static FAILURE_STRING = "The '|' and '&' operators must be surrounded by single spaces";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new TypeOperatorSpacingWalker(sourceFile, this.getOptions()));
|
||||
}
|
||||
}
|
||||
|
||||
class TypeOperatorSpacingWalker extends Lint.RuleWalker {
|
||||
public visitNode(node: ts.Node) {
|
||||
if (node.kind === ts.SyntaxKind.UnionType || node.kind === ts.SyntaxKind.IntersectionType) {
|
||||
const types = (<ts.UnionOrIntersectionTypeNode>node).types;
|
||||
let expectedStart = types[0].end + 2; // space, | or &
|
||||
for (let i = 1; i < types.length; i++) {
|
||||
const currentType = types[i];
|
||||
if (expectedStart !== currentType.pos || currentType.getLeadingTriviaWidth() !== 1) {
|
||||
const failure = this.createFailure(currentType.pos, currentType.getWidth(), Rule.FAILURE_STRING);
|
||||
this.addFailure(failure);
|
||||
}
|
||||
expectedStart = currentType.end + 2;
|
||||
}
|
||||
}
|
||||
super.visitNode(node);
|
||||
}
|
||||
}
|
||||
@@ -1,212 +0,0 @@
|
||||
var sys = (function () {
|
||||
var fileStream = new ActiveXObject("ADODB.Stream");
|
||||
fileStream.Type = 2;
|
||||
var binaryStream = new ActiveXObject("ADODB.Stream");
|
||||
binaryStream.Type = 1;
|
||||
var args = [];
|
||||
for (var i = 0; i < WScript.Arguments.length; i++) {
|
||||
args[i] = WScript.Arguments.Item(i);
|
||||
}
|
||||
return {
|
||||
args: args,
|
||||
createObject: function (typeName) { return new ActiveXObject(typeName); },
|
||||
write: function (s) {
|
||||
WScript.StdOut.Write(s);
|
||||
},
|
||||
writeFile: function (fileName, data) {
|
||||
fileStream.Open();
|
||||
binaryStream.Open();
|
||||
try {
|
||||
fileStream.Charset = "utf-8";
|
||||
fileStream.WriteText(data);
|
||||
fileStream.Position = 3;
|
||||
fileStream.CopyTo(binaryStream);
|
||||
binaryStream.SaveToFile(fileName, 2);
|
||||
}
|
||||
finally {
|
||||
binaryStream.Close();
|
||||
fileStream.Close();
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
function convertDocumentToMarkdown(doc) {
|
||||
var result = "";
|
||||
var lastStyle;
|
||||
var lastInTable;
|
||||
var tableColumnCount;
|
||||
var tableCellIndex;
|
||||
var columnAlignment = [];
|
||||
function setProperties(target, properties) {
|
||||
for (var name in properties) {
|
||||
if (properties.hasOwnProperty(name)) {
|
||||
var value = properties[name];
|
||||
if (typeof value === "object") {
|
||||
setProperties(target[name], value);
|
||||
}
|
||||
else {
|
||||
target[name] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function findReplace(findText, findOptions, replaceText, replaceOptions) {
|
||||
var find = doc.range().find;
|
||||
find.clearFormatting();
|
||||
setProperties(find, findOptions);
|
||||
var replace = find.replacement;
|
||||
replace.clearFormatting();
|
||||
setProperties(replace, replaceOptions);
|
||||
find.execute(findText, false, false, false, false, false, true, 0, true, replaceText, 2);
|
||||
}
|
||||
function write(s) {
|
||||
result += s;
|
||||
}
|
||||
function writeTableHeader() {
|
||||
for (var i = 0; i < tableColumnCount - 1; i++) {
|
||||
switch (columnAlignment[i]) {
|
||||
case 1:
|
||||
write("|:---:");
|
||||
break;
|
||||
case 2:
|
||||
write("|---:");
|
||||
break;
|
||||
default:
|
||||
write("|---");
|
||||
}
|
||||
}
|
||||
write("|\n");
|
||||
}
|
||||
function trimEndFormattingMarks(text) {
|
||||
var i = text.length;
|
||||
while (i > 0 && text.charCodeAt(i - 1) < 0x20)
|
||||
i--;
|
||||
return text.substr(0, i);
|
||||
}
|
||||
function writeBlockEnd() {
|
||||
switch (lastStyle) {
|
||||
case "Code":
|
||||
write("```\n\n");
|
||||
break;
|
||||
case "List Paragraph":
|
||||
case "Table":
|
||||
case "TOC":
|
||||
write("\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
function writeParagraph(p) {
|
||||
var text = p.range.text;
|
||||
var style = p.style.nameLocal;
|
||||
var inTable = p.range.tables.count > 0;
|
||||
var level = 1;
|
||||
var sectionBreak = text.indexOf("\x0C") >= 0;
|
||||
text = trimEndFormattingMarks(text);
|
||||
if (inTable) {
|
||||
style = "Table";
|
||||
}
|
||||
else if (style.match(/\s\d$/)) {
|
||||
level = +style.substr(style.length - 1);
|
||||
style = style.substr(0, style.length - 2);
|
||||
}
|
||||
if (lastStyle && style !== lastStyle) {
|
||||
writeBlockEnd();
|
||||
}
|
||||
switch (style) {
|
||||
case "Heading":
|
||||
case "Appendix":
|
||||
var section = p.range.listFormat.listString;
|
||||
write("####".substr(0, level) + ' <a name="' + section + '"/>' + section + " " + text + "\n\n");
|
||||
break;
|
||||
case "Normal":
|
||||
if (text.length) {
|
||||
write(text + "\n\n");
|
||||
}
|
||||
break;
|
||||
case "List Paragraph":
|
||||
write(" ".substr(0, p.range.listFormat.listLevelNumber * 2 - 2) + "* " + text + "\n");
|
||||
break;
|
||||
case "Grammar":
|
||||
write("  " + text.replace(/\s\s\s/g, " ").replace(/\x0B/g, " \n   ") + "\n\n");
|
||||
break;
|
||||
case "Code":
|
||||
if (lastStyle !== "Code") {
|
||||
write("```TypeScript\n");
|
||||
}
|
||||
else {
|
||||
write("\n");
|
||||
}
|
||||
write(text.replace(/\x0B/g, " \n") + "\n");
|
||||
break;
|
||||
case "Table":
|
||||
if (!lastInTable) {
|
||||
tableColumnCount = p.range.tables.item(1).columns.count + 1;
|
||||
tableCellIndex = 0;
|
||||
}
|
||||
if (tableCellIndex < tableColumnCount) {
|
||||
columnAlignment[tableCellIndex] = p.alignment;
|
||||
}
|
||||
write("|" + text);
|
||||
tableCellIndex++;
|
||||
if (tableCellIndex % tableColumnCount === 0) {
|
||||
write("\n");
|
||||
if (tableCellIndex === tableColumnCount) {
|
||||
writeTableHeader();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "TOC Heading":
|
||||
write("## " + text + "\n\n");
|
||||
break;
|
||||
case "TOC":
|
||||
var strings = text.split("\t");
|
||||
write(" ".substr(0, level * 2 - 2) + "* [" + strings[0] + " " + strings[1] + "](#" + strings[0] + ")\n");
|
||||
break;
|
||||
}
|
||||
if (sectionBreak) {
|
||||
write("<br/>\n\n");
|
||||
}
|
||||
lastStyle = style;
|
||||
lastInTable = inTable;
|
||||
}
|
||||
function writeDocument() {
|
||||
var title = doc.builtInDocumentProperties.item(1) + "";
|
||||
if (title.length) {
|
||||
write("# " + title + "\n\n");
|
||||
}
|
||||
for (var p = doc.paragraphs.first; p; p = p.next()) {
|
||||
writeParagraph(p);
|
||||
}
|
||||
writeBlockEnd();
|
||||
}
|
||||
findReplace("<", {}, "<", {});
|
||||
findReplace("<", { style: "Code" }, "<", {});
|
||||
findReplace("<", { style: "Code Fragment" }, "<", {});
|
||||
findReplace("<", { style: "Terminal" }, "<", {});
|
||||
findReplace("", { font: { subscript: true } }, "<sub>^&</sub>", { font: { subscript: false } });
|
||||
findReplace("", { style: "Code Fragment" }, "`^&`", { style: -66 });
|
||||
findReplace("", { style: "Production" }, "*^&*", { style: -66 });
|
||||
findReplace("", { style: "Terminal" }, "`^&`", { style: -66 });
|
||||
findReplace("", { font: { bold: true, italic: true } }, "***^&***", { font: { bold: false, italic: false } });
|
||||
findReplace("", { font: { italic: true } }, "*^&*", { font: { italic: false } });
|
||||
doc.fields.toggleShowCodes();
|
||||
findReplace("^19 REF", {}, "[^&](#^&)", {});
|
||||
doc.fields.toggleShowCodes();
|
||||
writeDocument();
|
||||
result = result.replace(/\x85/g, "\u2026");
|
||||
result = result.replace(/\x96/g, "\u2013");
|
||||
result = result.replace(/\x97/g, "\u2014");
|
||||
return result;
|
||||
}
|
||||
function main(args) {
|
||||
if (args.length !== 2) {
|
||||
sys.write("Syntax: word2md <inputfile> <outputfile>\n");
|
||||
return;
|
||||
}
|
||||
var app = sys.createObject("Word.Application");
|
||||
var doc = app.documents.open(args[0]);
|
||||
sys.writeFile(args[1], convertDocumentToMarkdown(doc));
|
||||
doc.close(false);
|
||||
app.quit();
|
||||
}
|
||||
main(sys.args);
|
||||
+46
-5
@@ -72,6 +72,9 @@ module Word {
|
||||
listFormat: ListFormat;
|
||||
tables: Tables;
|
||||
text: string;
|
||||
textRetrievalMode: {
|
||||
includeHiddenText: boolean;
|
||||
}
|
||||
words: Ranges;
|
||||
}
|
||||
|
||||
@@ -100,9 +103,19 @@ module Word {
|
||||
toggleShowCodes(): void;
|
||||
}
|
||||
|
||||
export interface Hyperlink {
|
||||
address: string;
|
||||
textToDisplay: string;
|
||||
range: Range;
|
||||
}
|
||||
|
||||
export interface Hyperlinks extends Collection<Hyperlink> {
|
||||
}
|
||||
|
||||
export interface Document {
|
||||
fields: Fields;
|
||||
paragraphs: Paragraphs;
|
||||
hyperlinks: Hyperlinks;
|
||||
builtInDocumentProperties: Collection<any>;
|
||||
close(saveChanges: boolean): void;
|
||||
range(): Range;
|
||||
@@ -195,6 +208,18 @@ function convertDocumentToMarkdown(doc: Word.Document): string {
|
||||
find.execute(findText, false, false, false, false, false, true, 0, true, replaceText, 2);
|
||||
}
|
||||
|
||||
function fixHyperlinks() {
|
||||
var count = doc.hyperlinks.count;
|
||||
for (var i = 0; i < count; i++) {
|
||||
var hyperlink = doc.hyperlinks.item(i + 1);
|
||||
var address = hyperlink.address;
|
||||
if (address && address.length > 0) {
|
||||
var textToDisplay = hyperlink.textToDisplay;
|
||||
hyperlink.textToDisplay = "[" + textToDisplay + "](" + address + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function write(s: string) {
|
||||
result += s;
|
||||
}
|
||||
@@ -236,13 +261,27 @@ function convertDocumentToMarkdown(doc: Word.Document): string {
|
||||
|
||||
function writeParagraph(p: Word.Paragraph) {
|
||||
|
||||
var text = p.range.text;
|
||||
var range = p.range;
|
||||
var text = range.text;
|
||||
var style = p.style.nameLocal;
|
||||
var inTable = p.range.tables.count > 0;
|
||||
var inTable = range.tables.count > 0;
|
||||
var level = 1;
|
||||
var sectionBreak = text.indexOf("\x0C") >= 0;
|
||||
|
||||
text = trimEndFormattingMarks(text);
|
||||
if (text === "/") {
|
||||
// An inline image shows up in the text as a "/". When we see a paragraph
|
||||
// consisting of nothing but "/", we check to see if the paragraph contains
|
||||
// hidden text and, if so, emit that instead. The hidden text is assumed to
|
||||
// contain an appropriate markdown image link.
|
||||
range.textRetrievalMode.includeHiddenText = true;
|
||||
var fullText = range.text;
|
||||
range.textRetrievalMode.includeHiddenText = false;
|
||||
if (text !== fullText) {
|
||||
text = "  " + fullText.substr(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (inTable) {
|
||||
style = "Table";
|
||||
}
|
||||
@@ -258,7 +297,7 @@ function convertDocumentToMarkdown(doc: Word.Document): string {
|
||||
|
||||
case "Heading":
|
||||
case "Appendix":
|
||||
var section = p.range.listFormat.listString;
|
||||
var section = range.listFormat.listString;
|
||||
write("####".substr(0, level) + ' <a name="' + section + '"/>' + section + " " + text + "\n\n");
|
||||
break;
|
||||
|
||||
@@ -269,7 +308,7 @@ function convertDocumentToMarkdown(doc: Word.Document): string {
|
||||
break;
|
||||
|
||||
case "List Paragraph":
|
||||
write(" ".substr(0, p.range.listFormat.listLevelNumber * 2 - 2) + "* " + text + "\n");
|
||||
write(" ".substr(0, range.listFormat.listLevelNumber * 2 - 2) + "* " + text + "\n");
|
||||
break;
|
||||
|
||||
case "Grammar":
|
||||
@@ -288,7 +327,7 @@ function convertDocumentToMarkdown(doc: Word.Document): string {
|
||||
|
||||
case "Table":
|
||||
if (!lastInTable) {
|
||||
tableColumnCount = p.range.tables.item(1).columns.count + 1;
|
||||
tableColumnCount = range.tables.item(1).columns.count + 1;
|
||||
tableCellIndex = 0;
|
||||
}
|
||||
if (tableCellIndex < tableColumnCount) {
|
||||
@@ -347,6 +386,8 @@ function convertDocumentToMarkdown(doc: Word.Document): string {
|
||||
findReplace("^19 REF", {}, "[^&](#^&)", {});
|
||||
doc.fields.toggleShowCodes();
|
||||
|
||||
fixHyperlinks();
|
||||
|
||||
writeDocument();
|
||||
|
||||
result = result.replace(/\x85/g, "\u2026");
|
||||
|
||||
+1415
-288
File diff suppressed because it is too large
Load Diff
+7737
-3901
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,12 @@
|
||||
/// <reference path="sys.ts"/>
|
||||
/// <reference path="types.ts"/>
|
||||
/// <reference path="core.ts"/>
|
||||
/// <reference path="diagnosticInformationMap.generated.ts"/>
|
||||
/// <reference path="scanner.ts"/>
|
||||
|
||||
module ts {
|
||||
namespace ts {
|
||||
/* @internal */
|
||||
export var optionDeclarations: CommandLineOption[] = [
|
||||
export let optionDeclarations: CommandLineOption[] = [
|
||||
{
|
||||
name: "charset",
|
||||
type: "string",
|
||||
@@ -30,6 +31,34 @@ module ts {
|
||||
type: "boolean",
|
||||
description: Diagnostics.Print_this_message,
|
||||
},
|
||||
{
|
||||
name: "init",
|
||||
type: "boolean",
|
||||
description: Diagnostics.Initializes_a_TypeScript_project_and_creates_a_tsconfig_json_file,
|
||||
},
|
||||
{
|
||||
name: "inlineSourceMap",
|
||||
type: "boolean",
|
||||
},
|
||||
{
|
||||
name: "inlineSources",
|
||||
type: "boolean",
|
||||
},
|
||||
{
|
||||
name: "jsx",
|
||||
type: {
|
||||
"preserve": JsxEmit.Preserve,
|
||||
"react": JsxEmit.React
|
||||
},
|
||||
paramType: Diagnostics.KIND,
|
||||
description: Diagnostics.Specify_JSX_code_generation_Colon_preserve_or_react,
|
||||
error: Diagnostics.Argument_for_jsx_must_be_preserve_or_react
|
||||
},
|
||||
{
|
||||
name: "reactNamespace",
|
||||
type: "string",
|
||||
description: Diagnostics.Specifies_the_object_invoked_for_createElement_and_spread_when_targeting_react_JSX_emit
|
||||
},
|
||||
{
|
||||
name: "listFiles",
|
||||
type: "boolean",
|
||||
@@ -50,21 +79,39 @@ module ts {
|
||||
shortName: "m",
|
||||
type: {
|
||||
"commonjs": ModuleKind.CommonJS,
|
||||
"amd": ModuleKind.AMD
|
||||
"amd": ModuleKind.AMD,
|
||||
"system": ModuleKind.System,
|
||||
"umd": ModuleKind.UMD,
|
||||
"es6": ModuleKind.ES6,
|
||||
"es2015": ModuleKind.ES2015,
|
||||
},
|
||||
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_or_amd,
|
||||
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_or_es2015,
|
||||
paramType: Diagnostics.KIND,
|
||||
error: Diagnostics.Argument_for_module_option_must_be_commonjs_or_amd
|
||||
error: Diagnostics.Argument_for_module_option_must_be_commonjs_amd_system_umd_or_es2015
|
||||
},
|
||||
{
|
||||
name: "newLine",
|
||||
type: {
|
||||
"crlf": NewLineKind.CarriageReturnLineFeed,
|
||||
"lf": NewLineKind.LineFeed
|
||||
},
|
||||
description: Diagnostics.Specifies_the_end_of_line_sequence_to_be_used_when_emitting_files_Colon_CRLF_dos_or_LF_unix,
|
||||
paramType: Diagnostics.NEWLINE,
|
||||
error: Diagnostics.Argument_for_newLine_option_must_be_CRLF_or_LF
|
||||
},
|
||||
{
|
||||
name: "noEmit",
|
||||
type: "boolean",
|
||||
description: Diagnostics.Do_not_emit_outputs,
|
||||
},
|
||||
{
|
||||
name: "noEmitHelpers",
|
||||
type: "boolean"
|
||||
},
|
||||
{
|
||||
name: "noEmitOnError",
|
||||
type: "boolean",
|
||||
description: Diagnostics.Do_not_emit_outputs_if_any_type_checking_errors_were_reported,
|
||||
description: Diagnostics.Do_not_emit_outputs_if_any_errors_were_reported,
|
||||
},
|
||||
{
|
||||
name: "noImplicitAny",
|
||||
@@ -79,9 +126,21 @@ module ts {
|
||||
name: "noResolve",
|
||||
type: "boolean",
|
||||
},
|
||||
{
|
||||
name: "skipDefaultLibCheck",
|
||||
type: "boolean",
|
||||
},
|
||||
{
|
||||
name: "out",
|
||||
type: "string",
|
||||
isFilePath: false, // This is intentionally broken to support compatability with existing tsconfig files
|
||||
// for correct behaviour, please use outFile
|
||||
paramType: Diagnostics.FILE,
|
||||
},
|
||||
{
|
||||
name: "outFile",
|
||||
type: "string",
|
||||
isFilePath: true,
|
||||
description: Diagnostics.Concatenate_and_emit_output_to_single_file,
|
||||
paramType: Diagnostics.FILE,
|
||||
},
|
||||
@@ -97,6 +156,12 @@ module ts {
|
||||
type: "boolean",
|
||||
description: Diagnostics.Do_not_erase_const_enum_declarations_in_generated_code
|
||||
},
|
||||
{
|
||||
name: "pretty",
|
||||
paramType: Diagnostics.KIND,
|
||||
description: Diagnostics.Stylize_errors_and_messages_using_color_and_context_experimental,
|
||||
type: "boolean"
|
||||
},
|
||||
{
|
||||
name: "project",
|
||||
shortName: "p",
|
||||
@@ -118,7 +183,7 @@ module ts {
|
||||
paramType: Diagnostics.LOCATION,
|
||||
},
|
||||
{
|
||||
name: "separateCompilation",
|
||||
name: "isolatedModules",
|
||||
type: "boolean",
|
||||
},
|
||||
{
|
||||
@@ -133,6 +198,12 @@ module ts {
|
||||
description: Diagnostics.Specifies_the_location_where_debugger_should_locate_TypeScript_files_instead_of_source_locations,
|
||||
paramType: Diagnostics.LOCATION,
|
||||
},
|
||||
{
|
||||
name: "suppressExcessPropertyErrors",
|
||||
type: "boolean",
|
||||
description: Diagnostics.Suppress_excess_property_checks_for_object_literals,
|
||||
experimental: true
|
||||
},
|
||||
{
|
||||
name: "suppressImplicitAnyIndexErrors",
|
||||
type: "boolean",
|
||||
@@ -147,10 +218,15 @@ module ts {
|
||||
{
|
||||
name: "target",
|
||||
shortName: "t",
|
||||
type: { "es3": ScriptTarget.ES3, "es5": ScriptTarget.ES5, "es6": ScriptTarget.ES6 },
|
||||
description: Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES6_experimental,
|
||||
type: {
|
||||
"es3": ScriptTarget.ES3,
|
||||
"es5": ScriptTarget.ES5,
|
||||
"es6": ScriptTarget.ES6,
|
||||
"es2015": ScriptTarget.ES2015,
|
||||
},
|
||||
description: Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES2015_experimental,
|
||||
paramType: Diagnostics.VERSION,
|
||||
error: Diagnostics.Argument_for_target_option_must_be_es3_es5_or_es6
|
||||
error: Diagnostics.Argument_for_target_option_must_be_ES3_ES5_or_ES2015
|
||||
},
|
||||
{
|
||||
name: "version",
|
||||
@@ -164,26 +240,95 @@ module ts {
|
||||
type: "boolean",
|
||||
description: Diagnostics.Watch_input_files,
|
||||
},
|
||||
{
|
||||
name: "experimentalDecorators",
|
||||
type: "boolean",
|
||||
description: Diagnostics.Enables_experimental_support_for_ES7_decorators
|
||||
},
|
||||
{
|
||||
name: "emitDecoratorMetadata",
|
||||
type: "boolean",
|
||||
experimental: true
|
||||
experimental: true,
|
||||
description: Diagnostics.Enables_experimental_support_for_emitting_type_metadata_for_decorators
|
||||
},
|
||||
{
|
||||
name: "moduleResolution",
|
||||
type: {
|
||||
"node": ModuleResolutionKind.NodeJs,
|
||||
"classic": ModuleResolutionKind.Classic
|
||||
},
|
||||
description: Diagnostics.Specifies_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6,
|
||||
error: Diagnostics.Argument_for_moduleResolution_option_must_be_node_or_classic,
|
||||
},
|
||||
{
|
||||
name: "allowUnusedLabels",
|
||||
type: "boolean",
|
||||
description: Diagnostics.Do_not_report_errors_on_unused_labels
|
||||
},
|
||||
{
|
||||
name: "noImplicitReturns",
|
||||
type: "boolean",
|
||||
description: Diagnostics.Report_error_when_not_all_code_paths_in_function_return_a_value
|
||||
},
|
||||
{
|
||||
name: "noFallthroughCasesInSwitch",
|
||||
type: "boolean",
|
||||
description: Diagnostics.Report_errors_for_fallthrough_cases_in_switch_statement
|
||||
},
|
||||
{
|
||||
name: "allowUnreachableCode",
|
||||
type: "boolean",
|
||||
description: Diagnostics.Do_not_report_errors_on_unreachable_code
|
||||
},
|
||||
{
|
||||
name: "forceConsistentCasingInFileNames",
|
||||
type: "boolean",
|
||||
description: Diagnostics.Disallow_inconsistently_cased_references_to_the_same_file
|
||||
},
|
||||
{
|
||||
name: "allowSyntheticDefaultImports",
|
||||
type: "boolean",
|
||||
description: Diagnostics.Allow_default_imports_from_modules_with_no_default_export_This_does_not_affect_code_emit_just_typechecking
|
||||
},
|
||||
{
|
||||
name: "allowJs",
|
||||
type: "boolean",
|
||||
description: Diagnostics.Allow_javascript_files_to_be_compiled
|
||||
}
|
||||
];
|
||||
|
||||
export function parseCommandLine(commandLine: string[]): ParsedCommandLine {
|
||||
var options: CompilerOptions = {};
|
||||
var fileNames: string[] = [];
|
||||
var errors: Diagnostic[] = [];
|
||||
var shortOptionNames: Map<string> = {};
|
||||
var optionNameMap: Map<CommandLineOption> = {};
|
||||
/* @internal */
|
||||
export interface OptionNameMap {
|
||||
optionNameMap: Map<CommandLineOption>;
|
||||
shortOptionNames: Map<string>;
|
||||
}
|
||||
|
||||
let optionNameMapCache: OptionNameMap;
|
||||
/* @internal */
|
||||
export function getOptionNameMap(): OptionNameMap {
|
||||
if (optionNameMapCache) {
|
||||
return optionNameMapCache;
|
||||
}
|
||||
|
||||
const optionNameMap: Map<CommandLineOption> = {};
|
||||
const shortOptionNames: Map<string> = {};
|
||||
forEach(optionDeclarations, option => {
|
||||
optionNameMap[option.name.toLowerCase()] = option;
|
||||
if (option.shortName) {
|
||||
shortOptionNames[option.shortName] = option.name;
|
||||
}
|
||||
});
|
||||
|
||||
optionNameMapCache = { optionNameMap, shortOptionNames };
|
||||
return optionNameMapCache;
|
||||
}
|
||||
|
||||
export function parseCommandLine(commandLine: string[], readFile?: (path: string) => string): ParsedCommandLine {
|
||||
const options: CompilerOptions = {};
|
||||
const fileNames: string[] = [];
|
||||
const errors: Diagnostic[] = [];
|
||||
const { optionNameMap, shortOptionNames } = getOptionNameMap();
|
||||
|
||||
parseStrings(commandLine);
|
||||
return {
|
||||
options,
|
||||
@@ -192,9 +337,10 @@ module ts {
|
||||
};
|
||||
|
||||
function parseStrings(args: string[]) {
|
||||
var i = 0;
|
||||
let i = 0;
|
||||
while (i < args.length) {
|
||||
var s = args[i++];
|
||||
let s = args[i];
|
||||
i++;
|
||||
if (s.charCodeAt(0) === CharacterCodes.at) {
|
||||
parseResponseFile(s.slice(1));
|
||||
}
|
||||
@@ -207,7 +353,7 @@ module ts {
|
||||
}
|
||||
|
||||
if (hasProperty(optionNameMap, s)) {
|
||||
var opt = optionNameMap[s];
|
||||
const opt = optionNameMap[s];
|
||||
|
||||
// Check to see if no argument was provided (e.g. "--locale" is the last command-line argument).
|
||||
if (!args[i] && opt.type !== "boolean") {
|
||||
@@ -216,23 +362,26 @@ module ts {
|
||||
|
||||
switch (opt.type) {
|
||||
case "number":
|
||||
options[opt.name] = parseInt(args[i++]);
|
||||
options[opt.name] = parseInt(args[i]);
|
||||
i++;
|
||||
break;
|
||||
case "boolean":
|
||||
options[opt.name] = true;
|
||||
break;
|
||||
case "string":
|
||||
options[opt.name] = args[i++] || "";
|
||||
options[opt.name] = args[i] || "";
|
||||
i++;
|
||||
break;
|
||||
// If not a primitive, the possible types are specified in what is effectively a map of options.
|
||||
default:
|
||||
var map = <Map<number>>opt.type;
|
||||
var key = (args[i++] || "").toLowerCase();
|
||||
let map = <Map<number>>opt.type;
|
||||
let key = (args[i] || "").toLowerCase();
|
||||
i++;
|
||||
if (hasProperty(map, key)) {
|
||||
options[opt.name] = map[key];
|
||||
}
|
||||
else {
|
||||
errors.push(createCompilerDiagnostic(opt.error));
|
||||
errors.push(createCompilerDiagnostic((<CommandLineOptionOfCustomType>opt).error));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -247,19 +396,19 @@ module ts {
|
||||
}
|
||||
|
||||
function parseResponseFile(fileName: string) {
|
||||
var text = sys.readFile(fileName);
|
||||
const text = readFile ? readFile(fileName) : sys.readFile(fileName);
|
||||
|
||||
if (!text) {
|
||||
errors.push(createCompilerDiagnostic(Diagnostics.File_0_not_found, fileName));
|
||||
return;
|
||||
}
|
||||
|
||||
var args: string[] = [];
|
||||
var pos = 0;
|
||||
const args: string[] = [];
|
||||
let pos = 0;
|
||||
while (true) {
|
||||
while (pos < text.length && text.charCodeAt(pos) <= CharacterCodes.space) pos++;
|
||||
if (pos >= text.length) break;
|
||||
var start = pos;
|
||||
const start = pos;
|
||||
if (text.charCodeAt(start) === CharacterCodes.doubleQuote) {
|
||||
pos++;
|
||||
while (pos < text.length && text.charCodeAt(pos) !== CharacterCodes.doubleQuote) pos++;
|
||||
@@ -284,89 +433,169 @@ module ts {
|
||||
* Read tsconfig.json file
|
||||
* @param fileName The path to the config file
|
||||
*/
|
||||
export function readConfigFile(fileName: string): any {
|
||||
export function readConfigFile(fileName: string, readFile: (path: string) => string): { config?: any; error?: Diagnostic } {
|
||||
let text = "";
|
||||
try {
|
||||
var text = sys.readFile(fileName);
|
||||
return /\S/.test(text) ? JSON.parse(text) : {};
|
||||
text = readFile(fileName);
|
||||
}
|
||||
catch (e) {
|
||||
return { error: createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message) };
|
||||
}
|
||||
return parseConfigFileTextToJson(fileName, text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the text of the tsconfig.json file
|
||||
* @param fileName The path to the config file
|
||||
* @param jsonText The text of the config file
|
||||
*/
|
||||
export function parseConfigFileTextToJson(fileName: string, jsonText: string): { config?: any; error?: Diagnostic } {
|
||||
try {
|
||||
const jsonTextWithoutComments = removeComments(jsonText);
|
||||
return { config: /\S/.test(jsonTextWithoutComments) ? JSON.parse(jsonTextWithoutComments) : {} };
|
||||
}
|
||||
catch (e) {
|
||||
return { error: createCompilerDiagnostic(Diagnostics.Failed_to_parse_file_0_Colon_1, fileName, e.message) };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove the comments from a json like text.
|
||||
* Comments can be single line comments (starting with # or //) or multiline comments using / * * /
|
||||
*
|
||||
* This method replace comment content by whitespace rather than completely remove them to keep positions in json parsing error reporting accurate.
|
||||
*/
|
||||
function removeComments(jsonText: string): string {
|
||||
let output = "";
|
||||
const scanner = createScanner(ScriptTarget.ES5, /* skipTrivia */ false, LanguageVariant.Standard, jsonText);
|
||||
let token: SyntaxKind;
|
||||
while ((token = scanner.scan()) !== SyntaxKind.EndOfFileToken) {
|
||||
switch (token) {
|
||||
case SyntaxKind.SingleLineCommentTrivia:
|
||||
case SyntaxKind.MultiLineCommentTrivia:
|
||||
// replace comments with whitespace to preserve original character positions
|
||||
output += scanner.getTokenText().replace(/\S/g, " ");
|
||||
break;
|
||||
default:
|
||||
output += scanner.getTokenText();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse the contents of a config file (tsconfig.json).
|
||||
* @param json The contents of the config file to parse
|
||||
* @param host Instance of ParseConfigHost used to enumerate files in folder.
|
||||
* @param basePath A root directory to resolve relative path entries in the config
|
||||
* file to. e.g. outDir
|
||||
* file to. e.g. outDir
|
||||
*/
|
||||
export function parseConfigFile(json: any, basePath?: string): ParsedCommandLine {
|
||||
var errors: Diagnostic[] = [];
|
||||
export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, configFileName?: string): ParsedCommandLine {
|
||||
const { options: optionsFromJsonConfigFile, errors } = convertCompilerOptionsFromJson(json["compilerOptions"], basePath, configFileName);
|
||||
|
||||
const options = extend(existingOptions, optionsFromJsonConfigFile);
|
||||
return {
|
||||
options: getCompilerOptions(),
|
||||
fileNames: getFiles(),
|
||||
options,
|
||||
fileNames: getFileNames(),
|
||||
errors
|
||||
};
|
||||
|
||||
function getCompilerOptions(): CompilerOptions {
|
||||
var options: CompilerOptions = {};
|
||||
var optionNameMap: Map<CommandLineOption> = {};
|
||||
forEach(optionDeclarations, option => {
|
||||
optionNameMap[option.name] = option;
|
||||
});
|
||||
var jsonOptions = json["compilerOptions"];
|
||||
if (jsonOptions) {
|
||||
for (var id in jsonOptions) {
|
||||
if (hasProperty(optionNameMap, id)) {
|
||||
var opt = optionNameMap[id];
|
||||
var optType = opt.type;
|
||||
var value = jsonOptions[id];
|
||||
var expectedType = typeof optType === "string" ? optType : "string";
|
||||
if (typeof value === expectedType) {
|
||||
if (typeof optType !== "string") {
|
||||
var key = value.toLowerCase();
|
||||
if (hasProperty(optType, key)) {
|
||||
value = optType[key];
|
||||
}
|
||||
else {
|
||||
errors.push(createCompilerDiagnostic(opt.error));
|
||||
value = 0;
|
||||
}
|
||||
}
|
||||
if (opt.isFilePath) {
|
||||
value = normalizePath(combinePaths(basePath, value));
|
||||
}
|
||||
options[opt.name] = value;
|
||||
}
|
||||
else {
|
||||
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, id, expectedType));
|
||||
}
|
||||
}
|
||||
else {
|
||||
errors.push(createCompilerDiagnostic(Diagnostics.Unknown_compiler_option_0, id));
|
||||
}
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
function getFiles(): string[] {
|
||||
var files: string[] = [];
|
||||
function getFileNames(): string[] {
|
||||
let fileNames: string[] = [];
|
||||
if (hasProperty(json, "files")) {
|
||||
if (json["files"] instanceof Array) {
|
||||
var files = map(<string[]>json["files"], s => combinePaths(basePath, s));
|
||||
fileNames = map(<string[]>json["files"], s => combinePaths(basePath, s));
|
||||
}
|
||||
else {
|
||||
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "files", "Array"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
var sysFiles = sys.readDirectory(basePath, ".ts");
|
||||
for (var i = 0; i < sysFiles.length; i++) {
|
||||
var name = sysFiles[i];
|
||||
if (!fileExtensionIs(name, ".d.ts") || !contains(sysFiles, name.substr(0, name.length - 5) + ".ts")) {
|
||||
files.push(name);
|
||||
const filesSeen: Map<boolean> = {};
|
||||
const exclude = json["exclude"] instanceof Array ? map(<string[]>json["exclude"], normalizeSlashes) : undefined;
|
||||
const supportedExtensions = getSupportedExtensions(options);
|
||||
Debug.assert(indexOf(supportedExtensions, ".ts") < indexOf(supportedExtensions, ".d.ts"), "Changed priority of extensions to pick");
|
||||
|
||||
// Get files of supported extensions in their order of resolution
|
||||
for (const extension of supportedExtensions) {
|
||||
const filesInDirWithExtension = host.readDirectory(basePath, extension, exclude);
|
||||
for (const fileName of filesInDirWithExtension) {
|
||||
// .ts extension would read the .d.ts extension files too but since .d.ts is lower priority extension,
|
||||
// lets pick them when its turn comes up
|
||||
if (extension === ".ts" && fileExtensionIs(fileName, ".d.ts")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If this is one of the output extension (which would be .d.ts and .js if we are allowing compilation of js files)
|
||||
// do not include this file if we included .ts or .tsx file with same base name as it could be output of the earlier compilation
|
||||
if (extension === ".d.ts" || (options.allowJs && contains(supportedJavascriptExtensions, extension))) {
|
||||
const baseName = fileName.substr(0, fileName.length - extension.length);
|
||||
if (hasProperty(filesSeen, baseName + ".ts") || hasProperty(filesSeen, baseName + ".tsx")) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
filesSeen[fileName] = true;
|
||||
fileNames.push(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return files;
|
||||
return fileNames;
|
||||
}
|
||||
}
|
||||
|
||||
export function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions, errors: Diagnostic[] } {
|
||||
const options: CompilerOptions = {};
|
||||
const errors: Diagnostic[] = [];
|
||||
|
||||
if (configFileName && getBaseFileName(configFileName) === "jsconfig.json") {
|
||||
options.module = ModuleKind.CommonJS;
|
||||
options.allowJs = true;
|
||||
}
|
||||
|
||||
if (!jsonOptions) {
|
||||
return { options, errors };
|
||||
}
|
||||
|
||||
const optionNameMap = arrayToMap(optionDeclarations, opt => opt.name);
|
||||
|
||||
for (const id in jsonOptions) {
|
||||
if (hasProperty(optionNameMap, id)) {
|
||||
const opt = optionNameMap[id];
|
||||
const optType = opt.type;
|
||||
let value = jsonOptions[id];
|
||||
const expectedType = typeof optType === "string" ? optType : "string";
|
||||
if (typeof value === expectedType) {
|
||||
if (typeof optType !== "string") {
|
||||
const key = value.toLowerCase();
|
||||
if (hasProperty(optType, key)) {
|
||||
value = optType[key];
|
||||
}
|
||||
else {
|
||||
errors.push(createCompilerDiagnostic((<CommandLineOptionOfCustomType>opt).error));
|
||||
value = 0;
|
||||
}
|
||||
}
|
||||
if (opt.isFilePath) {
|
||||
value = normalizePath(combinePaths(basePath, value));
|
||||
if (value === "") {
|
||||
value = ".";
|
||||
}
|
||||
}
|
||||
options[opt.name] = value;
|
||||
}
|
||||
else {
|
||||
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, id, expectedType));
|
||||
}
|
||||
}
|
||||
else {
|
||||
errors.push(createCompilerDiagnostic(Diagnostics.Unknown_compiler_option_0, id));
|
||||
}
|
||||
}
|
||||
|
||||
return { options, errors };
|
||||
}
|
||||
}
|
||||
|
||||
+291
-133
@@ -1,18 +1,71 @@
|
||||
/// <reference path="types.ts"/>
|
||||
|
||||
/* @internal */
|
||||
module ts {
|
||||
// Ternary values are defined such that
|
||||
// x & y is False if either x or y is False.
|
||||
// x & y is Maybe if either x or y is Maybe, but neither x or y is False.
|
||||
// x & y is True if both x and y are True.
|
||||
// x | y is False if both x and y are False.
|
||||
// x | y is Maybe if either x or y is Maybe, but neither x or y is True.
|
||||
// x | y is True if either x or y is True.
|
||||
namespace ts {
|
||||
/**
|
||||
* Ternary values are defined such that
|
||||
* x & y is False if either x or y is False.
|
||||
* x & y is Maybe if either x or y is Maybe, but neither x or y is False.
|
||||
* x & y is True if both x and y are True.
|
||||
* x | y is False if both x and y are False.
|
||||
* x | y is Maybe if either x or y is Maybe, but neither x or y is True.
|
||||
* x | y is True if either x or y is True.
|
||||
*/
|
||||
export const enum Ternary {
|
||||
False = 0,
|
||||
Maybe = 1,
|
||||
True = -1
|
||||
True = -1
|
||||
}
|
||||
|
||||
export function createFileMap<T>(keyMapper?: (key: string) => string): FileMap<T> {
|
||||
let files: Map<T> = {};
|
||||
return {
|
||||
get,
|
||||
set,
|
||||
contains,
|
||||
remove,
|
||||
forEachValue: forEachValueInMap,
|
||||
clear
|
||||
};
|
||||
|
||||
function forEachValueInMap(f: (key: Path, value: T) => void) {
|
||||
for (const key in files) {
|
||||
f(<Path>key, files[key]);
|
||||
}
|
||||
}
|
||||
|
||||
// path should already be well-formed so it does not need to be normalized
|
||||
function get(path: Path): T {
|
||||
return files[toKey(path)];
|
||||
}
|
||||
|
||||
function set(path: Path, value: T) {
|
||||
files[toKey(path)] = value;
|
||||
}
|
||||
|
||||
function contains(path: Path) {
|
||||
return hasProperty(files, toKey(path));
|
||||
}
|
||||
|
||||
function remove(path: Path) {
|
||||
const key = toKey(path);
|
||||
delete files[key];
|
||||
}
|
||||
|
||||
function clear() {
|
||||
files = {};
|
||||
}
|
||||
|
||||
function toKey(path: Path): string {
|
||||
return keyMapper ? keyMapper(path) : path;
|
||||
}
|
||||
}
|
||||
|
||||
export function toPath(fileName: string, basePath: string, getCanonicalFileName: (path: string) => string): Path {
|
||||
const nonCanonicalizedPath = isRootedDiskPath(fileName)
|
||||
? normalizePath(fileName)
|
||||
: getNormalizedAbsolutePath(fileName, basePath);
|
||||
return <Path>getCanonicalFileName(nonCanonicalizedPath);
|
||||
}
|
||||
|
||||
export const enum Comparison {
|
||||
@@ -23,10 +76,15 @@ module ts {
|
||||
|
||||
export interface StringSet extends Map<any> { }
|
||||
|
||||
/**
|
||||
* Iterates through 'array' by index and performs the callback on each element of array until the callback
|
||||
* returns a truthy value, then returns that value.
|
||||
* If no such value is found, the callback is applied to each element of array and undefined is returned.
|
||||
*/
|
||||
export function forEach<T, U>(array: T[], callback: (element: T, index: number) => U): U {
|
||||
if (array) {
|
||||
for (let i = 0, len = array.length; i < len; i++) {
|
||||
let result = callback(array[i], i);
|
||||
const result = callback(array[i], i);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
@@ -37,7 +95,7 @@ module ts {
|
||||
|
||||
export function contains<T>(array: T[], value: T): boolean {
|
||||
if (array) {
|
||||
for (let v of array) {
|
||||
for (const v of array) {
|
||||
if (v === value) {
|
||||
return true;
|
||||
}
|
||||
@@ -60,7 +118,7 @@ module ts {
|
||||
export function countWhere<T>(array: T[], predicate: (x: T) => boolean): number {
|
||||
let count = 0;
|
||||
if (array) {
|
||||
for (let v of array) {
|
||||
for (const v of array) {
|
||||
if (predicate(v)) {
|
||||
count++;
|
||||
}
|
||||
@@ -69,11 +127,11 @@ module ts {
|
||||
return count;
|
||||
}
|
||||
|
||||
export function filter<T>(array: T[], f: (x: T) => boolean): T[]{
|
||||
export function filter<T>(array: T[], f: (x: T) => boolean): T[] {
|
||||
let result: T[];
|
||||
if (array) {
|
||||
result = [];
|
||||
for (let item of array) {
|
||||
for (const item of array) {
|
||||
if (f(item)) {
|
||||
result.push(item);
|
||||
}
|
||||
@@ -82,11 +140,11 @@ module ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function map<T, U>(array: T[], f: (x: T) => U): U[]{
|
||||
export function map<T, U>(array: T[], f: (x: T) => U): U[] {
|
||||
let result: U[];
|
||||
if (array) {
|
||||
result = [];
|
||||
for (let v of array) {
|
||||
for (const v of array) {
|
||||
result.push(f(v));
|
||||
}
|
||||
}
|
||||
@@ -100,11 +158,11 @@ module ts {
|
||||
return array1.concat(array2);
|
||||
}
|
||||
|
||||
export function deduplicate<T>(array: T[]): T[]{
|
||||
export function deduplicate<T>(array: T[]): T[] {
|
||||
let result: T[];
|
||||
if (array) {
|
||||
result = [];
|
||||
for (let item of array) {
|
||||
for (const item of array) {
|
||||
if (!contains(result, item)) {
|
||||
result.push(item);
|
||||
}
|
||||
@@ -115,7 +173,7 @@ module ts {
|
||||
|
||||
export function sum(array: any[], prop: string): number {
|
||||
let result = 0;
|
||||
for (let v of array) {
|
||||
for (const v of array) {
|
||||
result += v[prop];
|
||||
}
|
||||
return result;
|
||||
@@ -123,11 +181,21 @@ module ts {
|
||||
|
||||
export function addRange<T>(to: T[], from: T[]): void {
|
||||
if (to && from) {
|
||||
for (let v of from) {
|
||||
for (const v of from) {
|
||||
to.push(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function rangeEquals<T>(array1: T[], array2: T[], pos: number, end: number) {
|
||||
while (pos < end) {
|
||||
if (array1[pos] !== array2[pos]) {
|
||||
return false;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last element of an array if non-empty, undefined otherwise.
|
||||
@@ -140,13 +208,20 @@ module ts {
|
||||
return array[array.length - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a binary search, finding the index at which 'value' occurs in 'array'.
|
||||
* If no such index is found, returns the 2's-complement of first index at which
|
||||
* number[index] exceeds number.
|
||||
* @param array A sorted array whose first element must be no larger than number
|
||||
* @param number The value to be searched for in the array.
|
||||
*/
|
||||
export function binarySearch(array: number[], value: number): number {
|
||||
let low = 0;
|
||||
let high = array.length - 1;
|
||||
|
||||
while (low <= high) {
|
||||
let middle = low + ((high - low) >> 1);
|
||||
let midValue = array[middle];
|
||||
const middle = low + ((high - low) >> 1);
|
||||
const midValue = array[middle];
|
||||
|
||||
if (midValue === value) {
|
||||
return middle;
|
||||
@@ -166,12 +241,14 @@ module ts {
|
||||
export function reduceLeft<T, U>(array: T[], f: (a: U, x: T) => U, initial: U): U;
|
||||
export function reduceLeft<T, U>(array: T[], f: (a: U, x: T) => U, initial?: U): U {
|
||||
if (array) {
|
||||
var count = array.length;
|
||||
const count = array.length;
|
||||
if (count > 0) {
|
||||
var pos = 0;
|
||||
var result = arguments.length <= 2 ? array[pos++] : initial;
|
||||
let pos = 0;
|
||||
let result = arguments.length <= 2 ? array[pos] : initial;
|
||||
pos++;
|
||||
while (pos < count) {
|
||||
result = f(<U>result, array[pos++]);
|
||||
result = f(<U>result, array[pos]);
|
||||
pos++;
|
||||
}
|
||||
return <U>result;
|
||||
}
|
||||
@@ -183,11 +260,13 @@ module ts {
|
||||
export function reduceRight<T, U>(array: T[], f: (a: U, x: T) => U, initial: U): U;
|
||||
export function reduceRight<T, U>(array: T[], f: (a: U, x: T) => U, initial?: U): U {
|
||||
if (array) {
|
||||
var pos = array.length - 1;
|
||||
let pos = array.length - 1;
|
||||
if (pos >= 0) {
|
||||
var result = arguments.length <= 2 ? array[pos--] : initial;
|
||||
let result = arguments.length <= 2 ? array[pos] : initial;
|
||||
pos--;
|
||||
while (pos >= 0) {
|
||||
result = f(<U>result, array[pos--]);
|
||||
result = f(<U>result, array[pos]);
|
||||
pos--;
|
||||
}
|
||||
return <U>result;
|
||||
}
|
||||
@@ -195,7 +274,7 @@ module ts {
|
||||
return initial;
|
||||
}
|
||||
|
||||
let hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
|
||||
export function hasProperty<T>(map: Map<T>, key: string): boolean {
|
||||
return hasOwnProperty.call(map, key);
|
||||
@@ -206,7 +285,7 @@ module ts {
|
||||
}
|
||||
|
||||
export function isEmpty<T>(map: Map<T>) {
|
||||
for (let id in map) {
|
||||
for (const id in map) {
|
||||
if (hasProperty(map, id)) {
|
||||
return false;
|
||||
}
|
||||
@@ -215,21 +294,21 @@ module ts {
|
||||
}
|
||||
|
||||
export function clone<T>(object: T): T {
|
||||
let result: any = {};
|
||||
for (let id in object) {
|
||||
const result: any = {};
|
||||
for (const id in object) {
|
||||
result[id] = (<any>object)[id];
|
||||
}
|
||||
return <T>result;
|
||||
}
|
||||
|
||||
export function extend<T>(first: Map<T>, second: Map<T>): Map<T> {
|
||||
let result: Map<T> = {};
|
||||
for (let id in first) {
|
||||
result[id] = first[id];
|
||||
export function extend<T1 extends Map<{}>, T2 extends Map<{}>>(first: T1 , second: T2): T1 & T2 {
|
||||
const result: T1 & T2 = <any>{};
|
||||
for (const id in first) {
|
||||
(result as any)[id] = first[id];
|
||||
}
|
||||
for (let id in second) {
|
||||
for (const id in second) {
|
||||
if (!hasProperty(result, id)) {
|
||||
result[id] = second[id];
|
||||
(result as any)[id] = second[id];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -237,7 +316,7 @@ module ts {
|
||||
|
||||
export function forEachValue<T, U>(map: Map<T>, callback: (value: T) => U): U {
|
||||
let result: U;
|
||||
for (let id in map) {
|
||||
for (const id in map) {
|
||||
if (result = callback(map[id])) break;
|
||||
}
|
||||
return result;
|
||||
@@ -245,7 +324,7 @@ module ts {
|
||||
|
||||
export function forEachKey<T, U>(map: Map<T>, callback: (key: string) => U): U {
|
||||
let result: U;
|
||||
for (let id in map) {
|
||||
for (const id in map) {
|
||||
if (result = callback(id)) break;
|
||||
}
|
||||
return result;
|
||||
@@ -256,7 +335,7 @@ module ts {
|
||||
}
|
||||
|
||||
export function copyMap<T>(source: Map<T>, target: Map<T>): void {
|
||||
for (let p in source) {
|
||||
for (const p in source) {
|
||||
target[p] = source[p];
|
||||
}
|
||||
}
|
||||
@@ -272,7 +351,7 @@ module ts {
|
||||
* index in the array will be the one associated with the produced key.
|
||||
*/
|
||||
export function arrayToMap<T>(array: T[], makeKey: (value: T) => string): Map<T> {
|
||||
let result: Map<T> = {};
|
||||
const result: Map<T> = {};
|
||||
|
||||
forEach(array, value => {
|
||||
result[makeKey(value)] = value;
|
||||
@@ -281,6 +360,44 @@ module ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce the properties of a map.
|
||||
*
|
||||
* @param map The map to reduce
|
||||
* @param callback An aggregation function that is called for each entry in the map
|
||||
* @param initial The initial value for the reduction.
|
||||
*/
|
||||
export function reduceProperties<T, U>(map: Map<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
|
||||
let result = initial;
|
||||
if (map) {
|
||||
for (const key in map) {
|
||||
if (hasProperty(map, key)) {
|
||||
result = callback(result, map[key], String(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether a value is an array.
|
||||
*/
|
||||
export function isArray(value: any): value is any[] {
|
||||
return Array.isArray ? Array.isArray(value) : value instanceof Array;
|
||||
}
|
||||
|
||||
export function memoize<T>(callback: () => T): () => T {
|
||||
let value: T;
|
||||
return () => {
|
||||
if (callback) {
|
||||
value = callback();
|
||||
callback = undefined;
|
||||
}
|
||||
return value;
|
||||
};
|
||||
}
|
||||
|
||||
function formatStringFromArgs(text: string, args: { [index: number]: any; }, baseIndex?: number): string {
|
||||
baseIndex = baseIndex || 0;
|
||||
|
||||
@@ -289,23 +406,26 @@ module ts {
|
||||
|
||||
export let localizedDiagnosticMessages: Map<string> = undefined;
|
||||
|
||||
export function getLocaleSpecificMessage(message: string) {
|
||||
return localizedDiagnosticMessages && localizedDiagnosticMessages[message]
|
||||
? localizedDiagnosticMessages[message]
|
||||
: message;
|
||||
export function getLocaleSpecificMessage(message: DiagnosticMessage) {
|
||||
return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key]
|
||||
? localizedDiagnosticMessages[message.key]
|
||||
: message.message;
|
||||
}
|
||||
|
||||
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: any[]): Diagnostic;
|
||||
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): Diagnostic {
|
||||
let end = start + length;
|
||||
const end = start + length;
|
||||
|
||||
Debug.assert(start >= 0, "start must be non-negative, is " + start);
|
||||
Debug.assert(length >= 0, "length must be non-negative, is " + length);
|
||||
Debug.assert(start <= file.text.length, `start must be within the bounds of the file. ${ start } > ${ file.text.length }`);
|
||||
Debug.assert(end <= file.text.length, `end must be the bounds of the file. ${ end } > ${ file.text.length }`);
|
||||
|
||||
let text = getLocaleSpecificMessage(message.key);
|
||||
|
||||
if (file) {
|
||||
Debug.assert(start <= file.text.length, `start must be within the bounds of the file. ${ start } > ${ file.text.length }`);
|
||||
Debug.assert(end <= file.text.length, `end must be the bounds of the file. ${ end } > ${ file.text.length }`);
|
||||
}
|
||||
|
||||
let text = getLocaleSpecificMessage(message);
|
||||
|
||||
if (arguments.length > 4) {
|
||||
text = formatStringFromArgs(text, arguments, 4);
|
||||
}
|
||||
@@ -323,7 +443,7 @@ module ts {
|
||||
|
||||
export function createCompilerDiagnostic(message: DiagnosticMessage, ...args: any[]): Diagnostic;
|
||||
export function createCompilerDiagnostic(message: DiagnosticMessage): Diagnostic {
|
||||
let text = getLocaleSpecificMessage(message.key);
|
||||
let text = getLocaleSpecificMessage(message);
|
||||
|
||||
if (arguments.length > 1) {
|
||||
text = formatStringFromArgs(text, arguments, 1);
|
||||
@@ -342,7 +462,7 @@ module ts {
|
||||
|
||||
export function chainDiagnosticMessages(details: DiagnosticMessageChain, message: DiagnosticMessage, ...args: any[]): DiagnosticMessageChain;
|
||||
export function chainDiagnosticMessages(details: DiagnosticMessageChain, message: DiagnosticMessage): DiagnosticMessageChain {
|
||||
let text = getLocaleSpecificMessage(message.key);
|
||||
let text = getLocaleSpecificMessage(message);
|
||||
|
||||
if (arguments.length > 2) {
|
||||
text = formatStringFromArgs(text, arguments, 2);
|
||||
@@ -358,8 +478,12 @@ module ts {
|
||||
}
|
||||
|
||||
export function concatenateDiagnosticMessageChains(headChain: DiagnosticMessageChain, tailChain: DiagnosticMessageChain): DiagnosticMessageChain {
|
||||
Debug.assert(!headChain.next);
|
||||
headChain.next = tailChain;
|
||||
let lastChain = headChain;
|
||||
while (lastChain.next) {
|
||||
lastChain = lastChain.next;
|
||||
}
|
||||
|
||||
lastChain.next = tailChain;
|
||||
return headChain;
|
||||
}
|
||||
|
||||
@@ -386,10 +510,10 @@ module ts {
|
||||
function compareMessageText(text1: string | DiagnosticMessageChain, text2: string | DiagnosticMessageChain): Comparison {
|
||||
while (text1 && text2) {
|
||||
// We still have both chains.
|
||||
let string1 = typeof text1 === "string" ? text1 : text1.messageText;
|
||||
let string2 = typeof text2 === "string" ? text2 : text2.messageText;
|
||||
const string1 = typeof text1 === "string" ? text1 : text1.messageText;
|
||||
const string2 = typeof text2 === "string" ? text2 : text2.messageText;
|
||||
|
||||
let res = compareValues(string1, string2);
|
||||
const res = compareValues(string1, string2);
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
@@ -407,7 +531,7 @@ module ts {
|
||||
return text1 ? Comparison.GreaterThan : Comparison.LessThan;
|
||||
}
|
||||
|
||||
export function sortAndDeduplicateDiagnostics(diagnostics: Diagnostic[]): Diagnostic[]{
|
||||
export function sortAndDeduplicateDiagnostics(diagnostics: Diagnostic[]): Diagnostic[] {
|
||||
return deduplicateSortedDiagnostics(diagnostics.sort(compareDiagnostics));
|
||||
}
|
||||
|
||||
@@ -416,11 +540,11 @@ module ts {
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
let newDiagnostics = [diagnostics[0]];
|
||||
const newDiagnostics = [diagnostics[0]];
|
||||
let previousDiagnostic = diagnostics[0];
|
||||
for (let i = 1; i < diagnostics.length; i++) {
|
||||
let currentDiagnostic = diagnostics[i];
|
||||
let isDupe = compareDiagnostics(currentDiagnostic, previousDiagnostic) === Comparison.EqualTo;
|
||||
const currentDiagnostic = diagnostics[i];
|
||||
const isDupe = compareDiagnostics(currentDiagnostic, previousDiagnostic) === Comparison.EqualTo;
|
||||
if (!isDupe) {
|
||||
newDiagnostics.push(currentDiagnostic);
|
||||
previousDiagnostic = currentDiagnostic;
|
||||
@@ -438,9 +562,9 @@ module ts {
|
||||
export function getRootLength(path: string): number {
|
||||
if (path.charCodeAt(0) === CharacterCodes.slash) {
|
||||
if (path.charCodeAt(1) !== CharacterCodes.slash) return 1;
|
||||
let p1 = path.indexOf("/", 2);
|
||||
const p1 = path.indexOf("/", 2);
|
||||
if (p1 < 0) return 2;
|
||||
let p2 = path.indexOf("/", p1 + 1);
|
||||
const p2 = path.indexOf("/", p1 + 1);
|
||||
if (p2 < 0) return p1 + 1;
|
||||
return p2 + 1;
|
||||
}
|
||||
@@ -448,24 +572,34 @@ module ts {
|
||||
if (path.charCodeAt(2) === CharacterCodes.slash) return 3;
|
||||
return 2;
|
||||
}
|
||||
let idx = path.indexOf('://');
|
||||
if (idx !== -1) return idx + 3
|
||||
// Per RFC 1738 'file' URI schema has the shape file://<host>/<path>
|
||||
// if <host> is omitted then it is assumed that host value is 'localhost',
|
||||
// however slash after the omitted <host> is not removed.
|
||||
// file:///folder1/file1 - this is a correct URI
|
||||
// file://folder2/file2 - this is an incorrect URI
|
||||
if (path.lastIndexOf("file:///", 0) === 0) {
|
||||
return "file:///".length;
|
||||
}
|
||||
const idx = path.indexOf("://");
|
||||
if (idx !== -1) {
|
||||
return idx + "://".length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
export let directorySeparator = "/";
|
||||
function getNormalizedParts(normalizedSlashedPath: string, rootLength: number) {
|
||||
let parts = normalizedSlashedPath.substr(rootLength).split(directorySeparator);
|
||||
let normalized: string[] = [];
|
||||
for (let part of parts) {
|
||||
const parts = normalizedSlashedPath.substr(rootLength).split(directorySeparator);
|
||||
const normalized: string[] = [];
|
||||
for (const part of parts) {
|
||||
if (part !== ".") {
|
||||
if (part === ".." && normalized.length > 0 && normalized[normalized.length - 1] !== "..") {
|
||||
if (part === ".." && normalized.length > 0 && lastOrUndefined(normalized) !== "..") {
|
||||
normalized.pop();
|
||||
}
|
||||
else {
|
||||
// A part may be an empty string (which is 'falsy') if the path had consecutive slashes,
|
||||
// e.g. "path//file.ts". Drop these before re-joining the parts.
|
||||
if(part) {
|
||||
if (part) {
|
||||
normalized.push(part);
|
||||
}
|
||||
}
|
||||
@@ -477,12 +611,14 @@ module ts {
|
||||
|
||||
export function normalizePath(path: string): string {
|
||||
path = normalizeSlashes(path);
|
||||
let rootLength = getRootLength(path);
|
||||
let normalized = getNormalizedParts(path, rootLength);
|
||||
const rootLength = getRootLength(path);
|
||||
const normalized = getNormalizedParts(path, rootLength);
|
||||
return path.substr(0, rootLength) + normalized.join(directorySeparator);
|
||||
}
|
||||
|
||||
export function getDirectoryPath(path: string) {
|
||||
export function getDirectoryPath(path: Path): Path;
|
||||
export function getDirectoryPath(path: string): string;
|
||||
export function getDirectoryPath(path: string): any {
|
||||
return path.substr(0, Math.max(getRootLength(path), path.lastIndexOf(directorySeparator)));
|
||||
}
|
||||
|
||||
@@ -495,14 +631,14 @@ module ts {
|
||||
}
|
||||
|
||||
function normalizedPathComponents(path: string, rootLength: number) {
|
||||
let normalizedParts = getNormalizedParts(path, rootLength);
|
||||
const normalizedParts = getNormalizedParts(path, rootLength);
|
||||
return [path.substr(0, rootLength)].concat(normalizedParts);
|
||||
}
|
||||
|
||||
export function getNormalizedPathComponents(path: string, currentDirectory: string) {
|
||||
path = normalizeSlashes(path);
|
||||
let rootLength = getRootLength(path);
|
||||
if (rootLength == 0) {
|
||||
if (rootLength === 0) {
|
||||
// If the path is not rooted it is relative to current directory
|
||||
path = combinePaths(normalizeSlashes(currentDirectory), path);
|
||||
rootLength = getRootLength(path);
|
||||
@@ -523,20 +659,20 @@ module ts {
|
||||
|
||||
function getNormalizedPathComponentsOfUrl(url: string) {
|
||||
// Get root length of http://www.website.com/folder1/foler2/
|
||||
// In this example the root is: http://www.website.com/
|
||||
// In this example the root is: http://www.website.com/
|
||||
// normalized path components should be ["http://www.website.com/", "folder1", "folder2"]
|
||||
|
||||
let urlLength = url.length;
|
||||
const urlLength = url.length;
|
||||
// Initial root length is http:// part
|
||||
let rootLength = url.indexOf("://") + "://".length;
|
||||
while (rootLength < urlLength) {
|
||||
// Consume all immediate slashes in the protocol
|
||||
// Consume all immediate slashes in the protocol
|
||||
// eg.initial rootlength is just file:// but it needs to consume another "/" in file:///
|
||||
if (url.charCodeAt(rootLength) === CharacterCodes.slash) {
|
||||
rootLength++;
|
||||
}
|
||||
else {
|
||||
// non slash character means we continue proceeding to next component of root search
|
||||
// non slash character means we continue proceeding to next component of root search
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -547,17 +683,17 @@ module ts {
|
||||
}
|
||||
|
||||
// Find the index of "/" after website.com so the root can be http://www.website.com/ (from existing http://)
|
||||
let indexOfNextSlash = url.indexOf(directorySeparator, rootLength);
|
||||
const indexOfNextSlash = url.indexOf(directorySeparator, rootLength);
|
||||
if (indexOfNextSlash !== -1) {
|
||||
// Found the "/" after the website.com so the root is length of http://www.website.com/
|
||||
// Found the "/" after the website.com so the root is length of http://www.website.com/
|
||||
// and get components afetr the root normally like any other folder components
|
||||
rootLength = indexOfNextSlash + 1;
|
||||
return normalizedPathComponents(url, rootLength);
|
||||
}
|
||||
else {
|
||||
// Can't find the host assume the rest of the string as component
|
||||
// Can't find the host assume the rest of the string as component
|
||||
// but make sure we append "/" to it as root is not joined using "/"
|
||||
// eg. if url passed in was http://website.com we want to use root as [http://website.com/]
|
||||
// eg. if url passed in was http://website.com we want to use root as [http://website.com/]
|
||||
// so that other path manipulations will be correct and it can be merged with relative paths correctly
|
||||
return [url + directorySeparator];
|
||||
}
|
||||
@@ -573,16 +709,17 @@ module ts {
|
||||
}
|
||||
|
||||
export function getRelativePathToDirectoryOrUrl(directoryPathOrUrl: string, relativeOrAbsolutePath: string, currentDirectory: string, getCanonicalFileName: (fileName: string) => string, isAbsolutePathAnUrl: boolean) {
|
||||
let pathComponents = getNormalizedPathOrUrlComponents(relativeOrAbsolutePath, currentDirectory);
|
||||
let directoryComponents = getNormalizedPathOrUrlComponents(directoryPathOrUrl, currentDirectory);
|
||||
if (directoryComponents.length > 1 && directoryComponents[directoryComponents.length - 1] === "") {
|
||||
const pathComponents = getNormalizedPathOrUrlComponents(relativeOrAbsolutePath, currentDirectory);
|
||||
const directoryComponents = getNormalizedPathOrUrlComponents(directoryPathOrUrl, currentDirectory);
|
||||
if (directoryComponents.length > 1 && lastOrUndefined(directoryComponents) === "") {
|
||||
// If the directory path given was of type test/cases/ then we really need components of directory to be only till its name
|
||||
// that is ["test", "cases", ""] needs to be actually ["test", "cases"]
|
||||
directoryComponents.length--;
|
||||
}
|
||||
|
||||
// Find the component that differs
|
||||
for (var joinStartIndex = 0; joinStartIndex < pathComponents.length && joinStartIndex < directoryComponents.length; joinStartIndex++) {
|
||||
let joinStartIndex: number;
|
||||
for (joinStartIndex = 0; joinStartIndex < pathComponents.length && joinStartIndex < directoryComponents.length; joinStartIndex++) {
|
||||
if (getCanonicalFileName(directoryComponents[joinStartIndex]) !== getCanonicalFileName(pathComponents[joinStartIndex])) {
|
||||
break;
|
||||
}
|
||||
@@ -591,7 +728,7 @@ module ts {
|
||||
// Get the relative path
|
||||
if (joinStartIndex) {
|
||||
let relativePath = "";
|
||||
let relativePathComponents = pathComponents.slice(joinStartIndex, pathComponents.length);
|
||||
const relativePathComponents = pathComponents.slice(joinStartIndex, pathComponents.length);
|
||||
for (; joinStartIndex < directoryComponents.length; joinStartIndex++) {
|
||||
if (directoryComponents[joinStartIndex] !== "") {
|
||||
relativePath = relativePath + ".." + directorySeparator;
|
||||
@@ -611,7 +748,10 @@ module ts {
|
||||
}
|
||||
|
||||
export function getBaseFileName(path: string) {
|
||||
let i = path.lastIndexOf(directorySeparator);
|
||||
if (path === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const i = path.lastIndexOf(directorySeparator);
|
||||
return i < 0 ? path : path.substring(i + 1);
|
||||
}
|
||||
|
||||
@@ -624,43 +764,46 @@ module ts {
|
||||
}
|
||||
|
||||
export function fileExtensionIs(path: string, extension: string): boolean {
|
||||
let pathLen = path.length;
|
||||
let extLen = extension.length;
|
||||
const pathLen = path.length;
|
||||
const extLen = extension.length;
|
||||
return pathLen > extLen && path.substr(pathLen - extLen, extLen) === extension;
|
||||
}
|
||||
|
||||
let supportedExtensions = [".d.ts", ".ts", ".js"];
|
||||
/**
|
||||
* List of supported extensions in order of file resolution precedence.
|
||||
*/
|
||||
export const supportedTypeScriptExtensions = [".ts", ".tsx", ".d.ts"];
|
||||
export const supportedJavascriptExtensions = [".js", ".jsx"];
|
||||
const allSupportedExtensions = supportedTypeScriptExtensions.concat(supportedJavascriptExtensions);
|
||||
|
||||
export function getSupportedExtensions(options?: CompilerOptions): string[] {
|
||||
return options && options.allowJs ? allSupportedExtensions : supportedTypeScriptExtensions;
|
||||
}
|
||||
|
||||
export function isSupportedSourceFileName(fileName: string, compilerOptions?: CompilerOptions) {
|
||||
if (!fileName) { return false; }
|
||||
|
||||
for (const extension of getSupportedExtensions(compilerOptions)) {
|
||||
if (fileExtensionIs(fileName, extension)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const extensionsToRemove = [".d.ts", ".ts", ".js", ".tsx", ".jsx"];
|
||||
export function removeFileExtension(path: string): string {
|
||||
for (let ext of supportedExtensions) {
|
||||
|
||||
for (const ext of extensionsToRemove) {
|
||||
if (fileExtensionIs(path, ext)) {
|
||||
return path.substr(0, path.length - ext.length);
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
let backslashOrDoubleQuote = /[\"\\]/g;
|
||||
let escapedCharsRegExp = /[\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
|
||||
let escapedCharsMap: Map<string> = {
|
||||
"\0": "\\0",
|
||||
"\t": "\\t",
|
||||
"\v": "\\v",
|
||||
"\f": "\\f",
|
||||
"\b": "\\b",
|
||||
"\r": "\\r",
|
||||
"\n": "\\n",
|
||||
"\\": "\\\\",
|
||||
"\"": "\\\"",
|
||||
"\u2028": "\\u2028", // lineSeparator
|
||||
"\u2029": "\\u2029", // paragraphSeparator
|
||||
"\u0085": "\\u0085" // nextLine
|
||||
};
|
||||
|
||||
export interface ObjectAllocator {
|
||||
getNodeConstructor(kind: SyntaxKind): new () => Node;
|
||||
getNodeConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => Node;
|
||||
getSourceFileConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => SourceFile;
|
||||
getSymbolConstructor(): new (flags: SymbolFlags, name: string) => Symbol;
|
||||
getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type;
|
||||
getSignatureConstructor(): new (checker: TypeChecker) => Signature;
|
||||
@@ -679,23 +822,21 @@ module ts {
|
||||
function Signature(checker: TypeChecker) {
|
||||
}
|
||||
|
||||
function Node(kind: SyntaxKind, pos: number, end: number) {
|
||||
this.kind = kind;
|
||||
this.pos = pos;
|
||||
this.end = end;
|
||||
this.flags = NodeFlags.None;
|
||||
this.parent = undefined;
|
||||
}
|
||||
|
||||
export let objectAllocator: ObjectAllocator = {
|
||||
getNodeConstructor: kind => {
|
||||
function Node() {
|
||||
}
|
||||
Node.prototype = {
|
||||
kind: kind,
|
||||
pos: 0,
|
||||
end: 0,
|
||||
flags: 0,
|
||||
parent: undefined,
|
||||
};
|
||||
return <any>Node;
|
||||
},
|
||||
getNodeConstructor: () => <any>Node,
|
||||
getSourceFileConstructor: () => <any>Node,
|
||||
getSymbolConstructor: () => <any>Symbol,
|
||||
getTypeConstructor: () => <any>Type,
|
||||
getSignatureConstructor: () => <any>Signature
|
||||
}
|
||||
};
|
||||
|
||||
export const enum AssertionLevel {
|
||||
None = 0,
|
||||
@@ -704,8 +845,8 @@ module ts {
|
||||
VeryAggressive = 3,
|
||||
}
|
||||
|
||||
export module Debug {
|
||||
let currentAssertionLevel = AssertionLevel.None;
|
||||
export namespace Debug {
|
||||
const currentAssertionLevel = AssertionLevel.None;
|
||||
|
||||
export function shouldAssert(level: AssertionLevel): boolean {
|
||||
return currentAssertionLevel >= level;
|
||||
@@ -717,13 +858,30 @@ module ts {
|
||||
if (verboseDebugInfo) {
|
||||
verboseDebugString = "\r\nVerbose Debug Information: " + verboseDebugInfo();
|
||||
}
|
||||
|
||||
debugger;
|
||||
throw new Error("Debug Failure. False expression: " + (message || "") + verboseDebugString);
|
||||
}
|
||||
}
|
||||
|
||||
export function fail(message?: string): void {
|
||||
Debug.assert(false, message);
|
||||
Debug.assert(/*expression*/ false, message);
|
||||
}
|
||||
}
|
||||
|
||||
export function copyListRemovingItem<T>(item: T, list: T[]) {
|
||||
const copiedList: T[] = [];
|
||||
for (const e of list) {
|
||||
if (e !== item) {
|
||||
copiedList.push(e);
|
||||
}
|
||||
}
|
||||
return copiedList;
|
||||
}
|
||||
|
||||
export function createGetCanonicalFileName(useCaseSensitivefileNames: boolean): (fileName: string) => string {
|
||||
return useCaseSensitivefileNames
|
||||
? ((fileName) => fileName)
|
||||
: ((fileName) => fileName.toLowerCase());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+326
-193
File diff suppressed because it is too large
Load Diff
@@ -1,541 +0,0 @@
|
||||
// <auto-generated />
|
||||
/// <reference path="types.ts" />
|
||||
/* @internal */
|
||||
module ts {
|
||||
export var Diagnostics = {
|
||||
Unterminated_string_literal: { code: 1002, category: DiagnosticCategory.Error, key: "Unterminated string literal." },
|
||||
Identifier_expected: { code: 1003, category: DiagnosticCategory.Error, key: "Identifier expected." },
|
||||
_0_expected: { code: 1005, category: DiagnosticCategory.Error, key: "'{0}' expected." },
|
||||
A_file_cannot_have_a_reference_to_itself: { code: 1006, category: DiagnosticCategory.Error, key: "A file cannot have a reference to itself." },
|
||||
Trailing_comma_not_allowed: { code: 1009, category: DiagnosticCategory.Error, key: "Trailing comma not allowed." },
|
||||
Asterisk_Slash_expected: { code: 1010, category: DiagnosticCategory.Error, key: "'*/' expected." },
|
||||
Unexpected_token: { code: 1012, category: DiagnosticCategory.Error, key: "Unexpected token." },
|
||||
A_rest_parameter_must_be_last_in_a_parameter_list: { code: 1014, category: DiagnosticCategory.Error, key: "A rest parameter must be last in a parameter list." },
|
||||
Parameter_cannot_have_question_mark_and_initializer: { code: 1015, category: DiagnosticCategory.Error, key: "Parameter cannot have question mark and initializer." },
|
||||
A_required_parameter_cannot_follow_an_optional_parameter: { code: 1016, category: DiagnosticCategory.Error, key: "A required parameter cannot follow an optional parameter." },
|
||||
An_index_signature_cannot_have_a_rest_parameter: { code: 1017, category: DiagnosticCategory.Error, key: "An index signature cannot have a rest parameter." },
|
||||
An_index_signature_parameter_cannot_have_an_accessibility_modifier: { code: 1018, category: DiagnosticCategory.Error, key: "An index signature parameter cannot have an accessibility modifier." },
|
||||
An_index_signature_parameter_cannot_have_a_question_mark: { code: 1019, category: DiagnosticCategory.Error, key: "An index signature parameter cannot have a question mark." },
|
||||
An_index_signature_parameter_cannot_have_an_initializer: { code: 1020, category: DiagnosticCategory.Error, key: "An index signature parameter cannot have an initializer." },
|
||||
An_index_signature_must_have_a_type_annotation: { code: 1021, category: DiagnosticCategory.Error, key: "An index signature must have a type annotation." },
|
||||
An_index_signature_parameter_must_have_a_type_annotation: { code: 1022, category: DiagnosticCategory.Error, key: "An index signature parameter must have a type annotation." },
|
||||
An_index_signature_parameter_type_must_be_string_or_number: { code: 1023, category: DiagnosticCategory.Error, key: "An index signature parameter type must be 'string' or 'number'." },
|
||||
A_class_or_interface_declaration_can_only_have_one_extends_clause: { code: 1024, category: DiagnosticCategory.Error, key: "A class or interface declaration can only have one 'extends' clause." },
|
||||
An_extends_clause_must_precede_an_implements_clause: { code: 1025, category: DiagnosticCategory.Error, key: "An 'extends' clause must precede an 'implements' clause." },
|
||||
A_class_can_only_extend_a_single_class: { code: 1026, category: DiagnosticCategory.Error, key: "A class can only extend a single class." },
|
||||
A_class_declaration_can_only_have_one_implements_clause: { code: 1027, category: DiagnosticCategory.Error, key: "A class declaration can only have one 'implements' clause." },
|
||||
Accessibility_modifier_already_seen: { code: 1028, category: DiagnosticCategory.Error, key: "Accessibility modifier already seen." },
|
||||
_0_modifier_must_precede_1_modifier: { code: 1029, category: DiagnosticCategory.Error, key: "'{0}' modifier must precede '{1}' modifier." },
|
||||
_0_modifier_already_seen: { code: 1030, category: DiagnosticCategory.Error, key: "'{0}' modifier already seen." },
|
||||
_0_modifier_cannot_appear_on_a_class_element: { code: 1031, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a class element." },
|
||||
An_interface_declaration_cannot_have_an_implements_clause: { code: 1032, category: DiagnosticCategory.Error, key: "An interface declaration cannot have an 'implements' clause." },
|
||||
super_must_be_followed_by_an_argument_list_or_member_access: { code: 1034, category: DiagnosticCategory.Error, key: "'super' must be followed by an argument list or member access." },
|
||||
Only_ambient_modules_can_use_quoted_names: { code: 1035, category: DiagnosticCategory.Error, key: "Only ambient modules can use quoted names." },
|
||||
Statements_are_not_allowed_in_ambient_contexts: { code: 1036, category: DiagnosticCategory.Error, key: "Statements are not allowed in ambient contexts." },
|
||||
A_declare_modifier_cannot_be_used_in_an_already_ambient_context: { code: 1038, category: DiagnosticCategory.Error, key: "A 'declare' modifier cannot be used in an already ambient context." },
|
||||
Initializers_are_not_allowed_in_ambient_contexts: { code: 1039, category: DiagnosticCategory.Error, key: "Initializers are not allowed in ambient contexts." },
|
||||
_0_modifier_cannot_appear_on_a_module_element: { code: 1044, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a module element." },
|
||||
A_declare_modifier_cannot_be_used_with_an_interface_declaration: { code: 1045, category: DiagnosticCategory.Error, key: "A 'declare' modifier cannot be used with an interface declaration." },
|
||||
A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file: { code: 1046, category: DiagnosticCategory.Error, key: "A 'declare' modifier is required for a top level declaration in a .d.ts file." },
|
||||
A_rest_parameter_cannot_be_optional: { code: 1047, category: DiagnosticCategory.Error, key: "A rest parameter cannot be optional." },
|
||||
A_rest_parameter_cannot_have_an_initializer: { code: 1048, category: DiagnosticCategory.Error, key: "A rest parameter cannot have an initializer." },
|
||||
A_set_accessor_must_have_exactly_one_parameter: { code: 1049, category: DiagnosticCategory.Error, key: "A 'set' accessor must have exactly one parameter." },
|
||||
A_set_accessor_cannot_have_an_optional_parameter: { code: 1051, category: DiagnosticCategory.Error, key: "A 'set' accessor cannot have an optional parameter." },
|
||||
A_set_accessor_parameter_cannot_have_an_initializer: { code: 1052, category: DiagnosticCategory.Error, key: "A 'set' accessor parameter cannot have an initializer." },
|
||||
A_set_accessor_cannot_have_rest_parameter: { code: 1053, category: DiagnosticCategory.Error, key: "A 'set' accessor cannot have rest parameter." },
|
||||
A_get_accessor_cannot_have_parameters: { code: 1054, category: DiagnosticCategory.Error, key: "A 'get' accessor cannot have parameters." },
|
||||
Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher: { code: 1056, category: DiagnosticCategory.Error, key: "Accessors are only available when targeting ECMAScript 5 and higher." },
|
||||
Enum_member_must_have_initializer: { code: 1061, category: DiagnosticCategory.Error, key: "Enum member must have initializer." },
|
||||
An_export_assignment_cannot_be_used_in_an_internal_module: { code: 1063, category: DiagnosticCategory.Error, key: "An export assignment cannot be used in an internal module." },
|
||||
Ambient_enum_elements_can_only_have_integer_literal_initializers: { code: 1066, category: DiagnosticCategory.Error, key: "Ambient enum elements can only have integer literal initializers." },
|
||||
Unexpected_token_A_constructor_method_accessor_or_property_was_expected: { code: 1068, category: DiagnosticCategory.Error, key: "Unexpected token. A constructor, method, accessor, or property was expected." },
|
||||
A_declare_modifier_cannot_be_used_with_an_import_declaration: { code: 1079, category: DiagnosticCategory.Error, key: "A 'declare' modifier cannot be used with an import declaration." },
|
||||
Invalid_reference_directive_syntax: { code: 1084, category: DiagnosticCategory.Error, key: "Invalid 'reference' directive syntax." },
|
||||
Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher: { code: 1085, category: DiagnosticCategory.Error, key: "Octal literals are not available when targeting ECMAScript 5 and higher." },
|
||||
An_accessor_cannot_be_declared_in_an_ambient_context: { code: 1086, category: DiagnosticCategory.Error, key: "An accessor cannot be declared in an ambient context." },
|
||||
_0_modifier_cannot_appear_on_a_constructor_declaration: { code: 1089, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a constructor declaration." },
|
||||
_0_modifier_cannot_appear_on_a_parameter: { code: 1090, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a parameter." },
|
||||
Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement: { code: 1091, category: DiagnosticCategory.Error, key: "Only a single variable declaration is allowed in a 'for...in' statement." },
|
||||
Type_parameters_cannot_appear_on_a_constructor_declaration: { code: 1092, category: DiagnosticCategory.Error, key: "Type parameters cannot appear on a constructor declaration." },
|
||||
Type_annotation_cannot_appear_on_a_constructor_declaration: { code: 1093, category: DiagnosticCategory.Error, key: "Type annotation cannot appear on a constructor declaration." },
|
||||
An_accessor_cannot_have_type_parameters: { code: 1094, category: DiagnosticCategory.Error, key: "An accessor cannot have type parameters." },
|
||||
A_set_accessor_cannot_have_a_return_type_annotation: { code: 1095, category: DiagnosticCategory.Error, key: "A 'set' accessor cannot have a return type annotation." },
|
||||
An_index_signature_must_have_exactly_one_parameter: { code: 1096, category: DiagnosticCategory.Error, key: "An index signature must have exactly one parameter." },
|
||||
_0_list_cannot_be_empty: { code: 1097, category: DiagnosticCategory.Error, key: "'{0}' list cannot be empty." },
|
||||
Type_parameter_list_cannot_be_empty: { code: 1098, category: DiagnosticCategory.Error, key: "Type parameter list cannot be empty." },
|
||||
Type_argument_list_cannot_be_empty: { code: 1099, category: DiagnosticCategory.Error, key: "Type argument list cannot be empty." },
|
||||
Invalid_use_of_0_in_strict_mode: { code: 1100, category: DiagnosticCategory.Error, key: "Invalid use of '{0}' in strict mode." },
|
||||
with_statements_are_not_allowed_in_strict_mode: { code: 1101, category: DiagnosticCategory.Error, key: "'with' statements are not allowed in strict mode." },
|
||||
delete_cannot_be_called_on_an_identifier_in_strict_mode: { code: 1102, category: DiagnosticCategory.Error, key: "'delete' cannot be called on an identifier in strict mode." },
|
||||
A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement: { code: 1104, category: DiagnosticCategory.Error, key: "A 'continue' statement can only be used within an enclosing iteration statement." },
|
||||
A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement: { code: 1105, category: DiagnosticCategory.Error, key: "A 'break' statement can only be used within an enclosing iteration or switch statement." },
|
||||
Jump_target_cannot_cross_function_boundary: { code: 1107, category: DiagnosticCategory.Error, key: "Jump target cannot cross function boundary." },
|
||||
A_return_statement_can_only_be_used_within_a_function_body: { code: 1108, category: DiagnosticCategory.Error, key: "A 'return' statement can only be used within a function body." },
|
||||
Expression_expected: { code: 1109, category: DiagnosticCategory.Error, key: "Expression expected." },
|
||||
Type_expected: { code: 1110, category: DiagnosticCategory.Error, key: "Type expected." },
|
||||
A_class_member_cannot_be_declared_optional: { code: 1112, category: DiagnosticCategory.Error, key: "A class member cannot be declared optional." },
|
||||
A_default_clause_cannot_appear_more_than_once_in_a_switch_statement: { code: 1113, category: DiagnosticCategory.Error, key: "A 'default' clause cannot appear more than once in a 'switch' statement." },
|
||||
Duplicate_label_0: { code: 1114, category: DiagnosticCategory.Error, key: "Duplicate label '{0}'" },
|
||||
A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement: { code: 1115, category: DiagnosticCategory.Error, key: "A 'continue' statement can only jump to a label of an enclosing iteration statement." },
|
||||
A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement: { code: 1116, category: DiagnosticCategory.Error, key: "A 'break' statement can only jump to a label of an enclosing statement." },
|
||||
An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode: { code: 1117, category: DiagnosticCategory.Error, key: "An object literal cannot have multiple properties with the same name in strict mode." },
|
||||
An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name: { code: 1118, category: DiagnosticCategory.Error, key: "An object literal cannot have multiple get/set accessors with the same name." },
|
||||
An_object_literal_cannot_have_property_and_accessor_with_the_same_name: { code: 1119, category: DiagnosticCategory.Error, key: "An object literal cannot have property and accessor with the same name." },
|
||||
An_export_assignment_cannot_have_modifiers: { code: 1120, category: DiagnosticCategory.Error, key: "An export assignment cannot have modifiers." },
|
||||
Octal_literals_are_not_allowed_in_strict_mode: { code: 1121, category: DiagnosticCategory.Error, key: "Octal literals are not allowed in strict mode." },
|
||||
A_tuple_type_element_list_cannot_be_empty: { code: 1122, category: DiagnosticCategory.Error, key: "A tuple type element list cannot be empty." },
|
||||
Variable_declaration_list_cannot_be_empty: { code: 1123, category: DiagnosticCategory.Error, key: "Variable declaration list cannot be empty." },
|
||||
Digit_expected: { code: 1124, category: DiagnosticCategory.Error, key: "Digit expected." },
|
||||
Hexadecimal_digit_expected: { code: 1125, category: DiagnosticCategory.Error, key: "Hexadecimal digit expected." },
|
||||
Unexpected_end_of_text: { code: 1126, category: DiagnosticCategory.Error, key: "Unexpected end of text." },
|
||||
Invalid_character: { code: 1127, category: DiagnosticCategory.Error, key: "Invalid character." },
|
||||
Declaration_or_statement_expected: { code: 1128, category: DiagnosticCategory.Error, key: "Declaration or statement expected." },
|
||||
Statement_expected: { code: 1129, category: DiagnosticCategory.Error, key: "Statement expected." },
|
||||
case_or_default_expected: { code: 1130, category: DiagnosticCategory.Error, key: "'case' or 'default' expected." },
|
||||
Property_or_signature_expected: { code: 1131, category: DiagnosticCategory.Error, key: "Property or signature expected." },
|
||||
Enum_member_expected: { code: 1132, category: DiagnosticCategory.Error, key: "Enum member expected." },
|
||||
Type_reference_expected: { code: 1133, category: DiagnosticCategory.Error, key: "Type reference expected." },
|
||||
Variable_declaration_expected: { code: 1134, category: DiagnosticCategory.Error, key: "Variable declaration expected." },
|
||||
Argument_expression_expected: { code: 1135, category: DiagnosticCategory.Error, key: "Argument expression expected." },
|
||||
Property_assignment_expected: { code: 1136, category: DiagnosticCategory.Error, key: "Property assignment expected." },
|
||||
Expression_or_comma_expected: { code: 1137, category: DiagnosticCategory.Error, key: "Expression or comma expected." },
|
||||
Parameter_declaration_expected: { code: 1138, category: DiagnosticCategory.Error, key: "Parameter declaration expected." },
|
||||
Type_parameter_declaration_expected: { code: 1139, category: DiagnosticCategory.Error, key: "Type parameter declaration expected." },
|
||||
Type_argument_expected: { code: 1140, category: DiagnosticCategory.Error, key: "Type argument expected." },
|
||||
String_literal_expected: { code: 1141, category: DiagnosticCategory.Error, key: "String literal expected." },
|
||||
Line_break_not_permitted_here: { code: 1142, category: DiagnosticCategory.Error, key: "Line break not permitted here." },
|
||||
or_expected: { code: 1144, category: DiagnosticCategory.Error, key: "'{' or ';' expected." },
|
||||
Modifiers_not_permitted_on_index_signature_members: { code: 1145, category: DiagnosticCategory.Error, key: "Modifiers not permitted on index signature members." },
|
||||
Declaration_expected: { code: 1146, category: DiagnosticCategory.Error, key: "Declaration expected." },
|
||||
Import_declarations_in_an_internal_module_cannot_reference_an_external_module: { code: 1147, category: DiagnosticCategory.Error, key: "Import declarations in an internal module cannot reference an external module." },
|
||||
Cannot_compile_external_modules_unless_the_module_flag_is_provided: { code: 1148, category: DiagnosticCategory.Error, key: "Cannot compile external modules unless the '--module' flag is provided." },
|
||||
File_name_0_differs_from_already_included_file_name_1_only_in_casing: { code: 1149, category: DiagnosticCategory.Error, key: "File name '{0}' differs from already included file name '{1}' only in casing" },
|
||||
new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead: { code: 1150, category: DiagnosticCategory.Error, key: "'new T[]' cannot be used to create an array. Use 'new Array<T>()' instead." },
|
||||
var_let_or_const_expected: { code: 1152, category: DiagnosticCategory.Error, key: "'var', 'let' or 'const' expected." },
|
||||
let_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1153, category: DiagnosticCategory.Error, key: "'let' declarations are only available when targeting ECMAScript 6 and higher." },
|
||||
const_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1154, category: DiagnosticCategory.Error, key: "'const' declarations are only available when targeting ECMAScript 6 and higher." },
|
||||
const_declarations_must_be_initialized: { code: 1155, category: DiagnosticCategory.Error, key: "'const' declarations must be initialized" },
|
||||
const_declarations_can_only_be_declared_inside_a_block: { code: 1156, category: DiagnosticCategory.Error, key: "'const' declarations can only be declared inside a block." },
|
||||
let_declarations_can_only_be_declared_inside_a_block: { code: 1157, category: DiagnosticCategory.Error, key: "'let' declarations can only be declared inside a block." },
|
||||
Unterminated_template_literal: { code: 1160, category: DiagnosticCategory.Error, key: "Unterminated template literal." },
|
||||
Unterminated_regular_expression_literal: { code: 1161, category: DiagnosticCategory.Error, key: "Unterminated regular expression literal." },
|
||||
An_object_member_cannot_be_declared_optional: { code: 1162, category: DiagnosticCategory.Error, key: "An object member cannot be declared optional." },
|
||||
yield_expression_must_be_contained_within_a_generator_declaration: { code: 1163, category: DiagnosticCategory.Error, key: "'yield' expression must be contained_within a generator declaration." },
|
||||
Computed_property_names_are_not_allowed_in_enums: { code: 1164, category: DiagnosticCategory.Error, key: "Computed property names are not allowed in enums." },
|
||||
A_computed_property_name_in_an_ambient_context_must_directly_refer_to_a_built_in_symbol: { code: 1165, category: DiagnosticCategory.Error, key: "A computed property name in an ambient context must directly refer to a built-in symbol." },
|
||||
A_computed_property_name_in_a_class_property_declaration_must_directly_refer_to_a_built_in_symbol: { code: 1166, category: DiagnosticCategory.Error, key: "A computed property name in a class property declaration must directly refer to a built-in symbol." },
|
||||
Computed_property_names_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1167, category: DiagnosticCategory.Error, key: "Computed property names are only available when targeting ECMAScript 6 and higher." },
|
||||
A_computed_property_name_in_a_method_overload_must_directly_refer_to_a_built_in_symbol: { code: 1168, category: DiagnosticCategory.Error, key: "A computed property name in a method overload must directly refer to a built-in symbol." },
|
||||
A_computed_property_name_in_an_interface_must_directly_refer_to_a_built_in_symbol: { code: 1169, category: DiagnosticCategory.Error, key: "A computed property name in an interface must directly refer to a built-in symbol." },
|
||||
A_computed_property_name_in_a_type_literal_must_directly_refer_to_a_built_in_symbol: { code: 1170, category: DiagnosticCategory.Error, key: "A computed property name in a type literal must directly refer to a built-in symbol." },
|
||||
A_comma_expression_is_not_allowed_in_a_computed_property_name: { code: 1171, category: DiagnosticCategory.Error, key: "A comma expression is not allowed in a computed property name." },
|
||||
extends_clause_already_seen: { code: 1172, category: DiagnosticCategory.Error, key: "'extends' clause already seen." },
|
||||
extends_clause_must_precede_implements_clause: { code: 1173, category: DiagnosticCategory.Error, key: "'extends' clause must precede 'implements' clause." },
|
||||
Classes_can_only_extend_a_single_class: { code: 1174, category: DiagnosticCategory.Error, key: "Classes can only extend a single class." },
|
||||
implements_clause_already_seen: { code: 1175, category: DiagnosticCategory.Error, key: "'implements' clause already seen." },
|
||||
Interface_declaration_cannot_have_implements_clause: { code: 1176, category: DiagnosticCategory.Error, key: "Interface declaration cannot have 'implements' clause." },
|
||||
Binary_digit_expected: { code: 1177, category: DiagnosticCategory.Error, key: "Binary digit expected." },
|
||||
Octal_digit_expected: { code: 1178, category: DiagnosticCategory.Error, key: "Octal digit expected." },
|
||||
Unexpected_token_expected: { code: 1179, category: DiagnosticCategory.Error, key: "Unexpected token. '{' expected." },
|
||||
Property_destructuring_pattern_expected: { code: 1180, category: DiagnosticCategory.Error, key: "Property destructuring pattern expected." },
|
||||
Array_element_destructuring_pattern_expected: { code: 1181, category: DiagnosticCategory.Error, key: "Array element destructuring pattern expected." },
|
||||
A_destructuring_declaration_must_have_an_initializer: { code: 1182, category: DiagnosticCategory.Error, key: "A destructuring declaration must have an initializer." },
|
||||
Destructuring_declarations_are_not_allowed_in_ambient_contexts: { code: 1183, category: DiagnosticCategory.Error, key: "Destructuring declarations are not allowed in ambient contexts." },
|
||||
An_implementation_cannot_be_declared_in_ambient_contexts: { code: 1184, category: DiagnosticCategory.Error, key: "An implementation cannot be declared in ambient contexts." },
|
||||
Modifiers_cannot_appear_here: { code: 1184, category: DiagnosticCategory.Error, key: "Modifiers cannot appear here." },
|
||||
Merge_conflict_marker_encountered: { code: 1185, category: DiagnosticCategory.Error, key: "Merge conflict marker encountered." },
|
||||
A_rest_element_cannot_have_an_initializer: { code: 1186, category: DiagnosticCategory.Error, key: "A rest element cannot have an initializer." },
|
||||
A_parameter_property_may_not_be_a_binding_pattern: { code: 1187, category: DiagnosticCategory.Error, key: "A parameter property may not be a binding pattern." },
|
||||
Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement: { code: 1188, category: DiagnosticCategory.Error, key: "Only a single variable declaration is allowed in a 'for...of' statement." },
|
||||
The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer: { code: 1189, category: DiagnosticCategory.Error, key: "The variable declaration of a 'for...in' statement cannot have an initializer." },
|
||||
The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer: { code: 1190, category: DiagnosticCategory.Error, key: "The variable declaration of a 'for...of' statement cannot have an initializer." },
|
||||
An_import_declaration_cannot_have_modifiers: { code: 1191, category: DiagnosticCategory.Error, key: "An import declaration cannot have modifiers." },
|
||||
External_module_0_has_no_default_export: { code: 1192, category: DiagnosticCategory.Error, key: "External module '{0}' has no default export." },
|
||||
An_export_declaration_cannot_have_modifiers: { code: 1193, category: DiagnosticCategory.Error, key: "An export declaration cannot have modifiers." },
|
||||
Export_declarations_are_not_permitted_in_an_internal_module: { code: 1194, category: DiagnosticCategory.Error, key: "Export declarations are not permitted in an internal module." },
|
||||
Catch_clause_variable_name_must_be_an_identifier: { code: 1195, category: DiagnosticCategory.Error, key: "Catch clause variable name must be an identifier." },
|
||||
Catch_clause_variable_cannot_have_a_type_annotation: { code: 1196, category: DiagnosticCategory.Error, key: "Catch clause variable cannot have a type annotation." },
|
||||
Catch_clause_variable_cannot_have_an_initializer: { code: 1197, category: DiagnosticCategory.Error, key: "Catch clause variable cannot have an initializer." },
|
||||
An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive: { code: 1198, category: DiagnosticCategory.Error, key: "An extended Unicode escape value must be between 0x0 and 0x10FFFF inclusive." },
|
||||
Unterminated_Unicode_escape_sequence: { code: 1199, category: DiagnosticCategory.Error, key: "Unterminated Unicode escape sequence." },
|
||||
Line_terminator_not_permitted_before_arrow: { code: 1200, category: DiagnosticCategory.Error, key: "Line terminator not permitted before arrow." },
|
||||
Import_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_or_import_d_from_mod_instead: { code: 1202, category: DiagnosticCategory.Error, key: "Import assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'import * as ns from \"mod\"', 'import {a} from \"mod\"' or 'import d from \"mod\"' instead." },
|
||||
Export_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_export_default_instead: { code: 1203, category: DiagnosticCategory.Error, key: "Export assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'export default' instead." },
|
||||
Cannot_compile_external_modules_into_amd_or_commonjs_when_targeting_es6_or_higher: { code: 1204, category: DiagnosticCategory.Error, key: "Cannot compile external modules into amd or commonjs when targeting es6 or higher." },
|
||||
Decorators_are_only_available_when_targeting_ECMAScript_5_and_higher: { code: 1205, category: DiagnosticCategory.Error, key: "Decorators are only available when targeting ECMAScript 5 and higher." },
|
||||
Decorators_are_not_valid_here: { code: 1206, category: DiagnosticCategory.Error, key: "Decorators are not valid here." },
|
||||
Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name: { code: 1207, category: DiagnosticCategory.Error, key: "Decorators cannot be applied to multiple get/set accessors of the same name." },
|
||||
Cannot_compile_non_external_modules_when_the_separateCompilation_flag_is_provided: { code: 1208, category: DiagnosticCategory.Error, key: "Cannot compile non-external modules when the '--separateCompilation' flag is provided." },
|
||||
Ambient_const_enums_are_not_allowed_when_the_separateCompilation_flag_is_provided: { code: 1209, category: DiagnosticCategory.Error, key: "Ambient const enums are not allowed when the '--separateCompilation' flag is provided." },
|
||||
Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode: { code: 1210, category: DiagnosticCategory.Error, key: "Invalid use of '{0}'. Class definitions are automatically in strict mode." },
|
||||
A_class_declaration_without_the_default_modifier_must_have_a_name: { code: 1211, category: DiagnosticCategory.Error, key: "A class declaration without the 'default' modifier must have a name" },
|
||||
Identifier_expected_0_is_a_reserved_word_in_strict_mode: { code: 1212, category: DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode" },
|
||||
Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode: { code: 1213, category: DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode." },
|
||||
Identifier_expected_0_is_a_reserved_word_in_strict_mode_External_Module_is_automatically_in_strict_mode: { code: 1214, category: DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode. External Module is automatically in strict mode." },
|
||||
Type_expected_0_is_a_reserved_word_in_strict_mode: { code: 1215, category: DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode" },
|
||||
Type_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode: { code: 1216, category: DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode." },
|
||||
Type_expected_0_is_a_reserved_word_in_strict_mode_Module_is_automatically_in_strict_mode: { code: 1217, category: DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode. Module is automatically in strict mode." },
|
||||
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
|
||||
Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." },
|
||||
Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },
|
||||
Circular_definition_of_import_alias_0: { code: 2303, category: DiagnosticCategory.Error, key: "Circular definition of import alias '{0}'." },
|
||||
Cannot_find_name_0: { code: 2304, category: DiagnosticCategory.Error, key: "Cannot find name '{0}'." },
|
||||
Module_0_has_no_exported_member_1: { code: 2305, category: DiagnosticCategory.Error, key: "Module '{0}' has no exported member '{1}'." },
|
||||
File_0_is_not_an_external_module: { code: 2306, category: DiagnosticCategory.Error, key: "File '{0}' is not an external module." },
|
||||
Cannot_find_external_module_0: { code: 2307, category: DiagnosticCategory.Error, key: "Cannot find external module '{0}'." },
|
||||
A_module_cannot_have_more_than_one_export_assignment: { code: 2308, category: DiagnosticCategory.Error, key: "A module cannot have more than one export assignment." },
|
||||
An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements: { code: 2309, category: DiagnosticCategory.Error, key: "An export assignment cannot be used in a module with other exported elements." },
|
||||
Type_0_recursively_references_itself_as_a_base_type: { code: 2310, category: DiagnosticCategory.Error, key: "Type '{0}' recursively references itself as a base type." },
|
||||
A_class_may_only_extend_another_class: { code: 2311, category: DiagnosticCategory.Error, key: "A class may only extend another class." },
|
||||
An_interface_may_only_extend_a_class_or_another_interface: { code: 2312, category: DiagnosticCategory.Error, key: "An interface may only extend a class or another interface." },
|
||||
Constraint_of_a_type_parameter_cannot_reference_any_type_parameter_from_the_same_type_parameter_list: { code: 2313, category: DiagnosticCategory.Error, key: "Constraint of a type parameter cannot reference any type parameter from the same type parameter list." },
|
||||
Generic_type_0_requires_1_type_argument_s: { code: 2314, category: DiagnosticCategory.Error, key: "Generic type '{0}' requires {1} type argument(s)." },
|
||||
Type_0_is_not_generic: { code: 2315, category: DiagnosticCategory.Error, key: "Type '{0}' is not generic." },
|
||||
Global_type_0_must_be_a_class_or_interface_type: { code: 2316, category: DiagnosticCategory.Error, key: "Global type '{0}' must be a class or interface type." },
|
||||
Global_type_0_must_have_1_type_parameter_s: { code: 2317, category: DiagnosticCategory.Error, key: "Global type '{0}' must have {1} type parameter(s)." },
|
||||
Cannot_find_global_type_0: { code: 2318, category: DiagnosticCategory.Error, key: "Cannot find global type '{0}'." },
|
||||
Named_property_0_of_types_1_and_2_are_not_identical: { code: 2319, category: DiagnosticCategory.Error, key: "Named property '{0}' of types '{1}' and '{2}' are not identical." },
|
||||
Interface_0_cannot_simultaneously_extend_types_1_and_2: { code: 2320, category: DiagnosticCategory.Error, key: "Interface '{0}' cannot simultaneously extend types '{1}' and '{2}'." },
|
||||
Excessive_stack_depth_comparing_types_0_and_1: { code: 2321, category: DiagnosticCategory.Error, key: "Excessive stack depth comparing types '{0}' and '{1}'." },
|
||||
Type_0_is_not_assignable_to_type_1: { code: 2322, category: DiagnosticCategory.Error, key: "Type '{0}' is not assignable to type '{1}'." },
|
||||
Property_0_is_missing_in_type_1: { code: 2324, category: DiagnosticCategory.Error, key: "Property '{0}' is missing in type '{1}'." },
|
||||
Property_0_is_private_in_type_1_but_not_in_type_2: { code: 2325, category: DiagnosticCategory.Error, key: "Property '{0}' is private in type '{1}' but not in type '{2}'." },
|
||||
Types_of_property_0_are_incompatible: { code: 2326, category: DiagnosticCategory.Error, key: "Types of property '{0}' are incompatible." },
|
||||
Property_0_is_optional_in_type_1_but_required_in_type_2: { code: 2327, category: DiagnosticCategory.Error, key: "Property '{0}' is optional in type '{1}' but required in type '{2}'." },
|
||||
Types_of_parameters_0_and_1_are_incompatible: { code: 2328, category: DiagnosticCategory.Error, key: "Types of parameters '{0}' and '{1}' are incompatible." },
|
||||
Index_signature_is_missing_in_type_0: { code: 2329, category: DiagnosticCategory.Error, key: "Index signature is missing in type '{0}'." },
|
||||
Index_signatures_are_incompatible: { code: 2330, category: DiagnosticCategory.Error, key: "Index signatures are incompatible." },
|
||||
this_cannot_be_referenced_in_a_module_body: { code: 2331, category: DiagnosticCategory.Error, key: "'this' cannot be referenced in a module body." },
|
||||
this_cannot_be_referenced_in_current_location: { code: 2332, category: DiagnosticCategory.Error, key: "'this' cannot be referenced in current location." },
|
||||
this_cannot_be_referenced_in_constructor_arguments: { code: 2333, category: DiagnosticCategory.Error, key: "'this' cannot be referenced in constructor arguments." },
|
||||
this_cannot_be_referenced_in_a_static_property_initializer: { code: 2334, category: DiagnosticCategory.Error, key: "'this' cannot be referenced in a static property initializer." },
|
||||
super_can_only_be_referenced_in_a_derived_class: { code: 2335, category: DiagnosticCategory.Error, key: "'super' can only be referenced in a derived class." },
|
||||
super_cannot_be_referenced_in_constructor_arguments: { code: 2336, category: DiagnosticCategory.Error, key: "'super' cannot be referenced in constructor arguments." },
|
||||
Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors: { code: 2337, category: DiagnosticCategory.Error, key: "Super calls are not permitted outside constructors or in nested functions inside constructors" },
|
||||
super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class: { code: 2338, category: DiagnosticCategory.Error, key: "'super' property access is permitted only in a constructor, member function, or member accessor of a derived class" },
|
||||
Property_0_does_not_exist_on_type_1: { code: 2339, category: DiagnosticCategory.Error, key: "Property '{0}' does not exist on type '{1}'." },
|
||||
Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword: { code: 2340, category: DiagnosticCategory.Error, key: "Only public and protected methods of the base class are accessible via the 'super' keyword" },
|
||||
Property_0_is_private_and_only_accessible_within_class_1: { code: 2341, category: DiagnosticCategory.Error, key: "Property '{0}' is private and only accessible within class '{1}'." },
|
||||
An_index_expression_argument_must_be_of_type_string_number_symbol_or_any: { code: 2342, category: DiagnosticCategory.Error, key: "An index expression argument must be of type 'string', 'number', 'symbol, or 'any'." },
|
||||
Type_0_does_not_satisfy_the_constraint_1: { code: 2344, category: DiagnosticCategory.Error, key: "Type '{0}' does not satisfy the constraint '{1}'." },
|
||||
Argument_of_type_0_is_not_assignable_to_parameter_of_type_1: { code: 2345, category: DiagnosticCategory.Error, key: "Argument of type '{0}' is not assignable to parameter of type '{1}'." },
|
||||
Supplied_parameters_do_not_match_any_signature_of_call_target: { code: 2346, category: DiagnosticCategory.Error, key: "Supplied parameters do not match any signature of call target." },
|
||||
Untyped_function_calls_may_not_accept_type_arguments: { code: 2347, category: DiagnosticCategory.Error, key: "Untyped function calls may not accept type arguments." },
|
||||
Value_of_type_0_is_not_callable_Did_you_mean_to_include_new: { code: 2348, category: DiagnosticCategory.Error, key: "Value of type '{0}' is not callable. Did you mean to include 'new'?" },
|
||||
Cannot_invoke_an_expression_whose_type_lacks_a_call_signature: { code: 2349, category: DiagnosticCategory.Error, key: "Cannot invoke an expression whose type lacks a call signature." },
|
||||
Only_a_void_function_can_be_called_with_the_new_keyword: { code: 2350, category: DiagnosticCategory.Error, key: "Only a void function can be called with the 'new' keyword." },
|
||||
Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature: { code: 2351, category: DiagnosticCategory.Error, key: "Cannot use 'new' with an expression whose type lacks a call or construct signature." },
|
||||
Neither_type_0_nor_type_1_is_assignable_to_the_other: { code: 2352, category: DiagnosticCategory.Error, key: "Neither type '{0}' nor type '{1}' is assignable to the other." },
|
||||
No_best_common_type_exists_among_return_expressions: { code: 2354, category: DiagnosticCategory.Error, key: "No best common type exists among return expressions." },
|
||||
A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_or_consist_of_a_single_throw_statement: { code: 2355, category: DiagnosticCategory.Error, key: "A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement." },
|
||||
An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type: { code: 2356, category: DiagnosticCategory.Error, key: "An arithmetic operand must be of type 'any', 'number' or an enum type." },
|
||||
The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer: { code: 2357, category: DiagnosticCategory.Error, key: "The operand of an increment or decrement operator must be a variable, property or indexer." },
|
||||
The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2358, category: DiagnosticCategory.Error, key: "The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter." },
|
||||
The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type: { code: 2359, category: DiagnosticCategory.Error, key: "The right-hand side of an 'instanceof' expression must be of type 'any' or of a type assignable to the 'Function' interface type." },
|
||||
The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol: { code: 2360, category: DiagnosticCategory.Error, key: "The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'." },
|
||||
The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2361, category: DiagnosticCategory.Error, key: "The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter" },
|
||||
The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type: { code: 2362, category: DiagnosticCategory.Error, key: "The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type." },
|
||||
The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type: { code: 2363, category: DiagnosticCategory.Error, key: "The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type." },
|
||||
Invalid_left_hand_side_of_assignment_expression: { code: 2364, category: DiagnosticCategory.Error, key: "Invalid left-hand side of assignment expression." },
|
||||
Operator_0_cannot_be_applied_to_types_1_and_2: { code: 2365, category: DiagnosticCategory.Error, key: "Operator '{0}' cannot be applied to types '{1}' and '{2}'." },
|
||||
Type_parameter_name_cannot_be_0: { code: 2368, category: DiagnosticCategory.Error, key: "Type parameter name cannot be '{0}'" },
|
||||
A_parameter_property_is_only_allowed_in_a_constructor_implementation: { code: 2369, category: DiagnosticCategory.Error, key: "A parameter property is only allowed in a constructor implementation." },
|
||||
A_rest_parameter_must_be_of_an_array_type: { code: 2370, category: DiagnosticCategory.Error, key: "A rest parameter must be of an array type." },
|
||||
A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation: { code: 2371, category: DiagnosticCategory.Error, key: "A parameter initializer is only allowed in a function or constructor implementation." },
|
||||
Parameter_0_cannot_be_referenced_in_its_initializer: { code: 2372, category: DiagnosticCategory.Error, key: "Parameter '{0}' cannot be referenced in its initializer." },
|
||||
Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it: { code: 2373, category: DiagnosticCategory.Error, key: "Initializer of parameter '{0}' cannot reference identifier '{1}' declared after it." },
|
||||
Duplicate_string_index_signature: { code: 2374, category: DiagnosticCategory.Error, key: "Duplicate string index signature." },
|
||||
Duplicate_number_index_signature: { code: 2375, category: DiagnosticCategory.Error, key: "Duplicate number index signature." },
|
||||
A_super_call_must_be_the_first_statement_in_the_constructor_when_a_class_contains_initialized_properties_or_has_parameter_properties: { code: 2376, category: DiagnosticCategory.Error, key: "A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties." },
|
||||
Constructors_for_derived_classes_must_contain_a_super_call: { code: 2377, category: DiagnosticCategory.Error, key: "Constructors for derived classes must contain a 'super' call." },
|
||||
A_get_accessor_must_return_a_value_or_consist_of_a_single_throw_statement: { code: 2378, category: DiagnosticCategory.Error, key: "A 'get' accessor must return a value or consist of a single 'throw' statement." },
|
||||
Getter_and_setter_accessors_do_not_agree_in_visibility: { code: 2379, category: DiagnosticCategory.Error, key: "Getter and setter accessors do not agree in visibility." },
|
||||
get_and_set_accessor_must_have_the_same_type: { code: 2380, category: DiagnosticCategory.Error, key: "'get' and 'set' accessor must have the same type." },
|
||||
A_signature_with_an_implementation_cannot_use_a_string_literal_type: { code: 2381, category: DiagnosticCategory.Error, key: "A signature with an implementation cannot use a string literal type." },
|
||||
Specialized_overload_signature_is_not_assignable_to_any_non_specialized_signature: { code: 2382, category: DiagnosticCategory.Error, key: "Specialized overload signature is not assignable to any non-specialized signature." },
|
||||
Overload_signatures_must_all_be_exported_or_not_exported: { code: 2383, category: DiagnosticCategory.Error, key: "Overload signatures must all be exported or not exported." },
|
||||
Overload_signatures_must_all_be_ambient_or_non_ambient: { code: 2384, category: DiagnosticCategory.Error, key: "Overload signatures must all be ambient or non-ambient." },
|
||||
Overload_signatures_must_all_be_public_private_or_protected: { code: 2385, category: DiagnosticCategory.Error, key: "Overload signatures must all be public, private or protected." },
|
||||
Overload_signatures_must_all_be_optional_or_required: { code: 2386, category: DiagnosticCategory.Error, key: "Overload signatures must all be optional or required." },
|
||||
Function_overload_must_be_static: { code: 2387, category: DiagnosticCategory.Error, key: "Function overload must be static." },
|
||||
Function_overload_must_not_be_static: { code: 2388, category: DiagnosticCategory.Error, key: "Function overload must not be static." },
|
||||
Function_implementation_name_must_be_0: { code: 2389, category: DiagnosticCategory.Error, key: "Function implementation name must be '{0}'." },
|
||||
Constructor_implementation_is_missing: { code: 2390, category: DiagnosticCategory.Error, key: "Constructor implementation is missing." },
|
||||
Function_implementation_is_missing_or_not_immediately_following_the_declaration: { code: 2391, category: DiagnosticCategory.Error, key: "Function implementation is missing or not immediately following the declaration." },
|
||||
Multiple_constructor_implementations_are_not_allowed: { code: 2392, category: DiagnosticCategory.Error, key: "Multiple constructor implementations are not allowed." },
|
||||
Duplicate_function_implementation: { code: 2393, category: DiagnosticCategory.Error, key: "Duplicate function implementation." },
|
||||
Overload_signature_is_not_compatible_with_function_implementation: { code: 2394, category: DiagnosticCategory.Error, key: "Overload signature is not compatible with function implementation." },
|
||||
Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local: { code: 2395, category: DiagnosticCategory.Error, key: "Individual declarations in merged declaration {0} must be all exported or all local." },
|
||||
Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters: { code: 2396, category: DiagnosticCategory.Error, key: "Duplicate identifier 'arguments'. Compiler uses 'arguments' to initialize rest parameters." },
|
||||
Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference: { code: 2399, category: DiagnosticCategory.Error, key: "Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference." },
|
||||
Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference: { code: 2400, category: DiagnosticCategory.Error, key: "Expression resolves to variable declaration '_this' that compiler uses to capture 'this' reference." },
|
||||
Duplicate_identifier_super_Compiler_uses_super_to_capture_base_class_reference: { code: 2401, category: DiagnosticCategory.Error, key: "Duplicate identifier '_super'. Compiler uses '_super' to capture base class reference." },
|
||||
Expression_resolves_to_super_that_compiler_uses_to_capture_base_class_reference: { code: 2402, category: DiagnosticCategory.Error, key: "Expression resolves to '_super' that compiler uses to capture base class reference." },
|
||||
Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2: { code: 2403, category: DiagnosticCategory.Error, key: "Subsequent variable declarations must have the same type. Variable '{0}' must be of type '{1}', but here has type '{2}'." },
|
||||
The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation: { code: 2404, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement cannot use a type annotation." },
|
||||
The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any: { code: 2405, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement must be of type 'string' or 'any'." },
|
||||
Invalid_left_hand_side_in_for_in_statement: { code: 2406, category: DiagnosticCategory.Error, key: "Invalid left-hand side in 'for...in' statement." },
|
||||
The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2407, category: DiagnosticCategory.Error, key: "The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter." },
|
||||
Setters_cannot_return_a_value: { code: 2408, category: DiagnosticCategory.Error, key: "Setters cannot return a value." },
|
||||
Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class: { code: 2409, category: DiagnosticCategory.Error, key: "Return type of constructor signature must be assignable to the instance type of the class" },
|
||||
All_symbols_within_a_with_block_will_be_resolved_to_any: { code: 2410, category: DiagnosticCategory.Error, key: "All symbols within a 'with' block will be resolved to 'any'." },
|
||||
Property_0_of_type_1_is_not_assignable_to_string_index_type_2: { code: 2411, category: DiagnosticCategory.Error, key: "Property '{0}' of type '{1}' is not assignable to string index type '{2}'." },
|
||||
Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2: { code: 2412, category: DiagnosticCategory.Error, key: "Property '{0}' of type '{1}' is not assignable to numeric index type '{2}'." },
|
||||
Numeric_index_type_0_is_not_assignable_to_string_index_type_1: { code: 2413, category: DiagnosticCategory.Error, key: "Numeric index type '{0}' is not assignable to string index type '{1}'." },
|
||||
Class_name_cannot_be_0: { code: 2414, category: DiagnosticCategory.Error, key: "Class name cannot be '{0}'" },
|
||||
Class_0_incorrectly_extends_base_class_1: { code: 2415, category: DiagnosticCategory.Error, key: "Class '{0}' incorrectly extends base class '{1}'." },
|
||||
Class_static_side_0_incorrectly_extends_base_class_static_side_1: { code: 2417, category: DiagnosticCategory.Error, key: "Class static side '{0}' incorrectly extends base class static side '{1}'." },
|
||||
Type_name_0_in_extends_clause_does_not_reference_constructor_function_for_0: { code: 2419, category: DiagnosticCategory.Error, key: "Type name '{0}' in extends clause does not reference constructor function for '{0}'." },
|
||||
Class_0_incorrectly_implements_interface_1: { code: 2420, category: DiagnosticCategory.Error, key: "Class '{0}' incorrectly implements interface '{1}'." },
|
||||
A_class_may_only_implement_another_class_or_interface: { code: 2422, category: DiagnosticCategory.Error, key: "A class may only implement another class or interface." },
|
||||
Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor: { code: 2423, category: DiagnosticCategory.Error, key: "Class '{0}' defines instance member function '{1}', but extended class '{2}' defines it as instance member accessor." },
|
||||
Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_property: { code: 2424, category: DiagnosticCategory.Error, key: "Class '{0}' defines instance member function '{1}', but extended class '{2}' defines it as instance member property." },
|
||||
Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function: { code: 2425, category: DiagnosticCategory.Error, key: "Class '{0}' defines instance member property '{1}', but extended class '{2}' defines it as instance member function." },
|
||||
Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function: { code: 2426, category: DiagnosticCategory.Error, key: "Class '{0}' defines instance member accessor '{1}', but extended class '{2}' defines it as instance member function." },
|
||||
Interface_name_cannot_be_0: { code: 2427, category: DiagnosticCategory.Error, key: "Interface name cannot be '{0}'" },
|
||||
All_declarations_of_an_interface_must_have_identical_type_parameters: { code: 2428, category: DiagnosticCategory.Error, key: "All declarations of an interface must have identical type parameters." },
|
||||
Interface_0_incorrectly_extends_interface_1: { code: 2430, category: DiagnosticCategory.Error, key: "Interface '{0}' incorrectly extends interface '{1}'." },
|
||||
Enum_name_cannot_be_0: { code: 2431, category: DiagnosticCategory.Error, key: "Enum name cannot be '{0}'" },
|
||||
In_an_enum_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_its_first_enum_element: { code: 2432, category: DiagnosticCategory.Error, key: "In an enum with multiple declarations, only one declaration can omit an initializer for its first enum element." },
|
||||
A_module_declaration_cannot_be_in_a_different_file_from_a_class_or_function_with_which_it_is_merged: { code: 2433, category: DiagnosticCategory.Error, key: "A module declaration cannot be in a different file from a class or function with which it is merged" },
|
||||
A_module_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged: { code: 2434, category: DiagnosticCategory.Error, key: "A module declaration cannot be located prior to a class or function with which it is merged" },
|
||||
Ambient_external_modules_cannot_be_nested_in_other_modules: { code: 2435, category: DiagnosticCategory.Error, key: "Ambient external modules cannot be nested in other modules." },
|
||||
Ambient_external_module_declaration_cannot_specify_relative_module_name: { code: 2436, category: DiagnosticCategory.Error, key: "Ambient external module declaration cannot specify relative module name." },
|
||||
Module_0_is_hidden_by_a_local_declaration_with_the_same_name: { code: 2437, category: DiagnosticCategory.Error, key: "Module '{0}' is hidden by a local declaration with the same name" },
|
||||
Import_name_cannot_be_0: { code: 2438, category: DiagnosticCategory.Error, key: "Import name cannot be '{0}'" },
|
||||
Import_or_export_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name: { code: 2439, category: DiagnosticCategory.Error, key: "Import or export declaration in an ambient external module declaration cannot reference external module through relative external module name." },
|
||||
Import_declaration_conflicts_with_local_declaration_of_0: { code: 2440, category: DiagnosticCategory.Error, key: "Import declaration conflicts with local declaration of '{0}'" },
|
||||
Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module: { code: 2441, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'. Compiler reserves name '{1}' in top level scope of an external module." },
|
||||
Types_have_separate_declarations_of_a_private_property_0: { code: 2442, category: DiagnosticCategory.Error, key: "Types have separate declarations of a private property '{0}'." },
|
||||
Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2: { code: 2443, category: DiagnosticCategory.Error, key: "Property '{0}' is protected but type '{1}' is not a class derived from '{2}'." },
|
||||
Property_0_is_protected_in_type_1_but_public_in_type_2: { code: 2444, category: DiagnosticCategory.Error, key: "Property '{0}' is protected in type '{1}' but public in type '{2}'." },
|
||||
Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses: { code: 2445, category: DiagnosticCategory.Error, key: "Property '{0}' is protected and only accessible within class '{1}' and its subclasses." },
|
||||
Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1: { code: 2446, category: DiagnosticCategory.Error, key: "Property '{0}' is protected and only accessible through an instance of class '{1}'." },
|
||||
The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead: { code: 2447, category: DiagnosticCategory.Error, key: "The '{0}' operator is not allowed for boolean types. Consider using '{1}' instead." },
|
||||
Block_scoped_variable_0_used_before_its_declaration: { code: 2448, category: DiagnosticCategory.Error, key: "Block-scoped variable '{0}' used before its declaration." },
|
||||
The_operand_of_an_increment_or_decrement_operator_cannot_be_a_constant: { code: 2449, category: DiagnosticCategory.Error, key: "The operand of an increment or decrement operator cannot be a constant." },
|
||||
Left_hand_side_of_assignment_expression_cannot_be_a_constant: { code: 2450, category: DiagnosticCategory.Error, key: "Left-hand side of assignment expression cannot be a constant." },
|
||||
Cannot_redeclare_block_scoped_variable_0: { code: 2451, category: DiagnosticCategory.Error, key: "Cannot redeclare block-scoped variable '{0}'." },
|
||||
An_enum_member_cannot_have_a_numeric_name: { code: 2452, category: DiagnosticCategory.Error, key: "An enum member cannot have a numeric name." },
|
||||
The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly: { code: 2453, category: DiagnosticCategory.Error, key: "The type argument for type parameter '{0}' cannot be inferred from the usage. Consider specifying the type arguments explicitly." },
|
||||
Type_argument_candidate_1_is_not_a_valid_type_argument_because_it_is_not_a_supertype_of_candidate_0: { code: 2455, category: DiagnosticCategory.Error, key: "Type argument candidate '{1}' is not a valid type argument because it is not a supertype of candidate '{0}'." },
|
||||
Type_alias_0_circularly_references_itself: { code: 2456, category: DiagnosticCategory.Error, key: "Type alias '{0}' circularly references itself." },
|
||||
Type_alias_name_cannot_be_0: { code: 2457, category: DiagnosticCategory.Error, key: "Type alias name cannot be '{0}'" },
|
||||
An_AMD_module_cannot_have_multiple_name_assignments: { code: 2458, category: DiagnosticCategory.Error, key: "An AMD module cannot have multiple name assignments." },
|
||||
Type_0_has_no_property_1_and_no_string_index_signature: { code: 2459, category: DiagnosticCategory.Error, key: "Type '{0}' has no property '{1}' and no string index signature." },
|
||||
Type_0_has_no_property_1: { code: 2460, category: DiagnosticCategory.Error, key: "Type '{0}' has no property '{1}'." },
|
||||
Type_0_is_not_an_array_type: { code: 2461, category: DiagnosticCategory.Error, key: "Type '{0}' is not an array type." },
|
||||
A_rest_element_must_be_last_in_an_array_destructuring_pattern: { code: 2462, category: DiagnosticCategory.Error, key: "A rest element must be last in an array destructuring pattern" },
|
||||
A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature: { code: 2463, category: DiagnosticCategory.Error, key: "A binding pattern parameter cannot be optional in an implementation signature." },
|
||||
A_computed_property_name_must_be_of_type_string_number_symbol_or_any: { code: 2464, category: DiagnosticCategory.Error, key: "A computed property name must be of type 'string', 'number', 'symbol', or 'any'." },
|
||||
this_cannot_be_referenced_in_a_computed_property_name: { code: 2465, category: DiagnosticCategory.Error, key: "'this' cannot be referenced in a computed property name." },
|
||||
super_cannot_be_referenced_in_a_computed_property_name: { code: 2466, category: DiagnosticCategory.Error, key: "'super' cannot be referenced in a computed property name." },
|
||||
A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type: { code: 2467, category: DiagnosticCategory.Error, key: "A computed property name cannot reference a type parameter from its containing type." },
|
||||
Cannot_find_global_value_0: { code: 2468, category: DiagnosticCategory.Error, key: "Cannot find global value '{0}'." },
|
||||
The_0_operator_cannot_be_applied_to_type_symbol: { code: 2469, category: DiagnosticCategory.Error, key: "The '{0}' operator cannot be applied to type 'symbol'." },
|
||||
Symbol_reference_does_not_refer_to_the_global_Symbol_constructor_object: { code: 2470, category: DiagnosticCategory.Error, key: "'Symbol' reference does not refer to the global Symbol constructor object." },
|
||||
A_computed_property_name_of_the_form_0_must_be_of_type_symbol: { code: 2471, category: DiagnosticCategory.Error, key: "A computed property name of the form '{0}' must be of type 'symbol'." },
|
||||
Spread_operator_in_new_expressions_is_only_available_when_targeting_ECMAScript_6_and_higher: { code: 2472, category: DiagnosticCategory.Error, key: "Spread operator in 'new' expressions is only available when targeting ECMAScript 6 and higher." },
|
||||
Enum_declarations_must_all_be_const_or_non_const: { code: 2473, category: DiagnosticCategory.Error, key: "Enum declarations must all be const or non-const." },
|
||||
In_const_enum_declarations_member_initializer_must_be_constant_expression: { code: 2474, category: DiagnosticCategory.Error, key: "In 'const' enum declarations member initializer must be constant expression." },
|
||||
const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment: { code: 2475, category: DiagnosticCategory.Error, key: "'const' enums can only be used in property or index access expressions or the right hand side of an import declaration or export assignment." },
|
||||
A_const_enum_member_can_only_be_accessed_using_a_string_literal: { code: 2476, category: DiagnosticCategory.Error, key: "A const enum member can only be accessed using a string literal." },
|
||||
const_enum_member_initializer_was_evaluated_to_a_non_finite_value: { code: 2477, category: DiagnosticCategory.Error, key: "'const' enum member initializer was evaluated to a non-finite value." },
|
||||
const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN: { code: 2478, category: DiagnosticCategory.Error, key: "'const' enum member initializer was evaluated to disallowed value 'NaN'." },
|
||||
Property_0_does_not_exist_on_const_enum_1: { code: 2479, category: DiagnosticCategory.Error, key: "Property '{0}' does not exist on 'const' enum '{1}'." },
|
||||
let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations: { code: 2480, category: DiagnosticCategory.Error, key: "'let' is not allowed to be used as a name in 'let' or 'const' declarations." },
|
||||
Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1: { code: 2481, category: DiagnosticCategory.Error, key: "Cannot initialize outer scoped variable '{0}' in the same scope as block scoped declaration '{1}'." },
|
||||
The_left_hand_side_of_a_for_of_statement_cannot_use_a_type_annotation: { code: 2483, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...of' statement cannot use a type annotation." },
|
||||
Export_declaration_conflicts_with_exported_declaration_of_0: { code: 2484, category: DiagnosticCategory.Error, key: "Export declaration conflicts with exported declaration of '{0}'" },
|
||||
The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant: { code: 2485, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...of' statement cannot be a previously defined constant." },
|
||||
The_left_hand_side_of_a_for_in_statement_cannot_be_a_previously_defined_constant: { code: 2486, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement cannot be a previously defined constant." },
|
||||
Invalid_left_hand_side_in_for_of_statement: { code: 2487, category: DiagnosticCategory.Error, key: "Invalid left-hand side in 'for...of' statement." },
|
||||
Type_must_have_a_Symbol_iterator_method_that_returns_an_iterator: { code: 2488, category: DiagnosticCategory.Error, key: "Type must have a '[Symbol.iterator]()' method that returns an iterator." },
|
||||
An_iterator_must_have_a_next_method: { code: 2489, category: DiagnosticCategory.Error, key: "An iterator must have a 'next()' method." },
|
||||
The_type_returned_by_the_next_method_of_an_iterator_must_have_a_value_property: { code: 2490, category: DiagnosticCategory.Error, key: "The type returned by the 'next()' method of an iterator must have a 'value' property." },
|
||||
The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern: { code: 2491, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement cannot be a destructuring pattern." },
|
||||
Cannot_redeclare_identifier_0_in_catch_clause: { code: 2492, category: DiagnosticCategory.Error, key: "Cannot redeclare identifier '{0}' in catch clause" },
|
||||
Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2: { code: 2493, category: DiagnosticCategory.Error, key: "Tuple type '{0}' with length '{1}' cannot be assigned to tuple with length '{2}'." },
|
||||
Using_a_string_in_a_for_of_statement_is_only_supported_in_ECMAScript_5_and_higher: { code: 2494, category: DiagnosticCategory.Error, key: "Using a string in a 'for...of' statement is only supported in ECMAScript 5 and higher." },
|
||||
Type_0_is_not_an_array_type_or_a_string_type: { code: 2495, category: DiagnosticCategory.Error, key: "Type '{0}' is not an array type or a string type." },
|
||||
The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression: { code: 2496, category: DiagnosticCategory.Error, key: "The 'arguments' object cannot be referenced in an arrow function in ES3 and ES5. Consider using a standard function expression." },
|
||||
External_module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct: { code: 2497, category: DiagnosticCategory.Error, key: "External module '{0}' resolves to a non-module entity and cannot be imported using this construct." },
|
||||
External_module_0_uses_export_and_cannot_be_used_with_export_Asterisk: { code: 2498, category: DiagnosticCategory.Error, key: "External module '{0}' uses 'export =' and cannot be used with 'export *'." },
|
||||
An_interface_can_only_extend_an_identifier_Slashqualified_name_with_optional_type_arguments: { code: 2499, category: DiagnosticCategory.Error, key: "An interface can only extend an identifier/qualified-name with optional type arguments." },
|
||||
A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments: { code: 2500, category: DiagnosticCategory.Error, key: "A class can only implement an identifier/qualified-name with optional type arguments." },
|
||||
A_rest_element_cannot_contain_a_binding_pattern: { code: 2501, category: DiagnosticCategory.Error, key: "A rest element cannot contain a binding pattern." },
|
||||
Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
|
||||
Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." },
|
||||
Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." },
|
||||
Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 4006, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of constructor signature from exported interface has or is using private name '{1}'." },
|
||||
Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 4008, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of call signature from exported interface has or is using private name '{1}'." },
|
||||
Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1: { code: 4010, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of public static method from exported class has or is using private name '{1}'." },
|
||||
Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1: { code: 4012, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of public method from exported class has or is using private name '{1}'." },
|
||||
Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1: { code: 4014, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of method from exported interface has or is using private name '{1}'." },
|
||||
Type_parameter_0_of_exported_function_has_or_is_using_private_name_1: { code: 4016, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported function has or is using private name '{1}'." },
|
||||
Implements_clause_of_exported_class_0_has_or_is_using_private_name_1: { code: 4019, category: DiagnosticCategory.Error, key: "Implements clause of exported class '{0}' has or is using private name '{1}'." },
|
||||
Extends_clause_of_exported_class_0_has_or_is_using_private_name_1: { code: 4020, category: DiagnosticCategory.Error, key: "Extends clause of exported class '{0}' has or is using private name '{1}'." },
|
||||
Extends_clause_of_exported_interface_0_has_or_is_using_private_name_1: { code: 4022, category: DiagnosticCategory.Error, key: "Extends clause of exported interface '{0}' has or is using private name '{1}'." },
|
||||
Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4023, category: DiagnosticCategory.Error, key: "Exported variable '{0}' has or is using name '{1}' from external module {2} but cannot be named." },
|
||||
Exported_variable_0_has_or_is_using_name_1_from_private_module_2: { code: 4024, category: DiagnosticCategory.Error, key: "Exported variable '{0}' has or is using name '{1}' from private module '{2}'." },
|
||||
Exported_variable_0_has_or_is_using_private_name_1: { code: 4025, category: DiagnosticCategory.Error, key: "Exported variable '{0}' has or is using private name '{1}'." },
|
||||
Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4026, category: DiagnosticCategory.Error, key: "Public static property '{0}' of exported class has or is using name '{1}' from external module {2} but cannot be named." },
|
||||
Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4027, category: DiagnosticCategory.Error, key: "Public static property '{0}' of exported class has or is using name '{1}' from private module '{2}'." },
|
||||
Public_static_property_0_of_exported_class_has_or_is_using_private_name_1: { code: 4028, category: DiagnosticCategory.Error, key: "Public static property '{0}' of exported class has or is using private name '{1}'." },
|
||||
Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4029, category: DiagnosticCategory.Error, key: "Public property '{0}' of exported class has or is using name '{1}' from external module {2} but cannot be named." },
|
||||
Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4030, category: DiagnosticCategory.Error, key: "Public property '{0}' of exported class has or is using name '{1}' from private module '{2}'." },
|
||||
Public_property_0_of_exported_class_has_or_is_using_private_name_1: { code: 4031, category: DiagnosticCategory.Error, key: "Public property '{0}' of exported class has or is using private name '{1}'." },
|
||||
Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4032, category: DiagnosticCategory.Error, key: "Property '{0}' of exported interface has or is using name '{1}' from private module '{2}'." },
|
||||
Property_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4033, category: DiagnosticCategory.Error, key: "Property '{0}' of exported interface has or is using private name '{1}'." },
|
||||
Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4034, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public static property setter from exported class has or is using name '{1}' from private module '{2}'." },
|
||||
Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_private_name_1: { code: 4035, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public static property setter from exported class has or is using private name '{1}'." },
|
||||
Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4036, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public property setter from exported class has or is using name '{1}' from private module '{2}'." },
|
||||
Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_private_name_1: { code: 4037, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public property setter from exported class has or is using private name '{1}'." },
|
||||
Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4038, category: DiagnosticCategory.Error, key: "Return type of public static property getter from exported class has or is using name '{0}' from external module {1} but cannot be named." },
|
||||
Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1: { code: 4039, category: DiagnosticCategory.Error, key: "Return type of public static property getter from exported class has or is using name '{0}' from private module '{1}'." },
|
||||
Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_private_name_0: { code: 4040, category: DiagnosticCategory.Error, key: "Return type of public static property getter from exported class has or is using private name '{0}'." },
|
||||
Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4041, category: DiagnosticCategory.Error, key: "Return type of public property getter from exported class has or is using name '{0}' from external module {1} but cannot be named." },
|
||||
Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1: { code: 4042, category: DiagnosticCategory.Error, key: "Return type of public property getter from exported class has or is using name '{0}' from private module '{1}'." },
|
||||
Return_type_of_public_property_getter_from_exported_class_has_or_is_using_private_name_0: { code: 4043, category: DiagnosticCategory.Error, key: "Return type of public property getter from exported class has or is using private name '{0}'." },
|
||||
Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1: { code: 4044, category: DiagnosticCategory.Error, key: "Return type of constructor signature from exported interface has or is using name '{0}' from private module '{1}'." },
|
||||
Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0: { code: 4045, category: DiagnosticCategory.Error, key: "Return type of constructor signature from exported interface has or is using private name '{0}'." },
|
||||
Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1: { code: 4046, category: DiagnosticCategory.Error, key: "Return type of call signature from exported interface has or is using name '{0}' from private module '{1}'." },
|
||||
Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0: { code: 4047, category: DiagnosticCategory.Error, key: "Return type of call signature from exported interface has or is using private name '{0}'." },
|
||||
Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1: { code: 4048, category: DiagnosticCategory.Error, key: "Return type of index signature from exported interface has or is using name '{0}' from private module '{1}'." },
|
||||
Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0: { code: 4049, category: DiagnosticCategory.Error, key: "Return type of index signature from exported interface has or is using private name '{0}'." },
|
||||
Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4050, category: DiagnosticCategory.Error, key: "Return type of public static method from exported class has or is using name '{0}' from external module {1} but cannot be named." },
|
||||
Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1: { code: 4051, category: DiagnosticCategory.Error, key: "Return type of public static method from exported class has or is using name '{0}' from private module '{1}'." },
|
||||
Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0: { code: 4052, category: DiagnosticCategory.Error, key: "Return type of public static method from exported class has or is using private name '{0}'." },
|
||||
Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4053, category: DiagnosticCategory.Error, key: "Return type of public method from exported class has or is using name '{0}' from external module {1} but cannot be named." },
|
||||
Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1: { code: 4054, category: DiagnosticCategory.Error, key: "Return type of public method from exported class has or is using name '{0}' from private module '{1}'." },
|
||||
Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0: { code: 4055, category: DiagnosticCategory.Error, key: "Return type of public method from exported class has or is using private name '{0}'." },
|
||||
Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1: { code: 4056, category: DiagnosticCategory.Error, key: "Return type of method from exported interface has or is using name '{0}' from private module '{1}'." },
|
||||
Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0: { code: 4057, category: DiagnosticCategory.Error, key: "Return type of method from exported interface has or is using private name '{0}'." },
|
||||
Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4058, category: DiagnosticCategory.Error, key: "Return type of exported function has or is using name '{0}' from external module {1} but cannot be named." },
|
||||
Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1: { code: 4059, category: DiagnosticCategory.Error, key: "Return type of exported function has or is using name '{0}' from private module '{1}'." },
|
||||
Return_type_of_exported_function_has_or_is_using_private_name_0: { code: 4060, category: DiagnosticCategory.Error, key: "Return type of exported function has or is using private name '{0}'." },
|
||||
Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4061, category: DiagnosticCategory.Error, key: "Parameter '{0}' of constructor from exported class has or is using name '{1}' from external module {2} but cannot be named." },
|
||||
Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4062, category: DiagnosticCategory.Error, key: "Parameter '{0}' of constructor from exported class has or is using name '{1}' from private module '{2}'." },
|
||||
Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1: { code: 4063, category: DiagnosticCategory.Error, key: "Parameter '{0}' of constructor from exported class has or is using private name '{1}'." },
|
||||
Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4064, category: DiagnosticCategory.Error, key: "Parameter '{0}' of constructor signature from exported interface has or is using name '{1}' from private module '{2}'." },
|
||||
Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 4065, category: DiagnosticCategory.Error, key: "Parameter '{0}' of constructor signature from exported interface has or is using private name '{1}'." },
|
||||
Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4066, category: DiagnosticCategory.Error, key: "Parameter '{0}' of call signature from exported interface has or is using name '{1}' from private module '{2}'." },
|
||||
Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 4067, category: DiagnosticCategory.Error, key: "Parameter '{0}' of call signature from exported interface has or is using private name '{1}'." },
|
||||
Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4068, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public static method from exported class has or is using name '{1}' from external module {2} but cannot be named." },
|
||||
Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4069, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public static method from exported class has or is using name '{1}' from private module '{2}'." },
|
||||
Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1: { code: 4070, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public static method from exported class has or is using private name '{1}'." },
|
||||
Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4071, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public method from exported class has or is using name '{1}' from external module {2} but cannot be named." },
|
||||
Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4072, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public method from exported class has or is using name '{1}' from private module '{2}'." },
|
||||
Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1: { code: 4073, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public method from exported class has or is using private name '{1}'." },
|
||||
Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4074, category: DiagnosticCategory.Error, key: "Parameter '{0}' of method from exported interface has or is using name '{1}' from private module '{2}'." },
|
||||
Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1: { code: 4075, category: DiagnosticCategory.Error, key: "Parameter '{0}' of method from exported interface has or is using private name '{1}'." },
|
||||
Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4076, category: DiagnosticCategory.Error, key: "Parameter '{0}' of exported function has or is using name '{1}' from external module {2} but cannot be named." },
|
||||
Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2: { code: 4077, category: DiagnosticCategory.Error, key: "Parameter '{0}' of exported function has or is using name '{1}' from private module '{2}'." },
|
||||
Parameter_0_of_exported_function_has_or_is_using_private_name_1: { code: 4078, category: DiagnosticCategory.Error, key: "Parameter '{0}' of exported function has or is using private name '{1}'." },
|
||||
Exported_type_alias_0_has_or_is_using_private_name_1: { code: 4081, category: DiagnosticCategory.Error, key: "Exported type alias '{0}' has or is using private name '{1}'." },
|
||||
Default_export_of_the_module_has_or_is_using_private_name_0: { code: 4082, category: DiagnosticCategory.Error, key: "Default export of the module has or is using private name '{0}'." },
|
||||
Loop_contains_block_scoped_variable_0_referenced_by_a_function_in_the_loop_This_is_only_supported_in_ECMAScript_6_or_higher: { code: 4091, category: DiagnosticCategory.Error, key: "Loop contains block-scoped variable '{0}' referenced by a function in the loop. This is only supported in ECMAScript 6 or higher." },
|
||||
The_current_host_does_not_support_the_0_option: { code: 5001, category: DiagnosticCategory.Error, key: "The current host does not support the '{0}' option." },
|
||||
Cannot_find_the_common_subdirectory_path_for_the_input_files: { code: 5009, category: DiagnosticCategory.Error, key: "Cannot find the common subdirectory path for the input files." },
|
||||
Cannot_read_file_0_Colon_1: { code: 5012, category: DiagnosticCategory.Error, key: "Cannot read file '{0}': {1}" },
|
||||
Unsupported_file_encoding: { code: 5013, category: DiagnosticCategory.Error, key: "Unsupported file encoding." },
|
||||
Unknown_compiler_option_0: { code: 5023, category: DiagnosticCategory.Error, key: "Unknown compiler option '{0}'." },
|
||||
Compiler_option_0_requires_a_value_of_type_1: { code: 5024, category: DiagnosticCategory.Error, key: "Compiler option '{0}' requires a value of type {1}." },
|
||||
Could_not_write_file_0_Colon_1: { code: 5033, category: DiagnosticCategory.Error, key: "Could not write file '{0}': {1}" },
|
||||
Option_mapRoot_cannot_be_specified_without_specifying_sourcemap_option: { code: 5038, category: DiagnosticCategory.Error, key: "Option 'mapRoot' cannot be specified without specifying 'sourcemap' option." },
|
||||
Option_sourceRoot_cannot_be_specified_without_specifying_sourcemap_option: { code: 5039, category: DiagnosticCategory.Error, key: "Option 'sourceRoot' cannot be specified without specifying 'sourcemap' option." },
|
||||
Option_noEmit_cannot_be_specified_with_option_out_or_outDir: { code: 5040, category: DiagnosticCategory.Error, key: "Option 'noEmit' cannot be specified with option 'out' or 'outDir'." },
|
||||
Option_noEmit_cannot_be_specified_with_option_declaration: { code: 5041, category: DiagnosticCategory.Error, key: "Option 'noEmit' cannot be specified with option 'declaration'." },
|
||||
Option_project_cannot_be_mixed_with_source_files_on_a_command_line: { code: 5042, category: DiagnosticCategory.Error, key: "Option 'project' cannot be mixed with source files on a command line." },
|
||||
Option_sourceMap_cannot_be_specified_with_option_separateCompilation: { code: 5043, category: DiagnosticCategory.Error, key: "Option 'sourceMap' cannot be specified with option 'separateCompilation'." },
|
||||
Option_declaration_cannot_be_specified_with_option_separateCompilation: { code: 5044, category: DiagnosticCategory.Error, key: "Option 'declaration' cannot be specified with option 'separateCompilation'." },
|
||||
Option_noEmitOnError_cannot_be_specified_with_option_separateCompilation: { code: 5045, category: DiagnosticCategory.Error, key: "Option 'noEmitOnError' cannot be specified with option 'separateCompilation'." },
|
||||
Option_out_cannot_be_specified_with_option_separateCompilation: { code: 5046, category: DiagnosticCategory.Error, key: "Option 'out' cannot be specified with option 'separateCompilation'." },
|
||||
Option_separateCompilation_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES6_or_higher: { code: 5047, category: DiagnosticCategory.Error, key: "Option 'separateCompilation' can only be used when either option'--module' is provided or option 'target' is 'ES6' or higher." },
|
||||
Concatenate_and_emit_output_to_single_file: { code: 6001, category: DiagnosticCategory.Message, key: "Concatenate and emit output to single file." },
|
||||
Generates_corresponding_d_ts_file: { code: 6002, category: DiagnosticCategory.Message, key: "Generates corresponding '.d.ts' file." },
|
||||
Specifies_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations: { code: 6003, category: DiagnosticCategory.Message, key: "Specifies the location where debugger should locate map files instead of generated locations." },
|
||||
Specifies_the_location_where_debugger_should_locate_TypeScript_files_instead_of_source_locations: { code: 6004, category: DiagnosticCategory.Message, key: "Specifies the location where debugger should locate TypeScript files instead of source locations." },
|
||||
Watch_input_files: { code: 6005, category: DiagnosticCategory.Message, key: "Watch input files." },
|
||||
Redirect_output_structure_to_the_directory: { code: 6006, category: DiagnosticCategory.Message, key: "Redirect output structure to the directory." },
|
||||
Do_not_erase_const_enum_declarations_in_generated_code: { code: 6007, category: DiagnosticCategory.Message, key: "Do not erase const enum declarations in generated code." },
|
||||
Do_not_emit_outputs_if_any_type_checking_errors_were_reported: { code: 6008, category: DiagnosticCategory.Message, key: "Do not emit outputs if any type checking errors were reported." },
|
||||
Do_not_emit_comments_to_output: { code: 6009, category: DiagnosticCategory.Message, key: "Do not emit comments to output." },
|
||||
Do_not_emit_outputs: { code: 6010, category: DiagnosticCategory.Message, key: "Do not emit outputs." },
|
||||
Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES6_experimental: { code: 6015, category: DiagnosticCategory.Message, key: "Specify ECMAScript target version: 'ES3' (default), 'ES5', or 'ES6' (experimental)" },
|
||||
Specify_module_code_generation_Colon_commonjs_or_amd: { code: 6016, category: DiagnosticCategory.Message, key: "Specify module code generation: 'commonjs' or 'amd'" },
|
||||
Print_this_message: { code: 6017, category: DiagnosticCategory.Message, key: "Print this message." },
|
||||
Print_the_compiler_s_version: { code: 6019, category: DiagnosticCategory.Message, key: "Print the compiler's version." },
|
||||
Compile_the_project_in_the_given_directory: { code: 6020, category: DiagnosticCategory.Message, key: "Compile the project in the given directory." },
|
||||
Syntax_Colon_0: { code: 6023, category: DiagnosticCategory.Message, key: "Syntax: {0}" },
|
||||
options: { code: 6024, category: DiagnosticCategory.Message, key: "options" },
|
||||
file: { code: 6025, category: DiagnosticCategory.Message, key: "file" },
|
||||
Examples_Colon_0: { code: 6026, category: DiagnosticCategory.Message, key: "Examples: {0}" },
|
||||
Options_Colon: { code: 6027, category: DiagnosticCategory.Message, key: "Options:" },
|
||||
Version_0: { code: 6029, category: DiagnosticCategory.Message, key: "Version {0}" },
|
||||
Insert_command_line_options_and_files_from_a_file: { code: 6030, category: DiagnosticCategory.Message, key: "Insert command line options and files from a file." },
|
||||
File_change_detected_Starting_incremental_compilation: { code: 6032, category: DiagnosticCategory.Message, key: "File change detected. Starting incremental compilation..." },
|
||||
KIND: { code: 6034, category: DiagnosticCategory.Message, key: "KIND" },
|
||||
FILE: { code: 6035, category: DiagnosticCategory.Message, key: "FILE" },
|
||||
VERSION: { code: 6036, category: DiagnosticCategory.Message, key: "VERSION" },
|
||||
LOCATION: { code: 6037, category: DiagnosticCategory.Message, key: "LOCATION" },
|
||||
DIRECTORY: { code: 6038, category: DiagnosticCategory.Message, key: "DIRECTORY" },
|
||||
Compilation_complete_Watching_for_file_changes: { code: 6042, category: DiagnosticCategory.Message, key: "Compilation complete. Watching for file changes." },
|
||||
Generates_corresponding_map_file: { code: 6043, category: DiagnosticCategory.Message, key: "Generates corresponding '.map' file." },
|
||||
Compiler_option_0_expects_an_argument: { code: 6044, category: DiagnosticCategory.Error, key: "Compiler option '{0}' expects an argument." },
|
||||
Unterminated_quoted_string_in_response_file_0: { code: 6045, category: DiagnosticCategory.Error, key: "Unterminated quoted string in response file '{0}'." },
|
||||
Argument_for_module_option_must_be_commonjs_or_amd: { code: 6046, category: DiagnosticCategory.Error, key: "Argument for '--module' option must be 'commonjs' or 'amd'." },
|
||||
Argument_for_target_option_must_be_es3_es5_or_es6: { code: 6047, category: DiagnosticCategory.Error, key: "Argument for '--target' option must be 'es3', 'es5', or 'es6'." },
|
||||
Locale_must_be_of_the_form_language_or_language_territory_For_example_0_or_1: { code: 6048, category: DiagnosticCategory.Error, key: "Locale must be of the form <language> or <language>-<territory>. For example '{0}' or '{1}'." },
|
||||
Unsupported_locale_0: { code: 6049, category: DiagnosticCategory.Error, key: "Unsupported locale '{0}'." },
|
||||
Unable_to_open_file_0: { code: 6050, category: DiagnosticCategory.Error, key: "Unable to open file '{0}'." },
|
||||
Corrupted_locale_file_0: { code: 6051, category: DiagnosticCategory.Error, key: "Corrupted locale file {0}." },
|
||||
Raise_error_on_expressions_and_declarations_with_an_implied_any_type: { code: 6052, category: DiagnosticCategory.Message, key: "Raise error on expressions and declarations with an implied 'any' type." },
|
||||
File_0_not_found: { code: 6053, category: DiagnosticCategory.Error, key: "File '{0}' not found." },
|
||||
File_0_must_have_extension_ts_or_d_ts: { code: 6054, category: DiagnosticCategory.Error, key: "File '{0}' must have extension '.ts' or '.d.ts'." },
|
||||
Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures: { code: 6055, category: DiagnosticCategory.Message, key: "Suppress noImplicitAny errors for indexing objects lacking index signatures." },
|
||||
Do_not_emit_declarations_for_code_that_has_an_internal_annotation: { code: 6056, category: DiagnosticCategory.Message, key: "Do not emit declarations for code that has an '@internal' annotation." },
|
||||
Preserve_new_lines_when_emitting_code: { code: 6057, category: DiagnosticCategory.Message, key: "Preserve new-lines when emitting code." },
|
||||
Specifies_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir: { code: 6058, category: DiagnosticCategory.Message, key: "Specifies the root directory of input files. Use to control the output directory structure with --outDir." },
|
||||
File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files: { code: 6059, category: DiagnosticCategory.Error, key: "File '{0}' is not under 'rootDir' '{1}'. 'rootDir' is expected to contain all source files." },
|
||||
Variable_0_implicitly_has_an_1_type: { code: 7005, category: DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." },
|
||||
Parameter_0_implicitly_has_an_1_type: { code: 7006, category: DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." },
|
||||
Member_0_implicitly_has_an_1_type: { code: 7008, category: DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." },
|
||||
new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type: { code: 7009, category: DiagnosticCategory.Error, key: "'new' expression, whose target lacks a construct signature, implicitly has an 'any' type." },
|
||||
_0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type: { code: 7010, category: DiagnosticCategory.Error, key: "'{0}', which lacks return-type annotation, implicitly has an '{1}' return type." },
|
||||
Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type: { code: 7011, category: DiagnosticCategory.Error, key: "Function expression, which lacks return-type annotation, implicitly has an '{0}' return type." },
|
||||
Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type: { code: 7013, category: DiagnosticCategory.Error, key: "Construct signature, which lacks return-type annotation, implicitly has an 'any' return type." },
|
||||
Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation: { code: 7016, category: DiagnosticCategory.Error, key: "Property '{0}' implicitly has type 'any', because its 'set' accessor lacks a type annotation." },
|
||||
Index_signature_of_object_type_implicitly_has_an_any_type: { code: 7017, category: DiagnosticCategory.Error, key: "Index signature of object type implicitly has an 'any' type." },
|
||||
Object_literal_s_property_0_implicitly_has_an_1_type: { code: 7018, category: DiagnosticCategory.Error, key: "Object literal's property '{0}' implicitly has an '{1}' type." },
|
||||
Rest_parameter_0_implicitly_has_an_any_type: { code: 7019, category: DiagnosticCategory.Error, key: "Rest parameter '{0}' implicitly has an 'any[]' type." },
|
||||
Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type: { code: 7020, category: DiagnosticCategory.Error, key: "Call signature, which lacks return-type annotation, implicitly has an 'any' return type." },
|
||||
_0_implicitly_has_type_any_because_it_is_referenced_directly_or_indirectly_in_its_own_type_annotation: { code: 7021, category: DiagnosticCategory.Error, key: "'{0}' implicitly has type 'any' because it is referenced directly or indirectly in its own type annotation." },
|
||||
_0_implicitly_has_type_any_because_it_is_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer: { code: 7022, category: DiagnosticCategory.Error, key: "'{0}' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer." },
|
||||
_0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions: { code: 7023, category: DiagnosticCategory.Error, key: "'{0}' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions." },
|
||||
Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions: { code: 7024, category: DiagnosticCategory.Error, key: "Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions." },
|
||||
You_cannot_rename_this_element: { code: 8000, category: DiagnosticCategory.Error, key: "You cannot rename this element." },
|
||||
You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library: { code: 8001, category: DiagnosticCategory.Error, key: "You cannot rename elements that are defined in the standard TypeScript library." },
|
||||
import_can_only_be_used_in_a_ts_file: { code: 8002, category: DiagnosticCategory.Error, key: "'import ... =' can only be used in a .ts file." },
|
||||
export_can_only_be_used_in_a_ts_file: { code: 8003, category: DiagnosticCategory.Error, key: "'export=' can only be used in a .ts file." },
|
||||
type_parameter_declarations_can_only_be_used_in_a_ts_file: { code: 8004, category: DiagnosticCategory.Error, key: "'type parameter declarations' can only be used in a .ts file." },
|
||||
implements_clauses_can_only_be_used_in_a_ts_file: { code: 8005, category: DiagnosticCategory.Error, key: "'implements clauses' can only be used in a .ts file." },
|
||||
interface_declarations_can_only_be_used_in_a_ts_file: { code: 8006, category: DiagnosticCategory.Error, key: "'interface declarations' can only be used in a .ts file." },
|
||||
module_declarations_can_only_be_used_in_a_ts_file: { code: 8007, category: DiagnosticCategory.Error, key: "'module declarations' can only be used in a .ts file." },
|
||||
type_aliases_can_only_be_used_in_a_ts_file: { code: 8008, category: DiagnosticCategory.Error, key: "'type aliases' can only be used in a .ts file." },
|
||||
_0_can_only_be_used_in_a_ts_file: { code: 8009, category: DiagnosticCategory.Error, key: "'{0}' can only be used in a .ts file." },
|
||||
types_can_only_be_used_in_a_ts_file: { code: 8010, category: DiagnosticCategory.Error, key: "'types' can only be used in a .ts file." },
|
||||
type_arguments_can_only_be_used_in_a_ts_file: { code: 8011, category: DiagnosticCategory.Error, key: "'type arguments' can only be used in a .ts file." },
|
||||
parameter_modifiers_can_only_be_used_in_a_ts_file: { code: 8012, category: DiagnosticCategory.Error, key: "'parameter modifiers' can only be used in a .ts file." },
|
||||
can_only_be_used_in_a_ts_file: { code: 8013, category: DiagnosticCategory.Error, key: "'?' can only be used in a .ts file." },
|
||||
property_declarations_can_only_be_used_in_a_ts_file: { code: 8014, category: DiagnosticCategory.Error, key: "'property declarations' can only be used in a .ts file." },
|
||||
enum_declarations_can_only_be_used_in_a_ts_file: { code: 8015, category: DiagnosticCategory.Error, key: "'enum declarations' can only be used in a .ts file." },
|
||||
type_assertion_expressions_can_only_be_used_in_a_ts_file: { code: 8016, category: DiagnosticCategory.Error, key: "'type assertion expressions' can only be used in a .ts file." },
|
||||
decorators_can_only_be_used_in_a_ts_file: { code: 8017, category: DiagnosticCategory.Error, key: "'decorators' can only be used in a .ts file." },
|
||||
yield_expressions_are_not_currently_supported: { code: 9000, category: DiagnosticCategory.Error, key: "'yield' expressions are not currently supported." },
|
||||
Generators_are_not_currently_supported: { code: 9001, category: DiagnosticCategory.Error, key: "Generators are not currently supported." },
|
||||
Only_identifiers_Slashqualified_names_with_optional_type_arguments_are_currently_supported_in_a_class_extends_clauses: { code: 9002, category: DiagnosticCategory.Error, key: "Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clauses." },
|
||||
class_expressions_are_not_currently_supported: { code: 9003, category: DiagnosticCategory.Error, key: "'class' expressions are not currently supported." },
|
||||
class_declarations_are_only_supported_directly_inside_a_module_or_as_a_top_level_declaration: { code: 9004, category: DiagnosticCategory.Error, key: "'class' declarations are only supported directly inside a module or as a top level declaration." },
|
||||
};
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+4197
-1552
File diff suppressed because it is too large
Load Diff
+2369
-990
File diff suppressed because it is too large
Load Diff
+1035
-246
File diff suppressed because it is too large
Load Diff
+550
-238
File diff suppressed because one or more lines are too long
@@ -0,0 +1,390 @@
|
||||
/// <reference path="checker.ts"/>
|
||||
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
export interface SourceMapWriter {
|
||||
getSourceMapData(): SourceMapData;
|
||||
setSourceFile(sourceFile: SourceFile): void;
|
||||
emitPos(pos: number): void;
|
||||
emitStart(range: TextRange): void;
|
||||
emitEnd(range: TextRange, stopOverridingSpan?: boolean): void;
|
||||
changeEmitSourcePos(): void;
|
||||
getText(): string;
|
||||
getSourceMappingURL(): string;
|
||||
initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void;
|
||||
reset(): void;
|
||||
}
|
||||
|
||||
let nullSourceMapWriter: SourceMapWriter;
|
||||
|
||||
export function getNullSourceMapWriter(): SourceMapWriter {
|
||||
if (nullSourceMapWriter === undefined) {
|
||||
nullSourceMapWriter = {
|
||||
getSourceMapData(): SourceMapData { return undefined; },
|
||||
setSourceFile(sourceFile: SourceFile): void { },
|
||||
emitStart(range: TextRange): void { },
|
||||
emitEnd(range: TextRange, stopOverridingSpan?: boolean): void { },
|
||||
emitPos(pos: number): void { },
|
||||
changeEmitSourcePos(): void { },
|
||||
getText(): string { return undefined; },
|
||||
getSourceMappingURL(): string { return undefined; },
|
||||
initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void { },
|
||||
reset(): void { },
|
||||
};
|
||||
}
|
||||
|
||||
return nullSourceMapWriter;
|
||||
}
|
||||
|
||||
export function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter): SourceMapWriter {
|
||||
const compilerOptions = host.getCompilerOptions();
|
||||
let currentSourceFile: SourceFile;
|
||||
let sourceMapDir: string; // The directory in which sourcemap will be
|
||||
let stopOverridingSpan = false;
|
||||
let modifyLastSourcePos = false;
|
||||
|
||||
// Current source map file and its index in the sources list
|
||||
let sourceMapSourceIndex: number;
|
||||
|
||||
// Last recorded and encoded spans
|
||||
let lastRecordedSourceMapSpan: SourceMapSpan;
|
||||
let lastEncodedSourceMapSpan: SourceMapSpan;
|
||||
let lastEncodedNameIndex: number;
|
||||
|
||||
// Source map data
|
||||
let sourceMapData: SourceMapData;
|
||||
|
||||
return {
|
||||
getSourceMapData: () => sourceMapData,
|
||||
setSourceFile,
|
||||
emitPos,
|
||||
emitStart,
|
||||
emitEnd,
|
||||
changeEmitSourcePos,
|
||||
getText,
|
||||
getSourceMappingURL,
|
||||
initialize,
|
||||
reset,
|
||||
};
|
||||
|
||||
function initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) {
|
||||
if (sourceMapData) {
|
||||
reset();
|
||||
}
|
||||
|
||||
currentSourceFile = undefined;
|
||||
|
||||
// Current source map file and its index in the sources list
|
||||
sourceMapSourceIndex = -1;
|
||||
|
||||
// Last recorded and encoded spans
|
||||
lastRecordedSourceMapSpan = undefined;
|
||||
lastEncodedSourceMapSpan = {
|
||||
emittedLine: 1,
|
||||
emittedColumn: 1,
|
||||
sourceLine: 1,
|
||||
sourceColumn: 1,
|
||||
sourceIndex: 0
|
||||
};
|
||||
lastEncodedNameIndex = 0;
|
||||
|
||||
// Initialize source map data
|
||||
sourceMapData = {
|
||||
sourceMapFilePath: sourceMapFilePath,
|
||||
jsSourceMappingURL: !compilerOptions.inlineSourceMap ? getBaseFileName(normalizeSlashes(sourceMapFilePath)) : undefined,
|
||||
sourceMapFile: getBaseFileName(normalizeSlashes(filePath)),
|
||||
sourceMapSourceRoot: compilerOptions.sourceRoot || "",
|
||||
sourceMapSources: [],
|
||||
inputSourceFileNames: [],
|
||||
sourceMapNames: [],
|
||||
sourceMapMappings: "",
|
||||
sourceMapSourcesContent: compilerOptions.inlineSources ? [] : undefined,
|
||||
sourceMapDecodedMappings: []
|
||||
};
|
||||
|
||||
// Normalize source root and make sure it has trailing "/" so that it can be used to combine paths with the
|
||||
// relative paths of the sources list in the sourcemap
|
||||
sourceMapData.sourceMapSourceRoot = ts.normalizeSlashes(sourceMapData.sourceMapSourceRoot);
|
||||
if (sourceMapData.sourceMapSourceRoot.length && sourceMapData.sourceMapSourceRoot.charCodeAt(sourceMapData.sourceMapSourceRoot.length - 1) !== CharacterCodes.slash) {
|
||||
sourceMapData.sourceMapSourceRoot += directorySeparator;
|
||||
}
|
||||
|
||||
if (compilerOptions.mapRoot) {
|
||||
sourceMapDir = normalizeSlashes(compilerOptions.mapRoot);
|
||||
if (!isBundledEmit) { // emitting single module file
|
||||
Debug.assert(sourceFiles.length === 1);
|
||||
// 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(sourceFiles[0], host, sourceMapDir));
|
||||
}
|
||||
|
||||
if (!isRootedDiskPath(sourceMapDir) && !isUrl(sourceMapDir)) {
|
||||
// The relative paths are relative to the common directory
|
||||
sourceMapDir = combinePaths(host.getCommonSourceDirectory(), sourceMapDir);
|
||||
sourceMapData.jsSourceMappingURL = getRelativePathToDirectoryOrUrl(
|
||||
getDirectoryPath(normalizePath(filePath)), // get the relative sourceMapDir path based on jsFilePath
|
||||
combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), // this is where user expects to see sourceMap
|
||||
host.getCurrentDirectory(),
|
||||
host.getCanonicalFileName,
|
||||
/*isAbsolutePathAnUrl*/ true);
|
||||
}
|
||||
else {
|
||||
sourceMapData.jsSourceMappingURL = combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
sourceMapDir = getDirectoryPath(normalizePath(filePath));
|
||||
}
|
||||
}
|
||||
|
||||
function reset() {
|
||||
currentSourceFile = undefined;
|
||||
sourceMapDir = undefined;
|
||||
sourceMapSourceIndex = undefined;
|
||||
lastRecordedSourceMapSpan = undefined;
|
||||
lastEncodedSourceMapSpan = undefined;
|
||||
lastEncodedNameIndex = undefined;
|
||||
sourceMapData = undefined;
|
||||
}
|
||||
|
||||
function updateLastEncodedAndRecordedSpans() {
|
||||
if (modifyLastSourcePos) {
|
||||
// Reset the source pos
|
||||
modifyLastSourcePos = false;
|
||||
|
||||
// Change Last recorded Map with last encoded emit line and character
|
||||
lastRecordedSourceMapSpan.emittedLine = lastEncodedSourceMapSpan.emittedLine;
|
||||
lastRecordedSourceMapSpan.emittedColumn = lastEncodedSourceMapSpan.emittedColumn;
|
||||
|
||||
// Pop sourceMapDecodedMappings to remove last entry
|
||||
sourceMapData.sourceMapDecodedMappings.pop();
|
||||
|
||||
// Change the last encoded source map
|
||||
lastEncodedSourceMapSpan = sourceMapData.sourceMapDecodedMappings.length ?
|
||||
sourceMapData.sourceMapDecodedMappings[sourceMapData.sourceMapDecodedMappings.length - 1] :
|
||||
undefined;
|
||||
|
||||
// TODO: Update lastEncodedNameIndex
|
||||
// Since we dont support this any more, lets not worry about it right now.
|
||||
// When we start supporting nameIndex, we will get back to this
|
||||
|
||||
// Change the encoded source map
|
||||
const sourceMapMappings = sourceMapData.sourceMapMappings;
|
||||
let lenthToSet = sourceMapMappings.length - 1;
|
||||
for (; lenthToSet >= 0; lenthToSet--) {
|
||||
const currentChar = sourceMapMappings.charAt(lenthToSet);
|
||||
if (currentChar === ",") {
|
||||
// Separator for the entry found
|
||||
break;
|
||||
}
|
||||
if (currentChar === ";" && lenthToSet !== 0 && sourceMapMappings.charAt(lenthToSet - 1) !== ";") {
|
||||
// Last line separator found
|
||||
break;
|
||||
}
|
||||
}
|
||||
sourceMapData.sourceMapMappings = sourceMapMappings.substr(0, Math.max(0, lenthToSet));
|
||||
}
|
||||
}
|
||||
|
||||
// Encoding for sourcemap span
|
||||
function encodeLastRecordedSourceMapSpan() {
|
||||
if (!lastRecordedSourceMapSpan || lastRecordedSourceMapSpan === lastEncodedSourceMapSpan) {
|
||||
return;
|
||||
}
|
||||
|
||||
let prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn;
|
||||
// Line/Comma delimiters
|
||||
if (lastEncodedSourceMapSpan.emittedLine === lastRecordedSourceMapSpan.emittedLine) {
|
||||
// Emit comma to separate the entry
|
||||
if (sourceMapData.sourceMapMappings) {
|
||||
sourceMapData.sourceMapMappings += ",";
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Emit line delimiters
|
||||
for (let encodedLine = lastEncodedSourceMapSpan.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) {
|
||||
sourceMapData.sourceMapMappings += ";";
|
||||
}
|
||||
prevEncodedEmittedColumn = 1;
|
||||
}
|
||||
|
||||
// 1. Relative Column 0 based
|
||||
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.emittedColumn - prevEncodedEmittedColumn);
|
||||
|
||||
// 2. Relative sourceIndex
|
||||
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan.sourceIndex);
|
||||
|
||||
// 3. Relative sourceLine 0 based
|
||||
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan.sourceLine);
|
||||
|
||||
// 4. Relative sourceColumn 0 based
|
||||
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan.sourceColumn);
|
||||
|
||||
// 5. Relative namePosition 0 based
|
||||
if (lastRecordedSourceMapSpan.nameIndex >= 0) {
|
||||
Debug.assert(false, "We do not support name index right now, Make sure to update updateLastEncodedAndRecordedSpans when we start using this");
|
||||
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex - lastEncodedNameIndex);
|
||||
lastEncodedNameIndex = lastRecordedSourceMapSpan.nameIndex;
|
||||
}
|
||||
|
||||
lastEncodedSourceMapSpan = lastRecordedSourceMapSpan;
|
||||
sourceMapData.sourceMapDecodedMappings.push(lastEncodedSourceMapSpan);
|
||||
}
|
||||
|
||||
function emitPos(pos: number) {
|
||||
if (pos === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceLinePos = getLineAndCharacterOfPosition(currentSourceFile, pos);
|
||||
|
||||
// Convert the location to be one-based.
|
||||
sourceLinePos.line++;
|
||||
sourceLinePos.character++;
|
||||
|
||||
const emittedLine = writer.getLine();
|
||||
const emittedColumn = writer.getColumn();
|
||||
|
||||
// If this location wasn't recorded or the location in source is going backwards, record the span
|
||||
if (!lastRecordedSourceMapSpan ||
|
||||
lastRecordedSourceMapSpan.emittedLine !== emittedLine ||
|
||||
lastRecordedSourceMapSpan.emittedColumn !== emittedColumn ||
|
||||
(lastRecordedSourceMapSpan.sourceIndex === sourceMapSourceIndex &&
|
||||
(lastRecordedSourceMapSpan.sourceLine > sourceLinePos.line ||
|
||||
(lastRecordedSourceMapSpan.sourceLine === sourceLinePos.line && lastRecordedSourceMapSpan.sourceColumn > sourceLinePos.character)))) {
|
||||
|
||||
// Encode the last recordedSpan before assigning new
|
||||
encodeLastRecordedSourceMapSpan();
|
||||
|
||||
// New span
|
||||
lastRecordedSourceMapSpan = {
|
||||
emittedLine: emittedLine,
|
||||
emittedColumn: emittedColumn,
|
||||
sourceLine: sourceLinePos.line,
|
||||
sourceColumn: sourceLinePos.character,
|
||||
sourceIndex: sourceMapSourceIndex
|
||||
};
|
||||
|
||||
stopOverridingSpan = false;
|
||||
}
|
||||
else if (!stopOverridingSpan) {
|
||||
// Take the new pos instead since there is no change in emittedLine and column since last location
|
||||
lastRecordedSourceMapSpan.sourceLine = sourceLinePos.line;
|
||||
lastRecordedSourceMapSpan.sourceColumn = sourceLinePos.character;
|
||||
lastRecordedSourceMapSpan.sourceIndex = sourceMapSourceIndex;
|
||||
}
|
||||
|
||||
updateLastEncodedAndRecordedSpans();
|
||||
}
|
||||
|
||||
function getStartPos(range: TextRange) {
|
||||
const rangeHasDecorators = !!(range as Node).decorators;
|
||||
return range.pos !== -1 ? skipTrivia(currentSourceFile.text, rangeHasDecorators ? (range as Node).decorators.end : range.pos) : -1;
|
||||
}
|
||||
|
||||
function emitStart(range: TextRange) {
|
||||
emitPos(getStartPos(range));
|
||||
}
|
||||
|
||||
function emitEnd(range: TextRange, stopOverridingEnd?: boolean) {
|
||||
emitPos(range.end);
|
||||
stopOverridingSpan = stopOverridingEnd;
|
||||
}
|
||||
|
||||
function changeEmitSourcePos() {
|
||||
Debug.assert(!modifyLastSourcePos);
|
||||
modifyLastSourcePos = true;
|
||||
}
|
||||
|
||||
function setSourceFile(sourceFile: SourceFile) {
|
||||
currentSourceFile = sourceFile;
|
||||
|
||||
// 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
|
||||
const sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir;
|
||||
|
||||
const source = getRelativePathToDirectoryOrUrl(sourcesDirectoryPath,
|
||||
currentSourceFile.fileName,
|
||||
host.getCurrentDirectory(),
|
||||
host.getCanonicalFileName,
|
||||
/*isAbsolutePathAnUrl*/ true);
|
||||
|
||||
sourceMapSourceIndex = indexOf(sourceMapData.sourceMapSources, source);
|
||||
if (sourceMapSourceIndex === -1) {
|
||||
sourceMapSourceIndex = sourceMapData.sourceMapSources.length;
|
||||
sourceMapData.sourceMapSources.push(source);
|
||||
|
||||
// The one that can be used from program to get the actual source file
|
||||
sourceMapData.inputSourceFileNames.push(sourceFile.fileName);
|
||||
|
||||
if (compilerOptions.inlineSources) {
|
||||
sourceMapData.sourceMapSourcesContent.push(sourceFile.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getText() {
|
||||
encodeLastRecordedSourceMapSpan();
|
||||
|
||||
return stringify({
|
||||
version: 3,
|
||||
file: sourceMapData.sourceMapFile,
|
||||
sourceRoot: sourceMapData.sourceMapSourceRoot,
|
||||
sources: sourceMapData.sourceMapSources,
|
||||
names: sourceMapData.sourceMapNames,
|
||||
mappings: sourceMapData.sourceMapMappings,
|
||||
sourcesContent: sourceMapData.sourceMapSourcesContent,
|
||||
});
|
||||
}
|
||||
|
||||
function getSourceMappingURL() {
|
||||
if (compilerOptions.inlineSourceMap) {
|
||||
// Encode the sourceMap into the sourceMap url
|
||||
const base64SourceMapText = convertToBase64(getText());
|
||||
return sourceMapData.jsSourceMappingURL = `data:application/json;base64,${base64SourceMapText}`;
|
||||
}
|
||||
else {
|
||||
return sourceMapData.jsSourceMappingURL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
function base64FormatEncode(inValue: number) {
|
||||
if (inValue < 64) {
|
||||
return base64Chars.charAt(inValue);
|
||||
}
|
||||
|
||||
throw TypeError(inValue + ": not a 64 based value");
|
||||
}
|
||||
|
||||
function base64VLQFormatEncode(inValue: number) {
|
||||
// Add a new least significant bit that has the sign of the value.
|
||||
// if negative number the least significant bit that gets added to the number has value 1
|
||||
// else least significant bit value that gets added is 0
|
||||
// eg. -1 changes to binary : 01 [1] => 3
|
||||
// +1 changes to binary : 01 [0] => 2
|
||||
if (inValue < 0) {
|
||||
inValue = ((-inValue) << 1) + 1;
|
||||
}
|
||||
else {
|
||||
inValue = inValue << 1;
|
||||
}
|
||||
|
||||
// Encode 5 bits at a time starting from least significant bits
|
||||
let encodedStr = "";
|
||||
do {
|
||||
let currentDigit = inValue & 31; // 11111
|
||||
inValue = inValue >> 5;
|
||||
if (inValue > 0) {
|
||||
// There are still more digits to decode, set the msb (6th bit)
|
||||
currentDigit = currentDigit | 32;
|
||||
}
|
||||
encodedStr = encodedStr + base64FormatEncode(currentDigit);
|
||||
} while (inValue > 0);
|
||||
|
||||
return encodedStr;
|
||||
}
|
||||
}
|
||||
+363
-62
@@ -1,6 +1,9 @@
|
||||
/// <reference path="core.ts"/>
|
||||
|
||||
module ts {
|
||||
namespace ts {
|
||||
export type FileWatcherCallback = (path: string, removed?: boolean) => void;
|
||||
export type DirectoryWatcherCallback = (path: string) => void;
|
||||
|
||||
export interface System {
|
||||
args: string[];
|
||||
newLine: string;
|
||||
@@ -8,27 +11,42 @@ module ts {
|
||||
write(s: string): void;
|
||||
readFile(path: string, encoding?: string): string;
|
||||
writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
|
||||
watchFile?(path: string, callback: (path: string) => void): FileWatcher;
|
||||
watchFile?(path: Path, callback: FileWatcherCallback): FileWatcher;
|
||||
watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
|
||||
resolvePath(path: string): string;
|
||||
fileExists(path: string): boolean;
|
||||
directoryExists(path: string): boolean;
|
||||
createDirectory(path: string): void;
|
||||
getExecutingFilePath(): string;
|
||||
getCurrentDirectory(): string;
|
||||
readDirectory(path: string, extension?: string): string[];
|
||||
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
|
||||
getMemoryUsage?(): number;
|
||||
exit(exitCode?: number): void;
|
||||
}
|
||||
|
||||
interface WatchedFile {
|
||||
filePath: Path;
|
||||
callback: FileWatcherCallback;
|
||||
mtime?: Date;
|
||||
}
|
||||
|
||||
export interface FileWatcher {
|
||||
close(): void;
|
||||
}
|
||||
|
||||
export interface DirectoryWatcher extends FileWatcher {
|
||||
directoryPath: Path;
|
||||
referenceCount: number;
|
||||
}
|
||||
|
||||
declare var require: any;
|
||||
declare var module: any;
|
||||
declare var process: any;
|
||||
declare var global: any;
|
||||
declare var __filename: string;
|
||||
declare var Buffer: {
|
||||
new (str: string, encoding?: string): any;
|
||||
};
|
||||
|
||||
declare class Enumerator {
|
||||
public atEnd(): boolean;
|
||||
@@ -37,20 +55,39 @@ module ts {
|
||||
constructor(o: any);
|
||||
}
|
||||
|
||||
declare var ChakraHost: {
|
||||
args: string[];
|
||||
currentDirectory: string;
|
||||
executingFile: string;
|
||||
newLine?: string;
|
||||
useCaseSensitiveFileNames?: boolean;
|
||||
echo(s: string): void;
|
||||
quit(exitCode?: number): void;
|
||||
fileExists(path: string): boolean;
|
||||
directoryExists(path: string): boolean;
|
||||
createDirectory(path: string): void;
|
||||
resolvePath(path: string): string;
|
||||
readFile(path: string): string;
|
||||
writeFile(path: string, contents: string): void;
|
||||
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
|
||||
watchFile?(path: string, callback: FileWatcherCallback): FileWatcher;
|
||||
watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
|
||||
};
|
||||
|
||||
export var sys: System = (function () {
|
||||
|
||||
function getWScriptSystem(): System {
|
||||
|
||||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
const fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
|
||||
var fileStream = new ActiveXObject("ADODB.Stream");
|
||||
const fileStream = new ActiveXObject("ADODB.Stream");
|
||||
fileStream.Type = 2 /*text*/;
|
||||
|
||||
var binaryStream = new ActiveXObject("ADODB.Stream");
|
||||
const binaryStream = new ActiveXObject("ADODB.Stream");
|
||||
binaryStream.Type = 1 /*binary*/;
|
||||
|
||||
var args: string[] = [];
|
||||
for (var i = 0; i < WScript.Arguments.length; i++) {
|
||||
const args: string[] = [];
|
||||
for (let i = 0; i < WScript.Arguments.length; i++) {
|
||||
args[i] = WScript.Arguments.Item(i);
|
||||
}
|
||||
|
||||
@@ -68,7 +105,7 @@ module ts {
|
||||
// Load file and read the first two bytes into a string with no interpretation
|
||||
fileStream.Charset = "x-ansi";
|
||||
fileStream.LoadFromFile(fileName);
|
||||
var bom = fileStream.ReadText(2) || "";
|
||||
const bom = fileStream.ReadText(2) || "";
|
||||
// Position must be at 0 before encoding can be changed
|
||||
fileStream.Position = 0;
|
||||
// [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8
|
||||
@@ -109,29 +146,38 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getCanonicalPath(path: string): string {
|
||||
return path.toLowerCase();
|
||||
}
|
||||
|
||||
function getNames(collection: any): string[] {
|
||||
var result: string[] = [];
|
||||
for (var e = new Enumerator(collection); !e.atEnd(); e.moveNext()) {
|
||||
const result: string[] = [];
|
||||
for (let e = new Enumerator(collection); !e.atEnd(); e.moveNext()) {
|
||||
result.push(e.item().Name);
|
||||
}
|
||||
return result.sort();
|
||||
}
|
||||
|
||||
function readDirectory(path: string, extension?: string): string[] {
|
||||
var result: string[] = [];
|
||||
function readDirectory(path: string, extension?: string, exclude?: string[]): string[] {
|
||||
const result: string[] = [];
|
||||
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
|
||||
visitDirectory(path);
|
||||
return result;
|
||||
function visitDirectory(path: string) {
|
||||
var folder = fso.GetFolder(path || ".");
|
||||
var files = getNames(folder.files);
|
||||
for (let name of files) {
|
||||
if (!extension || fileExtensionIs(name, extension)) {
|
||||
result.push(combinePaths(path, name));
|
||||
const folder = fso.GetFolder(path || ".");
|
||||
const files = getNames(folder.files);
|
||||
for (const current of files) {
|
||||
const name = combinePaths(path, current);
|
||||
if ((!extension || fileExtensionIs(name, extension)) && !contains(exclude, getCanonicalPath(name))) {
|
||||
result.push(name);
|
||||
}
|
||||
}
|
||||
var subfolders = getNames(folder.subfolders);
|
||||
for (let current of subfolders) {
|
||||
visitDirectory(combinePaths(path, current));
|
||||
const subfolders = getNames(folder.subfolders);
|
||||
for (const current of subfolders) {
|
||||
const name = combinePaths(path, current);
|
||||
if (!contains(exclude, getCanonicalPath(name))) {
|
||||
visitDirectory(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,27 +221,210 @@ module ts {
|
||||
}
|
||||
};
|
||||
}
|
||||
function getNodeSystem(): System {
|
||||
var _fs = require("fs");
|
||||
var _path = require("path");
|
||||
var _os = require('os');
|
||||
|
||||
var platform: string = _os.platform();
|
||||
function getNodeSystem(): System {
|
||||
const _fs = require("fs");
|
||||
const _path = require("path");
|
||||
const _os = require("os");
|
||||
|
||||
// average async stat takes about 30 microseconds
|
||||
// set chunk size to do 30 files in < 1 millisecond
|
||||
function createPollingWatchedFileSet(interval = 2500, chunkSize = 30) {
|
||||
let watchedFiles: WatchedFile[] = [];
|
||||
let nextFileToCheck = 0;
|
||||
let watchTimer: any;
|
||||
|
||||
function getModifiedTime(fileName: string): Date {
|
||||
return _fs.statSync(fileName).mtime;
|
||||
}
|
||||
|
||||
function poll(checkedIndex: number) {
|
||||
const watchedFile = watchedFiles[checkedIndex];
|
||||
if (!watchedFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
_fs.stat(watchedFile.filePath, (err: any, stats: any) => {
|
||||
if (err) {
|
||||
watchedFile.callback(watchedFile.filePath);
|
||||
}
|
||||
else if (watchedFile.mtime.getTime() !== stats.mtime.getTime()) {
|
||||
watchedFile.mtime = getModifiedTime(watchedFile.filePath);
|
||||
watchedFile.callback(watchedFile.filePath, watchedFile.mtime.getTime() === 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// this implementation uses polling and
|
||||
// stat due to inconsistencies of fs.watch
|
||||
// and efficiency of stat on modern filesystems
|
||||
function startWatchTimer() {
|
||||
watchTimer = setInterval(() => {
|
||||
let count = 0;
|
||||
let nextToCheck = nextFileToCheck;
|
||||
let firstCheck = -1;
|
||||
while ((count < chunkSize) && (nextToCheck !== firstCheck)) {
|
||||
poll(nextToCheck);
|
||||
if (firstCheck < 0) {
|
||||
firstCheck = nextToCheck;
|
||||
}
|
||||
nextToCheck++;
|
||||
if (nextToCheck === watchedFiles.length) {
|
||||
nextToCheck = 0;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
nextFileToCheck = nextToCheck;
|
||||
}, interval);
|
||||
}
|
||||
|
||||
function addFile(filePath: Path, callback: FileWatcherCallback): WatchedFile {
|
||||
const file: WatchedFile = {
|
||||
filePath,
|
||||
callback,
|
||||
mtime: getModifiedTime(filePath)
|
||||
};
|
||||
|
||||
watchedFiles.push(file);
|
||||
if (watchedFiles.length === 1) {
|
||||
startWatchTimer();
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
function removeFile(file: WatchedFile) {
|
||||
watchedFiles = copyListRemovingItem(file, watchedFiles);
|
||||
}
|
||||
|
||||
return {
|
||||
getModifiedTime: getModifiedTime,
|
||||
poll: poll,
|
||||
startWatchTimer: startWatchTimer,
|
||||
addFile: addFile,
|
||||
removeFile: removeFile
|
||||
};
|
||||
}
|
||||
|
||||
function createWatchedFileSet() {
|
||||
const dirWatchers = createFileMap<DirectoryWatcher>();
|
||||
// One file can have multiple watchers
|
||||
const fileWatcherCallbacks = createFileMap<FileWatcherCallback[]>();
|
||||
return { addFile, removeFile };
|
||||
|
||||
function reduceDirWatcherRefCountForFile(filePath: Path) {
|
||||
const dirPath = getDirectoryPath(filePath);
|
||||
if (dirWatchers.contains(dirPath)) {
|
||||
const watcher = dirWatchers.get(dirPath);
|
||||
watcher.referenceCount -= 1;
|
||||
if (watcher.referenceCount <= 0) {
|
||||
watcher.close();
|
||||
dirWatchers.remove(dirPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addDirWatcher(dirPath: Path): void {
|
||||
if (dirWatchers.contains(dirPath)) {
|
||||
const watcher = dirWatchers.get(dirPath);
|
||||
watcher.referenceCount += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
const watcher: DirectoryWatcher = _fs.watch(
|
||||
dirPath,
|
||||
{ persistent: true },
|
||||
(eventName: string, relativeFileName: string) => fileEventHandler(eventName, relativeFileName, dirPath)
|
||||
);
|
||||
watcher.referenceCount = 1;
|
||||
dirWatchers.set(dirPath, watcher);
|
||||
return;
|
||||
}
|
||||
|
||||
function addFileWatcherCallback(filePath: Path, callback: FileWatcherCallback): void {
|
||||
if (fileWatcherCallbacks.contains(filePath)) {
|
||||
fileWatcherCallbacks.get(filePath).push(callback);
|
||||
}
|
||||
else {
|
||||
fileWatcherCallbacks.set(filePath, [callback]);
|
||||
}
|
||||
}
|
||||
|
||||
function addFile(filePath: Path, callback: FileWatcherCallback): WatchedFile {
|
||||
addFileWatcherCallback(filePath, callback);
|
||||
addDirWatcher(getDirectoryPath(filePath));
|
||||
|
||||
return { filePath, callback };
|
||||
}
|
||||
|
||||
function removeFile(watchedFile: WatchedFile) {
|
||||
removeFileWatcherCallback(watchedFile.filePath, watchedFile.callback);
|
||||
reduceDirWatcherRefCountForFile(watchedFile.filePath);
|
||||
}
|
||||
|
||||
function removeFileWatcherCallback(filePath: Path, callback: FileWatcherCallback) {
|
||||
if (fileWatcherCallbacks.contains(filePath)) {
|
||||
const newCallbacks = copyListRemovingItem(callback, fileWatcherCallbacks.get(filePath));
|
||||
if (newCallbacks.length === 0) {
|
||||
fileWatcherCallbacks.remove(filePath);
|
||||
}
|
||||
else {
|
||||
fileWatcherCallbacks.set(filePath, newCallbacks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param watcherPath is the path from which the watcher is triggered.
|
||||
*/
|
||||
function fileEventHandler(eventName: string, relativeFileName: string, baseDirPath: Path) {
|
||||
// When files are deleted from disk, the triggered "rename" event would have a relativefileName of "undefined"
|
||||
const filePath = typeof relativeFileName !== "string"
|
||||
? undefined
|
||||
: toPath(relativeFileName, baseDirPath, createGetCanonicalFileName(sys.useCaseSensitiveFileNames));
|
||||
if (eventName === "change" && fileWatcherCallbacks.contains(filePath)) {
|
||||
for (const fileCallback of fileWatcherCallbacks.get(filePath)) {
|
||||
fileCallback(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// REVIEW: for now this implementation uses polling.
|
||||
// The advantage of polling is that it works reliably
|
||||
// on all os and with network mounted files.
|
||||
// For 90 referenced files, the average time to detect
|
||||
// changes is 2*msInterval (by default 5 seconds).
|
||||
// The overhead of this is .04 percent (1/2500) with
|
||||
// average pause of < 1 millisecond (and max
|
||||
// pause less than 1.5 milliseconds); question is
|
||||
// do we anticipate reference sets in the 100s and
|
||||
// do we care about waiting 10-20 seconds to detect
|
||||
// changes for large reference sets? If so, do we want
|
||||
// to increase the chunk size or decrease the interval
|
||||
// time dynamically to match the large reference set?
|
||||
const pollingWatchedFileSet = createPollingWatchedFileSet();
|
||||
const watchedFileSet = createWatchedFileSet();
|
||||
|
||||
function isNode4OrLater(): boolean {
|
||||
return parseInt(process.version.charAt(1)) >= 4;
|
||||
}
|
||||
|
||||
const platform: string = _os.platform();
|
||||
// win32\win64 are case insensitive platforms, MacOS (darwin) by default is also case insensitive
|
||||
var useCaseSensitiveFileNames = platform !== "win32" && platform !== "win64" && platform !== "darwin";
|
||||
const useCaseSensitiveFileNames = platform !== "win32" && platform !== "win64" && platform !== "darwin";
|
||||
|
||||
function readFile(fileName: string, encoding?: string): string {
|
||||
if (!_fs.existsSync(fileName)) {
|
||||
return undefined;
|
||||
}
|
||||
var buffer = _fs.readFileSync(fileName);
|
||||
var len = buffer.length;
|
||||
const buffer = _fs.readFileSync(fileName);
|
||||
let len = buffer.length;
|
||||
if (len >= 2 && buffer[0] === 0xFE && buffer[1] === 0xFF) {
|
||||
// Big endian UTF-16 byte order mark detected. Since big endian is not supported by node.js,
|
||||
// flip all byte pairs and treat as little endian.
|
||||
len &= ~1;
|
||||
for (var i = 0; i < len; i += 2) {
|
||||
var temp = buffer[i];
|
||||
for (let i = 0; i < len; i += 2) {
|
||||
const temp = buffer[i];
|
||||
buffer[i] = buffer[i + 1];
|
||||
buffer[i + 1] = temp;
|
||||
}
|
||||
@@ -216,32 +445,49 @@ module ts {
|
||||
function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void {
|
||||
// If a BOM is required, emit one
|
||||
if (writeByteOrderMark) {
|
||||
data = '\uFEFF' + data;
|
||||
data = "\uFEFF" + data;
|
||||
}
|
||||
|
||||
_fs.writeFileSync(fileName, data, "utf8");
|
||||
let fd: number;
|
||||
|
||||
try {
|
||||
fd = _fs.openSync(fileName, "w");
|
||||
_fs.writeSync(fd, data, undefined, "utf8");
|
||||
}
|
||||
finally {
|
||||
if (fd !== undefined) {
|
||||
_fs.closeSync(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function readDirectory(path: string, extension?: string): string[] {
|
||||
var result: string[] = [];
|
||||
function getCanonicalPath(path: string): string {
|
||||
return useCaseSensitiveFileNames ? path : path.toLowerCase();
|
||||
}
|
||||
|
||||
function readDirectory(path: string, extension?: string, exclude?: string[]): string[] {
|
||||
const result: string[] = [];
|
||||
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
|
||||
visitDirectory(path);
|
||||
return result;
|
||||
function visitDirectory(path: string) {
|
||||
var files = _fs.readdirSync(path || ".").sort();
|
||||
var directories: string[] = [];
|
||||
for (let current of files) {
|
||||
var name = combinePaths(path, current);
|
||||
var stat = _fs.lstatSync(name);
|
||||
if (stat.isFile()) {
|
||||
if (!extension || fileExtensionIs(name, extension)) {
|
||||
result.push(name);
|
||||
const files = _fs.readdirSync(path || ".").sort();
|
||||
const directories: string[] = [];
|
||||
for (const current of files) {
|
||||
const name = combinePaths(path, current);
|
||||
if (!contains(exclude, getCanonicalPath(name))) {
|
||||
const stat = _fs.statSync(name);
|
||||
if (stat.isFile()) {
|
||||
if (!extension || fileExtensionIs(name, extension)) {
|
||||
result.push(name);
|
||||
}
|
||||
}
|
||||
else if (stat.isDirectory()) {
|
||||
directories.push(name);
|
||||
}
|
||||
}
|
||||
else if (stat.isDirectory()) {
|
||||
directories.push(name);
|
||||
}
|
||||
}
|
||||
for (let current of directories) {
|
||||
for (const current of directories) {
|
||||
visitDirectory(current);
|
||||
}
|
||||
}
|
||||
@@ -252,26 +498,45 @@ module ts {
|
||||
newLine: _os.EOL,
|
||||
useCaseSensitiveFileNames: useCaseSensitiveFileNames,
|
||||
write(s: string): void {
|
||||
// 1 is a standard descriptor for stdout
|
||||
_fs.writeSync(1, s);
|
||||
process.stdout.write(s);
|
||||
},
|
||||
readFile,
|
||||
writeFile,
|
||||
watchFile: (fileName, callback) => {
|
||||
// watchFile polls a file every 250ms, picking up file notifications.
|
||||
_fs.watchFile(fileName, { persistent: true, interval: 250 }, fileChanged);
|
||||
|
||||
watchFile: (filePath, callback) => {
|
||||
// Node 4.0 stablized the `fs.watch` function on Windows which avoids polling
|
||||
// and is more efficient than `fs.watchFile` (ref: https://github.com/nodejs/node/pull/2649
|
||||
// and https://github.com/Microsoft/TypeScript/issues/4643), therefore
|
||||
// if the current node.js version is newer than 4, use `fs.watch` instead.
|
||||
const watchSet = isNode4OrLater() ? watchedFileSet : pollingWatchedFileSet;
|
||||
const watchedFile = watchSet.addFile(filePath, callback);
|
||||
return {
|
||||
close() { _fs.unwatchFile(fileName, fileChanged); }
|
||||
close: () => watchSet.removeFile(watchedFile)
|
||||
};
|
||||
},
|
||||
watchDirectory: (path, callback, recursive) => {
|
||||
// Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows
|
||||
// (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643)
|
||||
let options: any;
|
||||
if (isNode4OrLater() && (process.platform === "win32" || process.platform === "darwin")) {
|
||||
options = { persistent: true, recursive: !!recursive };
|
||||
}
|
||||
else {
|
||||
options = { persistent: true };
|
||||
}
|
||||
|
||||
function fileChanged(curr: any, prev: any) {
|
||||
if (+curr.mtime <= +prev.mtime) {
|
||||
return;
|
||||
return _fs.watch(
|
||||
path,
|
||||
options,
|
||||
(eventName: string, relativeFileName: string) => {
|
||||
// In watchDirectory we only care about adding and removing files (when event name is
|
||||
// "rename"); changes made within files are handled by corresponding fileWatchers (when
|
||||
// event name is "change")
|
||||
if (eventName === "rename") {
|
||||
// When deleting a file, the passed baseFileName is null
|
||||
callback(!relativeFileName ? relativeFileName : normalizePath(combinePaths(path, relativeFileName)));
|
||||
};
|
||||
}
|
||||
|
||||
callback(fileName);
|
||||
};
|
||||
);
|
||||
},
|
||||
resolvePath: function (path: string): string {
|
||||
return _path.resolve(path);
|
||||
@@ -305,14 +570,50 @@ module ts {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getChakraSystem(): System {
|
||||
|
||||
return {
|
||||
newLine: ChakraHost.newLine || "\r\n",
|
||||
args: ChakraHost.args,
|
||||
useCaseSensitiveFileNames: !!ChakraHost.useCaseSensitiveFileNames,
|
||||
write: ChakraHost.echo,
|
||||
readFile(path: string, encoding?: string) {
|
||||
// encoding is automatically handled by the implementation in ChakraHost
|
||||
return ChakraHost.readFile(path);
|
||||
},
|
||||
writeFile(path: string, data: string, writeByteOrderMark?: boolean) {
|
||||
// If a BOM is required, emit one
|
||||
if (writeByteOrderMark) {
|
||||
data = "\uFEFF" + data;
|
||||
}
|
||||
|
||||
ChakraHost.writeFile(path, data);
|
||||
},
|
||||
resolvePath: ChakraHost.resolvePath,
|
||||
fileExists: ChakraHost.fileExists,
|
||||
directoryExists: ChakraHost.directoryExists,
|
||||
createDirectory: ChakraHost.createDirectory,
|
||||
getExecutingFilePath: () => ChakraHost.executingFile,
|
||||
getCurrentDirectory: () => ChakraHost.currentDirectory,
|
||||
readDirectory: ChakraHost.readDirectory,
|
||||
exit: ChakraHost.quit,
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") {
|
||||
return getWScriptSystem();
|
||||
}
|
||||
else if (typeof module !== "undefined" && module.exports) {
|
||||
else if (typeof process !== "undefined" && process.nextTick && !process.browser && typeof require !== "undefined") {
|
||||
// process and process.nextTick checks if current environment is node-like
|
||||
// process.browser check excludes webpack and browserify
|
||||
return getNodeSystem();
|
||||
}
|
||||
else if (typeof ChakraHost !== "undefined") {
|
||||
return getChakraSystem();
|
||||
}
|
||||
else {
|
||||
return undefined; // Unsupported host
|
||||
}
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
+389
-99
@@ -1,9 +1,17 @@
|
||||
/// <reference path="program.ts"/>
|
||||
/// <reference path="commandLineParser.ts"/>
|
||||
|
||||
module ts {
|
||||
namespace ts {
|
||||
export interface SourceFile {
|
||||
fileWatcher: FileWatcher;
|
||||
fileWatcher?: FileWatcher;
|
||||
}
|
||||
|
||||
let reportDiagnostic = reportDiagnosticSimply;
|
||||
|
||||
function reportDiagnostics(diagnostics: Diagnostic[], host: CompilerHost): void {
|
||||
for (const diagnostic of diagnostics) {
|
||||
reportDiagnostic(diagnostic, host);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -11,15 +19,15 @@ module ts {
|
||||
* and if it is, attempts to set the appropriate language.
|
||||
*/
|
||||
function validateLocaleAndSetLanguage(locale: string, errors: Diagnostic[]): boolean {
|
||||
var matchResult = /^([a-z]+)([_\-]([a-z]+))?$/.exec(locale.toLowerCase());
|
||||
const matchResult = /^([a-z]+)([_\-]([a-z]+))?$/.exec(locale.toLowerCase());
|
||||
|
||||
if (!matchResult) {
|
||||
errors.push(createCompilerDiagnostic(Diagnostics.Locale_must_be_of_the_form_language_or_language_territory_For_example_0_or_1, 'en', 'ja-jp'));
|
||||
errors.push(createCompilerDiagnostic(Diagnostics.Locale_must_be_of_the_form_language_or_language_territory_For_example_0_or_1, "en", "ja-jp"));
|
||||
return false;
|
||||
}
|
||||
|
||||
var language = matchResult[1];
|
||||
var territory = matchResult[3];
|
||||
const language = matchResult[1];
|
||||
const territory = matchResult[3];
|
||||
|
||||
// First try the entire locale, then fall back to just language if that's all we have.
|
||||
if (!trySetLanguageAndTerritory(language, territory, errors) &&
|
||||
@@ -33,10 +41,10 @@ module ts {
|
||||
}
|
||||
|
||||
function trySetLanguageAndTerritory(language: string, territory: string, errors: Diagnostic[]): boolean {
|
||||
var compilerFilePath = normalizePath(sys.getExecutingFilePath());
|
||||
var containingDirectoryPath = getDirectoryPath(compilerFilePath);
|
||||
const compilerFilePath = normalizePath(sys.getExecutingFilePath());
|
||||
const containingDirectoryPath = getDirectoryPath(compilerFilePath);
|
||||
|
||||
var filePath = combinePaths(containingDirectoryPath, language);
|
||||
let filePath = combinePaths(containingDirectoryPath, language);
|
||||
|
||||
if (territory) {
|
||||
filePath = filePath + "-" + territory;
|
||||
@@ -49,8 +57,9 @@ module ts {
|
||||
}
|
||||
|
||||
// TODO: Add codePage support for readFile?
|
||||
let fileContents = "";
|
||||
try {
|
||||
var fileContents = sys.readFile(filePath);
|
||||
fileContents = sys.readFile(filePath);
|
||||
}
|
||||
catch (e) {
|
||||
errors.push(createCompilerDiagnostic(Diagnostics.Unable_to_open_file_0, filePath));
|
||||
@@ -68,7 +77,7 @@ module ts {
|
||||
}
|
||||
|
||||
function countLines(program: Program): number {
|
||||
var count = 0;
|
||||
let count = 0;
|
||||
forEach(program.getSourceFiles(), file => {
|
||||
count += getLineStarts(file).length;
|
||||
});
|
||||
@@ -76,29 +85,128 @@ module ts {
|
||||
}
|
||||
|
||||
function getDiagnosticText(message: DiagnosticMessage, ...args: any[]): string {
|
||||
var diagnostic = createCompilerDiagnostic.apply(undefined, arguments);
|
||||
const diagnostic = createCompilerDiagnostic.apply(undefined, arguments);
|
||||
return <string>diagnostic.messageText;
|
||||
}
|
||||
|
||||
function reportDiagnostic(diagnostic: Diagnostic) {
|
||||
var output = "";
|
||||
|
||||
if (diagnostic.file) {
|
||||
var loc = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
|
||||
function getRelativeFileName(fileName: string, host: CompilerHost): string {
|
||||
return host ? convertToRelativePath(fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName)) : fileName;
|
||||
}
|
||||
|
||||
output += `${ diagnostic.file.fileName }(${ loc.line + 1 },${ loc.character + 1 }): `;
|
||||
function reportDiagnosticSimply(diagnostic: Diagnostic, host: CompilerHost): void {
|
||||
let output = "";
|
||||
|
||||
if (diagnostic.file) {
|
||||
const { line, character } = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
|
||||
const relativeFileName = getRelativeFileName(diagnostic.file.fileName, host);
|
||||
output += `${ relativeFileName }(${ line + 1 },${ character + 1 }): `;
|
||||
}
|
||||
|
||||
var category = DiagnosticCategory[diagnostic.category].toLowerCase();
|
||||
const category = DiagnosticCategory[diagnostic.category].toLowerCase();
|
||||
output += `${ category } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) }${ sys.newLine }`;
|
||||
|
||||
sys.write(output);
|
||||
}
|
||||
|
||||
function reportDiagnostics(diagnostics: Diagnostic[]) {
|
||||
for (var i = 0; i < diagnostics.length; i++) {
|
||||
reportDiagnostic(diagnostics[i]);
|
||||
|
||||
const redForegroundEscapeSequence = "\u001b[91m";
|
||||
const yellowForegroundEscapeSequence = "\u001b[93m";
|
||||
const blueForegroundEscapeSequence = "\u001b[93m";
|
||||
const gutterStyleSequence = "\u001b[100;30m";
|
||||
const gutterSeparator = " ";
|
||||
const resetEscapeSequence = "\u001b[0m";
|
||||
const elipsis = "...";
|
||||
const categoryFormatMap: Map<string> = {
|
||||
[DiagnosticCategory.Warning]: yellowForegroundEscapeSequence,
|
||||
[DiagnosticCategory.Error]: redForegroundEscapeSequence,
|
||||
[DiagnosticCategory.Message]: blueForegroundEscapeSequence,
|
||||
};
|
||||
|
||||
function formatAndReset(text: string, formatStyle: string) {
|
||||
return formatStyle + text + resetEscapeSequence;
|
||||
}
|
||||
|
||||
function reportDiagnosticWithColorAndContext(diagnostic: Diagnostic, host: CompilerHost): void {
|
||||
let output = "";
|
||||
|
||||
if (diagnostic.file) {
|
||||
const { start, length, file } = diagnostic;
|
||||
const { line: firstLine, character: firstLineChar } = getLineAndCharacterOfPosition(file, start);
|
||||
const { line: lastLine, character: lastLineChar } = getLineAndCharacterOfPosition(file, start + length);
|
||||
const lastLineInFile = getLineAndCharacterOfPosition(file, file.text.length).line;
|
||||
const relativeFileName = getRelativeFileName(file.fileName, host);
|
||||
|
||||
const hasMoreThanFiveLines = (lastLine - firstLine) >= 4;
|
||||
let gutterWidth = (lastLine + 1 + "").length;
|
||||
if (hasMoreThanFiveLines) {
|
||||
gutterWidth = Math.max(elipsis.length, gutterWidth);
|
||||
}
|
||||
|
||||
output += sys.newLine;
|
||||
for (let i = firstLine; i <= lastLine; i++) {
|
||||
// If the error spans over 5 lines, we'll only show the first 2 and last 2 lines,
|
||||
// so we'll skip ahead to the second-to-last line.
|
||||
if (hasMoreThanFiveLines && firstLine + 1 < i && i < lastLine - 1) {
|
||||
output += formatAndReset(padLeft(elipsis, gutterWidth), gutterStyleSequence) + gutterSeparator + sys.newLine;
|
||||
i = lastLine - 1;
|
||||
}
|
||||
|
||||
const lineStart = getPositionOfLineAndCharacter(file, i, 0);
|
||||
const lineEnd = i < lastLineInFile ? getPositionOfLineAndCharacter(file, i + 1, 0) : file.text.length;
|
||||
let lineContent = file.text.slice(lineStart, lineEnd);
|
||||
lineContent = lineContent.replace(/\s+$/g, ""); // trim from end
|
||||
lineContent = lineContent.replace("\t", " "); // convert tabs to single spaces
|
||||
|
||||
// Output the gutter and the actual contents of the line.
|
||||
output += formatAndReset(padLeft(i + 1 + "", gutterWidth), gutterStyleSequence) + gutterSeparator;
|
||||
output += lineContent + sys.newLine;
|
||||
|
||||
// Output the gutter and the error span for the line using tildes.
|
||||
output += formatAndReset(padLeft("", gutterWidth), gutterStyleSequence) + gutterSeparator;
|
||||
output += redForegroundEscapeSequence;
|
||||
if (i === firstLine) {
|
||||
// If we're on the last line, then limit it to the last character of the last line.
|
||||
// Otherwise, we'll just squiggle the rest of the line, giving 'slice' no end position.
|
||||
const lastCharForLine = i === lastLine ? lastLineChar : undefined;
|
||||
|
||||
output += lineContent.slice(0, firstLineChar).replace(/\S/g, " ");
|
||||
output += lineContent.slice(firstLineChar, lastCharForLine).replace(/./g, "~");
|
||||
}
|
||||
else if (i === lastLine) {
|
||||
output += lineContent.slice(0, lastLineChar).replace(/./g, "~");
|
||||
}
|
||||
else {
|
||||
// Squiggle the entire line.
|
||||
output += lineContent.replace(/./g, "~");
|
||||
}
|
||||
output += resetEscapeSequence;
|
||||
|
||||
output += sys.newLine;
|
||||
}
|
||||
|
||||
output += sys.newLine;
|
||||
output += `${ relativeFileName }(${ firstLine + 1 },${ firstLineChar + 1 }): `;
|
||||
}
|
||||
|
||||
const categoryColor = categoryFormatMap[diagnostic.category];
|
||||
const category = DiagnosticCategory[diagnostic.category].toLowerCase();
|
||||
output += `${ formatAndReset(category, categoryColor) } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) }`;
|
||||
output += sys.newLine + sys.newLine;
|
||||
|
||||
sys.write(output);
|
||||
}
|
||||
|
||||
function reportWatchDiagnostic(diagnostic: Diagnostic) {
|
||||
let output = new Date().toLocaleTimeString() + " - ";
|
||||
|
||||
if (diagnostic.file) {
|
||||
const loc = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
|
||||
output += `${ diagnostic.file.fileName }(${ loc.line + 1 },${ loc.character + 1 }): `;
|
||||
}
|
||||
|
||||
output += `${ flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) }${ sys.newLine }`;
|
||||
|
||||
sys.write(output);
|
||||
}
|
||||
|
||||
function padLeft(s: string, length: number) {
|
||||
@@ -133,19 +241,27 @@ module ts {
|
||||
}
|
||||
|
||||
export function executeCommandLine(args: string[]): void {
|
||||
var commandLine = parseCommandLine(args);
|
||||
var configFileName: string; // Configuration file name (if any)
|
||||
var configFileWatcher: FileWatcher; // Configuration file watcher
|
||||
var cachedProgram: Program; // Program cached from last compilation
|
||||
var rootFileNames: string[]; // Root fileNames for compilation
|
||||
var compilerOptions: CompilerOptions; // Compiler options for compilation
|
||||
var compilerHost: CompilerHost; // Compiler host
|
||||
var hostGetSourceFile: typeof compilerHost.getSourceFile; // getSourceFile method from default host
|
||||
var timerHandle: number; // Handle for 0.25s wait timer
|
||||
const commandLine = parseCommandLine(args);
|
||||
let configFileName: string; // Configuration file name (if any)
|
||||
let cachedConfigFileText: string; // Cached configuration file text, used for reparsing (if any)
|
||||
let configFileWatcher: FileWatcher; // Configuration file watcher
|
||||
let directoryWatcher: FileWatcher; // Directory watcher to monitor source file addition/removal
|
||||
let cachedProgram: Program; // Program cached from last compilation
|
||||
let rootFileNames: string[]; // Root fileNames for compilation
|
||||
let compilerOptions: CompilerOptions; // Compiler options for compilation
|
||||
let compilerHost: CompilerHost; // Compiler host
|
||||
let hostGetSourceFile: typeof compilerHost.getSourceFile; // getSourceFile method from default host
|
||||
let timerHandleForRecompilation: number; // Handle for 0.25s wait timer to trigger recompilation
|
||||
let timerHandleForDirectoryChanges: number; // Handle for 0.25s wait timer to trigger directory change handler
|
||||
|
||||
// This map stores and reuses results of fileExists check that happen inside 'createProgram'
|
||||
// This allows to save time in module resolution heavy scenarios when existence of the same file might be checked multiple times.
|
||||
let cachedExistingFiles: Map<boolean>;
|
||||
let hostFileExists: typeof compilerHost.fileExists;
|
||||
|
||||
if (commandLine.options.locale) {
|
||||
if (!isJSONSupported()) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale"));
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale"), /* compilerHost */ undefined);
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
validateLocaleAndSetLanguage(commandLine.options.locale, commandLine.errors);
|
||||
@@ -154,12 +270,17 @@ module ts {
|
||||
// If there are any errors due to command line parsing and/or
|
||||
// setting up localization, report them and quit.
|
||||
if (commandLine.errors.length > 0) {
|
||||
reportDiagnostics(commandLine.errors);
|
||||
reportDiagnostics(commandLine.errors, compilerHost);
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
|
||||
if (commandLine.options.init) {
|
||||
writeConfigFile(commandLine.options, commandLine.fileNames);
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
if (commandLine.options.version) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Version_0, ts.version));
|
||||
printVersion();
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
@@ -171,18 +292,33 @@ module ts {
|
||||
|
||||
if (commandLine.options.project) {
|
||||
if (!isJSONSupported()) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--project"));
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--project"), /* compilerHost */ undefined);
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
configFileName = normalizePath(combinePaths(commandLine.options.project, "tsconfig.json"));
|
||||
if (commandLine.fileNames.length !== 0) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line));
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line), /* compilerHost */ undefined);
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
|
||||
const fileOrDirectory = normalizePath(commandLine.options.project);
|
||||
if (!fileOrDirectory /* current directory "." */ || sys.directoryExists(fileOrDirectory)) {
|
||||
configFileName = combinePaths(fileOrDirectory, "tsconfig.json");
|
||||
if (!sys.fileExists(configFileName)) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Cannot_find_a_tsconfig_json_file_at_the_specified_directory_Colon_0, commandLine.options.project), /* compilerHost */ undefined);
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
}
|
||||
else {
|
||||
configFileName = fileOrDirectory;
|
||||
if (!sys.fileExists(configFileName)) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_specified_path_does_not_exist_Colon_0, commandLine.options.project), /* compilerHost */ undefined);
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (commandLine.fileNames.length === 0 && isJSONSupported()) {
|
||||
var searchPath = normalizePath(sys.getCurrentDirectory());
|
||||
configFileName = findConfigFile(searchPath);
|
||||
const searchPath = normalizePath(sys.getCurrentDirectory());
|
||||
configFileName = findConfigFile(searchPath, sys.fileExists);
|
||||
}
|
||||
|
||||
if (commandLine.fileNames.length === 0 && !configFileName) {
|
||||
@@ -191,35 +327,72 @@ module ts {
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
if (commandLine.options.watch) {
|
||||
// Firefox has Object.prototype.watch
|
||||
if (commandLine.options.watch && commandLine.options.hasOwnProperty("watch")) {
|
||||
if (!sys.watchFile) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"));
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* compilerHost */ undefined);
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
if (configFileName) {
|
||||
configFileWatcher = sys.watchFile(configFileName, configFileChanged);
|
||||
const configFilePath = toPath(configFileName, sys.getCurrentDirectory(), createGetCanonicalFileName(sys.useCaseSensitiveFileNames));
|
||||
configFileWatcher = sys.watchFile(configFilePath, configFileChanged);
|
||||
}
|
||||
if (sys.watchDirectory && configFileName) {
|
||||
const directory = ts.getDirectoryPath(configFileName);
|
||||
directoryWatcher = sys.watchDirectory(
|
||||
// When the configFileName is just "tsconfig.json", the watched directory should be
|
||||
// the current direcotry; if there is a given "project" parameter, then the configFileName
|
||||
// is an absolute file name.
|
||||
directory == "" ? "." : directory,
|
||||
watchedDirectoryChanged, /*recursive*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
performCompilation();
|
||||
|
||||
function parseConfigFile(): ParsedCommandLine {
|
||||
if (!cachedConfigFileText) {
|
||||
try {
|
||||
cachedConfigFileText = sys.readFile(configFileName);
|
||||
}
|
||||
catch (e) {
|
||||
const error = createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, configFileName, e.message);
|
||||
reportWatchDiagnostic(error);
|
||||
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!cachedConfigFileText) {
|
||||
const error = createCompilerDiagnostic(Diagnostics.File_0_not_found, configFileName);
|
||||
reportDiagnostics([error], /* compilerHost */ undefined);
|
||||
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
return;
|
||||
}
|
||||
|
||||
const result = parseConfigFileTextToJson(configFileName, cachedConfigFileText);
|
||||
const configObject = result.config;
|
||||
if (!configObject) {
|
||||
reportDiagnostics([result.error], /* compilerHost */ undefined);
|
||||
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
return;
|
||||
}
|
||||
const configParseResult = parseJsonConfigFileContent(configObject, sys, getDirectoryPath(configFileName), commandLine.options);
|
||||
if (configParseResult.errors.length > 0) {
|
||||
reportDiagnostics(configParseResult.errors, /* compilerHost */ undefined);
|
||||
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
return;
|
||||
}
|
||||
return configParseResult;
|
||||
}
|
||||
|
||||
// Invoked to perform initial compilation or re-compilation in watch mode
|
||||
function performCompilation() {
|
||||
|
||||
if (!cachedProgram) {
|
||||
if (configFileName) {
|
||||
var configObject = readConfigFile(configFileName);
|
||||
if (!configObject) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Unable_to_open_file_0, configFileName));
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
var configParseResult = parseConfigFile(configObject, getDirectoryPath(configFileName));
|
||||
if (configParseResult.errors.length > 0) {
|
||||
reportDiagnostics(configParseResult.errors);
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
const configParseResult = parseConfigFile();
|
||||
rootFileNames = configParseResult.fileNames;
|
||||
compilerOptions = extend(commandLine.options, configParseResult.options);
|
||||
compilerOptions = configParseResult.options;
|
||||
}
|
||||
else {
|
||||
rootFileNames = commandLine.fileNames;
|
||||
@@ -228,32 +401,50 @@ module ts {
|
||||
compilerHost = createCompilerHost(compilerOptions);
|
||||
hostGetSourceFile = compilerHost.getSourceFile;
|
||||
compilerHost.getSourceFile = getSourceFile;
|
||||
|
||||
hostFileExists = compilerHost.fileExists;
|
||||
compilerHost.fileExists = cachedFileExists;
|
||||
}
|
||||
|
||||
var compileResult = compile(rootFileNames, compilerOptions, compilerHost);
|
||||
if (compilerOptions.pretty) {
|
||||
reportDiagnostic = reportDiagnosticWithColorAndContext;
|
||||
}
|
||||
|
||||
// reset the cache of existing files
|
||||
cachedExistingFiles = {};
|
||||
|
||||
const compileResult = compile(rootFileNames, compilerOptions, compilerHost);
|
||||
|
||||
if (!compilerOptions.watch) {
|
||||
return sys.exit(compileResult.exitStatus);
|
||||
}
|
||||
|
||||
setCachedProgram(compileResult.program);
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Compilation_complete_Watching_for_file_changes));
|
||||
reportWatchDiagnostic(createCompilerDiagnostic(Diagnostics.Compilation_complete_Watching_for_file_changes));
|
||||
}
|
||||
|
||||
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError ?: (message: string) => void) {
|
||||
function cachedFileExists(fileName: string): boolean {
|
||||
if (hasProperty(cachedExistingFiles, fileName)) {
|
||||
return cachedExistingFiles[fileName];
|
||||
}
|
||||
return cachedExistingFiles[fileName] = hostFileExists(fileName);
|
||||
}
|
||||
|
||||
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void) {
|
||||
// Return existing SourceFile object if one is available
|
||||
if (cachedProgram) {
|
||||
var sourceFile = cachedProgram.getSourceFile(fileName);
|
||||
const sourceFile = cachedProgram.getSourceFile(fileName);
|
||||
// A modified source file has no watcher and should not be reused
|
||||
if (sourceFile && sourceFile.fileWatcher) {
|
||||
return sourceFile;
|
||||
}
|
||||
}
|
||||
// Use default host function
|
||||
var sourceFile = hostGetSourceFile(fileName, languageVersion, onError);
|
||||
const sourceFile = hostGetSourceFile(fileName, languageVersion, onError);
|
||||
if (sourceFile && compilerOptions.watch) {
|
||||
// Attach a file watcher
|
||||
sourceFile.fileWatcher = sys.watchFile(sourceFile.fileName, () => sourceFileChanged(sourceFile));
|
||||
const filePath = toPath(sourceFile.fileName, sys.getCurrentDirectory(), createGetCanonicalFileName(sys.useCaseSensitiveFileNames));
|
||||
sourceFile.fileWatcher = sys.watchFile(filePath, (fileName: string, removed?: boolean) => sourceFileChanged(sourceFile, removed));
|
||||
}
|
||||
return sourceFile;
|
||||
}
|
||||
@@ -261,7 +452,7 @@ module ts {
|
||||
// Change cached program to the given program
|
||||
function setCachedProgram(program: Program) {
|
||||
if (cachedProgram) {
|
||||
var newSourceFiles = program ? program.getSourceFiles() : undefined;
|
||||
const newSourceFiles = program ? program.getSourceFiles() : undefined;
|
||||
forEach(cachedProgram.getSourceFiles(), sourceFile => {
|
||||
if (!(newSourceFiles && contains(newSourceFiles, sourceFile))) {
|
||||
if (sourceFile.fileWatcher) {
|
||||
@@ -275,31 +466,65 @@ module ts {
|
||||
}
|
||||
|
||||
// If a source file changes, mark it as unwatched and start the recompilation timer
|
||||
function sourceFileChanged(sourceFile: SourceFile) {
|
||||
function sourceFileChanged(sourceFile: SourceFile, removed?: boolean) {
|
||||
sourceFile.fileWatcher.close();
|
||||
sourceFile.fileWatcher = undefined;
|
||||
startTimer();
|
||||
if (removed) {
|
||||
const index = rootFileNames.indexOf(sourceFile.fileName);
|
||||
if (index >= 0) {
|
||||
rootFileNames.splice(index, 1);
|
||||
}
|
||||
}
|
||||
startTimerForRecompilation();
|
||||
}
|
||||
|
||||
// If the configuration file changes, forget cached program and start the recompilation timer
|
||||
function configFileChanged() {
|
||||
setCachedProgram(undefined);
|
||||
startTimer();
|
||||
cachedConfigFileText = undefined;
|
||||
startTimerForRecompilation();
|
||||
}
|
||||
|
||||
function watchedDirectoryChanged(fileName: string) {
|
||||
if (fileName && !ts.isSupportedSourceFileName(fileName, commandLine.options)) {
|
||||
return;
|
||||
}
|
||||
|
||||
startTimerForHandlingDirectoryChanges();
|
||||
}
|
||||
|
||||
function startTimerForHandlingDirectoryChanges() {
|
||||
if (timerHandleForDirectoryChanges) {
|
||||
clearTimeout(timerHandleForDirectoryChanges);
|
||||
}
|
||||
timerHandleForDirectoryChanges = setTimeout(directoryChangeHandler, 250);
|
||||
}
|
||||
|
||||
function directoryChangeHandler() {
|
||||
const parsedCommandLine = parseConfigFile();
|
||||
const newFileNames = ts.map(parsedCommandLine.fileNames, compilerHost.getCanonicalFileName);
|
||||
const canonicalRootFileNames = ts.map(rootFileNames, compilerHost.getCanonicalFileName);
|
||||
|
||||
// We check if the project file list has changed. If so, we just throw away the old program and start fresh.
|
||||
if (!arrayIsEqualTo(newFileNames && newFileNames.sort(), canonicalRootFileNames && canonicalRootFileNames.sort())) {
|
||||
setCachedProgram(undefined);
|
||||
startTimerForRecompilation();
|
||||
}
|
||||
}
|
||||
|
||||
// Upon detecting a file change, wait for 250ms and then perform a recompilation. This gives batch
|
||||
// operations (such as saving all modified files in an editor) a chance to complete before we kick
|
||||
// off a new compilation.
|
||||
function startTimer() {
|
||||
if (timerHandle) {
|
||||
clearTimeout(timerHandle);
|
||||
function startTimerForRecompilation() {
|
||||
if (timerHandleForRecompilation) {
|
||||
clearTimeout(timerHandleForRecompilation);
|
||||
}
|
||||
timerHandle = setTimeout(recompile, 250);
|
||||
timerHandleForRecompilation = setTimeout(recompile, 250);
|
||||
}
|
||||
|
||||
function recompile() {
|
||||
timerHandle = undefined;
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.File_change_detected_Starting_incremental_compilation));
|
||||
timerHandleForRecompilation = undefined;
|
||||
reportWatchDiagnostic(createCompilerDiagnostic(Diagnostics.File_change_detected_Starting_incremental_compilation));
|
||||
performCompilation();
|
||||
}
|
||||
}
|
||||
@@ -312,8 +537,8 @@ module ts {
|
||||
checkTime = 0;
|
||||
emitTime = 0;
|
||||
|
||||
var program = createProgram(fileNames, compilerOptions, compilerHost);
|
||||
var exitStatus = compileProgram();
|
||||
const program = createProgram(fileNames, compilerOptions, compilerHost);
|
||||
const exitStatus = compileProgram();
|
||||
|
||||
if (compilerOptions.listFiles) {
|
||||
forEach(program.getSourceFiles(), file => {
|
||||
@@ -322,7 +547,7 @@ module ts {
|
||||
}
|
||||
|
||||
if (compilerOptions.diagnostics) {
|
||||
var memoryUsed = sys.getMemoryUsage ? sys.getMemoryUsage() : -1;
|
||||
const memoryUsed = sys.getMemoryUsage ? sys.getMemoryUsage() : -1;
|
||||
reportCountStatistic("Files", program.getSourceFiles().length);
|
||||
reportCountStatistic("Lines", countLines(program));
|
||||
reportCountStatistic("Nodes", program.getNodeCount());
|
||||
@@ -350,22 +575,23 @@ module ts {
|
||||
return { program, exitStatus };
|
||||
|
||||
function compileProgram(): ExitStatus {
|
||||
// First get any syntactic errors.
|
||||
var diagnostics = program.getSyntacticDiagnostics();
|
||||
reportDiagnostics(diagnostics);
|
||||
let diagnostics: Diagnostic[];
|
||||
|
||||
// If we didn't have any syntactic errors, then also try getting the global and
|
||||
// First get and report any syntactic errors.
|
||||
diagnostics = program.getSyntacticDiagnostics();
|
||||
|
||||
// If we didn't have any syntactic errors, then also try getting the global and
|
||||
// semantic errors.
|
||||
if (diagnostics.length === 0) {
|
||||
var diagnostics = program.getGlobalDiagnostics();
|
||||
reportDiagnostics(diagnostics);
|
||||
diagnostics = program.getOptionsDiagnostics().concat(program.getGlobalDiagnostics());
|
||||
|
||||
if (diagnostics.length === 0) {
|
||||
var diagnostics = program.getSemanticDiagnostics();
|
||||
reportDiagnostics(diagnostics);
|
||||
diagnostics = program.getSemanticDiagnostics();
|
||||
}
|
||||
}
|
||||
|
||||
reportDiagnostics(diagnostics, compilerHost);
|
||||
|
||||
// If the user doesn't want us to emit, then we're done at this point.
|
||||
if (compilerOptions.noEmit) {
|
||||
return diagnostics.length
|
||||
@@ -374,8 +600,8 @@ module ts {
|
||||
}
|
||||
|
||||
// Otherwise, emit and report any errors we ran into.
|
||||
var emitOutput = program.emit();
|
||||
reportDiagnostics(emitOutput.diagnostics);
|
||||
const emitOutput = program.emit();
|
||||
reportDiagnostics(emitOutput.diagnostics, compilerHost);
|
||||
|
||||
// If the emitter didn't emit anything, then pass that value along.
|
||||
if (emitOutput.emitSkipped) {
|
||||
@@ -397,22 +623,22 @@ module ts {
|
||||
}
|
||||
|
||||
function printHelp() {
|
||||
var output = "";
|
||||
let output = "";
|
||||
|
||||
// We want to align our "syntax" and "examples" commands to a certain margin.
|
||||
var syntaxLength = getDiagnosticText(Diagnostics.Syntax_Colon_0, "").length;
|
||||
var examplesLength = getDiagnosticText(Diagnostics.Examples_Colon_0, "").length;
|
||||
var marginLength = Math.max(syntaxLength, examplesLength);
|
||||
const syntaxLength = getDiagnosticText(Diagnostics.Syntax_Colon_0, "").length;
|
||||
const examplesLength = getDiagnosticText(Diagnostics.Examples_Colon_0, "").length;
|
||||
let marginLength = Math.max(syntaxLength, examplesLength);
|
||||
|
||||
// Build up the syntactic skeleton.
|
||||
var syntax = makePadding(marginLength - syntaxLength);
|
||||
let syntax = makePadding(marginLength - syntaxLength);
|
||||
syntax += "tsc [" + getDiagnosticText(Diagnostics.options) + "] [" + getDiagnosticText(Diagnostics.file) + " ...]";
|
||||
|
||||
output += getDiagnosticText(Diagnostics.Syntax_Colon_0, syntax);
|
||||
output += sys.newLine + sys.newLine;
|
||||
|
||||
// Build up the list of examples.
|
||||
var padding = makePadding(marginLength);
|
||||
const padding = makePadding(marginLength);
|
||||
output += getDiagnosticText(Diagnostics.Examples_Colon_0, makePadding(marginLength - examplesLength) + "tsc hello.ts") + sys.newLine;
|
||||
output += padding + "tsc --out file.js file.ts" + sys.newLine;
|
||||
output += padding + "tsc @args.txt" + sys.newLine;
|
||||
@@ -421,17 +647,17 @@ module ts {
|
||||
output += getDiagnosticText(Diagnostics.Options_Colon) + sys.newLine;
|
||||
|
||||
// Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch")
|
||||
var optsList = filter(optionDeclarations.slice(), v => !v.experimental);
|
||||
const optsList = filter(optionDeclarations.slice(), v => !v.experimental);
|
||||
optsList.sort((a, b) => compareValues<string>(a.name.toLowerCase(), b.name.toLowerCase()));
|
||||
|
||||
// We want our descriptions to align at the same column in our output,
|
||||
// so we keep track of the longest option usage string.
|
||||
var marginLength = 0;
|
||||
var usageColumn: string[] = []; // Things like "-d, --declaration" go in here.
|
||||
var descriptionColumn: string[] = [];
|
||||
marginLength = 0;
|
||||
const usageColumn: string[] = []; // Things like "-d, --declaration" go in here.
|
||||
const descriptionColumn: string[] = [];
|
||||
|
||||
for (var i = 0; i < optsList.length; i++) {
|
||||
var option = optsList[i];
|
||||
for (let i = 0; i < optsList.length; i++) {
|
||||
const option = optsList[i];
|
||||
|
||||
// If an option lacks a description,
|
||||
// it is not officially supported.
|
||||
@@ -439,7 +665,7 @@ module ts {
|
||||
continue;
|
||||
}
|
||||
|
||||
var usageText = " ";
|
||||
let usageText = " ";
|
||||
if (option.shortName) {
|
||||
usageText += "-" + option.shortName;
|
||||
usageText += getParamType(option);
|
||||
@@ -457,15 +683,15 @@ module ts {
|
||||
}
|
||||
|
||||
// Special case that can't fit in the loop.
|
||||
var usageText = " @<" + getDiagnosticText(Diagnostics.file) + ">";
|
||||
const usageText = " @<" + getDiagnosticText(Diagnostics.file) + ">";
|
||||
usageColumn.push(usageText);
|
||||
descriptionColumn.push(getDiagnosticText(Diagnostics.Insert_command_line_options_and_files_from_a_file));
|
||||
marginLength = Math.max(usageText.length, marginLength);
|
||||
|
||||
// Print out each row, aligning all the descriptions on the same column.
|
||||
for (var i = 0; i < usageColumn.length; i++) {
|
||||
var usage = usageColumn[i];
|
||||
var description = descriptionColumn[i];
|
||||
for (let i = 0; i < usageColumn.length; i++) {
|
||||
const usage = usageColumn[i];
|
||||
const description = descriptionColumn[i];
|
||||
output += usage + makePadding(marginLength - usage.length + 2) + description + sys.newLine;
|
||||
}
|
||||
|
||||
@@ -483,6 +709,70 @@ module ts {
|
||||
return Array(paddingLength + 1).join(" ");
|
||||
}
|
||||
}
|
||||
|
||||
function writeConfigFile(options: CompilerOptions, fileNames: string[]) {
|
||||
const currentDirectory = sys.getCurrentDirectory();
|
||||
const file = normalizePath(combinePaths(currentDirectory, "tsconfig.json"));
|
||||
if (sys.fileExists(file)) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), /* compilerHost */ undefined);
|
||||
}
|
||||
else {
|
||||
const compilerOptions = extend(options, defaultInitCompilerOptions);
|
||||
const configurations: any = {
|
||||
compilerOptions: serializeCompilerOptions(compilerOptions),
|
||||
exclude: ["node_modules"]
|
||||
};
|
||||
|
||||
if (fileNames && fileNames.length) {
|
||||
// only set the files property if we have at least one file
|
||||
configurations.files = fileNames;
|
||||
}
|
||||
|
||||
sys.writeFile(file, JSON.stringify(configurations, undefined, 4));
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file), /* compilerHost */ undefined);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
function serializeCompilerOptions(options: CompilerOptions): Map<string | number | boolean> {
|
||||
const result: Map<string | number | boolean> = {};
|
||||
const optionsNameMap = getOptionNameMap().optionNameMap;
|
||||
|
||||
for (const name in options) {
|
||||
if (hasProperty(options, name)) {
|
||||
const value = options[name];
|
||||
switch (name) {
|
||||
case "init":
|
||||
case "watch":
|
||||
case "version":
|
||||
case "help":
|
||||
case "project":
|
||||
break;
|
||||
default:
|
||||
let optionDefinition = optionsNameMap[name.toLowerCase()];
|
||||
if (optionDefinition) {
|
||||
if (typeof optionDefinition.type === "string") {
|
||||
// string, number or boolean
|
||||
result[name] = value;
|
||||
}
|
||||
else {
|
||||
// Enum
|
||||
const typeMap = <Map<number>>optionDefinition.type;
|
||||
for (const key in typeMap) {
|
||||
if (hasProperty(typeMap, key)) {
|
||||
if (typeMap[key] === value)
|
||||
result[name] = key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ts.executeCommandLine(ts.sys.args);
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"core.ts",
|
||||
"sys.ts",
|
||||
"types.ts",
|
||||
"diagnosticInformationMap.generated.ts",
|
||||
"scanner.ts",
|
||||
"parser.ts",
|
||||
"utilities.ts",
|
||||
@@ -19,7 +20,6 @@
|
||||
"emitter.ts",
|
||||
"program.ts",
|
||||
"commandLineParser.ts",
|
||||
"tsc.ts",
|
||||
"diagnosticInformationMap.generated.ts"
|
||||
"tsc.ts"
|
||||
]
|
||||
}
|
||||
|
||||
+1056
-214
File diff suppressed because it is too large
Load Diff
+1248
-376
File diff suppressed because it is too large
Load Diff
+149
-179
@@ -1,7 +1,7 @@
|
||||
/// <reference path='harness.ts' />
|
||||
/// <reference path='runnerbase.ts' />
|
||||
/// <reference path='typeWriter.ts' />
|
||||
/// <reference path='syntacticCleaner.ts' />
|
||||
/// <reference path="harness.ts" />
|
||||
/// <reference path="runnerbase.ts" />
|
||||
/// <reference path="typeWriter.ts" />
|
||||
/* tslint:disable:no-null */
|
||||
|
||||
const enum CompilerTestType {
|
||||
Conformance,
|
||||
@@ -10,7 +10,8 @@ const enum CompilerTestType {
|
||||
}
|
||||
|
||||
class CompilerBaselineRunner extends RunnerBase {
|
||||
private basePath = 'tests/cases';
|
||||
private basePath = "tests/cases";
|
||||
private testSuiteName: string;
|
||||
private errors: boolean;
|
||||
private emit: boolean;
|
||||
private decl: boolean;
|
||||
@@ -18,139 +19,107 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
|
||||
public options: string;
|
||||
|
||||
constructor(public testType?: CompilerTestType) {
|
||||
constructor(public testType: CompilerTestType) {
|
||||
super();
|
||||
this.errors = true;
|
||||
this.emit = true;
|
||||
this.decl = true;
|
||||
this.output = true;
|
||||
if (testType === CompilerTestType.Conformance) {
|
||||
this.basePath += '/conformance';
|
||||
this.testSuiteName = "conformance";
|
||||
}
|
||||
else if (testType === CompilerTestType.Regressions) {
|
||||
this.basePath += '/compiler';
|
||||
this.testSuiteName = "compiler";
|
||||
}
|
||||
else if (testType === CompilerTestType.Test262) {
|
||||
this.basePath += '/test262';
|
||||
} else {
|
||||
this.basePath += '/compiler'; // default to this for historical reasons
|
||||
this.testSuiteName = "test262";
|
||||
}
|
||||
else {
|
||||
this.testSuiteName = "compiler"; // default to this for historical reasons
|
||||
}
|
||||
this.basePath += "/" + this.testSuiteName;
|
||||
}
|
||||
|
||||
private makeUnitName(name: string, root: string) {
|
||||
return ts.isRootedDiskPath(name) ? name : ts.combinePaths(root, name);
|
||||
};
|
||||
|
||||
public checkTestCodeOutput(fileName: string) {
|
||||
describe('compiler tests for ' + fileName, () => {
|
||||
describe("compiler tests for " + fileName, () => {
|
||||
// Mocha holds onto the closure environment of the describe callback even after the test is done.
|
||||
// Everything declared here should be cleared out in the "after" callback.
|
||||
var justName: string;
|
||||
var content: string;
|
||||
var testCaseContent: { settings: Harness.TestCaseParser.CompilerSetting[]; testUnitData: Harness.TestCaseParser.TestUnitData[]; }
|
||||
let justName: string;
|
||||
|
||||
var units: Harness.TestCaseParser.TestUnitData[];
|
||||
var tcSettings: Harness.TestCaseParser.CompilerSetting[];
|
||||
var createNewInstance: boolean;
|
||||
let lastUnit: Harness.TestCaseParser.TestUnitData;
|
||||
let harnessSettings: Harness.TestCaseParser.CompilerSettings;
|
||||
let hasNonDtsFiles: boolean;
|
||||
|
||||
var lastUnit: Harness.TestCaseParser.TestUnitData;
|
||||
var rootDir: string;
|
||||
|
||||
var result: Harness.Compiler.CompilerResult;
|
||||
var program: ts.Program;
|
||||
var options: ts.CompilerOptions;
|
||||
let result: Harness.Compiler.CompilerResult;
|
||||
let options: ts.CompilerOptions;
|
||||
// equivalent to the files that will be passed on the command line
|
||||
var toBeCompiled: { unitName: string; content: string }[];
|
||||
let toBeCompiled: Harness.Compiler.TestFile[];
|
||||
// equivalent to other files on the file system not directly passed to the compiler (ie things that are referenced by other files)
|
||||
var otherFiles: { unitName: string; content: string }[];
|
||||
var harnessCompiler: Harness.Compiler.HarnessCompiler;
|
||||
|
||||
var createNewInstance = false;
|
||||
let otherFiles: Harness.Compiler.TestFile[];
|
||||
|
||||
before(() => {
|
||||
justName = fileName.replace(/^.*[\\\/]/, ''); // strips the fileName from the path.
|
||||
content = Harness.IO.readFile(fileName);
|
||||
testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, fileName);
|
||||
units = testCaseContent.testUnitData;
|
||||
tcSettings = testCaseContent.settings;
|
||||
createNewInstance = false;
|
||||
justName = fileName.replace(/^.*[\\\/]/, ""); // strips the fileName from the path.
|
||||
const content = Harness.IO.readFile(fileName);
|
||||
const testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, fileName);
|
||||
const units = testCaseContent.testUnitData;
|
||||
harnessSettings = testCaseContent.settings;
|
||||
lastUnit = units[units.length - 1];
|
||||
rootDir = lastUnit.originalFilePath.indexOf('conformance') === -1 ? 'tests/cases/compiler/' : lastUnit.originalFilePath.substring(0, lastUnit.originalFilePath.lastIndexOf('/')) + '/';
|
||||
harnessCompiler = Harness.Compiler.getCompiler();
|
||||
hasNonDtsFiles = ts.forEach(units, unit => !ts.fileExtensionIs(unit.name, ".d.ts"));
|
||||
const rootDir = lastUnit.originalFilePath.indexOf("conformance") === -1 ? "tests/cases/compiler/" : lastUnit.originalFilePath.substring(0, lastUnit.originalFilePath.lastIndexOf("/")) + "/";
|
||||
// We need to assemble the list of input files for the compiler and other related files on the 'filesystem' (ie in a multi-file test)
|
||||
// If the last file in a test uses require or a triple slash reference we'll assume all other files will be brought in via references,
|
||||
// otherwise, assume all files are just meant to be in the same compilation session without explicit references to one another.
|
||||
toBeCompiled = [];
|
||||
otherFiles = [];
|
||||
if (/require\(/.test(lastUnit.content) || /reference\spath/.test(lastUnit.content)) {
|
||||
toBeCompiled.push({ unitName: rootDir + lastUnit.name, content: lastUnit.content });
|
||||
toBeCompiled.push({ unitName: this.makeUnitName(lastUnit.name, rootDir), content: lastUnit.content });
|
||||
units.forEach(unit => {
|
||||
if (unit.name !== lastUnit.name) {
|
||||
otherFiles.push({ unitName: rootDir + unit.name, content: unit.content });
|
||||
otherFiles.push({ unitName: this.makeUnitName(unit.name, rootDir), content: unit.content });
|
||||
}
|
||||
});
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
toBeCompiled = units.map(unit => {
|
||||
return { unitName: rootDir + unit.name, content: unit.content };
|
||||
return { unitName: this.makeUnitName(unit.name, rootDir), content: unit.content };
|
||||
});
|
||||
}
|
||||
|
||||
options = harnessCompiler.compileFiles(toBeCompiled, otherFiles, function (compileResult, _program) {
|
||||
result = compileResult;
|
||||
// The program will be used by typeWriter
|
||||
program = _program;
|
||||
}, function (settings) {
|
||||
harnessCompiler.setCompilerSettings(tcSettings);
|
||||
});
|
||||
});
|
||||
const output = Harness.Compiler.compileFiles(
|
||||
toBeCompiled, otherFiles, harnessSettings, /* options */ undefined, /* currentDirectory */ undefined);
|
||||
|
||||
beforeEach(() => {
|
||||
/* The compiler doesn't handle certain flags flipping during a single compilation setting. Tests on these flags will need
|
||||
a fresh compiler instance for themselves and then create a fresh one for the next test. Would be nice to get dev fixes
|
||||
eventually to remove this limitation. */
|
||||
for (var i = 0; i < tcSettings.length; ++i) {
|
||||
// noImplicitAny is passed to getCompiler, but target is just passed in the settings blob to setCompilerSettings
|
||||
if (!createNewInstance && (tcSettings[i].flag == "noimplicitany" || tcSettings[i].flag === 'target')) {
|
||||
harnessCompiler = Harness.Compiler.getCompiler();
|
||||
harnessCompiler.setCompilerSettings(tcSettings);
|
||||
createNewInstance = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (createNewInstance) {
|
||||
harnessCompiler = Harness.Compiler.getCompiler();
|
||||
createNewInstance = false;
|
||||
}
|
||||
options = output.options;
|
||||
result = output.result;
|
||||
});
|
||||
|
||||
after(() => {
|
||||
// Mocha holds onto the closure environment of the describe callback even after the test is done.
|
||||
// Therefore we have to clean out large objects after the test is done.
|
||||
justName = undefined;
|
||||
content = undefined;
|
||||
testCaseContent = undefined;
|
||||
units = undefined;
|
||||
tcSettings = undefined;
|
||||
lastUnit = undefined;
|
||||
rootDir = undefined;
|
||||
hasNonDtsFiles = undefined;
|
||||
result = undefined;
|
||||
program = undefined;
|
||||
options = undefined;
|
||||
toBeCompiled = undefined;
|
||||
otherFiles = undefined;
|
||||
harnessCompiler = undefined;
|
||||
});
|
||||
|
||||
function getByteOrderMarkText(file: Harness.Compiler.GeneratedFile): string {
|
||||
return file.writeByteOrderMark ? "\u00EF\u00BB\u00BF" : "";
|
||||
}
|
||||
|
||||
function getErrorBaseline(toBeCompiled: { unitName: string; content: string }[], otherFiles: { unitName: string; content: string }[], result: Harness.Compiler.CompilerResult) {
|
||||
function getErrorBaseline(toBeCompiled: Harness.Compiler.TestFile[], otherFiles: Harness.Compiler.TestFile[], result: Harness.Compiler.CompilerResult) {
|
||||
return Harness.Compiler.getErrorBaseline(toBeCompiled.concat(otherFiles), result.errors);
|
||||
}
|
||||
|
||||
// check errors
|
||||
it('Correct errors for ' + fileName, () => {
|
||||
it("Correct errors for " + fileName, () => {
|
||||
if (this.errors) {
|
||||
Harness.Baseline.runBaseline('Correct errors for ' + fileName, justName.replace(/\.ts$/, '.errors.txt'), (): string => {
|
||||
Harness.Baseline.runBaseline("Correct errors for " + fileName, justName.replace(/\.tsx?$/, ".errors.txt"), (): string => {
|
||||
if (result.errors.length === 0) return null;
|
||||
return getErrorBaseline(toBeCompiled, otherFiles, result);
|
||||
});
|
||||
@@ -158,12 +127,12 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
});
|
||||
|
||||
// Source maps?
|
||||
it('Correct sourcemap content for ' + fileName, () => {
|
||||
if (options.sourceMap) {
|
||||
Harness.Baseline.runBaseline('Correct sourcemap content for ' + fileName, justName.replace(/\.ts$/, '.sourcemap.txt'), () => {
|
||||
var record = result.getSourceMapRecord();
|
||||
it("Correct sourcemap content for " + fileName, () => {
|
||||
if (options.sourceMap || options.inlineSourceMap) {
|
||||
Harness.Baseline.runBaseline("Correct sourcemap content for " + fileName, justName.replace(/\.tsx?$/, ".sourcemap.txt"), () => {
|
||||
const record = result.getSourceMapRecord();
|
||||
if (options.noEmitOnError && result.errors.length !== 0 && record === undefined) {
|
||||
// Because of the noEmitOnError option no files are created. We need to return null because baselining isn't required.
|
||||
// Because of the noEmitOnError option no files are created. We need to return null because baselining isn"t required.
|
||||
return null;
|
||||
}
|
||||
return record;
|
||||
@@ -171,78 +140,82 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
it('Correct JS output for ' + fileName, () => {
|
||||
if (!ts.fileExtensionIs(lastUnit.name, '.d.ts') && this.emit) {
|
||||
if (result.files.length === 0 && result.errors.length === 0) {
|
||||
throw new Error('Expected at least one js file to be emitted or at least one error to be created.');
|
||||
it("Correct JS output for " + fileName, () => {
|
||||
if (hasNonDtsFiles && this.emit) {
|
||||
if (!options.noEmit && result.files.length === 0 && result.errors.length === 0) {
|
||||
throw new Error("Expected at least one js file to be emitted or at least one error to be created.");
|
||||
}
|
||||
|
||||
// check js output
|
||||
Harness.Baseline.runBaseline('Correct JS output for ' + fileName, justName.replace(/\.ts/, '.js'), () => {
|
||||
var tsCode = '';
|
||||
var tsSources = otherFiles.concat(toBeCompiled);
|
||||
Harness.Baseline.runBaseline("Correct JS output for " + fileName, justName.replace(/\.tsx?/, ".js"), () => {
|
||||
let tsCode = "";
|
||||
const tsSources = otherFiles.concat(toBeCompiled);
|
||||
if (tsSources.length > 1) {
|
||||
tsCode += '//// [' + fileName + '] ////\r\n\r\n';
|
||||
tsCode += "//// [" + fileName + "] ////\r\n\r\n";
|
||||
}
|
||||
for (var i = 0; i < tsSources.length; i++) {
|
||||
tsCode += '//// [' + Harness.Path.getFileName(tsSources[i].unitName) + ']\r\n';
|
||||
tsCode += tsSources[i].content + (i < (tsSources.length - 1) ? '\r\n' : '');
|
||||
for (let i = 0; i < tsSources.length; i++) {
|
||||
tsCode += "//// [" + Harness.Path.getFileName(tsSources[i].unitName) + "]\r\n";
|
||||
tsCode += tsSources[i].content + (i < (tsSources.length - 1) ? "\r\n" : "");
|
||||
}
|
||||
|
||||
var jsCode = '';
|
||||
for (var i = 0; i < result.files.length; i++) {
|
||||
jsCode += '//// [' + Harness.Path.getFileName(result.files[i].fileName) + ']\r\n';
|
||||
let jsCode = "";
|
||||
for (let i = 0; i < result.files.length; i++) {
|
||||
jsCode += "//// [" + Harness.Path.getFileName(result.files[i].fileName) + "]\r\n";
|
||||
jsCode += getByteOrderMarkText(result.files[i]);
|
||||
jsCode += result.files[i].code;
|
||||
// Re-enable this if we want to do another comparison of old vs new compiler baselines
|
||||
// jsCode += SyntacticCleaner.clean(result.files[i].code);
|
||||
}
|
||||
|
||||
if (result.declFilesCode.length > 0) {
|
||||
jsCode += '\r\n\r\n';
|
||||
for (var i = 0; i < result.declFilesCode.length; i++) {
|
||||
jsCode += '//// [' + Harness.Path.getFileName(result.declFilesCode[i].fileName) + ']\r\n';
|
||||
jsCode += "\r\n\r\n";
|
||||
for (let i = 0; i < result.declFilesCode.length; i++) {
|
||||
jsCode += "//// [" + Harness.Path.getFileName(result.declFilesCode[i].fileName) + "]\r\n";
|
||||
jsCode += getByteOrderMarkText(result.declFilesCode[i]);
|
||||
jsCode += result.declFilesCode[i].code;
|
||||
}
|
||||
}
|
||||
|
||||
var declFileCompilationResult = harnessCompiler.compileDeclarationFiles(toBeCompiled, otherFiles, result, function (settings) {
|
||||
harnessCompiler.setCompilerSettings(tcSettings);
|
||||
}, options);
|
||||
const declFileCompilationResult =
|
||||
Harness.Compiler.compileDeclarationFiles(
|
||||
toBeCompiled, otherFiles, result, harnessSettings, options, /*currentDirectory*/ undefined);
|
||||
|
||||
if (declFileCompilationResult && declFileCompilationResult.declResult.errors.length) {
|
||||
jsCode += '\r\n\r\n//// [DtsFileErrors]\r\n';
|
||||
jsCode += '\r\n\r\n';
|
||||
jsCode += "\r\n\r\n//// [DtsFileErrors]\r\n";
|
||||
jsCode += "\r\n\r\n";
|
||||
jsCode += getErrorBaseline(declFileCompilationResult.declInputFiles, declFileCompilationResult.declOtherFiles, declFileCompilationResult.declResult);
|
||||
}
|
||||
|
||||
if (jsCode.length > 0) {
|
||||
return tsCode + '\r\n\r\n' + jsCode;
|
||||
} else {
|
||||
return tsCode + "\r\n\r\n" + jsCode;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it('Correct Sourcemap output for ' + fileName, () => {
|
||||
if (options.sourceMap) {
|
||||
it("Correct Sourcemap output for " + fileName, () => {
|
||||
if (options.inlineSourceMap) {
|
||||
if (result.sourceMaps.length > 0) {
|
||||
throw new Error("No sourcemap files should be generated if inlineSourceMaps was set.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else if (options.sourceMap) {
|
||||
if (result.sourceMaps.length !== result.files.length) {
|
||||
throw new Error('Number of sourcemap files should be same as js files.');
|
||||
throw new Error("Number of sourcemap files should be same as js files.");
|
||||
}
|
||||
|
||||
Harness.Baseline.runBaseline('Correct Sourcemap output for ' + fileName, justName.replace(/\.ts/, '.js.map'), () => {
|
||||
Harness.Baseline.runBaseline("Correct Sourcemap output for " + fileName, justName.replace(/\.tsx?/, ".js.map"), () => {
|
||||
if (options.noEmitOnError && result.errors.length !== 0 && result.sourceMaps.length === 0) {
|
||||
// We need to return null here or the runBaseLine will actually create a empty file.
|
||||
// Baselining isn't required here because there is no output.
|
||||
return null;
|
||||
}
|
||||
|
||||
var sourceMapCode = '';
|
||||
for (var i = 0; i < result.sourceMaps.length; i++) {
|
||||
sourceMapCode += '//// [' + Harness.Path.getFileName(result.sourceMaps[i].fileName) + ']\r\n';
|
||||
let sourceMapCode = "";
|
||||
for (let i = 0; i < result.sourceMaps.length; i++) {
|
||||
sourceMapCode += "//// [" + Harness.Path.getFileName(result.sourceMaps[i].fileName) + "]\r\n";
|
||||
sourceMapCode += getByteOrderMarkText(result.sourceMaps[i]);
|
||||
sourceMapCode += result.sourceMaps[i].code;
|
||||
}
|
||||
@@ -252,53 +225,53 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
}
|
||||
});
|
||||
|
||||
it('Correct type/symbol baselines for ' + fileName, () => {
|
||||
it("Correct type/symbol baselines for " + fileName, () => {
|
||||
if (fileName.indexOf("APISample") >= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// NEWTODO: Type baselines
|
||||
if (result.errors.length === 0) {
|
||||
// The full walker simulates the types that you would get from doing a full
|
||||
// The full walker simulates the types that you would get from doing a full
|
||||
// compile. The pull walker simulates the types you get when you just do
|
||||
// a type query for a random node (like how the LS would do it). Most of the
|
||||
// time, these will be the same. However, occasionally, they can be different.
|
||||
// Specifically, when the compiler internally depends on symbol IDs to order
|
||||
// things, then we may see different results because symbols can be created in a
|
||||
// things, then we may see different results because symbols can be created in a
|
||||
// different order with 'pull' operations, and thus can produce slightly differing
|
||||
// output.
|
||||
//
|
||||
// For example, with a full type check, we may see a type outputed as: number | string
|
||||
// But with a pull type check, we may see it as: string | number
|
||||
//
|
||||
// These types are equivalent, but depend on what order the compiler observed
|
||||
// These types are equivalent, but depend on what order the compiler observed
|
||||
// certain parts of the program.
|
||||
|
||||
let allFiles = toBeCompiled.concat(otherFiles).filter(file => !!program.getSourceFile(file.unitName));
|
||||
const program = result.program;
|
||||
const allFiles = toBeCompiled.concat(otherFiles).filter(file => !!program.getSourceFile(file.unitName));
|
||||
|
||||
let fullWalker = new TypeWriterWalker(program, /*fullTypeCheck:*/ true);
|
||||
let pullWalker = new TypeWriterWalker(program, /*fullTypeCheck:*/ false);
|
||||
const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ true);
|
||||
|
||||
let fullResults: ts.Map<TypeWriterResult[]> = {};
|
||||
let pullResults: ts.Map<TypeWriterResult[]> = {};
|
||||
const fullResults: ts.Map<TypeWriterResult[]> = {};
|
||||
const pullResults: ts.Map<TypeWriterResult[]> = {};
|
||||
|
||||
for (let sourceFile of allFiles) {
|
||||
for (const sourceFile of allFiles) {
|
||||
fullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName);
|
||||
pullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName);
|
||||
}
|
||||
|
||||
// Produce baselines. The first gives the types for all expressions.
|
||||
// The second gives symbols for all identifiers.
|
||||
var e1: Error, e2: Error;
|
||||
let e1: Error, e2: Error;
|
||||
try {
|
||||
checkBaseLines(/*isSymbolBaseLine:*/ false);
|
||||
checkBaseLines(/*isSymbolBaseLine*/ false);
|
||||
}
|
||||
catch (e) {
|
||||
e1 = e;
|
||||
}
|
||||
|
||||
try {
|
||||
checkBaseLines(/*isSymbolBaseLine:*/ true);
|
||||
checkBaseLines(/*isSymbolBaseLine*/ true);
|
||||
}
|
||||
catch (e) {
|
||||
e2 = e;
|
||||
@@ -311,70 +284,70 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
return;
|
||||
|
||||
function checkBaseLines(isSymbolBaseLine: boolean) {
|
||||
let fullBaseLine = generateBaseLine(fullResults, isSymbolBaseLine);
|
||||
let pullBaseLine = generateBaseLine(pullResults, isSymbolBaseLine);
|
||||
const fullBaseLine = generateBaseLine(fullResults, isSymbolBaseLine);
|
||||
const pullBaseLine = generateBaseLine(pullResults, isSymbolBaseLine);
|
||||
|
||||
let fullExtension = isSymbolBaseLine ? '.symbols' : '.types';
|
||||
let pullExtension = isSymbolBaseLine ? '.symbols.pull' : '.types.pull';
|
||||
const fullExtension = isSymbolBaseLine ? ".symbols" : ".types";
|
||||
const pullExtension = isSymbolBaseLine ? ".symbols.pull" : ".types.pull";
|
||||
|
||||
if (fullBaseLine !== pullBaseLine) {
|
||||
Harness.Baseline.runBaseline('Correct full information for ' + fileName, justName.replace(/\.ts/, fullExtension), () => fullBaseLine);
|
||||
Harness.Baseline.runBaseline('Correct pull information for ' + fileName, justName.replace(/\.ts/, pullExtension), () => pullBaseLine);
|
||||
Harness.Baseline.runBaseline("Correct full information for " + fileName, justName.replace(/\.tsx?/, fullExtension), () => fullBaseLine);
|
||||
Harness.Baseline.runBaseline("Correct pull information for " + fileName, justName.replace(/\.tsx?/, pullExtension), () => pullBaseLine);
|
||||
}
|
||||
else {
|
||||
Harness.Baseline.runBaseline('Correct information for ' + fileName, justName.replace(/\.ts/, fullExtension), () => fullBaseLine);
|
||||
Harness.Baseline.runBaseline("Correct information for " + fileName, justName.replace(/\.tsx?/, fullExtension), () => fullBaseLine);
|
||||
}
|
||||
}
|
||||
|
||||
function generateBaseLine(typeWriterResults: ts.Map<TypeWriterResult[]>, isSymbolBaseline: boolean): string {
|
||||
let typeLines: string[] = [];
|
||||
let typeMap: { [fileName: string]: { [lineNum: number]: string[]; } } = {};
|
||||
const typeLines: string[] = [];
|
||||
const typeMap: { [fileName: string]: { [lineNum: number]: string[]; } } = {};
|
||||
|
||||
allFiles.forEach(file => {
|
||||
var codeLines = file.content.split('\n');
|
||||
const codeLines = file.content.split("\n");
|
||||
typeWriterResults[file.unitName].forEach(result => {
|
||||
if (isSymbolBaseline && !result.symbol) {
|
||||
return;
|
||||
}
|
||||
|
||||
var typeOrSymbolString = isSymbolBaseline ? result.symbol : result.type;
|
||||
var formattedLine = result.sourceText.replace(/\r?\n/g, "") + " : " + typeOrSymbolString;
|
||||
const typeOrSymbolString = isSymbolBaseline ? result.symbol : result.type;
|
||||
const formattedLine = result.sourceText.replace(/\r?\n/g, "") + " : " + typeOrSymbolString;
|
||||
if (!typeMap[file.unitName]) {
|
||||
typeMap[file.unitName] = {};
|
||||
}
|
||||
|
||||
var typeInfo = [formattedLine];
|
||||
var existingTypeInfo = typeMap[file.unitName][result.line];
|
||||
let typeInfo = [formattedLine];
|
||||
const existingTypeInfo = typeMap[file.unitName][result.line];
|
||||
if (existingTypeInfo) {
|
||||
typeInfo = existingTypeInfo.concat(typeInfo);
|
||||
}
|
||||
typeMap[file.unitName][result.line] = typeInfo;
|
||||
});
|
||||
|
||||
typeLines.push('=== ' + file.unitName + ' ===\r\n');
|
||||
for (var i = 0; i < codeLines.length; i++) {
|
||||
var currentCodeLine = codeLines[i];
|
||||
typeLines.push(currentCodeLine + '\r\n');
|
||||
typeLines.push("=== " + file.unitName + " ===\r\n");
|
||||
for (let i = 0; i < codeLines.length; i++) {
|
||||
const currentCodeLine = codeLines[i];
|
||||
typeLines.push(currentCodeLine + "\r\n");
|
||||
if (typeMap[file.unitName]) {
|
||||
var typeInfo = typeMap[file.unitName][i];
|
||||
const typeInfo = typeMap[file.unitName][i];
|
||||
if (typeInfo) {
|
||||
typeInfo.forEach(ty => {
|
||||
typeLines.push('>' + ty + '\r\n');
|
||||
typeLines.push(">" + ty + "\r\n");
|
||||
});
|
||||
if (i + 1 < codeLines.length && (codeLines[i + 1].match(/^\s*[{|}]\s*$/) || codeLines[i + 1].trim() === '')) {
|
||||
if (i + 1 < codeLines.length && (codeLines[i + 1].match(/^\s*[{|}]\s*$/) || codeLines[i + 1].trim() === "")) {
|
||||
}
|
||||
else {
|
||||
typeLines.push('\r\n');
|
||||
typeLines.push("\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
typeLines.push('No type information for this code.');
|
||||
typeLines.push("No type information for this code.");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return typeLines.join('');
|
||||
return typeLines.join("");
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -382,25 +355,22 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
}
|
||||
|
||||
public initializeTests() {
|
||||
describe("Setup compiler for compiler baselines", () => {
|
||||
var harnessCompiler = Harness.Compiler.getCompiler();
|
||||
this.parseOptions();
|
||||
});
|
||||
|
||||
// this will set up a series of describe/it blocks to run between the setup and cleanup phases
|
||||
if (this.tests.length === 0) {
|
||||
var testFiles = this.enumerateFiles(this.basePath, /\.ts$/, { recursive: true });
|
||||
testFiles.forEach(fn => {
|
||||
fn = fn.replace(/\\/g, "/");
|
||||
this.checkTestCodeOutput(fn);
|
||||
describe(this.testSuiteName + " tests", () => {
|
||||
describe("Setup compiler for compiler baselines", () => {
|
||||
this.parseOptions();
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.tests.forEach(test => this.checkTestCodeOutput(test));
|
||||
}
|
||||
|
||||
describe("Cleanup after compiler baselines", () => {
|
||||
var harnessCompiler = Harness.Compiler.getCompiler();
|
||||
// this will set up a series of describe/it blocks to run between the setup and cleanup phases
|
||||
if (this.tests.length === 0) {
|
||||
const testFiles = this.enumerateFiles(this.basePath, /\.tsx?$/, { recursive: true });
|
||||
testFiles.forEach(fn => {
|
||||
fn = fn.replace(/\\/g, "/");
|
||||
this.checkTestCodeOutput(fn);
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.tests.forEach(test => this.checkTestCodeOutput(test));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -411,25 +381,25 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
this.decl = false;
|
||||
this.output = false;
|
||||
|
||||
var opts = this.options.split(',');
|
||||
for (var i = 0; i < opts.length; i++) {
|
||||
const opts = this.options.split(",");
|
||||
for (let i = 0; i < opts.length; i++) {
|
||||
switch (opts[i]) {
|
||||
case 'error':
|
||||
case "error":
|
||||
this.errors = true;
|
||||
break;
|
||||
case 'emit':
|
||||
case "emit":
|
||||
this.emit = true;
|
||||
break;
|
||||
case 'decl':
|
||||
case "decl":
|
||||
this.decl = true;
|
||||
break;
|
||||
case 'output':
|
||||
case "output":
|
||||
this.output = true;
|
||||
break;
|
||||
default:
|
||||
throw new Error('unsupported flag');
|
||||
throw new Error("unsupported flag");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
// Allows for executing a program with command-line arguments and reading the result
|
||||
interface IExec {
|
||||
exec: (fileName: string, cmdLineArgs: string[], handleResult: (ExecResult: ExecResult) => void) => void;
|
||||
}
|
||||
|
||||
class ExecResult {
|
||||
public stdout = "";
|
||||
public stderr = "";
|
||||
public exitCode: number;
|
||||
}
|
||||
|
||||
class WindowsScriptHostExec implements IExec {
|
||||
public exec(fileName: string, cmdLineArgs: string[], handleResult: (ExecResult: ExecResult) => void) : void {
|
||||
var result = new ExecResult();
|
||||
var shell = new ActiveXObject('WScript.Shell');
|
||||
try {
|
||||
var process = shell.Exec(fileName + ' ' + cmdLineArgs.join(' '));
|
||||
} catch(e) {
|
||||
result.stderr = e.message;
|
||||
result.exitCode = 1;
|
||||
handleResult(result);
|
||||
return;
|
||||
}
|
||||
// Wait for it to finish running
|
||||
while (process.Status != 0) { /* todo: sleep? */ }
|
||||
|
||||
|
||||
result.exitCode = process.ExitCode;
|
||||
if(!process.StdOut.AtEndOfStream) result.stdout = process.StdOut.ReadAll();
|
||||
if(!process.StdErr.AtEndOfStream) result.stderr = process.StdErr.ReadAll();
|
||||
|
||||
handleResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
class NodeExec implements IExec {
|
||||
public exec(fileName: string, cmdLineArgs: string[], handleResult: (ExecResult: ExecResult) => void) : void {
|
||||
var nodeExec = require('child_process').exec;
|
||||
|
||||
var result = new ExecResult();
|
||||
result.exitCode = null;
|
||||
var cmdLine = fileName + ' ' + cmdLineArgs.join(' ');
|
||||
var process = nodeExec(cmdLine, function(error: any, stdout: string, stderr: string) {
|
||||
result.stdout = stdout;
|
||||
result.stderr = stderr;
|
||||
result.exitCode = error ? error.code : 0;
|
||||
handleResult(result);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var Exec: IExec = function() : IExec {
|
||||
var global = <any>Function("return this;").call(null);
|
||||
if(typeof global.ActiveXObject !== "undefined") {
|
||||
return new WindowsScriptHostExec();
|
||||
} else {
|
||||
return new NodeExec();
|
||||
}
|
||||
}();
|
||||
+1591
-843
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,12 @@
|
||||
///<reference path='fourslash.ts' />
|
||||
///<reference path='harness.ts'/>
|
||||
///<reference path='runnerbase.ts' />
|
||||
///<reference path="fourslash.ts" />
|
||||
///<reference path="harness.ts"/>
|
||||
///<reference path="runnerbase.ts" />
|
||||
/* tslint:disable:no-null */
|
||||
|
||||
const enum FourSlashTestType {
|
||||
const enum FourSlashTestType {
|
||||
Native,
|
||||
Shims,
|
||||
ShimsWithPreprocess,
|
||||
Server
|
||||
}
|
||||
|
||||
@@ -16,16 +18,20 @@ class FourSlashRunner extends RunnerBase {
|
||||
super();
|
||||
switch (testType) {
|
||||
case FourSlashTestType.Native:
|
||||
this.basePath = 'tests/cases/fourslash';
|
||||
this.testSuiteName = 'fourslash';
|
||||
this.basePath = "tests/cases/fourslash";
|
||||
this.testSuiteName = "fourslash";
|
||||
break;
|
||||
case FourSlashTestType.Shims:
|
||||
this.basePath = 'tests/cases/fourslash/shims';
|
||||
this.testSuiteName = 'fourslash-shims';
|
||||
this.basePath = "tests/cases/fourslash/shims";
|
||||
this.testSuiteName = "fourslash-shims";
|
||||
break;
|
||||
case FourSlashTestType.ShimsWithPreprocess:
|
||||
this.basePath = "tests/cases/fourslash/shims-pp";
|
||||
this.testSuiteName = "fourslash-shims-pp";
|
||||
break;
|
||||
case FourSlashTestType.Server:
|
||||
this.basePath = 'tests/cases/fourslash/server';
|
||||
this.testSuiteName = 'fourslash-server';
|
||||
this.basePath = "tests/cases/fourslash/server";
|
||||
this.testSuiteName = "fourslash-server";
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -35,77 +41,30 @@ class FourSlashRunner extends RunnerBase {
|
||||
this.tests = this.enumerateFiles(this.basePath, /\.ts/i, { recursive: false });
|
||||
}
|
||||
|
||||
describe(this.testSuiteName, () => {
|
||||
describe(this.testSuiteName + " tests", () => {
|
||||
this.tests.forEach((fn: string) => {
|
||||
fn = ts.normalizeSlashes(fn);
|
||||
var justName = fn.replace(/^.*[\\\/]/, '');
|
||||
describe(fn, () => {
|
||||
fn = ts.normalizeSlashes(fn);
|
||||
const justName = fn.replace(/^.*[\\\/]/, "");
|
||||
|
||||
// Convert to relative path
|
||||
var testIndex = fn.indexOf('tests/');
|
||||
if (testIndex >= 0) fn = fn.substr(testIndex);
|
||||
// Convert to relative path
|
||||
const testIndex = fn.indexOf("tests/");
|
||||
if (testIndex >= 0) fn = fn.substr(testIndex);
|
||||
|
||||
if (justName && !justName.match(/fourslash\.ts$/i) && !justName.match(/\.d\.ts$/i)) {
|
||||
it(this.testSuiteName + ' test ' + justName + ' runs correctly',() => {
|
||||
FourSlash.runFourSlashTest(this.basePath, this.testType, fn);
|
||||
});
|
||||
}
|
||||
if (justName && !justName.match(/fourslash\.ts$/i) && !justName.match(/\.d\.ts$/i)) {
|
||||
it(this.testSuiteName + " test " + justName + " runs correctly", () => {
|
||||
FourSlash.runFourSlashTest(this.basePath, this.testType, fn);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Generate Tao XML', () => {
|
||||
var invalidReasons: any = {};
|
||||
FourSlash.xmlData.forEach(xml => {
|
||||
if (xml.invalidReason !== null) {
|
||||
invalidReasons[xml.invalidReason] = (invalidReasons[xml.invalidReason] || 0) + 1;
|
||||
}
|
||||
});
|
||||
var invalidReport: { reason: string; count: number }[] = [];
|
||||
for (var reason in invalidReasons) {
|
||||
if (invalidReasons.hasOwnProperty(reason)) {
|
||||
invalidReport.push({ reason: reason, count: invalidReasons[reason] });
|
||||
}
|
||||
}
|
||||
invalidReport.sort((lhs, rhs) => lhs.count > rhs.count ? -1 : lhs.count === rhs.count ? 0 : 1);
|
||||
|
||||
var lines: string[] = [];
|
||||
lines.push('<!-- Blocked Test Report');
|
||||
invalidReport.forEach((reasonAndCount) => {
|
||||
lines.push(reasonAndCount.count + ' tests blocked by ' + reasonAndCount.reason);
|
||||
});
|
||||
lines.push('-->');
|
||||
lines.push('<TaoTest xmlns="http://microsoft.com/schemas/VSLanguages/TAO">');
|
||||
lines.push(' <InitTest>');
|
||||
lines.push(' <StartTarget />');
|
||||
lines.push(' </InitTest>');
|
||||
lines.push(' <ScenarioList>');
|
||||
FourSlash.xmlData.forEach(xml => {
|
||||
if (xml.invalidReason !== null) {
|
||||
lines.push('<!-- Skipped ' + xml.originalName + ', reason: ' + xml.invalidReason + ' -->');
|
||||
} else {
|
||||
lines.push(' <Scenario Name="' + xml.originalName + '">');
|
||||
xml.actions.forEach(action => {
|
||||
lines.push(' ' + action);
|
||||
});
|
||||
lines.push(' </Scenario>');
|
||||
}
|
||||
});
|
||||
lines.push(' </ScenarioList>');
|
||||
lines.push(' <CleanupScenario>');
|
||||
lines.push(' <CloseAllDocuments />');
|
||||
lines.push(' <CleanupCreatedFiles />');
|
||||
lines.push(' </CleanupScenario>');
|
||||
lines.push(' <CleanupTest>');
|
||||
lines.push(' <CloseTarget />');
|
||||
lines.push(' </CleanupTest>');
|
||||
lines.push('</TaoTest>');
|
||||
Harness.IO.writeFile('built/local/fourslash.xml', lines.join('\r\n'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class GeneratedFourslashRunner extends FourSlashRunner {
|
||||
constructor(testType: FourSlashTestType) {
|
||||
super(testType);
|
||||
this.basePath += '/generated/';
|
||||
this.basePath += "/generated/";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+620
-742
File diff suppressed because it is too large
Load Diff
@@ -1,13 +1,13 @@
|
||||
/// <reference path='..\services\services.ts' />
|
||||
/// <reference path='..\services\shims.ts' />
|
||||
/// <reference path='..\server\client.ts' />
|
||||
/// <reference path='harness.ts' />
|
||||
/// <reference path="..\services\services.ts" />
|
||||
/// <reference path="..\services\shims.ts" />
|
||||
/// <reference path="..\server\client.ts" />
|
||||
/// <reference path="harness.ts" />
|
||||
|
||||
module Harness.LanguageService {
|
||||
namespace Harness.LanguageService {
|
||||
export class ScriptInfo {
|
||||
public version: number = 1;
|
||||
public editRanges: { length: number; textChangeRange: ts.TextChangeRange; }[] = [];
|
||||
public lineMap: number[] = null;
|
||||
private lineMap: number[] = undefined;
|
||||
|
||||
constructor(public fileName: string, public content: string) {
|
||||
this.setContent(content);
|
||||
@@ -15,7 +15,11 @@ module Harness.LanguageService {
|
||||
|
||||
private setContent(content: string): void {
|
||||
this.content = content;
|
||||
this.lineMap = ts.computeLineStarts(content);
|
||||
this.lineMap = undefined;
|
||||
}
|
||||
|
||||
public getLineMap(): number[] {
|
||||
return this.lineMap || (this.lineMap = ts.computeLineStarts(this.content));
|
||||
}
|
||||
|
||||
public updateContent(content: string): void {
|
||||
@@ -26,9 +30,9 @@ module Harness.LanguageService {
|
||||
|
||||
public editContent(start: number, end: number, newText: string): void {
|
||||
// Apply edits
|
||||
var prefix = this.content.substring(0, start);
|
||||
var middle = newText;
|
||||
var suffix = this.content.substring(end);
|
||||
const prefix = this.content.substring(0, start);
|
||||
const middle = newText;
|
||||
const suffix = this.content.substring(end);
|
||||
this.setContent(prefix + middle + suffix);
|
||||
|
||||
// Store edit range + new length of script
|
||||
@@ -48,10 +52,10 @@ module Harness.LanguageService {
|
||||
return ts.unchangedTextChangeRange;
|
||||
}
|
||||
|
||||
var initialEditRangeIndex = this.editRanges.length - (this.version - startVersion);
|
||||
var lastEditRangeIndex = this.editRanges.length - (this.version - endVersion);
|
||||
const initialEditRangeIndex = this.editRanges.length - (this.version - startVersion);
|
||||
const lastEditRangeIndex = this.editRanges.length - (this.version - endVersion);
|
||||
|
||||
var entries = this.editRanges.slice(initialEditRangeIndex, lastEditRangeIndex);
|
||||
const entries = this.editRanges.slice(initialEditRangeIndex, lastEditRangeIndex);
|
||||
return ts.collapseTextChangeRangesAcrossMultipleVersions(entries.map(e => e.textChangeRange));
|
||||
}
|
||||
}
|
||||
@@ -74,7 +78,7 @@ module Harness.LanguageService {
|
||||
}
|
||||
|
||||
public getChangeRange(oldScript: ts.IScriptSnapshot): ts.TextChangeRange {
|
||||
var oldShim = <ScriptSnapshot>oldScript;
|
||||
const oldShim = <ScriptSnapshot>oldScript;
|
||||
return this.scriptInfo.getTextChangeRangeBetweenVersions(oldShim.version, this.version);
|
||||
}
|
||||
}
|
||||
@@ -92,25 +96,22 @@ module Harness.LanguageService {
|
||||
}
|
||||
|
||||
public getChangeRange(oldScript: ts.ScriptSnapshotShim): string {
|
||||
var oldShim = <ScriptSnapshotProxy>oldScript;
|
||||
const oldShim = <ScriptSnapshotProxy>oldScript;
|
||||
|
||||
var range = this.scriptSnapshot.getChangeRange(oldShim.scriptSnapshot);
|
||||
if (range === null) {
|
||||
return null;
|
||||
const range = this.scriptSnapshot.getChangeRange(oldShim.scriptSnapshot);
|
||||
if (range === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return JSON.stringify({ span: { start: range.span.start, length: range.span.length }, newLength: range.newLength });
|
||||
}
|
||||
}
|
||||
|
||||
class CancellationToken {
|
||||
public static None: CancellationToken = new CancellationToken(null);
|
||||
|
||||
constructor(private cancellationToken: ts.CancellationToken) {
|
||||
}
|
||||
class DefaultHostCancellationToken implements ts.HostCancellationToken {
|
||||
public static Instance = new DefaultHostCancellationToken();
|
||||
|
||||
public isCancellationRequested() {
|
||||
return this.cancellationToken && this.cancellationToken.isCancellationRequested();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,11 +122,11 @@ module Harness.LanguageService {
|
||||
getPreProcessedFileInfo(fileName: string, fileContents: string): ts.PreProcessedFileInfo;
|
||||
}
|
||||
|
||||
export class LanguageServiceAdapterHost {
|
||||
export class LanguageServiceAdapterHost {
|
||||
protected fileNameToScript: ts.Map<ScriptInfo> = {};
|
||||
|
||||
constructor(protected cancellationToken: ts.CancellationToken = CancellationToken.None,
|
||||
protected settings = ts.getDefaultCompilerOptions()) {
|
||||
|
||||
constructor(protected cancellationToken = DefaultHostCancellationToken.Instance,
|
||||
protected settings = ts.getDefaultCompilerOptions()) {
|
||||
}
|
||||
|
||||
public getNewLine(): string {
|
||||
@@ -133,8 +134,8 @@ module Harness.LanguageService {
|
||||
}
|
||||
|
||||
public getFilenames(): string[] {
|
||||
var fileNames: string[] = [];
|
||||
ts.forEachKey(this.fileNameToScript,(fileName) => { fileNames.push(fileName); });
|
||||
const fileNames: string[] = [];
|
||||
ts.forEachKey(this.fileNameToScript, (fileName) => { fileNames.push(fileName); });
|
||||
return fileNames;
|
||||
}
|
||||
|
||||
@@ -147,8 +148,8 @@ module Harness.LanguageService {
|
||||
}
|
||||
|
||||
public editScript(fileName: string, start: number, end: number, newText: string) {
|
||||
var script = this.getScriptInfo(fileName);
|
||||
if (script !== null) {
|
||||
const script = this.getScriptInfo(fileName);
|
||||
if (script !== undefined) {
|
||||
script.editContent(start, end, newText);
|
||||
return;
|
||||
}
|
||||
@@ -156,7 +157,7 @@ module Harness.LanguageService {
|
||||
throw new Error("No script with name '" + fileName + "'");
|
||||
}
|
||||
|
||||
public openFile(fileName: string): void {
|
||||
public openFile(fileName: string, content?: string): void {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,28 +165,29 @@ module Harness.LanguageService {
|
||||
* @param col 0 based index
|
||||
*/
|
||||
public positionToLineAndCharacter(fileName: string, position: number): ts.LineAndCharacter {
|
||||
var script: ScriptInfo = this.fileNameToScript[fileName];
|
||||
const script: ScriptInfo = this.fileNameToScript[fileName];
|
||||
assert.isNotNull(script);
|
||||
|
||||
return ts.computeLineAndCharacterOfPosition(script.lineMap, position);
|
||||
return ts.computeLineAndCharacterOfPosition(script.getLineMap(), position);
|
||||
}
|
||||
}
|
||||
|
||||
/// Native adapter
|
||||
class NativeLanguageServiceHost extends LanguageServiceAdapterHost implements ts.LanguageServiceHost {
|
||||
getCompilationSettings(): ts.CompilerOptions { return this.settings; }
|
||||
getCancellationToken(): ts.CancellationToken { return this.cancellationToken; }
|
||||
class NativeLanguageServiceHost extends LanguageServiceAdapterHost implements ts.LanguageServiceHost {
|
||||
getCompilationSettings() { return this.settings; }
|
||||
getCancellationToken() { return this.cancellationToken; }
|
||||
getCurrentDirectory(): string { return ""; }
|
||||
getDefaultLibFileName(): string { return ""; }
|
||||
getScriptFileNames(): string[] { return this.getFilenames(); }
|
||||
getScriptSnapshot(fileName: string): ts.IScriptSnapshot {
|
||||
var script = this.getScriptInfo(fileName);
|
||||
const script = this.getScriptInfo(fileName);
|
||||
return script ? new ScriptSnapshot(script) : undefined;
|
||||
}
|
||||
getScriptVersion(fileName: string): string {
|
||||
var script = this.getScriptInfo(fileName);
|
||||
const script = this.getScriptInfo(fileName);
|
||||
return script ? script.version.toString() : undefined;
|
||||
}
|
||||
|
||||
log(s: string): void { }
|
||||
trace(s: string): void { }
|
||||
error(s: string): void { }
|
||||
@@ -193,21 +195,47 @@ module Harness.LanguageService {
|
||||
|
||||
export class NativeLanugageServiceAdapter implements LanguageServiceAdapter {
|
||||
private host: NativeLanguageServiceHost;
|
||||
constructor(cancellationToken?: ts.CancellationToken, options?: ts.CompilerOptions) {
|
||||
constructor(cancellationToken?: ts.HostCancellationToken, options?: ts.CompilerOptions) {
|
||||
this.host = new NativeLanguageServiceHost(cancellationToken, options);
|
||||
}
|
||||
getHost() { return this.host; }
|
||||
getLanguageService(): ts.LanguageService { return ts.createLanguageService(this.host); }
|
||||
getClassifier(): ts.Classifier { return ts.createClassifier(); }
|
||||
getPreProcessedFileInfo(fileName: string, fileContents: string): ts.PreProcessedFileInfo { return ts.preProcessFile(fileContents); }
|
||||
getPreProcessedFileInfo(fileName: string, fileContents: string): ts.PreProcessedFileInfo { return ts.preProcessFile(fileContents, /* readImportFiles */ true, ts.hasJavaScriptFileExtension(fileName)); }
|
||||
}
|
||||
|
||||
/// Shim adapter
|
||||
class ShimLanguageServiceHost extends LanguageServiceAdapterHost implements ts.LanguageServiceShimHost {
|
||||
class ShimLanguageServiceHost extends LanguageServiceAdapterHost implements ts.LanguageServiceShimHost, ts.CoreServicesShimHost {
|
||||
private nativeHost: NativeLanguageServiceHost;
|
||||
constructor(cancellationToken?: ts.CancellationToken, options?: ts.CompilerOptions) {
|
||||
|
||||
public getModuleResolutionsForFile: (fileName: string) => string;
|
||||
|
||||
constructor(preprocessToResolve: boolean, cancellationToken?: ts.HostCancellationToken, options?: ts.CompilerOptions) {
|
||||
super(cancellationToken, options);
|
||||
this.nativeHost = new NativeLanguageServiceHost(cancellationToken, options);
|
||||
|
||||
if (preprocessToResolve) {
|
||||
const compilerOptions = this.nativeHost.getCompilationSettings();
|
||||
const moduleResolutionHost: ts.ModuleResolutionHost = {
|
||||
fileExists: fileName => this.getScriptInfo(fileName) !== undefined,
|
||||
readFile: fileName => {
|
||||
const scriptInfo = this.getScriptInfo(fileName);
|
||||
return scriptInfo && scriptInfo.content;
|
||||
}
|
||||
};
|
||||
this.getModuleResolutionsForFile = (fileName) => {
|
||||
const scriptInfo = this.getScriptInfo(fileName);
|
||||
const preprocessInfo = ts.preProcessFile(scriptInfo.content, /*readImportFiles*/ true);
|
||||
const imports: ts.Map<string> = {};
|
||||
for (const module of preprocessInfo.importedFiles) {
|
||||
const resolutionInfo = ts.resolveModuleName(module.fileName, fileName, compilerOptions, moduleResolutionHost);
|
||||
if (resolutionInfo.resolvedModule) {
|
||||
imports[module.fileName] = resolutionInfo.resolvedModule.resolvedFileName;
|
||||
}
|
||||
}
|
||||
return JSON.stringify(imports);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
getFilenames(): string[] { return this.nativeHost.getFilenames(); }
|
||||
@@ -217,32 +245,48 @@ module Harness.LanguageService {
|
||||
positionToLineAndCharacter(fileName: string, position: number): ts.LineAndCharacter { return this.nativeHost.positionToLineAndCharacter(fileName, position); }
|
||||
|
||||
getCompilationSettings(): string { return JSON.stringify(this.nativeHost.getCompilationSettings()); }
|
||||
getCancellationToken(): ts.CancellationToken { return this.nativeHost.getCancellationToken(); }
|
||||
getCancellationToken(): ts.HostCancellationToken { return this.nativeHost.getCancellationToken(); }
|
||||
getCurrentDirectory(): string { return this.nativeHost.getCurrentDirectory(); }
|
||||
getDefaultLibFileName(): string { return this.nativeHost.getDefaultLibFileName(); }
|
||||
getScriptFileNames(): string { return JSON.stringify(this.nativeHost.getScriptFileNames()); }
|
||||
getScriptSnapshot(fileName: string): ts.ScriptSnapshotShim {
|
||||
var nativeScriptSnapshot = this.nativeHost.getScriptSnapshot(fileName);
|
||||
return nativeScriptSnapshot && new ScriptSnapshotProxy(nativeScriptSnapshot);
|
||||
const nativeScriptSnapshot = this.nativeHost.getScriptSnapshot(fileName);
|
||||
return nativeScriptSnapshot && new ScriptSnapshotProxy(nativeScriptSnapshot);
|
||||
}
|
||||
getScriptVersion(fileName: string): string { return this.nativeHost.getScriptVersion(fileName); }
|
||||
getLocalizedDiagnosticMessages(): string { return JSON.stringify({}); }
|
||||
|
||||
readDirectory(rootDir: string, extension: string): string {
|
||||
throw new Error("NYI");
|
||||
}
|
||||
fileExists(fileName: string) { return this.getScriptInfo(fileName) !== undefined; }
|
||||
readFile(fileName: string) {
|
||||
const snapshot = this.nativeHost.getScriptSnapshot(fileName);
|
||||
return snapshot && snapshot.getText(0, snapshot.getLength());
|
||||
}
|
||||
log(s: string): void { this.nativeHost.log(s); }
|
||||
trace(s: string): void { this.nativeHost.trace(s); }
|
||||
error(s: string): void { this.nativeHost.error(s); }
|
||||
directoryExists(directoryName: string): boolean {
|
||||
// for tests pessimistically assume that directory always exists
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class ClassifierShimProxy implements ts.Classifier {
|
||||
class ClassifierShimProxy implements ts.Classifier {
|
||||
constructor(private shim: ts.ClassifierShim) {
|
||||
}
|
||||
getEncodedLexicalClassifications(text: string, lexState: ts.EndOfLineState, classifyKeywordsInGenerics?: boolean): ts.Classifications {
|
||||
throw new Error("NYI");
|
||||
}
|
||||
getClassificationsForLine(text: string, lexState: ts.EndOfLineState, classifyKeywordsInGenerics?: boolean): ts.ClassificationResult {
|
||||
var result = this.shim.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics).split('\n');
|
||||
var entries: ts.ClassificationInfo[] = [];
|
||||
var i = 0;
|
||||
var position = 0;
|
||||
const result = this.shim.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics).split("\n");
|
||||
const entries: ts.ClassificationInfo[] = [];
|
||||
let i = 0;
|
||||
let position = 0;
|
||||
|
||||
for (; i < result.length - 1; i += 2) {
|
||||
var t = entries[i / 2] = {
|
||||
const t = entries[i / 2] = {
|
||||
length: parseInt(result[i]),
|
||||
classification: parseInt(result[i + 1])
|
||||
};
|
||||
@@ -250,7 +294,7 @@ module Harness.LanguageService {
|
||||
assert.isTrue(t.length > 0, "Result length should be greater than 0, got :" + t.length);
|
||||
position += t.length;
|
||||
}
|
||||
var finalLexState = parseInt(result[result.length - 1]);
|
||||
const finalLexState = parseInt(result[result.length - 1]);
|
||||
|
||||
assert.equal(position, text.length, "Expected cumulative length of all entries to match the length of the source. expected: " + text.length + ", but got: " + position);
|
||||
|
||||
@@ -262,11 +306,11 @@ module Harness.LanguageService {
|
||||
}
|
||||
|
||||
function unwrapJSONCallResult(result: string): any {
|
||||
var parsedResult = JSON.parse(result);
|
||||
const parsedResult = JSON.parse(result);
|
||||
if (parsedResult.error) {
|
||||
throw new Error("Language Service Shim Error: " + JSON.stringify(parsedResult.error));
|
||||
}
|
||||
else if (parsedResult.canceled) {
|
||||
else if (parsedResult.canceled) {
|
||||
throw new ts.OperationCanceledException();
|
||||
}
|
||||
return parsedResult.result;
|
||||
@@ -275,13 +319,6 @@ module Harness.LanguageService {
|
||||
class LanguageServiceShimProxy implements ts.LanguageService {
|
||||
constructor(private shim: ts.LanguageServiceShim) {
|
||||
}
|
||||
private unwrappJSONCallResult(result: string): any {
|
||||
var parsedResult = JSON.parse(result);
|
||||
if (parsedResult.error) {
|
||||
throw new Error("Language Service Shim Error: " + JSON.stringify(parsedResult.error));
|
||||
}
|
||||
return parsedResult.result;
|
||||
}
|
||||
cleanupSemanticCache(): void {
|
||||
this.shim.cleanupSemanticCache();
|
||||
}
|
||||
@@ -300,6 +337,12 @@ module Harness.LanguageService {
|
||||
getSemanticClassifications(fileName: string, span: ts.TextSpan): ts.ClassifiedSpan[] {
|
||||
return unwrapJSONCallResult(this.shim.getSemanticClassifications(fileName, span.start, span.length));
|
||||
}
|
||||
getEncodedSyntacticClassifications(fileName: string, span: ts.TextSpan): ts.Classifications {
|
||||
return unwrapJSONCallResult(this.shim.getEncodedSyntacticClassifications(fileName, span.start, span.length));
|
||||
}
|
||||
getEncodedSemanticClassifications(fileName: string, span: ts.TextSpan): ts.Classifications {
|
||||
return unwrapJSONCallResult(this.shim.getEncodedSemanticClassifications(fileName, span.start, span.length));
|
||||
}
|
||||
getCompletionsAtPosition(fileName: string, position: number): ts.CompletionInfo {
|
||||
return unwrapJSONCallResult(this.shim.getCompletionsAtPosition(fileName, position));
|
||||
}
|
||||
@@ -327,6 +370,9 @@ module Harness.LanguageService {
|
||||
getDefinitionAtPosition(fileName: string, position: number): ts.DefinitionInfo[] {
|
||||
return unwrapJSONCallResult(this.shim.getDefinitionAtPosition(fileName, position));
|
||||
}
|
||||
getTypeDefinitionAtPosition(fileName: string, position: number): ts.DefinitionInfo[] {
|
||||
return unwrapJSONCallResult(this.shim.getTypeDefinitionAtPosition(fileName, position));
|
||||
}
|
||||
getReferencesAtPosition(fileName: string, position: number): ts.ReferenceEntry[] {
|
||||
return unwrapJSONCallResult(this.shim.getReferencesAtPosition(fileName, position));
|
||||
}
|
||||
@@ -366,6 +412,9 @@ module Harness.LanguageService {
|
||||
getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: ts.FormatCodeOptions): ts.TextChange[] {
|
||||
return unwrapJSONCallResult(this.shim.getFormattingEditsAfterKeystroke(fileName, position, key, JSON.stringify(options)));
|
||||
}
|
||||
getDocCommentTemplateAtPosition(fileName: string, position: number): ts.TextInsertion {
|
||||
return unwrapJSONCallResult(this.shim.getDocCommentTemplateAtPosition(fileName, position));
|
||||
}
|
||||
getEmitOutput(fileName: string): ts.EmitOutput {
|
||||
return unwrapJSONCallResult(this.shim.getEmitOutput(fileName));
|
||||
}
|
||||
@@ -381,26 +430,27 @@ module Harness.LanguageService {
|
||||
export class ShimLanugageServiceAdapter implements LanguageServiceAdapter {
|
||||
private host: ShimLanguageServiceHost;
|
||||
private factory: ts.TypeScriptServicesFactory;
|
||||
constructor(cancellationToken?: ts.CancellationToken, options?: ts.CompilerOptions) {
|
||||
this.host = new ShimLanguageServiceHost(cancellationToken, options);
|
||||
constructor(preprocessToResolve: boolean, cancellationToken?: ts.HostCancellationToken, options?: ts.CompilerOptions) {
|
||||
this.host = new ShimLanguageServiceHost(preprocessToResolve, cancellationToken, options);
|
||||
this.factory = new TypeScript.Services.TypeScriptServicesFactory();
|
||||
}
|
||||
getHost() { return this.host; }
|
||||
getLanguageService(): ts.LanguageService { return new LanguageServiceShimProxy(this.factory.createLanguageServiceShim(this.host)); }
|
||||
getClassifier(): ts.Classifier { return new ClassifierShimProxy(this.factory.createClassifierShim(this.host)); }
|
||||
getPreProcessedFileInfo(fileName: string, fileContents: string): ts.PreProcessedFileInfo {
|
||||
var shimResult: {
|
||||
let shimResult: {
|
||||
referencedFiles: ts.IFileReference[];
|
||||
importedFiles: ts.IFileReference[];
|
||||
isLibFile: boolean;
|
||||
};
|
||||
|
||||
var coreServicesShim = this.factory.createCoreServicesShim(this.host);
|
||||
const coreServicesShim = this.factory.createCoreServicesShim(this.host);
|
||||
shimResult = unwrapJSONCallResult(coreServicesShim.getPreProcessedFileInfo(fileName, ts.ScriptSnapshot.fromString(fileContents)));
|
||||
|
||||
var convertResult: ts.PreProcessedFileInfo = {
|
||||
const convertResult: ts.PreProcessedFileInfo = {
|
||||
referencedFiles: [],
|
||||
importedFiles: [],
|
||||
ambientExternalModules: [],
|
||||
isLibFile: shimResult.isLibFile
|
||||
};
|
||||
|
||||
@@ -425,28 +475,28 @@ module Harness.LanguageService {
|
||||
}
|
||||
|
||||
// Server adapter
|
||||
class SessionClientHost extends NativeLanguageServiceHost implements ts.server.SessionClientHost {
|
||||
class SessionClientHost extends NativeLanguageServiceHost implements ts.server.SessionClientHost {
|
||||
private client: ts.server.SessionClient;
|
||||
|
||||
constructor(cancellationToken: ts.CancellationToken, settings: ts.CompilerOptions) {
|
||||
constructor(cancellationToken: ts.HostCancellationToken, settings: ts.CompilerOptions) {
|
||||
super(cancellationToken, settings);
|
||||
}
|
||||
|
||||
onMessage(message: string): void {
|
||||
|
||||
onMessage(message: string): void {
|
||||
|
||||
}
|
||||
|
||||
writeMessage(message: string): void {
|
||||
|
||||
writeMessage(message: string): void {
|
||||
|
||||
}
|
||||
|
||||
setClient(client: ts.server.SessionClient) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
openFile(fileName: string): void {
|
||||
super.openFile(fileName);
|
||||
this.client.openFile(fileName);
|
||||
openFile(fileName: string, content?: string): void {
|
||||
super.openFile(fileName, content);
|
||||
this.client.openFile(fileName, content);
|
||||
}
|
||||
|
||||
editScript(fileName: string, start: number, end: number, newText: string) {
|
||||
@@ -455,7 +505,7 @@ module Harness.LanguageService {
|
||||
}
|
||||
}
|
||||
|
||||
class SessionServerHost implements ts.server.ServerHost, ts.server.Logger {
|
||||
class SessionServerHost implements ts.server.ServerHost, ts.server.Logger {
|
||||
args: string[] = [];
|
||||
newLine: string;
|
||||
useCaseSensitiveFileNames: boolean = false;
|
||||
@@ -464,24 +514,24 @@ module Harness.LanguageService {
|
||||
this.newLine = this.host.getNewLine();
|
||||
}
|
||||
|
||||
onMessage(message: string): void {
|
||||
|
||||
onMessage(message: string): void {
|
||||
|
||||
}
|
||||
|
||||
writeMessage(message: string): void {
|
||||
}
|
||||
|
||||
write(message: string): void {
|
||||
write(message: string): void {
|
||||
this.writeMessage(message);
|
||||
}
|
||||
|
||||
|
||||
readFile(fileName: string): string {
|
||||
if (fileName.indexOf(Harness.Compiler.defaultLibFileName) >= 0) {
|
||||
if (fileName.indexOf(Harness.Compiler.defaultLibFileName) >= 0) {
|
||||
fileName = Harness.Compiler.defaultLibFileName;
|
||||
}
|
||||
|
||||
var snapshot = this.host.getScriptSnapshot(fileName);
|
||||
|
||||
const snapshot = this.host.getScriptSnapshot(fileName);
|
||||
return snapshot && snapshot.getText(0, snapshot.getLength());
|
||||
}
|
||||
|
||||
@@ -518,8 +568,12 @@ module Harness.LanguageService {
|
||||
readDirectory(path: string, extension?: string): string[] {
|
||||
throw new Error("Not implemented Yet.");
|
||||
}
|
||||
|
||||
watchFile(fileName: string, callback: (fileName: string) => void): ts.FileWatcher {
|
||||
|
||||
watchFile(fileName: string, callback: (fileName: string) => void): ts.FileWatcher {
|
||||
return { close() { } };
|
||||
}
|
||||
|
||||
watchDirectory(path: string, callback: (path: string) => void, recursive?: boolean): ts.FileWatcher {
|
||||
return { close() { } };
|
||||
}
|
||||
|
||||
@@ -533,7 +587,7 @@ module Harness.LanguageService {
|
||||
msg(message: string) {
|
||||
return this.host.log(message);
|
||||
}
|
||||
|
||||
|
||||
loggingEnabled() {
|
||||
return true;
|
||||
}
|
||||
@@ -553,19 +607,21 @@ module Harness.LanguageService {
|
||||
startGroup(): void {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class ServerLanugageServiceAdapter implements LanguageServiceAdapter {
|
||||
private host: SessionClientHost;
|
||||
private client: ts.server.SessionClient;
|
||||
constructor(cancellationToken?: ts.CancellationToken, options?: ts.CompilerOptions) {
|
||||
constructor(cancellationToken?: ts.HostCancellationToken, options?: ts.CompilerOptions) {
|
||||
// This is the main host that tests use to direct tests
|
||||
var clientHost = new SessionClientHost(cancellationToken, options);
|
||||
var client = new ts.server.SessionClient(clientHost);
|
||||
const clientHost = new SessionClientHost(cancellationToken, options);
|
||||
const client = new ts.server.SessionClient(clientHost);
|
||||
|
||||
// This host is just a proxy for the clientHost, it uses the client
|
||||
// host to answer server queries about files on disk
|
||||
var serverHost = new SessionServerHost(clientHost);
|
||||
var server = new ts.server.Session(serverHost, serverHost);
|
||||
const serverHost = new SessionServerHost(clientHost);
|
||||
const server = new ts.server.Session(serverHost,
|
||||
Buffer ? Buffer.byteLength : (string: string, encoding?: string) => string.length,
|
||||
process.hrtime, serverHost);
|
||||
|
||||
// Fake the connection between the client and the server
|
||||
serverHost.writeMessage = client.onMessage.bind(client);
|
||||
|
||||
@@ -3,11 +3,15 @@ var fs: any = require('fs');
|
||||
var path: any = require('path');
|
||||
|
||||
function instrumentForRecording(fn: string, tscPath: string) {
|
||||
instrument(tscPath, 'ts.sys = Playback.wrapSystem(ts.sys); ts.sys.startRecord("' + fn + '");', 'ts.sys.endRecord();');
|
||||
instrument(tscPath, `
|
||||
ts.sys = Playback.wrapSystem(ts.sys);
|
||||
ts.sys.startRecord("${ fn }");`, `ts.sys.endRecord();`);
|
||||
}
|
||||
|
||||
function instrumentForReplay(logFilename: string, tscPath: string) {
|
||||
instrument(tscPath, 'ts.sys = Playback.wrapSystem(ts.sys); ts.sys.startReplay("' + logFilename + '");');
|
||||
instrument(tscPath, `
|
||||
ts.sys = Playback.wrapSystem(ts.sys);
|
||||
ts.sys.startReplay("${ logFilename }");`);
|
||||
}
|
||||
|
||||
function instrument(tscPath: string, prepareCode: string, cleanupCode: string = '') {
|
||||
|
||||
+142
-124
@@ -1,6 +1,7 @@
|
||||
/// <reference path="..\..\src\compiler\sys.ts" />
|
||||
/// <reference path="..\..\src\harness\harness.ts" />
|
||||
/// <reference path="..\..\src\harness\runnerbase.ts" />
|
||||
/* tslint:disable:no-null */
|
||||
|
||||
interface FileInformation {
|
||||
contents: string;
|
||||
@@ -12,6 +13,7 @@ interface FindFileResult {
|
||||
}
|
||||
|
||||
interface IOLog {
|
||||
timestamp: string;
|
||||
arguments: string[];
|
||||
executingPath: string;
|
||||
currentDirectory: string;
|
||||
@@ -58,6 +60,12 @@ interface IOLog {
|
||||
path: string;
|
||||
result?: string;
|
||||
}[];
|
||||
directoriesRead: {
|
||||
path: string,
|
||||
extension: string,
|
||||
exclude: string[],
|
||||
result: string[]
|
||||
}[];
|
||||
}
|
||||
|
||||
interface PlaybackControl {
|
||||
@@ -69,10 +77,10 @@ interface PlaybackControl {
|
||||
endRecord(): void;
|
||||
}
|
||||
|
||||
module Playback {
|
||||
var recordLog: IOLog = undefined;
|
||||
var replayLog: IOLog = undefined;
|
||||
var recordLogFileNameBase = '';
|
||||
namespace Playback {
|
||||
let recordLog: IOLog = undefined;
|
||||
let replayLog: IOLog = undefined;
|
||||
let recordLogFileNameBase = "";
|
||||
|
||||
interface Memoized<T> {
|
||||
(s: string): T;
|
||||
@@ -80,26 +88,29 @@ module Playback {
|
||||
}
|
||||
|
||||
function memoize<T>(func: (s: string) => T): Memoized<T> {
|
||||
var lookup: { [s: string]: T } = {};
|
||||
var run: Memoized<T> = <Memoized<T>>((s: string) => {
|
||||
let lookup: { [s: string]: T } = {};
|
||||
const run: Memoized<T> = <Memoized<T>>((s: string) => {
|
||||
if (lookup.hasOwnProperty(s)) return lookup[s];
|
||||
return lookup[s] = func(s);
|
||||
});
|
||||
run.reset = () => {
|
||||
lookup = null;
|
||||
};
|
||||
|
||||
|
||||
return run;
|
||||
}
|
||||
|
||||
export interface PlaybackIO extends Harness.IO, PlaybackControl { }
|
||||
|
||||
export interface PlaybackSystem extends ts.System, PlaybackControl { }
|
||||
|
||||
function createEmptyLog(): IOLog {
|
||||
return {
|
||||
timestamp: (new Date()).toString(),
|
||||
arguments: [],
|
||||
currentDirectory: '',
|
||||
currentDirectory: "",
|
||||
filesRead: [],
|
||||
directoriesRead: [],
|
||||
filesWritten: [],
|
||||
filesDeleted: [],
|
||||
filesAppended: [],
|
||||
@@ -109,12 +120,14 @@ module Playback {
|
||||
dirExists: [],
|
||||
dirsCreated: [],
|
||||
pathsResolved: [],
|
||||
executingPath: ''
|
||||
executingPath: ""
|
||||
};
|
||||
}
|
||||
|
||||
function initWrapper<T>(wrapper: PlaybackControl, underlying: T) {
|
||||
Object.keys(underlying).forEach(prop => {
|
||||
function initWrapper(wrapper: PlaybackSystem, underlying: ts.System): void;
|
||||
function initWrapper(wrapper: PlaybackIO, underlying: Harness.IO): void;
|
||||
function initWrapper(wrapper: PlaybackSystem | PlaybackIO, underlying: ts.System | Harness.IO): void {
|
||||
ts.forEach(Object.keys(underlying), prop => {
|
||||
(<any>wrapper)[prop] = (<any>underlying)[prop];
|
||||
});
|
||||
|
||||
@@ -134,6 +147,93 @@ module Playback {
|
||||
wrapper.startRecord = (fileNameBase) => {
|
||||
recordLogFileNameBase = fileNameBase;
|
||||
recordLog = createEmptyLog();
|
||||
|
||||
if (typeof underlying.args !== "function") {
|
||||
recordLog.arguments = <string[]>underlying.args;
|
||||
}
|
||||
};
|
||||
|
||||
wrapper.startReplayFromFile = logFn => {
|
||||
wrapper.startReplayFromString(underlying.readFile(logFn));
|
||||
};
|
||||
wrapper.endRecord = () => {
|
||||
if (recordLog !== undefined) {
|
||||
let i = 0;
|
||||
const fn = () => recordLogFileNameBase + i + ".json";
|
||||
while (underlying.fileExists(fn())) i++;
|
||||
underlying.writeFile(fn(), JSON.stringify(recordLog));
|
||||
recordLog = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
wrapper.fileExists = recordReplay(wrapper.fileExists, underlying)(
|
||||
path => callAndRecord(underlying.fileExists(path), recordLog.fileExists, { path }),
|
||||
memoize(path => {
|
||||
// If we read from the file, it must exist
|
||||
if (findResultByPath(wrapper, replayLog.filesRead, path, null) !== null) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return findResultByFields(replayLog.fileExists, { path }, /*defaultValue*/ false);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
wrapper.getExecutingFilePath = () => {
|
||||
if (replayLog !== undefined) {
|
||||
return replayLog.executingPath;
|
||||
}
|
||||
else if (recordLog !== undefined) {
|
||||
return recordLog.executingPath = underlying.getExecutingFilePath();
|
||||
}
|
||||
else {
|
||||
return underlying.getExecutingFilePath();
|
||||
}
|
||||
};
|
||||
|
||||
wrapper.getCurrentDirectory = () => {
|
||||
if (replayLog !== undefined) {
|
||||
return replayLog.currentDirectory || "";
|
||||
}
|
||||
else if (recordLog !== undefined) {
|
||||
return recordLog.currentDirectory = underlying.getCurrentDirectory();
|
||||
}
|
||||
else {
|
||||
return underlying.getCurrentDirectory();
|
||||
}
|
||||
};
|
||||
|
||||
wrapper.resolvePath = recordReplay(wrapper.resolvePath, underlying)(
|
||||
path => callAndRecord(underlying.resolvePath(path), recordLog.pathsResolved, { path }),
|
||||
memoize(path => findResultByFields(replayLog.pathsResolved, { path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog.currentDirectory ? replayLog.currentDirectory + "/" + path : ts.normalizeSlashes(path))));
|
||||
|
||||
wrapper.readFile = recordReplay(wrapper.readFile, underlying)(
|
||||
path => {
|
||||
const result = underlying.readFile(path);
|
||||
const logEntry = { path, codepage: 0, result: { contents: result, codepage: 0 } };
|
||||
recordLog.filesRead.push(logEntry);
|
||||
return result;
|
||||
},
|
||||
memoize(path => findResultByPath(wrapper, replayLog.filesRead, path).contents));
|
||||
|
||||
wrapper.readDirectory = recordReplay(wrapper.readDirectory, underlying)(
|
||||
(path, extension, exclude) => {
|
||||
const result = (<ts.System>underlying).readDirectory(path, extension, exclude);
|
||||
const logEntry = { path, extension, exclude, result };
|
||||
recordLog.directoriesRead.push(logEntry);
|
||||
return result;
|
||||
},
|
||||
(path, extension, exclude) => findResultByPath(wrapper, replayLog.directoriesRead.filter(d => d.extension === extension && ts.arrayIsEqualTo(d.exclude, exclude)), path));
|
||||
|
||||
wrapper.writeFile = recordReplay(wrapper.writeFile, underlying)(
|
||||
(path, contents) => callAndRecord(underlying.writeFile(path, contents), recordLog.filesWritten, { path, contents, bom: false }),
|
||||
(path, contents) => noOpReplay("writeFile"));
|
||||
|
||||
wrapper.exit = (exitCode) => {
|
||||
if (recordLog !== undefined) {
|
||||
wrapper.endRecord();
|
||||
}
|
||||
underlying.exit(exitCode);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -142,9 +242,11 @@ module Playback {
|
||||
return <any>(function () {
|
||||
if (replayLog !== undefined) {
|
||||
return replay.apply(undefined, arguments);
|
||||
} else if (recordLog !== undefined) {
|
||||
}
|
||||
else if (recordLog !== undefined) {
|
||||
return record.apply(undefined, arguments);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return original.apply(underlying, arguments);
|
||||
}
|
||||
});
|
||||
@@ -161,152 +263,68 @@ module Playback {
|
||||
}
|
||||
|
||||
function findResultByFields<T>(logArray: { result?: T }[], expectedFields: {}, defaultValue?: T): T {
|
||||
var predicate = (entry: { result?: T }) => {
|
||||
const predicate = (entry: { result?: T }) => {
|
||||
return Object.getOwnPropertyNames(expectedFields).every((name) => (<any>entry)[name] === (<any>expectedFields)[name]);
|
||||
};
|
||||
var results = logArray.filter(entry => predicate(entry));
|
||||
const results = logArray.filter(entry => predicate(entry));
|
||||
if (results.length === 0) {
|
||||
if (defaultValue !== undefined) {
|
||||
return defaultValue;
|
||||
} else {
|
||||
throw new Error('No matching result in log array for: ' + JSON.stringify(expectedFields));
|
||||
}
|
||||
else {
|
||||
throw new Error("No matching result in log array for: " + JSON.stringify(expectedFields));
|
||||
}
|
||||
}
|
||||
return results[0].result;
|
||||
}
|
||||
|
||||
function findResultByPath<T>(wrapper: { resolvePath(s: string): string }, logArray: { path: string; result?: T }[], expectedPath: string, defaultValue?: T): T {
|
||||
var normalizedName = ts.normalizeSlashes(expectedPath).toLowerCase();
|
||||
const normalizedName = ts.normalizePath(expectedPath).toLowerCase();
|
||||
// Try to find the result through normal fileName
|
||||
for (var i = 0; i < logArray.length; i++) {
|
||||
for (let i = 0; i < logArray.length; i++) {
|
||||
if (ts.normalizeSlashes(logArray[i].path).toLowerCase() === normalizedName) {
|
||||
return logArray[i].result;
|
||||
}
|
||||
}
|
||||
// Fallback, try to resolve the target paths as well
|
||||
if (replayLog.pathsResolved.length > 0) {
|
||||
var normalizedResolvedName = wrapper.resolvePath(expectedPath).toLowerCase();
|
||||
for (var i = 0; i < logArray.length; i++) {
|
||||
const normalizedResolvedName = wrapper.resolvePath(expectedPath).toLowerCase();
|
||||
for (let i = 0; i < logArray.length; i++) {
|
||||
if (wrapper.resolvePath(logArray[i].path).toLowerCase() === normalizedResolvedName) {
|
||||
return logArray[i].result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we got here, we didn't find a match
|
||||
if (defaultValue === undefined) {
|
||||
throw new Error('No matching result in log array for path: ' + expectedPath);
|
||||
} else {
|
||||
throw new Error("No matching result in log array for path: " + expectedPath);
|
||||
}
|
||||
else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
var pathEquivCache: any = {};
|
||||
function pathsAreEquivalent(left: string, right: string, wrapper: { resolvePath(s: string): string }) {
|
||||
var key = left + '-~~-' + right;
|
||||
function areSame(a: string, b: string) {
|
||||
return ts.normalizeSlashes(a).toLowerCase() === ts.normalizeSlashes(b).toLowerCase();
|
||||
}
|
||||
function check() {
|
||||
if (Harness.Path.getFileName(left).toLowerCase() === Harness.Path.getFileName(right).toLowerCase()) {
|
||||
return areSame(left, right) || areSame(wrapper.resolvePath(left), right) || areSame(left, wrapper.resolvePath(right)) || areSame(wrapper.resolvePath(left), wrapper.resolvePath(right));
|
||||
}
|
||||
}
|
||||
if (pathEquivCache.hasOwnProperty(key)) {
|
||||
return pathEquivCache[key];
|
||||
} else {
|
||||
return pathEquivCache[key] = check();
|
||||
}
|
||||
}
|
||||
|
||||
function noOpReplay(name: string) {
|
||||
//console.log("Swallowed write operation during replay: " + name);
|
||||
// console.log("Swallowed write operation during replay: " + name);
|
||||
}
|
||||
|
||||
export function wrapSystem(underlying: ts.System): PlaybackSystem {
|
||||
var wrapper: PlaybackSystem = <any>{};
|
||||
export function wrapIO(underlying: Harness.IO): PlaybackIO {
|
||||
const wrapper: PlaybackIO = <any>{};
|
||||
initWrapper(wrapper, underlying);
|
||||
|
||||
wrapper.startReplayFromFile = logFn => {
|
||||
wrapper.startReplayFromString(underlying.readFile(logFn));
|
||||
};
|
||||
wrapper.endRecord = () => {
|
||||
if (recordLog !== undefined) {
|
||||
var i = 0;
|
||||
var fn = () => recordLogFileNameBase + i + '.json';
|
||||
while (underlying.fileExists(fn())) i++;
|
||||
underlying.writeFile(fn(), JSON.stringify(recordLog));
|
||||
recordLog = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
Object.defineProperty(wrapper, 'args', {
|
||||
get() {
|
||||
if (replayLog !== undefined) {
|
||||
return replayLog.arguments;
|
||||
} else if (recordLog !== undefined) {
|
||||
recordLog.arguments = underlying.args;
|
||||
}
|
||||
return underlying.args;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
wrapper.fileExists = recordReplay(wrapper.fileExists, underlying)(
|
||||
(path) => callAndRecord(underlying.fileExists(path), recordLog.fileExists, { path: path }),
|
||||
memoize((path) => {
|
||||
// If we read from the file, it must exist
|
||||
if (findResultByPath(wrapper, replayLog.filesRead, path, null) !== null) {
|
||||
return true;
|
||||
} else {
|
||||
return findResultByFields(replayLog.fileExists, { path: path }, false);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
wrapper.getExecutingFilePath = () => {
|
||||
if (replayLog !== undefined) {
|
||||
return replayLog.executingPath;
|
||||
} else if (recordLog !== undefined) {
|
||||
return recordLog.executingPath = underlying.getExecutingFilePath();
|
||||
} else {
|
||||
return underlying.getExecutingFilePath();
|
||||
}
|
||||
};
|
||||
|
||||
wrapper.getCurrentDirectory = () => {
|
||||
if (replayLog !== undefined) {
|
||||
return replayLog.currentDirectory || '';
|
||||
} else if (recordLog !== undefined) {
|
||||
return recordLog.currentDirectory = underlying.getCurrentDirectory();
|
||||
} else {
|
||||
return underlying.getCurrentDirectory();
|
||||
}
|
||||
};
|
||||
|
||||
wrapper.resolvePath = recordReplay(wrapper.resolvePath, underlying)(
|
||||
(path) => callAndRecord(underlying.resolvePath(path), recordLog.pathsResolved, { path: path }),
|
||||
memoize((path) => findResultByFields(replayLog.pathsResolved, { path: path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog.currentDirectory ? replayLog.currentDirectory + '/' + path : ts.normalizeSlashes(path))));
|
||||
|
||||
wrapper.readFile = recordReplay(wrapper.readFile, underlying)(
|
||||
(path) => {
|
||||
var result = underlying.readFile(path);
|
||||
var logEntry = { path: path, codepage: 0, result: { contents: result, codepage: 0 } };
|
||||
recordLog.filesRead.push(logEntry);
|
||||
return result;
|
||||
},
|
||||
memoize((path) => findResultByPath(wrapper, replayLog.filesRead, path).contents));
|
||||
|
||||
wrapper.writeFile = recordReplay(wrapper.writeFile, underlying)(
|
||||
(path, contents) => callAndRecord(underlying.writeFile(path, contents), recordLog.filesWritten, { path: path, contents: contents, bom: false }),
|
||||
(path, contents) => noOpReplay('writeFile'));
|
||||
|
||||
wrapper.exit = (exitCode) => {
|
||||
if (recordLog !== undefined) {
|
||||
wrapper.endRecord();
|
||||
}
|
||||
underlying.exit(exitCode);
|
||||
};
|
||||
wrapper.directoryName = (path): string => { throw new Error("NotSupported"); };
|
||||
wrapper.createDirectory = (path): void => { throw new Error("NotSupported"); };
|
||||
wrapper.directoryExists = (path): boolean => { throw new Error("NotSupported"); };
|
||||
wrapper.deleteFile = (path): void => { throw new Error("NotSupported"); };
|
||||
wrapper.listFiles = (path, filter, options): string[] => { throw new Error("NotSupported"); };
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
export function wrapSystem(underlying: ts.System): PlaybackSystem {
|
||||
const wrapper: PlaybackSystem = <any>{};
|
||||
initWrapper(wrapper, underlying);
|
||||
return wrapper;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
/// <reference path="exec.ts" />
|
||||
/// <reference path="generate.ts" />
|
||||
/// <reference path="harness.ts" />
|
||||
/// <reference path="diff.ts" />
|
||||
+266
-202
@@ -1,24 +1,17 @@
|
||||
///<reference path="harness.ts" />
|
||||
///<reference path="runnerbase.ts" />
|
||||
/* tslint:disable:no-null */
|
||||
|
||||
// Test case is json of below type in tests/cases/project/
|
||||
interface ProjectRunnerTestCase {
|
||||
scenario: string;
|
||||
projectRoot: string; // project where it lives - this also is the current directory when compiling
|
||||
inputFiles: string[]; // list of input files to be given to program
|
||||
out?: string; // --out
|
||||
outDir?: string; // --outDir
|
||||
sourceMap?: boolean; // --map
|
||||
mapRoot?: string; // --mapRoot
|
||||
resolveMapRoot?: boolean; // should we resolve this map root and give compiler the absolute disk path as map root?
|
||||
sourceRoot?: string; // --sourceRoot
|
||||
resolveSourceRoot?: boolean; // should we resolve this source root and give compiler the absolute disk path as map root?
|
||||
declaration?: boolean; // --d
|
||||
baselineCheck?: boolean; // Verify the baselines of output files, if this is false, we will write to output to the disk but there is no verification of baselines
|
||||
runTest?: boolean; // Run the resulting test
|
||||
bug?: string; // If there is any bug associated with this test case
|
||||
noResolve?: boolean;
|
||||
rootDir?: string; // --rootDir
|
||||
}
|
||||
|
||||
interface ProjectRunnerTestCaseResolutionInfo extends ProjectRunnerTestCase {
|
||||
@@ -33,20 +26,20 @@ interface BatchCompileProjectTestCaseEmittedFile extends Harness.Compiler.Genera
|
||||
|
||||
interface CompileProjectFilesResult {
|
||||
moduleKind: ts.ModuleKind;
|
||||
program: ts.Program;
|
||||
program?: ts.Program;
|
||||
compilerOptions?: ts.CompilerOptions;
|
||||
errors: ts.Diagnostic[];
|
||||
sourceMapData: ts.SourceMapData[];
|
||||
sourceMapData?: ts.SourceMapData[];
|
||||
}
|
||||
|
||||
interface BatchCompileProjectTestCaseResult extends CompileProjectFilesResult {
|
||||
outputFiles: BatchCompileProjectTestCaseEmittedFile[];
|
||||
nonSubfolderDiskFiles: number;
|
||||
outputFiles?: BatchCompileProjectTestCaseEmittedFile[];
|
||||
}
|
||||
|
||||
class ProjectRunner extends RunnerBase {
|
||||
public initializeTests() {
|
||||
if (this.tests.length === 0) {
|
||||
var testFiles = this.enumerateFiles("tests/cases/project", /\.json$/, { recursive: true });
|
||||
const testFiles = this.enumerateFiles("tests/cases/project", /\.json$/, { recursive: true });
|
||||
testFiles.forEach(fn => {
|
||||
fn = fn.replace(/\\/g, "/");
|
||||
this.runProjectTestCase(fn);
|
||||
@@ -58,22 +51,23 @@ class ProjectRunner extends RunnerBase {
|
||||
}
|
||||
|
||||
private runProjectTestCase(testCaseFileName: string) {
|
||||
var testCase: ProjectRunnerTestCase;
|
||||
let testCase: ProjectRunnerTestCase & ts.CompilerOptions;
|
||||
|
||||
let testFileText: string = null;
|
||||
try {
|
||||
var testFileText = ts.sys.readFile(testCaseFileName);
|
||||
testFileText = Harness.IO.readFile(testCaseFileName);
|
||||
}
|
||||
catch (e) {
|
||||
assert(false, "Unable to open testcase file: " + testCaseFileName + ": " + e.message);
|
||||
}
|
||||
|
||||
try {
|
||||
testCase = <ProjectRunnerTestCase>JSON.parse(testFileText);
|
||||
testCase = <ProjectRunnerTestCase & ts.CompilerOptions>JSON.parse(testFileText);
|
||||
}
|
||||
catch (e) {
|
||||
assert(false, "Testcase: " + testCaseFileName + " does not contain valid json format: " + e.message);
|
||||
}
|
||||
var testCaseJustName = testCaseFileName.replace(/^.*[\\\/]/, '').replace(/\.json/, "");
|
||||
let testCaseJustName = testCaseFileName.replace(/^.*[\\\/]/, "").replace(/\.json/, "");
|
||||
|
||||
function moduleNameToString(moduleKind: ts.ModuleKind) {
|
||||
return moduleKind === ts.ModuleKind.AMD
|
||||
@@ -89,7 +83,7 @@ class ProjectRunner extends RunnerBase {
|
||||
}
|
||||
|
||||
// When test case output goes to tests/baselines/local/projectOutput/testCaseName/moduleKind/
|
||||
// We have these two separate locations because when comparing baselines the baseline verifier will delete the existing file
|
||||
// We have these two separate locations because when comparing baselines the baseline verifier will delete the existing file
|
||||
// so even if it was created by compiler in that location, the file will be deleted by verified before we can read it
|
||||
// so lets keep these two locations separate
|
||||
function getProjectOutputFolder(fileName: string, moduleKind: ts.ModuleKind) {
|
||||
@@ -97,9 +91,9 @@ class ProjectRunner extends RunnerBase {
|
||||
}
|
||||
|
||||
function cleanProjectUrl(url: string) {
|
||||
var diskProjectPath = ts.normalizeSlashes(ts.sys.resolvePath(testCase.projectRoot));
|
||||
var projectRootUrl = "file:///" + diskProjectPath;
|
||||
var normalizedProjectRoot = ts.normalizeSlashes(testCase.projectRoot);
|
||||
let diskProjectPath = ts.normalizeSlashes(Harness.IO.resolvePath(testCase.projectRoot));
|
||||
let projectRootUrl = "file:///" + diskProjectPath;
|
||||
const normalizedProjectRoot = ts.normalizeSlashes(testCase.projectRoot);
|
||||
diskProjectPath = diskProjectPath.substr(0, diskProjectPath.lastIndexOf(normalizedProjectRoot));
|
||||
projectRootUrl = projectRootUrl.substr(0, projectRootUrl.lastIndexOf(normalizedProjectRoot));
|
||||
if (url && url.length) {
|
||||
@@ -110,6 +104,7 @@ class ProjectRunner extends RunnerBase {
|
||||
else if (url.indexOf(diskProjectPath) === 0) {
|
||||
// Replace the disk specific path into the project root path
|
||||
url = url.substr(diskProjectPath.length);
|
||||
// TODO: should be '!=='?
|
||||
if (url.charCodeAt(0) != ts.CharacterCodes.slash) {
|
||||
url = "/" + url;
|
||||
}
|
||||
@@ -120,24 +115,25 @@ class ProjectRunner extends RunnerBase {
|
||||
}
|
||||
|
||||
function getCurrentDirectory() {
|
||||
return ts.sys.resolvePath(testCase.projectRoot);
|
||||
return Harness.IO.resolvePath(testCase.projectRoot);
|
||||
}
|
||||
|
||||
function compileProjectFiles(moduleKind: ts.ModuleKind, getInputFiles: ()=> string[],
|
||||
getSourceFileText: (fileName: string) => string,
|
||||
writeFile: (fileName: string, data: string, writeByteOrderMark: boolean) => void): CompileProjectFilesResult {
|
||||
function compileProjectFiles(moduleKind: ts.ModuleKind, getInputFiles: () => string[],
|
||||
getSourceFileTextImpl: (fileName: string) => string,
|
||||
writeFile: (fileName: string, data: string, writeByteOrderMark: boolean) => void,
|
||||
compilerOptions: ts.CompilerOptions): CompileProjectFilesResult {
|
||||
|
||||
var program = ts.createProgram(getInputFiles(), createCompilerOptions(), createCompilerHost());
|
||||
var errors = ts.getPreEmitDiagnostics(program);
|
||||
const program = ts.createProgram(getInputFiles(), compilerOptions, createCompilerHost());
|
||||
let errors = ts.getPreEmitDiagnostics(program);
|
||||
|
||||
var emitResult = program.emit();
|
||||
const emitResult = program.emit();
|
||||
errors = ts.concatenate(errors, emitResult.diagnostics);
|
||||
var sourceMapData = emitResult.sourceMaps;
|
||||
const sourceMapData = emitResult.sourceMaps;
|
||||
|
||||
// Clean up source map data that will be used in baselining
|
||||
if (sourceMapData) {
|
||||
for (var i = 0; i < sourceMapData.length; i++) {
|
||||
for (var j = 0; j < sourceMapData[i].sourceMapSources.length; j++) {
|
||||
for (let i = 0; i < sourceMapData.length; i++) {
|
||||
for (let j = 0; j < sourceMapData[i].sourceMapSources.length; j++) {
|
||||
sourceMapData[i].sourceMapSources[j] = cleanProjectUrl(sourceMapData[i].sourceMapSources[j]);
|
||||
}
|
||||
sourceMapData[i].jsSourceMappingURL = cleanProjectUrl(sourceMapData[i].jsSourceMappingURL);
|
||||
@@ -152,27 +148,18 @@ class ProjectRunner extends RunnerBase {
|
||||
sourceMapData
|
||||
};
|
||||
|
||||
function createCompilerOptions(): ts.CompilerOptions {
|
||||
return {
|
||||
declaration: !!testCase.declaration,
|
||||
sourceMap: !!testCase.sourceMap,
|
||||
out: testCase.out,
|
||||
outDir: testCase.outDir,
|
||||
mapRoot: testCase.resolveMapRoot && testCase.mapRoot ? ts.sys.resolvePath(testCase.mapRoot) : testCase.mapRoot,
|
||||
sourceRoot: testCase.resolveSourceRoot && testCase.sourceRoot ? ts.sys.resolvePath(testCase.sourceRoot) : testCase.sourceRoot,
|
||||
module: moduleKind,
|
||||
noResolve: testCase.noResolve,
|
||||
rootDir: testCase.rootDir
|
||||
};
|
||||
function getSourceFileText(fileName: string): string {
|
||||
const text = getSourceFileTextImpl(fileName);
|
||||
return text !== undefined ? text : getSourceFileTextImpl(ts.getNormalizedAbsolutePath(fileName, getCurrentDirectory()));
|
||||
}
|
||||
|
||||
function getSourceFile(fileName: string, languageVersion: ts.ScriptTarget): ts.SourceFile {
|
||||
var sourceFile: ts.SourceFile = undefined;
|
||||
let sourceFile: ts.SourceFile = undefined;
|
||||
if (fileName === Harness.Compiler.defaultLibFileName) {
|
||||
sourceFile = languageVersion === ts.ScriptTarget.ES6 ? Harness.Compiler.defaultES6LibSourceFile : Harness.Compiler.defaultLibSourceFile;
|
||||
}
|
||||
else {
|
||||
var text = getSourceFileText(fileName);
|
||||
const text = getSourceFileText(fileName);
|
||||
if (text !== undefined) {
|
||||
sourceFile = Harness.Compiler.createSourceFileAndAssertInvariants(fileName, text, languageVersion);
|
||||
}
|
||||
@@ -188,32 +175,117 @@ class ProjectRunner extends RunnerBase {
|
||||
writeFile,
|
||||
getCurrentDirectory,
|
||||
getCanonicalFileName: Harness.Compiler.getCanonicalFileName,
|
||||
useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,
|
||||
getNewLine: () => ts.sys.newLine
|
||||
useCaseSensitiveFileNames: () => Harness.IO.useCaseSensitiveFileNames(),
|
||||
getNewLine: () => Harness.IO.newLine(),
|
||||
fileExists: fileName => fileName === Harness.Compiler.defaultLibFileName || getSourceFileText(fileName) !== undefined,
|
||||
readFile: fileName => Harness.IO.readFile(fileName)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function batchCompilerProjectTestCase(moduleKind: ts.ModuleKind): BatchCompileProjectTestCaseResult{
|
||||
var nonSubfolderDiskFiles = 0;
|
||||
|
||||
var outputFiles: BatchCompileProjectTestCaseEmittedFile[] = [];
|
||||
function batchCompilerProjectTestCase(moduleKind: ts.ModuleKind): BatchCompileProjectTestCaseResult {
|
||||
let nonSubfolderDiskFiles = 0;
|
||||
|
||||
var projectCompilerResult = compileProjectFiles(moduleKind, () => testCase.inputFiles, getSourceFileText, writeFile);
|
||||
const outputFiles: BatchCompileProjectTestCaseEmittedFile[] = [];
|
||||
let inputFiles = testCase.inputFiles;
|
||||
let compilerOptions = createCompilerOptions();
|
||||
|
||||
let configFileName: string;
|
||||
if (compilerOptions.project) {
|
||||
// Parse project
|
||||
configFileName = ts.normalizePath(ts.combinePaths(compilerOptions.project, "tsconfig.json"));
|
||||
assert(!inputFiles || inputFiles.length === 0, "cannot specify input files and project option together");
|
||||
}
|
||||
else if (!inputFiles || inputFiles.length === 0) {
|
||||
configFileName = ts.findConfigFile("", fileExists);
|
||||
}
|
||||
|
||||
if (configFileName) {
|
||||
const result = ts.readConfigFile(configFileName, getSourceFileText);
|
||||
if (result.error) {
|
||||
return {
|
||||
moduleKind,
|
||||
errors: [result.error]
|
||||
};
|
||||
}
|
||||
|
||||
const configObject = result.config;
|
||||
const configParseResult = ts.parseJsonConfigFileContent(configObject, { readDirectory }, ts.getDirectoryPath(configFileName), compilerOptions);
|
||||
if (configParseResult.errors.length > 0) {
|
||||
return {
|
||||
moduleKind,
|
||||
errors: configParseResult.errors
|
||||
};
|
||||
}
|
||||
inputFiles = configParseResult.fileNames;
|
||||
compilerOptions = configParseResult.options;
|
||||
}
|
||||
|
||||
const projectCompilerResult = compileProjectFiles(moduleKind, () => inputFiles, getSourceFileText, writeFile, compilerOptions);
|
||||
return {
|
||||
moduleKind,
|
||||
program: projectCompilerResult.program,
|
||||
compilerOptions,
|
||||
sourceMapData: projectCompilerResult.sourceMapData,
|
||||
outputFiles,
|
||||
errors: projectCompilerResult.errors,
|
||||
nonSubfolderDiskFiles,
|
||||
};
|
||||
|
||||
function createCompilerOptions() {
|
||||
// Set the special options that depend on other testcase options
|
||||
const compilerOptions: ts.CompilerOptions = {
|
||||
mapRoot: testCase.resolveMapRoot && testCase.mapRoot ? Harness.IO.resolvePath(testCase.mapRoot) : testCase.mapRoot,
|
||||
sourceRoot: testCase.resolveSourceRoot && testCase.sourceRoot ? Harness.IO.resolvePath(testCase.sourceRoot) : testCase.sourceRoot,
|
||||
module: moduleKind,
|
||||
moduleResolution: ts.ModuleResolutionKind.Classic, // currently all tests use classic module resolution kind, this will change in the future
|
||||
};
|
||||
// Set the values specified using json
|
||||
const optionNameMap: ts.Map<ts.CommandLineOption> = {};
|
||||
ts.forEach(ts.optionDeclarations, option => {
|
||||
optionNameMap[option.name] = option;
|
||||
});
|
||||
for (const name in testCase) {
|
||||
if (name !== "mapRoot" && name !== "sourceRoot" && ts.hasProperty(optionNameMap, name)) {
|
||||
const option = optionNameMap[name];
|
||||
const optType = option.type;
|
||||
let value = <any>testCase[name];
|
||||
if (typeof optType !== "string") {
|
||||
const key = value.toLowerCase();
|
||||
if (ts.hasProperty(optType, key)) {
|
||||
value = optType[key];
|
||||
}
|
||||
}
|
||||
compilerOptions[option.name] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return compilerOptions;
|
||||
}
|
||||
|
||||
function getFileNameInTheProjectTest(fileName: string): string {
|
||||
return ts.isRootedDiskPath(fileName)
|
||||
? fileName
|
||||
: ts.normalizeSlashes(testCase.projectRoot) + "/" + ts.normalizeSlashes(fileName);
|
||||
}
|
||||
|
||||
function readDirectory(rootDir: string, extension: string, exclude: string[]): string[] {
|
||||
const harnessReadDirectoryResult = Harness.IO.readDirectory(getFileNameInTheProjectTest(rootDir), extension, exclude);
|
||||
const result: string[] = [];
|
||||
for (let i = 0; i < harnessReadDirectoryResult.length; i++) {
|
||||
result[i] = ts.getRelativePathToDirectoryOrUrl(testCase.projectRoot, harnessReadDirectoryResult[i],
|
||||
getCurrentDirectory(), Harness.Compiler.getCanonicalFileName, /*isAbsolutePathAnUrl*/ false);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function fileExists(fileName: string): boolean {
|
||||
return Harness.IO.fileExists(getFileNameInTheProjectTest(fileName));
|
||||
}
|
||||
|
||||
function getSourceFileText(fileName: string): string {
|
||||
let text: string = undefined;
|
||||
try {
|
||||
var text = ts.sys.readFile(ts.isRootedDiskPath(fileName)
|
||||
? fileName
|
||||
: ts.normalizeSlashes(testCase.projectRoot) + "/" + ts.normalizeSlashes(fileName));
|
||||
text = Harness.IO.readFile(getFileNameInTheProjectTest(fileName));
|
||||
}
|
||||
catch (e) {
|
||||
// text doesn't get defined.
|
||||
@@ -222,86 +294,98 @@ class ProjectRunner extends RunnerBase {
|
||||
}
|
||||
|
||||
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean) {
|
||||
var diskFileName = ts.isRootedDiskPath(fileName)
|
||||
// convert file name to rooted name
|
||||
// if filename is not rooted - concat it with project root and then expand project root relative to current directory
|
||||
const diskFileName = ts.isRootedDiskPath(fileName)
|
||||
? fileName
|
||||
: ts.normalizeSlashes(testCase.projectRoot) + "/" + ts.normalizeSlashes(fileName);
|
||||
: Harness.IO.resolvePath(ts.normalizeSlashes(testCase.projectRoot) + "/" + ts.normalizeSlashes(fileName));
|
||||
|
||||
var diskRelativeName = ts.getRelativePathToDirectoryOrUrl(testCase.projectRoot, diskFileName,
|
||||
getCurrentDirectory(), Harness.Compiler.getCanonicalFileName, /*isAbsolutePathAnUrl*/ false);
|
||||
const currentDirectory = getCurrentDirectory();
|
||||
// compute file name relative to current directory (expanded project root)
|
||||
let diskRelativeName = ts.getRelativePathToDirectoryOrUrl(currentDirectory, diskFileName, currentDirectory, Harness.Compiler.getCanonicalFileName, /*isAbsolutePathAnUrl*/ false);
|
||||
if (ts.isRootedDiskPath(diskRelativeName) || diskRelativeName.substr(0, 3) === "../") {
|
||||
// If the generated output file resides in the parent folder or is rooted path,
|
||||
// If the generated output file resides in the parent folder or is rooted path,
|
||||
// we need to instead create files that can live in the project reference folder
|
||||
// but make sure extension of these files matches with the fileName the compiler asked to write
|
||||
diskRelativeName = "diskFile" + nonSubfolderDiskFiles++ +
|
||||
diskRelativeName = "diskFile" + nonSubfolderDiskFiles +
|
||||
(Harness.Compiler.isDTS(fileName) ? ".d.ts" :
|
||||
Harness.Compiler.isJS(fileName) ? ".js" : ".js.map");
|
||||
nonSubfolderDiskFiles++;
|
||||
}
|
||||
|
||||
if (Harness.Compiler.isJS(fileName)) {
|
||||
// Make sure if there is URl we have it cleaned up
|
||||
var indexOfSourceMapUrl = data.lastIndexOf("//# sourceMappingURL=");
|
||||
if (indexOfSourceMapUrl != -1) {
|
||||
const indexOfSourceMapUrl = data.lastIndexOf("//# sourceMappingURL=");
|
||||
if (indexOfSourceMapUrl !== -1) {
|
||||
data = data.substring(0, indexOfSourceMapUrl + 21) + cleanProjectUrl(data.substring(indexOfSourceMapUrl + 21));
|
||||
}
|
||||
}
|
||||
else if (Harness.Compiler.isJSMap(fileName)) {
|
||||
// Make sure sources list is cleaned
|
||||
var sourceMapData = JSON.parse(data);
|
||||
for (var i = 0; i < sourceMapData.sources.length; i++) {
|
||||
const sourceMapData = JSON.parse(data);
|
||||
for (let i = 0; i < sourceMapData.sources.length; i++) {
|
||||
sourceMapData.sources[i] = cleanProjectUrl(sourceMapData.sources[i]);
|
||||
}
|
||||
sourceMapData.sourceRoot = cleanProjectUrl(sourceMapData.sourceRoot);
|
||||
data = JSON.stringify(sourceMapData);
|
||||
}
|
||||
|
||||
var outputFilePath = getProjectOutputFolder(diskRelativeName, moduleKind);
|
||||
const outputFilePath = getProjectOutputFolder(diskRelativeName, moduleKind);
|
||||
// Actual writing of file as in tc.ts
|
||||
function ensureDirectoryStructure(directoryname: string) {
|
||||
if (directoryname) {
|
||||
if (!ts.sys.directoryExists(directoryname)) {
|
||||
if (!Harness.IO.directoryExists(directoryname)) {
|
||||
ensureDirectoryStructure(ts.getDirectoryPath(directoryname));
|
||||
ts.sys.createDirectory(directoryname);
|
||||
Harness.IO.createDirectory(directoryname);
|
||||
}
|
||||
}
|
||||
}
|
||||
ensureDirectoryStructure(ts.getDirectoryPath(ts.normalizePath(outputFilePath)));
|
||||
ts.sys.writeFile(outputFilePath, data, writeByteOrderMark);
|
||||
Harness.IO.writeFile(outputFilePath, data);
|
||||
|
||||
outputFiles.push({ emittedFileName: fileName, code: data, fileName: diskRelativeName, writeByteOrderMark: writeByteOrderMark });
|
||||
}
|
||||
}
|
||||
|
||||
function compileCompileDTsFiles(compilerResult: BatchCompileProjectTestCaseResult) {
|
||||
var allInputFiles: { emittedFileName: string; code: string; }[] = [];
|
||||
var compilerOptions = compilerResult.program.getCompilerOptions();
|
||||
const allInputFiles: { emittedFileName: string; code: string; }[] = [];
|
||||
if (!compilerResult.program) {
|
||||
return;
|
||||
}
|
||||
const compilerOptions = compilerResult.program.getCompilerOptions();
|
||||
|
||||
ts.forEach(compilerResult.program.getSourceFiles(), sourceFile => {
|
||||
if (Harness.Compiler.isDTS(sourceFile.fileName)) {
|
||||
if (ts.isDeclarationFile(sourceFile)) {
|
||||
allInputFiles.unshift({ emittedFileName: sourceFile.fileName, code: sourceFile.text });
|
||||
}
|
||||
else if (ts.shouldEmitToOwnFile(sourceFile, compilerResult.program.getCompilerOptions())) {
|
||||
else if (!(compilerOptions.outFile || compilerOptions.out)) {
|
||||
let emitOutputFilePathWithoutExtension: string = undefined;
|
||||
if (compilerOptions.outDir) {
|
||||
var sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, compilerResult.program.getCurrentDirectory());
|
||||
let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, compilerResult.program.getCurrentDirectory());
|
||||
sourceFilePath = sourceFilePath.replace(compilerResult.program.getCommonSourceDirectory(), "");
|
||||
var emitOutputFilePathWithoutExtension = ts.removeFileExtension(ts.combinePaths(compilerOptions.outDir, sourceFilePath));
|
||||
emitOutputFilePathWithoutExtension = ts.removeFileExtension(ts.combinePaths(compilerOptions.outDir, sourceFilePath));
|
||||
}
|
||||
else {
|
||||
var emitOutputFilePathWithoutExtension = ts.removeFileExtension(sourceFile.fileName);
|
||||
emitOutputFilePathWithoutExtension = ts.removeFileExtension(sourceFile.fileName);
|
||||
}
|
||||
|
||||
var outputDtsFileName = emitOutputFilePathWithoutExtension + ".d.ts";
|
||||
allInputFiles.unshift(findOutpuDtsFile(outputDtsFileName));
|
||||
const outputDtsFileName = emitOutputFilePathWithoutExtension + ".d.ts";
|
||||
const file = findOutpuDtsFile(outputDtsFileName);
|
||||
if (file) {
|
||||
allInputFiles.unshift(file);
|
||||
}
|
||||
}
|
||||
else {
|
||||
var outputDtsFileName = ts.removeFileExtension(compilerOptions.out) + ".d.ts";
|
||||
var outputDtsFile = findOutpuDtsFile(outputDtsFileName);
|
||||
const outputDtsFileName = ts.removeFileExtension(compilerOptions.outFile || compilerOptions.out) + ".d.ts";
|
||||
const outputDtsFile = findOutpuDtsFile(outputDtsFileName);
|
||||
if (!ts.contains(allInputFiles, outputDtsFile)) {
|
||||
allInputFiles.unshift(outputDtsFile);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return compileProjectFiles(compilerResult.moduleKind,getInputFiles, getSourceFileText, writeFile);
|
||||
// Dont allow config files since we are compiling existing source options
|
||||
return compileProjectFiles(compilerResult.moduleKind, getInputFiles, getSourceFileText, writeFile, compilerResult.compilerOptions);
|
||||
|
||||
function findOutpuDtsFile(fileName: string) {
|
||||
return ts.forEach(compilerResult.outputFiles, outputFile => outputFile.emittedFileName === fileName ? outputFile : undefined);
|
||||
@@ -310,7 +394,16 @@ class ProjectRunner extends RunnerBase {
|
||||
return ts.map(allInputFiles, outputFile => outputFile.emittedFileName);
|
||||
}
|
||||
function getSourceFileText(fileName: string): string {
|
||||
return ts.forEach(allInputFiles, inputFile => inputFile.emittedFileName === fileName ? inputFile.code : undefined);
|
||||
for (const inputFile of allInputFiles) {
|
||||
const isMatchingFile = ts.isRootedDiskPath(fileName)
|
||||
? ts.getNormalizedAbsolutePath(inputFile.emittedFileName, getCurrentDirectory()) === fileName
|
||||
: inputFile.emittedFileName === fileName;
|
||||
|
||||
if (isMatchingFile) {
|
||||
return inputFile.code;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean) {
|
||||
@@ -318,142 +411,113 @@ class ProjectRunner extends RunnerBase {
|
||||
}
|
||||
|
||||
function getErrorsBaseline(compilerResult: CompileProjectFilesResult) {
|
||||
var inputFiles = ts.map(ts.filter(compilerResult.program.getSourceFiles(),
|
||||
const inputFiles = compilerResult.program ? ts.map(ts.filter(compilerResult.program.getSourceFiles(),
|
||||
sourceFile => sourceFile.fileName !== "lib.d.ts"),
|
||||
sourceFile => {
|
||||
return { unitName: sourceFile.fileName, content: sourceFile.text };
|
||||
});
|
||||
var diagnostics = ts.map(compilerResult.errors, error => Harness.Compiler.getMinimalDiagnostic(error));
|
||||
return {
|
||||
unitName: ts.isRootedDiskPath(sourceFile.fileName) ?
|
||||
RunnerBase.removeFullPaths(sourceFile.fileName) :
|
||||
sourceFile.fileName,
|
||||
content: sourceFile.text
|
||||
};
|
||||
}) : [];
|
||||
|
||||
return Harness.Compiler.getErrorBaseline(inputFiles, diagnostics);
|
||||
return Harness.Compiler.getErrorBaseline(inputFiles, compilerResult.errors);
|
||||
}
|
||||
|
||||
describe('Compiling project for ' + testCase.scenario + ': testcase ' + testCaseFileName, () => {
|
||||
function verifyCompilerResults(compilerResult: BatchCompileProjectTestCaseResult) {
|
||||
function getCompilerResolutionInfo() {
|
||||
var resolutionInfo: ProjectRunnerTestCaseResolutionInfo = {
|
||||
scenario: testCase.scenario,
|
||||
projectRoot: testCase.projectRoot,
|
||||
inputFiles: testCase.inputFiles,
|
||||
out: testCase.out,
|
||||
outDir: testCase.outDir,
|
||||
sourceMap: testCase.sourceMap,
|
||||
mapRoot: testCase.mapRoot,
|
||||
resolveMapRoot: testCase.resolveMapRoot,
|
||||
sourceRoot: testCase.sourceRoot,
|
||||
resolveSourceRoot: testCase.resolveSourceRoot,
|
||||
declaration: testCase.declaration,
|
||||
baselineCheck: testCase.baselineCheck,
|
||||
runTest: testCase.runTest,
|
||||
bug: testCase.bug,
|
||||
rootDir: testCase.rootDir,
|
||||
resolvedInputFiles: ts.map(compilerResult.program.getSourceFiles(), inputFile => inputFile.fileName),
|
||||
emittedFiles: ts.map(compilerResult.outputFiles, outputFile => outputFile.emittedFileName)
|
||||
};
|
||||
const name = "Compiling project for " + testCase.scenario + ": testcase " + testCaseFileName;
|
||||
|
||||
return resolutionInfo;
|
||||
}
|
||||
describe("Projects tests", () => {
|
||||
describe(name, () => {
|
||||
function verifyCompilerResults(moduleKind: ts.ModuleKind) {
|
||||
let compilerResult: BatchCompileProjectTestCaseResult;
|
||||
|
||||
it('Resolution information of (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, () => {
|
||||
Harness.Baseline.runBaseline('Resolution information of (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.json', () => {
|
||||
return JSON.stringify(getCompilerResolutionInfo(), undefined, " ");
|
||||
});
|
||||
});
|
||||
|
||||
if (compilerResult.errors.length) {
|
||||
it('Errors for (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, () => {
|
||||
Harness.Baseline.runBaseline('Errors for (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.errors.txt', () => {
|
||||
return getErrorsBaseline(compilerResult);
|
||||
function getCompilerResolutionInfo() {
|
||||
const resolutionInfo: ProjectRunnerTestCaseResolutionInfo & ts.CompilerOptions = JSON.parse(JSON.stringify(testCase));
|
||||
resolutionInfo.resolvedInputFiles = ts.map(compilerResult.program.getSourceFiles(), inputFile => {
|
||||
return ts.convertToRelativePath(inputFile.fileName, getCurrentDirectory(), path => Harness.Compiler.getCanonicalFileName(path));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (testCase.baselineCheck) {
|
||||
ts.forEach(compilerResult.outputFiles, outputFile => {
|
||||
it('Baseline of emitted result (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, () => {
|
||||
Harness.Baseline.runBaseline('Baseline of emitted result (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + outputFile.fileName, () => {
|
||||
try {
|
||||
return ts.sys.readFile(getProjectOutputFolder(outputFile.fileName, compilerResult.moduleKind));
|
||||
}
|
||||
catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
if (compilerResult.sourceMapData) {
|
||||
it('SourceMapRecord for (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, () => {
|
||||
Harness.Baseline.runBaseline('SourceMapRecord for (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.sourcemap.txt', () => {
|
||||
return Harness.SourceMapRecoder.getSourceMapRecord(compilerResult.sourceMapData, compilerResult.program,
|
||||
ts.filter(compilerResult.outputFiles, outputFile => Harness.Compiler.isJS(outputFile.emittedFileName)));
|
||||
});
|
||||
resolutionInfo.emittedFiles = ts.map(compilerResult.outputFiles, outputFile => {
|
||||
return ts.convertToRelativePath(outputFile.emittedFileName, getCurrentDirectory(), path => Harness.Compiler.getCanonicalFileName(path));
|
||||
});
|
||||
return resolutionInfo;
|
||||
}
|
||||
|
||||
// Verify that all the generated .d.ts files compile
|
||||
if (!compilerResult.errors.length && testCase.declaration) {
|
||||
var dTsCompileResult = compileCompileDTsFiles(compilerResult);
|
||||
if (dTsCompileResult.errors.length) {
|
||||
it('Errors in generated Dts files for (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, () => {
|
||||
Harness.Baseline.runBaseline('Errors in generated Dts files for (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.dts.errors.txt', () => {
|
||||
return getErrorsBaseline(dTsCompileResult);
|
||||
it(name + ": " + moduleNameToString(moduleKind), () => {
|
||||
// Compile using node
|
||||
compilerResult = batchCompilerProjectTestCase(moduleKind);
|
||||
});
|
||||
|
||||
it("Resolution information of (" + moduleNameToString(moduleKind) + "): " + testCaseFileName, () => {
|
||||
Harness.Baseline.runBaseline("Resolution information of (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".json", () => {
|
||||
return JSON.stringify(getCompilerResolutionInfo(), undefined, " ");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it("Errors for (" + moduleNameToString(moduleKind) + "): " + testCaseFileName, () => {
|
||||
if (compilerResult.errors.length) {
|
||||
Harness.Baseline.runBaseline("Errors for (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".errors.txt", () => {
|
||||
return getErrorsBaseline(compilerResult);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
it("Baseline of emitted result (" + moduleNameToString(moduleKind) + "): " + testCaseFileName, () => {
|
||||
if (testCase.baselineCheck) {
|
||||
ts.forEach(compilerResult.outputFiles, outputFile => {
|
||||
|
||||
Harness.Baseline.runBaseline("Baseline of emitted result (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + outputFile.fileName, () => {
|
||||
try {
|
||||
return Harness.IO.readFile(getProjectOutputFolder(outputFile.fileName, compilerResult.moduleKind));
|
||||
}
|
||||
catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
it("SourceMapRecord for (" + moduleNameToString(moduleKind) + "): " + testCaseFileName, () => {
|
||||
if (compilerResult.sourceMapData) {
|
||||
Harness.Baseline.runBaseline("SourceMapRecord for (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".sourcemap.txt", () => {
|
||||
return Harness.SourceMapRecoder.getSourceMapRecord(compilerResult.sourceMapData, compilerResult.program,
|
||||
ts.filter(compilerResult.outputFiles, outputFile => Harness.Compiler.isJS(outputFile.emittedFileName)));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Verify that all the generated .d.ts files compile
|
||||
|
||||
it("Errors in generated Dts files for (" + moduleNameToString(moduleKind) + "): " + testCaseFileName, () => {
|
||||
if (!compilerResult.errors.length && testCase.declaration) {
|
||||
const dTsCompileResult = compileCompileDTsFiles(compilerResult);
|
||||
if (dTsCompileResult && dTsCompileResult.errors.length) {
|
||||
Harness.Baseline.runBaseline("Errors in generated Dts files for (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".dts.errors.txt", () => {
|
||||
return getErrorsBaseline(dTsCompileResult);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
after(() => {
|
||||
compilerResult = undefined;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Compile using node
|
||||
var nodeCompilerResult = batchCompilerProjectTestCase(ts.ModuleKind.CommonJS);
|
||||
verifyCompilerResults(nodeCompilerResult);
|
||||
verifyCompilerResults(ts.ModuleKind.CommonJS);
|
||||
verifyCompilerResults(ts.ModuleKind.AMD);
|
||||
|
||||
// Compile using amd
|
||||
var amdCompilerResult = batchCompilerProjectTestCase(ts.ModuleKind.AMD);
|
||||
verifyCompilerResults(amdCompilerResult);
|
||||
|
||||
if (testCase.runTest) {
|
||||
//TODO(ryanca/danquirk): Either support this or remove this option from the interface as well as test case json files
|
||||
// Node results
|
||||
assert.isTrue(!nodeCompilerResult.nonSubfolderDiskFiles, "Cant run test case that generates parent folders/absolute path");
|
||||
//it("runs without error: (" + moduleNameToString(nodeCompilerResult.moduleKind) + ')', function (done: any) {
|
||||
// Exec.exec("node.exe", ['"' + baseLineLocalPath(nodeCompilerResult.outputFiles[0].diskRelativeName, nodeCompilerResult.moduleKind) + '"'], function (res) {
|
||||
// Harness.Assert.equal(res.stdout, "");
|
||||
// Harness.Assert.equal(res.stderr, "");
|
||||
// done();
|
||||
// })
|
||||
//});
|
||||
|
||||
// Amd results
|
||||
assert.isTrue(!amdCompilerResult.nonSubfolderDiskFiles, "Cant run test case that generates parent folders/absolute path");
|
||||
//var amdDriverTemplate = "var requirejs = require('../r.js');\n\n" +
|
||||
// "requirejs.config({\n" +
|
||||
// " nodeRequire: require\n" +
|
||||
// "});\n\n" +
|
||||
// "requirejs(['{0}'],\n" +
|
||||
// "function ({0}) {\n" +
|
||||
// "});";
|
||||
//var moduleName = baseLineLocalPath(amdCompilerResult.outputFiles[0].diskRelativeName, amdCompilerResult.moduleKind).replace(/\.js$/, "");
|
||||
//sys.writeFile(testCase.projectRoot + '/driver.js', amdDriverTemplate.replace(/\{0}/g, moduleName));
|
||||
//it("runs without error (" + moduleNameToString(amdCompilerResult.moduleKind) + ')', function (done: any) {
|
||||
// Exec.exec("node.exe", ['"' + testCase.projectRoot + '/driver.js"'], function (res) {
|
||||
// Harness.Assert.equal(res.stdout, "");
|
||||
// Harness.Assert.equal(res.stderr, "");
|
||||
// done();
|
||||
// })
|
||||
//});
|
||||
}
|
||||
|
||||
after(() => {
|
||||
// Mocha holds onto the closure environment of the describe callback even after the test is done.
|
||||
// Therefore we have to clean out large objects after the test is done.
|
||||
nodeCompilerResult = undefined;
|
||||
amdCompilerResult = undefined;
|
||||
testCase = undefined;
|
||||
testFileText = undefined;
|
||||
testCaseJustName = undefined;
|
||||
after(() => {
|
||||
// Mocha holds onto the closure environment of the describe callback even after the test is done.
|
||||
// Therefore we have to clean out large objects after the test is done.
|
||||
testCase = undefined;
|
||||
testFileText = undefined;
|
||||
testCaseJustName = undefined;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+66
-62
@@ -1,6 +1,6 @@
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
@@ -13,74 +13,79 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
/// <reference path='test262Runner.ts' />
|
||||
/// <reference path='compilerRunner.ts' />
|
||||
/// <reference path='fourslashRunner.ts' />
|
||||
/// <reference path='projectsRunner.ts' />
|
||||
/// <reference path='rwcRunner.ts' />
|
||||
/// <reference path="test262Runner.ts" />
|
||||
/// <reference path="compilerRunner.ts" />
|
||||
/// <reference path="fourslashRunner.ts" />
|
||||
/// <reference path="projectsRunner.ts" />
|
||||
/// <reference path="rwcRunner.ts" />
|
||||
/// <reference path="harness.ts" />
|
||||
|
||||
/* tslint:disable:no-null */
|
||||
|
||||
let runners: RunnerBase[] = [];
|
||||
let iterations = 1;
|
||||
|
||||
function runTests(runners: RunnerBase[]) {
|
||||
if (reverse) {
|
||||
runners = runners.reverse();
|
||||
}
|
||||
for (var i = iterations; i > 0; i--) {
|
||||
for (var j = 0; j < runners.length; j++) {
|
||||
for (let i = iterations; i > 0; i--) {
|
||||
for (let j = 0; j < runners.length; j++) {
|
||||
runners[j].initializeTests();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var runners: RunnerBase[] = [];
|
||||
global.runners = runners;
|
||||
var reverse: boolean = false;
|
||||
var iterations: number = 1;
|
||||
|
||||
// users can define tests to run in mytest.config that will override cmd line args, otherwise use cmd line args (test.config), otherwise no options
|
||||
var mytestconfig = 'mytest.config';
|
||||
var testconfig = 'test.config';
|
||||
var testConfigFile =
|
||||
let mytestconfig = "mytest.config";
|
||||
let testconfig = "test.config";
|
||||
let testConfigFile =
|
||||
Harness.IO.fileExists(mytestconfig) ? Harness.IO.readFile(mytestconfig) :
|
||||
(Harness.IO.fileExists(testconfig) ? Harness.IO.readFile(testconfig) : '');
|
||||
(Harness.IO.fileExists(testconfig) ? Harness.IO.readFile(testconfig) : "");
|
||||
|
||||
if (testConfigFile !== '') {
|
||||
// TODO: not sure why this is crashing mocha
|
||||
//var testConfig = JSON.parse(testConfigRaw);
|
||||
var testConfig = testConfigFile.match(/test:\s\['(.*)'\]/);
|
||||
var options = testConfig ? [testConfig[1]] : [];
|
||||
for (var i = 0; i < options.length; i++) {
|
||||
switch (options[i]) {
|
||||
case 'compiler':
|
||||
runners.push(new CompilerBaselineRunner(CompilerTestType.Conformance));
|
||||
runners.push(new CompilerBaselineRunner(CompilerTestType.Regressions));
|
||||
runners.push(new ProjectRunner());
|
||||
break;
|
||||
case 'conformance':
|
||||
runners.push(new CompilerBaselineRunner(CompilerTestType.Conformance));
|
||||
break;
|
||||
case 'project':
|
||||
runners.push(new ProjectRunner());
|
||||
break;
|
||||
case 'fourslash':
|
||||
runners.push(new FourSlashRunner(FourSlashTestType.Native));
|
||||
break;
|
||||
case 'fourslash-shims':
|
||||
runners.push(new FourSlashRunner(FourSlashTestType.Shims));
|
||||
break;
|
||||
case 'fourslash-server':
|
||||
runners.push(new FourSlashRunner(FourSlashTestType.Server));
|
||||
break;
|
||||
case 'fourslash-generated':
|
||||
runners.push(new GeneratedFourslashRunner(FourSlashTestType.Native));
|
||||
break;
|
||||
case 'rwc':
|
||||
runners.push(new RWCRunner());
|
||||
break;
|
||||
case 'test262':
|
||||
runners.push(new Test262BaselineRunner());
|
||||
break;
|
||||
case 'reverse':
|
||||
reverse = true;
|
||||
break;
|
||||
if (testConfigFile !== "") {
|
||||
const testConfig = JSON.parse(testConfigFile);
|
||||
if (testConfig.light) {
|
||||
Harness.lightMode = true;
|
||||
}
|
||||
|
||||
if (testConfig.test && testConfig.test.length > 0) {
|
||||
for (const option of testConfig.test) {
|
||||
if (!option) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (option) {
|
||||
case "compiler":
|
||||
runners.push(new CompilerBaselineRunner(CompilerTestType.Conformance));
|
||||
runners.push(new CompilerBaselineRunner(CompilerTestType.Regressions));
|
||||
runners.push(new ProjectRunner());
|
||||
break;
|
||||
case "conformance":
|
||||
runners.push(new CompilerBaselineRunner(CompilerTestType.Conformance));
|
||||
break;
|
||||
case "project":
|
||||
runners.push(new ProjectRunner());
|
||||
break;
|
||||
case "fourslash":
|
||||
runners.push(new FourSlashRunner(FourSlashTestType.Native));
|
||||
break;
|
||||
case "fourslash-shims":
|
||||
runners.push(new FourSlashRunner(FourSlashTestType.Shims));
|
||||
break;
|
||||
case "fourslash-shims-pp":
|
||||
runners.push(new FourSlashRunner(FourSlashTestType.ShimsWithPreprocess));
|
||||
break;
|
||||
case "fourslash-server":
|
||||
runners.push(new FourSlashRunner(FourSlashTestType.Server));
|
||||
break;
|
||||
case "fourslash-generated":
|
||||
runners.push(new GeneratedFourslashRunner(FourSlashTestType.Native));
|
||||
break;
|
||||
case "rwc":
|
||||
runners.push(new RWCRunner());
|
||||
break;
|
||||
case "test262":
|
||||
runners.push(new Test262BaselineRunner());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,10 +103,9 @@ if (runners.length === 0) {
|
||||
// language services
|
||||
runners.push(new FourSlashRunner(FourSlashTestType.Native));
|
||||
runners.push(new FourSlashRunner(FourSlashTestType.Shims));
|
||||
runners.push(new FourSlashRunner(FourSlashTestType.ShimsWithPreprocess));
|
||||
runners.push(new FourSlashRunner(FourSlashTestType.Server));
|
||||
//runners.push(new GeneratedFourslashRunner());
|
||||
// runners.push(new GeneratedFourslashRunner());
|
||||
}
|
||||
|
||||
ts.sys.newLine = '\r\n';
|
||||
|
||||
runTests(runners);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path="harness.ts" />
|
||||
|
||||
class RunnerBase {
|
||||
abstract class RunnerBase {
|
||||
constructor() { }
|
||||
|
||||
// contains the tests to run
|
||||
@@ -12,30 +12,28 @@ class RunnerBase {
|
||||
}
|
||||
|
||||
public enumerateFiles(folder: string, regex?: RegExp, options?: { recursive: boolean }): string[] {
|
||||
return Harness.IO.listFiles(Harness.userSpecifiedroot + folder, regex, { recursive: (options ? options.recursive : false) });
|
||||
return Harness.IO.listFiles(Harness.userSpecifiedRoot + folder, regex, { recursive: (options ? options.recursive : false) });
|
||||
}
|
||||
|
||||
/** Setup the runner's tests so that they are ready to be executed by the harness
|
||||
* The first test should be a describe/it block that sets up the harness's compiler instance appropriately
|
||||
*/
|
||||
public initializeTests(): void {
|
||||
throw new Error('method not implemented');
|
||||
}
|
||||
public abstract initializeTests(): void;
|
||||
|
||||
/** Replaces instances of full paths with fileNames only */
|
||||
static removeFullPaths(path: string) {
|
||||
var fixedPath = path;
|
||||
let fixedPath = path;
|
||||
|
||||
// full paths either start with a drive letter or / for *nix, shouldn't have \ in the path at this point
|
||||
var fullPath = /(\w+:|\/)?([\w+\-\.]|\/)*\.ts/g;
|
||||
var fullPathList = fixedPath.match(fullPath);
|
||||
const fullPath = /(\w+:|\/)?([\w+\-\.]|\/)*\.tsx?/g;
|
||||
const fullPathList = fixedPath.match(fullPath);
|
||||
if (fullPathList) {
|
||||
fullPathList.forEach((match: string) => fixedPath = fixedPath.replace(match, Harness.Path.getFileName(match)));
|
||||
}
|
||||
|
||||
|
||||
// when running in the browser the 'full path' is the host name, shows up in error baselines
|
||||
var localHost = /http:\/localhost:\d+/g;
|
||||
fixedPath = fixedPath.replace(localHost, '');
|
||||
const localHost = /http:\/localhost:\d+/g;
|
||||
fixedPath = fixedPath.replace(localHost, "");
|
||||
return fixedPath;
|
||||
}
|
||||
}
|
||||
+98
-74
@@ -1,39 +1,43 @@
|
||||
/// <reference path='harness.ts'/>
|
||||
/// <reference path='runnerbase.ts' />
|
||||
/// <reference path='syntacticCleaner.ts' />
|
||||
/// <reference path='loggedIO.ts' />
|
||||
/// <reference path='..\compiler\commandLineParser.ts'/>
|
||||
/// <reference path="harness.ts"/>
|
||||
/// <reference path="runnerbase.ts" />
|
||||
/// <reference path="loggedIO.ts" />
|
||||
/// <reference path="..\compiler\commandLineParser.ts"/>
|
||||
/* tslint:disable:no-null */
|
||||
|
||||
module RWC {
|
||||
function runWithIOLog(ioLog: IOLog, fn: () => void) {
|
||||
var oldSys = ts.sys;
|
||||
namespace RWC {
|
||||
function runWithIOLog(ioLog: IOLog, fn: (oldIO: Harness.IO) => void) {
|
||||
const oldIO = Harness.IO;
|
||||
|
||||
var wrappedSys = Playback.wrapSystem(ts.sys);
|
||||
wrappedSys.startReplayFromData(ioLog);
|
||||
ts.sys = wrappedSys;
|
||||
const wrappedIO = Playback.wrapIO(oldIO);
|
||||
wrappedIO.startReplayFromData(ioLog);
|
||||
Harness.IO = wrappedIO;
|
||||
|
||||
try {
|
||||
fn();
|
||||
fn(oldIO);
|
||||
} finally {
|
||||
wrappedSys.endReplay();
|
||||
ts.sys = oldSys;
|
||||
wrappedIO.endReplay();
|
||||
Harness.IO = oldIO;
|
||||
}
|
||||
}
|
||||
|
||||
function isTsConfigFile(file: { path: string }): boolean {
|
||||
const tsConfigFileName = "tsconfig.json";
|
||||
return file.path.substr(file.path.length - tsConfigFileName.length).toLowerCase() === tsConfigFileName;
|
||||
}
|
||||
|
||||
export function runRWCTest(jsonPath: string) {
|
||||
describe("Testing a RWC project: " + jsonPath, () => {
|
||||
var inputFiles: { unitName: string; content: string; }[] = [];
|
||||
var otherFiles: { unitName: string; content: string; }[] = [];
|
||||
var compilerResult: Harness.Compiler.CompilerResult;
|
||||
var compilerOptions: ts.CompilerOptions;
|
||||
var baselineOpts: Harness.Baseline.BaselineOptions = {
|
||||
Subfolder: 'rwc',
|
||||
Baselinefolder: 'internal/baselines'
|
||||
let inputFiles: Harness.Compiler.TestFile[] = [];
|
||||
let otherFiles: Harness.Compiler.TestFile[] = [];
|
||||
let compilerResult: Harness.Compiler.CompilerResult;
|
||||
let compilerOptions: ts.CompilerOptions;
|
||||
let baselineOpts: Harness.Baseline.BaselineOptions = {
|
||||
Subfolder: "rwc",
|
||||
Baselinefolder: "internal/baselines"
|
||||
};
|
||||
var baseName = /(.*)\/(.*).json/.exec(ts.normalizeSlashes(jsonPath))[2];
|
||||
var currentDirectory: string;
|
||||
var useCustomLibraryFile: boolean;
|
||||
|
||||
let baseName = /(.*)\/(.*).json/.exec(ts.normalizeSlashes(jsonPath))[2];
|
||||
let currentDirectory: string;
|
||||
let useCustomLibraryFile: boolean;
|
||||
after(() => {
|
||||
// Mocha holds onto the closure environment of the describe callback even after the test is done.
|
||||
// Therefore we have to clean out large objects after the test is done.
|
||||
@@ -50,15 +54,14 @@ module RWC {
|
||||
useCustomLibraryFile = undefined;
|
||||
});
|
||||
|
||||
it('can compile', () => {
|
||||
var harnessCompiler = Harness.Compiler.getCompiler();
|
||||
var opts: ts.ParsedCommandLine;
|
||||
it("can compile", () => {
|
||||
let opts: ts.ParsedCommandLine;
|
||||
|
||||
var ioLog: IOLog = JSON.parse(Harness.IO.readFile(jsonPath));
|
||||
const ioLog: IOLog = JSON.parse(Harness.IO.readFile(jsonPath));
|
||||
currentDirectory = ioLog.currentDirectory;
|
||||
useCustomLibraryFile = ioLog.useCustomLibraryFile;
|
||||
runWithIOLog(ioLog, () => {
|
||||
opts = ts.parseCommandLine(ioLog.arguments);
|
||||
opts = ts.parseCommandLine(ioLog.arguments, fileName => Harness.IO.readFile(fileName));
|
||||
assert.equal(opts.errors.length, 0);
|
||||
|
||||
// To provide test coverage of output javascript file,
|
||||
@@ -66,19 +69,33 @@ module RWC {
|
||||
opts.options.noEmitOnError = false;
|
||||
});
|
||||
|
||||
runWithIOLog(ioLog, () => {
|
||||
harnessCompiler.reset();
|
||||
runWithIOLog(ioLog, oldIO => {
|
||||
let fileNames = opts.fileNames;
|
||||
|
||||
const tsconfigFile = ts.forEach(ioLog.filesRead, f => isTsConfigFile(f) ? f : undefined);
|
||||
if (tsconfigFile) {
|
||||
const tsconfigFileContents = getHarnessCompilerInputUnit(tsconfigFile.path);
|
||||
const parsedTsconfigFileContents = ts.parseConfigFileTextToJson(tsconfigFile.path, tsconfigFileContents.content);
|
||||
const configParseResult = ts.parseJsonConfigFileContent(parsedTsconfigFileContents.config, Harness.IO, ts.getDirectoryPath(tsconfigFile.path));
|
||||
fileNames = configParseResult.fileNames;
|
||||
opts.options = ts.extend(opts.options, configParseResult.options);
|
||||
}
|
||||
|
||||
// Load the files
|
||||
ts.forEach(opts.fileNames, fileName => {
|
||||
for (const fileName of fileNames) {
|
||||
inputFiles.push(getHarnessCompilerInputUnit(fileName));
|
||||
});
|
||||
}
|
||||
|
||||
// Add files to compilation
|
||||
for(let fileRead of ioLog.filesRead) {
|
||||
const isInInputList = (resolvedPath: string) => (inputFile: { unitName: string; content: string; }) => inputFile.unitName === resolvedPath;
|
||||
for (const fileRead of ioLog.filesRead) {
|
||||
// Check if the file is already added into the set of input files.
|
||||
var resolvedPath = ts.normalizeSlashes(ts.sys.resolvePath(fileRead.path));
|
||||
var inInputList = ts.forEach(inputFiles, inputFile => inputFile.unitName === resolvedPath);
|
||||
const resolvedPath = ts.normalizeSlashes(Harness.IO.resolvePath(fileRead.path));
|
||||
const inInputList = ts.forEach(inputFiles, isInInputList(resolvedPath));
|
||||
|
||||
if (isTsConfigFile(fileRead)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Harness.isLibraryFile(fileRead.path)) {
|
||||
if (inInputList) {
|
||||
@@ -86,7 +103,7 @@ module RWC {
|
||||
}
|
||||
otherFiles.push(getHarnessCompilerInputUnit(fileRead.path));
|
||||
}
|
||||
else if (!opts.options.noLib && Harness.isLibraryFile(fileRead.path)){
|
||||
else if (!opts.options.noLib && Harness.isLibraryFile(fileRead.path)) {
|
||||
if (!inInputList) {
|
||||
// If useCustomLibraryFile is true, we will use lib.d.ts from json object
|
||||
// otherwise use the lib.d.ts from built/local
|
||||
@@ -97,7 +114,8 @@ module RWC {
|
||||
inputFiles.push(getHarnessCompilerInputUnit(fileRead.path));
|
||||
}
|
||||
else {
|
||||
inputFiles.push(Harness.getDefaultLibraryFile());
|
||||
// set the flag to put default library to the beginning of the list
|
||||
inputFiles.unshift(Harness.getDefaultLibraryFile(oldIO));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -107,37 +125,42 @@ module RWC {
|
||||
opts.options.noLib = true;
|
||||
|
||||
// Emit the results
|
||||
compilerOptions = harnessCompiler.compileFiles(inputFiles, otherFiles, compileResult => {
|
||||
compilerResult = compileResult;
|
||||
},
|
||||
/*settingsCallback*/ undefined, opts.options,
|
||||
// Since all Rwc json file specified current directory in its json file, we need to pass this information to compilerHost
|
||||
// so that when the host is asked for current directory, it should give the value from json rather than from process
|
||||
currentDirectory,
|
||||
/*assertInvariants:*/ false);
|
||||
compilerOptions = null;
|
||||
const output = Harness.Compiler.compileFiles(
|
||||
inputFiles,
|
||||
otherFiles,
|
||||
/* harnessOptions */ undefined,
|
||||
opts.options,
|
||||
// Since each RWC json file specifies its current directory in its json file, we need
|
||||
// to pass this information in explicitly instead of acquiring it from the process.
|
||||
currentDirectory);
|
||||
|
||||
compilerOptions = output.options;
|
||||
compilerResult = output.result;
|
||||
});
|
||||
|
||||
function getHarnessCompilerInputUnit(fileName: string) {
|
||||
var unitName = ts.normalizeSlashes(ts.sys.resolvePath(fileName));
|
||||
function getHarnessCompilerInputUnit(fileName: string): Harness.Compiler.TestFile {
|
||||
const unitName = ts.normalizeSlashes(Harness.IO.resolvePath(fileName));
|
||||
let content: string = null;
|
||||
try {
|
||||
var content = ts.sys.readFile(unitName);
|
||||
content = Harness.IO.readFile(unitName);
|
||||
}
|
||||
catch (e) {
|
||||
// Leave content undefined.
|
||||
content = Harness.IO.readFile(fileName);
|
||||
}
|
||||
return { unitName, content };
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
it('has the expected emitted code', () => {
|
||||
Harness.Baseline.runBaseline('has the expected emitted code', baseName + '.output.js', () => {
|
||||
return Harness.Compiler.collateOutputs(compilerResult.files, s => SyntacticCleaner.clean(s));
|
||||
it("has the expected emitted code", () => {
|
||||
Harness.Baseline.runBaseline("has the expected emitted code", baseName + ".output.js", () => {
|
||||
return Harness.Compiler.collateOutputs(compilerResult.files);
|
||||
}, false, baselineOpts);
|
||||
});
|
||||
|
||||
it('has the expected declaration file content', () => {
|
||||
Harness.Baseline.runBaseline('has the expected declaration file content', baseName + '.d.ts', () => {
|
||||
it("has the expected declaration file content", () => {
|
||||
Harness.Baseline.runBaseline("has the expected declaration file content", baseName + ".d.ts", () => {
|
||||
if (!compilerResult.declFilesCode.length) {
|
||||
return null;
|
||||
}
|
||||
@@ -146,8 +169,8 @@ module RWC {
|
||||
}, false, baselineOpts);
|
||||
});
|
||||
|
||||
it('has the expected source maps', () => {
|
||||
Harness.Baseline.runBaseline('has the expected source maps', baseName + '.map', () => {
|
||||
it("has the expected source maps", () => {
|
||||
Harness.Baseline.runBaseline("has the expected source maps", baseName + ".map", () => {
|
||||
if (!compilerResult.sourceMaps.length) {
|
||||
return null;
|
||||
}
|
||||
@@ -156,16 +179,16 @@ module RWC {
|
||||
}, false, baselineOpts);
|
||||
});
|
||||
|
||||
//it('has correct source map record', () => {
|
||||
// if (compilerOptions.sourceMap) {
|
||||
// Harness.Baseline.runBaseline('has correct source map record', baseName + '.sourcemap.txt', () => {
|
||||
// return compilerResult.getSourceMapRecord();
|
||||
// }, false, baselineOpts);
|
||||
// }
|
||||
//});
|
||||
/*it("has correct source map record", () => {
|
||||
if (compilerOptions.sourceMap) {
|
||||
Harness.Baseline.runBaseline("has correct source map record", baseName + ".sourcemap.txt", () => {
|
||||
return compilerResult.getSourceMapRecord();
|
||||
}, false, baselineOpts);
|
||||
}
|
||||
});*/
|
||||
|
||||
it('has the expected errors', () => {
|
||||
Harness.Baseline.runBaseline('has the expected errors', baseName + '.errors.txt', () => {
|
||||
it("has the expected errors", () => {
|
||||
Harness.Baseline.runBaseline("has the expected errors", baseName + ".errors.txt", () => {
|
||||
if (compilerResult.errors.length === 0) {
|
||||
return null;
|
||||
}
|
||||
@@ -176,17 +199,18 @@ module RWC {
|
||||
|
||||
// Ideally, a generated declaration file will have no errors. But we allow generated
|
||||
// declaration file errors as part of the baseline.
|
||||
it('has the expected errors in generated declaration files', () => {
|
||||
it("has the expected errors in generated declaration files", () => {
|
||||
if (compilerOptions.declaration && !compilerResult.errors.length) {
|
||||
Harness.Baseline.runBaseline('has the expected errors in generated declaration files', baseName + '.dts.errors.txt', () => {
|
||||
var declFileCompilationResult = Harness.Compiler.getCompiler().compileDeclarationFiles(inputFiles, otherFiles, compilerResult,
|
||||
/*settingscallback*/ undefined, compilerOptions, currentDirectory);
|
||||
Harness.Baseline.runBaseline("has the expected errors in generated declaration files", baseName + ".dts.errors.txt", () => {
|
||||
const declFileCompilationResult = Harness.Compiler.compileDeclarationFiles(
|
||||
inputFiles, otherFiles, compilerResult, /*harnessSettings*/ undefined, compilerOptions, currentDirectory);
|
||||
|
||||
if (declFileCompilationResult.declResult.errors.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Harness.Compiler.minimalDiagnosticsToString(declFileCompilationResult.declResult.errors) +
|
||||
ts.sys.newLine + ts.sys.newLine +
|
||||
Harness.IO.newLine() + Harness.IO.newLine() +
|
||||
Harness.Compiler.getErrorBaseline(declFileCompilationResult.declInputFiles.concat(declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.errors);
|
||||
}, false, baselineOpts);
|
||||
}
|
||||
@@ -205,8 +229,8 @@ class RWCRunner extends RunnerBase {
|
||||
*/
|
||||
public initializeTests(): void {
|
||||
// Read in and evaluate the test list
|
||||
var testList = Harness.IO.listFiles(RWCRunner.sourcePath, /.+\.json$/);
|
||||
for (var i = 0; i < testList.length; i++) {
|
||||
const testList = Harness.IO.listFiles(RWCRunner.sourcePath, /.+\.json$/);
|
||||
for (let i = 0; i < testList.length; i++) {
|
||||
this.runTest(testList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
@@ -13,22 +13,22 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
///<reference path='harness.ts'/>
|
||||
///<reference path="harness.ts"/>
|
||||
|
||||
module Harness.SourceMapRecoder {
|
||||
namespace Harness.SourceMapRecoder {
|
||||
|
||||
interface SourceMapSpanWithDecodeErrors {
|
||||
sourceMapSpan: ts.SourceMapSpan;
|
||||
decodeErrors: string[];
|
||||
}
|
||||
|
||||
module SourceMapDecoder {
|
||||
var sourceMapMappings: string;
|
||||
var sourceMapNames: string[];
|
||||
var decodingIndex: number;
|
||||
var prevNameIndex: number;
|
||||
var decodeOfEncodedMapping: ts.SourceMapSpan;
|
||||
var errorDecodeOfEncodedMapping: string;
|
||||
namespace SourceMapDecoder {
|
||||
let sourceMapMappings: string;
|
||||
let sourceMapNames: string[];
|
||||
let decodingIndex: number;
|
||||
let prevNameIndex: number;
|
||||
let decodeOfEncodedMapping: ts.SourceMapSpan;
|
||||
let errorDecodeOfEncodedMapping: string;
|
||||
|
||||
export function initializeSourceMapDecoding(sourceMapData: ts.SourceMapData) {
|
||||
sourceMapMappings = sourceMapData.sourceMapMappings;
|
||||
@@ -46,15 +46,15 @@ module Harness.SourceMapRecoder {
|
||||
}
|
||||
|
||||
function isSourceMappingSegmentEnd() {
|
||||
if (decodingIndex == sourceMapMappings.length) {
|
||||
if (decodingIndex === sourceMapMappings.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sourceMapMappings.charAt(decodingIndex) == ',') {
|
||||
if (sourceMapMappings.charAt(decodingIndex) == ",") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sourceMapMappings.charAt(decodingIndex) == ';') {
|
||||
if (sourceMapMappings.charAt(decodingIndex) == ";") {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -82,9 +82,9 @@ module Harness.SourceMapRecoder {
|
||||
return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(sourceMapMappings.charAt(decodingIndex));
|
||||
}
|
||||
|
||||
var moreDigits = true;
|
||||
var shiftCount = 0;
|
||||
var value = 0;
|
||||
let moreDigits = true;
|
||||
let shiftCount = 0;
|
||||
let value = 0;
|
||||
|
||||
for (; moreDigits; decodingIndex++) {
|
||||
if (createErrorIfCondition(decodingIndex >= sourceMapMappings.length, "Error in decoding base64VLQFormatDecode, past the mapping string")) {
|
||||
@@ -92,10 +92,10 @@ module Harness.SourceMapRecoder {
|
||||
}
|
||||
|
||||
// 6 digit number
|
||||
var currentByte = base64FormatDecode();
|
||||
const currentByte = base64FormatDecode();
|
||||
|
||||
// If msb is set, we still have more bits to continue
|
||||
moreDigits = (currentByte & 32) != 0;
|
||||
moreDigits = (currentByte & 32) !== 0;
|
||||
|
||||
// least significant 5 bits are the next msbs in the final value.
|
||||
value = value | ((currentByte & 31) << shiftCount);
|
||||
@@ -103,7 +103,7 @@ module Harness.SourceMapRecoder {
|
||||
}
|
||||
|
||||
// Least significant bit if 1 represents negative and rest of the msb is actual absolute value
|
||||
if ((value & 1) == 0) {
|
||||
if ((value & 1) === 0) {
|
||||
// + number
|
||||
value = value >> 1;
|
||||
}
|
||||
@@ -117,7 +117,7 @@ module Harness.SourceMapRecoder {
|
||||
}
|
||||
|
||||
while (decodingIndex < sourceMapMappings.length) {
|
||||
if (sourceMapMappings.charAt(decodingIndex) == ';') {
|
||||
if (sourceMapMappings.charAt(decodingIndex) == ";") {
|
||||
// New line
|
||||
decodeOfEncodedMapping.emittedLine++;
|
||||
decodeOfEncodedMapping.emittedColumn = 1;
|
||||
@@ -125,7 +125,7 @@ module Harness.SourceMapRecoder {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sourceMapMappings.charAt(decodingIndex) == ',') {
|
||||
if (sourceMapMappings.charAt(decodingIndex) == ",") {
|
||||
// Next entry is on same line - no action needed
|
||||
decodingIndex++;
|
||||
continue;
|
||||
@@ -143,7 +143,7 @@ module Harness.SourceMapRecoder {
|
||||
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
|
||||
}
|
||||
|
||||
// 2. Relative sourceIndex
|
||||
// 2. Relative sourceIndex
|
||||
decodeOfEncodedMapping.sourceIndex += base64VLQFormatDecode();
|
||||
// Incorrect sourceIndex dont support this map
|
||||
if (createErrorIfCondition(decodeOfEncodedMapping.sourceIndex < 0, "Invalid sourceIndex found")) {
|
||||
@@ -165,14 +165,13 @@ module Harness.SourceMapRecoder {
|
||||
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
|
||||
}
|
||||
|
||||
// 4. Relative sourceColumn 0 based
|
||||
// 4. Relative sourceColumn 0 based
|
||||
decodeOfEncodedMapping.sourceColumn += base64VLQFormatDecode();
|
||||
// Incorrect sourceColumn dont support this map
|
||||
if (createErrorIfCondition(decodeOfEncodedMapping.sourceColumn < 1, "Invalid sourceLine found")) {
|
||||
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
|
||||
}
|
||||
// 5. Check if there is name:
|
||||
decodeOfEncodedMapping.nameIndex = -1;
|
||||
if (!isSourceMappingSegmentEnd()) {
|
||||
prevNameIndex += base64VLQFormatDecode();
|
||||
decodeOfEncodedMapping.nameIndex = prevNameIndex;
|
||||
@@ -182,7 +181,7 @@ module Harness.SourceMapRecoder {
|
||||
}
|
||||
}
|
||||
// Dont support reading mappings that dont have information about original source and its line numbers
|
||||
if (createErrorIfCondition(!isSourceMappingSegmentEnd(), "Unsupported Error Format: There are more entries after " + (decodeOfEncodedMapping.nameIndex == -1 ? "sourceColumn" : "nameIndex"))) {
|
||||
if (createErrorIfCondition(!isSourceMappingSegmentEnd(), "Unsupported Error Format: There are more entries after " + (decodeOfEncodedMapping.nameIndex === -1 ? "sourceColumn" : "nameIndex"))) {
|
||||
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
|
||||
}
|
||||
|
||||
@@ -190,7 +189,7 @@ module Harness.SourceMapRecoder {
|
||||
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
|
||||
}
|
||||
|
||||
createErrorIfCondition(true, "No encoded entry found");
|
||||
createErrorIfCondition(/*condition*/ true, "No encoded entry found");
|
||||
}
|
||||
|
||||
export function hasCompletedDecoding() {
|
||||
@@ -202,20 +201,20 @@ module Harness.SourceMapRecoder {
|
||||
}
|
||||
}
|
||||
|
||||
module SourceMapSpanWriter {
|
||||
var sourceMapRecoder: Compiler.WriterAggregator;
|
||||
var sourceMapSources: string[];
|
||||
var sourceMapNames: string[];
|
||||
namespace SourceMapSpanWriter {
|
||||
let sourceMapRecoder: Compiler.WriterAggregator;
|
||||
let sourceMapSources: string[];
|
||||
let sourceMapNames: string[];
|
||||
|
||||
var jsFile: Compiler.GeneratedFile;
|
||||
var jsLineMap: number[];
|
||||
var tsCode: string;
|
||||
var tsLineMap: number[];
|
||||
let jsFile: Compiler.GeneratedFile;
|
||||
let jsLineMap: number[];
|
||||
let tsCode: string;
|
||||
let tsLineMap: number[];
|
||||
|
||||
var spansOnSingleLine: SourceMapSpanWithDecodeErrors[];
|
||||
var prevWrittenSourcePos: number;
|
||||
var prevWrittenJsLine: number;
|
||||
var spanMarkerContinues: boolean;
|
||||
let spansOnSingleLine: SourceMapSpanWithDecodeErrors[];
|
||||
let prevWrittenSourcePos: number;
|
||||
let prevWrittenJsLine: number;
|
||||
let spanMarkerContinues: boolean;
|
||||
|
||||
export function intializeSourceMapSpanWriter(sourceMapRecordWriter: Compiler.WriterAggregator, sourceMapData: ts.SourceMapData, currentJsFile: Compiler.GeneratedFile) {
|
||||
sourceMapRecoder = sourceMapRecordWriter;
|
||||
@@ -237,16 +236,19 @@ module Harness.SourceMapRecoder {
|
||||
sourceMapRecoder.WriteLine("mapUrl: " + sourceMapData.jsSourceMappingURL);
|
||||
sourceMapRecoder.WriteLine("sourceRoot: " + sourceMapData.sourceMapSourceRoot);
|
||||
sourceMapRecoder.WriteLine("sources: " + sourceMapData.sourceMapSources);
|
||||
if (sourceMapData.sourceMapSourcesContent) {
|
||||
sourceMapRecoder.WriteLine("sourcesContent: " + JSON.stringify(sourceMapData.sourceMapSourcesContent));
|
||||
}
|
||||
sourceMapRecoder.WriteLine("===================================================================");
|
||||
}
|
||||
|
||||
function getSourceMapSpanString(mapEntry: ts.SourceMapSpan, getAbsentNameIndex?: boolean) {
|
||||
var mapString = "Emitted(" + mapEntry.emittedLine + ", " + mapEntry.emittedColumn + ") Source(" + mapEntry.sourceLine + ", " + mapEntry.sourceColumn + ") + SourceIndex(" + mapEntry.sourceIndex + ")";
|
||||
let mapString = "Emitted(" + mapEntry.emittedLine + ", " + mapEntry.emittedColumn + ") Source(" + mapEntry.sourceLine + ", " + mapEntry.sourceColumn + ") + SourceIndex(" + mapEntry.sourceIndex + ")";
|
||||
if (mapEntry.nameIndex >= 0 && mapEntry.nameIndex < sourceMapNames.length) {
|
||||
mapString += " name (" + sourceMapNames[mapEntry.nameIndex] + ")";
|
||||
}
|
||||
else {
|
||||
if (mapEntry.nameIndex != -1 || getAbsentNameIndex) {
|
||||
if ((mapEntry.nameIndex && mapEntry.nameIndex !== -1) || getAbsentNameIndex) {
|
||||
mapString += " nameIndex (" + mapEntry.nameIndex + ")";
|
||||
}
|
||||
}
|
||||
@@ -256,15 +258,15 @@ module Harness.SourceMapRecoder {
|
||||
|
||||
export function recordSourceMapSpan(sourceMapSpan: ts.SourceMapSpan) {
|
||||
// verify the decoded span is same as the new span
|
||||
var decodeResult = SourceMapDecoder.decodeNextEncodedSourceMapSpan();
|
||||
var decodedErrors: string[];
|
||||
const decodeResult = SourceMapDecoder.decodeNextEncodedSourceMapSpan();
|
||||
let decodedErrors: string[];
|
||||
if (decodeResult.error
|
||||
|| decodeResult.sourceMapSpan.emittedLine != sourceMapSpan.emittedLine
|
||||
|| decodeResult.sourceMapSpan.emittedColumn != sourceMapSpan.emittedColumn
|
||||
|| decodeResult.sourceMapSpan.sourceLine != sourceMapSpan.sourceLine
|
||||
|| decodeResult.sourceMapSpan.sourceColumn != sourceMapSpan.sourceColumn
|
||||
|| decodeResult.sourceMapSpan.sourceIndex != sourceMapSpan.sourceIndex
|
||||
|| decodeResult.sourceMapSpan.nameIndex != sourceMapSpan.nameIndex) {
|
||||
|| decodeResult.sourceMapSpan.emittedLine !== sourceMapSpan.emittedLine
|
||||
|| decodeResult.sourceMapSpan.emittedColumn !== sourceMapSpan.emittedColumn
|
||||
|| decodeResult.sourceMapSpan.sourceLine !== sourceMapSpan.sourceLine
|
||||
|| decodeResult.sourceMapSpan.sourceColumn !== sourceMapSpan.sourceColumn
|
||||
|| decodeResult.sourceMapSpan.sourceIndex !== sourceMapSpan.sourceIndex
|
||||
|| decodeResult.sourceMapSpan.nameIndex !== sourceMapSpan.nameIndex) {
|
||||
if (decodeResult.error) {
|
||||
decodedErrors = ["!!^^ !!^^ There was decoding error in the sourcemap at this location: " + decodeResult.error];
|
||||
}
|
||||
@@ -275,7 +277,7 @@ module Harness.SourceMapRecoder {
|
||||
}
|
||||
|
||||
if (spansOnSingleLine.length && spansOnSingleLine[0].sourceMapSpan.emittedLine !== sourceMapSpan.emittedLine) {
|
||||
// On different line from the one that we have been recording till now,
|
||||
// On different line from the one that we have been recording till now,
|
||||
writeRecordedSpans();
|
||||
spansOnSingleLine = [{ sourceMapSpan: sourceMapSpan, decodeErrors: decodedErrors }];
|
||||
}
|
||||
@@ -285,7 +287,7 @@ module Harness.SourceMapRecoder {
|
||||
}
|
||||
|
||||
export function recordNewSourceFileSpan(sourceMapSpan: ts.SourceMapSpan, newSourceFileCode: string) {
|
||||
assert.isTrue(spansOnSingleLine.length == 0 || spansOnSingleLine[0].sourceMapSpan.emittedLine !== sourceMapSpan.emittedLine, "new file source map span should be on new line. We currently handle only that scenario");
|
||||
assert.isTrue(spansOnSingleLine.length === 0 || spansOnSingleLine[0].sourceMapSpan.emittedLine !== sourceMapSpan.emittedLine, "new file source map span should be on new line. We currently handle only that scenario");
|
||||
recordSourceMapSpan(sourceMapSpan);
|
||||
|
||||
assert.isTrue(spansOnSingleLine.length === 1);
|
||||
@@ -314,8 +316,8 @@ module Harness.SourceMapRecoder {
|
||||
}
|
||||
|
||||
function getTextOfLine(line: number, lineMap: number[], code: string) {
|
||||
var startPos = lineMap[line];
|
||||
var endPos = lineMap[line + 1];
|
||||
const startPos = lineMap[line];
|
||||
const endPos = lineMap[line + 1];
|
||||
return code.substring(startPos, endPos);
|
||||
}
|
||||
|
||||
@@ -326,14 +328,16 @@ module Harness.SourceMapRecoder {
|
||||
}
|
||||
|
||||
function writeRecordedSpans() {
|
||||
const markerIds: string[] = [];
|
||||
|
||||
function getMarkerId(markerIndex: number) {
|
||||
var markerId = "";
|
||||
let markerId = "";
|
||||
if (spanMarkerContinues) {
|
||||
assert.isTrue(markerIndex === 0);
|
||||
markerId = "1->";
|
||||
}
|
||||
else {
|
||||
var markerId = "" + (markerIndex + 1);
|
||||
markerId = "" + (markerIndex + 1);
|
||||
if (markerId.length < 2) {
|
||||
markerId = markerId + " ";
|
||||
}
|
||||
@@ -342,10 +346,10 @@ module Harness.SourceMapRecoder {
|
||||
return markerId;
|
||||
}
|
||||
|
||||
var prevEmittedCol: number;
|
||||
let prevEmittedCol: number;
|
||||
function iterateSpans(fn: (currentSpan: SourceMapSpanWithDecodeErrors, index: number) => void) {
|
||||
prevEmittedCol = 1;
|
||||
for (var i = 0; i < spansOnSingleLine.length; i++) {
|
||||
for (let i = 0; i < spansOnSingleLine.length; i++) {
|
||||
fn(spansOnSingleLine[i], i);
|
||||
prevEmittedCol = spansOnSingleLine[i].sourceMapSpan.emittedColumn;
|
||||
}
|
||||
@@ -353,18 +357,18 @@ module Harness.SourceMapRecoder {
|
||||
|
||||
function writeSourceMapIndent(indentLength: number, indentPrefix: string) {
|
||||
sourceMapRecoder.Write(indentPrefix);
|
||||
for (var i = 1; i < indentLength; i++) {
|
||||
for (let i = 1; i < indentLength; i++) {
|
||||
sourceMapRecoder.Write(" ");
|
||||
}
|
||||
}
|
||||
|
||||
function writeSourceMapMarker(currentSpan: SourceMapSpanWithDecodeErrors, index: number, endColumn = currentSpan.sourceMapSpan.emittedColumn, endContinues?: boolean) {
|
||||
var markerId = getMarkerId(index);
|
||||
const markerId = getMarkerId(index);
|
||||
markerIds.push(markerId);
|
||||
|
||||
writeSourceMapIndent(prevEmittedCol, markerId);
|
||||
|
||||
for (var i = prevEmittedCol; i < endColumn; i++) {
|
||||
for (let i = prevEmittedCol; i < endColumn; i++) {
|
||||
sourceMapRecoder.Write("^");
|
||||
}
|
||||
if (endContinues) {
|
||||
@@ -375,8 +379,8 @@ module Harness.SourceMapRecoder {
|
||||
}
|
||||
|
||||
function writeSourceMapSourceText(currentSpan: SourceMapSpanWithDecodeErrors, index: number) {
|
||||
var sourcePos = tsLineMap[currentSpan.sourceMapSpan.sourceLine - 1] + (currentSpan.sourceMapSpan.sourceColumn - 1);
|
||||
var sourceText = "";
|
||||
const sourcePos = tsLineMap[currentSpan.sourceMapSpan.sourceLine - 1] + (currentSpan.sourceMapSpan.sourceColumn - 1);
|
||||
let sourceText = "";
|
||||
if (prevWrittenSourcePos < sourcePos) {
|
||||
// Position that goes forward, get text
|
||||
sourceText = tsCode.substring(prevWrittenSourcePos, sourcePos);
|
||||
@@ -384,17 +388,17 @@ module Harness.SourceMapRecoder {
|
||||
|
||||
if (currentSpan.decodeErrors) {
|
||||
// If there are decode errors, write
|
||||
for (var i = 0; i < currentSpan.decodeErrors.length; i++) {
|
||||
for (let i = 0; i < currentSpan.decodeErrors.length; i++) {
|
||||
writeSourceMapIndent(prevEmittedCol, markerIds[index]);
|
||||
sourceMapRecoder.WriteLine(currentSpan.decodeErrors[i]);
|
||||
}
|
||||
}
|
||||
|
||||
var tsCodeLineMap = ts.computeLineStarts(sourceText);
|
||||
for (var i = 0; i < tsCodeLineMap.length; i++) {
|
||||
writeSourceMapIndent(prevEmittedCol, i == 0 ? markerIds[index] : " >");
|
||||
const tsCodeLineMap = ts.computeLineStarts(sourceText);
|
||||
for (let i = 0; i < tsCodeLineMap.length; i++) {
|
||||
writeSourceMapIndent(prevEmittedCol, i === 0 ? markerIds[index] : " >");
|
||||
sourceMapRecoder.Write(getTextOfLine(i, tsCodeLineMap, sourceText));
|
||||
if (i == tsCodeLineMap.length - 1) {
|
||||
if (i === tsCodeLineMap.length - 1) {
|
||||
sourceMapRecoder.WriteLine("");
|
||||
}
|
||||
}
|
||||
@@ -407,16 +411,15 @@ module Harness.SourceMapRecoder {
|
||||
}
|
||||
|
||||
if (spansOnSingleLine.length) {
|
||||
var currentJsLine = spansOnSingleLine[0].sourceMapSpan.emittedLine;
|
||||
const currentJsLine = spansOnSingleLine[0].sourceMapSpan.emittedLine;
|
||||
|
||||
// Write js line
|
||||
writeJsFileLines(currentJsLine);
|
||||
|
||||
// Emit markers
|
||||
var markerIds: string[] = [];
|
||||
iterateSpans(writeSourceMapMarker);
|
||||
|
||||
var jsFileText = getTextOfLine(currentJsLine, jsLineMap, jsFile.code);
|
||||
const jsFileText = getTextOfLine(currentJsLine, jsLineMap, jsFile.code);
|
||||
if (prevEmittedCol < jsFileText.length) {
|
||||
// There is remaining text on this line that will be part of next source span so write marker that continues
|
||||
writeSourceMapMarker(undefined, spansOnSingleLine.length, /*endColumn*/ jsFileText.length, /*endContinues*/ true);
|
||||
@@ -434,17 +437,17 @@ module Harness.SourceMapRecoder {
|
||||
}
|
||||
|
||||
export function getSourceMapRecord(sourceMapDataList: ts.SourceMapData[], program: ts.Program, jsFiles: Compiler.GeneratedFile[]) {
|
||||
var sourceMapRecoder = new Compiler.WriterAggregator();
|
||||
const sourceMapRecoder = new Compiler.WriterAggregator();
|
||||
|
||||
for (var i = 0; i < sourceMapDataList.length; i++) {
|
||||
var sourceMapData = sourceMapDataList[i];
|
||||
var prevSourceFile: ts.SourceFile = null;
|
||||
for (let i = 0; i < sourceMapDataList.length; i++) {
|
||||
const sourceMapData = sourceMapDataList[i];
|
||||
let prevSourceFile: ts.SourceFile;
|
||||
|
||||
SourceMapSpanWriter.intializeSourceMapSpanWriter(sourceMapRecoder, sourceMapData, jsFiles[i]);
|
||||
for (var j = 0; j < sourceMapData.sourceMapDecodedMappings.length; j++) {
|
||||
var decodedSourceMapping = sourceMapData.sourceMapDecodedMappings[j];
|
||||
var currentSourceFile = program.getSourceFile(sourceMapData.inputSourceFileNames[decodedSourceMapping.sourceIndex]);
|
||||
if (currentSourceFile != prevSourceFile) {
|
||||
for (let j = 0; j < sourceMapData.sourceMapDecodedMappings.length; j++) {
|
||||
const decodedSourceMapping = sourceMapData.sourceMapDecodedMappings[j];
|
||||
const currentSourceFile = program.getSourceFile(sourceMapData.inputSourceFileNames[decodedSourceMapping.sourceIndex]);
|
||||
if (currentSourceFile !== prevSourceFile) {
|
||||
SourceMapSpanWriter.recordNewSourceFileSpan(decodedSourceMapping, currentSourceFile.text);
|
||||
prevSourceFile = currentSourceFile;
|
||||
}
|
||||
@@ -452,9 +455,9 @@ module Harness.SourceMapRecoder {
|
||||
SourceMapSpanWriter.recordSourceMapSpan(decodedSourceMapping);
|
||||
}
|
||||
}
|
||||
SourceMapSpanWriter.close();// If the last spans werent emitted, emit them
|
||||
SourceMapSpanWriter.close(); // If the last spans werent emitted, emit them
|
||||
}
|
||||
sourceMapRecoder.Close();
|
||||
return sourceMapRecoder.lines.join('\r\n');
|
||||
return sourceMapRecoder.lines.join("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
// Use this to get emitter-agnostic baselines
|
||||
|
||||
class SyntacticCleaner {
|
||||
static clean(sourceFileContents: string) {
|
||||
return sourceFileContents;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Re-implement or maybe delete
|
||||
class SyntacticCleaner extends TypeScript.SyntaxWalker {
|
||||
private emit: string[] = [];
|
||||
|
||||
public visitToken(token: TypeScript.ISyntaxToken): void {
|
||||
this.emit.push(token.text());
|
||||
if (token.kind() === TypeScript.SyntaxKind.SemicolonToken) {
|
||||
this.emit.push('\r\n');
|
||||
} else {
|
||||
this.emit.push(' ');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static clean(sourceFileContents: string): string {
|
||||
var parsed = TypeScript.Parser.parse('_emitted.ts', TypeScript.SimpleText.fromString(sourceFileContents), TypeScript.LanguageVersion.EcmaScript5, false);
|
||||
var cleaner = new SyntacticCleaner();
|
||||
cleaner.visitSourceUnit(parsed.sourceUnit());
|
||||
return cleaner.emit.join('');
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -1,13 +1,13 @@
|
||||
/// <reference path='harness.ts' />
|
||||
/// <reference path='runnerbase.ts' />
|
||||
/// <reference path='syntacticCleaner.ts' />
|
||||
/// <reference path="harness.ts" />
|
||||
/// <reference path="runnerbase.ts" />
|
||||
/* tslint:disable:no-null */
|
||||
|
||||
class Test262BaselineRunner extends RunnerBase {
|
||||
private static basePath = 'internal/cases/test262';
|
||||
private static helpersFilePath = 'tests/cases/test262-harness/helpers.d.ts';
|
||||
private static helperFile = {
|
||||
private static basePath = "internal/cases/test262";
|
||||
private static helpersFilePath = "tests/cases/test262-harness/helpers.d.ts";
|
||||
private static helperFile: Harness.Compiler.TestFile = {
|
||||
unitName: Test262BaselineRunner.helpersFilePath,
|
||||
content: Harness.IO.readFile(Test262BaselineRunner.helpersFilePath)
|
||||
content: Harness.IO.readFile(Test262BaselineRunner.helpersFilePath),
|
||||
};
|
||||
private static testFileExtensionRegex = /\.js$/;
|
||||
private static options: ts.CompilerOptions = {
|
||||
@@ -16,8 +16,8 @@ class Test262BaselineRunner extends RunnerBase {
|
||||
module: ts.ModuleKind.CommonJS
|
||||
};
|
||||
private static baselineOptions: Harness.Baseline.BaselineOptions = {
|
||||
Subfolder: 'test262',
|
||||
Baselinefolder: 'internal/baselines'
|
||||
Subfolder: "test262",
|
||||
Baselinefolder: "internal/baselines"
|
||||
};
|
||||
|
||||
private static getTestFilePath(filename: string): string {
|
||||
@@ -25,23 +25,23 @@ class Test262BaselineRunner extends RunnerBase {
|
||||
}
|
||||
|
||||
private runTest(filePath: string) {
|
||||
describe('test262 test for ' + filePath, () => {
|
||||
describe("test262 test for " + filePath, () => {
|
||||
// Mocha holds onto the closure environment of the describe callback even after the test is done.
|
||||
// Everything declared here should be cleared out in the "after" callback.
|
||||
var testState: {
|
||||
let testState: {
|
||||
filename: string;
|
||||
compilerResult: Harness.Compiler.CompilerResult;
|
||||
inputFiles: { unitName: string; content: string }[];
|
||||
program: ts.Program;
|
||||
inputFiles: Harness.Compiler.TestFile[];
|
||||
};
|
||||
|
||||
before(() => {
|
||||
var content = Harness.IO.readFile(filePath);
|
||||
var testFilename = ts.removeFileExtension(filePath).replace(/\//g, '_') + ".test";
|
||||
var testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, testFilename);
|
||||
const content = Harness.IO.readFile(filePath);
|
||||
const testFilename = ts.removeFileExtension(filePath).replace(/\//g, "_") + ".test";
|
||||
const testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, testFilename);
|
||||
|
||||
var inputFiles = testCaseContent.testUnitData.map(unit => {
|
||||
return { unitName: Test262BaselineRunner.getTestFilePath(unit.name), content: unit.content };
|
||||
const inputFiles: Harness.Compiler.TestFile[] = testCaseContent.testUnitData.map(unit => {
|
||||
const unitName = Test262BaselineRunner.getTestFilePath(unit.name);
|
||||
return { unitName, content: unit.content };
|
||||
});
|
||||
|
||||
// Emit the results
|
||||
@@ -49,29 +49,32 @@ class Test262BaselineRunner extends RunnerBase {
|
||||
filename: testFilename,
|
||||
inputFiles: inputFiles,
|
||||
compilerResult: undefined,
|
||||
program: undefined,
|
||||
};
|
||||
|
||||
Harness.Compiler.getCompiler().compileFiles([Test262BaselineRunner.helperFile].concat(inputFiles), /*otherFiles*/ [], (compilerResult, program) => {
|
||||
testState.compilerResult = compilerResult;
|
||||
testState.program = program;
|
||||
}, /*settingsCallback*/ undefined, Test262BaselineRunner.options);
|
||||
const output = Harness.Compiler.compileFiles(
|
||||
[Test262BaselineRunner.helperFile].concat(inputFiles),
|
||||
/*otherFiles*/ [],
|
||||
/* harnessOptions */ undefined,
|
||||
Test262BaselineRunner.options,
|
||||
/* currentDirectory */ undefined
|
||||
);
|
||||
testState.compilerResult = output.result;
|
||||
});
|
||||
|
||||
after(() => {
|
||||
testState = undefined;
|
||||
});
|
||||
|
||||
it('has the expected emitted code', () => {
|
||||
Harness.Baseline.runBaseline('has the expected emitted code', testState.filename + '.output.js', () => {
|
||||
var files = testState.compilerResult.files.filter(f=> f.fileName !== Test262BaselineRunner.helpersFilePath);
|
||||
return Harness.Compiler.collateOutputs(files, s => SyntacticCleaner.clean(s));
|
||||
it("has the expected emitted code", () => {
|
||||
Harness.Baseline.runBaseline("has the expected emitted code", testState.filename + ".output.js", () => {
|
||||
const files = testState.compilerResult.files.filter(f => f.fileName !== Test262BaselineRunner.helpersFilePath);
|
||||
return Harness.Compiler.collateOutputs(files);
|
||||
}, false, Test262BaselineRunner.baselineOptions);
|
||||
});
|
||||
|
||||
it('has the expected errors', () => {
|
||||
Harness.Baseline.runBaseline('has the expected errors', testState.filename + '.errors.txt', () => {
|
||||
var errors = testState.compilerResult.errors;
|
||||
it("has the expected errors", () => {
|
||||
Harness.Baseline.runBaseline("has the expected errors", testState.filename + ".errors.txt", () => {
|
||||
const errors = testState.compilerResult.errors;
|
||||
if (errors.length === 0) {
|
||||
return null;
|
||||
}
|
||||
@@ -80,14 +83,14 @@ class Test262BaselineRunner extends RunnerBase {
|
||||
}, false, Test262BaselineRunner.baselineOptions);
|
||||
});
|
||||
|
||||
it('satisfies invariants', () => {
|
||||
var sourceFile = testState.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename));
|
||||
it("satisfies invariants", () => {
|
||||
const sourceFile = testState.compilerResult.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.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename));
|
||||
it("has the expected AST", () => {
|
||||
Harness.Baseline.runBaseline("has the expected AST", testState.filename + ".AST.txt", () => {
|
||||
const sourceFile = testState.compilerResult.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename));
|
||||
return Utils.sourceFileToJSON(sourceFile);
|
||||
}, false, Test262BaselineRunner.baselineOptions);
|
||||
});
|
||||
@@ -97,7 +100,7 @@ class Test262BaselineRunner extends RunnerBase {
|
||||
public initializeTests() {
|
||||
// this will set up a series of describe/it blocks to run between the setup and cleanup phases
|
||||
if (this.tests.length === 0) {
|
||||
var testFiles = this.enumerateFiles(Test262BaselineRunner.basePath, Test262BaselineRunner.testFileExtensionRegex, { recursive: true });
|
||||
const testFiles = this.enumerateFiles(Test262BaselineRunner.basePath, Test262BaselineRunner.testFileExtensionRegex, { recursive: true });
|
||||
testFiles.forEach(fn => {
|
||||
this.runTest(ts.normalizePath(fn));
|
||||
});
|
||||
@@ -106,4 +109,4 @@ class Test262BaselineRunner extends RunnerBase {
|
||||
this.tests.forEach(test => this.runTest(test));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+19
-14
@@ -13,7 +13,7 @@ class TypeWriterWalker {
|
||||
private checker: ts.TypeChecker;
|
||||
|
||||
constructor(private program: ts.Program, fullTypeCheck: boolean) {
|
||||
// Consider getting both the diagnostics checker and the non-diagnostics checker to verify
|
||||
// Consider getting both the diagnostics checker and the non-diagnostics checker to verify
|
||||
// they are consistent.
|
||||
this.checker = fullTypeCheck
|
||||
? program.getDiagnosticsProducingTypeChecker()
|
||||
@@ -21,7 +21,7 @@ class TypeWriterWalker {
|
||||
}
|
||||
|
||||
public getTypeAndSymbols(fileName: string): TypeWriterResult[] {
|
||||
var sourceFile = this.program.getSourceFile(fileName);
|
||||
const sourceFile = this.program.getSourceFile(fileName);
|
||||
this.currentSourceFile = sourceFile;
|
||||
this.results = [];
|
||||
this.visitNode(sourceFile);
|
||||
@@ -37,24 +37,29 @@ class TypeWriterWalker {
|
||||
}
|
||||
|
||||
private logTypeAndSymbol(node: ts.Node): void {
|
||||
var actualPos = ts.skipTrivia(this.currentSourceFile.text, node.pos);
|
||||
var lineAndCharacter = this.currentSourceFile.getLineAndCharacterOfPosition(actualPos);
|
||||
var sourceText = ts.getTextOfNodeFromSourceText(this.currentSourceFile.text, node);
|
||||
const actualPos = ts.skipTrivia(this.currentSourceFile.text, node.pos);
|
||||
const lineAndCharacter = this.currentSourceFile.getLineAndCharacterOfPosition(actualPos);
|
||||
const sourceText = ts.getTextOfNodeFromSourceText(this.currentSourceFile.text, node);
|
||||
|
||||
// Workaround to ensure we output 'C' instead of 'typeof C' for base class expressions
|
||||
// let type = this.checker.getTypeAtLocation(node);
|
||||
const type = node.parent && ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent) && this.checker.getTypeAtLocation(node.parent) || this.checker.getTypeAtLocation(node);
|
||||
|
||||
var type = this.checker.getTypeAtLocation(node);
|
||||
ts.Debug.assert(type !== undefined, "type doesn't exist");
|
||||
var symbol = this.checker.getSymbolAtLocation(node);
|
||||
const symbol = this.checker.getSymbolAtLocation(node);
|
||||
|
||||
var typeString = this.checker.typeToString(type, node.parent, ts.TypeFormatFlags.NoTruncation);
|
||||
var symbolString: string;
|
||||
const typeString = this.checker.typeToString(type, node.parent, ts.TypeFormatFlags.NoTruncation);
|
||||
let symbolString: string;
|
||||
if (symbol) {
|
||||
symbolString = "Symbol(" + this.checker.symbolToString(symbol, node.parent);
|
||||
if (symbol.declarations) {
|
||||
for (let declaration of symbol.declarations) {
|
||||
for (const declaration of symbol.declarations) {
|
||||
symbolString += ", ";
|
||||
let declSourceFile = declaration.getSourceFile();
|
||||
let declLineAndCharacter = declSourceFile.getLineAndCharacterOfPosition(declaration.pos);
|
||||
symbolString += `Decl(${ ts.getBaseFileName(declSourceFile.fileName) }, ${ declLineAndCharacter.line }, ${ declLineAndCharacter.character })`
|
||||
const declSourceFile = declaration.getSourceFile();
|
||||
const declLineAndCharacter = declSourceFile.getLineAndCharacterOfPosition(declaration.pos);
|
||||
const fileName = ts.getBaseFileName(declSourceFile.fileName);
|
||||
const isLibFile = /lib(.*)\.d\.ts/i.test(fileName);
|
||||
symbolString += `Decl(${ fileName }, ${ isLibFile ? "--" : declLineAndCharacter.line }, ${ isLibFile ? "--" : declLineAndCharacter.character })`;
|
||||
}
|
||||
}
|
||||
symbolString += ")";
|
||||
@@ -68,4 +73,4 @@ class TypeWriterWalker {
|
||||
symbol: symbolString
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user