Merge branch 'master' into rwcRunner

This commit is contained in:
Sheetal Nandi
2014-10-15 10:36:36 -07:00
3269 changed files with 78134 additions and 34271 deletions
+1
View File
@@ -36,4 +36,5 @@ tests/*.d.ts
*.config
scripts/debug.bat
scripts/run.bat
scripts/word2md.js
coverage/
+52 -5
View File
@@ -2,6 +2,7 @@
var fs = require("fs");
var path = require("path");
var child_process = require("child_process");
// Variables
var compilerDirectory = "src/compiler/";
@@ -9,6 +10,7 @@ var servicesDirectory = "src/services/";
var harnessDirectory = "src/harness/";
var libraryDirectory = "src/lib/";
var scriptsDirectory = "scripts/";
var docDirectory = "doc/";
var builtDirectory = "built/";
var builtLocalDirectory = "built/local/";
@@ -54,6 +56,10 @@ var servicesSources = [
}).concat([
"services.ts",
"shims.ts",
"signatureHelp.ts",
"utilities.ts",
"navigationBar.ts",
"outliningElementsCollector.ts"
].map(function (f) {
return path.join(servicesDirectory, f);
}));
@@ -63,7 +69,6 @@ var harnessSources = [
"sourceMapRecorder.ts",
"harnessLanguageService.ts",
"fourslash.ts",
"external/json2.ts",
"runnerbase.ts",
"compilerRunner.ts",
"typeWriter.ts",
@@ -123,6 +128,7 @@ function concatenateFiles(destinationFile, sourceFiles) {
}
var useDebugMode = false;
var generateDeclarations = false;
var host = (process.env.host || process.env.TYPESCRIPT_HOST || "node");
var compilerFilename = "tsc.js";
/* Compiles a file from a list of sources
@@ -137,6 +143,9 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOu
file(outFile, prereqs, function() {
var dir = useBuiltCompiler ? builtLocalDirectory : LKGDirectory;
var options = "-removeComments --module commonjs -noImplicitAny "; //" -propagateEnumConstants "
if (generateDeclarations) {
options += "--declaration ";
}
var cmd = host + " " + dir + compilerFilename + " " + options + " ";
if (useDebugMode) {
@@ -245,7 +254,7 @@ task("local", ["generate-diagnostics", "lib", tscFile, servicesFile]);
// Local target to build the compiler and services
desc("Emit debug mode files with sourcemaps");
task("debug", function() {
useDebugMode = true;
useDebugMode = true;
});
@@ -259,6 +268,44 @@ task("clean", function() {
jake.rmRf(builtDirectory);
});
// generate declarations for compiler and services
desc("Generate declarations for compiler and services");
task("declaration", function() {
generateDeclarations = true;
});
// 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");
var headerMd = path.join(docDirectory, "header.md");
file(word2mdTs);
// word2md script
compileFile(word2mdJs,
[word2mdTs],
[word2mdTs],
[],
false);
// The generated spec.md; built for the 'generate-spec' task
file(specMd, [word2mdJs, specWord], function () {
jake.cpR(headerMd, specMd, {silent: true});
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", libraryTargets, function() {
@@ -318,7 +365,7 @@ function exec(cmd, completeHandler) {
complete();
})
try{
ex.run();
ex.run();
} catch(e) {
console.log('Exception: ' + e)
}
@@ -342,7 +389,7 @@ function cleanTestDirs() {
function writeTestConfigFile(tests, testConfigFile) {
console.log('Running test(s): ' + tests);
var testConfigContents = '{\n' + '\ttest: [\'' + tests + '\']\n}';
fs.writeFileSync('test.config', testConfigContents);
fs.writeFileSync('test.config', testConfigContents);
}
function deleteTemporaryProjectOutput() {
@@ -385,7 +432,7 @@ 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);
exec(cmd);
}, { async: true });
// Browser tests
+17 -11
View File
@@ -1,3 +1,7 @@
[![Build Status](https://travis-ci.org/Microsoft/TypeScript.svg?branch=master)](https://travis-ci.org/Microsoft/TypeScript)
[![Issue Stats](http://issuestats.com/github/Microsoft/TypeScript/badge/pr)](http://issuestats.com/github/microsoft/typescript)
[![Issue Stats](http://issuestats.com/github/Microsoft/TypeScript/badge/issue)](http://issuestats.com/github/microsoft/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).
@@ -18,7 +22,7 @@ There are many ways to [contribute](https://github.com/Microsoft/TypeScript/blob
* [Quick tutorial](http://www.typescriptlang.org/Tutorial)
* [Programming handbook](http://www.typescriptlang.org/Handbook)
* [Language specification](http://go.microsoft.com/fwlink/?LinkId=267238)
* [Language specification](https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md)
* [Homepage](http://www.typescriptlang.org/)
## Building
@@ -47,16 +51,18 @@ npm install
Use one of the following to build and test:
```
jake local # Build the compiler into built/local
jake clean # Delete the built compiler
jake LKG # Replace the last known good with the built one.
# Bootstrapping step to be executed when the built compiler reaches a stable state.
jake tests # Build the test infrastructure using the built compiler.
jake runtests # Run tests using the built compiler and test infrastructure.
# You can override the host or specify a test for this command.
# Use host=<hostName> or tests=<testPath>.
jake baseline-accept # This replaces the baseline test results with the results obtained from jake runtests.
jake -T # List the above commands.
jake local # Build the compiler into built/local
jake clean # Delete the built compiler
jake LKG # Replace the last known good with the built one.
# Bootstrapping step to be executed when the built compiler reaches a stable state.
jake tests # Build the test infrastructure using the built compiler.
jake runtests # Run tests using the built compiler and test infrastructure.
# You can override the host or specify a test for this command.
# 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 -T # List the above commands.
```
-61
View File
@@ -19,67 +19,6 @@ limitations under the License.
---------------------------------------------
Third Party Code Components
--------------------------------------------
---- Mozilla Developer Code---------
The following Mozilla Developer Code is under Public Domain as updated after Aug. 20, 2012, see, https://developer.mozilla.org/en-US/docs/Project:Copyrights
1. Array filter Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/filter
Any copyright is dedicated to the Public Domain.
2. Array forEach Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach
Any copyright is dedicated to the Public Domain.
3. Array indexOf Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf
Any copyright is dedicated to the Public Domain.
4. Array map Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map
Any copyright is dedicated to the Public Domain.
5. Array Reduce Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/Reduce
Any copyright is dedicated to the Public Domain.
6. String Trim Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String/Trim
Any copyright is dedicated to the Public Domain.
7. Date now Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date/now
Any copyright is dedicated to the Public Domain.
------------JSON2 Script------------------------
json2.js 2012-10-08
Public Domain.
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
See, http://www.JSON.org/js.html
--------------r.js----------------------
Copyright (c) 2010-2011 Dojo Foundation. All Rights Reserved.
Originally License under MIT License
-------------------------------------------------------------------------
Provided for Informational Purposes Only
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------- DefinitelyTyped --------------------
This file is based on or incorporates material from the projects listed below (collectively ?Third Party Code?). Microsoft is not the original author of the Third Party Code. The original copyright notice and the license, under which Microsoft received such Third Party Code, are set forth below. Such licenses and notices are provided for informational purposes only. Microsoft, not the third party, licenses the Third Party Code to you under the terms set forth in the EULA for the Microsoft Product. Microsoft reserves all other rights not expressly granted under this agreement, whether by implication, estoppel or otherwise.
+16 -16
View File
@@ -1182,14 +1182,14 @@ interface Int8Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Int8Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -1240,14 +1240,14 @@ interface Uint8Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Uint8Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -1298,14 +1298,14 @@ interface Int16Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Int16Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -1356,14 +1356,14 @@ interface Uint16Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Uint16Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -1414,14 +1414,14 @@ interface Int32Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Int32Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -1472,14 +1472,14 @@ interface Uint32Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Uint32Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -1530,14 +1530,14 @@ interface Float32Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Float32Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -1588,14 +1588,14 @@ interface Float64Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Float64Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
+16 -16
View File
@@ -79,14 +79,14 @@ interface Int8Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Int8Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -137,14 +137,14 @@ interface Uint8Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Uint8Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -195,14 +195,14 @@ interface Int16Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Int16Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -253,14 +253,14 @@ interface Uint16Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Uint16Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -311,14 +311,14 @@ interface Int32Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Int32Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -369,14 +369,14 @@ interface Uint32Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Uint32Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -427,14 +427,14 @@ interface Float32Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Float32Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -485,14 +485,14 @@ interface Float64Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Float64Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
+16 -16
View File
@@ -79,14 +79,14 @@ interface Int8Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Int8Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -137,14 +137,14 @@ interface Uint8Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Uint8Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -195,14 +195,14 @@ interface Int16Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Int16Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -253,14 +253,14 @@ interface Uint16Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Uint16Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -311,14 +311,14 @@ interface Int32Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Int32Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -369,14 +369,14 @@ interface Uint32Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Uint32Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -427,14 +427,14 @@ interface Float32Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Float32Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -485,14 +485,14 @@ interface Float64Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Float64Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
+2509 -2077
View File
File diff suppressed because it is too large Load Diff
+5109 -3585
View File
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
+2
View File
@@ -0,0 +1,2 @@
# TypeScript Language Specification
+5438
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "typescript",
"author": "Microsoft Corp.",
"homepage": "http://typescriptlang.org/",
"version": "1.1.0",
"version": "1.3.0",
"licenses": [
{
"type": "Apache License 2.0",
+184
View File
@@ -0,0 +1,184 @@
var sys = (function () {
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) { return WScript.StdOut.Write(s); }
};
})();
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("&emsp;&emsp;" + text.replace(/\s\s\s/g, "&emsp;").replace(/\x0B/g, " \n&emsp;&emsp;&emsp;") + "\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() {
for (var p = doc.paragraphs.first; p; p = p.next()) {
writeParagraph(p);
}
writeBlockEnd();
}
findReplace("<", {}, "&lt;", {});
findReplace("&lt;", { style: "Code" }, "<", {});
findReplace("&lt;", { style: "Code Fragment" }, "<", {});
findReplace("&lt;", { 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();
return result;
}
function main(args) {
if (args.length !== 1) {
sys.write("Syntax: word2md <filename>\n");
return;
}
var app = sys.createObject("Word.Application");
var doc = app.documents.open(args[0]);
sys.write(convertDocumentToMarkdown(doc));
doc.close(false);
app.quit();
}
main(sys.args);
+339
View File
@@ -0,0 +1,339 @@
// word2md - Word to Markdown conversion tool
//
// word2md converts a Microsoft Word document to Markdown formatted text. The tool uses the
// Word Automation APIs to start an instance of Word and access the contents of the document
// being converted. The tool must be run using the cscript.exe script host and requires Word
// to be installed on the target machine. The name of the document to convert must be specified
// as a command line argument and the resulting Markdown is written to standard output. The
// tool recognizes the specific Word styles used in the TypeScript Language Specification.
module Word {
export interface Collection<T> {
count: number;
item(index: number): T;
}
export interface Font {
bold: boolean;
italic: boolean;
subscript: boolean;
superscript: boolean;
}
export interface Find {
font: Font;
format: boolean;
replacement: Replacement;
style: any;
text: string;
clearFormatting(): void;
execute(
findText: string,
matchCase: boolean,
matchWholeWord: boolean,
matchWildcards: boolean,
matchSoundsLike: boolean,
matchAllWordForms: boolean,
forward: boolean,
wrap: number,
format: boolean,
replaceWith: string,
replace: number): boolean;
}
export interface Replacement {
font: Font;
style: any;
text: string;
clearFormatting(): void;
}
export interface ListFormat {
listLevelNumber: number;
listString: string;
}
export interface Column {
}
export interface Columns extends Collection<Column> {
}
export interface Table {
columns: Columns;
}
export interface Tables extends Collection<Table> {
}
export interface Range {
find: Find;
listFormat: ListFormat;
tables: Tables;
text: string;
words: Ranges;
}
export interface Ranges extends Collection<Range> {
}
export interface Style {
nameLocal: string;
}
export interface Paragraph {
alignment: number;
range: Range;
style: Style;
next(): Paragraph;
}
export interface Paragraphs extends Collection<Paragraph> {
first: Paragraph;
}
export interface Field {
}
export interface Fields extends Collection<Field> {
toggleShowCodes(): void;
}
export interface Document {
fields: Fields;
paragraphs: Paragraphs;
close(saveChanges: boolean): void;
range(): Range;
}
export interface Documents extends Collection<Document> {
open(filename: string): Document;
}
export interface Application {
documents: Documents;
quit(): void;
}
}
var sys = (function () {
var args: string[] = [];
for (var i = 0; i < WScript.Arguments.length; i++) {
args[i] = WScript.Arguments.Item(i);
}
return {
args: args,
createObject: (typeName: string) => new ActiveXObject(typeName),
write: (s: string) => WScript.StdOut.Write(s)
};
})();
interface FindReplaceOptions {
style?: any;
font?: {
bold?: boolean;
italic?: boolean;
subscript?: boolean;
};
}
function convertDocumentToMarkdown(doc: Word.Document): string {
var result: string = "";
var lastStyle: string;
var lastInTable: boolean;
var tableColumnCount: number;
var tableCellIndex: number;
var columnAlignment: number[] = [];
function setProperties(target: any, properties: any) {
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: string, findOptions: FindReplaceOptions, replaceText: string, replaceOptions: FindReplaceOptions) {
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: string) {
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: string) {
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: Word.Paragraph) {
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("&emsp;&emsp;" + text.replace(/\s\s\s/g, "&emsp;").replace(/\x0B/g, " \n&emsp;&emsp;&emsp;") + "\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() {
for (var p = doc.paragraphs.first; p; p = p.next()) {
writeParagraph(p);
}
writeBlockEnd();
}
findReplace("<", {}, "&lt;", {});
findReplace("&lt;", { style: "Code" }, "<", {});
findReplace("&lt;", { style: "Code Fragment" }, "<", {});
findReplace("&lt;", { style: "Terminal" }, "<", {});
findReplace("", { font: { subscript: true } }, "<sub>^&</sub>", { font: { subscript: false } });
findReplace("", { style: "Code Fragment" }, "`^&`", { style: -66 /* default font */ });
findReplace("", { style: "Production" }, "*^&*", { style: -66 /* default font */});
findReplace("", { style: "Terminal" }, "`^&`", { style: -66 /* default font */});
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();
return result;
}
function main(args: string[]) {
if (args.length !== 1) {
sys.write("Syntax: word2md <filename>\n");
return;
}
var app: Word.Application = sys.createObject("Word.Application");
var doc = app.documents.open(args[0]);
sys.write(convertDocumentToMarkdown(doc));
doc.close(false);
app.quit();
}
main(sys.args);
+9 -4
View File
@@ -84,8 +84,13 @@ module ts {
if (node.name) {
node.name.parent = node;
}
file.semanticErrors.push(createDiagnosticForNode(node.name ? node.name : node,
Diagnostics.Duplicate_identifier_0, getDisplayName(node)));
// Report errors every position with duplicate declaration
// Report errors on previous encountered declarations
forEach(symbol.declarations, (declaration) => {
file.semanticErrors.push(createDiagnosticForNode(declaration.name, Diagnostics.Duplicate_identifier_0, getDisplayName(declaration)));
});
file.semanticErrors.push(createDiagnosticForNode(node.name, Diagnostics.Duplicate_identifier_0, getDisplayName(node)));
symbol = createSymbol(0, name);
}
}
@@ -226,7 +231,7 @@ module ts {
function bindConstructorDeclaration(node: ConstructorDeclaration) {
bindDeclaration(node, SymbolFlags.Constructor, 0);
forEach(node.parameters, p => {
if (p.flags & (NodeFlags.Public | NodeFlags.Private)) {
if (p.flags & (NodeFlags.Public | NodeFlags.Private | NodeFlags.Protected)) {
bindDeclaration(p, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
}
});
@@ -332,7 +337,7 @@ module ts {
break;
case SyntaxKind.SourceFile:
if (isExternalModule(<SourceFile>node)) {
bindAnonymousDeclaration(node, SymbolFlags.ValueModule, '"' + getModuleNameFromFilename((<SourceFile>node).filename) + '"');
bindAnonymousDeclaration(node, SymbolFlags.ValueModule, '"' + removeFileExtension((<SourceFile>node).filename) + '"');
break;
}
default:
+1764 -677
View File
File diff suppressed because it is too large Load Diff
+77 -22
View File
@@ -11,7 +11,9 @@ module ts {
var result: U;
if (array) {
for (var i = 0, len = array.length; i < len; i++) {
if (result = callback(array[i])) break;
if (result = callback(array[i])) {
break;
}
}
}
return result;
@@ -19,8 +21,7 @@ module ts {
export function contains<T>(array: T[], value: T): boolean {
if (array) {
var len = array.length;
for (var i = 0; i < len; i++) {
for (var i = 0, len = array.length; i < len; i++) {
if (array[i] === value) {
return true;
}
@@ -31,8 +32,7 @@ module ts {
export function indexOf<T>(array: T[], value: T): number {
if (array) {
var len = array.length;
for (var i = 0; i < len; i++) {
for (var i = 0, len = array.length; i < len; i++) {
if (array[i] === value) {
return i;
}
@@ -41,10 +41,21 @@ module ts {
return -1;
}
export function filter<T>(array: T[], f: (x: T) => boolean): T[] {
var result: T[];
export function countWhere<T>(array: T[], predicate: (x: T) => boolean): number {
var count = 0;
if (array) {
result = [];
for (var i = 0, len = array.length; i < len; i++) {
if (predicate(array[i])) {
count++;
}
}
}
return count;
}
export function filter<T>(array: T[], f: (x: T) => boolean): T[] {
if (array) {
var result: T[] = [];
for (var i = 0, len = array.length; i < len; i++) {
var item = array[i];
if (f(item)) {
@@ -56,11 +67,9 @@ module ts {
}
export function map<T, U>(array: T[], f: (x: T) => U): U[] {
var result: U[];
if (array) {
result = [];
var len = array.length;
for (var i = 0; i < len; i++) {
var result: U[] = [];
for (var i = 0, len = array.length; i < len; i++) {
result.push(f(array[i]));
}
}
@@ -73,6 +82,17 @@ module ts {
return array1.concat(array2);
}
export function deduplicate<T>(array: T[]): T[] {
if (array) {
var result: T[] = [];
for (var i = 0, len = array.length; i < len; i++) {
var item = array[i];
if (!contains(result, item)) result.push(item);
}
}
return result;
}
export function sum(array: any[], prop: string): number {
var result = 0;
for (var i = 0; i < array.length; i++) {
@@ -189,11 +209,9 @@ module ts {
export var localizedDiagnosticMessages: Map<string> = undefined;
export function getLocaleSpecificMessage(message: string) {
if (ts.localizedDiagnosticMessages) {
message = localizedDiagnosticMessages[message];
}
return message;
return localizedDiagnosticMessages && localizedDiagnosticMessages[message]
? localizedDiagnosticMessages[message]
: message;
}
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: any[]): Diagnostic;
@@ -401,7 +419,7 @@ module ts {
return normalizedPathComponents(path, rootLength);
}
export function getNormalizedPathFromPathCompoments(pathComponents: string[]) {
export function getNormalizedPathFromPathComponents(pathComponents: string[]) {
if (pathComponents && pathComponents.length) {
return pathComponents[0] + pathComponents.slice(1).join(directorySeparator);
}
@@ -458,18 +476,18 @@ module ts {
}
}
export function getRelativePathToDirectoryOrUrl(directoryPathOrUrl: string, relativeOrAbsolutePath: string, currentDirectory: string, isAbsolutePathAnUrl: boolean) {
export function getRelativePathToDirectoryOrUrl(directoryPathOrUrl: string, relativeOrAbsolutePath: string, currentDirectory: string, getCanonicalFileName: (fileName: string) => string, isAbsolutePathAnUrl: boolean) {
var pathComponents = getNormalizedPathOrUrlComponents(relativeOrAbsolutePath, currentDirectory);
var directoryComponents = getNormalizedPathOrUrlComponents(directoryPathOrUrl, currentDirectory);
if (directoryComponents.length > 1 && directoryComponents[directoryComponents.length - 1] === "") {
// If the directory path given was of type test/cases/ then we really need components of directry to be only till its name
// 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++) {
if (directoryComponents[joinStartIndex] !== pathComponents[joinStartIndex]) {
if (getCanonicalFileName(directoryComponents[joinStartIndex]) !== getCanonicalFileName(pathComponents[joinStartIndex])) {
break;
}
}
@@ -488,7 +506,7 @@ module ts {
}
// Cant find the relative path, get the absolute path
var absolutePath = getNormalizedPathFromPathCompoments(pathComponents);
var absolutePath = getNormalizedPathFromPathComponents(pathComponents);
if (isAbsolutePathAnUrl && isRootedDiskPath(absolutePath)) {
absolutePath = "file:///" + absolutePath;
}
@@ -515,6 +533,43 @@ module ts {
return pathLen > extLen && path.substr(pathLen - extLen, extLen) === extension;
}
var supportedExtensions = [".d.ts", ".ts", ".js"];
export function removeFileExtension(path: string): string {
for (var i = 0; i < supportedExtensions.length; i++) {
var ext = supportedExtensions[i];
if (fileExtensionIs(path, ext)) {
return path.substr(0, path.length - ext.length);
}
}
return path;
}
var escapedCharsRegExp = /[\t\v\f\b\0\r\n\"\\\u2028\u2029\u0085]/g;
var escapedCharsMap: Map<string> = {
"\t": "\\t",
"\v": "\\v",
"\f": "\\f",
"\b": "\\b",
"\0": "\\0",
"\r": "\\r",
"\n": "\\n",
"\"": "\\\"",
"\u2028": "\\u2028", // lineSeparator
"\u2029": "\\u2029", // paragraphSeparator
"\u0085": "\\u0085" // nextLine
};
/** NOTE: This *does not* support the full escape characters, it only supports the subset that can be used in file names
* or string literals. If the information encoded in the map changes, this needs to be revisited. */
export function escapeString(s: string): string {
return escapedCharsRegExp.test(s) ? s.replace(escapedCharsRegExp, c => {
return escapedCharsMap[c] || c;
}) : s;
}
export interface ObjectAllocator {
getNodeConstructor(kind: SyntaxKind): new () => Node;
getSymbolConstructor(): new (flags: SymbolFlags, name: string) => Symbol;
@@ -5,6 +5,7 @@ module ts {
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." },
@@ -84,6 +85,7 @@ module ts {
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." },
@@ -112,6 +114,7 @@ module ts {
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." },
Filename_0_differs_from_already_included_filename_1_only_in_casing: { code: 1149, category: DiagnosticCategory.Error, key: "Filename '{0}' differs from already included filename '{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." },
An_enum_member_cannot_have_a_numeric_name: { code: 1151, category: DiagnosticCategory.Error, key: "An enum member cannot have a numeric name." },
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." },
@@ -137,9 +140,9 @@ module ts {
Type_0_is_not_assignable_to_type_1_Colon: { code: 2322, category: DiagnosticCategory.Error, key: "Type '{0}' is not assignable to type '{1}':" },
Type_0_is_not_assignable_to_type_1: { code: 2323, 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}'." },
Private_property_0_cannot_be_reimplemented: { code: 2325, category: DiagnosticCategory.Error, key: "Private property '{0}' cannot be reimplemented." },
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_Colon: { code: 2326, category: DiagnosticCategory.Error, key: "Types of property '{0}' are incompatible:" },
Required_property_0_cannot_be_reimplemented_with_optional_property_in_1: { code: 2327, category: DiagnosticCategory.Error, key: "Required property '{0}' cannot be reimplemented with optional property in '{1}'." },
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_Colon: { 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_Colon: { code: 2330, category: DiagnosticCategory.Error, key: "Index signatures are incompatible:" },
@@ -152,8 +155,8 @@ module ts {
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_methods_of_the_base_class_are_accessible_via_the_super_keyword: { code: 2340, category: DiagnosticCategory.Error, key: "Only public methods of the base class are accessible via the 'super' keyword" },
Property_0_is_inaccessible: { code: 2341, category: DiagnosticCategory.Error, key: "Property '{0}' is inaccessible." },
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_or_any: { code: 2342, category: DiagnosticCategory.Error, key: "An index expression argument must be of type 'string', 'number', or 'any'." },
Type_0_does_not_satisfy_the_constraint_1_Colon: { code: 2343, category: DiagnosticCategory.Error, key: "Type '{0}' does not satisfy the constraint '{1}':" },
Type_0_does_not_satisfy_the_constraint_1: { code: 2344, category: DiagnosticCategory.Error, key: "Type '{0}' does not satisfy the constraint '{1}'." },
@@ -178,8 +181,6 @@ module ts {
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}'." },
No_best_common_type_exists_between_0_1_and_2: { code: 2366, category: DiagnosticCategory.Error, key: "No best common type exists between '{0}', '{1}', and '{2}'." },
No_best_common_type_exists_between_0_and_1: { code: 2367, category: DiagnosticCategory.Error, key: "No best common type exists between '{0}' and '{1}'." },
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." },
@@ -197,7 +198,7 @@ module ts {
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_or_private: { code: 2385, category: DiagnosticCategory.Error, key: "Overload signatures must all be public or private." },
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." },
@@ -254,6 +255,12 @@ module ts {
Import_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name: { code: 2439, category: DiagnosticCategory.Error, key: "Import 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." },
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_name_1_from_private_module_2: { code: 4001, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using name '{1}' from private module '{2}'." },
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}'." },
@@ -390,6 +397,10 @@ module ts {
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." },
};
}
+62 -18
View File
@@ -11,6 +11,10 @@
"category": "Error",
"code": 1005
},
"A file cannot have a reference to itself.": {
"category": "Error",
"code": 1006
},
"Trailing comma not allowed.": {
"category": "Error",
"code": 1009
@@ -183,7 +187,7 @@
"category": "Error",
"code": 1066
},
"Unexpected token. A constructor, method, accessor, or property was expected." : {
"Unexpected token. A constructor, method, accessor, or property was expected.": {
"category": "Error",
"code": 1068
},
@@ -327,6 +331,10 @@
"category": "Error",
"code": 1121
},
"A tuple type element list cannot be empty.": {
"category": "Error",
"code": 1122
},
"Variable declaration list cannot be empty.": {
"category": "Error",
"code": 1123
@@ -436,9 +444,13 @@
"code": 1149
},
"'new T[]' cannot be used to create an array. Use 'new Array<T>()' instead.": {
"category": "Error",
"code": 1150
},
"category": "Error",
"code": 1150
},
"An enum member cannot have a numeric name.": {
"category": "Error",
"code": 1151
},
"Duplicate identifier '{0}'.": {
"category": "Error",
@@ -540,7 +552,7 @@
"category": "Error",
"code": 2324
},
"Private property '{0}' cannot be reimplemented.": {
"Property '{0}' is private in type '{1}' but not in type '{2}'.": {
"category": "Error",
"code": 2325
},
@@ -548,7 +560,7 @@
"category": "Error",
"code": 2326
},
"Required property '{0}' cannot be reimplemented with optional property in '{1}'.": {
"Property '{0}' is optional in type '{1}' but required in type '{2}'.": {
"category": "Error",
"code": 2327
},
@@ -600,11 +612,11 @@
"category": "Error",
"code": 2339
},
"Only public methods of the base class are accessible via the 'super' keyword": {
"Only public and protected methods of the base class are accessible via the 'super' keyword": {
"category": "Error",
"code": 2340
},
"Property '{0}' is inaccessible.": {
"Property '{0}' is private and only accessible within class '{1}'.": {
"category": "Error",
"code": 2341
},
@@ -704,14 +716,6 @@
"category": "Error",
"code": 2365
},
"No best common type exists between '{0}', '{1}', and '{2}'.": {
"category": "Error",
"code": 2366
},
"No best common type exists between '{0}' and '{1}'.": {
"category": "Error",
"code": 2367
},
"Type parameter name cannot be '{0}'": {
"category": "Error",
"code": 2368
@@ -780,7 +784,7 @@
"category": "Error",
"code": 2384
},
"Overload signatures must all be public or private.": {
"Overload signatures must all be public, private or protected.": {
"category": "Error",
"code": 2385
},
@@ -1008,7 +1012,30 @@
"category": "Error",
"code": 2441
},
"Types have separate declarations of a private property '{0}'.": {
"category": "Error",
"code": 2442
},
"Property '{0}' is protected but type '{1}' is not a class derived from '{2}'.": {
"category": "Error",
"code": 2443
},
"Property '{0}' is protected in type '{1}' but public in type '{2}'.": {
"category": "Error",
"code": 2444
},
"Property '{0}' is protected and only accessible within class '{1}' and its subclasses.": {
"category": "Error",
"code": 2445
},
"Property '{0}' is protected and only accessible through an instance of class '{1}'.": {
"category": "Error",
"code": 2446
},
"The '{0}' operator is not allowed for boolean types. Consider using '{1}' instead.": {
"category": "Error",
"code": 2447
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
@@ -1332,6 +1359,7 @@
"category": "Error",
"code": 5001
},
"Cannot find the common subdirectory path for the input files.": {
"category": "Error",
"code": 5009
@@ -1557,6 +1585,22 @@
"category": "Error",
"code": 7020
},
"'{0}' implicitly has type 'any' because it is referenced directly or indirectly in its own type annotation.": {
"category": "Error",
"code": 7021
},
"'{0}' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer.": {
"category": "Error",
"code": 7022
},
"'{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.": {
"category": "Error",
"code": 7023
},
"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.": {
"category": "Error",
"code": 7024
},
"You cannot rename this element.": {
"category": "Error",
"code": 8000
+211 -106
View File
@@ -4,7 +4,9 @@
/// <reference path="parser.ts"/>
module ts {
interface EmitTextWriter extends TextWriter {
interface EmitTextWriter extends SymbolWriter {
write(s: string): void;
getText(): string;
rawWrite(s: string): void;
writeLiteral(s: string): void;
getTextPos(): number;
@@ -14,7 +16,7 @@ module ts {
}
var indentStrings: string[] = ["", " "];
function getIndentString(level: number) {
export function getIndentString(level: number) {
if (indentStrings[level] === undefined) {
indentStrings[level] = getIndentString(level - 1) + indentStrings[1];
}
@@ -25,7 +27,22 @@ module ts {
return indentStrings[1].length;
}
export function emitFiles(resolver: EmitResolver): EmitResult {
export function shouldEmitToOwnFile(sourceFile: SourceFile, compilerOptions: CompilerOptions): boolean {
if (!isDeclarationFile(sourceFile)) {
if ((isExternalModule(sourceFile) || !compilerOptions.out) && !fileExtensionIs(sourceFile.filename, ".js")) {
return true;
}
return false;
}
return false;
}
export function isExternalModuleOrDeclarationFile(sourceFile: SourceFile) {
return isExternalModule(sourceFile) || isDeclarationFile(sourceFile);
}
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compilerOnSave feature
export function emitFiles(resolver: EmitResolver, targetSourceFile?: SourceFile): EmitResult {
var program = resolver.getProgram();
var compilerHost = program.getCompilerHost();
var compilerOptions = program.getCompilerOptions();
@@ -34,34 +51,22 @@ module ts {
var newLine = program.getCompilerHost().getNewLine();
function getSourceFilePathInNewDir(newDirPath: string, sourceFile: SourceFile) {
var sourceFilePath = getNormalizedPathFromPathCompoments(getNormalizedPathComponents(sourceFile.filename, compilerHost.getCurrentDirectory()));
var sourceFilePath = getNormalizedPathFromPathComponents(getNormalizedPathComponents(sourceFile.filename, compilerHost.getCurrentDirectory()));
sourceFilePath = sourceFilePath.replace(program.getCommonSourceDirectory(), "");
return combinePaths(newDirPath, sourceFilePath);
}
function shouldEmitToOwnFile(sourceFile: SourceFile) {
if (!(sourceFile.flags & NodeFlags.DeclarationFile)) {
if ((isExternalModule(sourceFile) || !compilerOptions.out) && !fileExtensionIs(sourceFile.filename, ".js")) {
return true;
}
}
}
function getOwnEmitOutputFilePath(sourceFile: SourceFile, extension: string) {
if (program.getCompilerOptions().outDir) {
var emitOutputFilePathWithoutExtension = getModuleNameFromFilename(getSourceFilePathInNewDir(program.getCompilerOptions().outDir, sourceFile));
if (compilerOptions.outDir) {
var emitOutputFilePathWithoutExtension = removeFileExtension(getSourceFilePathInNewDir(compilerOptions.outDir, sourceFile));
}
else {
var emitOutputFilePathWithoutExtension = getModuleNameFromFilename(sourceFile.filename);
var emitOutputFilePathWithoutExtension = removeFileExtension(sourceFile.filename);
}
return emitOutputFilePathWithoutExtension + extension;
}
function isExternalModuleOrDeclarationFile(sourceFile: SourceFile) {
return isExternalModule(sourceFile) || (sourceFile.flags & NodeFlags.DeclarationFile) !== 0;
}
function getFirstConstructorWithBody(node: ClassDeclaration): ConstructorDeclaration {
return forEach(node.members, member => {
if (member.kind === SyntaxKind.Constructor && (<ConstructorDeclaration>member).body) {
@@ -98,7 +103,7 @@ module ts {
};
}
function createTextWriter(writeSymbol: (symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags)=> void): EmitTextWriter {
function createTextWriter(trackSymbol: (symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags)=> void): EmitTextWriter {
var output = "";
var indent = 0;
var lineStart = true;
@@ -144,8 +149,16 @@ module ts {
}
}
function writeKind(text: string, kind: SymbolDisplayPartKind) {
write(text);
}
function writeSymbol(text: string, symbol: Symbol) {
write(text);
}
return {
write: write,
trackSymbol: trackSymbol,
writeKind: writeKind,
writeSymbol: writeSymbol,
rawWrite: rawWrite,
writeLiteral: writeLiteral,
@@ -157,6 +170,7 @@ module ts {
getLine: () => lineCount + 1,
getColumn: () => lineStart ? indent * getIndentSize() + 1 : output.length - linePos + 1,
getText: () => output,
clear: () => { }
};
}
@@ -179,7 +193,7 @@ module ts {
});
}
function emitComments(comments: Comment[], trailingSeparator: boolean, writer: EmitTextWriter, writeComment: (comment: Comment, writer: EmitTextWriter) => void) {
function emitComments(comments: CommentRange[], trailingSeparator: boolean, writer: EmitTextWriter, writeComment: (comment: CommentRange, writer: EmitTextWriter) => void) {
var emitLeadingSpace = !trailingSeparator;
forEach(comments, comment => {
if (emitLeadingSpace) {
@@ -200,7 +214,7 @@ module ts {
});
}
function emitNewLineBeforeLeadingComments(node: TextRange, leadingComments: Comment[], writer: EmitTextWriter) {
function emitNewLineBeforeLeadingComments(node: TextRange, leadingComments: CommentRange[], writer: EmitTextWriter) {
// If the leading comments start on different line than the start of node, write new line
if (leadingComments && leadingComments.length && node.pos !== leadingComments[0].pos &&
getLineOfLocalPosition(node.pos) !== getLineOfLocalPosition(leadingComments[0].pos)) {
@@ -208,7 +222,7 @@ module ts {
}
}
function writeCommentRange(comment: Comment, writer: EmitTextWriter) {
function writeCommentRange(comment: CommentRange, writer: EmitTextWriter) {
if (currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk) {
var firstCommentLineAndCharacter = currentSourceFile.getLineAndCharacterFromPosition(comment.pos);
var firstCommentLineIndent: number;
@@ -304,7 +318,7 @@ module ts {
}
function emitJavaScript(jsFilePath: string, root?: SourceFile) {
var writer = createTextWriter(writeSymbol);
var writer = createTextWriter(trackSymbol);
var write = writer.write;
var writeLine = writer.writeLine;
var increaseIndent = writer.increaseIndent;
@@ -360,7 +374,7 @@ module ts {
/** Sourcemap data that will get encoded */
var sourceMapData: SourceMapData;
function writeSymbol(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags) { }
function trackSymbol(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags) { }
function initializeEmitterWithSourceMaps() {
var sourceMapDir: string; // The directory in which sourcemap will be
@@ -524,7 +538,8 @@ module ts {
sourceMapData.sourceMapSources.push(getRelativePathToDirectoryOrUrl(sourcesDirectoryPath,
node.filename,
compilerHost.getCurrentDirectory(),
/*isAbsolutePathAnUrl*/ true));
compilerHost.getCanonicalFileName,
/*isAbsolutePathAnUrl*/ true));
sourceMapSourceIndex = sourceMapData.sourceMapSources.length - 1;
// The one that can be used from program to get the actual source file
@@ -582,23 +597,48 @@ module ts {
sourceMapNameIndices.pop();
};
function writeCommentRangeWithMap(comment: Comment, writer: EmitTextWriter) {
function writeCommentRangeWithMap(comment: CommentRange, writer: EmitTextWriter) {
recordSourceMapSpan(comment.pos);
writeCommentRange(comment, writer);
recordSourceMapSpan(comment.end);
}
function serializeSourceMapContents(version: number, file: string, sourceRoot: string, sources: string[], names: string[], mappings: string) {
if (typeof JSON !== "undefined") {
return JSON.stringify({
version: version,
file: file,
sourceRoot: sourceRoot,
sources: sources,
names: names,
mappings: mappings
});
}
return "{\"version\":" + version + ",\"file\":\"" + escapeString(file) + "\",\"sourceRoot\":\"" + escapeString(sourceRoot) + "\",\"sources\":[" + serializeStringArray(sources) + "],\"names\":[" + serializeStringArray(names) + "],\"mappings\":\"" + escapeString(mappings) + "\"}";
function serializeStringArray(list: string[]): string {
var output = "";
for (var i = 0, n = list.length; i < n; i++) {
if (i) {
output += ",";
}
output += "\"" + escapeString(list[i]) + "\"";
}
return output;
}
}
function writeJavaScriptAndSourceMapFile(emitOutput: string, writeByteOrderMark: boolean) {
// Write source map file
encodeLastRecordedSourceMapSpan();
writeFile(sourceMapData.sourceMapFilePath, JSON.stringify({
version: 3,
file: sourceMapData.sourceMapFile,
sourceRoot: sourceMapData.sourceMapSourceRoot,
sources: sourceMapData.sourceMapSources,
names: sourceMapData.sourceMapNames,
mappings: sourceMapData.sourceMapMappings
}), /*writeByteOrderMark*/ false);
writeFile(sourceMapData.sourceMapFilePath, serializeSourceMapContents(
3,
sourceMapData.sourceMapFile,
sourceMapData.sourceMapSourceRoot,
sourceMapData.sourceMapSources,
sourceMapData.sourceMapNames,
sourceMapData.sourceMapMappings), /*writeByteOrderMark*/ false);
sourceMapDataList.push(sourceMapData);
// Write sourcemap url to the js file and write the js file
@@ -641,7 +681,8 @@ module ts {
getDirectoryPath(normalizePath(jsFilePath)), // get the relative sourceMapDir path based on jsFilePath
combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), // this is where user expects to see sourceMap
compilerHost.getCurrentDirectory(),
/*isAbsolutePathAnUrl*/ true);
compilerHost.getCanonicalFileName,
/*isAbsolutePathAnUrl*/ true);
}
else {
sourceMapData.jsSourceMappingURL = combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL);
@@ -697,23 +738,46 @@ module ts {
}
}
function emitCommaList(nodes: Node[], count?: number) {
if (!(count >= 0)) count = nodes.length;
if (nodes) {
for (var i = 0; i < count; i++) {
if (i) write(", ");
emit(nodes[i]);
function emitTrailingCommaIfPresent(nodeList: NodeArray<Node>, isMultiline: boolean): void {
if (nodeList.hasTrailingComma) {
write(",");
if (isMultiline) {
writeLine();
}
}
}
function emitMultiLineList(nodes: Node[]) {
function emitCommaList(nodes: NodeArray<Node>, includeTrailingComma: boolean, count?: number) {
if (!(count >= 0)) {
count = nodes.length;
}
if (nodes) {
for (var i = 0; i < count; i++) {
if (i) {
write(", ");
}
emit(nodes[i]);
}
if (includeTrailingComma) {
emitTrailingCommaIfPresent(nodes, /*isMultiline*/ false);
}
}
}
function emitMultiLineList(nodes: NodeArray<Node>, includeTrailingComma: boolean) {
if (nodes) {
for (var i = 0; i < nodes.length; i++) {
if (i) write(",");
if (i) {
write(",");
}
writeLine();
emit(nodes[i]);
}
if (includeTrailingComma) {
emitTrailingCommaIfPresent(nodes, /*isMultiline*/ true);
}
}
}
@@ -781,8 +845,8 @@ module ts {
case SyntaxKind.ContinueStatement:
case SyntaxKind.ExportAssignment:
return false;
case SyntaxKind.LabelledStatement:
return (<LabelledStatement>node.parent).label === node;
case SyntaxKind.LabeledStatement:
return (<LabeledStatement>node.parent).label === node;
case SyntaxKind.CatchBlock:
return (<CatchBlock>node.parent).variable === node;
}
@@ -825,14 +889,14 @@ module ts {
if (node.flags & NodeFlags.MultiLine) {
write("[");
increaseIndent();
emitMultiLineList(node.elements);
emitMultiLineList(node.elements, /*includeTrailingComma*/ true);
decreaseIndent();
writeLine();
write("]");
}
else {
write("[");
emitCommaList(node.elements);
emitCommaList(node.elements, /*includeTrailingComma*/ true);
write("]");
}
}
@@ -844,14 +908,14 @@ module ts {
else if (node.flags & NodeFlags.MultiLine) {
write("{");
increaseIndent();
emitMultiLineList(node.properties);
emitMultiLineList(node.properties, /*includeTrailingComma*/ compilerOptions.target >= ScriptTarget.ES5);
decreaseIndent();
writeLine();
write("}");
}
else {
write("{ ");
emitCommaList(node.properties);
emitCommaList(node.properties, /*includeTrailingComma*/ compilerOptions.target >= ScriptTarget.ES5);
write(" }");
}
}
@@ -865,14 +929,15 @@ module ts {
}
function emitPropertyAccess(node: PropertyAccess) {
var text = resolver.getPropertyAccessSubstitution(node);
if (text) {
write(text);
return;
var constantValue = resolver.getConstantValue(node);
if (constantValue !== undefined) {
write(constantValue.toString() + " /* " + identifierToString(node.right) + " */");
}
else {
emit(node.left);
write(".");
emit(node.right);
}
emit(node.left);
write(".");
emit(node.right);
}
function emitIndexedAccess(node: IndexedAccess) {
@@ -897,13 +962,13 @@ module ts {
emitThis(node.func);
if (node.arguments.length) {
write(", ");
emitCommaList(node.arguments);
emitCommaList(node.arguments, /*includeTrailingComma*/ false);
}
write(")");
}
else {
write("(");
emitCommaList(node.arguments);
emitCommaList(node.arguments, /*includeTrailingComma*/ false);
write(")");
}
}
@@ -913,7 +978,7 @@ module ts {
emit(node.func);
if (node.arguments) {
write("(");
emitCommaList(node.arguments);
emitCommaList(node.arguments, /*includeTrailingComma*/ false);
write(")");
}
}
@@ -1086,7 +1151,7 @@ module ts {
if (node.declarations) {
emitToken(SyntaxKind.VarKeyword, endPos);
write(" ");
emitCommaList(node.declarations);
emitCommaList(node.declarations, /*includeTrailingComma*/ false);
}
if (node.initializer) {
emit(node.initializer);
@@ -1200,7 +1265,7 @@ module ts {
write(";");
}
function emitLabelledStatement(node: LabelledStatement) {
function emitLabelledStatement(node: LabeledStatement) {
emit(node.label);
write(": ");
emit(node.statement);
@@ -1234,7 +1299,7 @@ module ts {
function emitVariableStatement(node: VariableStatement) {
emitLeadingComments(node);
if (!(node.flags & NodeFlags.Export)) write("var ");
emitCommaList(node.declarations);
emitCommaList(node.declarations, /*includeTrailingComma*/ false);
write(";");
emitTrailingComments(node);
}
@@ -1343,7 +1408,7 @@ module ts {
increaseIndent();
write("(");
if (node) {
emitCommaList(node.parameters, node.parameters.length - (hasRestParameters(node) ? 1 : 0));
emitCommaList(node.parameters, /*includeTrailingComma*/ false, node.parameters.length - (hasRestParameters(node) ? 1 : 0));
}
write(")");
decreaseIndent();
@@ -1431,7 +1496,7 @@ module ts {
function emitParameterPropertyAssignments(node: ConstructorDeclaration) {
forEach(node.parameters, param => {
if (param.flags & (NodeFlags.Public | NodeFlags.Private)) {
if (param.flags & NodeFlags.AccessibilityModifier) {
writeLine();
emitStart(param);
emitStart(param.name);
@@ -1973,7 +2038,7 @@ module ts {
}
}
function emitNode(node: Node) {
function emitNode(node: Node): void {
if (!node) {
return;
}
@@ -2071,8 +2136,8 @@ module ts {
case SyntaxKind.CaseClause:
case SyntaxKind.DefaultClause:
return emitCaseOrDefaultClause(<CaseOrDefaultClause>node);
case SyntaxKind.LabelledStatement:
return emitLabelledStatement(<LabelledStatement>node);
case SyntaxKind.LabeledStatement:
return emitLabelledStatement(<LabeledStatement>node);
case SyntaxKind.ThrowStatement:
return emitThrowStatement(<ThrowStatement>node);
case SyntaxKind.TryStatement:
@@ -2104,7 +2169,7 @@ module ts {
function getLeadingCommentsWithoutDetachedComments() {
// get the leading comments from detachedPos
var leadingComments = getLeadingComments(currentSourceFile.text, detachedCommentsInfo[detachedCommentsInfo.length - 1].detachedCommentEndPos);
var leadingComments = getLeadingCommentRanges(currentSourceFile.text, detachedCommentsInfo[detachedCommentsInfo.length - 1].detachedCommentEndPos);
if (detachedCommentsInfo.length - 1) {
detachedCommentsInfo.pop();
}
@@ -2118,14 +2183,14 @@ module ts {
function getLeadingCommentsToEmit(node: Node) {
// Emit the leading comments only if the parent's pos doesn't match because parent should take care of emitting these comments
if (node.parent.kind === SyntaxKind.SourceFile || node.pos !== node.parent.pos) {
var leadingComments: Comment[];
var leadingComments: CommentRange[];
if (hasDetachedComments(node.pos)) {
// get comments without detached comments
leadingComments = getLeadingCommentsWithoutDetachedComments();
}
else {
// get the leading comments from the node
leadingComments = getLeadingCommentsOfNode(node, currentSourceFile);
leadingComments = getLeadingCommentRangesOfNode(node, currentSourceFile);
}
return leadingComments;
}
@@ -2141,21 +2206,21 @@ module ts {
function emitTrailingDeclarationComments(node: Node) {
// Emit the trailing comments only if the parent's end doesn't match
if (node.parent.kind === SyntaxKind.SourceFile || node.end !== node.parent.end) {
var trailingComments = getTrailingComments(currentSourceFile.text, node.end);
var trailingComments = getTrailingCommentRanges(currentSourceFile.text, node.end);
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
emitComments(trailingComments, /*trailingSeparator*/ false, writer, writeComment);
}
}
function emitLeadingCommentsOfLocalPosition(pos: number) {
var leadingComments: Comment[];
var leadingComments: CommentRange[];
if (hasDetachedComments(pos)) {
// get comments without detached comments
leadingComments = getLeadingCommentsWithoutDetachedComments();
}
else {
// get the leading comments from the node
leadingComments = getLeadingComments(currentSourceFile.text, pos);
leadingComments = getLeadingCommentRanges(currentSourceFile.text, pos);
}
emitNewLineBeforeLeadingComments({ pos: pos, end: pos }, leadingComments, writer);
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
@@ -2163,10 +2228,10 @@ module ts {
}
function emitDetachedCommentsAtPosition(node: TextRange) {
var leadingComments = getLeadingComments(currentSourceFile.text, node.pos);
var leadingComments = getLeadingCommentRanges(currentSourceFile.text, node.pos);
if (leadingComments) {
var detachedComments: Comment[] = [];
var lastComment: Comment;
var detachedComments: CommentRange[] = [];
var lastComment: CommentRange;
forEach(leadingComments, comment => {
if (lastComment) {
@@ -2210,7 +2275,7 @@ module ts {
function emitPinnedOrTripleSlashCommentsOfNode(node: Node) {
var pinnedComments = ts.filter(getLeadingCommentsToEmit(node), isPinnedOrTripleSlashComment);
function isPinnedOrTripleSlashComment(comment: Comment) {
function isPinnedOrTripleSlashComment(comment: CommentRange) {
if (currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk) {
return currentSourceFile.text.charCodeAt(comment.pos + 2) === CharacterCodes.exclamation;
}
@@ -2249,7 +2314,7 @@ module ts {
}
function emitDeclarations(jsFilePath: string, root?: SourceFile) {
var writer = createTextWriter(writeSymbol);
var writer = createTextWriter(trackSymbol);
var write = writer.write;
var writeLine = writer.writeLine;
var increaseIndent = writer.increaseIndent;
@@ -2277,7 +2342,7 @@ module ts {
var oldWriter = writer;
forEach(importDeclarations, aliasToWrite => {
var aliasEmitInfo = forEach(aliasDeclarationEmitInfo, declEmitInfo => declEmitInfo.declaration === aliasToWrite ? declEmitInfo : undefined);
writer = createTextWriter(writeSymbol);
writer = createTextWriter(trackSymbol);
for (var declarationIndent = aliasEmitInfo.indent; declarationIndent; declarationIndent--) {
writer.increaseIndent();
}
@@ -2288,10 +2353,9 @@ module ts {
writer = oldWriter;
}
function writeSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) {
function trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) {
var symbolAccesibilityResult = resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning);
if (symbolAccesibilityResult.accessibility === SymbolAccessibility.Accessible) {
resolver.writeSymbol(symbol, enclosingDeclaration, meaning, writer);
// write the aliases
if (symbolAccesibilityResult && symbolAccesibilityResult.aliasesToMakeVisible) {
@@ -2368,12 +2432,18 @@ module ts {
if (node.flags & NodeFlags.Private) {
write("private ");
}
else if (node.flags & NodeFlags.Protected) {
write("protected ");
}
write("static ");
}
else {
if (node.flags & NodeFlags.Private) {
write("private ");
}
else if (node.flags & NodeFlags.Protected) {
write("protected ");
}
// If the node is parented in the current source file we need to emit export declare or just export
else if (node.parent === currentSourceFile) {
// If the node is exported
@@ -2630,7 +2700,7 @@ module ts {
function emitParameterProperties(constructorDeclaration: ConstructorDeclaration) {
if (constructorDeclaration) {
forEach(constructorDeclaration.parameters, param => {
if (param.flags & (NodeFlags.Public | NodeFlags.Private)) {
if (param.flags & NodeFlags.AccessibilityModifier) {
emitPropertyDeclaration(param);
}
});
@@ -3070,7 +3140,7 @@ module ts {
}
}
function resolveScriptReference(sourceFile: SourceFile, reference: FileReference) {
function tryResolveScriptReference(sourceFile: SourceFile, reference: FileReference) {
var referenceFileName = normalizePath(combinePaths(getDirectoryPath(sourceFile.filename), reference.filename));
return program.getSourceFile(referenceFileName);
}
@@ -3082,15 +3152,16 @@ module ts {
function writeReferencePath(referencedFile: SourceFile) {
var declFileName = referencedFile.flags & NodeFlags.DeclarationFile
? referencedFile.filename // Declaration file, use declaration file name
: shouldEmitToOwnFile(referencedFile)
: shouldEmitToOwnFile(referencedFile, compilerOptions)
? getOwnEmitOutputFilePath(referencedFile, ".d.ts") // Own output file so get the .d.ts file
: getModuleNameFromFilename(compilerOptions.out) + ".d.ts";// Global out file
: removeFileExtension(compilerOptions.out) + ".d.ts";// Global out file
declFileName = getRelativePathToDirectoryOrUrl(
getDirectoryPath(normalizeSlashes(jsFilePath)),
declFileName,
compilerHost.getCurrentDirectory(),
/*isAbsolutePathAnUrl*/ false);
compilerHost.getCanonicalFileName,
/*isAbsolutePathAnUrl*/ false);
referencePathsOutput += "/// <reference path=\"" + declFileName + "\" />" + newLine;
}
@@ -3100,12 +3171,12 @@ module ts {
if (!compilerOptions.noResolve) {
var addedGlobalFileReference = false;
forEach(root.referencedFiles, fileReference => {
var referencedFile = resolveScriptReference(root, fileReference);
var referencedFile = tryResolveScriptReference(root, fileReference);
// All the references that are not going to be part of same file
if ((referencedFile.flags & NodeFlags.DeclarationFile) || // This is a declare file reference
shouldEmitToOwnFile(referencedFile) || // This is referenced file is emitting its own js file
!addedGlobalFileReference) { // Or the global out file corresponding to this reference was not added
if (referencedFile && ((referencedFile.flags & NodeFlags.DeclarationFile) || // This is a declare file reference
shouldEmitToOwnFile(referencedFile, compilerOptions) || // This is referenced file is emitting its own js file
!addedGlobalFileReference)) { // Or the global out file corresponding to this reference was not added
writeReferencePath(referencedFile);
if (!isExternalModuleOrDeclarationFile(referencedFile)) {
@@ -3125,11 +3196,11 @@ module ts {
// Check what references need to be added
if (!compilerOptions.noResolve) {
forEach(sourceFile.referencedFiles, fileReference => {
var referencedFile = resolveScriptReference(sourceFile, fileReference);
var referencedFile = tryResolveScriptReference(sourceFile, fileReference);
// If the reference file is a declaration file or an external module, emit that reference
if (isExternalModuleOrDeclarationFile(referencedFile) &&
!contains(emittedReferencedFiles, referencedFile)) { // If the file reference was not already emitted
if (referencedFile && (isExternalModuleOrDeclarationFile(referencedFile) &&
!contains(emittedReferencedFiles, referencedFile))) { // If the file reference was not already emitted
writeReferencePath(referencedFile);
emittedReferencedFiles.push(referencedFile);
@@ -3157,33 +3228,67 @@ module ts {
}
});
declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos);
writeFile(getModuleNameFromFilename(jsFilePath) + ".d.ts", declarationOutput, compilerOptions.emitBOM);
writeFile(removeFileExtension(jsFilePath) + ".d.ts", declarationOutput, compilerOptions.emitBOM);
}
}
var shouldEmitDeclarations = resolver.shouldEmitDeclarations();
var hasSemanticErrors = resolver.hasSemanticErrors();
function emitFile(jsFilePath: string, sourceFile?: SourceFile) {
emitJavaScript(jsFilePath, sourceFile);
if (shouldEmitDeclarations) {
if (!hasSemanticErrors && compilerOptions.declaration) {
emitDeclarations(jsFilePath, sourceFile);
}
}
forEach(program.getSourceFiles(), sourceFile => {
if (shouldEmitToOwnFile(sourceFile)) {
var jsFilePath = getOwnEmitOutputFilePath(sourceFile, ".js");
emitFile(jsFilePath, sourceFile);
}
});
if (compilerOptions.out) {
emitFile(compilerOptions.out);
}
if (targetSourceFile === undefined) {
// No targetSourceFile is specified (e.g. calling emitter from batch compiler)
forEach(program.getSourceFiles(), sourceFile => {
if (shouldEmitToOwnFile(sourceFile, compilerOptions)) {
var jsFilePath = getOwnEmitOutputFilePath(sourceFile, ".js");
emitFile(jsFilePath, sourceFile);
}
});
if (compilerOptions.out) {
emitFile(compilerOptions.out);
}
}
else {
// targetSourceFile is specified (e.g calling emitter from language service or calling getSemanticDiagnostic from language service)
if (shouldEmitToOwnFile(targetSourceFile, compilerOptions)) {
// If shouldEmitToOwnFile returns true or targetSourceFile is an external module file, then emit targetSourceFile in its own output file
var jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, ".js");
emitFile(jsFilePath, targetSourceFile);
}
else if (!isDeclarationFile(targetSourceFile) && compilerOptions.out) {
// Otherwise, if --out is specified and targetSourceFile is not a declaration file,
// Emit all, non-external-module file, into one single output file
emitFile(compilerOptions.out);
}
}
// Sort and make the unique list of diagnostics
diagnostics.sort(compareDiagnostics);
diagnostics = deduplicateSortedDiagnostics(diagnostics);
// Update returnCode if there is any EmitterError
var hasEmitterError = forEach(diagnostics, diagnostic => diagnostic.category === DiagnosticCategory.Error);
// Check and update returnCode for syntactic and semantic
var returnCode: EmitReturnStatus;
if (hasEmitterError) {
returnCode = EmitReturnStatus.EmitErrorsEncountered;
} else if (hasSemanticErrors && compilerOptions.declaration) {
returnCode = EmitReturnStatus.DeclarationGenerationSkipped;
} else if (hasSemanticErrors && !compilerOptions.declaration) {
returnCode = EmitReturnStatus.JSGeneratedWithSemanticErrors;
} else {
returnCode = EmitReturnStatus.Succeeded;
}
return {
emitResultStatus: returnCode,
errors: diagnostics,
sourceMaps: sourceMapDataList
};
+302 -105
View File
@@ -17,22 +17,11 @@ module ts {
return node;
}
var moduleExtensions = [".d.ts", ".ts", ".js"];
interface ReferenceComments {
referencedFiles: FileReference[];
amdDependencies: string[];
}
export function getModuleNameFromFilename(filename: string) {
for (var i = 0; i < moduleExtensions.length; i++) {
var ext = moduleExtensions[i];
var len = filename.length - ext.length;
if (len > 0 && filename.substr(len) === ext) return filename.substr(0, len);
}
return filename;
}
export function getSourceFileOfNode(node: Node): SourceFile {
while (node && node.kind !== SyntaxKind.SourceFile) node = node.parent;
return <SourceFile>node;
@@ -50,15 +39,15 @@ module ts {
return node.pos;
}
export function getTokenPosOfNode(node: Node): number {
return skipTrivia(getSourceFileOfNode(node).text, node.pos);
export function getTokenPosOfNode(node: Node, sourceFile?: SourceFile): number {
return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos);
}
export function getSourceTextOfNodeFromSourceText(sourceText: string, node: Node): string {
export function getTextOfNodeFromSourceText(sourceText: string, node: Node): string {
return sourceText.substring(skipTrivia(sourceText, node.pos), node.end);
}
export function getSourceTextOfNode(node: Node): string {
export function getTextOfNode(node: Node): string {
var text = getSourceFileOfNode(node).text;
return text.substring(skipTrivia(text, node.pos), node.end);
}
@@ -75,7 +64,7 @@ module ts {
// Return display name of an identifier
export function identifierToString(identifier: Identifier) {
return identifier.kind === SyntaxKind.Missing ? "(Missing)" : getSourceTextOfNode(identifier);
return identifier.kind === SyntaxKind.Missing ? "(Missing)" : getTextOfNode(identifier);
}
export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): Diagnostic {
@@ -122,6 +111,10 @@ module ts {
return file.externalModuleIndicator !== undefined;
}
export function isDeclarationFile(file: SourceFile): boolean {
return (file.flags & NodeFlags.DeclarationFile) !== 0;
}
export function isPrologueDirective(node: Node): boolean {
return node.kind === SyntaxKind.ExpressionStatement && (<ExpressionStatement>node).expression.kind === SyntaxKind.StringLiteral;
}
@@ -138,25 +131,27 @@ module ts {
return (<Identifier>(<ExpressionStatement>node).expression).text === "use strict";
}
export function getLeadingCommentsOfNode(node: Node, sourceFileOfNode: SourceFile) {
export function getLeadingCommentRangesOfNode(node: Node, sourceFileOfNode?: SourceFile) {
sourceFileOfNode = sourceFileOfNode || getSourceFileOfNode(node);
// If parameter/type parameter, the prev token trailing comments are part of this node too
if (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter) {
// e.g. (/** blah */ a, /** blah */ b);
return concatenate(getTrailingComments(sourceFileOfNode.text, node.pos),
return concatenate(getTrailingCommentRanges(sourceFileOfNode.text, node.pos),
// e.g.: (
// /** blah */ a,
// /** blah */ b);
getLeadingComments(sourceFileOfNode.text, node.pos));
getLeadingCommentRanges(sourceFileOfNode.text, node.pos));
}
else {
return getLeadingComments(sourceFileOfNode.text, node.pos);
return getLeadingCommentRanges(sourceFileOfNode.text, node.pos);
}
}
export function getJsDocComments(node: Declaration, sourceFileOfNode: SourceFile) {
return filter(getLeadingCommentsOfNode(node, sourceFileOfNode), comment => isJsDocComment(comment));
return filter(getLeadingCommentRangesOfNode(node, sourceFileOfNode), comment => isJsDocComment(comment));
function isJsDocComment(comment: Comment) {
function isJsDocComment(comment: CommentRange) {
// True if the comment starts with '/**' but not if it is '/**/'
return sourceFileOfNode.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk &&
sourceFileOfNode.text.charCodeAt(comment.pos + 2) === CharacterCodes.asterisk &&
@@ -228,6 +223,10 @@ module ts {
return children((<TypeLiteralNode>node).members);
case SyntaxKind.ArrayType:
return child((<ArrayTypeNode>node).elementType);
case SyntaxKind.TupleType:
return children((<TupleTypeNode>node).elementTypes);
case SyntaxKind.UnionType:
return children((<UnionTypeNode>node).types);
case SyntaxKind.ArrayLiteral:
return children((<ArrayLiteral>node).elements);
case SyntaxKind.ObjectLiteral:
@@ -305,9 +304,9 @@ module ts {
case SyntaxKind.DefaultClause:
return child((<CaseOrDefaultClause>node).expression) ||
children((<CaseOrDefaultClause>node).statements);
case SyntaxKind.LabelledStatement:
return child((<LabelledStatement>node).label) ||
child((<LabelledStatement>node).statement);
case SyntaxKind.LabeledStatement:
return child((<LabeledStatement>node).label) ||
child((<LabeledStatement>node).statement);
case SyntaxKind.ThrowStatement:
return child((<ThrowStatement>node).expression);
case SyntaxKind.TryStatement:
@@ -371,7 +370,7 @@ module ts {
case SyntaxKind.SwitchStatement:
case SyntaxKind.CaseClause:
case SyntaxKind.DefaultClause:
case SyntaxKind.LabelledStatement:
case SyntaxKind.LabeledStatement:
case SyntaxKind.TryStatement:
case SyntaxKind.TryBlock:
case SyntaxKind.CatchBlock:
@@ -485,6 +484,32 @@ module ts {
return false;
}
export function isStatement(n: Node): boolean {
switch(n.kind) {
case SyntaxKind.BreakStatement:
case SyntaxKind.ContinueStatement:
case SyntaxKind.DebuggerStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.ExpressionStatement:
case SyntaxKind.EmptyStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.LabeledStatement:
case SyntaxKind.ReturnStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.ThrowKeyword:
case SyntaxKind.TryStatement:
case SyntaxKind.VariableStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.ExportAssignment:
return true;
default:
return false;
}
}
// True if the given identifier, string literal, or number literal is the name of a declaration node
export function isDeclarationOrFunctionExpressionOrCatchVariableName(name: Node): boolean {
if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) {
@@ -503,6 +528,39 @@ module ts {
return false;
}
export function getAncestor(node: Node, kind: SyntaxKind): Node {
switch (kind) {
// special-cases that can be come first
case SyntaxKind.ClassDeclaration:
while (node) {
switch (node.kind) {
case SyntaxKind.ClassDeclaration:
return <ClassDeclaration>node;
case SyntaxKind.EnumDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ImportDeclaration:
// early exit cases - declarations cannot be nested in classes
return undefined;
default:
node = node.parent;
continue;
}
}
break;
default:
while (node) {
if (node.kind === kind) {
return node;
}
node = node.parent;
}
break;
}
return undefined;
}
enum ParsingContext {
SourceElements, // Elements in source file
ModuleElements, // Elements in module declaration
@@ -520,6 +578,7 @@ module ts {
Parameters, // Parameters in parameter list
TypeParameters, // Type parameters in type parameter list
TypeArguments, // Type arguments in type argument list
TupleElementTypes, // Element types in tuple element type list
Count // Number of parsing contexts
}
@@ -547,6 +606,7 @@ module ts {
case ParsingContext.Parameters: return Diagnostics.Parameter_declaration_expected;
case ParsingContext.TypeParameters: return Diagnostics.Type_parameter_declaration_expected;
case ParsingContext.TypeArguments: return Diagnostics.Type_argument_expected;
case ParsingContext.TupleElementTypes: return Diagnostics.Type_expected;
}
};
@@ -563,12 +623,6 @@ module ts {
Parameters, // Parameters in parameter list
}
enum TrailingCommaBehavior {
Disallow,
Allow,
Preserve
}
// Tracks whether we nested (directly or indirectly) in a certain control block.
// Used for validating break and continue statements.
enum ControlBlockContext {
@@ -589,10 +643,15 @@ module ts {
return SyntaxKind.FirstKeyword <= token && token <= SyntaxKind.LastKeyword;
}
export function isTrivia(token: SyntaxKind) {
return SyntaxKind.FirstTriviaToken <= token && token <= SyntaxKind.LastTriviaToken;
}
export function isModifier(token: SyntaxKind): boolean {
switch (token) {
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.StaticKeyword:
case SyntaxKind.ExportKeyword:
case SyntaxKind.DeclareKeyword:
@@ -755,7 +814,7 @@ module ts {
// applying some stricter checks on that node.
function grammarErrorOnNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): void {
var span = getErrorSpanForNode(node);
var start = skipTrivia(file.text, span.pos);
var start = span.end > span.pos ? skipTrivia(file.text, span.pos) : span.pos;
var length = span.end - start;
file.syntacticErrors.push(createFileDiagnostic(file, start, length, message, arg0, arg1, arg2));
@@ -949,7 +1008,10 @@ module ts {
return finishNode(node);
}
error(Diagnostics.Identifier_expected);
return <Identifier>createMissingNode();
var node = <Identifier>createMissingNode();
node.text = "";
return node;
}
function parseIdentifier(): Identifier {
@@ -1009,12 +1071,13 @@ module ts {
case ParsingContext.TypeParameters:
return isIdentifier();
case ParsingContext.ArgumentExpressions:
return isExpression();
return token === SyntaxKind.CommaToken || isExpression();
case ParsingContext.ArrayLiteralMembers:
return token === SyntaxKind.CommaToken || isExpression();
case ParsingContext.Parameters:
return isParameter();
case ParsingContext.TypeArguments:
case ParsingContext.TupleElementTypes:
return isType();
}
@@ -1050,6 +1113,7 @@ module ts {
// Tokens other than ')' are here for better error recovery
return token === SyntaxKind.CloseParenToken || token === SyntaxKind.SemicolonToken;
case ParsingContext.ArrayLiteralMembers:
case ParsingContext.TupleElementTypes:
return token === SyntaxKind.CloseBracketToken;
case ParsingContext.Parameters:
// Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery
@@ -1137,7 +1201,7 @@ module ts {
}
// Parses a comma-delimited list of elements
function parseDelimitedList<T extends Node>(kind: ParsingContext, parseElement: () => T, trailingCommaBehavior: TrailingCommaBehavior): NodeArray<T> {
function parseDelimitedList<T extends Node>(kind: ParsingContext, parseElement: () => T, allowTrailingComma: boolean): NodeArray<T> {
var saveParsingContext = parsingContext;
parsingContext |= 1 << kind;
var result = <NodeArray<T>>[];
@@ -1160,19 +1224,6 @@ module ts {
error(Diagnostics._0_expected, ",");
}
else if (isListTerminator(kind)) {
// Check if the last token was a comma.
if (commaStart >= 0) {
if (trailingCommaBehavior === TrailingCommaBehavior.Disallow) {
if (file.syntacticErrors.length === errorCountBeforeParsingList) {
// Report a grammar error so we don't affect lookahead
grammarErrorAtPos(commaStart, scanner.getStartPos() - commaStart, Diagnostics.Trailing_comma_not_allowed);
}
}
else if (trailingCommaBehavior === TrailingCommaBehavior.Preserve) {
result.push(<T>createNode(SyntaxKind.OmittedExpression));
}
}
break;
}
else {
@@ -1183,6 +1234,23 @@ module ts {
nextToken();
}
}
// Recording the trailing comma is deliberately done after the previous
// loop, and not just if we see a list terminator. This is because the list
// may have ended incorrectly, but it is still important to know if there
// was a trailing comma.
// Check if the last token was a comma.
if (commaStart >= 0) {
if (!allowTrailingComma) {
if (file.syntacticErrors.length === errorCountBeforeParsingList) {
// Report a grammar error so we don't affect lookahead
grammarErrorAtPos(commaStart, scanner.getStartPos() - commaStart, Diagnostics.Trailing_comma_not_allowed);
}
}
// Always preserve a trailing comma by marking it on the NodeArray
result.hasTrailingComma = true;
}
result.end = getNodeEnd();
parsingContext = saveParsingContext;
return result;
@@ -1205,7 +1273,7 @@ module ts {
function parseBracketedList<T extends Node>(kind: ParsingContext, parseElement: () => T, startToken: SyntaxKind, endToken: SyntaxKind): NodeArray<T> {
if (parseExpected(startToken)) {
var result = parseDelimitedList(kind, parseElement, TrailingCommaBehavior.Disallow);
var result = parseDelimitedList(kind, parseElement, /*allowTrailingComma*/ false);
parseExpected(endToken);
return result;
}
@@ -1368,14 +1436,25 @@ module ts {
return finishNode(node);
}
function parseSignature(kind: SyntaxKind, returnToken: SyntaxKind): ParsedSignature {
function parseSignature(kind: SyntaxKind, returnToken: SyntaxKind, returnTokenRequired: boolean): ParsedSignature {
if (kind === SyntaxKind.ConstructSignature) {
parseExpected(SyntaxKind.NewKeyword);
}
var typeParameters = parseTypeParameters();
var parameters = parseParameterList(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken);
checkParameterList(parameters);
var type = parseOptional(returnToken) ? parseType() : undefined;
var type: TypeNode;
if (returnTokenRequired) {
parseExpected(returnToken);
type = parseType();
}
else if (parseOptional(returnToken))
{
type = parseType();
}
return {
typeParameters: typeParameters,
parameters: parameters,
@@ -1439,7 +1518,7 @@ module ts {
function parseSignatureMember(kind: SyntaxKind, returnToken: SyntaxKind): SignatureDeclaration {
var node = <SignatureDeclaration>createNode(kind);
var sig = parseSignature(kind, returnToken);
var sig = parseSignature(kind, returnToken, /* returnTokenRequired */ false);
node.typeParameters = sig.typeParameters;
node.parameters = sig.parameters;
node.type = sig.type;
@@ -1512,7 +1591,7 @@ module ts {
}
if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) {
node.kind = SyntaxKind.Method;
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken);
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false);
(<MethodDeclaration>node).typeParameters = sig.typeParameters;
(<MethodDeclaration>node).parameters = sig.parameters;
(<MethodDeclaration>node).type = sig.type;
@@ -1570,10 +1649,21 @@ module ts {
return finishNode(node);
}
function parseTupleType(): TupleTypeNode {
var node = <TupleTypeNode>createNode(SyntaxKind.TupleType);
var startTokenPos = scanner.getTokenPos();
var startErrorCount = file.syntacticErrors.length;
node.elementTypes = parseBracketedList(ParsingContext.TupleElementTypes, parseType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
if (!node.elementTypes.length && file.syntacticErrors.length === startErrorCount) {
grammarErrorAtPos(startTokenPos, scanner.getStartPos() - startTokenPos, Diagnostics.A_tuple_type_element_list_cannot_be_empty);
}
return finishNode(node);
}
function parseFunctionType(signatureKind: SyntaxKind): TypeLiteralNode {
var node = <TypeLiteralNode>createNode(SyntaxKind.TypeLiteral);
var member = <SignatureDeclaration>createNode(signatureKind);
var sig = parseSignature(signatureKind, SyntaxKind.EqualsGreaterThanToken);
var sig = parseSignature(signatureKind, SyntaxKind.EqualsGreaterThanToken, /* returnTokenRequired */ true);
member.typeParameters = sig.typeParameters;
member.parameters = sig.parameters;
member.type = sig.type;
@@ -1600,6 +1690,8 @@ module ts {
return parseTypeQuery();
case SyntaxKind.OpenBraceToken:
return parseTypeLiteral();
case SyntaxKind.OpenBracketToken:
return parseTupleType();
case SyntaxKind.OpenParenToken:
case SyntaxKind.LessThanToken:
return parseFunctionType(SyntaxKind.CallSignature);
@@ -1623,6 +1715,7 @@ module ts {
case SyntaxKind.VoidKeyword:
case SyntaxKind.TypeOfKeyword:
case SyntaxKind.OpenBraceToken:
case SyntaxKind.OpenBracketToken:
case SyntaxKind.LessThanToken:
case SyntaxKind.NewKeyword:
return true;
@@ -1638,9 +1731,9 @@ module ts {
}
}
function parseType(): TypeNode {
function parseNonUnionType(): TypeNode {
var type = parseNonArrayType();
while (type && !scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) {
while (!scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) {
parseExpected(SyntaxKind.CloseBracketToken);
var node = <ArrayTypeNode>createNode(SyntaxKind.ArrayType, type.pos);
node.elementType = type;
@@ -1649,6 +1742,22 @@ module ts {
return type;
}
function parseType(): TypeNode {
var type = parseNonUnionType();
if (token === SyntaxKind.BarToken) {
var types = <NodeArray<TypeNode>>[type];
types.pos = type.pos;
while (parseOptional(SyntaxKind.BarToken)) {
types.push(parseNonUnionType());
}
types.end = getNodeEnd();
var node = <UnionTypeNode>createNode(SyntaxKind.UnionType, type.pos);
node.types = types;
type = finishNode(node);
}
return type;
}
function parseTypeAnnotation(): TypeNode {
return parseOptional(SyntaxKind.ColonToken) ? parseType() : undefined;
}
@@ -1829,7 +1938,7 @@ module ts {
var pos = getNodePos();
if (triState === Tristate.True) {
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken);
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false);
// If we have an arrow, then try to parse the body.
// Even if not, try to parse if we have an opening brace, just in case we're in an error state.
@@ -1932,7 +2041,7 @@ module ts {
function tryParseSignatureIfArrowOrBraceFollows(): ParsedSignature {
return tryParse(() => {
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken);
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false);
// Parsing a signature isn't enough.
// Parenthesized arrow signatures often look like other valid expressions.
@@ -2081,10 +2190,10 @@ module ts {
// The identifier eval or arguments may not appear as the LeftHandSideExpression of an
// Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression
// operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator
if ((token === SyntaxKind.PlusPlusToken || token === SyntaxKind.MinusMinusToken) && isEvalOrArgumentsIdentifier(operand)) {
if ((operator === SyntaxKind.PlusPlusToken || operator === SyntaxKind.MinusMinusToken) && isEvalOrArgumentsIdentifier(operand)) {
reportInvalidUseInStrictMode(<Identifier>operand);
}
else if (token === SyntaxKind.DeleteKeyword && operand.kind === SyntaxKind.Identifier) {
else if (operator === SyntaxKind.DeleteKeyword && operand.kind === SyntaxKind.Identifier) {
// When a delete operator occurs within strict mode code, a SyntaxError is thrown if its
// UnaryExpression is a direct reference to a variable, function argument, or function name
grammarErrorOnNode(operand, Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode);
@@ -2143,10 +2252,38 @@ module ts {
function parseCallAndAccess(expr: Expression, inNewExpression: boolean): Expression {
while (true) {
var dotStart = scanner.getTokenPos();
if (parseOptional(SyntaxKind.DotToken)) {
var propertyAccess = <PropertyAccess>createNode(SyntaxKind.PropertyAccess, expr.pos);
// Technically a keyword is valid here as all keywords are identifier names.
// However, often we'll encounter this in error situations when the keyword
// is actually starting another valid construct.
//
// So, we check for the following specific case:
//
// name.
// keyword identifierNameOrKeyword
//
// Note: the newlines are important here. For example, if that above code
// were rewritten into:
//
// name.keyword
// identifierNameOrKeyword
//
// Then we would consider it valid. That's because ASI would take effect and
// the code would be implicitly: "name.keyword; identifierNameOrKeyword".
// In the first case though, ASI will not take effect because there is not a
// line terminator after the keyword.
if (scanner.hasPrecedingLineBreak() && scanner.isReservedWord() && lookAhead(() => scanner.isReservedWord())) {
grammarErrorAtPos(dotStart, scanner.getStartPos() - dotStart, Diagnostics.Identifier_expected);
var id = <Identifier>createMissingNode();
}
else {
var id = parseIdentifierName();
}
propertyAccess.left = expr;
propertyAccess.right = parseIdentifierName();
propertyAccess.right = id;
expr = finishNode(propertyAccess);
continue;
}
@@ -2188,7 +2325,8 @@ module ts {
else {
parseExpected(SyntaxKind.OpenParenToken);
}
callExpr.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions, parseAssignmentExpression, TrailingCommaBehavior.Disallow);
callExpr.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions,
parseArgumentExpression, /*allowTrailingComma*/ false);
parseExpected(SyntaxKind.CloseParenToken);
expr = finishNode(callExpr);
continue;
@@ -2257,15 +2395,33 @@ module ts {
return finishNode(node);
}
function parseAssignmentExpressionOrOmittedExpression(omittedExpressionDiagnostic: DiagnosticMessage): Expression {
if (token === SyntaxKind.CommaToken) {
if (omittedExpressionDiagnostic) {
var errorStart = scanner.getTokenPos();
var errorLength = scanner.getTextPos() - errorStart;
grammarErrorAtPos(errorStart, errorLength, omittedExpressionDiagnostic);
}
return createNode(SyntaxKind.OmittedExpression);
}
return parseAssignmentExpression();
}
function parseArrayLiteralElement(): Expression {
return token === SyntaxKind.CommaToken ? createNode(SyntaxKind.OmittedExpression) : parseAssignmentExpression();
return parseAssignmentExpressionOrOmittedExpression(/*omittedExpressionDiagnostic*/ undefined);
}
function parseArgumentExpression(): Expression {
return parseAssignmentExpressionOrOmittedExpression(Diagnostics.Argument_expression_expected);
}
function parseArrayLiteral(): ArrayLiteral {
var node = <ArrayLiteral>createNode(SyntaxKind.ArrayLiteral);
parseExpected(SyntaxKind.OpenBracketToken);
if (scanner.hasPrecedingLineBreak()) node.flags |= NodeFlags.MultiLine;
node.elements = parseDelimitedList(ParsingContext.ArrayLiteralMembers, parseArrayLiteralElement, TrailingCommaBehavior.Preserve);
node.elements = parseDelimitedList(ParsingContext.ArrayLiteralMembers,
parseArrayLiteralElement, /*allowTrailingComma*/ true);
parseExpected(SyntaxKind.CloseBracketToken);
return finishNode(node);
}
@@ -2274,7 +2430,7 @@ module ts {
var node = <PropertyDeclaration>createNode(SyntaxKind.PropertyAssignment);
node.name = parsePropertyName();
if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) {
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken);
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false);
var body = parseBody(/* ignoreMissingOpenBrace */ false);
// do not propagate property name as name for function expression
// for scenarios like
@@ -2307,10 +2463,7 @@ module ts {
node.flags |= NodeFlags.MultiLine;
}
// ES3 itself does not accept a trailing comma in an object literal, however, we'd like to preserve it in ES5.
var trailingCommaBehavior = languageVersion === ScriptTarget.ES3 ? TrailingCommaBehavior.Allow : TrailingCommaBehavior.Preserve;
node.properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralMember, trailingCommaBehavior);
node.properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralMember, /*allowTrailingComma*/ true);
parseExpected(SyntaxKind.CloseBraceToken);
var seen: Map<SymbolFlags> = {};
@@ -2374,7 +2527,7 @@ module ts {
var pos = getNodePos();
parseExpected(SyntaxKind.FunctionKeyword);
var name = isIdentifier() ? parseIdentifier() : undefined;
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken);
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false);
var body = parseBody(/* ignoreMissingOpenBrace */ false);
if (name && isInStrictMode && isEvalOrArgumentsIdentifier(name)) {
// It is a SyntaxError to use within strict mode code the identifiers eval or arguments as the
@@ -2399,7 +2552,8 @@ module ts {
parseExpected(SyntaxKind.NewKeyword);
node.func = parseCallAndAccess(parsePrimaryExpression(), /* inNewExpression */ true);
if (parseOptional(SyntaxKind.OpenParenToken) || token === SyntaxKind.LessThanToken && (node.typeArguments = tryParse(parseTypeArgumentsAndOpenParen))) {
node.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions, parseAssignmentExpression, TrailingCommaBehavior.Disallow);
node.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions,
parseArgumentExpression, /*allowTrailingComma*/ false);
parseExpected(SyntaxKind.CloseParenToken);
}
return finishNode(node);
@@ -2799,13 +2953,13 @@ module ts {
return isIdentifier() && lookAhead(() => nextToken() === SyntaxKind.ColonToken);
}
function parseLabelledStatement(): LabelledStatement {
var node = <LabelledStatement>createNode(SyntaxKind.LabelledStatement);
function parseLabelledStatement(): LabeledStatement {
var node = <LabeledStatement>createNode(SyntaxKind.LabeledStatement);
node.label = parseIdentifier();
parseExpected(SyntaxKind.ColonToken);
if (labelledStatementInfo.nodeIsNestedInLabel(node.label, /*requireIterationStatement*/ false, /*stopAtFunctionBoundary*/ true)) {
grammarErrorOnNode(node.label, Diagnostics.Duplicate_label_0, getSourceTextOfNodeFromSourceText(sourceText, node.label));
grammarErrorOnNode(node.label, Diagnostics.Duplicate_label_0, getTextOfNodeFromSourceText(sourceText, node.label));
}
labelledStatementInfo.addLabel(node.label);
@@ -2863,6 +3017,7 @@ module ts {
}
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.StaticKeyword:
// When followed by an identifier or keyword, these do not start a statement but
// might instead be following type members
@@ -2967,7 +3122,8 @@ module ts {
}
function parseVariableDeclarationList(flags: NodeFlags, noIn?: boolean): NodeArray<VariableDeclaration> {
return parseDelimitedList(ParsingContext.VariableDeclarations, () => parseVariableDeclaration(flags, noIn), TrailingCommaBehavior.Disallow);
return parseDelimitedList(ParsingContext.VariableDeclarations,
() => parseVariableDeclaration(flags, noIn), /*allowTrailingComma*/ false);
}
function parseVariableStatement(pos?: number, flags?: NodeFlags): VariableStatement {
@@ -2989,7 +3145,7 @@ module ts {
if (flags) node.flags = flags;
parseExpected(SyntaxKind.FunctionKeyword);
node.name = parseIdentifier();
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken);
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false);
node.typeParameters = sig.typeParameters;
node.parameters = sig.parameters;
node.type = sig.type;
@@ -3006,7 +3162,7 @@ module ts {
var node = <ConstructorDeclaration>createNode(SyntaxKind.Constructor, pos);
node.flags = flags;
parseExpected(SyntaxKind.ConstructorKeyword);
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken);
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false);
node.typeParameters = sig.typeParameters;
node.parameters = sig.parameters;
node.type = sig.type;
@@ -3033,7 +3189,7 @@ module ts {
var method = <MethodDeclaration>createNode(SyntaxKind.Method, pos);
method.flags = flags;
method.name = name;
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken);
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false);
method.typeParameters = sig.typeParameters;
method.parameters = sig.parameters;
method.type = sig.type;
@@ -3106,7 +3262,7 @@ module ts {
var node = <MethodDeclaration>createNode(kind, pos);
node.flags = flags;
node.name = parsePropertyName();
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken);
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false);
node.typeParameters = sig.typeParameters;
node.parameters = sig.parameters;
node.type = sig.type;
@@ -3181,6 +3337,8 @@ module ts {
var lastDeclareModifierLength: number;
var lastPrivateModifierStart: number;
var lastPrivateModifierLength: number;
var lastProtectedModifierStart: number;
var lastProtectedModifierLength: number;
while (true) {
var modifierStart = scanner.getTokenPos();
@@ -3193,7 +3351,7 @@ module ts {
switch (modifierToken) {
case SyntaxKind.PublicKeyword:
if (flags & NodeFlags.Private || flags & NodeFlags.Public) {
if (flags & NodeFlags.AccessibilityModifier) {
grammarErrorAtPos(modifierStart, modifierLength, Diagnostics.Accessibility_modifier_already_seen);
}
else if (flags & NodeFlags.Static) {
@@ -3206,7 +3364,7 @@ module ts {
break;
case SyntaxKind.PrivateKeyword:
if (flags & NodeFlags.Private || flags & NodeFlags.Public) {
if (flags & NodeFlags.AccessibilityModifier) {
grammarErrorAtPos(modifierStart, modifierLength, Diagnostics.Accessibility_modifier_already_seen);
}
else if (flags & NodeFlags.Static) {
@@ -3220,6 +3378,21 @@ module ts {
flags |= NodeFlags.Private;
break;
case SyntaxKind.ProtectedKeyword:
if (flags & NodeFlags.Public || flags & NodeFlags.Private || flags & NodeFlags.Protected) {
grammarErrorAtPos(modifierStart, modifierLength, Diagnostics.Accessibility_modifier_already_seen);
}
else if (flags & NodeFlags.Static) {
grammarErrorAtPos(modifierStart, modifierLength, Diagnostics._0_modifier_must_precede_1_modifier, "protected", "static");
}
else if (context === ModifierContext.ModuleElements || context === ModifierContext.SourceElements) {
grammarErrorAtPos(modifierStart, modifierLength, Diagnostics._0_modifier_cannot_appear_on_a_module_element, "protected");
}
lastProtectedModifierStart = modifierStart;
lastProtectedModifierLength = modifierLength;
flags |= NodeFlags.Protected;
break;
case SyntaxKind.StaticKeyword:
if (flags & NodeFlags.Static) {
grammarErrorAtPos(modifierStart, modifierLength, Diagnostics._0_modifier_already_seen, "static");
@@ -3277,6 +3450,9 @@ module ts {
else if (token === SyntaxKind.ConstructorKeyword && flags & NodeFlags.Private) {
grammarErrorAtPos(lastPrivateModifierStart, lastPrivateModifierLength, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "private");
}
else if (token === SyntaxKind.ConstructorKeyword && flags & NodeFlags.Protected) {
grammarErrorAtPos(lastProtectedModifierStart, lastProtectedModifierLength, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "protected");
}
else if (token === SyntaxKind.ImportKeyword) {
if (flags & NodeFlags.Ambient) {
grammarErrorAtPos(lastDeclareModifierStart, lastDeclareModifierLength, Diagnostics.A_declare_modifier_cannot_be_used_with_an_import_declaration, "declare");
@@ -3346,7 +3522,8 @@ module ts {
var implementsKeywordLength: number;
if (parseOptional(SyntaxKind.ImplementsKeyword)) {
implementsKeywordLength = scanner.getStartPos() - implementsKeywordStart;
node.implementedTypes = parseDelimitedList(ParsingContext.BaseTypeReferences, parseTypeReference, TrailingCommaBehavior.Disallow);
node.implementedTypes = parseDelimitedList(ParsingContext.BaseTypeReferences,
parseTypeReference, /*allowTrailingComma*/ false);
}
var errorCountBeforeClassBody = file.syntacticErrors.length;
if (parseExpected(SyntaxKind.OpenBraceToken)) {
@@ -3374,7 +3551,8 @@ module ts {
var extendsKeywordLength: number;
if (parseOptional(SyntaxKind.ExtendsKeyword)) {
extendsKeywordLength = scanner.getStartPos() - extendsKeywordStart;
node.baseTypes = parseDelimitedList(ParsingContext.BaseTypeReferences, parseTypeReference, TrailingCommaBehavior.Disallow);
node.baseTypes = parseDelimitedList(ParsingContext.BaseTypeReferences,
parseTypeReference, /*allowTrailingComma*/ false);
}
var errorCountBeforeInterfaceBody = file.syntacticErrors.length;
node.members = parseTypeLiteral().members;
@@ -3383,7 +3561,7 @@ module ts {
}
return finishNode(node);
}
function parseAndCheckEnumDeclaration(pos: number, flags: NodeFlags): EnumDeclaration {
function isIntegerLiteral(expression: Expression): boolean {
function isInteger(literalExpression: LiteralExpression): boolean {
@@ -3438,7 +3616,8 @@ module ts {
parseExpected(SyntaxKind.EnumKeyword);
node.name = parseIdentifier();
if (parseExpected(SyntaxKind.OpenBraceToken)) {
node.members = parseDelimitedList(ParsingContext.EnumMembers, parseAndCheckEnumMember, TrailingCommaBehavior.Allow);
node.members = parseDelimitedList(ParsingContext.EnumMembers,
parseAndCheckEnumMember, /*allowTrailingComma*/ true);
parseExpected(SyntaxKind.CloseBraceToken);
}
else {
@@ -3533,7 +3712,7 @@ module ts {
return finishNode(node);
}
function isDeclaration() {
function isDeclaration(): boolean {
switch (token) {
case SyntaxKind.VarKeyword:
case SyntaxKind.FunctionKeyword:
@@ -3553,6 +3732,7 @@ module ts {
case SyntaxKind.DeclareKeyword:
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.StaticKeyword:
// Check for modifier on source element
return lookAhead(() => { nextToken(); return isDeclaration(); });
@@ -3659,15 +3839,17 @@ module ts {
}
else {
var matchResult = fullTripleSlashReferencePathRegEx.exec(comment);
var start = range.pos;
var end = range.end;
var length = end - start;
if (!matchResult) {
var start = range.pos;
var length = range.end - start;
errorAtPos(start, length, Diagnostics.Invalid_reference_directive_syntax);
}
else {
referencedFiles.push({
pos: range.pos,
end: range.end,
pos: start,
end: end,
filename: matchResult[3]
});
}
@@ -3697,7 +3879,7 @@ module ts {
: undefined);
}
scanner = createScanner(languageVersion, sourceText, scanError, onComment);
scanner = createScanner(languageVersion, /*skipTrivia*/ true, sourceText, scanError, onComment);
var rootNodeFlags: NodeFlags = 0;
if (fileExtensionIs(filename, ".d.ts")) {
rootNodeFlags = NodeFlags.DeclarationFile;
@@ -3776,17 +3958,31 @@ module ts {
var start = refPos;
var length = refEnd - refPos;
}
var diagnostic: DiagnosticMessage;
if (hasExtension(filename)) {
if (!fileExtensionIs(filename, ".ts")) {
errors.push(createFileDiagnostic(refFile, start, length, Diagnostics.File_0_must_have_extension_ts_or_d_ts, filename));
diagnostic = Diagnostics.File_0_must_have_extension_ts_or_d_ts;
}
else if (!findSourceFile(filename, isDefaultLib, refFile, refPos, refEnd)) {
errors.push(createFileDiagnostic(refFile, start, length, Diagnostics.File_0_not_found, filename));
diagnostic = Diagnostics.File_0_not_found;
}
else if (refFile && host.getCanonicalFileName(filename) === host.getCanonicalFileName(refFile.filename)) {
diagnostic = Diagnostics.A_file_cannot_have_a_reference_to_itself;
}
}
else {
if (!(findSourceFile(filename + ".ts", isDefaultLib, refFile, refPos, refEnd) || findSourceFile(filename + ".d.ts", isDefaultLib, refFile, refPos, refEnd))) {
errors.push(createFileDiagnostic(refFile, start, length, Diagnostics.File_0_not_found, filename + ".ts"));
diagnostic = Diagnostics.File_0_not_found;
filename += ".ts";
}
}
if (diagnostic) {
if (refFile) {
errors.push(createFileDiagnostic(refFile, start, length, diagnostic, filename));
}
else {
errors.push(createCompilerDiagnostic(diagnostic, filename));
}
}
}
@@ -3831,7 +4027,8 @@ module ts {
function processReferencedFiles(file: SourceFile, basePath: string) {
forEach(file.referencedFiles, ref => {
processSourceFile(normalizePath(combinePaths(basePath, ref.filename)), /* isDefaultLib */ false, file, ref.pos, ref.end);
var referencedFilename = isRootedDiskPath(ref.filename) ? ref.filename : combinePaths(basePath, ref.filename);
processSourceFile(normalizePath(referencedFilename), /* isDefaultLib */ false, file, ref.pos, ref.end);
});
}
@@ -3856,7 +4053,7 @@ module ts {
}
}
}
else if (node.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>node).name.kind === SyntaxKind.StringLiteral && (node.flags & NodeFlags.Ambient || file.flags & NodeFlags.DeclarationFile)) {
else if (node.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>node).name.kind === SyntaxKind.StringLiteral && (node.flags & NodeFlags.Ambient || isDeclarationFile(file))) {
// TypeScript 1.0 spec (April 2014): 12.1.6
// An AmbientExternalModuleDeclaration declares an external module.
// This type of declaration is permitted only in the global module.
@@ -3919,11 +4116,11 @@ module ts {
// Each file contributes into common source file path
if (!(sourceFile.flags & NodeFlags.DeclarationFile)
&& !fileExtensionIs(sourceFile.filename, ".js")) {
var sourcePathCompoments = getNormalizedPathComponents(sourceFile.filename, host.getCurrentDirectory());
sourcePathCompoments.pop(); // FileName is not part of directory
var sourcePathComponents = getNormalizedPathComponents(sourceFile.filename, host.getCurrentDirectory());
sourcePathComponents.pop(); // FileName is not part of directory
if (commonPathComponents) {
for (var i = 0; i < Math.min(commonPathComponents.length, sourcePathCompoments.length); i++) {
if (commonPathComponents[i] !== sourcePathCompoments[i]) {
for (var i = 0; i < Math.min(commonPathComponents.length, sourcePathComponents.length); i++) {
if (commonPathComponents[i] !== sourcePathComponents[i]) {
if (i === 0) {
errors.push(createCompilerDiagnostic(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files));
return;
@@ -3936,18 +4133,18 @@ module ts {
}
// If the fileComponent path completely matched and less than already found update the length
if (sourcePathCompoments.length < commonPathComponents.length) {
commonPathComponents.length = sourcePathCompoments.length;
if (sourcePathComponents.length < commonPathComponents.length) {
commonPathComponents.length = sourcePathComponents.length;
}
}
else {
// first file
commonPathComponents = sourcePathCompoments;
commonPathComponents = sourcePathComponents;
}
}
});
commonSourceDirectory = getNormalizedPathFromPathCompoments(commonPathComponents);
commonSourceDirectory = getNormalizedPathFromPathComponents(commonPathComponents);
if (commonSourceDirectory) {
// Make sure directory path ends with directory separator so this string can directly
// used to replace with "" to get the relative path of the source file and the relative path doesn't
+42 -9
View File
@@ -371,8 +371,8 @@ module ts {
// between the given position and the next line break are returned. The return value is an array containing a TextRange for each
// comment. Single-line comment ranges include the beginning '//' characters but not the ending line break. Multi-line comment
// ranges include the beginning '/* and ending '*/' characters. The return value is undefined if no comments were found.
function getCommentRanges(text: string, pos: number, trailing: boolean): Comment[] {
var result: Comment[];
function getCommentRanges(text: string, pos: number, trailing: boolean): CommentRange[] {
var result: CommentRange[];
var collecting = trailing || pos === 0;
while (true) {
var ch = text.charCodeAt(pos);
@@ -440,11 +440,11 @@ module ts {
}
}
export function getLeadingComments(text: string, pos: number): Comment[] {
export function getLeadingCommentRanges(text: string, pos: number): CommentRange[] {
return getCommentRanges(text, pos, /*trailing*/ false);
}
export function getTrailingComments(text: string, pos: number): Comment[] {
export function getTrailingCommentRanges(text: string, pos: number): CommentRange[] {
return getCommentRanges(text, pos, /*trailing*/ true);
}
@@ -460,7 +460,7 @@ module ts {
ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierPart(ch, languageVersion);
}
export function createScanner(languageVersion: ScriptTarget, text?: string, onError?: ErrorCallback, onComment?: CommentCallback): Scanner {
export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, text?: string, onError?: ErrorCallback, onComment?: CommentCallback): Scanner {
var pos: number; // Current position (end position of text of current token)
var len: number; // Length of text
var startPos: number; // Start position of whitespace before current token
@@ -694,12 +694,34 @@ module ts {
case CharacterCodes.lineFeed:
case CharacterCodes.carriageReturn:
precedingLineBreak = true;
if (skipTrivia) {
pos++;
continue;
}
else {
if (ch === CharacterCodes.carriageReturn && pos + 1 < len && text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) {
// consume both CR and LF
pos += 2;
}
else {
pos++;
}
return token = SyntaxKind.NewLineTrivia;
}
case CharacterCodes.tab:
case CharacterCodes.verticalTab:
case CharacterCodes.formFeed:
case CharacterCodes.space:
pos++;
continue;
if (skipTrivia) {
pos++;
continue;
}
else {
while (pos < len && isWhiteSpace(text.charCodeAt(pos))) {
pos++;
}
return token = SyntaxKind.WhitespaceTrivia;
}
case CharacterCodes.exclamation:
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
if (text.charCodeAt(pos + 2) === CharacterCodes.equals) {
@@ -776,7 +798,13 @@ module ts {
if (onComment) {
onComment(tokenPos, pos);
}
continue;
if (skipTrivia) {
continue;
}
else {
return token = SyntaxKind.SingleLineCommentTrivia;
}
}
// Multi-line comment
if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) {
@@ -806,7 +834,12 @@ module ts {
onComment(tokenPos, pos);
}
continue;
if (skipTrivia) {
continue;
}
else {
return token = SyntaxKind.MultiLineCommentTrivia;
}
}
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
+34 -17
View File
@@ -9,7 +9,7 @@
/// <reference path="commandLineParser.ts"/>
module ts {
var version = "1.1.0.0";
var version = "1.3.0.0";
/**
* Checks to see if the locale is in the appropriate format,
@@ -199,8 +199,14 @@ module ts {
export function executeCommandLine(args: string[]): void {
var commandLine = parseCommandLine(args);
var compilerOptions = commandLine.options;
if (compilerOptions.locale) {
if (typeof JSON === "undefined") {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale"));
return sys.exit(1);
}
if (commandLine.options.locale) {
validateLocaleAndSetLanguage(commandLine.options.locale, commandLine.errors);
}
@@ -208,32 +214,38 @@ module ts {
// setting up localization, report them and quit.
if (commandLine.errors.length > 0) {
reportDiagnostics(commandLine.errors);
return sys.exit(1);
return sys.exit(EmitReturnStatus.CompilerOptionsErrors);
}
if (commandLine.options.version) {
if (compilerOptions.version) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Version_0, version));
return sys.exit(0);
return sys.exit(EmitReturnStatus.Succeeded);
}
if (commandLine.options.help || commandLine.filenames.length === 0) {
if (compilerOptions.help) {
printVersion();
printHelp();
return sys.exit(0);
return sys.exit(EmitReturnStatus.Succeeded);
}
var defaultCompilerHost = createCompilerHost(commandLine.options);
if (commandLine.filenames.length === 0) {
printVersion();
printHelp();
return sys.exit(EmitReturnStatus.CompilerOptionsErrors);
}
var defaultCompilerHost = createCompilerHost(compilerOptions);
if (commandLine.options.watch) {
if (compilerOptions.watch) {
if (!sys.watchFile) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"));
return sys.exit(1);
return sys.exit(EmitReturnStatus.CompilerOptionsErrors);
}
watchProgram(commandLine, defaultCompilerHost);
}
else {
var result = compile(commandLine, defaultCompilerHost).errors.length > 0 ? 1 : 0;
var result = compile(commandLine, defaultCompilerHost).exitStatus
return sys.exit(result);
}
}
@@ -328,21 +340,27 @@ module ts {
function compile(commandLine: ParsedCommandLine, compilerHost: CompilerHost) {
var parseStart = new Date().getTime();
var program = createProgram(commandLine.filenames, commandLine.options, compilerHost);
var compilerOptions = commandLine.options;
var program = createProgram(commandLine.filenames, compilerOptions, compilerHost);
var bindStart = new Date().getTime();
var errors = program.getDiagnostics();
var errors: Diagnostic[] = program.getDiagnostics();
var exitStatus: EmitReturnStatus;
if (errors.length) {
var checkStart = bindStart;
var emitStart = bindStart;
var reportStart = bindStart;
exitStatus = EmitReturnStatus.AllOutputGenerationSkipped;
}
else {
var checker = program.getTypeChecker(/*fullTypeCheckMode*/ true);
var checkStart = new Date().getTime();
var semanticErrors = checker.getDiagnostics();
var emitStart = new Date().getTime();
var emitErrors = checker.emitFiles().errors;
var emitOutput = checker.emitFiles();
var emitErrors = emitOutput.errors;
exitStatus = emitOutput.emitResultStatus;
var reportStart = new Date().getTime();
errors = concatenate(semanticErrors, emitErrors);
}
@@ -366,8 +384,7 @@ module ts {
reportTimeStatistic("Total time", reportStart - parseStart);
}
return { program: program, errors: errors };
return { program: program, exitStatus: exitStatus }
}
function printVersion() {
@@ -392,7 +409,7 @@ module ts {
// Build up the list of examples.
var padding = makePadding(marginLength);
output += getDiagnosticText(Diagnostics.Examples_Colon_0, makePadding(marginLength - examplesLength) + "tsc hello.ts") + sys.newLine;
output += padding + "tsc --out foo.js foo.ts" + sys.newLine;
output += padding + "tsc --out file.js file.ts" + sys.newLine;
output += padding + "tsc @args.txt" + sys.newLine;
output += sys.newLine;
+185 -58
View File
@@ -12,6 +12,10 @@ module ts {
export enum SyntaxKind {
Unknown,
EndOfFileToken,
SingleLineCommentTrivia,
MultiLineCommentTrivia,
NewLineTrivia,
WhitespaceTrivia,
// Literals
NumericLiteral,
StringLiteral,
@@ -149,6 +153,8 @@ module ts {
TypeQuery,
TypeLiteral,
ArrayType,
TupleType,
UnionType,
// Expression
ArrayLiteral,
ObjectLiteral,
@@ -183,7 +189,7 @@ module ts {
SwitchStatement,
CaseClause,
DefaultClause,
LabelledStatement,
LabeledStatement,
ThrowStatement,
TryStatement,
TryBlock,
@@ -219,9 +225,13 @@ module ts {
FirstFutureReservedWord = ImplementsKeyword,
LastFutureReservedWord = YieldKeyword,
FirstTypeNode = TypeReference,
LastTypeNode = ArrayType,
LastTypeNode = UnionType,
FirstPunctuation = OpenBraceToken,
LastPunctuation = CaretEqualsToken
LastPunctuation = CaretEqualsToken,
FirstToken = EndOfFileToken,
LastToken = StringKeyword,
FirstTriviaToken = SingleLineCommentTrivia,
LastTriviaToken = WhitespaceTrivia
}
export enum NodeFlags {
@@ -231,12 +241,14 @@ module ts {
Rest = 0x00000008, // Parameter
Public = 0x00000010, // Property/Method
Private = 0x00000020, // Property/Method
Static = 0x00000040, // Property/Method
MultiLine = 0x00000080, // Multi-line array or object literal
Synthetic = 0x00000100, // Synthetic node (for full fidelity)
DeclarationFile = 0x00000200, // Node is a .d.ts file
Protected = 0x00000040, // Property/Method
Static = 0x00000080, // Property/Method
MultiLine = 0x00000100, // Multi-line array or object literal
Synthetic = 0x00000200, // Synthetic node (for full fidelity)
DeclarationFile = 0x00000400, // Node is a .d.ts file
Modifier = Export | Ambient | Public | Private | Static
Modifier = Export | Ambient | Public | Private | Protected | Static,
AccessibilityModifier = Public | Private | Protected
}
export interface Node extends TextRange {
@@ -250,7 +262,9 @@ module ts {
localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes)
}
export interface NodeArray<T> extends Array<T>, TextRange { }
export interface NodeArray<T> extends Array<T>, TextRange {
hasTrailingComma?: boolean;
}
export interface Identifier extends Node {
text: string; // Text of identifier (with escapes converted to characters)
@@ -320,6 +334,14 @@ module ts {
elementType: TypeNode;
}
export interface TupleTypeNode extends TypeNode {
elementTypes: NodeArray<TypeNode>;
}
export interface UnionTypeNode extends TypeNode {
types: NodeArray<TypeNode>;
}
export interface StringLiteralTypeNode extends TypeNode {
text: string;
}
@@ -459,7 +481,7 @@ module ts {
statements: NodeArray<Statement>;
}
export interface LabelledStatement extends Statement {
export interface LabeledStatement extends Statement {
label: Identifier;
statement: Statement;
}
@@ -516,7 +538,7 @@ module ts {
filename: string;
}
export interface Comment extends TextRange {
export interface CommentRange extends TextRange {
hasTrailingNewLine?: boolean;
}
@@ -569,7 +591,7 @@ module ts {
export interface SourceMapData {
/** Where the sourcemap file is written */
sourceMapFilePath: string;
/** source map url written in the js file */
/** source map URL written in the js file */
jsSourceMappingURL: string;
/** Source map's file field - js file name*/
sourceMapFile: string;
@@ -588,7 +610,18 @@ module ts {
sourceMapDecodedMappings: SourceMapSpan[];
}
// Return code used by getEmitOutput function to indicate status of the function
export enum EmitReturnStatus {
Succeeded = 0, // All outputs generated as requested (.js, .map, .d.ts), no errors reported
AllOutputGenerationSkipped = 1, // No .js generated because of syntax errors, nothing generated
JSGeneratedWithSemanticErrors = 2, // .js and .map generated with semantic errors
DeclarationGenerationSkipped = 3, // .d.ts generation skipped because of semantic errors or declaration emitter specific errors; Output .js with semantic errors
EmitErrorsEncountered = 4, // Emitter errors occurred during emitting process
CompilerOptionsErrors = 5, // Errors occurred in parsing compiler options, nothing generated
}
export interface EmitResult {
emitResultStatus: EmitReturnStatus;
errors: Diagnostic[];
sourceMaps: SourceMapData[]; // Array of sourceMapData if compiler emitted sourcemaps
}
@@ -602,7 +635,7 @@ module ts {
getSymbolCount(): number;
getTypeCount(): number;
checkProgram(): void;
emitFiles(): EmitResult;
emitFiles(targetSourceFile?: SourceFile): EmitResult;
getParentOfSymbol(symbol: Symbol): Symbol;
getTypeOfSymbol(symbol: Symbol): Type;
getPropertiesOfType(type: Type): Symbol[];
@@ -615,26 +648,63 @@ module ts {
getTypeOfNode(node: Node): Type;
getApparentType(type: Type): ApparentType;
typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
writeType(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string;
writeSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void;
getFullyQualifiedName(symbol: Symbol): string;
getAugmentedPropertiesOfApparentType(type: Type): Symbol[];
getRootSymbol(symbol: Symbol): Symbol;
getRootSymbols(symbol: Symbol): Symbol[];
getContextualType(node: Node): Type;
getResolvedSignature(node: CallExpression, candidatesOutArray?: Signature[]): Signature;
getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature;
writeSignature(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
writeTypeParameter(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
writeTypeParametersOfSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags): void;
isImplementationOfOverload(node: FunctionDeclaration): boolean;
isUndefinedSymbol(symbol: Symbol): boolean;
isArgumentsSymbol(symbol: Symbol): boolean;
// Returns the constant value of this enum member, or 'undefined' if the enum member has a
// computed value.
getEnumMemberValue(node: EnumMember): number;
isValidPropertyAccess(node: PropertyAccess, propertyName: string): boolean;
getAliasedSymbol(symbol: Symbol): Symbol;
}
export interface TextWriter {
write(s: string): void;
writeSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void;
export interface SymbolWriter {
writeKind(text: string, kind: SymbolDisplayPartKind): void;
writeSymbol(text: string, symbol: Symbol): void;
writeLine(): void;
increaseIndent(): void;
decreaseIndent(): void;
getText(): string;
clear(): void;
// Called when the symbol writer encounters a symbol to write. Currently only used by the
// declaration emitter to help determine if it should patch up the final declaration file
// with import statements it previously saw (but chose not to emit).
trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void;
}
export enum TypeFormatFlags {
None = 0x00000000,
WriteArrayAsGenericType = 0x00000001, // Write Array<T> instead T[]
UseTypeOfFunction = 0x00000002, // Write typeof instead of function type literal
NoTruncation = 0x00000004, // Don't truncate typeToString result
None = 0x00000000,
WriteArrayAsGenericType = 0x00000001, // Write Array<T> instead T[]
UseTypeOfFunction = 0x00000002, // Write typeof instead of function type literal
NoTruncation = 0x00000004, // Don't truncate typeToString result
WriteArrowStyleSignature = 0x00000008, // Write arrow style signature
WriteOwnNameForAnyLike = 0x00000010, // Write symbol's own name instead of 'any' for any like types (eg. unknown, __resolving__ etc)
WriteTypeArgumentsOfSignature = 0x00000020, // Write the type arguments instead of type parameters of the signature
}
export enum SymbolFormatFlags {
None = 0x00000000,
WriteTypeParametersOrArguments = 0x00000001, // Write symbols's type argument if it is instantiated symbol
// eg. class C<T> { p: T } <-- Show p as C<T>.p here
// var a: C<number>;
// var p = a.p; <--- Here p is property of C<number> so show it as C<number>.p instead of just C.p
UseOnlyExternalAliasing = 0x00000002, // Use only external alias information to get the symbol name in the given context
// eg. module m { export class c { } } import x = m.c;
// When this flag is specified m.c will be used to refer to the class instead of alias symbol x
}
export enum SymbolAccessibility {
@@ -654,20 +724,22 @@ module ts {
getProgram(): Program;
getLocalNameOfContainer(container: Declaration): string;
getExpressionNamePrefix(node: Identifier): string;
getPropertyAccessSubstitution(node: PropertyAccess): string;
getExportAssignmentName(node: SourceFile): string;
isReferencedImportDeclaration(node: ImportDeclaration): boolean;
isTopLevelValueImportedViaEntityName(node: ImportDeclaration): boolean;
getNodeCheckFlags(node: Node): NodeCheckFlags;
getEnumMemberValue(node: EnumMember): number;
shouldEmitDeclarations(): boolean;
hasSemanticErrors(): boolean;
isDeclarationVisible(node: Declaration): boolean;
isImplementationOfOverload(node: FunctionDeclaration): boolean;
writeTypeAtLocation(location: Node, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: TextWriter): void;
writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: TextWriter): void;
writeSymbol(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, writer: TextWriter): void;
writeTypeAtLocation(location: Node, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessiblityResult;
isImportDeclarationEntityNameReferenceDeclarationVisibile(entityName: EntityName): SymbolAccessiblityResult;
// Returns the constant value this property access resolves to, or 'undefined' if it does
// resolve to a constant.
getConstantValue(node: PropertyAccess): number;
}
export enum SymbolFlags {
@@ -690,19 +762,22 @@ module ts {
ConstructSignature = 0x00010000, // Construct signature
IndexSignature = 0x00020000, // Index signature
TypeParameter = 0x00040000, // Type parameter
UnionProperty = 0x00080000, // Property in union type
// Export markers (see comment in declareModuleMember in binder)
ExportValue = 0x00080000, // Exported value marker
ExportType = 0x00100000, // Exported type marker
ExportNamespace = 0x00200000, // Exported namespace marker
ExportValue = 0x00100000, // Exported value marker
ExportType = 0x00200000, // Exported type marker
ExportNamespace = 0x00400000, // Exported namespace marker
Import = 0x00400000, // Import
Instantiated = 0x00800000, // Instantiated symbol
Merged = 0x01000000, // Merged symbol (created during program binding)
Transient = 0x02000000, // Transient symbol (created during type check)
Prototype = 0x04000000, // Symbol for the prototype property (without source code representation)
Import = 0x00800000, // Import
Instantiated = 0x01000000, // Instantiated symbol
Merged = 0x02000000, // Merged symbol (created during program binding)
Transient = 0x04000000, // Transient symbol (created during type check)
Prototype = 0x08000000, // Prototype property (no source representation)
Undefined = 0x10000000, // Symbol for the undefined
Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor,
Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor | UnionProperty,
Type = Class | Interface | Enum | TypeLiteral | ObjectLiteral | TypeParameter,
Namespace = ValueModule | NamespaceModule,
Module = ValueModule | NamespaceModule,
@@ -760,6 +835,7 @@ module ts {
mapper?: TypeMapper; // Type mapper for instantiation alias
referenced?: boolean; // True if alias symbol has been referenced as a value
exportAssignSymbol?: Symbol; // Symbol exported from external module
unionType?: UnionType; // Containing union type for union property
}
export interface TransientSymbol extends Symbol, SymbolLinks { }
@@ -769,24 +845,28 @@ module ts {
}
export enum NodeCheckFlags {
TypeChecked = 0x00000001, // Node has been type checked
LexicalThis = 0x00000002, // Lexical 'this' reference
CaptureThis = 0x00000004, // Lexical 'this' used in body
EmitExtends = 0x00000008, // Emit __extends
SuperInstance = 0x00000010, // Instance 'super' reference
SuperStatic = 0x00000020, // Static 'super' reference
ContextChecked = 0x00000040, // Contextual types have been assigned
TypeChecked = 0x00000001, // Node has been type checked
LexicalThis = 0x00000002, // Lexical 'this' reference
CaptureThis = 0x00000004, // Lexical 'this' used in body
EmitExtends = 0x00000008, // Emit __extends
SuperInstance = 0x00000010, // Instance 'super' reference
SuperStatic = 0x00000020, // Static 'super' reference
ContextChecked = 0x00000040, // Contextual types have been assigned
// Values for enum members have been computed, and any errors have been reported for them.
EnumValuesComputed = 0x00000080,
}
export interface NodeLinks {
resolvedType?: Type; // Cached type of type node
resolvedSignature?: Signature; // Cached signature of signature node or call expression
resolvedSymbol?: Symbol; // Cached name resolution result
flags?: NodeCheckFlags; // Set of flags specific to Node
enumMemberValue?: number; // Constant value of enum member
resolvedType?: Type; // Cached type of type node
resolvedSignature?: Signature; // Cached signature of signature node or call expression
resolvedSymbol?: Symbol; // Cached name resolution result
flags?: NodeCheckFlags; // Set of flags specific to Node
enumMemberValue?: number; // Constant value of enum member
isIllegalTypeReferenceInConstraint?: boolean; // Is type reference in constraint refers to the type parameter from the same list
isVisible?: boolean; // Is this node visible
localModuleName?: string; // Local name for module instance
isVisible?: boolean; // Is this node visible
localModuleName?: string; // Local name for module instance
assignmentChecks?: Map<boolean>; // Cache of assignment checks
}
export enum TypeFlags {
@@ -803,13 +883,15 @@ module ts {
Class = 0x00000400, // Class
Interface = 0x00000800, // Interface
Reference = 0x00001000, // Generic type reference
Anonymous = 0x00002000, // Anonymous
FromSignature = 0x00004000, // Created for signature assignment check
Tuple = 0x00002000, // Tuple
Union = 0x00004000, // Union
Anonymous = 0x00008000, // Anonymous
FromSignature = 0x00010000, // Created for signature assignment check
Intrinsic = Any | String | Number | Boolean | Void | Undefined | Null,
Intrinsic = Any | String | Number | Boolean | Void | Undefined | Null,
StringLike = String | StringLiteral,
NumberLike = Number | Enum,
ObjectType = Class | Interface | Reference | Anonymous
ObjectType = Class | Interface | Reference | Tuple | Union | Anonymous,
}
// Properties common to all types
@@ -862,6 +944,15 @@ module ts {
openReferenceChecks: Map<boolean>; // Open type reference check cache
}
export interface TupleType extends ObjectType {
elementTypes: Type[]; // Element types
baseArrayType: TypeReference; // Array<T> where T is best common type of element types
}
export interface UnionType extends ObjectType {
types: Type[]; // Constituent types
}
// Resolved object type
export interface ResolvedObjectType extends ObjectType {
members: SymbolTable; // Properties by name
@@ -891,9 +982,10 @@ module ts {
resolvedReturnType: Type; // Resolved return type
minArgumentCount: number; // Number of non-optional parameters
hasRestParameter: boolean; // True if last parameter is rest parameter
hasStringLiterals: boolean; // True if instantiated
hasStringLiterals: boolean; // True if specialized
target?: Signature; // Instantiation target
mapper?: TypeMapper; // Instantiation mapper
unionSignatures?: Signature[]; // Underlying signatures of a union signature
erasedSignatureCache?: Signature; // Erased version of signature (deferred)
isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison
}
@@ -908,9 +1000,10 @@ module ts {
}
export interface InferenceContext {
typeParameters: TypeParameter[];
inferences: Type[][];
inferredTypes: Type[];
typeParameters: TypeParameter[]; // Type parameters for which inferences are made
inferenceCount: number; // Incremented for every inference made (whether new or not)
inferences: Type[][]; // Inferences made for each type parameter
inferredTypes: Type[]; // Inferred type for each type parameter
}
export interface DiagnosticMessage {
@@ -977,6 +1070,15 @@ module ts {
AMD,
}
export interface LineAndCharacter {
line: number;
/*
* This value denotes the character position in line and is different from the 'column' because of tab characters.
*/
character: number;
}
export enum ScriptTarget {
ES3,
ES5,
@@ -1131,6 +1233,31 @@ module ts {
verticalTab = 0x0B, // \v
}
export enum SymbolDisplayPartKind {
aliasName,
className,
enumName,
fieldName,
interfaceName,
keyword,
lineBreak,
numericLiteral,
stringLiteral,
localName,
methodName,
moduleName,
operator,
parameterName,
propertyName,
punctuation,
space,
text,
typeParameterName,
enumMemberName,
functionName,
regularExpressionLiteral,
}
export interface CancellationToken {
isCancellationRequested(): boolean;
}
+2 -5
View File
@@ -156,10 +156,7 @@ class CompilerBaselineRunner extends RunnerBase {
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: { unitName: string; content: string }[], otherFiles: { unitName: string; content: string }[], result: Harness.Compiler.CompilerResult) {
return Harness.Compiler.getErrorBaseline(toBeCompiled.concat(otherFiles), result.errors);
}
@@ -168,7 +165,7 @@ class CompilerBaselineRunner extends RunnerBase {
if (this.errors) {
Harness.Baseline.runBaseline('Correct errors for ' + fileName, justName.replace(/\.ts$/, '.errors.txt'), (): string => {
if (result.errors.length === 0) return null;
return getErrorBaseline(toBeCompiled, otherFiles, result);
});
}
-225
View File
@@ -1,225 +0,0 @@
if (!String.prototype.trim) {
String.prototype.trim = function () {
return this.replace(/^\s+|\s+$/g, '');
};
}
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (searchElement, fromIndex) {
"use strict";
if (this == null) {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (len === 0) {
return -1;
}
var n = 0;
if (arguments.length > 0) {
n = Number(arguments[1]);
if (n != n) {
n = 0;
} else if (n != 0 && n != Infinity && n != -Infinity) {
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
}
if (n >= len) {
return -1;
}
var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
for (; k < len; k++) {
if (k in t && t[k] === searchElement) {
return k;
}
}
return -1;
};
}
if (!Array.prototype.filter) {
Array.prototype.filter = function (fun, thisp) {
"use strict";
if (this == null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun != "function")
throw new TypeError();
var res = [];
for (var i = 0; i < len; i++) {
if (i in t) {
var val = t[i];
if (fun.call(thisp, val, i, t))
res.push(val);
}
}
return res;
};
}
if (!Array.prototype.map) {
Array.prototype.map = function (callback, thisArg) {
var T = undefined, A, k;
if (this == null) {
throw new TypeError(" this is null or not defined");
}
// 1. Let O be the result of calling ToObject passing the |this| value as the argument.
var O = Object(this);
// 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0;
if ({}.toString.call(callback) != "[object Function]") {
throw new TypeError(callback + " is not a function");
}
if (thisArg) {
T = thisArg;
}
// 6. Let A be a new array created as if by the expression new Array(len) where Array is
// the standard built-in constructor with that name and len is the value of len.
A = new Array(len);
// 7. Let k be 0
k = 0;
while (k < len) {
var kValue, mappedValue;
if (k in O) {
// i. Let kValue be the result of calling the Get internal method of O with argument Pk.
kValue = O[k];
// ii. Let mappedValue be the result of calling the Call internal method of callback
// with T as the this value and argument list containing kValue, k, and O.
mappedValue = callback.call(T, kValue, k, O);
// iii. Call the DefineOwnProperty internal method of A with arguments
// Pk, Property Descriptor {Value: mappedValue, : true, Enumerable: true, Configurable: true},
// and false.
// In browsers that support Object.defineProperty, use the following:
// Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true });
// For best browser support, use the following:
A[k] = mappedValue;
}
// d. Increase k by 1.
k++;
}
// 9. return A
return A;
};
}
if (!Array.prototype.reduce) {
Array.prototype.reduce = function reduce(accumulator) {
if (this === null || this === undefined)
throw new TypeError("Object is null or undefined");
var i = 0, l = this.length >> 0, curr;
if (typeof accumulator !== "function")
throw new TypeError("First argument is not callable");
if (arguments.length < 2) {
if (l === 0)
throw new TypeError("Array length is 0 and no second argument");
curr = this[0];
i = 1;
} else
curr = arguments[1];
while (i < l) {
if (i in this)
curr = accumulator.call(undefined, curr, this[i], i, this);
++i;
}
return curr;
};
}
if (!Array.prototype.forEach) {
Array.prototype.forEach = function (callback, thisArg) {
var T, k;
if (this == null) {
throw new TypeError(" this is null or not defined");
}
// 1. Let O be the result of calling ToObject passing the |this| value as the argument.
var O = Object(this);
// 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0;
if ({}.toString.call(callback) != "[object Function]") {
throw new TypeError(callback + " is not a function");
}
if (thisArg) {
T = thisArg;
} else {
T = undefined;
}
// 6. Let k be 0
k = 0;
while (k < len) {
var kValue;
if (k in O) {
// i. Let kValue be the result of calling the Get internal method of O with argument Pk.
kValue = O[k];
// ii. Call the Call internal method of callback with T as the this value and
// argument list containing kValue, k, and O.
callback.call(T, kValue, k, O);
}
// d. Increase k by 1.
k++;
}
// 8. return undefined
};
}
if (!Date.now) {
Date.now = function () {
return (new Date()).getTime();
};
}
if (!Array.prototype.some) {
Array.prototype.some = function (fun/*, thisp */ ) {
"use strict";
if (this == null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun != "function")
throw new TypeError();
var thisp = arguments[1];
for (var i = 0; i < len; i++) {
var idx = i.toString();
if (idx in t && fun.call(thisp, t[i], i, t))
return true;
}
return false;
};
}
-354
View File
@@ -1,354 +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.
//
/*----------------- ThirdPartyNotices -------------------------------------------------------
This file is based on or incorporates material from the projects listed below
(collectively "Third Party Code"). Microsoft is not the original author of the
Third Party Code. The original copyright notice and the license, under which
Microsoft received such Third Party Code, are set forth below. Such license and
notices are provided for informational purposes only. Microsoft licenses the Third
Party Code to you under the terms of the Apache 2.0 License.
--
Array filter Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/filter
Array forEach Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach
Array indexOf Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf
Array map Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map
Array Reduce Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/Reduce
Array some Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/some
String Trim Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String/Trim
Date now Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date/now
Copyright (c) 2007 - 2012 Mozilla Developer Network and individual contributors
Licensed by Microsoft 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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions and
limitations under the License.
--
Original License provided for Informational Purposes Only
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------- End of ThirdPartyNotices --------------------------------------------------- */
// Compatibility with non ES5 compliant engines
if (!String.prototype.trim) {
String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g, '');
};
}
// Compatibility with non ES5 compliant engines
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (searchElement: any, fromIndex?: any) {
"use strict";
if (this == null) {
throw new TypeError();
}
var t = Object(this);
var len: any = t.length >>> 0;
if (len === 0) {
return -1;
}
var n: any = 0;
if (arguments.length > 0) {
n = Number(arguments[1]);
if (n != n) { // shortcut for verifying if it's NaN
n = 0;
}
else if (n != 0 && n != Infinity && n != -Infinity) {
n = (n > 0 || <any>-1) * Math.floor(Math.abs(n));
}
}
if (n >= len) {
return -1;
}
var k: any = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
for (; k < len; k++) {
if (k in t && t[k] === searchElement) {
return k;
}
}
return -1;
}
}
if (!Array.prototype.filter)
{
Array.prototype.filter = function(fun: any, thisp?: any)
{
"use strict";
if (this == null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun != "function")
throw new TypeError();
var res: any[] = [];
for (var i = 0; i < len; i++)
{
if (<any>i in t)
{
var val = t[i]; // in case fun mutates this
if (fun.call(thisp, val, i, t))
res.push(val);
}
}
return res;
};
}
// Production steps of ECMA-262, Edition 5, 15.4.4.19
// Reference: http://es5.github.com/#x15.4.4.19
if (!Array.prototype.map) {
Array.prototype.map = function(callback: any, thisArg?: any) {
var T: any = undefined, A: any, k: any;
if (this == null) {
throw new TypeError(" this is null or not defined");
}
// 1. Let O be the result of calling ToObject passing the |this| value as the argument.
var O = Object(this);
// 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0;
// 4. If IsCallable(callback) is false, throw a TypeError exception.
// See: http://es5.github.com/#x9.11
if ({}.toString.call(callback) != "[object Function]") {
throw new TypeError(callback + " is not a function");
}
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (thisArg) {
T = thisArg;
}
// 6. Let A be a new array created as if by the expression new Array(len) where Array is
// the standard built-in constructor with that name and len is the value of len.
A = new Array(len);
// 7. Let k be 0
k = 0;
// 8. Repeat, while k < len
while(k < len) {
var kValue: any, mappedValue: any;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) {
// i. Let kValue be the result of calling the Get internal method of O with argument Pk.
kValue = O[ k ];
// ii. Let mappedValue be the result of calling the Call internal method of callback
// with T as the this value and argument list containing kValue, k, and O.
mappedValue = callback.call(T, kValue, k, O);
// iii. Call the DefineOwnProperty internal method of A with arguments
// Pk, Property Descriptor {Value: mappedValue, : true, Enumerable: true, Configurable: true},
// and false.
// In browsers that support Object.defineProperty, use the following:
// Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true });
// For best browser support, use the following:
A[ k ] = mappedValue;
}
// d. Increase k by 1.
k++;
}
// 9. return A
return A;
};
}
if (!Array.prototype.reduce) {
Array.prototype.reduce = function reduce(accumulator: any){
if (this===null || this===undefined) throw new TypeError("Object is null or undefined");
var i = 0, l = this.length >> 0, curr: any;
if(typeof accumulator !== "function") // ES5 : "If IsCallable(callbackfn) is false, throw a TypeError exception."
throw new TypeError("First argument is not callable");
if(arguments.length < 2) {
if (l === 0) throw new TypeError("Array length is 0 and no second argument");
curr = this[0];
i = 1; // start accumulating at the second element
}
else
curr = arguments[1];
while (i < l) {
if(<any>i in this) curr = accumulator.call(undefined, curr, this[i], i, this);
++i;
}
return curr;
};
}
// Compatibility with non ES5 compliant engines
// Production steps of ECMA-262, Edition 5, 15.4.4.18
// Reference: http://es5.github.com/#x15.4.4.18
if (!Array.prototype.forEach) {
Array.prototype.forEach = function(callback: any, thisArg?: any) {
var T: any, k: any;
if (this == null) {
throw new TypeError(" this is null or not defined");
}
// 1. Let O be the result of calling ToObject passing the |this| value as the argument.
var O = Object(this);
// 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0; // Hack to convert O.length to a UInt32
// 4. If IsCallable(callback) is false, throw a TypeError exception.
// See: http://es5.github.com/#x9.11
if ({ }.toString.call(callback) != "[object Function]") {
throw new TypeError(callback + " is not a function");
}
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (thisArg) {
T = thisArg;
}
else {
T = undefined; // added to stop definite assignment error
}
// 6. Let k be 0
k = 0;
// 7. Repeat, while k < len
while (k < len) {
var kValue: any;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) {
// i. Let kValue be the result of calling the Get internal method of O with argument Pk.
kValue = O[k];
// ii. Call the Call internal method of callback with T as the this value and
// argument list containing kValue, k, and O.
callback.call(T, kValue, k, O);
}
// d. Increase k by 1.
k++;
}
// 8. return undefined
};
}
// Compatibility with non ES5 compliant engines
if (!Date.now) {
Date.now = function() {
return (new Date()).getTime();
};
}
// Compatibility with non ES5 compliant engines
// Production steps of ECMA-262, Edition 5.1, 15.4.4.17
if (!Array.prototype.some)
{
Array.prototype.some = function(fun: any /*, thisp */)
{
"use strict";
if (this == null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun != "function")
throw new TypeError();
var thisp = arguments[1];
for (var i = 0; i < len; i++)
{
var idx = i.toString(); // REVIEW: this line is not from the Mozilla page, necessary to avoid our compile time checks against non-string/any types in an in expression
if (idx in t && fun.call(thisp, t[i], i, t))
return true;
}
return false;
};
}
-486
View File
@@ -1,486 +0,0 @@
/*
json2.js
2013-05-26
Public Domain.
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
See http://www.JSON.org/js.html
This code should be minified before deployment.
See http://javascript.crockford.com/jsmin.html
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
NOT CONTROL.
This file creates a global JSON object containing two methods: stringify
and parse.
JSON.stringify(value, replacer, space)
value any JavaScript value, usually an object or array.
replacer an optional parameter that determines how object
values are stringified for objects. It can be a
function or an array of strings.
space an optional parameter that specifies the indentation
of nested structures. If it is omitted, the text will
be packed without extra whitespace. If it is a number,
it will specify the number of spaces to indent at each
level. If it is a string (such as '\t' or '&nbsp;'),
it contains the characters used to indent at each level.
This method produces a JSON text from a JavaScript value.
When an object value is found, if the object contains a toJSON
method, its toJSON method will be called and the result will be
stringified. A toJSON method does not serialize: it returns the
value represented by the name/value pair that should be serialized,
or undefined if nothing should be serialized. The toJSON method
will be passed the key associated with the value, and this will be
bound to the value
For example, this would serialize Dates as ISO strings.
Date.prototype.toJSON = function (key) {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
return this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z';
};
You can provide an optional replacer method. It will be passed the
key and value of each member, with this bound to the containing
object. The value that is returned from your method will be
serialized. If your method returns undefined, then the member will
be excluded from the serialization.
If the replacer parameter is an array of strings, then it will be
used to select the members to be serialized. It filters the results
such that only members with keys listed in the replacer array are
stringified.
Values that do not have JSON representations, such as undefined or
functions, will not be serialized. Such values in objects will be
dropped; in arrays they will be replaced with null. You can use
a replacer function to replace those with JSON values.
JSON.stringify(undefined) returns undefined.
The optional space parameter produces a stringification of the
value that is filled with line breaks and indentation to make it
easier to read.
If the space parameter is a non-empty string, then that string will
be used for indentation. If the space parameter is a number, then
the indentation will be that many spaces.
Example:
text = JSON.stringify(['e', {pluribus: 'unum'}]);
// text is '["e",{"pluribus":"unum"}]'
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
text = JSON.stringify([new Date()], function (key, value) {
return this[key] instanceof Date ?
'Date(' + this[key] + ')' : value;
});
// text is '["Date(---current time---)"]'
JSON.parse(text, reviver)
This method parses a JSON text to produce an object or array.
It can throw a SyntaxError exception.
The optional reviver parameter is a function that can filter and
transform the results. It receives each of the keys and values,
and its return value is used instead of the original value.
If it returns what it received, then the structure is not modified.
If it returns undefined then the member is deleted.
Example:
// Parse the text. Values that look like ISO date strings will
// be converted to Date objects.
myData = JSON.parse(text, function (key, value) {
var a;
if (typeof value === 'string') {
a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
if (a) {
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+a[5], +a[6]));
}
}
return value;
});
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
var d;
if (typeof value === 'string' &&
value.slice(0, 5) === 'Date(' &&
value.slice(-1) === ')') {
d = new Date(value.slice(5, -1));
if (d) {
return d;
}
}
return value;
});
This is a reference implementation. You are free to copy, modify, or
redistribute.
*/
/*jslint evil: true, regexp: true */
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
lastIndex, length, parse, prototype, push, replace, slice, stringify,
test, toJSON, toString, valueOf
*/
// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.
if (typeof JSON !== 'object') {
JSON = {};
}
(function () {
'use strict';
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
if (typeof Date.prototype.toJSON !== 'function') {
Date.prototype.toJSON = function () {
return isFinite(this.valueOf())
? this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z'
: null;
};
String.prototype.toJSON =
Number.prototype.toJSON =
Boolean.prototype.toJSON = function () {
return this.valueOf();
};
}
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
gap,
indent,
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
},
rep;
function quote(string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
escapable.lastIndex = 0;
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
var c = meta[a];
return typeof c === 'string'
? c
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' : '"' + string + '"';
}
function str(key, holder) {
// Produce a string from holder[key].
var i, // The loop counter.
k, // The member key.
v, // The member value.
length,
mind = gap,
partial,
value = holder[key];
// If the value has a toJSON method, call it to obtain a replacement value.
if (value && typeof value === 'object' &&
typeof value.toJSON === 'function') {
value = value.toJSON(key);
}
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
if (typeof rep === 'function') {
value = rep.call(holder, key, value);
}
// What happens next depends on the value's type.
switch (typeof value) {
case 'string':
return quote(value);
case 'number':
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : 'null';
case 'boolean':
case 'null':
// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.
return String(value);
// If the type is 'object', we might be dealing with an object or an array or
// null.
case 'object':
// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.
if (!value) {
return 'null';
}
// Make an array to hold the partial results of stringifying this object value.
gap += indent;
partial = [];
// Is the value an array?
if (Object.prototype.toString.apply(value) === '[object Array]') {
// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || 'null';
}
// Join all of the elements together, separated with commas, and wrap them in
// brackets.
v = partial.length === 0
? '[]'
: gap
? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
: '[' + partial.join(',') + ']';
gap = mind;
return v;
}
// If the replacer is an array, use it to select the members to be stringified.
if (rep && typeof rep === 'object') {
length = rep.length;
for (i = 0; i < length; i += 1) {
if (typeof rep[i] === 'string') {
k = rep[i];
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
} else {
// Otherwise, iterate through all of the keys in the object.
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
}
// Join all of the member texts together, separated with commas,
// and wrap them in braces.
v = partial.length === 0
? '{}'
: gap
? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
: '{' + partial.join(',') + '}';
gap = mind;
return v;
}
}
// If the JSON object does not yet have a stringify method, give it one.
if (typeof JSON.stringify !== 'function') {
JSON.stringify = function (value, replacer, space) {
// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.
var i;
gap = '';
indent = '';
// If the space parameter is a number, make an indent string containing that
// many spaces.
if (typeof space === 'number') {
for (i = 0; i < space; i += 1) {
indent += ' ';
}
// If the space parameter is a string, it will be used as the indent string.
} else if (typeof space === 'string') {
indent = space;
}
// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.
rep = replacer;
if (replacer && typeof replacer !== 'function' &&
(typeof replacer !== 'object' ||
typeof replacer.length !== 'number')) {
throw new Error('JSON.stringify');
}
// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.
return str('', {'': value});
};
}
// If the JSON object does not yet have a parse method, give it one.
if (typeof JSON.parse !== 'function') {
JSON.parse = function (text, reviver) {
// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.
var j;
function walk(holder, key) {
// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.
var k, v, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}
// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
text = String(text);
cx.lastIndex = 0;
if (cx.test(text)) {
text = text.replace(cx, function (a) {
return '\\u' +
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.
// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
if (/^[\],:{}\s]*$/
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
j = eval('(' + text + ')');
// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.
return typeof reviver === 'function'
? walk({'': j}, '')
: j;
}
// If the text is not JSON parseable, then a SyntaxError is thrown.
throw new SyntaxError('JSON.parse');
};
}
}());
-486
View File
@@ -1,486 +0,0 @@
/*
json2.js
2013-05-26
Public Domain.
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
See http://www.JSON.org/js.html
This code should be minified before deployment.
See http://javascript.crockford.com/jsmin.html
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
NOT CONTROL.
This file creates a global JSON object containing two methods: stringify
and parse.
JSON.stringify(value, replacer, space)
value any JavaScript value, usually an object or array.
replacer an optional parameter that determines how object
values are stringified for objects. It can be a
function or an array of strings.
space an optional parameter that specifies the indentation
of nested structures. If it is omitted, the text will
be packed without extra whitespace. If it is a number,
it will specify the number of spaces to indent at each
level. If it is a string (such as '\t' or '&nbsp;'),
it contains the characters used to indent at each level.
This method produces a JSON text from a JavaScript value.
When an object value is found, if the object contains a toJSON
method, its toJSON method will be called and the result will be
stringified. A toJSON method does not serialize: it returns the
value represented by the name/value pair that should be serialized,
or undefined if nothing should be serialized. The toJSON method
will be passed the key associated with the value, and this will be
bound to the value
For example, this would serialize Dates as ISO strings.
Date.prototype.toJSON = function (key) {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
return this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z';
};
You can provide an optional replacer method. It will be passed the
key and value of each member, with this bound to the containing
object. The value that is returned from your method will be
serialized. If your method returns undefined, then the member will
be excluded from the serialization.
If the replacer parameter is an array of strings, then it will be
used to select the members to be serialized. It filters the results
such that only members with keys listed in the replacer array are
stringified.
Values that do not have JSON representations, such as undefined or
functions, will not be serialized. Such values in objects will be
dropped; in arrays they will be replaced with null. You can use
a replacer function to replace those with JSON values.
JSON.stringify(undefined) returns undefined.
The optional space parameter produces a stringification of the
value that is filled with line breaks and indentation to make it
easier to read.
If the space parameter is a non-empty string, then that string will
be used for indentation. If the space parameter is a number, then
the indentation will be that many spaces.
Example:
text = JSON.stringify(['e', {pluribus: 'unum'}]);
// text is '["e",{"pluribus":"unum"}]'
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
text = JSON.stringify([new Date()], function (key, value) {
return this[key] instanceof Date ?
'Date(' + this[key] + ')' : value;
});
// text is '["Date(---current time---)"]'
JSON.parse(text, reviver)
This method parses a JSON text to produce an object or array.
It can throw a SyntaxError exception.
The optional reviver parameter is a function that can filter and
transform the results. It receives each of the keys and values,
and its return value is used instead of the original value.
If it returns what it received, then the structure is not modified.
If it returns undefined then the member is deleted.
Example:
// Parse the text. Values that look like ISO date strings will
// be converted to Date objects.
myData = JSON.parse(text, function (key, value) {
var a;
if (typeof value === 'string') {
a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
if (a) {
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+a[5], +a[6]));
}
}
return value;
});
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
var d;
if (typeof value === 'string' &&
value.slice(0, 5) === 'Date(' &&
value.slice(-1) === ')') {
d = new Date(value.slice(5, -1));
if (d) {
return d;
}
}
return value;
});
This is a reference implementation. You are free to copy, modify, or
redistribute.
*/
/*jslint evil: true, regexp: true */
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
lastIndex, length, parse, prototype, push, replace, slice, stringify,
test, toJSON, toString, valueOf
*/
// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.
if (typeof JSON !== 'object') {
JSON = <any>{};
}
(function () {
'use strict';
function f(n: any) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
if (typeof Date.prototype.toJSON !== 'function') {
Date.prototype.toJSON = function () {
return isFinite(this.valueOf())
? this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z'
: null;
};
(<any>String.prototype).toJSON =
(<any>Number.prototype).toJSON =
(<any>Boolean.prototype).toJSON = function () {
return this.valueOf();
};
}
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
gap: any,
indent: any,
meta = <any>{ // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
},
rep: any;
function quote(string: string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
escapable.lastIndex = 0;
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
var c = meta[a];
return typeof c === 'string'
? c
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' : '"' + string + '"';
}
function str(key: any, holder: any) {
// Produce a string from holder[key].
var i: any, // The loop counter.
k: any, // The member key.
v: any, // The member value.
length: number,
mind = gap,
partial: any,
value = holder[key];
// If the value has a toJSON method, call it to obtain a replacement value.
if (value && typeof value === 'object' &&
typeof value.toJSON === 'function') {
value = value.toJSON(key);
}
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
if (typeof rep === 'function') {
value = rep.call(holder, key, value);
}
// What happens next depends on the value's type.
switch (typeof value) {
case 'string':
return quote(value);
case 'number':
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : 'null';
case 'boolean':
case 'null':
// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.
return String(value);
// If the type is 'object', we might be dealing with an object or an array or
// null.
case 'object':
// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.
if (!value) {
return 'null';
}
// Make an array to hold the partial results of stringifying this object value.
gap += indent;
partial = [];
// Is the value an array?
if (Object.prototype.toString.apply(value) === '[object Array]') {
// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || 'null';
}
// Join all of the elements together, separated with commas, and wrap them in
// brackets.
v = partial.length === 0
? '[]'
: gap
? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
: '[' + partial.join(',') + ']';
gap = mind;
return v;
}
// If the replacer is an array, use it to select the members to be stringified.
if (rep && typeof rep === 'object') {
length = rep.length;
for (i = 0; i < length; i += 1) {
if (typeof rep[i] === 'string') {
k = rep[i];
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
} else {
// Otherwise, iterate through all of the keys in the object.
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
}
// Join all of the member texts together, separated with commas,
// and wrap them in braces.
v = partial.length === 0
? '{}'
: gap
? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
: '{' + partial.join(',') + '}';
gap = mind;
return v;
}
}
// If the JSON object does not yet have a stringify method, give it one.
if (typeof JSON.stringify !== 'function') {
JSON.stringify = <any>function (value: any, replacer: any, space: any) {
// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.
var i: any;
gap = '';
indent = '';
// If the space parameter is a number, make an indent string containing that
// many spaces.
if (typeof space === 'number') {
for (i = 0; i < space; i += 1) {
indent += ' ';
}
// If the space parameter is a string, it will be used as the indent string.
} else if (typeof space === 'string') {
indent = space;
}
// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.
rep = replacer;
if (replacer && typeof replacer !== 'function' &&
(typeof replacer !== 'object' ||
typeof replacer.length !== 'number')) {
throw new Error('JSON.stringify');
}
// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.
return str('', {'': value});
};
}
// If the JSON object does not yet have a parse method, give it one.
if (typeof JSON.parse !== 'function') {
JSON.parse = function (text, reviver) {
// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.
var j: any;
function walk(holder: any, key: any) {
// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.
var k: any, v: any, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}
// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
text = String(text);
cx.lastIndex = 0;
if (cx.test(text)) {
text = text.replace(cx, function (a) {
return '\\u' +
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.
// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
if (/^[\],:{}\s]*$/
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
j = eval('(' + text + ')');
// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.
return typeof reviver === 'function'
? walk({'': j}, '')
: j;
}
// If the text is not JSON parseable, then a SyntaxError is thrown.
throw new SyntaxError('JSON.parse');
};
}
}());
+404 -174
View File
File diff suppressed because it is too large Load Diff
+53 -18
View File
@@ -534,18 +534,47 @@ module Harness {
export var defaultLibFileName = 'lib.d.ts';
export var defaultLibSourceFile = ts.createSourceFile(defaultLibFileName, IO.readFile(libFolder + 'lib.core.d.ts'), /*languageVersion*/ ts.ScriptTarget.ES5, /*version:*/ "0");
// Cache these between executions so we don't have to re-parse them for every test
export var fourslashFilename = 'fourslash.ts';
export var fourslashSourceFile: ts.SourceFile;
export function getCanonicalFileName(fileName: string): string {
return sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
}
export function createCompilerHost(filemap: { [filename: string]: ts.SourceFile; }, writeFile: (fn: string, contents: string, writeByteOrderMark:boolean) => void): ts.CompilerHost {
export function createCompilerHost(inputFiles: { unitName: string; content: string; }[],
writeFile: (fn: string, contents: string, writeByteOrderMark: boolean) => void,
scriptTarget: ts.ScriptTarget,
useCaseSensitiveFileNames: boolean): ts.CompilerHost {
// Local get canonical file name function, that depends on passed in parameter for useCaseSensitiveFileNames
function getCanonicalFileName(fileName: string): string {
return useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
}
var filemap: { [filename: string]: ts.SourceFile; } = {};
// Register input files
function register(file: { unitName: string; content: string; }) {
if (file.content !== undefined) {
var filename = Path.switchToForwardSlashes(file.unitName);
filemap[getCanonicalFileName(filename)] = ts.createSourceFile(filename, file.content, scriptTarget, /*version:*/ "0");
}
};
inputFiles.forEach(register);
return {
getCurrentDirectory: sys.getCurrentDirectory,
getCancellationToken: (): any => undefined,
getSourceFile: (fn, languageVersion) => {
if (Object.prototype.hasOwnProperty.call(filemap, getCanonicalFileName(fn))) {
return filemap[getCanonicalFileName(fn)];
} else {
}
else if (fn === fourslashFilename) {
var tsFn = 'tests/cases/fourslash/' + fourslashFilename;
fourslashSourceFile = fourslashSourceFile || ts.createSourceFile(tsFn, Harness.IO.readFile(tsFn), scriptTarget, /*version*/ "0", /*isOpen*/ false);
return fourslashSourceFile;
}
else {
var lib = defaultLibFileName;
if (fn === defaultLibFileName) {
return defaultLibSourceFile;
@@ -557,7 +586,7 @@ module Harness {
getDefaultLibFilename: () => defaultLibFileName,
writeFile: writeFile,
getCanonicalFileName: getCanonicalFileName,
useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames,
useCaseSensitiveFileNames: () => useCaseSensitiveFileNames,
getNewLine: ()=> sys.newLine
};
}
@@ -614,7 +643,7 @@ module Harness {
}
public compileFiles(inputFiles: { unitName: string; content: string }[],
otherFiles: { unitName: string; content?: string }[],
otherFiles: { unitName: string; content: string }[],
onComplete: (result: CompilerResult, checker: ts.TypeChecker) => void,
settingsCallback?: (settings: ts.CompilerOptions) => void,
options?: ts.CompilerOptions) {
@@ -628,9 +657,10 @@ module Harness {
settingsCallback(null);
}
var useCaseSensitiveFileNames = sys.useCaseSensitiveFileNames;
this.settings.forEach(setting => {
switch (setting.flag.toLowerCase()) {
// "filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outDir", "noimplicitany", "noresolve"
// "filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outdir", "noimplicitany", "noresolve"
case "module":
case "modulegentarget":
if (typeof setting.value === 'string') {
@@ -706,10 +736,13 @@ module Harness {
options.removeComments = setting.value === 'false';
break;
case 'usecasesensitivefilenames':
useCaseSensitiveFileNames = setting.value === 'true';
break;
case 'mapsourcefiles':
case 'maproot':
case 'generatedeclarationfiles':
case 'usecasesensitivefileresolution':
case 'gatherDiagnostics':
case 'codepage':
case 'createFileLog':
@@ -748,7 +781,10 @@ module Harness {
var fileOutputs: GeneratedFile[] = [];
var programFiles = inputFiles.map(file => file.unitName);
var program = ts.createProgram(programFiles, options, createCompilerHost(filemap, (fn, contents, writeByteOrderMark) => fileOutputs.push({ fileName: fn, code: contents, writeByteOrderMark: writeByteOrderMark })));
var program = ts.createProgram(programFiles, options, createCompilerHost(inputFiles.concat(otherFiles),
(fn, contents, writeByteOrderMark) => fileOutputs.push({ fileName: fn, code: contents, writeByteOrderMark: writeByteOrderMark }),
options.target,
useCaseSensitiveFileNames));
var hadParseErrors = program.getDiagnostics().length > 0;
@@ -818,7 +854,7 @@ module Harness {
var sourceFileName: string;
if (ts.isExternalModule(sourceFile) || !options.out) {
if (options.outDir) {
var sourceFilePath = ts.getNormalizedPathFromPathCompoments(ts.getNormalizedPathComponents(sourceFile.filename, result.currentDirectoryForProgram));
var sourceFilePath = ts.getNormalizedPathFromPathComponents(ts.getNormalizedPathComponents(sourceFile.filename, result.currentDirectoryForProgram));
sourceFilePath = sourceFilePath.replace(result.program.getCommonSourceDirectory(), "");
sourceFileName = ts.combinePaths(options.outDir, sourceFilePath);
}
@@ -831,7 +867,7 @@ module Harness {
sourceFileName = options.out;
}
return ts.getModuleNameFromFilename(sourceFileName) + ".d.ts";
return ts.removeFileExtension(sourceFileName) + ".d.ts";
}
});
@@ -873,9 +909,7 @@ module Harness {
return errorOutput;
}
export function getErrorBaseline(inputFiles: { unitName: string; content: string }[],
diagnostics: HarnessDiagnostic[]
) {
export function getErrorBaseline(inputFiles: { unitName: string; content: string }[], diagnostics: HarnessDiagnostic[]) {
var outputLines: string[] = [];
// Count up all the errors we find so we don't miss any
@@ -886,13 +920,13 @@ module Harness {
.split('\n')
.map(s => s.length > 0 && s.charAt(s.length - 1) === '\r' ? s.substr(0, s.length - 1) : s)
.filter(s => s.length > 0)
.map(s => '!!! ' + s);
.map(s => '!!! ' + error.category + " TS" + error.code + ": " + s);
errLines.forEach(e => outputLines.push(e));
totalErrorsReported++;
}
// Report glovbal errors:
// Report global errors
var globalErrors = diagnostics.filter(err => !err.filename);
globalErrors.forEach(err => outputErrorText(err));
@@ -962,7 +996,8 @@ module Harness {
// Verify we didn't miss any errors in total
assert.equal(totalErrorsReported, diagnostics.length, 'total number of errors');
return outputLines.join('\r\n');
return minimalDiagnosticsToString(diagnostics) +
sys.newLine + sys.newLine + outputLines.join('\r\n');
}
/* TODO: Delete?
@@ -983,7 +1018,7 @@ module Harness {
export function recreate(options?: { useMinimalDefaultLib: boolean; noImplicitAny: boolean; }) {
}
/** The harness' compiler instance used when tests are actually run. Reseting or changing settings of this compiler instance must be done within a testcase (i.e., describe/it) */
/** The harness' compiler instance used when tests are actually run. Reseting or changing settings of this compiler instance must be done within a test case (i.e., describe/it) */
var harnessCompiler: HarnessCompiler;
/** Returns the singleton harness compiler instance for generating and running tests.
@@ -1085,7 +1120,7 @@ module Harness {
}
export module TestCaseParser {
/** all the necesarry information to set the right compiler settings */
/** all the necessary information to set the right compiler settings */
export interface CompilerSetting {
flag: string;
value: string;
@@ -1104,7 +1139,7 @@ module Harness {
var optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*(\S*)/gm; // multiple matches on multiple lines
// List of allowed metadata names
var fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outDir", "noimplicitany", "noresolve", "newline", "newlines", "emitbom", "errortruncation"];
var fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outdir", "noimplicitany", "noresolve", "newline", "newlines", "emitbom", "errortruncation", "usecasesensitivefilenames"];
function extractCompilerSettings(content: string): CompilerSetting[] {
+18 -1
View File
@@ -134,6 +134,7 @@ module Harness.LanguageService {
private ls: ts.LanguageServiceShim = null;
private fileNameToScript: ts.Map<ScriptInfo> = {};
private settings: ts.CompilationSettings = {};
constructor(private cancellationToken: ts.CancellationToken = CancellationToken.None) {
}
@@ -199,13 +200,21 @@ module Harness.LanguageService {
/// Returns json for Tools.CompilationSettings
public getCompilationSettings(): string {
return JSON.stringify({}); // i.e. default settings
return JSON.stringify(this.settings);
}
public getCancellationToken(): ts.CancellationToken {
return this.cancellationToken;
}
public getCurrentDirectory(): string {
return "";
}
public getDefaultLibFilename(): string {
return "";
}
public getScriptFileNames(): string {
var fileNames: string[] = [];
ts.forEachKey(this.fileNameToScript, (fileName) => { fileNames.push(fileName); });
@@ -236,6 +245,14 @@ module Harness.LanguageService {
return this.ls;
}
public setCompilationSettings(settings: ts.CompilationSettings) {
for (var key in settings) {
if (settings.hasOwnProperty(key)) {
this.settings[key] = settings[key];
}
}
}
/** Return a new instance of the classifier service shim */
public getClassifier(): ts.ClassifierShim {
return new TypeScript.Services.TypeScriptServicesFactory().createClassifierShim(this);
+9 -10
View File
@@ -4,7 +4,7 @@
// 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 dictory when compiling
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
@@ -22,7 +22,7 @@ interface ProjectRunnerTestCase {
interface ProjectRunnerTestCaseResolutionInfo extends ProjectRunnerTestCase {
// Apart from actual test case the results of the resolution
resolvedInputFiles: string[]; // List of files that were asked to read by compiler
emittedFiles: string[]; // List of files that wre emitted by the compiler
emittedFiles: string[]; // List of files that were emitted by the compiler
}
interface BatchCompileProjectTestCaseEmittedFile extends Harness.Compiler.GeneratedFile {
@@ -69,7 +69,7 @@ class ProjectRunner extends RunnerBase {
testCase = <ProjectRunnerTestCase>JSON.parse(testFileText);
}
catch (e) {
assert(false, "Testcase: " + testCaseFileName + " doesnt not contain valid json format: " + e.message);
assert(false, "Testcase: " + testCaseFileName + " does not contain valid json format: " + e.message);
}
var testCaseJustName = testCaseFileName.replace(/^.*[\\\/]/, '').replace(/\.json/, "");
@@ -87,7 +87,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 compairing 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) {
@@ -226,9 +226,10 @@ class ProjectRunner extends RunnerBase {
? filename
: ts.normalizeSlashes(testCase.projectRoot) + "/" + ts.normalizeSlashes(filename);
var diskRelativeName = ts.getRelativePathToDirectoryOrUrl(testCase.projectRoot, diskFileName, getCurrentDirectory(), false);
var diskRelativeName = ts.getRelativePathToDirectoryOrUrl(testCase.projectRoot, diskFileName,
getCurrentDirectory(), Harness.Compiler.getCanonicalFileName, /*isAbsolutePathAnUrl*/ false);
if (ts.isRootedDiskPath(diskRelativeName) || diskRelativeName.substr(0, 3) === "../") {
// If the generated output file recides 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++ +
@@ -299,13 +300,11 @@ class ProjectRunner extends RunnerBase {
return { unitName: sourceFile.filename, content: sourceFile.text };
});
var diagnostics = ts.map(compilerResult.errors, error => Harness.Compiler.getMinimalDiagnostic(error));
var errors = Harness.Compiler.minimalDiagnosticsToString(diagnostics);
errors += sys.newLine + sys.newLine + Harness.Compiler.getErrorBaseline(inputFiles, diagnostics);
return errors;
return Harness.Compiler.getErrorBaseline(inputFiles, diagnostics);
}
describe('Compiling project for ' + testCase.scenario +': testcase ' + testCaseFileName, () => {
describe('Compiling project for ' + testCase.scenario + ': testcase ' + testCaseFileName, () => {
function verifyCompilerResults(compilerResult: BatchCompileProjectTestCaseResult) {
function getCompilerResolutionInfo() {
var resolutionInfo: ProjectRunnerTestCaseResolutionInfo = {
+1 -3
View File
@@ -164,9 +164,7 @@ module RWC {
return null;
}
return Harness.Compiler.minimalDiagnosticsToString(compilerResult.errors) +
sys.newLine + sys.newLine +
Harness.Compiler.getErrorBaseline(inputFiles.concat(otherFiles), compilerResult.errors);
return Harness.Compiler.getErrorBaseline(inputFiles.concat(otherFiles), compilerResult.errors);
}, false, baselineOpts);
});
+4 -4
View File
@@ -67,8 +67,8 @@ class TypeWriterWalker {
case ts.SyntaxKind.ContinueStatement:
case ts.SyntaxKind.BreakStatement:
return (<ts.BreakOrContinueStatement>parent).label === identifier;
case ts.SyntaxKind.LabelledStatement:
return (<ts.LabelledStatement>parent).label === identifier;
case ts.SyntaxKind.LabeledStatement:
return (<ts.LabeledStatement>parent).label === identifier;
}
return false;
}
@@ -76,7 +76,7 @@ class TypeWriterWalker {
private log(node: ts.Node, type: ts.Type): void {
var actualPos = ts.skipTrivia(this.currentSourceFile.text, node.pos);
var lineAndCharacter = this.currentSourceFile.getLineAndCharacterFromPosition(actualPos);
var sourceText = ts.getSourceTextOfNodeFromSourceText(this.currentSourceFile.text, node);
var sourceText = ts.getTextOfNodeFromSourceText(this.currentSourceFile.text, node);
// If we got an unknown type, we temporarily want to fall back to just pretending the name
// (source text) of the node is the type. This is to align with the old typeWriter to make
@@ -86,7 +86,7 @@ class TypeWriterWalker {
column: lineAndCharacter.character,
syntaxKind: ts.SyntaxKind[node.kind],
sourceText: sourceText,
type: this.checker.typeToString(type, node.parent, ts.TypeFormatFlags.NoTruncation)
type: this.checker.typeToString(type, node.parent, ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.WriteOwnNameForAnyLike)
});
}
+1 -1
View File
@@ -7,7 +7,7 @@ class UnitTestRunner extends RunnerBase {
}
public initializeTests() {
this.tests = this.enumerateFiles('tests/cases/unittests/services');
this.tests = this.enumerateFiles('tests/cases/unittests/services', /\.ts/i);
var outfile = new Harness.Compiler.WriterAggregator()
var outerr = new Harness.Compiler.WriterAggregator();
+16 -16
View File
@@ -63,14 +63,14 @@ interface Int8Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Int8Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -121,14 +121,14 @@ interface Uint8Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Uint8Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -179,14 +179,14 @@ interface Int16Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Int16Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -237,14 +237,14 @@ interface Uint16Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Uint16Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -295,14 +295,14 @@ interface Int32Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Int32Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -353,14 +353,14 @@ interface Uint32Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Uint32Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -411,14 +411,14 @@ interface Float32Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Float32Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
@@ -469,14 +469,14 @@ interface Float64Array extends ArrayBufferView {
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: Float64Array, offset?: number): void;
/**
* Sets a value or an array of values.
* @param A typed or untyped array of values to set.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: number[], offset?: number): void;
-73
View File
@@ -1,73 +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='references.ts' />
module TypeScript.Services {
export class BraceMatcher {
// Given a script name and position in the script, return a pair of text range if the
// position corresponds to a "brace matchin" characters (e.g. "{" or "(", etc.)
// If the position is not on any range, return an empty set.
public static getMatchSpans(syntaxTree: TypeScript.SyntaxTree, position: number): TypeScript.TextSpan[] {
var result: TypeScript.TextSpan[] = [];
var token = findToken(syntaxTree.sourceUnit(), position);
if (start(token) === position) {
var matchKind = BraceMatcher.getMatchingTokenKind(token);
if (matchKind !== null) {
var parentElement = token.parent;
for (var i = 0, n = childCount(parentElement); i < n; i++) {
var current = childAt(parentElement, i);
if (current !== null && fullWidth(current) > 0) {
if (current.kind() === matchKind) {
var range1 = new TypeScript.TextSpan(start(token), width(token));
var range2 = new TypeScript.TextSpan(start(current), width(current));
if (range1.start() < range2.start()) {
result.push(range1, range2);
}
else {
result.push(range2, range1);
}
break;
}
}
}
}
}
return result;
}
private static getMatchingTokenKind(token: TypeScript.ISyntaxToken): TypeScript.SyntaxKind {
switch (token.kind()) {
case TypeScript.SyntaxKind.OpenBraceToken: return TypeScript.SyntaxKind.CloseBraceToken
case TypeScript.SyntaxKind.OpenParenToken: return TypeScript.SyntaxKind.CloseParenToken;
case TypeScript.SyntaxKind.OpenBracketToken: return TypeScript.SyntaxKind.CloseBracketToken;
case TypeScript.SyntaxKind.LessThanToken: return TypeScript.SyntaxKind.GreaterThanToken;
case TypeScript.SyntaxKind.CloseBraceToken: return TypeScript.SyntaxKind.OpenBraceToken
case TypeScript.SyntaxKind.CloseParenToken: return TypeScript.SyntaxKind.OpenParenToken;
case TypeScript.SyntaxKind.CloseBracketToken: return TypeScript.SyntaxKind.OpenBracketToken;
case TypeScript.SyntaxKind.GreaterThanToken: return TypeScript.SyntaxKind.LessThanToken;
}
return null;
}
}
}
-3
View File
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
///<reference path='references.ts' />
module TypeScript.Services.Breakpoints {
function createBreakpointSpanInfo(parentElement: TypeScript.ISyntaxElement, ...childElements: TypeScript.ISyntaxElement[]): TextSpan {
if (!parentElement) {
@@ -798,7 +796,6 @@ module TypeScript.Services.Breakpoints {
var container = Syntax.containingNode(varDeclarationNode);
var varDeclarationSyntax = <TypeScript.VariableDeclarationSyntax>varDeclarationNode;
var varDeclarators = varDeclarationSyntax.variableDeclarators;
var varDeclaratorsCount = childCount(varDeclarators); // varDeclarators has to be non null because its checked in canHaveBreakpoint
if (container && container.kind() == TypeScript.SyntaxKind.VariableStatement) {
return this.breakpointSpanOfVariableStatement(container);
+5
View File
@@ -42,6 +42,10 @@ module TypeScript {
walker.walk(preAst.typeArguments);
}
function walkTupleTypeChildren(preAst: TupleTypeSyntax, walker: AstWalker): void {
walker.walk(preAst.types);
}
function walkTypeOfExpressionChildren(preAst: TypeOfExpressionSyntax, walker: AstWalker): void {
walker.walk(preAst.expression);
}
@@ -561,6 +565,7 @@ module TypeScript {
childrenWalkers[SyntaxKind.TriviaList] = null;
childrenWalkers[SyntaxKind.TrueKeyword] = null;
childrenWalkers[SyntaxKind.TryStatement] = walkTryStatementChildren;
childrenWalkers[SyntaxKind.TupleType] = walkTupleTypeChildren;
childrenWalkers[SyntaxKind.TypeAnnotation] = walkTypeAnnotationChildren;
childrenWalkers[SyntaxKind.TypeArgumentList] = walkTypeArgumentListChildren;
childrenWalkers[SyntaxKind.TypeOfExpression] = walkTypeOfExpressionChildren;
-1
View File
@@ -12,7 +12,6 @@
/////<reference path='base64.ts' />
/////<reference path='sourceMapping.ts' />
/////<reference path='emitter.ts' />
/////<reference path='types.ts' />
/////<reference path='pathUtils.ts' />
/////<reference path='referenceResolution.ts' />
/////<reference path='precompile.ts' />
-102
View File
@@ -1,102 +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='references.ts' />
module TypeScript {
export class MemberName {
public prefix: string = "";
public suffix: string = "";
public isString() { return false; }
public isArray() { return false; }
public isMarker() { return !this.isString() && !this.isArray(); }
public toString(): string {
return MemberName.memberNameToString(this);
}
static memberNameToString(memberName: MemberName, markerInfo?: number[], markerBaseLength: number = 0): string {
var result = memberName.prefix;
if (memberName.isString()) {
result += (<MemberNameString>memberName).text;
}
else if (memberName.isArray()) {
var ar = <MemberNameArray>memberName;
for (var index = 0; index < ar.entries.length; index++) {
if (ar.entries[index].isMarker()) {
if (markerInfo) {
markerInfo.push(markerBaseLength + result.length);
}
continue;
}
result += MemberName.memberNameToString(ar.entries[index], markerInfo, markerBaseLength + result.length);
result += ar.delim;
}
}
result += memberName.suffix;
return result;
}
static create(text: string): MemberName;
static create(entry: MemberName, prefix: string, suffix: string): MemberName;
static create(arg1: any, arg2?: any, arg3?: any): MemberName {
if (typeof arg1 === "string") {
return new MemberNameString(arg1);
}
else {
var result = new MemberNameArray();
if (arg2)
result.prefix = arg2;
if (arg3)
result.suffix = arg3;
result.entries.push(arg1);
return result;
}
}
}
export class MemberNameString extends MemberName {
constructor(public text: string) {
super();
}
public isString() { return true; }
}
export class MemberNameArray extends MemberName {
public delim: string = "";
public entries: MemberName[] = [];
public isArray() { return true; }
public add(entry: MemberName) {
this.entries.push(entry);
}
public addAll(entries: MemberName[]) {
for (var i = 0 ; i < entries.length; i++) {
this.entries.push(entries[i]);
}
}
constructor() {
super();
}
}
}
-2
View File
@@ -1,8 +1,6 @@
///<reference path='references.ts' />
module TypeScript {
export var LocalizedDiagnosticMessages: ts.Map<any> = null;
export class Location {
private _fileName: string;
private _lineMap: LineMap;
-1
View File
@@ -36,5 +36,4 @@
///<reference path='indentationNodeContextPool.ts' />
///<reference path='indentationTrackingWalker.ts' />
///<reference path='multipleTokenIndenter.ts' />
///<reference path='singleTokenIndenter.ts' />
///<reference path='formatter.ts' />
+5 -3
View File
@@ -112,9 +112,11 @@ module TypeScript.Services.Formatting {
//
// TODO: Change the ILanguageService interface to return TextEditInfo (with start, and length) instead of TextEdit (with minChar and limChar)
formattingEdits.forEach((item) => {
var edit = new ts.TextChange(new TextSpan(item.position, item.length), item.replaceWith);
result.push(edit);
formattingEdits.forEach(item => {
result.push({
span: new TextSpan(item.position, item.length),
newText: item.replaceWith
});
});
return result;
@@ -1,46 +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='formatting.ts' />
module TypeScript.Services.Formatting {
export class SingleTokenIndenter extends IndentationTrackingWalker {
private indentationAmount: number = null;
private indentationPosition: number;
constructor(indentationPosition: number, sourceUnit: SourceUnitSyntax, snapshot: ITextSnapshot, indentFirstToken: boolean, options: FormattingOptions) {
super(new TextSpan(indentationPosition, 1), sourceUnit, snapshot, indentFirstToken, options);
this.indentationPosition = indentationPosition;
}
public static getIndentationAmount(position: number, sourceUnit: SourceUnitSyntax, snapshot: ITextSnapshot, options: FormattingOptions): number {
var walker = new SingleTokenIndenter(position, sourceUnit, snapshot, true, options);
visitNodeOrToken(walker, sourceUnit);
return walker.indentationAmount;
}
public indentToken(token: ISyntaxToken, indentationAmount: number, commentIndentationAmount: number): void {
// Compute an indentation string for this token
if (token.fullWidth() === 0 || (this.indentationPosition - this.position() < token.leadingTriviaWidth())) {
// The position is in the leading trivia, use comment indentation
this.indentationAmount = commentIndentationAmount;
}
else {
this.indentationAmount = indentationAmount;
}
}
}
}
+396
View File
@@ -0,0 +1,396 @@
///<reference path='..\services.ts' />
module ts.formatting {
export module SmartIndenter {
export function getIndentation(position: number, sourceFile: SourceFile, options: TypeScript.FormattingOptions): number {
if (position > sourceFile.text.length) {
return 0; // past EOF
}
var precedingToken = findPrecedingToken(position, sourceFile);
if (!precedingToken) {
return 0;
}
// no indentation in string \regex literals
if ((precedingToken.kind === SyntaxKind.StringLiteral || precedingToken.kind === SyntaxKind.RegularExpressionLiteral) &&
precedingToken.getStart(sourceFile) <= position &&
precedingToken.end > position) {
return 0;
}
var lineAtPosition = sourceFile.getLineAndCharacterFromPosition(position).line;
if (precedingToken.kind === SyntaxKind.CommaToken && precedingToken.parent.kind !== SyntaxKind.BinaryExpression) {
// previous token is comma that separates items in list - find the previous item and try to derive indentation from it
var actualIndentation = getActualIndentationForListItemBeforeComma(precedingToken, sourceFile, options);
if (actualIndentation !== -1) {
return actualIndentation;
}
}
// try to find node that can contribute to indentation and includes 'position' starting from 'precedingToken'
// if such node is found - compute initial indentation for 'position' inside this node
var previous: Node;
var current = precedingToken;
var currentStart: LineAndCharacter;
var indentationDelta: number;
while (current) {
if (positionBelongsToNode(current, position, sourceFile) && nodeContentIsIndented(current, previous)) {
currentStart = getStartLineAndCharacterForNode(current, sourceFile);
if (nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile)) {
indentationDelta = 0;
}
else {
indentationDelta = lineAtPosition !== currentStart.line ? options.indentSpaces : 0;
}
break;
}
// check if current node is a list item - if yes, take indentation from it
var actualIndentation = getActualIndentationForListItem(current, sourceFile, options);
if (actualIndentation !== -1) {
return actualIndentation;
}
previous = current;
current = current.parent;
}
if (!current) {
// no parent was found - return 0 to be indented on the level of SourceFile
return 0;
}
var parent: Node = current.parent;
var parentStart: LineAndCharacter;
// walk upwards and collect indentations for pairs of parent-child nodes
// indentation is not added if parent and child nodes start on the same line or if parent is IfStatement and child starts on the same line with 'else clause'
while (parent) {
// check if current node is a list item - if yes, take indentation from it
var actualIndentation = getActualIndentationForListItem(current, sourceFile, options);
if (actualIndentation !== -1) {
return actualIndentation + indentationDelta;
}
parentStart = sourceFile.getLineAndCharacterFromPosition(parent.getStart(sourceFile));
var parentAndChildShareLine =
parentStart.line === currentStart.line ||
childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile);
// try to fetch actual indentation for current node from source text
var actualIndentation = getActualIndentationForNode(current, parent, currentStart, parentAndChildShareLine, sourceFile, options);
if (actualIndentation !== -1) {
return actualIndentation + indentationDelta;
}
// increase indentation if parent node wants its content to be indented and parent and child nodes don't start on the same line
if (nodeContentIsIndented(parent, current) && !parentAndChildShareLine) {
indentationDelta += options.indentSpaces;
}
current = parent;
currentStart = parentStart;
parent = current.parent;
}
return indentationDelta;
}
/*
* Function returns -1 if indentation cannot be determined
*/
function getActualIndentationForListItemBeforeComma(commaToken: Node, sourceFile: SourceFile, options: TypeScript.FormattingOptions): number {
// previous token is comma that separates items in list - find the previous item and try to derive indentation from it
var commaItemInfo = findListItemInfo(commaToken);
Debug.assert(commaItemInfo.listItemIndex > 0);
// The item we're interested in is right before the comma
return deriveActualIndentationFromList(commaItemInfo.list.getChildren(), commaItemInfo.listItemIndex - 1, sourceFile, options);
}
/*
* Function returns -1 if actual indentation for node should not be used (i.e because node is nested expression)
*/
function getActualIndentationForNode(current: Node,
parent: Node,
currentLineAndChar: LineAndCharacter,
parentAndChildShareLine: boolean,
sourceFile: SourceFile,
options: TypeScript.FormattingOptions): number {
// actual indentation is used for statements\declarations if one of cases below is true:
// - parent is SourceFile - by default immediate children of SourceFile are not indented except when user indents them manually
// - parent and child are not on the same line
var useActualIndentation =
(isDeclaration(current) || isStatement(current)) &&
(parent.kind === SyntaxKind.SourceFile || !parentAndChildShareLine);
if (!useActualIndentation) {
return -1;
}
return findColumnForFirstNonWhitespaceCharacterInLine(currentLineAndChar, sourceFile, options);
}
function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken: Node, current: Node, lineAtPosition: number, sourceFile: SourceFile): boolean {
var nextToken = findNextToken(precedingToken, current);
if (!nextToken) {
return false;
}
if (nextToken.kind === SyntaxKind.OpenBraceToken) {
// open braces are always indented at the parent level
return true;
}
else if (nextToken.kind === SyntaxKind.CloseBraceToken) {
// close braces are indented at the parent level if they are located on the same line with cursor
// this means that if new line will be added at $ position, this case will be indented
// class A {
// $
// }
/// and this one - not
// class A {
// $}
var nextTokenStartLine = getStartLineAndCharacterForNode(nextToken, sourceFile).line;
return lineAtPosition === nextTokenStartLine;
}
return false;
}
function getStartLineAndCharacterForNode(n: Node, sourceFile: SourceFile): LineAndCharacter {
return sourceFile.getLineAndCharacterFromPosition(n.getStart(sourceFile));
}
function positionBelongsToNode(candidate: Node, position: number, sourceFile: SourceFile): boolean {
return candidate.end > position || !isCompletedNode(candidate, sourceFile);
}
function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: Node, childStartLine: number, sourceFile: SourceFile): boolean {
if (parent.kind === SyntaxKind.IfStatement && (<IfStatement>parent).elseStatement === child) {
var elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile);
Debug.assert(elseKeyword);
var elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line;
return elseKeywordStartLine === childStartLine;
}
}
function getActualIndentationForListItem(node: Node, sourceFile: SourceFile, options: TypeScript.FormattingOptions): number {
if (node.parent) {
switch (node.parent.kind) {
case SyntaxKind.TypeReference:
if ((<TypeReferenceNode>node.parent).typeArguments) {
return getActualIndentationFromList((<TypeReferenceNode>node.parent).typeArguments);
}
break;
case SyntaxKind.ObjectLiteral:
return getActualIndentationFromList((<ObjectLiteral>node.parent).properties);
case SyntaxKind.TypeLiteral:
return getActualIndentationFromList((<TypeLiteralNode>node.parent).members);
case SyntaxKind.ArrayLiteral:
return getActualIndentationFromList((<ArrayLiteral>node.parent).elements);
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.Method:
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
if ((<SignatureDeclaration>node.parent).typeParameters && node.end < (<SignatureDeclaration>node.parent).typeParameters.end) {
return getActualIndentationFromList((<SignatureDeclaration>node.parent).typeParameters);
}
return getActualIndentationFromList((<SignatureDeclaration>node.parent).parameters);
case SyntaxKind.NewExpression:
case SyntaxKind.CallExpression:
if ((<CallExpression>node.parent).typeArguments && node.end < (<CallExpression>node.parent).typeArguments.end) {
return getActualIndentationFromList((<CallExpression>node.parent).typeArguments);
}
return getActualIndentationFromList((<CallExpression>node.parent).arguments);
}
}
return -1;
function getActualIndentationFromList(list: Node[]): number {
var index = indexOf(list, node);
return index !== -1 ? deriveActualIndentationFromList(list, index, sourceFile, options) : -1;
}
}
function deriveActualIndentationFromList(list: Node[], index: number, sourceFile: SourceFile, options: TypeScript.FormattingOptions): number {
Debug.assert(index >= 0 && index < list.length);
var node = list[index];
// walk toward the start of the list starting from current node and check if the line is the same for all items.
// if end line for item [i - 1] differs from the start line for item [i] - find column of the first non-whitespace character on the line of item [i]
var lineAndCharacter = getStartLineAndCharacterForNode(node, sourceFile);
for (var i = index - 1; i >= 0; --i) {
if (list[i].kind === SyntaxKind.CommaToken) {
continue;
}
// skip list items that ends on the same line with the current list element
var prevEndLine = sourceFile.getLineAndCharacterFromPosition(list[i].end).line;
if (prevEndLine !== lineAndCharacter.line) {
return findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options);
}
lineAndCharacter = getStartLineAndCharacterForNode(list[i], sourceFile);
}
return -1;
}
function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter: LineAndCharacter, sourceFile: SourceFile, options: TypeScript.FormattingOptions): number {
var lineStart = sourceFile.getPositionFromLineAndCharacter(lineAndCharacter.line, 1);
var column = 0;
for (var i = 0; i < lineAndCharacter.character; ++i) {
var charCode = sourceFile.text.charCodeAt(lineStart + i);
if (!isWhiteSpace(charCode)) {
return column;
}
if (charCode === CharacterCodes.tab) {
column += options.spacesPerTab;
}
else {
column++;
}
}
return column;
}
function nodeContentIsIndented(parent: Node, child: Node): boolean {
switch (parent.kind) {
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
return true;
case SyntaxKind.ModuleDeclaration:
// ModuleBlock should take care of indentation
return false;
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.Method:
case SyntaxKind.FunctionExpression:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.Constructor:
// FunctionBlock should take care of indentation
return false;
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForStatement:
return child && child.kind !== SyntaxKind.Block;
case SyntaxKind.IfStatement:
return child && child.kind !== SyntaxKind.Block;
case SyntaxKind.TryStatement:
// TryBlock\CatchBlock\FinallyBlock should take care of indentation
return false;
case SyntaxKind.ArrayLiteral:
case SyntaxKind.Block:
case SyntaxKind.FunctionBlock:
case SyntaxKind.TryBlock:
case SyntaxKind.CatchBlock:
case SyntaxKind.FinallyBlock:
case SyntaxKind.ModuleBlock:
case SyntaxKind.ObjectLiteral:
case SyntaxKind.TypeLiteral:
case SyntaxKind.SwitchStatement:
case SyntaxKind.DefaultClause:
case SyntaxKind.CaseClause:
case SyntaxKind.ParenExpression:
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.VariableStatement:
case SyntaxKind.VariableDeclaration:
return true;
default:
return false;
}
}
/*
* Checks if node ends with 'expectedLastToken'.
* If child at position 'length - 1' is 'SemicolonToken' it is skipped and 'expectedLastToken' is compared with child at position 'length - 2'.
*/
function nodeEndsWith(n: Node, expectedLastToken: SyntaxKind, sourceFile: SourceFile): boolean {
var children = n.getChildren(sourceFile);
if (children.length) {
var last = children[children.length - 1];
if (last.kind === expectedLastToken) {
return true;
}
else if (last.kind === SyntaxKind.SemicolonToken && children.length !== 1) {
return children[children.length - 2].kind === expectedLastToken;
}
}
return false;
}
/*
* This function is always called when position of the cursor is located after the node
*/
function isCompletedNode(n: Node, sourceFile: SourceFile): boolean {
switch (n.kind) {
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.ObjectLiteral:
case SyntaxKind.Block:
case SyntaxKind.CatchBlock:
case SyntaxKind.FinallyBlock:
case SyntaxKind.FunctionBlock:
case SyntaxKind.ModuleBlock:
case SyntaxKind.SwitchStatement:
return nodeEndsWith(n, SyntaxKind.CloseBraceToken, sourceFile);
case SyntaxKind.ParenExpression:
case SyntaxKind.CallSignature:
case SyntaxKind.CallExpression:
case SyntaxKind.ConstructSignature:
return nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile);
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.Method:
case SyntaxKind.ArrowFunction:
return !(<FunctionDeclaration>n).body || isCompletedNode((<FunctionDeclaration>n).body, sourceFile);
case SyntaxKind.ModuleDeclaration:
return (<ModuleDeclaration>n).body && isCompletedNode((<ModuleDeclaration>n).body, sourceFile);
case SyntaxKind.IfStatement:
if ((<IfStatement>n).elseStatement) {
return isCompletedNode((<IfStatement>n).elseStatement, sourceFile);
}
return isCompletedNode((<IfStatement>n).thenStatement, sourceFile);
case SyntaxKind.ExpressionStatement:
return isCompletedNode((<ExpressionStatement>n).expression, sourceFile);
case SyntaxKind.ArrayLiteral:
return nodeEndsWith(n, SyntaxKind.CloseBracketToken, sourceFile);
case SyntaxKind.Missing:
return false;
case SyntaxKind.CaseClause:
case SyntaxKind.DefaultClause:
// there is no such thing as terminator token for CaseClause\DefaultClause so for simplicitly always consider them non-completed
return false;
case SyntaxKind.WhileStatement:
return isCompletedNode((<WhileStatement>n).statement, sourceFile);
case SyntaxKind.DoStatement:
// rough approximation: if DoStatement has While keyword - then if node is completed is checking the presence of ')';
var hasWhileKeyword = findChildOfKind(n, SyntaxKind.WhileKeyword, sourceFile);
if(hasWhileKeyword) {
return nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile);
}
return isCompletedNode((<DoStatement>n).statement, sourceFile);
default:
return true;
}
}
}
}
@@ -1,351 +0,0 @@
///<reference path='references.ts' />
module TypeScript.Services {
export class NavigationBarItemGetter {
private hasGlobalNode = false;
private getIndent(node: ISyntaxNode): number {
var indent = this.hasGlobalNode ? 1 : 0;
var current = node.parent;
while (current != null) {
if (current.kind() == SyntaxKind.ModuleDeclaration || current.kind() === SyntaxKind.FunctionDeclaration) {
indent++;
}
current = current.parent;
}
return indent;
}
private getKindModifiers(modifiers: TypeScript.ISyntaxToken[]): string {
var result: string[] = [];
for (var i = 0, n = modifiers.length; i < n; i++) {
result.push(modifiers[i].text());
}
return result.length > 0 ? result.join(',') : ts.ScriptElementKindModifier.none;
}
public getItems(node: TypeScript.SourceUnitSyntax): ts.NavigationBarItem[] {
return this.getItemsWorker(() => this.getTopLevelNodes(node), n => this.createTopLevelItem(n));
}
private getChildNodes(nodes: IModuleElementSyntax[]): ISyntaxNode[] {
var childNodes: ISyntaxNode[] = [];
for (var i = 0, n = nodes.length; i < n; i++) {
var node = <ISyntaxNode>nodes[i];
if (node.kind() === SyntaxKind.FunctionDeclaration) {
childNodes.push(node);
}
else if (node.kind() === SyntaxKind.VariableStatement) {
var variableDeclaration = (<VariableStatementSyntax>node).variableDeclaration;
childNodes.push.apply(childNodes, variableDeclaration.variableDeclarators);
}
}
return childNodes;
}
private getTopLevelNodes(node: SourceUnitSyntax): ISyntaxNode[] {
var topLevelNodes: ISyntaxNode[] = [];
topLevelNodes.push(node);
this.addTopLevelNodes(node.moduleElements, topLevelNodes);
return topLevelNodes;
}
private addTopLevelNodes(nodes: IModuleElementSyntax[], topLevelNodes: ISyntaxNode[]): void {
for (var i = 0, n = nodes.length; i < n; i++) {
var node = nodes[i];
switch (node.kind()) {
case SyntaxKind.ClassDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.InterfaceDeclaration:
topLevelNodes.push(node);
break;
case SyntaxKind.ModuleDeclaration:
var moduleDeclaration = <ModuleDeclarationSyntax>node;
topLevelNodes.push(node);
this.addTopLevelNodes(moduleDeclaration.moduleElements, topLevelNodes);
break;
case SyntaxKind.FunctionDeclaration:
var functionDeclaration = <FunctionDeclarationSyntax>node;
if (this.isTopLevelFunctionDeclaration(functionDeclaration)) {
topLevelNodes.push(node);
this.addTopLevelNodes(functionDeclaration.block.statements, topLevelNodes);
}
break;
}
}
}
public isTopLevelFunctionDeclaration(functionDeclaration: FunctionDeclarationSyntax) {
// A function declaration is 'top level' if it contains any function declarations
// within it.
return functionDeclaration.block && ArrayUtilities.any(functionDeclaration.block.statements, s => s.kind() === SyntaxKind.FunctionDeclaration);
}
private getItemsWorker(getNodes: () => ISyntaxNode[], createItem: (n: ISyntaxNode) => ts.NavigationBarItem): ts.NavigationBarItem[] {
var items: ts.NavigationBarItem[] = [];
var keyToItem = createIntrinsicsObject<ts.NavigationBarItem>();
var nodes = getNodes();
for (var i = 0, n = nodes.length; i < n; i++) {
var child = nodes[i];
var item = createItem(child);
if (item != null) {
if (item.text.length > 0) {
var key = item.text + "-" + item.kind;
var itemWithSameName = keyToItem[key];
if (itemWithSameName) {
// We had an item with the same name. Merge these items together.
this.merge(itemWithSameName, item);
}
else {
keyToItem[key] = item;
items.push(item);
}
}
}
}
return items;
}
private merge(target: ts.NavigationBarItem, source: ts.NavigationBarItem) {
// First, add any spans in the source to the target.
target.spans.push.apply(target.spans, source.spans);
if (source.childItems) {
if (!target.childItems) {
target.childItems = [];
}
// Next, recursively merge or add any children in the source as appropriate.
outer:
for (var i = 0, n = source.childItems.length; i < n; i++) {
var sourceChild = source.childItems[i];
for (var j = 0, m = target.childItems.length; j < m; j++) {
var targetChild = target.childItems[j];
if (targetChild.text === sourceChild.text && targetChild.kind === sourceChild.kind) {
// Found a match. merge them.
this.merge(targetChild, sourceChild);
continue outer;
}
}
// Didn't find a match, just add this child to the list.
target.childItems.push(sourceChild);
}
}
}
private createChildItem(node: ISyntaxNode): ts.NavigationBarItem {
switch (node.kind()) {
case SyntaxKind.Parameter:
var parameter = <ParameterSyntax>node;
if (parameter.modifiers.length === 0) {
return null;
}
return new ts.NavigationBarItem(parameter.identifier.text(), ts.ScriptElementKind.memberVariableElement, this.getKindModifiers(parameter.modifiers), [TextSpan.fromBounds(start(node), end(node))]);
case SyntaxKind.MemberFunctionDeclaration:
var memberFunction = <MemberFunctionDeclarationSyntax>node;
return new ts.NavigationBarItem(memberFunction.propertyName.text(), ts.ScriptElementKind.memberFunctionElement, this.getKindModifiers(memberFunction.modifiers), [TextSpan.fromBounds(start(node), end(node))]);
case SyntaxKind.GetAccessor:
var getAccessor = <GetAccessorSyntax>node;
return new ts.NavigationBarItem(getAccessor.propertyName.text(), ts.ScriptElementKind.memberGetAccessorElement, this.getKindModifiers(getAccessor.modifiers), [TextSpan.fromBounds(start(node), end(node))]);
case SyntaxKind.SetAccessor:
var setAccessor = <SetAccessorSyntax>node;
return new ts.NavigationBarItem(setAccessor.propertyName.text(), ts.ScriptElementKind.memberSetAccessorElement, this.getKindModifiers(setAccessor.modifiers), [TextSpan.fromBounds(start(node), end(node))]);
case SyntaxKind.IndexSignature:
var indexSignature = <IndexSignatureSyntax>node;
return new ts.NavigationBarItem("[]", ts.ScriptElementKind.indexSignatureElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]);
case SyntaxKind.EnumElement:
var enumElement = <EnumElementSyntax>node;
return new ts.NavigationBarItem(enumElement.propertyName.text(), ts.ScriptElementKind.memberVariableElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]);
case SyntaxKind.CallSignature:
var callSignature = <CallSignatureSyntax>node;
return new ts.NavigationBarItem("()", ts.ScriptElementKind.callSignatureElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]);
case SyntaxKind.ConstructSignature:
var constructSignature = <ConstructSignatureSyntax>node;
return new ts.NavigationBarItem("new()", ts.ScriptElementKind.constructSignatureElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]);
case SyntaxKind.MethodSignature:
var methodSignature = <MethodSignatureSyntax>node;
return new ts.NavigationBarItem(methodSignature.propertyName.text(), ts.ScriptElementKind.memberFunctionElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]);
case SyntaxKind.PropertySignature:
var propertySignature = <PropertySignatureSyntax>node;
return new ts.NavigationBarItem(propertySignature.propertyName.text(), ts.ScriptElementKind.memberVariableElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]);
case SyntaxKind.FunctionDeclaration:
var functionDeclaration = <FunctionDeclarationSyntax>node;
if (!this.isTopLevelFunctionDeclaration(functionDeclaration)) {
return new ts.NavigationBarItem(functionDeclaration.identifier.text(), ts.ScriptElementKind.functionElement, this.getKindModifiers(functionDeclaration.modifiers), [TextSpan.fromBounds(start(node), end(node))]);
}
break;
case SyntaxKind.MemberVariableDeclaration:
var memberVariableDeclaration = <MemberVariableDeclarationSyntax>node;
return new ts.NavigationBarItem(memberVariableDeclaration.variableDeclarator.propertyName.text(), ts.ScriptElementKind.memberVariableElement, this.getKindModifiers(memberVariableDeclaration.modifiers), [TextSpan.fromBounds(start(memberVariableDeclaration.variableDeclarator), end(memberVariableDeclaration.variableDeclarator))]);
case SyntaxKind.VariableDeclarator:
var variableDeclarator = <VariableDeclaratorSyntax>node;
return new ts.NavigationBarItem(variableDeclarator.propertyName.text(), ts.ScriptElementKind.variableElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(variableDeclarator), end(variableDeclarator))]);
case SyntaxKind.ConstructorDeclaration:
var constructorDeclaration = <ConstructorDeclarationSyntax>node;
return new ts.NavigationBarItem("constructor", ts.ScriptElementKind.constructorImplementationElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]);
}
return null;
}
private createTopLevelItem(node: ISyntaxNode): ts.NavigationBarItem {
switch (node.kind()) {
case SyntaxKind.SourceUnit:
return this.createSourceUnitItem(<SourceUnitSyntax>node);
case SyntaxKind.ClassDeclaration:
return this.createClassItem(<ClassDeclarationSyntax>node);
case SyntaxKind.EnumDeclaration:
return this.createEnumItem(<EnumDeclarationSyntax>node);
case SyntaxKind.InterfaceDeclaration:
return this.createIterfaceItem(<InterfaceDeclarationSyntax>node);
case SyntaxKind.ModuleDeclaration:
return this.createModuleItem(<ModuleDeclarationSyntax>node);
case SyntaxKind.FunctionDeclaration:
return this.createFunctionItem(<FunctionDeclarationSyntax>node);
}
return null;
}
private getModuleNames(node: TypeScript.ModuleDeclarationSyntax): string[] {
var result: string[] = [];
if (node.stringLiteral) {
result.push(node.stringLiteral.text());
}
else {
this.getModuleNamesHelper(node.name, result);
}
return result;
}
private getModuleNamesHelper(name: TypeScript.INameSyntax, result: string[]): void {
if (name.kind() === TypeScript.SyntaxKind.QualifiedName) {
var qualifiedName = <TypeScript.QualifiedNameSyntax>name;
this.getModuleNamesHelper(qualifiedName.left, result);
result.push(qualifiedName.right.text());
}
else {
result.push((<TypeScript.ISyntaxToken>name).text());
}
}
private createModuleItem(node: ModuleDeclarationSyntax): ts.NavigationBarItem {
var moduleNames = this.getModuleNames(node);
var childItems = this.getItemsWorker(() => this.getChildNodes(node.moduleElements), n => this.createChildItem(n));
return new ts.NavigationBarItem(moduleNames.join("."),
ts.ScriptElementKind.moduleElement,
this.getKindModifiers(node.modifiers),
[TextSpan.fromBounds(start(node), end(node))],
childItems,
this.getIndent(node));
}
private createFunctionItem(node: FunctionDeclarationSyntax) {
var childItems = this.getItemsWorker(() => node.block.statements, n => this.createChildItem(n));
return new ts.NavigationBarItem(node.identifier.text(),
ts.ScriptElementKind.functionElement,
this.getKindModifiers(node.modifiers),
[TextSpan.fromBounds(start(node), end(node))],
childItems,
this.getIndent(node));
}
private createSourceUnitItem(node: SourceUnitSyntax): ts.NavigationBarItem {
var childItems = this.getItemsWorker(() => this.getChildNodes(node.moduleElements), n => this.createChildItem(n));
if (childItems === null || childItems.length === 0) {
return null;
}
this.hasGlobalNode = true;
return new ts.NavigationBarItem("<global>",
ts.ScriptElementKind.moduleElement,
ts.ScriptElementKindModifier.none,
[TextSpan.fromBounds(start(node), end(node))],
childItems);
}
private createClassItem(node: ClassDeclarationSyntax): ts.NavigationBarItem {
var constructor = <ConstructorDeclarationSyntax>ArrayUtilities.firstOrDefault(
node.classElements, n => n.kind() === SyntaxKind.ConstructorDeclaration);
// Add the constructor parameters in as children of hte class (for property parameters).
var nodes: ISyntaxNode[] = constructor
? (<ISyntaxNode[]>constructor.callSignature.parameterList.parameters).concat(node.classElements)
: node.classElements;
var childItems = this.getItemsWorker(() => nodes, n => this.createChildItem(n));
return new ts.NavigationBarItem(
node.identifier.text(),
ts.ScriptElementKind.classElement,
this.getKindModifiers(node.modifiers),
[TextSpan.fromBounds(start(node), end(node))],
childItems,
this.getIndent(node));
}
private createEnumItem(node: TypeScript.EnumDeclarationSyntax): ts.NavigationBarItem {
var childItems = this.getItemsWorker(() => node.enumElements, n => this.createChildItem(n));
return new ts.NavigationBarItem(
node.identifier.text(),
ts.ScriptElementKind.enumElement,
this.getKindModifiers(node.modifiers),
[TextSpan.fromBounds(start(node), end(node))],
childItems,
this.getIndent(node));
}
private createIterfaceItem(node: TypeScript.InterfaceDeclarationSyntax): ts.NavigationBarItem {
var childItems = this.getItemsWorker(() => node.body.typeMembers, n => this.createChildItem(n));
return new ts.NavigationBarItem(
node.identifier.text(),
ts.ScriptElementKind.interfaceElement,
this.getKindModifiers(node.modifiers),
[TextSpan.fromBounds(start(node), end(node))],
childItems,
this.getIndent(node));
}
}
}
-1
View File
@@ -1,4 +1,3 @@
///<reference path='references.ts' />
module TypeScript.Indentation {
export function columnForEndOfTokenAtPosition(syntaxTree: SyntaxTree, position: number, options: FormattingOptions): number {
+426
View File
@@ -0,0 +1,426 @@
/// <reference path='services.ts' />
/// <reference path="text/textSpan.ts" />
module ts.NavigationBar {
export function getNavigationBarItems(sourceFile: SourceFile): ts.NavigationBarItem[] {
// If the source file has any child items, then it included in the tree
// and takes lexical ownership of all other top-level items.
var hasGlobalNode = false;
return getItemsWorker(getTopLevelNodes(sourceFile), createTopLevelItem);
function getIndent(node: Node): number {
// If we have a global node in the tree,
// then it adds an extra layer of depth to all subnodes.
var indent = hasGlobalNode ? 1 : 0;
var current = node.parent;
while (current) {
switch (current.kind) {
case SyntaxKind.ModuleDeclaration:
// If we have a module declared as A.B.C, it is more "intuitive"
// to say it only has a single layer of depth
do {
current = current.parent;
}
while (current.kind === SyntaxKind.ModuleDeclaration);
// fall through
case SyntaxKind.ClassDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.FunctionDeclaration:
indent++;
}
current = current.parent;
}
return indent;
}
function getChildNodes(nodes: Node[]): Node[] {
var childNodes: Node[] = [];
for (var i = 0, n = nodes.length; i < n; i++) {
var node = nodes[i];
if (node.kind === SyntaxKind.ClassDeclaration ||
node.kind === SyntaxKind.EnumDeclaration ||
node.kind === SyntaxKind.InterfaceDeclaration ||
node.kind === SyntaxKind.ModuleDeclaration ||
node.kind === SyntaxKind.FunctionDeclaration) {
childNodes.push(node);
}
else if (node.kind === SyntaxKind.VariableStatement) {
childNodes.push.apply(childNodes, (<VariableStatement>node).declarations);
}
}
return sortNodes(childNodes);
}
function getTopLevelNodes(node: SourceFile): Node[] {
var topLevelNodes: Node[] = [];
topLevelNodes.push(node);
addTopLevelNodes(node.statements, topLevelNodes);
return topLevelNodes;
}
function sortNodes(nodes: Node[]): Node[] {
return nodes.slice(0).sort((n1: Declaration, n2: Declaration) => {
if (n1.name && n2.name) {
return n1.name.text.localeCompare(n2.name.text);
}
else if (n1.name) {
return 1;
}
else if (n2.name) {
-1;
}
else {
return n1.kind - n2.kind;
}
});
}
function addTopLevelNodes(nodes: Node[], topLevelNodes: Node[]): void {
nodes = sortNodes(nodes);
for (var i = 0, n = nodes.length; i < n; i++) {
var node = nodes[i];
switch (node.kind) {
case SyntaxKind.ClassDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.InterfaceDeclaration:
topLevelNodes.push(node);
break;
case SyntaxKind.ModuleDeclaration:
var moduleDeclaration = <ModuleDeclaration>node;
topLevelNodes.push(node);
addTopLevelNodes((<Block>getInnermostModule(moduleDeclaration).body).statements, topLevelNodes);
break;
case SyntaxKind.FunctionDeclaration:
var functionDeclaration = <FunctionDeclaration>node;
if (isTopLevelFunctionDeclaration(functionDeclaration)) {
topLevelNodes.push(node);
addTopLevelNodes((<Block>functionDeclaration.body).statements, topLevelNodes);
}
break;
}
}
}
function isTopLevelFunctionDeclaration(functionDeclaration: FunctionDeclaration) {
if (functionDeclaration.kind === SyntaxKind.FunctionDeclaration) {
// A function declaration is 'top level' if it contains any function declarations
// within it.
if (functionDeclaration.body && functionDeclaration.body.kind === SyntaxKind.FunctionBlock) {
if (forEach((<Block>functionDeclaration.body).statements,
s => s.kind === SyntaxKind.FunctionDeclaration && !isEmpty((<FunctionDeclaration>s).name.text))) {
return true;
}
// Or if it is not parented by another function. i.e all functions
// at module scope are 'top level'.
if (functionDeclaration.parent.kind !== SyntaxKind.FunctionBlock) {
return true;
}
}
}
return false;
}
function getItemsWorker(nodes: Node[], createItem: (n: Node) => ts.NavigationBarItem): ts.NavigationBarItem[] {
var items: ts.NavigationBarItem[] = [];
var keyToItem: Map<NavigationBarItem> = {};
for (var i = 0, n = nodes.length; i < n; i++) {
var child = nodes[i];
var item = createItem(child);
if (item !== undefined) {
if (item.text.length > 0) {
var key = item.text + "-" + item.kind + "-" + item.indent;
var itemWithSameName = keyToItem[key];
if (itemWithSameName) {
// We had an item with the same name. Merge these items together.
merge(itemWithSameName, item);
}
else {
keyToItem[key] = item;
items.push(item);
}
}
}
}
return items;
}
function merge(target: ts.NavigationBarItem, source: ts.NavigationBarItem) {
// First, add any spans in the source to the target.
target.spans.push.apply(target.spans, source.spans);
if (source.childItems) {
if (!target.childItems) {
target.childItems = [];
}
// Next, recursively merge or add any children in the source as appropriate.
outer:
for (var i = 0, n = source.childItems.length; i < n; i++) {
var sourceChild = source.childItems[i];
for (var j = 0, m = target.childItems.length; j < m; j++) {
var targetChild = target.childItems[j];
if (targetChild.text === sourceChild.text && targetChild.kind === sourceChild.kind) {
// Found a match. merge them.
merge(targetChild, sourceChild);
continue outer;
}
}
// Didn't find a match, just add this child to the list.
target.childItems.push(sourceChild);
}
}
}
function createChildItem(node: Node): ts.NavigationBarItem {
switch (node.kind) {
case SyntaxKind.Parameter:
if ((node.flags & NodeFlags.Modifier) === 0) {
return undefined;
}
return createItem(node, getTextOfNode((<ParameterDeclaration>node).name), ts.ScriptElementKind.memberVariableElement);
case SyntaxKind.Method:
return createItem(node, getTextOfNode((<MethodDeclaration>node).name), ts.ScriptElementKind.memberFunctionElement);
case SyntaxKind.GetAccessor:
return createItem(node, getTextOfNode((<AccessorDeclaration>node).name), ts.ScriptElementKind.memberGetAccessorElement);
case SyntaxKind.SetAccessor:
return createItem(node, getTextOfNode((<AccessorDeclaration>node).name), ts.ScriptElementKind.memberSetAccessorElement);
case SyntaxKind.IndexSignature:
return createItem(node, "[]", ts.ScriptElementKind.indexSignatureElement);
case SyntaxKind.EnumMember:
return createItem(node, getTextOfNode((<EnumMember>node).name), ts.ScriptElementKind.memberVariableElement);
case SyntaxKind.CallSignature:
return createItem(node, "()", ts.ScriptElementKind.callSignatureElement);
case SyntaxKind.ConstructSignature:
return createItem(node, "new()", ts.ScriptElementKind.constructSignatureElement);
case SyntaxKind.Property:
return createItem(node, getTextOfNode((<PropertyDeclaration>node).name), ts.ScriptElementKind.memberVariableElement);
case SyntaxKind.FunctionDeclaration:
return createItem(node, getTextOfNode((<FunctionDeclaration>node).name), ts.ScriptElementKind.functionElement);
case SyntaxKind.VariableDeclaration:
return createItem(node, getTextOfNode((<VariableDeclaration>node).name), ts.ScriptElementKind.variableElement);
case SyntaxKind.Constructor:
return createItem(node, "constructor", ts.ScriptElementKind.constructorImplementationElement);
}
return undefined;
function createItem(node: Node, name: string, scriptElementKind: string): NavigationBarItem {
return getNavigationBarItem(name, scriptElementKind, getNodeModifiers(node), [getNodeSpan(node)]);
}
}
function isEmpty(text: string) {
return !text || text.trim() === "";
}
function getNavigationBarItem(text: string, kind: string, kindModifiers: string, spans: TypeScript.TextSpan[], childItems: ts.NavigationBarItem[] = [], indent: number = 0): ts.NavigationBarItem {
if (isEmpty(text)) {
return undefined;
}
return {
text: text,
kind: kind,
kindModifiers: kindModifiers,
spans: spans,
childItems: childItems,
indent: indent,
bolded: false,
grayed: false
};
}
function createTopLevelItem(node: Node): ts.NavigationBarItem {
switch (node.kind) {
case SyntaxKind.SourceFile:
return createSourceFileItem(<SourceFile>node);
case SyntaxKind.ClassDeclaration:
return createClassItem(<ClassDeclaration>node);
case SyntaxKind.EnumDeclaration:
return createEnumItem(<EnumDeclaration>node);
case SyntaxKind.InterfaceDeclaration:
return createIterfaceItem(<InterfaceDeclaration>node);
case SyntaxKind.ModuleDeclaration:
return createModuleItem(<ModuleDeclaration>node);
case SyntaxKind.FunctionDeclaration:
return createFunctionItem(<FunctionDeclaration>node);
}
return undefined;
function getModuleName(moduleDeclaration: ModuleDeclaration): string {
// We want to maintain quotation marks.
if (moduleDeclaration.name.kind === SyntaxKind.StringLiteral) {
return getTextOfNode(moduleDeclaration.name);
}
// Otherwise, we need to aggregate each identifier to build up the qualified name.
var result: string[] = [];
result.push(moduleDeclaration.name.text);
while (moduleDeclaration.body && moduleDeclaration.body.kind === SyntaxKind.ModuleDeclaration) {
moduleDeclaration = <ModuleDeclaration>moduleDeclaration.body;
result.push(moduleDeclaration.name.text);
}
return result.join(".");
}
function createModuleItem(node: ModuleDeclaration): NavigationBarItem {
var moduleName = getModuleName(node);
var childItems = getItemsWorker(getChildNodes((<Block>getInnermostModule(node).body).statements), createChildItem);
return getNavigationBarItem(moduleName,
ts.ScriptElementKind.moduleElement,
getNodeModifiers(node),
[getNodeSpan(node)],
childItems,
getIndent(node));
}
function createFunctionItem(node: FunctionDeclaration) {
if (node.name && node.body && node.body.kind === SyntaxKind.FunctionBlock) {
var childItems = getItemsWorker(sortNodes((<Block>node.body).statements), createChildItem);
return getNavigationBarItem(node.name.text,
ts.ScriptElementKind.functionElement,
getNodeModifiers(node),
[getNodeSpan(node)],
childItems,
getIndent(node));
}
return undefined;
}
function createSourceFileItem(node: SourceFile): ts.NavigationBarItem {
var childItems = getItemsWorker(getChildNodes(node.statements), createChildItem);
if (childItems === undefined || childItems.length === 0) {
return undefined;
}
hasGlobalNode = true;
var rootName = isExternalModule(node) ?
"\"" + escapeString(getBaseFilename(removeFileExtension(normalizePath(node.filename)))) + "\"" :
"<global>"
return getNavigationBarItem(rootName,
ts.ScriptElementKind.moduleElement,
ts.ScriptElementKindModifier.none,
[getNodeSpan(node)],
childItems);
}
function createClassItem(node: ClassDeclaration): ts.NavigationBarItem {
var childItems: NavigationBarItem[];
if (node.members) {
var constructor = <ConstructorDeclaration>forEach(node.members, member => {
return member.kind === SyntaxKind.Constructor && member;
});
// Add the constructor parameters in as children of the class (for property parameters).
var nodes: Node[] = constructor
? constructor.parameters.concat(node.members)
: node.members;
var childItems = getItemsWorker(sortNodes(nodes), createChildItem);
}
return getNavigationBarItem(
node.name.text,
ts.ScriptElementKind.classElement,
getNodeModifiers(node),
[getNodeSpan(node)],
childItems,
getIndent(node));
}
function createEnumItem(node: EnumDeclaration): ts.NavigationBarItem {
var childItems = getItemsWorker(sortNodes(node.members), createChildItem);
return getNavigationBarItem(
node.name.text,
ts.ScriptElementKind.enumElement,
getNodeModifiers(node),
[getNodeSpan(node)],
childItems,
getIndent(node));
}
function createIterfaceItem(node: InterfaceDeclaration): ts.NavigationBarItem {
var childItems = getItemsWorker(sortNodes(node.members), createChildItem);
return getNavigationBarItem(
node.name.text,
ts.ScriptElementKind.interfaceElement,
getNodeModifiers(node),
[getNodeSpan(node)],
childItems,
getIndent(node));
}
}
function getInnermostModule(node: ModuleDeclaration): ModuleDeclaration {
while (node.body.kind === SyntaxKind.ModuleDeclaration) {
node = <ModuleDeclaration>node.body;
}
return node;
}
function getNodeSpan(node: Node) {
return node.kind === SyntaxKind.SourceFile
? TypeScript.TextSpan.fromBounds(node.getFullStart(), node.getEnd())
: TypeScript.TextSpan.fromBounds(node.getStart(), node.getEnd());
}
function getTextOfNode(node: Node): string {
return getTextOfNodeFromSourceText(sourceFile.text, node);
}
}
}
+58 -12
View File
@@ -13,8 +13,6 @@
// limitations under the License.
//
///<reference path='references.ts' />
module ts {
export interface OutliningSpan {
@@ -35,19 +33,32 @@ module ts {
export module OutliningElementsCollector {
export function collectElements(sourceFile: SourceFile): OutliningSpan[] {
var elements: OutliningSpan[] = [];
var collapseText = "...";
function addOutlineRange(hintSpanNode: Node, startElement: Node, endElement: Node) {
function addOutliningSpan(hintSpanNode: Node, startElement: Node, endElement: Node, autoCollapse: boolean) {
if (hintSpanNode && startElement && endElement) {
var span: OutliningSpan = {
textSpan: TypeScript.TextSpan.fromBounds(startElement.pos, endElement.end),
hintSpan: TypeScript.TextSpan.fromBounds(hintSpanNode.getStart(), hintSpanNode.end),
bannerText: "...",
autoCollapse: false
bannerText: collapseText,
autoCollapse: autoCollapse
};
elements.push(span);
}
}
function autoCollapse(node: Node) {
switch (node.kind) {
case SyntaxKind.ModuleBlock:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
return false;
}
return true;
}
var depth = 0;
var maxDepth = 20;
function walk(n: Node): void {
@@ -56,23 +67,58 @@ module ts {
}
switch (n.kind) {
case SyntaxKind.Block:
var parent = n.parent;
var openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile);
var closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile);
// Check if the block is standalone, or 'attached' to some parent statement.
// If the latter, we want to collaps the block, but consider its hint span
// to be the entire span of the parent.
if (parent.kind === SyntaxKind.DoStatement ||
parent.kind === SyntaxKind.ForInStatement ||
parent.kind === SyntaxKind.ForStatement ||
parent.kind === SyntaxKind.IfStatement ||
parent.kind === SyntaxKind.WhileStatement ||
parent.kind === SyntaxKind.WithStatement) {
addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n));
}
else {
// Block was a standalone block. In this case we want to only collapse
// the span of the block, independent of any parent span.
var span = TypeScript.TextSpan.fromBounds(n.getStart(), n.end);
elements.push({
textSpan: span,
hintSpan: span,
bannerText: collapseText,
autoCollapse: autoCollapse(n)
});
}
break;
case SyntaxKind.FunctionBlock:
case SyntaxKind.ModuleBlock:
case SyntaxKind.TryBlock:
case SyntaxKind.TryBlock:
case SyntaxKind.CatchBlock:
case SyntaxKind.FinallyBlock:
var openBrace = forEach(n.getChildren(), c => c.kind === SyntaxKind.OpenBraceToken && c);
var closeBrace = forEach(n.getChildren(), c => c.kind === SyntaxKind.CloseBraceToken && c);
addOutlineRange(n.parent, openBrace, closeBrace);
var openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile);
var closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile);
addOutliningSpan(n.parent, openBrace, closeBrace, autoCollapse(n));
break;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.ObjectLiteral:
var openBrace = forEach(n.getChildren(), c => c.kind === SyntaxKind.OpenBraceToken && c);
var closeBrace = forEach(n.getChildren(), c => c.kind === SyntaxKind.CloseBraceToken && c);
addOutlineRange(n, openBrace, closeBrace);
case SyntaxKind.SwitchStatement:
var openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile);
var closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile);
addOutliningSpan(n, openBrace, closeBrace, autoCollapse(n));
break;
case SyntaxKind.ArrayLiteral:
var openBracket = findChildOfKind(n, SyntaxKind.OpenBracketToken, sourceFile);
var closeBracket = findChildOfKind(n, SyntaxKind.CloseBracketToken, sourceFile);
addOutliningSpan(n, openBracket, closeBracket, autoCollapse(n));
break;
}
depth++;
-26
View File
@@ -1,26 +0,0 @@
/////<reference path='es5compat.ts' />
/////<reference path='..\compiler\typescript.ts' />
//// document.ts depends on incrementalParser.ts being run first.
/////<reference path='..\compiler\syntax\incrementalParser.ts' />
/////<reference path='document.ts' />
/////<reference path='syntaxUtilities.generated.ts' />
/////<reference path='coreServices.ts' />
/////<reference path='classifier.ts' />
/////<reference path='compilerState.ts' />
/////<reference path='indentation.ts' />
/////<reference path='languageService.ts' />
/////<reference path='completionHelpers.ts' />
/////<reference path='keywordCompletions.ts' />
/////<reference path='signatureInfoHelpers.ts' />
/////<reference path='completionSession.ts' />
/////<reference path='pullLanguageService.ts' />
/////<reference path='findReferenceHelpers.ts' />
/////<reference path='shims.ts' />
/////<reference path='formatting\formatting.ts' />
/////<reference path='outliningElementsCollector.ts' />
/////<reference path='braceMatcher.ts' />
/////<reference path='indenter.ts' />
/////<reference path='breakpoints.ts' />
/////<reference path='getScriptLexicalStructureWalker.ts' />
+2707 -748
View File
File diff suppressed because it is too large Load Diff
+165 -90
View File
@@ -22,42 +22,40 @@ var debugObjectHost = (<any>this);
module ts {
export interface ScriptSnapshotShim {
// Get's a portion of the script snapshot specified by [start, end).
/** Gets a portion of the script snapshot specified by [start, end). */
getText(start: number, end: number): string;
// Get's the length of this script snapshot.
/** Gets the length of this script snapshot. */
getLength(): number;
// This call returns the JSON encoded array of the type:
// number[]
/** This call returns the JSON-encoded array of the type: number[] */
getLineStartPositions(): string;
// Returns a JSON encoded value of the type:
// { span: { start: number; length: number }; newLength: number }
//
// Or null value if there was no change.
/**
* Returns a JSON-encoded value of the type:
* { span: { start: number; length: number }; newLength: number }
*
* Or undefined value if there was no change.
*/
getChangeRange(oldSnapshot: ScriptSnapshotShim): string;
}
//
// Public interface of the host of a language service shim instance.
//
/** Public interface of the host of a language service shim instance.*/
export interface LanguageServiceShimHost extends Logger {
getCompilationSettings(): string;
// Returns a JSON encoded value of the type:
// string[]
/** Returns a JSON-encoded value of the type: string[] */
getScriptFileNames(): string;
getScriptVersion(fileName: string): string;
getScriptIsOpen(fileName: string): boolean;
getScriptSnapshot(fileName: string): ScriptSnapshotShim;
getLocalizedDiagnosticMessages(): string;
getCancellationToken(): CancellationToken;
getCurrentDirectory(): string;
getDefaultLibFilename(): string;
}
//
// Public interface of of a language service instance shim.
//
/** Public interface of a language service instance shim. */
export interface ShimFactory {
registerShim(shim: Shim): void;
unregisterShim(shim: Shim): void;
@@ -80,48 +78,75 @@ module ts {
getSemanticDiagnostics(fileName: string): string;
getCompilerOptionsDiagnostics(): string;
getSyntacticClassifications(fileName: string, start: number, length: number): string;
getCompletionsAtPosition(fileName: string, position: number, isMemberCompletion: boolean): string;
getCompletionEntryDetails(fileName: string, position: number, entryName: string): string;
getTypeAtPosition(fileName: string, position: number): string;
getQuickInfoAtPosition(fileName: string, position: number): string;
getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): string;
getBreakpointStatementAtPosition(fileName: string, position: number): string;
getSignatureHelpItems(fileName: string, position: number): string;
getSignatureHelpCurrentArgumentState(fileName: string, position: number, applicableSpanStart: number): string;
// Returns a JSON encoded value of the type:
// { canRename: boolean, localizedErrorMessage: string, displayName: string, fullDisplayName: string, kind: string, kindModifiers: string, triggerSpan: { start; length } }
// Obsolete. Use getSignatureHelpItems instead.
getSignatureAtPosition(fileName: string, position: number): string;
/**
* Returns a JSON-encoded value of the type:
* { canRename: boolean, localizedErrorMessage: string, displayName: string, fullDisplayName: string, kind: string, kindModifiers: string, triggerSpan: { start; length } }
*/
getRenameInfo(fileName: string, position: number): string;
// Returns a JSON encoded value of the type:
// { fileName: string; textSpan: { start: number; length: number}; kind: string; name: string; containerKind: string; containerName: string }
//
// Or null value if no definition can be found.
/**
* Returns a JSON-encoded value of the type:
* { fileName: string, textSpan: { start: number, length: number } }[]
*/
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): string;
/**
* Returns a JSON-encoded value of the type:
* { fileName: string; textSpan: { start: number; length: number}; kind: string; name: string; containerKind: string; containerName: string }
*
* Or undefined value if no definition can be found.
*/
getDefinitionAtPosition(fileName: string, position: number): string;
// Returns a JSON encoded value of the type:
// { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean }[]
/**
* Returns a JSON-encoded value of the type:
* { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean }[]
*/
getReferencesAtPosition(fileName: string, position: number): string;
// Returns a JSON encoded value of the type:
// { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean }[]
/**
* Returns a JSON-encoded value of the type:
* { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean }[]
*/
getOccurrencesAtPosition(fileName: string, position: number): string;
// Returns a JSON encoded value of the type:
// { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean }[]
/**
* Returns a JSON-encoded value of the type:
* { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean }[]
*/
getImplementorsAtPosition(fileName: string, position: number): string;
// Returns a JSON encoded value of the type:
// { name: string; kind: string; kindModifiers: string; containerName: string; containerKind: string; matchKind: string; fileName: string; textSpan: { start: number; length: number}; } [] = [];
/**
* Returns a JSON-encoded value of the type:
* { name: string; kind: string; kindModifiers: string; containerName: string; containerKind: string; matchKind: string; fileName: string; textSpan: { start: number; length: number}; } [] = [];
*/
getNavigateToItems(searchValue: string): string;
// Returns a JSON encoded value of the type:
// { text: string; kind: string; kindModifiers: string; bolded: boolean; grayed: boolean; indent: number; spans: { start: number; length: number; }[]; childItems: <recursive use of this type>[] } [] = [];
/**
* Returns a JSON-encoded value of the type:
* { text: string; kind: string; kindModifiers: string; bolded: boolean; grayed: boolean; indent: number; spans: { start: number; length: number; }[]; childItems: <recursive use of this type>[] } [] = [];
*/
getNavigationBarItems(fileName: string): string;
// Returns a JSON encoded value of the type:
// { textSpan: { start: number, length: number }; hintSpan: { start: number, length: number }; bannerText: string; autoCollapse: boolean } [] = [];
/**
* Returns a JSON-encoded value of the type:
* { textSpan: { start: number, length: number }; hintSpan: { start: number, length: number }; bannerText: string; autoCollapse: boolean } [] = [];
*/
getOutliningSpans(fileName: string): string;
getTodoComments(fileName: string, todoCommentDescriptors: string): string;
@@ -145,19 +170,19 @@ module ts {
getDefaultCompilationSettings(): string;
}
/// TODO: delete this, it is only needed untill the VS interface is updated
enum LanguageVersion {
/// TODO: delete this, it is only needed until the VS interface is updated
export enum LanguageVersion {
EcmaScript3 = 0,
EcmaScript5 = 1,
}
enum ModuleGenTarget {
export enum ModuleGenTarget {
Unspecified = 0,
Synchronous = 1,
Asynchronous = 2,
}
interface CompilationSettings {
export interface CompilationSettings {
propagateEnumConstants?: boolean;
removeComments?: boolean;
watch?: boolean;
@@ -177,15 +202,18 @@ module ts {
gatherDiagnostics?: boolean;
codepage?: number;
emitBOM?: boolean;
// Declare indexer signature
[index: string]: any;
}
function languageVersionToScriptTarget(languageVersion: LanguageVersion): ScriptTarget {
if (typeof languageVersion === "undefined") return undefined;
switch (languageVersion) {
case LanguageVersion.EcmaScript3: return ScriptTarget.ES3;
case LanguageVersion.EcmaScript3: return ScriptTarget.ES3
case LanguageVersion.EcmaScript5: return ScriptTarget.ES5;
default: throw Error("unsuported LanguageVersion value: " + languageVersion);
default: throw Error("unsupported LanguageVersion value: " + languageVersion);
}
}
@@ -196,7 +224,7 @@ module ts {
case ModuleGenTarget.Asynchronous: return ModuleKind.AMD;
case ModuleGenTarget.Synchronous: return ModuleKind.CommonJS;
case ModuleGenTarget.Unspecified: return ModuleKind.None;
default: throw Error("unsuported ModuleGenTarget value: " + moduleGenTarget);
default: throw Error("unsupported ModuleGenTarget value: " + moduleGenTarget);
}
}
@@ -206,7 +234,7 @@ module ts {
switch (scriptTarget) {
case ScriptTarget.ES3: return LanguageVersion.EcmaScript3;
case ScriptTarget.ES5: return LanguageVersion.EcmaScript5;
default: throw Error("unsuported ScriptTarget value: " + scriptTarget);
default: throw Error("unsupported ScriptTarget value: " + scriptTarget);
}
}
@@ -217,7 +245,7 @@ module ts {
case ModuleKind.AMD: return ModuleGenTarget.Asynchronous;
case ModuleKind.CommonJS: return ModuleGenTarget.Synchronous;
case ModuleKind.None: return ModuleGenTarget.Unspecified;
default: throw Error("unsuported ModuleKind value: " + moduleKind);
default: throw Error("unsupported ModuleKind value: " + moduleKind);
}
}
@@ -319,12 +347,6 @@ module ts {
}
var options = compilationSettingsToCompilerOptions(<CompilerOptions>JSON.parse(<any>settingsJson));
/// TODO: this should be pushed into VS.
/// We can not ask the LS instance to resolve, as this will lead to asking the host about files it does not know about,
/// something it is not desinged to handle. for now make sure we never get a "noresolve == false".
/// This value should not matter, as the host runs resolution logic independentlly
options.noResolve = true;
return options;
}
@@ -350,6 +372,7 @@ module ts {
if (diagnosticMessagesJson == null || diagnosticMessagesJson == "") {
return null;
}
try {
return JSON.parse(diagnosticMessagesJson);
}
@@ -362,6 +385,14 @@ module ts {
public getCancellationToken(): CancellationToken {
return this.shimHost.getCancellationToken();
}
public getDefaultLibFilename(): string {
return this.shimHost.getDefaultLibFilename();
}
public getCurrentDirectory(): string {
return this.shimHost.getCurrentDirectory();
}
}
function simpleForwardCall(logger: Logger, actionDescription: string, action: () => any): any {
@@ -418,9 +449,12 @@ module ts {
return forwardJSONCall(this.logger, actionDescription, action);
}
// DISPOSE
// Ensure (almost) determinstic release of internal Javascript resources when
// some external native objects holds onto us (e.g. Com/Interop).
/// DISPOSE
/**
* Ensure (almost) deterministic release of internal Javascript resources when
* some external native objects holds onto us (e.g. Com/Interop).
*/
public dispose(dummy: any): void {
this.logger.log("dispose()");
this.languageService.dispose();
@@ -437,8 +471,11 @@ module ts {
super.dispose(dummy);
}
// REFRESH
// Update the list of scripts known to the compiler
/// REFRESH
/**
* Update the list of scripts known to the compiler
*/
public refresh(throwOnError: boolean): void {
this.forwardJSONCall(
"refresh(" + throwOnError + ")",
@@ -462,7 +499,8 @@ module ts {
start: diagnostic.start,
length: diagnostic.length,
/// TODO: no need for the tolowerCase call
category: DiagnosticCategory[diagnostic.category].toLowerCase()
category: DiagnosticCategory[diagnostic.category].toLowerCase(),
code: diagnostic.code
};
}
@@ -477,6 +515,24 @@ module ts {
};
}
public getSyntacticClassifications(fileName: string, start: number, length: number): string {
return this.forwardJSONCall(
"getSyntacticClassifications('" + fileName + "', " + start + ", " + length + ")",
() => {
var classifications = this.languageService.getSyntacticClassifications(fileName, new TypeScript.TextSpan(start, length));
return classifications;
});
}
public getSemanticClassifications(fileName: string, start: number, length: number): string {
return this.forwardJSONCall(
"getSemanticClassifications('" + fileName + "', " + start + ", " + length + ")",
() => {
var classifications = this.languageService.getSemanticClassifications(fileName, new TypeScript.TextSpan(start, length));
return classifications;
});
}
public getSyntacticDiagnostics(fileName: string): string {
return this.forwardJSONCall(
"getSyntacticDiagnostics('" + fileName + "')",
@@ -505,20 +561,27 @@ module ts {
}
/// QUICKINFO
/// Computes a string representation of the type at the requested position
/// in the active file.
public getTypeAtPosition(fileName: string, position: number): string {
/**
* Computes a string representation of the type at the requested position
* in the active file.
*/
public getQuickInfoAtPosition(fileName: string, position: number): string {
return this.forwardJSONCall(
"getTypeAtPosition('" + fileName + "', " + position + ")",
"getQuickInfoAtPosition('" + fileName + "', " + position + ")",
() => {
var typeInfo = this.languageService.getTypeAtPosition(fileName, position);
return typeInfo;
var quickInfo = this.languageService.getQuickInfoAtPosition(fileName, position);
return quickInfo;
});
}
/// NAMEORDOTTEDNAMESPAN
/// Computes span information of the name or dotted name at the requested position
// in the active file.
/**
* Computes span information of the name or dotted name at the requested position
* in the active file.
*/
public getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): string {
return this.forwardJSONCall(
"getNameOrDottedNameSpan('" + fileName + "', " + startPos + ", " + endPos + ")",
@@ -528,8 +591,10 @@ module ts {
});
}
/// STATEMENTSPAN
/// Computes span information of statement at the requested position in the active file.
/**
* STATEMENTSPAN
* Computes span information of statement at the requested position in the active file.
*/
public getBreakpointStatementAtPosition(fileName: string, position: number): string {
return this.forwardJSONCall(
"getBreakpointStatementAtPosition('" + fileName + "', " + position + ")",
@@ -550,19 +615,20 @@ module ts {
});
}
public getSignatureHelpCurrentArgumentState(fileName: string, position: number, applicableSpanStart: number): string {
public getSignatureAtPosition(fileName: string, position: number): string {
return this.forwardJSONCall(
"getSignatureHelpCurrentArgumentState('" + fileName + "', " + position + ", " + applicableSpanStart + ")",
"getSignatureAtPosition('" + fileName + "', " + position + ")",
() => {
var signatureInfo = this.languageService.getSignatureHelpItems(fileName, position);
return signatureInfo;
return this.languageService.getSignatureAtPosition(fileName, position);
});
}
/// GOTO DEFINITION
/// Computes the definition location and file for the symbol
/// at the requested position.
/**
* Computes the definition location and file for the symbol
* at the requested position.
*/
public getDefinitionAtPosition(fileName: string, position: number): string {
return this.forwardJSONCall(
"getDefinitionAtPosition('" + fileName + "', " + position + ")",
@@ -579,6 +645,14 @@ module ts {
});
}
public findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): string {
return this.forwardJSONCall(
"findRenameLocations('" + fileName + "', " + position + ", " + findInStrings + ", " + findInComments + ")",
() => {
return this.languageService.findRenameLocations(fileName, position, findInStrings, findInComments);
});
}
/// GET BRACE MATCHING
public getBraceMatchingAtPosition(fileName: string, position: number): string {
return this.forwardJSONCall(
@@ -600,9 +674,12 @@ module ts {
}
/// GET REFERENCES
/// Return references to a symbol at the requested position.
/// References are separated by "\n".
/// Each reference is a "fileindex min lim" sub-string.
/**
* Return references to a symbol at the requested position.
* References are separated by "\n".
* Each reference is a "fileindex min lim" sub-string.
*/
public getReferencesAtPosition(fileName: string, position: number): string {
return this.forwardJSONCall(
"getReferencesAtPosition('" + fileName + "', " + position + ")",
@@ -630,9 +707,12 @@ module ts {
/// COMPLETION LISTS
/// Get a string based representation of the completions
/// to provide at the given source position and providing a member completion
/// list if requested.
/**
* Get a string based representation of the completions
* to provide at the given source position and providing a member completion
* list if requested.
*/
public getCompletionsAtPosition(fileName: string, position: number, isMemberCompletion: boolean) {
return this.forwardJSONCall(
"getCompletionsAtPosition('" + fileName + "', " + position + ", " + isMemberCompletion + ")",
@@ -642,7 +722,7 @@ module ts {
});
}
/// Get a string based representation of a completion list entry details
/** Get a string based representation of a completion list entry details */
public getCompletionEntryDetails(fileName: string, position: number, entryName: string) {
return this.forwardJSONCall(
"getCompletionEntryDetails('" + fileName + "', " + position + ", " + entryName + ")",
@@ -683,7 +763,8 @@ module ts {
}
/// NAVIGATE TO
/// Return a list of symbols that are interesting to navigate to
/** Return a list of symbols that are interesting to navigate to */
public getNavigateToItems(searchValue: string): string {
return this.forwardJSONCall(
"getNavigateToItems('" + searchValue + "')",
@@ -762,9 +843,6 @@ module ts {
return forwardJSONCall(this.logger, actionDescription, action);
}
///
/// getPreProcessedFileInfo
///
public getPreProcessedFileInfo(fileName: string, sourceText: TypeScript.IScriptSnapshot): string {
return this.forwardJSONCall(
"getPreProcessedFileInfo('" + fileName + "')",
@@ -774,9 +852,6 @@ module ts {
});
}
///
/// getDefaultCompilationSettings
///
public getDefaultCompilationSettings(): string {
return this.forwardJSONCall(
"getDefaultCompilationSettings()",
@@ -846,7 +921,7 @@ module ts {
}
/// TODO: this is used by VS, clean this up on both sides of the interfrace
/// TODO: this is used by VS, clean this up on both sides of the interface
module TypeScript.Services {
export var TypeScriptServicesFactory = ts.TypeScriptServicesFactory;
}
+411
View File
@@ -0,0 +1,411 @@
///<reference path='services.ts' />
module ts.SignatureHelp {
// A partially written generic type expression is not guaranteed to have the correct syntax tree. the expression could be parsed as less than/greater than expression or a comma expression
// or some other combination depending on what the user has typed so far. For the purposes of signature help we need to consider any location after "<" as a possible generic type reference.
// To do this, the method will back parse the expression starting at the position required. it will try to parse the current expression as a generic type expression, if it did succeed it
// will return the generic identifier that started the expression (e.g. "foo" in "foo<any, |"). It is then up to the caller to ensure that this is a valid generic expression through
// looking up the type. The method will also keep track of the parameter index inside the expression.
//public static isInPartiallyWrittenTypeArgumentList(syntaxTree: TypeScript.SyntaxTree, position: number): any {
// var token = Syntax.findTokenOnLeft(syntaxTree.sourceUnit(), position, /*includeSkippedTokens*/ true);
// if (token && TypeScript.Syntax.hasAncestorOfKind(token, TypeScript.SyntaxKind.TypeParameterList)) {
// // We are in the wrong generic list. bail out
// return null;
// }
// var stack = 0;
// var argumentIndex = 0;
// whileLoop:
// while (token) {
// switch (token.kind()) {
// case TypeScript.SyntaxKind.LessThanToken:
// if (stack === 0) {
// // Found the beginning of the generic argument expression
// var lessThanToken = token;
// token = previousToken(token, /*includeSkippedTokens*/ true);
// if (!token || token.kind() !== TypeScript.SyntaxKind.IdentifierName) {
// break whileLoop;
// }
// // Found the name, return the data
// return {
// genericIdentifer: token,
// lessThanToken: lessThanToken,
// argumentIndex: argumentIndex
// };
// }
// else if (stack < 0) {
// // Seen one too many less than tokens, bail out
// break whileLoop;
// }
// else {
// stack--;
// }
// break;
// case TypeScript.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
// stack++;
// // Intentaion fall through
// case TypeScript.SyntaxKind.GreaterThanToken:
// stack++;
// break;
// case TypeScript.SyntaxKind.CommaToken:
// if (stack == 0) {
// argumentIndex++;
// }
// break;
// case TypeScript.SyntaxKind.CloseBraceToken:
// // This can be object type, skip untill we find the matching open brace token
// var unmatchedOpenBraceTokens = 0;
// // Skip untill the matching open brace token
// token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, TypeScript.SyntaxKind.CloseBraceToken, TypeScript.SyntaxKind.OpenBraceToken);
// if (!token) {
// // No matching token was found. bail out
// break whileLoop;
// }
// break;
// case TypeScript.SyntaxKind.EqualsGreaterThanToken:
// // This can be a function type or a constructor type. In either case, we want to skip the function defintion
// token = previousToken(token, /*includeSkippedTokens*/ true);
// if (token && token.kind() === TypeScript.SyntaxKind.CloseParenToken) {
// // Skip untill the matching open paren token
// token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, TypeScript.SyntaxKind.CloseParenToken, TypeScript.SyntaxKind.OpenParenToken);
// if (token && token.kind() === TypeScript.SyntaxKind.GreaterThanToken) {
// // Another generic type argument list, skip it\
// token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, TypeScript.SyntaxKind.GreaterThanToken, TypeScript.SyntaxKind.LessThanToken);
// }
// if (token && token.kind() === TypeScript.SyntaxKind.NewKeyword) {
// // In case this was a constructor type, skip the new keyword
// token = previousToken(token, /*includeSkippedTokens*/ true);
// }
// if (!token) {
// // No matching token was found. bail out
// break whileLoop;
// }
// }
// else {
// // This is not a funtion type. exit the main loop
// break whileLoop;
// }
// break;
// case TypeScript.SyntaxKind.IdentifierName:
// case TypeScript.SyntaxKind.AnyKeyword:
// case TypeScript.SyntaxKind.NumberKeyword:
// case TypeScript.SyntaxKind.StringKeyword:
// case TypeScript.SyntaxKind.VoidKeyword:
// case TypeScript.SyntaxKind.BooleanKeyword:
// case TypeScript.SyntaxKind.DotToken:
// case TypeScript.SyntaxKind.OpenBracketToken:
// case TypeScript.SyntaxKind.CloseBracketToken:
// // Valid tokens in a type name. Skip.
// break;
// default:
// break whileLoop;
// }
// token = previousToken(token, /*includeSkippedTokens*/ true);
// }
// return null;
//}
//private static moveBackUpTillMatchingTokenKind(token: TypeScript.ISyntaxToken, tokenKind: TypeScript.SyntaxKind, matchingTokenKind: TypeScript.SyntaxKind): TypeScript.ISyntaxToken {
// if (!token || token.kind() !== tokenKind) {
// throw TypeScript.Errors.invalidOperation();
// }
// // Skip the current token
// token = previousToken(token, /*includeSkippedTokens*/ true);
// var stack = 0;
// while (token) {
// if (token.kind() === matchingTokenKind) {
// if (stack === 0) {
// // Found the matching token, return
// return token;
// }
// else if (stack < 0) {
// // tokens overlapped.. bail out.
// break;
// }
// else {
// stack--;
// }
// }
// else if (token.kind() === tokenKind) {
// stack++;
// }
// // Move back
// token = previousToken(token, /*includeSkippedTokens*/ true);
// }
// // Did not find matching token
// return null;
//}
var emptyArray: any[] = [];
export function getSignatureHelpItems(sourceFile: SourceFile, position: number, typeInfoResolver: TypeChecker, cancellationToken: CancellationTokenObject): SignatureHelpItems {
// Decide whether to show signature help
var startingToken = findTokenOnLeftOfPosition(sourceFile, position);
if (!startingToken) {
// We are at the beginning of the file
return undefined;
}
var argumentInfo = getContainingArgumentInfo(startingToken);
cancellationToken.throwIfCancellationRequested();
// Semantic filtering of signature help
if (!argumentInfo) {
return undefined;
}
var call = <CallExpression>argumentInfo.list.parent;
var candidates = <Signature[]>[];
var resolvedSignature = typeInfoResolver.getResolvedSignature(call, candidates);
cancellationToken.throwIfCancellationRequested();
if (!candidates.length) {
return undefined;
}
return createSignatureHelpItems(candidates, resolvedSignature, argumentInfo);
/**
* If node is an argument, returns its index in the argument list.
* If not, returns -1.
*/
function getImmediatelyContainingArgumentInfo(node: Node): ListItemInfo {
if (node.parent.kind !== SyntaxKind.CallExpression && node.parent.kind !== SyntaxKind.NewExpression) {
return undefined;
}
// There are 3 cases to handle:
// 1. The token introduces a list, and should begin a sig help session
// 2. The token is either not associated with a list, or ends a list, so the session should end
// 3. The token is buried inside a list, and should give sig help
//
// The following are examples of each:
//
// Case 1:
// foo<$T, U>($a, b) -> The token introduces a list, and should begin a sig help session
// Case 2:
// fo$o<T, U>$(a, b)$ -> The token is either not associated with a list, or ends a list, so the session should end
// Case 3:
// foo<T$, U$>(a$, $b$) -> The token is buried inside a list, and should give sig help
var parent = <CallExpression>node.parent;
// Find out if 'node' is an argument, a type argument, or neither
if (node.kind === SyntaxKind.LessThanToken || node.kind === SyntaxKind.OpenParenToken) {
// Find the list that starts right *after* the < or ( token.
// If the user has just opened a list, consider this item 0.
var list = getChildListThatStartsWithOpenerToken(parent, node, sourceFile);
Debug.assert(list);
return {
list: list,
listItemIndex: 0
};
}
if (node.kind === SyntaxKind.GreaterThanToken
|| node.kind === SyntaxKind.CloseParenToken
|| node === parent.func) {
return undefined;
}
return findListItemInfo(node);
}
function getContainingArgumentInfo(node: Node): ListItemInfo {
for (var n = node; n.kind !== SyntaxKind.SourceFile; n = n.parent) {
if (n.kind === SyntaxKind.FunctionBlock) {
return undefined;
}
// If the node is not a subspan of its parent, this is a big problem.
// There have been crashes that might be caused by this violation.
if (n.pos < n.parent.pos || n.end > n.parent.end) {
Debug.fail("Node of kind " + SyntaxKind[n.kind] + " is not a subspan of its parent of kind " + SyntaxKind[n.parent.kind]);
}
var argumentInfo = getImmediatelyContainingArgumentInfo(n);
if (argumentInfo) {
return argumentInfo;
}
// TODO: Handle generic call with incomplete syntax
}
return undefined;
}
/**
* The selectedItemIndex could be negative for several reasons.
* 1. There are too many arguments for all of the overloads
* 2. None of the overloads were type compatible
* The solution here is to try to pick the best overload by picking
* either the first one that has an appropriate number of parameters,
* or the one with the most parameters.
*/
function selectBestInvalidOverloadIndex(candidates: Signature[], argumentCount: number): number {
var maxParamsSignatureIndex = -1;
var maxParams = -1;
for (var i = 0; i < candidates.length; i++) {
var candidate = candidates[i];
if (candidate.hasRestParameter || candidate.parameters.length >= argumentCount) {
return i;
}
if (candidate.parameters.length > maxParams) {
maxParams = candidate.parameters.length;
maxParamsSignatureIndex = i;
}
}
return maxParamsSignatureIndex;
}
function createSignatureHelpItems(candidates: Signature[], bestSignature: Signature, argumentInfoOrTypeArgumentInfo: ListItemInfo): SignatureHelpItems {
var argumentListOrTypeArgumentList = argumentInfoOrTypeArgumentInfo.list;
var items: SignatureHelpItem[] = map(candidates, candidateSignature => {
var parameters = candidateSignature.parameters;
var parameterHelpItems: SignatureHelpParameter[] = parameters.length === 0 ? emptyArray : map(parameters, p => {
var displayParts: SymbolDisplayPart[] = [];
if (candidateSignature.hasRestParameter && parameters[parameters.length - 1] === p) {
displayParts.push(punctuationPart(SyntaxKind.DotDotDotToken));
}
displayParts.push(symbolPart(p.name, p));
var isOptional = !!(p.valueDeclaration.flags & NodeFlags.QuestionMark);
if (isOptional) {
displayParts.push(punctuationPart(SyntaxKind.QuestionToken));
}
displayParts.push(punctuationPart(SyntaxKind.ColonToken));
displayParts.push(spacePart());
var typeParts = typeToDisplayParts(typeInfoResolver, typeInfoResolver.getTypeOfSymbol(p), argumentListOrTypeArgumentList);
displayParts.push.apply(displayParts, typeParts);
return {
name: p.name,
documentation: p.getDocumentationComment(),
displayParts: displayParts,
isOptional: isOptional
};
});
var callTargetNode = (<CallExpression>argumentListOrTypeArgumentList.parent).func;
var callTargetSymbol = typeInfoResolver.getSymbolInfo(callTargetNode);
var prefixParts = callTargetSymbol ? symbolToDisplayParts(typeInfoResolver, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined) : [];
var separatorParts = [punctuationPart(SyntaxKind.CommaToken), spacePart()];
// TODO(jfreeman): Constraints?
if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) {
prefixParts.push(punctuationPart(SyntaxKind.LessThanToken));
for (var i = 0, n = candidateSignature.typeParameters.length; i < n; i++) {
if (i) {
prefixParts.push.apply(prefixParts, separatorParts);
}
var tp = candidateSignature.typeParameters[i].symbol;
prefixParts.push(symbolPart(tp.name, tp));
}
prefixParts.push(punctuationPart(SyntaxKind.GreaterThanToken));
}
prefixParts.push(punctuationPart(SyntaxKind.OpenParenToken));
var suffixParts = [punctuationPart(SyntaxKind.CloseParenToken)];
suffixParts.push(punctuationPart(SyntaxKind.ColonToken));
suffixParts.push(spacePart());
var typeParts = typeToDisplayParts(typeInfoResolver, candidateSignature.getReturnType(), argumentListOrTypeArgumentList);
suffixParts.push.apply(suffixParts, typeParts);
return {
isVariadic: candidateSignature.hasRestParameter,
prefixDisplayParts: prefixParts,
suffixDisplayParts: suffixParts,
separatorDisplayParts: separatorParts,
parameters: parameterHelpItems,
documentation: candidateSignature.getDocumentationComment()
};
});
// We use full start and skip trivia on the end because we want to include trivia on
// both sides. For example,
//
// foo( /*comment */ a, b, c /*comment*/ )
// | |
//
// The applicable span is from the first bar to the second bar (inclusive,
// but not including parentheses)
var applicableSpanStart = argumentListOrTypeArgumentList.getFullStart();
var applicableSpanEnd = skipTrivia(sourceFile.text, argumentListOrTypeArgumentList.end, /*stopAfterLineBreak*/ false);
var applicableSpan = new TypeScript.TextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
// The listItemIndex we got back includes commas. Our goal is to return the index of the proper
// item (not including commas). Here are some examples:
// 1. foo(a, b, c $) -> the listItemIndex is 4, we want to return 2
// 2. foo(a, b, $ c) -> listItemIndex is 3, we want to return 2
// 3. foo($a) -> listItemIndex is 0, we want to return 0
//
// In general, we want to subtract the number of commas before the current index.
// But if we are on a comma, we also want to pretend we are on the argument *following*
// the comma. That amounts to taking the ceiling of half the index.
var argumentIndex = (argumentInfoOrTypeArgumentInfo.listItemIndex + 1) >> 1;
// argumentCount is the number of commas plus one, unless the list is completely empty,
// in which case there are 0.
var argumentCount = argumentListOrTypeArgumentList.getChildCount() === 0
? 0
: 1 + countWhere(argumentListOrTypeArgumentList.getChildren(), arg => arg.kind === SyntaxKind.CommaToken);
var selectedItemIndex = candidates.indexOf(bestSignature);
if (selectedItemIndex < 0) {
selectedItemIndex = selectBestInvalidOverloadIndex(candidates, argumentCount);
}
return {
items: items,
applicableSpan: applicableSpan,
selectedItemIndex: selectedItemIndex,
argumentIndex: argumentIndex,
argumentCount: argumentCount
};
}
}
function getChildListThatStartsWithOpenerToken(parent: Node, openerToken: Node, sourceFile: SourceFile): Node {
var children = parent.getChildren(sourceFile);
var indexOfOpenerToken = children.indexOf(openerToken);
return children[indexOfOpenerToken + 1];
}
}
-348
View File
@@ -1,348 +0,0 @@
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
///<reference path='references.ts' />
module TypeScript.Services {
export interface IPartiallyWrittenTypeArgumentListInformation {
genericIdentifer: TypeScript.ISyntaxToken;
lessThanToken: TypeScript.ISyntaxToken;
argumentIndex: number;
}
export interface IExpressionWithArgumentListSyntax extends IExpressionSyntax {
expression: IExpressionSyntax;
argumentList: ArgumentListSyntax;
}
export class SignatureInfoHelpers {
// A partially written generic type expression is not guaranteed to have the correct syntax tree. the expression could be parsed as less than/greater than expression or a comma expression
// or some other combination depending on what the user has typed so far. For the purposes of signature help we need to consider any location after "<" as a possible generic type reference.
// To do this, the method will back parse the expression starting at the position required. it will try to parse the current expression as a generic type expression, if it did succeed it
// will return the generic identifier that started the expression (e.g. "foo" in "foo<any, |"). It is then up to the caller to ensure that this is a valid generic expression through
// looking up the type. The method will also keep track of the parameter index inside the expression.
public static isInPartiallyWrittenTypeArgumentList(syntaxTree: TypeScript.SyntaxTree, position: number): IPartiallyWrittenTypeArgumentListInformation {
var token = Syntax.findTokenOnLeft(syntaxTree.sourceUnit(), position, /*includeSkippedTokens*/ true);
if (token && TypeScript.Syntax.hasAncestorOfKind(token, TypeScript.SyntaxKind.TypeParameterList)) {
// We are in the wrong generic list. bail out
return null;
}
var stack = 0;
var argumentIndex = 0;
whileLoop:
while (token) {
switch (token.kind()) {
case TypeScript.SyntaxKind.LessThanToken:
if (stack === 0) {
// Found the beginning of the generic argument expression
var lessThanToken = token;
token = previousToken(token, /*includeSkippedTokens*/ true);
if (!token || token.kind() !== TypeScript.SyntaxKind.IdentifierName) {
break whileLoop;
}
// Found the name, return the data
return {
genericIdentifer: token,
lessThanToken: lessThanToken,
argumentIndex: argumentIndex
};
}
else if (stack < 0) {
// Seen one too many less than tokens, bail out
break whileLoop;
}
else {
stack--;
}
break;
case TypeScript.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
stack++;
// Intentaion fall through
case TypeScript.SyntaxKind.GreaterThanToken:
stack++;
break;
case TypeScript.SyntaxKind.CommaToken:
if (stack == 0) {
argumentIndex++;
}
break;
case TypeScript.SyntaxKind.CloseBraceToken:
// This can be object type, skip untill we find the matching open brace token
var unmatchedOpenBraceTokens = 0;
// Skip untill the matching open brace token
token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, TypeScript.SyntaxKind.CloseBraceToken, TypeScript.SyntaxKind.OpenBraceToken);
if (!token) {
// No matching token was found. bail out
break whileLoop;
}
break;
case TypeScript.SyntaxKind.EqualsGreaterThanToken:
// This can be a function type or a constructor type. In either case, we want to skip the function defintion
token = previousToken(token, /*includeSkippedTokens*/ true);
if (token && token.kind() === TypeScript.SyntaxKind.CloseParenToken) {
// Skip untill the matching open paren token
token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, TypeScript.SyntaxKind.CloseParenToken, TypeScript.SyntaxKind.OpenParenToken);
if (token && token.kind() === TypeScript.SyntaxKind.GreaterThanToken) {
// Another generic type argument list, skip it\
token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, TypeScript.SyntaxKind.GreaterThanToken, TypeScript.SyntaxKind.LessThanToken);
}
if (token && token.kind() === TypeScript.SyntaxKind.NewKeyword) {
// In case this was a constructor type, skip the new keyword
token = previousToken(token, /*includeSkippedTokens*/ true);
}
if (!token) {
// No matching token was found. bail out
break whileLoop;
}
}
else {
// This is not a funtion type. exit the main loop
break whileLoop;
}
break;
case TypeScript.SyntaxKind.IdentifierName:
case TypeScript.SyntaxKind.AnyKeyword:
case TypeScript.SyntaxKind.NumberKeyword:
case TypeScript.SyntaxKind.StringKeyword:
case TypeScript.SyntaxKind.VoidKeyword:
case TypeScript.SyntaxKind.BooleanKeyword:
case TypeScript.SyntaxKind.DotToken:
case TypeScript.SyntaxKind.OpenBracketToken:
case TypeScript.SyntaxKind.CloseBracketToken:
// Valid tokens in a type name. Skip.
break;
default:
break whileLoop;
}
token = previousToken(token, /*includeSkippedTokens*/ true);
}
return null;
}
public static getSignatureInfoFromSignatureSymbol(symbol: TypeScript.PullSymbol, signatures: TypeScript.PullSignatureSymbol[], enclosingScopeSymbol: TypeScript.PullSymbol, compilerState: LanguageServiceCompiler) {
var signatureGroup: FormalSignatureItemInfo[] = [];
var hasOverloads = signatures.length > 1;
for (var i = 0, n = signatures.length; i < n; i++) {
var signature = signatures[i];
// filter out the definition signature if there are overloads
if (hasOverloads && signature.isDefinition()) {
continue;
}
var signatureGroupInfo = new FormalSignatureItemInfo();
var paramIndexInfo: number[] = [];
var functionName = signature.getScopedNameEx(enclosingScopeSymbol).toString();
if (!functionName && (!symbol.isType() || (<TypeScript.PullTypeSymbol>symbol).isNamedTypeSymbol())) {
functionName = symbol.getScopedNameEx(enclosingScopeSymbol).toString();
}
var signatureMemberName = signature.getSignatureTypeNameEx(functionName, /*shortform*/ false, /*brackets*/ false, enclosingScopeSymbol, /*getParamMarkerInfo*/ true, /*getTypeParameterMarkerInfo*/ true);
signatureGroupInfo.signatureInfo = TypeScript.MemberName.memberNameToString(signatureMemberName, paramIndexInfo);
signatureGroupInfo.docComment = signature.docComments();
var parameterMarkerIndex = 0;
if (signature.isGeneric()) {
var typeParameters = signature.getTypeParameters();
for (var j = 0, m = typeParameters.length; j < m; j++) {
var typeParameter = typeParameters[j];
var signatureTypeParameterInfo = new FormalTypeParameterInfo();
signatureTypeParameterInfo.name = typeParameter.getDisplayName();
signatureTypeParameterInfo.docComment = typeParameter.docComments();
signatureTypeParameterInfo.minChar = paramIndexInfo[2 * parameterMarkerIndex];
signatureTypeParameterInfo.limChar = paramIndexInfo[2 * parameterMarkerIndex + 1];
parameterMarkerIndex++;
signatureGroupInfo.typeParameters.push(signatureTypeParameterInfo);
}
}
var parameters = signature.parameters;
for (var j = 0, m = parameters.length; j < m; j++) {
var parameter = parameters[j];
var signatureParameterInfo = new FormalParameterInfo();
signatureParameterInfo.isVariable = signature.hasVarArgs && (j === parameters.length - 1);
signatureParameterInfo.name = parameter.getDisplayName();
signatureParameterInfo.docComment = parameter.docComments();
signatureParameterInfo.minChar = paramIndexInfo[2 * parameterMarkerIndex];
signatureParameterInfo.limChar = paramIndexInfo[2 * parameterMarkerIndex + 1];
parameterMarkerIndex++;
signatureGroupInfo.parameters.push(signatureParameterInfo);
}
signatureGroup.push(signatureGroupInfo);
}
return signatureGroup;
}
public static getSignatureInfoFromGenericSymbol(symbol: TypeScript.PullSymbol, enclosingScopeSymbol: TypeScript.PullSymbol, compilerState: LanguageServiceCompiler) {
var signatureGroupInfo = new FormalSignatureItemInfo();
var paramIndexInfo: number[] = [];
var symbolName = symbol.getScopedNameEx(enclosingScopeSymbol, /*skipTypeParametersInName*/ false, /*useConstaintInName*/ true, /*getPrettyTypeName*/ false, /*getTypeParamMarkerInfo*/ true);
signatureGroupInfo.signatureInfo = TypeScript.MemberName.memberNameToString(symbolName, paramIndexInfo);
signatureGroupInfo.docComment = symbol.docComments();
var parameterMarkerIndex = 0;
var typeSymbol = symbol.type;
var typeParameters = typeSymbol.getTypeParameters();
for (var i = 0, n = typeParameters.length; i < n; i++) {
var typeParameter = typeParameters[i];
var signatureTypeParameterInfo = new FormalTypeParameterInfo();
signatureTypeParameterInfo.name = typeParameter.getDisplayName();
signatureTypeParameterInfo.docComment = typeParameter.docComments();
signatureTypeParameterInfo.minChar = paramIndexInfo[2 * i];
signatureTypeParameterInfo.limChar = paramIndexInfo[2 * i + 1];
signatureGroupInfo.typeParameters.push(signatureTypeParameterInfo);
}
return [signatureGroupInfo];
}
public static getActualSignatureInfoFromCallExpression(ast: IExpressionWithArgumentListSyntax, caretPosition: number, typeParameterInformation: IPartiallyWrittenTypeArgumentListInformation): ActualSignatureInfo {
if (!ast) {
return null;
}
var result = new ActualSignatureInfo();
// The expression is not guaranteed to be complete, we need to populate the min and lim with the most accurate information we have about
// type argument and argument lists
var parameterMinChar = caretPosition;
var parameterLimChar = caretPosition;
if (ast.argumentList.typeArgumentList) {
parameterMinChar = Math.min(start(ast.argumentList.typeArgumentList));
parameterLimChar = Math.max(Math.max(start(ast.argumentList.typeArgumentList), end(ast.argumentList.typeArgumentList) + trailingTriviaWidth(ast.argumentList.typeArgumentList)));
}
if (ast.argumentList.arguments) {
parameterMinChar = Math.min(parameterMinChar, end(ast.argumentList.openParenToken));
parameterLimChar = Math.max(parameterLimChar,
ast.argumentList.closeParenToken.fullWidth() > 0 ? start(ast.argumentList.closeParenToken) : fullEnd(ast.argumentList));
}
result.parameterMinChar = parameterMinChar;
result.parameterLimChar = parameterLimChar;
result.currentParameterIsTypeParameter = false;
result.currentParameter = -1;
if (typeParameterInformation) {
result.currentParameterIsTypeParameter = true;
result.currentParameter = typeParameterInformation.argumentIndex;
}
else if (ast.argumentList.arguments && ast.argumentList.arguments.length > 0) {
result.currentParameter = 0;
for (var index = 0; index < ast.argumentList.arguments.length; index++) {
if (caretPosition > end(ast.argumentList.arguments[index]) + lastToken(ast.argumentList.arguments[index]).trailingTriviaWidth()) {
result.currentParameter++;
}
}
}
return result;
}
public static getActualSignatureInfoFromPartiallyWritenGenericExpression(caretPosition: number, typeParameterInformation: IPartiallyWrittenTypeArgumentListInformation): ActualSignatureInfo {
var result = new ActualSignatureInfo();
result.parameterMinChar = start(typeParameterInformation.lessThanToken);
result.parameterLimChar = Math.max(fullEnd(typeParameterInformation.lessThanToken), caretPosition);
result.currentParameterIsTypeParameter = true;
result.currentParameter = typeParameterInformation.argumentIndex;
return result;
}
public static isSignatureHelpBlocker(sourceUnit: TypeScript.SourceUnitSyntax, position: number): boolean {
// We shouldn't be getting a possition that is outside the file because
// isEntirelyInsideComment can't handle when the position is out of bounds,
// callers should be fixed, however we should be resiliant to bad inputs
// so we return true (this position is a blocker for getting signature help)
if (position < 0 || position > fullWidth(sourceUnit)) {
return true;
}
return TypeScript.Syntax.isEntirelyInsideComment(sourceUnit, position);
}
public static isTargetOfObjectCreationExpression(positionedToken: TypeScript.ISyntaxToken): boolean {
var positionedParent = TypeScript.Syntax.getAncestorOfKind(positionedToken, TypeScript.SyntaxKind.ObjectCreationExpression);
if (positionedParent) {
var objectCreationExpression = <TypeScript.ObjectCreationExpressionSyntax> positionedParent;
var expressionRelativeStart = objectCreationExpression.newKeyword.fullWidth();
var tokenRelativeStart = positionedToken.fullStart() - fullStart(positionedParent);
return tokenRelativeStart >= expressionRelativeStart &&
tokenRelativeStart <= (expressionRelativeStart + fullWidth(objectCreationExpression.expression));
}
return false;
}
private static moveBackUpTillMatchingTokenKind(token: TypeScript.ISyntaxToken, tokenKind: TypeScript.SyntaxKind, matchingTokenKind: TypeScript.SyntaxKind): TypeScript.ISyntaxToken {
if (!token || token.kind() !== tokenKind) {
throw TypeScript.Errors.invalidOperation();
}
// Skip the current token
token = previousToken(token, /*includeSkippedTokens*/ true);
var stack = 0;
while (token) {
if (token.kind() === matchingTokenKind) {
if (stack === 0) {
// Found the matching token, return
return token;
}
else if (stack < 0) {
// tokens overlapped.. bail out.
break;
}
else {
stack--;
}
}
else if (token.kind() === tokenKind) {
stack++;
}
// Move back
token = previousToken(token, /*includeSkippedTokens*/ true);
}
// Did not find matching token
return null;
}
}
}
@@ -42,6 +42,10 @@ module TypeScript {
return this.defaultVisit(node);
}
public visitTupleType(node: TupleTypeSyntax): any {
return this.defaultVisit(node);
}
public visitInterfaceDeclaration(node: InterfaceDeclarationSyntax): any {
return this.defaultVisit(node);
}
+40 -7
View File
@@ -1048,6 +1048,7 @@ module TypeScript.Parser {
case SyntaxKind.ExportKeyword:
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.StaticKeyword:
case SyntaxKind.DeclareKeyword:
return true;
@@ -1434,6 +1435,19 @@ module TypeScript.Parser {
return new syntaxFactory.ObjectTypeSyntax(parseNodeData, openBraceToken, typeMembers, eatToken(SyntaxKind.CloseBraceToken));
}
function parseTupleType(currentToken: ISyntaxToken): TupleTypeSyntax {
var openBracket = consumeToken(currentToken);
var types = Syntax.emptySeparatedList<ITypeSyntax>();
if (openBracket.fullWidth() > 0) {
var skippedTokens: ISyntaxToken[] = getArray();
types = parseSeparatedSyntaxList<ITypeSyntax>(ListParsingState.TupleType_Types, skippedTokens);
openBracket = addSkippedTokensAfterToken(openBracket, skippedTokens);
}
return new syntaxFactory.TupleTypeSyntax(parseNodeData, openBracket, types, eatToken(SyntaxKind.CloseBracketToken));
}
function isTypeMember(inErrorRecovery: boolean): boolean {
if (SyntaxUtilities.isTypeMember(currentNode())) {
return true;
@@ -1663,6 +1677,7 @@ module TypeScript.Parser {
// ERROR RECOVERY
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.StaticKeyword:
// None of the above are actually keywords. And they might show up in a real
// statement (i.e. "public();"). However, if we see 'public <identifier>' then
@@ -1731,6 +1746,7 @@ module TypeScript.Parser {
// ERROR RECOVERY
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.StaticKeyword:
// None of the above are actually keywords. And they might show up in a real
// statement (i.e. "public();"). However, if we see 'public <identifier>' then
@@ -3133,7 +3149,7 @@ module TypeScript.Parser {
token2 = peekToken(2);
token2Kind = token2.kind();
if (token1Kind === SyntaxKind.PublicKeyword || token1Kind === SyntaxKind.PrivateKeyword) {
if (SyntaxFacts.isAccessibilityModifier(token1Kind)) {
if (isIdentifier(token2)) {
// "(public id" or "(function id". Definitely an arrow function. Could never
// be a parenthesized expression. Note: this will be an *illegal* arrow
@@ -3557,11 +3573,12 @@ module TypeScript.Parser {
return consumeToken(_currentToken);
case SyntaxKind.OpenParenToken:
case SyntaxKind.LessThanToken: return tryParseFunctionType();
case SyntaxKind.VoidKeyword: return consumeToken(_currentToken);
case SyntaxKind.OpenBraceToken: return parseObjectType();
case SyntaxKind.NewKeyword: return parseConstructorType();
case SyntaxKind.TypeOfKeyword: return parseTypeQuery(_currentToken);
case SyntaxKind.LessThanToken: return tryParseFunctionType();
case SyntaxKind.VoidKeyword: return consumeToken(_currentToken);
case SyntaxKind.OpenBraceToken: return parseObjectType();
case SyntaxKind.NewKeyword: return parseConstructorType();
case SyntaxKind.TypeOfKeyword: return parseTypeQuery(_currentToken);
case SyntaxKind.OpenBracketToken: return parseTupleType(_currentToken);
}
return tryParseNameOrGenericType();
@@ -3973,6 +3990,7 @@ module TypeScript.Parser {
case ListParsingState.IndexSignature_Parameters: return isExpectedIndexSignature_ParametersTerminator();
case ListParsingState.TypeArgumentList_Types: return isExpectedTypeArgumentList_TypesTerminator();
case ListParsingState.TypeParameterList_TypeParameters: return isExpectedTypeParameterList_TypeParametersTerminator();
case ListParsingState.TupleType_Types: return isExpectedTupleType_TypesTerminator();
default:
throw Errors.invalidOperation();
}
@@ -4019,6 +4037,17 @@ module TypeScript.Parser {
return false;
}
function isExpectedTupleType_TypesTerminator(): boolean {
var token = currentToken();
var tokenKind = token.kind();
if (tokenKind === SyntaxKind.CloseBracketToken) {
return true;
}
// TODO: add more cases as necessary for error tolerance.
return false;
}
function isExpectedTypeParameterList_TypeParametersTerminator(): boolean {
var tokenKind = currentToken().kind();
if (tokenKind === SyntaxKind.GreaterThanToken) {
@@ -4187,6 +4216,7 @@ module TypeScript.Parser {
case ListParsingState.IndexSignature_Parameters: return isParameter();
case ListParsingState.TypeArgumentList_Types: return isType();
case ListParsingState.TypeParameterList_TypeParameters: return isTypeParameter();
case ListParsingState.TupleType_Types: return isType();
default: throw Errors.invalidOperation();
}
}
@@ -4230,6 +4260,7 @@ module TypeScript.Parser {
case ListParsingState.IndexSignature_Parameters: return tryParseParameter();
case ListParsingState.TypeArgumentList_Types: return tryParseType();
case ListParsingState.TypeParameterList_TypeParameters: return tryParseTypeParameter();
case ListParsingState.TupleType_Types: return tryParseType();
default: throw Errors.invalidOperation();
}
}
@@ -4254,6 +4285,7 @@ module TypeScript.Parser {
case ListParsingState.IndexSignature_Parameters: return getLocalizedText(DiagnosticCode.parameter, null);
case ListParsingState.TypeArgumentList_Types: return getLocalizedText(DiagnosticCode.type, null);
case ListParsingState.TypeParameterList_TypeParameters: return getLocalizedText(DiagnosticCode.type_parameter, null);
case ListParsingState.TupleType_Types: return getLocalizedText(DiagnosticCode.type, null);
case ListParsingState.ArrayLiteralExpression_AssignmentExpressions: return getLocalizedText(DiagnosticCode.expression, null);
default: throw Errors.invalidOperation();
}
@@ -4376,9 +4408,10 @@ module TypeScript.Parser {
IndexSignature_Parameters = 18,
TypeArgumentList_Types = 19,
TypeParameterList_TypeParameters = 20,
TupleType_Types = 21,
FirstListParsingState = SourceUnit_ModuleElements,
LastListParsingState = TypeParameterList_TypeParameters,
LastListParsingState = TupleType_Types,
}
// We keep the parser around as a singleton. This is because calling createParser is actually
+6
View File
@@ -421,6 +421,12 @@ module TypeScript.PrettyPrinter {
this.appendToken(node.greaterThanToken);
}
public visitTupleType(node: TupleTypeSyntax): void {
this.appendToken(node.openBracketToken);
this.appendSeparatorSpaceList(node.types);
this.appendToken(node.closeBracketToken);
}
public visitConstructorType(node: ConstructorTypeSyntax): void {
this.appendToken(node.newKeyword);
this.ensureSpace();
+11
View File
@@ -26,4 +26,15 @@ module TypeScript.SyntaxFacts {
var tokenKind = token.kind();
return tokenKind === SyntaxKind.IdentifierName || SyntaxFacts.isAnyKeyword(tokenKind);
}
export function isAccessibilityModifier(kind: SyntaxKind): boolean {
switch (kind) {
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
return true;
}
return false;
}
}
+11
View File
@@ -354,6 +354,17 @@ var definitions:ITypeDefinition[] = [
],
isTypeScriptSpecific: true
},
<any> {
name: 'TupleTypeSyntax',
baseType: 'ISyntaxNode',
interfaces: ['ITypeSyntax'],
children: [
<any>{ name: 'openBracketToken', isToken: true, excludeFromAST: true },
<any>{ name: 'types', isSeparatedList: true, elementType: 'ITypeSyntax' },
<any>{ name: 'closeBracketToken', isToken: true, excludeFromAST: true }
],
isTypeScriptSpecific: true
},
<any>{
name: 'TypeAnnotationSyntax',
baseType: 'ISyntaxNode',
+1
View File
@@ -158,6 +158,7 @@ module TypeScript {
ConstructorType,
GenericType,
TypeQuery,
TupleType,
// Module elements.
InterfaceDeclaration,
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+12 -6
View File
@@ -239,7 +239,7 @@ module TypeScript {
}
private checkParameterAccessibilityModifier(parameterList: ParameterListSyntax, modifier: ISyntaxToken, modifierIndex: number): boolean {
if (modifier.kind() !== SyntaxKind.PublicKeyword && modifier.kind() !== SyntaxKind.PrivateKeyword) {
if (!SyntaxFacts.isAccessibilityModifier(modifier.kind())) {
this.pushDiagnostic(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_parameter, [modifier.text()]);
return true;
}
@@ -321,6 +321,15 @@ module TypeScript {
super.visitTypeArgumentList(node);
}
public visitTupleType(node: TupleTypeSyntax): void {
if (this.checkForTrailingComma(node.types) ||
this.checkForAtLeastOneElement(node, node.types, node.openBracketToken, getLocalizedText(DiagnosticCode.type, null))) {
return
}
super.visitTupleType(node);
}
public visitTypeParameterList(node: TypeParameterListSyntax): void {
if (this.checkForTrailingComma(node.typeParameters) ||
this.checkForAtLeastOneElement(node, node.typeParameters, node.lessThanToken, getLocalizedText(DiagnosticCode.type_parameter, null))) {
@@ -515,9 +524,7 @@ module TypeScript {
for (var i = 0, n = list.length; i < n; i++) {
var modifier = list[i];
if (modifier.kind() === SyntaxKind.PublicKeyword ||
modifier.kind() === SyntaxKind.PrivateKeyword) {
if (SyntaxFacts.isAccessibilityModifier(modifier.kind())) {
if (seenAccessibilityModifier) {
this.pushDiagnostic(modifier, DiagnosticCode.Accessibility_modifier_already_seen);
return true;
@@ -752,8 +759,7 @@ module TypeScript {
for (var i = 0, n = modifiers.length; i < n; i++) {
var modifier = modifiers[i];
if (modifier.kind() === SyntaxKind.PublicKeyword ||
modifier.kind() === SyntaxKind.PrivateKeyword ||
if (SyntaxFacts.isAccessibilityModifier(modifier.kind()) ||
modifier.kind() === SyntaxKind.StaticKeyword) {
this.pushDiagnostic(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_module_element, [modifier.text()]);
return true;
-1
View File
@@ -150,7 +150,6 @@ module TypeScript.Syntax {
// When we run into a newline for the first time, create the string builder and copy
// all the values up to this newline into it.
var isCarriageReturnLineFeed = false;
switch (ch) {
case CharacterCodes.carriageReturn:
if (i < triviaText.length - 1 && triviaText.charCodeAt(i + 1) === CharacterCodes.lineFeed) {
@@ -13,6 +13,7 @@ module TypeScript {
case SyntaxKind.ConstructorType: return visitor.visitConstructorType(<ConstructorTypeSyntax>element);
case SyntaxKind.GenericType: return visitor.visitGenericType(<GenericTypeSyntax>element);
case SyntaxKind.TypeQuery: return visitor.visitTypeQuery(<TypeQuerySyntax>element);
case SyntaxKind.TupleType: return visitor.visitTupleType(<TupleTypeSyntax>element);
case SyntaxKind.InterfaceDeclaration: return visitor.visitInterfaceDeclaration(<InterfaceDeclarationSyntax>element);
case SyntaxKind.FunctionDeclaration: return visitor.visitFunctionDeclaration(<FunctionDeclarationSyntax>element);
case SyntaxKind.ModuleDeclaration: return visitor.visitModuleDeclaration(<ModuleDeclarationSyntax>element);
@@ -109,6 +110,7 @@ module TypeScript {
visitConstructorType(node: ConstructorTypeSyntax): any;
visitGenericType(node: GenericTypeSyntax): any;
visitTypeQuery(node: TypeQuerySyntax): any;
visitTupleType(node: TupleTypeSyntax): any;
visitInterfaceDeclaration(node: InterfaceDeclarationSyntax): any;
visitFunctionDeclaration(node: FunctionDeclarationSyntax): any;
visitModuleDeclaration(node: ModuleDeclarationSyntax): any;
@@ -103,6 +103,12 @@ module TypeScript {
this.visitNodeOrToken(node.name);
}
public visitTupleType(node: TupleTypeSyntax): void {
this.visitToken(node.openBracketToken);
this.visitSeparatedList(node.types);
this.visitToken(node.closeBracketToken);
}
public visitInterfaceDeclaration(node: InterfaceDeclarationSyntax): void {
this.visitList(node.modifiers);
this.visitToken(node.interfaceKeyword);
+19 -13
View File
@@ -1,26 +1,32 @@
///<reference path='references.ts' />
module TypeScript {
// Represents an immutable snapshot of a script at a specified time. Once acquired, the
// snapshot is observably immutable. i.e. the same calls with the same parameters will return
// the same values.
/**
* Represents an immutable snapshot of a script at a specified time.Once acquired, the
* snapshot is observably immutable. i.e. the same calls with the same parameters will return
* the same values.
*/
export interface IScriptSnapshot {
// Get's a portion of the script snapshot specified by [start, end).
/** Gets a portion of the script snapshot specified by [start, end). */
getText(start: number, end: number): string;
// Get's the length of this script snapshot.
/** Gets the length of this script snapshot. */
getLength(): number;
// This call returns the array containing the start position of every line.
// i.e."[0, 10, 55]". TODO: consider making this optional. The language service could
// always determine this (albeit in a more expensive manner).
/**
* This call returns the array containing the start position of every line.
* i.e."[0, 10, 55]". TODO: consider making this optional. The language service could
* always determine this (albeit in a more expensive manner).
*/
getLineStartPositions(): number[];
// Gets the TextChangeRange that describe how the text changed between this text and
// an older version. This informatoin is used by the incremental parser to determine
// what sections of the script need to be reparsed. 'null' can be returned if the
// change range cannot be determined. However, in that case, incremental parsing will
// not happen and the entire document will be reparsed.
/**
* Gets the TextChangeRange that describe how the text changed between this text and
* an older version. This information is used by the incremental parser to determine
* what sections of the script need to be re-parsed. 'undefined' can be returned if the
* change range cannot be determined. However, in that case, incremental parsing will
* not happen and the entire document will be re - parsed.
*/
getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange;
}
+1
View File
@@ -1,6 +1,7 @@
///<reference path='references.ts' />
module TypeScript {
export interface ISpan {
start(): number;
end(): number;
+247
View File
@@ -0,0 +1,247 @@
// These utilities are common to multiple language service features.
module ts {
export interface ListItemInfo {
listItemIndex: number;
list: Node;
}
export function findListItemInfo(node: Node): ListItemInfo {
var syntaxList = findContainingList(node);
var children = syntaxList.getChildren();
var index = indexOf(children, node);
return {
listItemIndex: index,
list: syntaxList
};
}
export function findChildOfKind(n: Node, kind: SyntaxKind, sourceFile?: SourceFile): Node {
return forEach(n.getChildren(sourceFile), c => c.kind === kind && c);
}
export function findContainingList(node: Node): Node {
// The node might be a list element (nonsynthetic) or a comma (synthetic). Either way, it will
// be parented by the container of the SyntaxList, not the SyntaxList itself.
// In order to find the list item index, we first need to locate SyntaxList itself and then search
// for the position of the relevant node (or comma).
var syntaxList = forEach(node.parent.getChildren(), c => {
// find syntax list that covers the span of the node
if (c.kind === SyntaxKind.SyntaxList && c.pos <= node.pos && c.end >= node.end) {
return c;
}
});
// syntaxList should not be undefined here. If it is, there is a problem. Find out if
// there at least is a child that is a list.
if (!syntaxList) {
Debug.assert(findChildOfKind(node.parent, SyntaxKind.SyntaxList),
"Node of kind " + SyntaxKind[node.parent.kind] + " has no list children");
}
return syntaxList;
}
/**
* Includes the start position of each child, but excludes the end.
*/
export function findListItemIndexContainingPosition(list: Node, position: number): number {
Debug.assert(list.kind === SyntaxKind.SyntaxList);
var children = list.getChildren();
for (var i = 0; i < children.length; i++) {
if (children[i].pos <= position && children[i].end > position) {
return i;
}
}
return -1;
}
/* Gets the token whose text has range [start, end) and
* position >= start and (position < end or (position === end && token is keyword or identifier))
*/
export function getTouchingWord(sourceFile: SourceFile, position: number): Node {
return getTouchingToken(sourceFile, position, isWord);
}
/* Gets the token whose text has range [start, end) and position >= start
* and (position < end or (position === end && token is keyword or identifier or numeric\string litera))
*/
export function getTouchingPropertyName(sourceFile: SourceFile, position: number): Node {
return getTouchingToken(sourceFile, position, isPropertyName);
}
/** Returns the token if position is in [start, end) or if position === end and includeItemAtEndPosition(token) === true */
export function getTouchingToken(sourceFile: SourceFile, position: number, includeItemAtEndPosition?: (n: Node) => boolean): Node {
return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, includeItemAtEndPosition);
}
/** Returns a token if position is in [start-of-leading-trivia, end) */
export function getTokenAtPosition(sourceFile: SourceFile, position: number): Node {
return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includeItemAtEndPosition*/ undefined);
}
/** Get the token whose text contains the position */
function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allowPositionInLeadingTrivia: boolean, includeItemAtEndPosition: (n: Node) => boolean): Node {
var current: Node = sourceFile;
outer: while (true) {
if (isToken(current)) {
// exit early
return current;
}
// find the child that contains 'position'
for (var i = 0, n = current.getChildCount(sourceFile); i < n; i++) {
var child = current.getChildAt(i);
var start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile);
if (start <= position) {
if (position < child.getEnd()) {
current = child;
continue outer;
}
else if (includeItemAtEndPosition && child.getEnd() === position) {
var previousToken = findPrecedingToken(position, sourceFile, child);
if (previousToken && includeItemAtEndPosition(previousToken)) {
return previousToken;
}
}
}
}
return current;
}
}
/**
* The token on the left of the position is the token that strictly includes the position
* or sits to the left of the cursor if it is on a boundary. For example
*
* fo|o -> will return foo
* foo <comment> |bar -> will return foo
*
*/
export function findTokenOnLeftOfPosition(file: SourceFile, position: number): Node {
// Ideally, getTokenAtPosition should return a token. However, it is currently
// broken, so we do a check to make sure the result was indeed a token.
var tokenAtPosition = getTokenAtPosition(file, position);
if (isToken(tokenAtPosition) && position > tokenAtPosition.getStart(file) && position < tokenAtPosition.getEnd()) {
return tokenAtPosition;
}
return findPrecedingToken(position, file);
}
export function findNextToken(previousToken: Node, parent: Node): Node {
return find(parent);
function find(n: Node): Node {
if (isToken(n) && n.pos === previousToken.end) {
// this is token that starts at the end of previous token - return it
return n;
}
var children = n.getChildren();
for (var i = 0, len = children.length; i < len; ++i) {
var child = children[i];
var shouldDiveInChildNode =
// previous token is enclosed somewhere in the child
(child.pos <= previousToken.pos && child.end > previousToken.end) ||
// previous token ends exactly at the beginning of child
(child.pos === previousToken.end);
if (shouldDiveInChildNode && nodeHasTokens(child)) {
return find(child);
}
}
return undefined;
}
}
export function findPrecedingToken(position: number, sourceFile: SourceFile, startNode?: Node): Node {
return find(startNode || sourceFile);
function findRightmostToken(n: Node): Node {
if (isToken(n)) {
return n;
}
var children = n.getChildren();
var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length);
return candidate && findRightmostToken(candidate);
}
function find(n: Node): Node {
if (isToken(n)) {
return n;
}
var children = n.getChildren();
for (var i = 0, len = children.length; i < len; ++i) {
var child = children[i];
if (nodeHasTokens(child)) {
if (position < child.end) {
if (child.getStart(sourceFile) >= position) {
// actual start of the node is past the position - previous token should be at the end of previous child
var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i);
return candidate && findRightmostToken(candidate)
}
else {
// candidate should be in this node
return find(child);
}
}
}
}
Debug.assert(startNode || n.kind === SyntaxKind.SourceFile);
// Here we know that none of child token nodes embrace the position,
// the only known case is when position is at the end of the file.
// Try to find the rightmost token in the file without filtering.
// Namely we are skipping the check: 'position < node.end'
if (children.length) {
var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length);
return candidate && findRightmostToken(candidate);
}
}
/// finds last node that is considered as candidate for search (isCandidate(node) === true) starting from 'exclusiveStartPosition'
function findRightmostChildNodeWithTokens(children: Node[], exclusiveStartPosition: number): Node {
for (var i = exclusiveStartPosition - 1; i >= 0; --i) {
if (nodeHasTokens(children[i])) {
return children[i];
}
}
}
}
function nodeHasTokens(n: Node): boolean {
if (n.kind === SyntaxKind.ExpressionStatement) {
return nodeHasTokens((<ExpressionStatement>n).expression);
}
if (n.kind === SyntaxKind.EndOfFileToken || n.kind === SyntaxKind.OmittedExpression || n.kind === SyntaxKind.Missing) {
return false;
}
// SyntaxList is already realized so getChildCount should be fast and non-expensive
return n.kind !== SyntaxKind.SyntaxList || n.getChildCount() !== 0;
}
export function isToken(n: Node): boolean {
return n.kind >= SyntaxKind.FirstToken && n.kind <= SyntaxKind.LastToken;
}
function isKeyword(n: Node): boolean {
return n.kind >= SyntaxKind.FirstKeyword && n.kind <= SyntaxKind.LastKeyword;
}
function isWord(n: Node): boolean {
return n.kind === SyntaxKind.Identifier || isKeyword(n);
}
function isPropertyName(n: Node): boolean {
return n.kind === SyntaxKind.StringLiteral || n.kind === SyntaxKind.NumericLiteral || isWord(n);
}
}
@@ -1,6 +1,9 @@
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction1.ts(1,13): error TS1110: Type expected.
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction1.ts (1 errors) ====
var v = (a: ) => {
~
!!! Type expected.
!!! error TS1110: Type expected.
};
@@ -1,8 +1,12 @@
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction2.ts(1,14): error TS1009: Trailing comma not allowed.
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction2.ts(1,13): error TS2304: Cannot find name 'b'.
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction2.ts (2 errors) ====
var v = (a: b,) => {
~
!!! Trailing comma not allowed.
!!! error TS1009: Trailing comma not allowed.
~
!!! Cannot find name 'b'.
!!! error TS2304: Cannot find name 'b'.
};
@@ -1,10 +1,15 @@
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts(1,12): error TS1005: ',' expected.
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts(1,14): error TS1005: ';' expected.
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts(1,10): error TS2304: Cannot find name 'a'.
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts (3 errors) ====
var v = (a): => {
~
!!! ',' expected.
!!! error TS1005: ',' expected.
~~
!!! ';' expected.
!!! error TS1005: ';' expected.
~
!!! Cannot find name 'a'.
!!! error TS2304: Cannot find name 'a'.
};
@@ -1,4 +1,7 @@
tests/cases/compiler/ArrowFunctionExpression1.ts(1,10): error TS2369: A parameter property is only allowed in a constructor implementation.
==== tests/cases/compiler/ArrowFunctionExpression1.ts (1 errors) ====
var v = (public x: string) => { };
~~~~~~~~~~~~~~~~
!!! A parameter property is only allowed in a constructor implementation.
!!! error TS2369: A parameter property is only allowed in a constructor implementation.
@@ -1,3 +1,10 @@
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts(10,19): error TS2304: Cannot find name 'T'.
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts(20,12): error TS2304: Cannot find name 'T'.
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts(22,23): error TS2304: Cannot find name 'T'.
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts(35,26): error TS2304: Cannot find name 'T'.
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts(46,15): error TS2304: Cannot find name 'T'.
==== tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts (5 errors) ====
// all expected to be errors
@@ -10,7 +17,7 @@
module clodule1 {
function f(x: T) { }
~
!!! Cannot find name 'T'.
!!! error TS2304: Cannot find name 'T'.
}
class clodule2<T>{
@@ -22,11 +29,11 @@
module clodule2 {
var x: T;
~
!!! Cannot find name 'T'.
!!! error TS2304: Cannot find name 'T'.
class D<U extends T>{
~
!!! Cannot find name 'T'.
!!! error TS2304: Cannot find name 'T'.
id: string;
value: U;
}
@@ -41,7 +48,7 @@
module clodule3 {
export var y = { id: T };
~
!!! Cannot find name 'T'.
!!! error TS2304: Cannot find name 'T'.
}
class clodule4<T>{
@@ -54,7 +61,7 @@
class D {
name: T;
~
!!! Cannot find name 'T'.
!!! error TS2304: Cannot find name 'T'.
}
}
@@ -1,16 +1,22 @@
==== tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModulesExportedGenericFunctionAndGenericClassStaticFunctionOfTheSameName.ts (1 errors) ====
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModulesExportedGenericFunctionAndGenericClassStaticFunctionOfTheSameName.ts(5,12): error TS2300: Duplicate identifier 'fn'.
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModulesExportedGenericFunctionAndGenericClassStaticFunctionOfTheSameName.ts(10,21): error TS2300: Duplicate identifier 'fn'.
==== tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModulesExportedGenericFunctionAndGenericClassStaticFunctionOfTheSameName.ts (2 errors) ====
class clodule<T> {
id: string;
value: T;
static fn<U>(id: U) { }
~~
!!! error TS2300: Duplicate identifier 'fn'.
}
module clodule {
// error: duplicate identifier expected
export function fn<T>(x: T, y: T): T {
~~
!!! Duplicate identifier 'fn'.
!!! error TS2300: Duplicate identifier 'fn'.
return x;
}
}
@@ -1,16 +1,22 @@
==== tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModulesExportedGenericFunctionAndNonGenericClassStaticFunctionOfTheSameName.ts (1 errors) ====
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModulesExportedGenericFunctionAndNonGenericClassStaticFunctionOfTheSameName.ts(5,12): error TS2300: Duplicate identifier 'fn'.
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModulesExportedGenericFunctionAndNonGenericClassStaticFunctionOfTheSameName.ts(10,21): error TS2300: Duplicate identifier 'fn'.
==== tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModulesExportedGenericFunctionAndNonGenericClassStaticFunctionOfTheSameName.ts (2 errors) ====
class clodule<T> {
id: string;
value: T;
static fn(id: string) { }
~~
!!! error TS2300: Duplicate identifier 'fn'.
}
module clodule {
// error: duplicate identifier expected
export function fn<T>(x: T, y: T): T {
~~
!!! Duplicate identifier 'fn'.
!!! error TS2300: Duplicate identifier 'fn'.
return x;
}
}
@@ -1,3 +1,6 @@
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModulesExportedStaticFunctionUsingClassPrivateStatics.ts(11,16): error TS2341: Property 'sfn' is private and only accessible within class 'clodule<T>'.
==== tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModulesExportedStaticFunctionUsingClassPrivateStatics.ts (1 errors) ====
class clodule<T> {
id: string;
@@ -11,7 +14,7 @@
export function fn<T>(x: T, y: T): number {
return clodule.sfn('a');
~~~~~~~~~~~
!!! Property 'clodule.sfn' is inaccessible.
!!! error TS2341: Property 'sfn' is private and only accessible within class 'clodule<T>'.
}
}
@@ -1,14 +1,22 @@
==== tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithStaticFunctionAndExportedFunctionThatShareAName.ts (2 errors) ====
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithStaticFunctionAndExportedFunctionThatShareAName.ts(4,12): error TS2300: Duplicate identifier 'Origin'.
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithStaticFunctionAndExportedFunctionThatShareAName.ts(8,21): error TS2300: Duplicate identifier 'Origin'.
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithStaticFunctionAndExportedFunctionThatShareAName.ts(16,16): error TS2300: Duplicate identifier 'Origin'.
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithStaticFunctionAndExportedFunctionThatShareAName.ts(20,25): error TS2300: Duplicate identifier 'Origin'.
==== tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithStaticFunctionAndExportedFunctionThatShareAName.ts (4 errors) ====
class Point {
constructor(public x: number, public y: number) { }
static Origin(): Point { return { x: 0, y: 0 }; } // unexpected error here bug 840246
~~~~~~
!!! error TS2300: Duplicate identifier 'Origin'.
}
module Point {
export function Origin() { return null; } //expected duplicate identifier error
~~~~~~
!!! Duplicate identifier 'Origin'.
!!! error TS2300: Duplicate identifier 'Origin'.
}
@@ -17,11 +25,13 @@
constructor(public x: number, public y: number) { }
static Origin(): Point { return { x: 0, y: 0 }; } // unexpected error here bug 840246
~~~~~~
!!! error TS2300: Duplicate identifier 'Origin'.
}
export module Point {
export function Origin() { return ""; }//expected duplicate identifier error
~~~~~~
!!! Duplicate identifier 'Origin'.
!!! error TS2300: Duplicate identifier 'Origin'.
}
}
@@ -1,14 +1,22 @@
==== tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithStaticVariableAndExportedVarThatShareAName.ts (2 errors) ====
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithStaticVariableAndExportedVarThatShareAName.ts(4,12): error TS2300: Duplicate identifier 'Origin'.
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithStaticVariableAndExportedVarThatShareAName.ts(8,16): error TS2300: Duplicate identifier 'Origin'.
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithStaticVariableAndExportedVarThatShareAName.ts(16,16): error TS2300: Duplicate identifier 'Origin'.
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithStaticVariableAndExportedVarThatShareAName.ts(20,20): error TS2300: Duplicate identifier 'Origin'.
==== tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithStaticVariableAndExportedVarThatShareAName.ts (4 errors) ====
class Point {
constructor(public x: number, public y: number) { }
static Origin: Point = { x: 0, y: 0 };
~~~~~~
!!! error TS2300: Duplicate identifier 'Origin'.
}
module Point {
export var Origin = ""; //expected duplicate identifier error
~~~~~~
!!! Duplicate identifier 'Origin'.
!!! error TS2300: Duplicate identifier 'Origin'.
}
@@ -17,11 +25,13 @@
constructor(public x: number, public y: number) { }
static Origin: Point = { x: 0, y: 0 };
~~~~~~
!!! error TS2300: Duplicate identifier 'Origin'.
}
export module Point {
export var Origin = ""; //expected duplicate identifier error
~~~~~~
!!! Duplicate identifier 'Origin'.
!!! error TS2300: Duplicate identifier 'Origin'.
}
}
@@ -1,3 +1,6 @@
tests/cases/conformance/internalModules/DeclarationMerging/module.ts(2,19): error TS2433: A module declaration cannot be in a different file from a class or function with which it is merged
==== tests/cases/conformance/internalModules/DeclarationMerging/class.ts (0 errors) ====
module X.Y {
export class Point {
@@ -14,7 +17,7 @@
module X.Y {
export module Point {
~~~~~
!!! A module declaration cannot be in a different file from a class or function with which it is merged
!!! error TS2433: A module declaration cannot be in a different file from a class or function with which it is merged
export var Origin = new Point(0, 0);
}
}
@@ -1,9 +1,13 @@
tests/cases/compiler/ClassDeclaration10.ts(2,4): error TS2390: Constructor implementation is missing.
tests/cases/compiler/ClassDeclaration10.ts(3,4): error TS2391: Function implementation is missing or not immediately following the declaration.
==== tests/cases/compiler/ClassDeclaration10.ts (2 errors) ====
class C {
constructor();
~~~~~~~~~~~~~~
!!! Constructor implementation is missing.
!!! error TS2390: Constructor implementation is missing.
foo();
~~~
!!! Function implementation is missing or not immediately following the declaration.
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
}
@@ -1,7 +1,10 @@
tests/cases/compiler/ClassDeclaration11.ts(2,4): error TS2390: Constructor implementation is missing.
==== tests/cases/compiler/ClassDeclaration11.ts (1 errors) ====
class C {
constructor();
~~~~~~~~~~~~~~
!!! Constructor implementation is missing.
!!! error TS2390: Constructor implementation is missing.
foo() { }
}
@@ -1,7 +1,10 @@
tests/cases/compiler/ClassDeclaration13.ts(3,4): error TS2389: Function implementation name must be 'foo'.
==== tests/cases/compiler/ClassDeclaration13.ts (1 errors) ====
class C {
foo();
bar() { }
~~~
!!! Function implementation name must be 'foo'.
!!! error TS2389: Function implementation name must be 'foo'.
}
@@ -1,9 +1,13 @@
tests/cases/compiler/ClassDeclaration14.ts(2,4): error TS2391: Function implementation is missing or not immediately following the declaration.
tests/cases/compiler/ClassDeclaration14.ts(3,4): error TS2390: Constructor implementation is missing.
==== tests/cases/compiler/ClassDeclaration14.ts (2 errors) ====
class C {
foo();
~~~
!!! Function implementation is missing or not immediately following the declaration.
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
constructor();
~~~~~~~~~~~~~~
!!! Constructor implementation is missing.
!!! error TS2390: Constructor implementation is missing.
}
@@ -1,7 +1,10 @@
tests/cases/compiler/ClassDeclaration15.ts(2,4): error TS2391: Function implementation is missing or not immediately following the declaration.
==== tests/cases/compiler/ClassDeclaration15.ts (1 errors) ====
class C {
foo();
~~~
!!! Function implementation is missing or not immediately following the declaration.
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
constructor() { }
}
@@ -1,7 +1,10 @@
tests/cases/compiler/ClassDeclaration21.ts(3,5): error TS2389: Function implementation name must be '0'.
==== tests/cases/compiler/ClassDeclaration21.ts (1 errors) ====
class C {
0();
1() { }
~
!!! Function implementation name must be '0'.
!!! error TS2389: Function implementation name must be '0'.
}
@@ -1,7 +1,10 @@
tests/cases/compiler/ClassDeclaration22.ts(3,5): error TS2389: Function implementation name must be '"foo"'.
==== tests/cases/compiler/ClassDeclaration22.ts (1 errors) ====
class C {
"foo"();
"bar"() { }
~~~~~
!!! Function implementation name must be '"foo"'.
!!! error TS2389: Function implementation name must be '"foo"'.
}
@@ -1,5 +1,8 @@
tests/cases/compiler/ClassDeclaration24.ts(1,7): error TS2414: Class name cannot be 'any'
==== tests/cases/compiler/ClassDeclaration24.ts (1 errors) ====
class any {
~~~
!!! Class name cannot be 'any'
!!! error TS2414: Class name cannot be 'any'
}
@@ -1,3 +1,7 @@
tests/cases/compiler/ClassDeclaration25.ts(6,5): error TS2391: Function implementation is missing or not immediately following the declaration.
tests/cases/compiler/ClassDeclaration25.ts(7,5): error TS2391: Function implementation is missing or not immediately following the declaration.
==== tests/cases/compiler/ClassDeclaration25.ts (2 errors) ====
interface IList<T> {
data(): T;
@@ -6,9 +10,9 @@
class List<U> implements IList<U> {
data(): U;
~~~~
!!! Function implementation is missing or not immediately following the declaration.
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
next(): string;
~~~~
!!! Function implementation is missing or not immediately following the declaration.
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
}
@@ -1,6 +1,9 @@
tests/cases/compiler/ClassDeclaration8.ts(2,3): error TS2390: Constructor implementation is missing.
==== tests/cases/compiler/ClassDeclaration8.ts (1 errors) ====
class C {
constructor();
~~~~~~~~~~~~~~
!!! Constructor implementation is missing.
!!! error TS2390: Constructor implementation is missing.
}
@@ -1,6 +1,9 @@
tests/cases/compiler/ClassDeclaration9.ts(2,4): error TS2391: Function implementation is missing or not immediately following the declaration.
==== tests/cases/compiler/ClassDeclaration9.ts (1 errors) ====
class C {
foo();
~~~
!!! Function implementation is missing or not immediately following the declaration.
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
}
@@ -1,11 +1,16 @@
tests/cases/compiler/ExportAssignment7.ts(1,14): error TS1148: Cannot compile external modules unless the '--module' flag is provided.
tests/cases/compiler/ExportAssignment7.ts(4,1): error TS2304: Cannot find name 'B'.
tests/cases/compiler/ExportAssignment7.ts(4,1): error TS2309: An export assignment cannot be used in a module with other exported elements.
==== tests/cases/compiler/ExportAssignment7.ts (3 errors) ====
export class C {
~
!!! Cannot compile external modules unless the '--module' flag is provided.
!!! error TS1148: Cannot compile external modules unless the '--module' flag is provided.
}
export = B;
~~~~~~~~~~~
!!! Cannot find name 'B'.
!!! error TS2304: Cannot find name 'B'.
~~~~~~~~~~~
!!! An export assignment cannot be used in a module with other exported elements.
!!! error TS2309: An export assignment cannot be used in a module with other exported elements.

Some files were not shown because too many files have changed in this diff Show More