mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-19 20:37:00 -05:00
Merge branch 'master' into classifier
This commit is contained in:
@@ -46,6 +46,8 @@ module ts {
|
||||
|
||||
var globals: SymbolTable = {};
|
||||
|
||||
var globalArraySymbol: Symbol;
|
||||
|
||||
var globalObjectType: ObjectType;
|
||||
var globalFunctionType: ObjectType;
|
||||
var globalArrayType: ObjectType;
|
||||
@@ -56,7 +58,6 @@ module ts {
|
||||
|
||||
var stringLiteralTypes: Map<StringLiteralType> = {};
|
||||
|
||||
var fullTypeCheck = false;
|
||||
var emitExtends = false;
|
||||
|
||||
var mergedSymbols: Symbol[] = [];
|
||||
@@ -616,8 +617,6 @@ module ts {
|
||||
members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
|
||||
}
|
||||
|
||||
// Takes a VariableDeclaration because it could be an exported var from a module (VariableDeclaration),
|
||||
// a class or object type property (PropertyDeclaration), or a parameter property (ParameterDeclaration)
|
||||
function isOptionalProperty(propertySymbol: Symbol): boolean {
|
||||
if (propertySymbol.flags & SymbolFlags.Prototype) {
|
||||
return false;
|
||||
@@ -2069,7 +2068,7 @@ module ts {
|
||||
return links.resolvedType;
|
||||
}
|
||||
|
||||
function getGlobalType(name: string, arity: number = 0): ObjectType {
|
||||
function getTypeOfGlobalSymbol(symbol: Symbol, arity: number): ObjectType {
|
||||
|
||||
function getTypeDeclaration(symbol: Symbol): Declaration {
|
||||
var declarations = symbol.declarations;
|
||||
@@ -2079,14 +2078,11 @@ module ts {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
return declaration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var symbol = resolveName(undefined, name, SymbolFlags.Type, Diagnostics.Cannot_find_global_type_0, name);
|
||||
if (!symbol) {
|
||||
return emptyObjectType;
|
||||
}
|
||||
@@ -2102,29 +2098,26 @@ module ts {
|
||||
return <ObjectType>type;
|
||||
}
|
||||
|
||||
// arrayType argument is used as a backup in case if globalArrayType is not defined
|
||||
function createArrayType(elementType: Type, arrayType?: ObjectType): Type {
|
||||
var rootType = globalArrayType || arrayType;
|
||||
return rootType !== emptyObjectType ? createTypeReference(<GenericType>rootType, [elementType]) : emptyObjectType;
|
||||
function getGlobalSymbol(name: string): Symbol {
|
||||
return resolveName(undefined, name, SymbolFlags.Type, Diagnostics.Cannot_find_global_type_0, name);
|
||||
}
|
||||
|
||||
function getGlobalType(name: string): ObjectType {
|
||||
return getTypeOfGlobalSymbol(getGlobalSymbol(name), 0);
|
||||
}
|
||||
|
||||
function createArrayType(elementType: Type): Type {
|
||||
// globalArrayType will be undefined if we get here during creation of the Array type. This for example happens if
|
||||
// user code augments the Array type with call or construct signatures that have an array type as the return type.
|
||||
// We instead use globalArraySymbol to obtain the (not yet fully constructed) Array type.
|
||||
var arrayType = globalArrayType || getDeclaredTypeOfSymbol(globalArraySymbol);
|
||||
return arrayType !== emptyObjectType ? createTypeReference(<GenericType>arrayType, [elementType]) : emptyObjectType;
|
||||
}
|
||||
|
||||
function getTypeFromArrayTypeNode(node: ArrayTypeNode): Type {
|
||||
var links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
var arrayType = globalArrayType;
|
||||
if (!arrayType) {
|
||||
// if user code contains augmentation for Array type that includes call\construct signatures with arrays as parameter\return types,
|
||||
// then we might step here then during initialization of the global Array type when globalArrayType is not yet set.
|
||||
// CODE: interface Array<T> { (): number[] }
|
||||
// in this case just resolve name 'Array' again and get declared type of symbol.
|
||||
// this type is the one that eventually should be set as 'globalArrayType'.
|
||||
// NOTE: this is specific to signatures since got signatures we realize parameter\return types.
|
||||
var arrayTypeSymbol = resolveName(node, "Array", SymbolFlags.Type, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
|
||||
Debug.assert(arrayTypeSymbol);
|
||||
arrayType = getDeclaredTypeOfSymbol(arrayTypeSymbol);
|
||||
Debug.assert(arrayType);
|
||||
}
|
||||
links.resolvedType = createArrayType(getTypeFromTypeNode(node.elementType), arrayType);
|
||||
links.resolvedType = createArrayType(getTypeFromTypeNode(node.elementType));
|
||||
}
|
||||
return links.resolvedType;
|
||||
}
|
||||
@@ -4362,7 +4355,7 @@ module ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fullTypeCheck && !(links.flags & NodeCheckFlags.TypeChecked)) {
|
||||
if (!(links.flags & NodeCheckFlags.TypeChecked)) {
|
||||
checkSignatureDeclaration(node);
|
||||
if (node.type) {
|
||||
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
|
||||
@@ -6260,7 +6253,6 @@ module ts {
|
||||
function checkSourceFile(node: SourceFile) {
|
||||
var links = getNodeLinks(node);
|
||||
if (!(links.flags & NodeCheckFlags.TypeChecked)) {
|
||||
fullTypeCheck = true;
|
||||
emitExtends = false;
|
||||
potentialThisCollisions.length = 0;
|
||||
forEach(node.statements, checkSourceElement);
|
||||
@@ -6277,7 +6269,6 @@ module ts {
|
||||
}
|
||||
if (emitExtends) links.flags |= NodeCheckFlags.EmitExtends;
|
||||
links.flags |= NodeCheckFlags.TypeChecked;
|
||||
fullTypeCheck = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6791,7 +6782,8 @@ module ts {
|
||||
getSymbolLinks(unknownSymbol).type = unknownType;
|
||||
globals[undefinedSymbol.name] = undefinedSymbol;
|
||||
// Initialize special types
|
||||
globalArrayType = getGlobalType("Array", 1);
|
||||
globalArraySymbol = getGlobalSymbol("Array");
|
||||
globalArrayType = getTypeOfGlobalSymbol(globalArraySymbol, 1);
|
||||
globalObjectType = getGlobalType("Object");
|
||||
globalFunctionType = getGlobalType("Function");
|
||||
globalStringType = getGlobalType("String");
|
||||
|
||||
@@ -89,7 +89,7 @@ module ts {
|
||||
description: Diagnostics.Do_not_emit_comments_to_output,
|
||||
},
|
||||
{
|
||||
name: "sourcemap",
|
||||
name: "sourceMap",
|
||||
type: "boolean",
|
||||
description: Diagnostics.Generates_corresponding_map_file,
|
||||
},
|
||||
|
||||
@@ -354,6 +354,80 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
// Extract comments from the given source text starting at the given position. If trailing is false, whitespace is skipped until
|
||||
// the first line break and comments between that location and the next token are returned. If trailing is true, comments occurring
|
||||
// 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 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): TextRange[] {
|
||||
var result: TextRange[];
|
||||
var collecting = trailing;
|
||||
while (true) {
|
||||
var ch = text.charCodeAt(pos);
|
||||
switch (ch) {
|
||||
case CharacterCodes.carriageReturn:
|
||||
if (text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) pos++;
|
||||
case CharacterCodes.lineFeed:
|
||||
pos++;
|
||||
if (trailing) {
|
||||
return result;
|
||||
}
|
||||
collecting = true;
|
||||
continue;
|
||||
case CharacterCodes.tab:
|
||||
case CharacterCodes.verticalTab:
|
||||
case CharacterCodes.formFeed:
|
||||
case CharacterCodes.space:
|
||||
pos++;
|
||||
continue;
|
||||
case CharacterCodes.slash:
|
||||
var nextChar = text.charCodeAt(pos + 1);
|
||||
if (nextChar === CharacterCodes.slash || nextChar === CharacterCodes.asterisk) {
|
||||
var startPos = pos;
|
||||
pos += 2;
|
||||
if (nextChar === CharacterCodes.slash) {
|
||||
while (pos < text.length) {
|
||||
if (isLineBreak(text.charCodeAt(pos))) {
|
||||
break;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (pos < text.length) {
|
||||
if (text.charCodeAt(pos) === CharacterCodes.asterisk && text.charCodeAt(pos + 1) === CharacterCodes.slash) {
|
||||
pos += 2;
|
||||
break;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
if (collecting) {
|
||||
if (!result) result = [];
|
||||
result.push({ pos: startPos, end: pos });
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpace(ch) || isLineBreak(ch))) {
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export function getLeadingComments(text: string, pos: number): TextRange[] {
|
||||
return getCommentRanges(text, pos, /*trailing*/ false);
|
||||
}
|
||||
|
||||
export function getTrailingComments(text: string, pos: number): TextRange[] {
|
||||
return getCommentRanges(text, pos, /*trailing*/ true);
|
||||
}
|
||||
|
||||
export function createScanner(languageVersion: ScriptTarget, 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
|
||||
|
||||
@@ -106,9 +106,6 @@ var sys: System = (function () {
|
||||
write(s: string): void {
|
||||
WScript.StdOut.Write(s);
|
||||
},
|
||||
writeErr(s: string): void {
|
||||
WScript.StdErr.Write(s);
|
||||
},
|
||||
readFile: readFile,
|
||||
writeFile: writeFile,
|
||||
resolvePath(path: string): string {
|
||||
@@ -195,10 +192,8 @@ var sys: System = (function () {
|
||||
newLine: _os.EOL,
|
||||
useCaseSensitiveFileNames: useCaseSensitiveFileNames,
|
||||
write(s: string): void {
|
||||
process.stdout.write(s);
|
||||
},
|
||||
writeErr(s: string): void {
|
||||
process.stderr.write(s);
|
||||
// 1 is a standard descriptor for stdout
|
||||
_fs.writeSync(1, s);
|
||||
},
|
||||
readFile: readFile,
|
||||
writeFile: writeFile,
|
||||
|
||||
@@ -254,7 +254,7 @@ module FourSlash {
|
||||
}
|
||||
});
|
||||
|
||||
this.languageServiceShimHost.addScript('lib.d.ts', Harness.Compiler.libTextMinimal);
|
||||
this.languageServiceShimHost.addDefaultLibrary();
|
||||
|
||||
|
||||
// Sneak into the language service and get its compiler so we can examine the syntax trees
|
||||
@@ -1419,8 +1419,8 @@ module FourSlash {
|
||||
for (var i = 0; i < spans.length; i++) {
|
||||
var expectedSpan = spans[i];
|
||||
var actualSpan = actual[i];
|
||||
if (expectedSpan.start !== actualSpan.start() || expectedSpan.end !== actualSpan.end()) {
|
||||
throw new Error('verifyOutliningSpans failed - span ' + (i + 1) + ' expected: (' + expectedSpan.start + ',' + expectedSpan.end + '), actual: (' + actualSpan.start() + ',' + actualSpan.end() + ')');
|
||||
if (expectedSpan.start !== actualSpan.textSpan.start() || expectedSpan.end !== actualSpan.textSpan.end()) {
|
||||
throw new Error('verifyOutliningSpans failed - span ' + (i + 1) + ' expected: (' + expectedSpan.start + ',' + expectedSpan.end + '), actual: (' + actualSpan.textSpan.start() + ',' + actualSpan.textSpan.end() + ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1467,7 +1467,7 @@ module FourSlash {
|
||||
var referenceLanguageService = referenceLanguageServiceShim.languageService;
|
||||
|
||||
// Add lib.d.ts to the reference language service
|
||||
referenceLanguageServiceShimHost.addScript('lib.d.ts', Harness.Compiler.libTextMinimal);
|
||||
referenceLanguageServiceShimHost.addDefaultLibrary();
|
||||
|
||||
for (var i = 0; i < this.testData.files.length; i++) {
|
||||
var file = this.testData.files[i];
|
||||
@@ -1885,7 +1885,7 @@ module FourSlash {
|
||||
|
||||
// Cache these between executions so we don't have to re-parse them for every test
|
||||
var fourslashSourceFile: ts.SourceFile = undefined;
|
||||
var libdtsSourceFile: ts.SourceFile = undefined;
|
||||
|
||||
export function runFourSlashTestContent(content: string, fileName: string): TestXmlData {
|
||||
// Parse out the files and their metadata
|
||||
var testData = parseTestData(content, fileName);
|
||||
@@ -1896,15 +1896,14 @@ module FourSlash {
|
||||
var fourslashFilename = 'fourslash.ts';
|
||||
var tsFn = 'tests/cases/fourslash/' + fourslashFilename;
|
||||
fourslashSourceFile = fourslashSourceFile || ts.createSourceFile(tsFn, Harness.IO.readFile(tsFn), ts.ScriptTarget.ES5, /*version*/ 0, /*isOpen*/ false);
|
||||
libdtsSourceFile = libdtsSourceFile || ts.createSourceFile('lib.d.ts', Harness.Compiler.libTextMinimal, ts.ScriptTarget.ES3, /*version*/ 0, /*isOpen*/ false);
|
||||
|
||||
var files: { [filename: string]: ts.SourceFile; } = {};
|
||||
files[fourslashFilename] = fourslashSourceFile;
|
||||
files[fileName] = ts.createSourceFile(fileName, content, ts.ScriptTarget.ES5, /*version*/ 0, /*isOpen*/ false);
|
||||
files['lib.d.ts'] = libdtsSourceFile;
|
||||
files[Harness.Compiler.defaultLibFileName] = Harness.Compiler.defaultLibSourceFile;
|
||||
|
||||
var host = Harness.Compiler.createCompilerHost(files, (fn, contents) => result = contents);
|
||||
var program = ts.createProgram([fileName, fourslashFilename], {}, host);
|
||||
var program = ts.createProgram([fourslashFilename, fileName], { out: "fourslashTestOutput.js" }, host);
|
||||
var checker = ts.createTypeChecker(program);
|
||||
checker.checkProgram();
|
||||
|
||||
|
||||
@@ -434,15 +434,15 @@ module Harness {
|
||||
export var libFolder: string;
|
||||
switch (Utils.getExecutionEnvironment()) {
|
||||
case Utils.ExecutionEnvironment.CScript:
|
||||
libFolder = Path.filePath(global['WScript'].ScriptFullName);
|
||||
libFolder = "built/local/";
|
||||
tcServicesFilename = "built/local/typescriptServices.js";
|
||||
break;
|
||||
case Utils.ExecutionEnvironment.Node:
|
||||
libFolder = (__dirname + '/');
|
||||
libFolder = "built/local/";
|
||||
tcServicesFilename = "built/local/typescriptServices.js";
|
||||
break;
|
||||
case Utils.ExecutionEnvironment.Browser:
|
||||
libFolder = "bin/";
|
||||
libFolder = "built/local/";
|
||||
tcServicesFilename = "built/local/typescriptServices.js";
|
||||
break;
|
||||
default:
|
||||
@@ -531,8 +531,8 @@ module Harness {
|
||||
}
|
||||
}
|
||||
|
||||
export var libText = IO.readFile(libFolder + "lib.d.ts");
|
||||
export var libTextMinimal = IO.readFile('bin/lib.core.d.ts');
|
||||
export var defaultLibFileName = 'lib.d.ts';
|
||||
export var defaultLibSourceFile = ts.createSourceFile(defaultLibFileName, IO.readFile(libFolder + 'lib.core.d.ts'), /*languageVersion*/ ts.ScriptTarget.ES5);
|
||||
|
||||
export function createCompilerHost(filemap: { [filename: string]: ts.SourceFile; }, writeFile: (fn: string, contents: string, writeByteOrderMark:boolean) => void): ts.CompilerHost {
|
||||
return {
|
||||
@@ -542,15 +542,15 @@ module Harness {
|
||||
if (fn in filemap) {
|
||||
return filemap[fn];
|
||||
} else {
|
||||
var lib = 'lib.d.ts';
|
||||
if (fn.substr(fn.length - lib.length) === lib) {
|
||||
return filemap[fn] = ts.createSourceFile('lib.d.ts', libTextMinimal, languageVersion);
|
||||
var lib = defaultLibFileName;
|
||||
if (fn === defaultLibFileName) {
|
||||
return defaultLibSourceFile;
|
||||
}
|
||||
// Don't throw here -- the compiler might be looking for a test that actually doesn't exist as part of the TC
|
||||
return null;
|
||||
}
|
||||
},
|
||||
getDefaultLibFilename: () => 'lib.d.ts',
|
||||
getDefaultLibFilename: () => defaultLibFileName,
|
||||
writeFile: writeFile,
|
||||
getCanonicalFileName: ts.getCanonicalFileName,
|
||||
useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames,
|
||||
|
||||
@@ -174,7 +174,7 @@ module Harness.LanguageService {
|
||||
}
|
||||
|
||||
public addDefaultLibrary() {
|
||||
this.addScript("lib.d.ts", Harness.Compiler.libText);
|
||||
this.addScript(Harness.Compiler.defaultLibFileName, Harness.Compiler.defaultLibSourceFile.text);
|
||||
}
|
||||
|
||||
public getHostIdentifier(): string {
|
||||
|
||||
@@ -136,8 +136,8 @@ class ProjectRunner extends RunnerBase {
|
||||
|
||||
function getSourceFile(filename: string, languageVersion: ts.ScriptTarget): ts.SourceFile {
|
||||
var sourceFile: ts.SourceFile = undefined;
|
||||
if (filename === 'lib.d.ts') {
|
||||
sourceFile = ts.createSourceFile('lib.d.ts', Harness.Compiler.libTextMinimal, languageVersion);
|
||||
if (filename === Harness.Compiler.defaultLibFileName) {
|
||||
sourceFile = Harness.Compiler.defaultLibSourceFile;
|
||||
}
|
||||
else {
|
||||
assert.isTrue(!ts.filter(readInputFiles, sourceFile => sourceFile.filename == filename).length, "Compiler trying to read same file again: " + filename);
|
||||
@@ -217,7 +217,7 @@ class ProjectRunner extends RunnerBase {
|
||||
function createCompilerHost(): ts.CompilerHost {
|
||||
return {
|
||||
getSourceFile: getSourceFile,
|
||||
getDefaultLibFilename: () => "lib.d.ts",
|
||||
getDefaultLibFilename: () => Harness.Compiler.defaultLibFileName,
|
||||
writeFile: writeFile,
|
||||
getCurrentDirectory: getCurrentDirectory,
|
||||
getCanonicalFileName: ts.getCanonicalFileName,
|
||||
|
||||
68
src/lib/core.d.ts
vendored
68
src/lib/core.d.ts
vendored
@@ -302,13 +302,13 @@ interface String {
|
||||
* Matches a string with a regular expression, and returns an array containing the results of that search.
|
||||
* @param regexp A variable name or string literal containing the regular expression pattern and flags.
|
||||
*/
|
||||
match(regexp: string): string[];
|
||||
match(regexp: string): RegExpMatchArray;
|
||||
|
||||
/**
|
||||
* Matches a string with a regular expression, and returns an array containing the results of that search.
|
||||
* @param regexp A regular expression object that contains the regular expression pattern and applicable flags.
|
||||
*/
|
||||
match(regexp: RegExp): string[];
|
||||
match(regexp: RegExp): RegExpMatchArray;
|
||||
|
||||
/**
|
||||
* Replaces text in a string, using a regular expression or search string.
|
||||
@@ -775,38 +775,15 @@ declare var Date: {
|
||||
now(): number;
|
||||
}
|
||||
|
||||
interface RegExpExecArray {
|
||||
[index: number]: string;
|
||||
length: number;
|
||||
|
||||
index: number;
|
||||
input: string;
|
||||
|
||||
toString(): string;
|
||||
toLocaleString(): string;
|
||||
concat(...items: string[][]): string[];
|
||||
join(separator?: string): string;
|
||||
pop(): string;
|
||||
push(...items: string[]): number;
|
||||
reverse(): string[];
|
||||
shift(): string;
|
||||
slice(start?: number, end?: number): string[];
|
||||
sort(compareFn?: (a: string, b: string) => number): string[];
|
||||
splice(start: number): string[];
|
||||
splice(start: number, deleteCount: number, ...items: string[]): string[];
|
||||
unshift(...items: string[]): number;
|
||||
|
||||
indexOf(searchElement: string, fromIndex?: number): number;
|
||||
lastIndexOf(searchElement: string, fromIndex?: number): number;
|
||||
every(callbackfn: (value: string, index: number, array: string[]) => boolean, thisArg?: any): boolean;
|
||||
some(callbackfn: (value: string, index: number, array: string[]) => boolean, thisArg?: any): boolean;
|
||||
forEach(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void;
|
||||
map(callbackfn: (value: string, index: number, array: string[]) => any, thisArg?: any): any[];
|
||||
filter(callbackfn: (value: string, index: number, array: string[]) => boolean, thisArg?: any): string[];
|
||||
reduce(callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: string[]) => any, initialValue?: any): any;
|
||||
reduceRight(callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: string[]) => any, initialValue?: any): any;
|
||||
interface RegExpMatchArray extends Array<string> {
|
||||
index?: number;
|
||||
input?: string;
|
||||
}
|
||||
|
||||
interface RegExpExecArray extends Array<string> {
|
||||
index: number;
|
||||
input: string;
|
||||
}
|
||||
|
||||
interface RegExp {
|
||||
/**
|
||||
@@ -964,11 +941,24 @@ declare var JSON: JSON;
|
||||
/////////////////////////////
|
||||
|
||||
interface Array<T> {
|
||||
/**
|
||||
* Gets or sets the length of the array. This is a number one higher than the highest element defined in an array.
|
||||
*/
|
||||
length: number;
|
||||
/**
|
||||
* Returns a string representation of an array.
|
||||
*/
|
||||
toString(): string;
|
||||
toLocaleString(): string;
|
||||
/**
|
||||
* Appends new elements to an array, and returns the new length of the array.
|
||||
* @param items New elements of the Array.
|
||||
*/
|
||||
push(...items: T[]): number;
|
||||
/**
|
||||
* Removes the last element from an array and returns it.
|
||||
*/
|
||||
pop(): T;
|
||||
/**
|
||||
* Combines two or more arrays.
|
||||
* @param items Additional items to add to the end of array1.
|
||||
@@ -984,15 +974,6 @@ interface Array<T> {
|
||||
* @param separator A string used to separate one element of an array from the next in the resulting String. If omitted, the array elements are separated with a comma.
|
||||
*/
|
||||
join(separator?: string): string;
|
||||
/**
|
||||
* Removes the last element from an array and returns it.
|
||||
*/
|
||||
pop(): T;
|
||||
/**
|
||||
* Appends new elements to an array, and returns the new length of the array.
|
||||
* @param items New elements of the Array.
|
||||
*/
|
||||
push(...items: T[]): number;
|
||||
/**
|
||||
* Reverses the elements in an Array.
|
||||
*/
|
||||
@@ -1109,11 +1090,6 @@ interface Array<T> {
|
||||
*/
|
||||
reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;
|
||||
|
||||
/**
|
||||
* Gets or sets the length of the array. This is a number one higher than the highest element defined in an array.
|
||||
*/
|
||||
length: number;
|
||||
|
||||
[n: number]: T;
|
||||
}
|
||||
declare var Array: {
|
||||
|
||||
@@ -49,7 +49,7 @@ module TypeScript {
|
||||
return isNoDefaultLibRegex.exec(comment);
|
||||
}
|
||||
|
||||
export var tripleSlashReferenceRegExp = /^(\/\/\/\s*<reference\s+path=)('|")(.+?)\2\s*(static=('|")(.+?)\2\s*)*\/>/;
|
||||
export var tripleSlashReferenceRegExp = /^(\/\/\/\s*<reference\s+path=)('|")(.+?)\2\s*(static=('|")(.+?)\5\s*)*\/>/;
|
||||
|
||||
function getFileReferenceFromReferencePath(fileName: string, text: ISimpleText, position: number, comment: string, diagnostics: Diagnostic[]): IFileReference {
|
||||
// First, just see if they've written: /// <reference\s+
|
||||
|
||||
@@ -15,95 +15,73 @@
|
||||
|
||||
///<reference path='references.ts' />
|
||||
|
||||
module TypeScript.Services {
|
||||
export class OutliningElementsCollector extends TypeScript.DepthLimitedWalker {
|
||||
// The maximum depth for collecting spans; this will cause us to miss deeply nested function/modules spans,
|
||||
// but will guarantee performance will not be closely tied to tree depth.
|
||||
private static MaximumDepth: number = 10;
|
||||
private inObjectLiteralExpression: boolean = false;
|
||||
module ts {
|
||||
|
||||
private elements: TypeScript.TextSpan[] = [];
|
||||
export interface OutliningSpan {
|
||||
/**
|
||||
* @param textSpan The span of the document to actually collapse.
|
||||
* @param hintSpan The span of the document to display when the user hovers over the
|
||||
* collapsed span.
|
||||
* @param bannerText The text to display in the editor for the collapsed region.
|
||||
* @param autoCollapse Whether or not this region should be automatically collapsed when
|
||||
* the 'Collapse to Definitions' command is invoked.
|
||||
*/
|
||||
textSpan: TypeScript.TextSpan;
|
||||
hintSpan: TypeScript.TextSpan;
|
||||
bannerText: string;
|
||||
autoCollapse: boolean;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super(OutliningElementsCollector.MaximumDepth);
|
||||
}
|
||||
export module OutliningElementsCollector {
|
||||
export function collectElements(sourceFile: SourceFile): OutliningSpan[] {
|
||||
var elements: OutliningSpan[] = [];
|
||||
|
||||
public visitClassDeclaration(node: TypeScript.ClassDeclarationSyntax): void {
|
||||
this.addOutlineRange(node, node.openBraceToken, node.closeBraceToken);
|
||||
super.visitClassDeclaration(node);
|
||||
}
|
||||
|
||||
public visitInterfaceDeclaration(node: TypeScript.InterfaceDeclarationSyntax): void {
|
||||
this.addOutlineRange(node, node.body.openBraceToken, node.body.closeBraceToken);
|
||||
super.visitInterfaceDeclaration(node);
|
||||
}
|
||||
|
||||
public visitModuleDeclaration(node: TypeScript.ModuleDeclarationSyntax): void {
|
||||
this.addOutlineRange(node, node.openBraceToken, node.closeBraceToken);
|
||||
super.visitModuleDeclaration(node);
|
||||
}
|
||||
|
||||
public visitEnumDeclaration(node: TypeScript.EnumDeclarationSyntax): void {
|
||||
this.addOutlineRange(node, node.openBraceToken, node.closeBraceToken);
|
||||
super.visitEnumDeclaration(node);
|
||||
}
|
||||
|
||||
public visitFunctionDeclaration(node: TypeScript.FunctionDeclarationSyntax): void {
|
||||
this.addOutlineRange(node, node.block, node.block);
|
||||
super.visitFunctionDeclaration(node);
|
||||
}
|
||||
|
||||
public visitFunctionExpression(node: TypeScript.FunctionExpressionSyntax): void {
|
||||
this.addOutlineRange(node, node.block, node.block);
|
||||
super.visitFunctionExpression(node);
|
||||
}
|
||||
|
||||
public visitConstructorDeclaration(node: TypeScript.ConstructorDeclarationSyntax): void {
|
||||
this.addOutlineRange(node, node.block, node.block);
|
||||
super.visitConstructorDeclaration(node);
|
||||
}
|
||||
|
||||
public visitMemberFunctionDeclaration(node: TypeScript.MemberFunctionDeclarationSyntax): void {
|
||||
this.addOutlineRange(node, node.block, node.block);
|
||||
super.visitMemberFunctionDeclaration(node);
|
||||
}
|
||||
|
||||
public visitGetAccessor(node: TypeScript.GetAccessorSyntax): void {
|
||||
if (!this.inObjectLiteralExpression) {
|
||||
this.addOutlineRange(node, node.block, node.block);
|
||||
function addOutlineRange(hintSpanNode: Node, startElement: Node, endElement: Node) {
|
||||
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
|
||||
};
|
||||
elements.push(span);
|
||||
}
|
||||
}
|
||||
super.visitGetAccessor(node);
|
||||
}
|
||||
|
||||
public visitSetAccessor(node: TypeScript.SetAccessorSyntax): void {
|
||||
if (!this.inObjectLiteralExpression) {
|
||||
this.addOutlineRange(node, node.block, node.block);
|
||||
var depth = 0;
|
||||
var maxDepth = 20;
|
||||
function walk(n: Node): void {
|
||||
if (depth > maxDepth) {
|
||||
return;
|
||||
}
|
||||
switch (n.kind) {
|
||||
case SyntaxKind.Block:
|
||||
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);
|
||||
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);
|
||||
break;
|
||||
}
|
||||
depth++;
|
||||
forEachChild(n, walk);
|
||||
depth--;
|
||||
}
|
||||
super.visitSetAccessor(node);
|
||||
}
|
||||
|
||||
public visitObjectLiteralExpression(node: TypeScript.ObjectLiteralExpressionSyntax): void {
|
||||
var savedInObjectLiteralExpression = this.inObjectLiteralExpression;
|
||||
this.inObjectLiteralExpression = true;
|
||||
super.visitObjectLiteralExpression(node);
|
||||
this.inObjectLiteralExpression = savedInObjectLiteralExpression;
|
||||
}
|
||||
|
||||
private addOutlineRange(node: TypeScript.ISyntaxNode, startElement: TypeScript.ISyntaxNodeOrToken, endElement: TypeScript.ISyntaxNodeOrToken) {
|
||||
if (startElement && endElement && !isShared(startElement) && !isShared(endElement)) {
|
||||
// Compute the position
|
||||
var start = TypeScript.start(startElement);
|
||||
var end = TypeScript.end(endElement);
|
||||
|
||||
// Push the new range
|
||||
this.elements.push(TypeScript.TextSpan.fromBounds(start, end));
|
||||
}
|
||||
}
|
||||
|
||||
public static collectElements(node: TypeScript.SourceUnitSyntax): TypeScript.TextSpan[] {
|
||||
var collector = new OutliningElementsCollector();
|
||||
visitNodeOrToken(collector, node);
|
||||
return collector.elements;
|
||||
walk(sourceFile);
|
||||
return elements;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -416,14 +416,14 @@ module ts {
|
||||
? TypeScript.Parser.parse(this.filename, text, this.languageVersion, TypeScript.isDTSFile(this.filename))
|
||||
: TypeScript.IncrementalParser.parse(oldSyntaxTree, textChangeRange, text);
|
||||
|
||||
return SourceFileObject.createSourceFileObject(this.languageVersion, this.filename, scriptSnapshot, version, isOpen, newSyntaxTree);
|
||||
return SourceFileObject.createSourceFileObject(this.filename, scriptSnapshot, this.languageVersion, version, isOpen, newSyntaxTree);
|
||||
}
|
||||
|
||||
public static createSourceFileObject(languageVersion: ScriptTarget, filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, version: number, isOpen: boolean, syntaxTree: TypeScript.SyntaxTree) {
|
||||
var newSoruceFile = <SourceFileObject><any>createSourceFile(filename, scriptSnapshot.getText(0, scriptSnapshot.getLength()), languageVersion, version, isOpen);
|
||||
newSoruceFile.scriptSnapshot = scriptSnapshot;
|
||||
newSoruceFile.syntaxTree = syntaxTree;
|
||||
return newSoruceFile;
|
||||
public static createSourceFileObject(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, languageVersion: ScriptTarget, version: number, isOpen: boolean, syntaxTree?: TypeScript.SyntaxTree) {
|
||||
var newSourceFile = <SourceFileObject><any>createSourceFile(filename, scriptSnapshot.getText(0, scriptSnapshot.getLength()), languageVersion, version, isOpen);
|
||||
newSourceFile.scriptSnapshot = scriptSnapshot;
|
||||
newSourceFile.syntaxTree = syntaxTree;
|
||||
return newSourceFile;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -482,7 +482,7 @@ module ts {
|
||||
getNavigateToItems(searchValue: string): NavigateToItem[];
|
||||
getScriptLexicalStructure(fileName: string): NavigateToItem[];
|
||||
|
||||
getOutliningRegions(fileName: string): TypeScript.TextSpan[];
|
||||
getOutliningRegions(fileName: string): OutliningSpan[];
|
||||
getBraceMatchingAtPosition(fileName: string, position: number): TypeScript.TextSpan[];
|
||||
getIndentationAtPosition(fileName: string, position: number, options: EditorOptions): number;
|
||||
|
||||
@@ -697,7 +697,7 @@ module ts {
|
||||
isOpen: boolean): SourceFile;
|
||||
|
||||
updateDocument(
|
||||
soruceFile: SourceFile,
|
||||
sourceFile: SourceFile,
|
||||
filename: string,
|
||||
compilationSettings: CompilerOptions,
|
||||
scriptSnapshot: TypeScript.IScriptSnapshot,
|
||||
@@ -962,6 +962,7 @@ module ts {
|
||||
// currently edited file.
|
||||
private currentfilename: string = "";
|
||||
private currentFileVersion: number = -1;
|
||||
private currentSourceFile: SourceFile = null;
|
||||
private currentFileSyntaxTree: TypeScript.SyntaxTree = null;
|
||||
private currentFileScriptSnapshot: TypeScript.IScriptSnapshot = null;
|
||||
|
||||
@@ -969,32 +970,71 @@ module ts {
|
||||
this.hostCache = new HostCache(host);
|
||||
}
|
||||
|
||||
public getCurrentFileSyntaxTree(filename: string): TypeScript.SyntaxTree {
|
||||
private initialize(filename: string) {
|
||||
// ensure that both source file and syntax tree are either initialized or not initialized
|
||||
Debug.assert(!!this.currentFileSyntaxTree === !!this.currentSourceFile);
|
||||
this.hostCache = new HostCache(this.host);
|
||||
|
||||
var version = this.hostCache.getVersion(filename);
|
||||
var syntaxTree: TypeScript.SyntaxTree = null;
|
||||
var sourceFile: SourceFile;
|
||||
|
||||
if (this.currentFileSyntaxTree === null || this.currentfilename !== filename) {
|
||||
var scriptSnapshot = this.hostCache.getScriptSnapshot(filename);
|
||||
syntaxTree = this.createSyntaxTree(filename, scriptSnapshot);
|
||||
sourceFile = createSourceFileFromScriptSnapshot(filename, scriptSnapshot, getDefaultCompilerOptions(), version, /*isOpen*/ true);
|
||||
|
||||
fixupParentReferences(sourceFile);
|
||||
}
|
||||
else if (this.currentFileVersion !== version) {
|
||||
var scriptSnapshot = this.hostCache.getScriptSnapshot(filename);
|
||||
syntaxTree = this.updateSyntaxTree(filename, scriptSnapshot, this.currentFileSyntaxTree, this.currentFileVersion);
|
||||
|
||||
var editRange = this.hostCache.getScriptTextChangeRangeSinceVersion(filename, this.currentFileVersion);
|
||||
sourceFile = !editRange
|
||||
? createSourceFileFromScriptSnapshot(filename, scriptSnapshot, getDefaultCompilerOptions(), version, /*isOpen*/ true)
|
||||
: this.currentSourceFile.update(scriptSnapshot, version, /*isOpen*/ true, editRange);
|
||||
|
||||
fixupParentReferences(sourceFile);
|
||||
}
|
||||
|
||||
if (syntaxTree !== null) {
|
||||
Debug.assert(sourceFile);
|
||||
// All done, ensure state is up to date
|
||||
this.currentFileScriptSnapshot = scriptSnapshot;
|
||||
this.currentFileVersion = version;
|
||||
this.currentfilename = filename;
|
||||
this.currentFileSyntaxTree = syntaxTree;
|
||||
this.currentSourceFile = sourceFile;
|
||||
}
|
||||
|
||||
function fixupParentReferences(sourceFile: SourceFile) {
|
||||
// normally parent references are set during binding.
|
||||
// however here SourceFile data is used only for syntactic features so running the whole binding process is an overhead.
|
||||
// walk over the nodes and set parent references
|
||||
var parent: Node = sourceFile;
|
||||
function walk(n: Node): void {
|
||||
n.parent = parent;
|
||||
|
||||
var saveParent = parent;
|
||||
parent = n;
|
||||
forEachChild(n, walk);
|
||||
parent = saveParent;
|
||||
}
|
||||
forEachChild(sourceFile, walk);
|
||||
}
|
||||
}
|
||||
|
||||
public getCurrentFileSyntaxTree(filename: string): TypeScript.SyntaxTree {
|
||||
this.initialize(filename);
|
||||
return this.currentFileSyntaxTree;
|
||||
}
|
||||
|
||||
public getCurrentSourceFile(filename: string): SourceFile {
|
||||
this.initialize(filename);
|
||||
return this.currentSourceFile;
|
||||
}
|
||||
|
||||
public getCurrentScriptSnapshot(filename: string): TypeScript.IScriptSnapshot {
|
||||
// update currentFileScriptSnapshot as a part of 'getCurrentFileSyntaxTree' call
|
||||
this.getCurrentFileSyntaxTree(filename);
|
||||
@@ -1093,6 +1133,10 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function createSourceFileFromScriptSnapshot(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, settings: CompilerOptions, version: number, isOpen: boolean) {
|
||||
return SourceFileObject.createSourceFileObject(filename, scriptSnapshot, settings.target, version, isOpen);
|
||||
}
|
||||
|
||||
export function createDocumentRegistry(): DocumentRegistry {
|
||||
var buckets: Map<Map<DocumentRegistryEntry>> = {};
|
||||
|
||||
@@ -1112,19 +1156,19 @@ module ts {
|
||||
function reportStats() {
|
||||
var bucketInfoArray = Object.keys(buckets).filter(name => name && name.charAt(0) === '_').map(name => {
|
||||
var entries = lookUp(buckets, name);
|
||||
var soruceFiles: { name: string; refCount: number; references: string[]; }[] = [];
|
||||
var sourceFiles: { name: string; refCount: number; references: string[]; }[] = [];
|
||||
for (var i in entries) {
|
||||
var entry = entries[i];
|
||||
soruceFiles.push({
|
||||
sourceFiles.push({
|
||||
name: i,
|
||||
refCount: entry.refCount,
|
||||
references: entry.owners.slice(0)
|
||||
});
|
||||
}
|
||||
soruceFiles.sort((x, y) => y.refCount - x.refCount);
|
||||
sourceFiles.sort((x, y) => y.refCount - x.refCount);
|
||||
return {
|
||||
bucket: name,
|
||||
sourceFiles: soruceFiles
|
||||
sourceFiles: sourceFiles
|
||||
};
|
||||
});
|
||||
return JSON.stringify(bucketInfoArray, null, 2);
|
||||
@@ -1140,7 +1184,7 @@ module ts {
|
||||
var bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true);
|
||||
var entry = lookUp(bucket, filename);
|
||||
if (!entry) {
|
||||
var sourceFile = createSourceFile(filename, scriptSnapshot.getText(0, scriptSnapshot.getLength()), compilationSettings.target, version, isOpen);
|
||||
var sourceFile = createSourceFileFromScriptSnapshot(filename, scriptSnapshot, compilationSettings, version, isOpen);
|
||||
|
||||
bucket[filename] = entry = {
|
||||
sourceFile: sourceFile,
|
||||
@@ -2024,6 +2068,12 @@ module ts {
|
||||
return syntaxTreeCache.getCurrentFileSyntaxTree(filename);
|
||||
}
|
||||
|
||||
function getCurrentSourceFile(filename: string): SourceFile {
|
||||
filename = TypeScript.switchToForwardSlashes(filename);
|
||||
var currentSourceFile = syntaxTreeCache.getCurrentSourceFile(filename);
|
||||
return currentSourceFile;
|
||||
}
|
||||
|
||||
function getNameOrDottedNameSpan(filename: string, startPos: number, endPos: number): SpanInfo {
|
||||
function getTypeInfoEligiblePath(filename: string, position: number, isConstructorValidPosition: boolean) {
|
||||
var sourceUnit = syntaxTreeCache.getCurrentFileSyntaxTree(filename).sourceUnit();
|
||||
@@ -2097,11 +2147,11 @@ module ts {
|
||||
return items;
|
||||
}
|
||||
|
||||
function getOutliningRegions(filename: string) {
|
||||
function getOutliningRegions(filename: string): OutliningSpan[] {
|
||||
// doesn't use compiler - no need to synchronize with host
|
||||
filename = TypeScript.switchToForwardSlashes(filename);
|
||||
var syntaxTree = getSyntaxTree(filename);
|
||||
return TypeScript.Services.OutliningElementsCollector.collectElements(syntaxTree.sourceUnit());
|
||||
var sourceFile = getCurrentSourceFile(filename);
|
||||
return OutliningElementsCollector.collectElements(sourceFile);
|
||||
}
|
||||
|
||||
function getBraceMatchingAtPosition(filename: string, position: number) {
|
||||
|
||||
@@ -726,7 +726,10 @@ module ts {
|
||||
"getOutliningRegions(\"" + fileName + "\")",
|
||||
() => {
|
||||
var items = this.languageService.getOutliningRegions(fileName);
|
||||
return items;
|
||||
// return just the part of data that language service v2 can understand
|
||||
// language service v2 will use the entire OutliningSpan
|
||||
var spans = map(items, i => i.textSpan);
|
||||
return spans;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user