mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
merge with master, accept baselines
This commit is contained in:
+70
-51
@@ -1,7 +1,7 @@
|
||||
/// <reference path="parser.ts"/>
|
||||
|
||||
module ts {
|
||||
/* @internal */ export var bindTime = 0;
|
||||
/* @internal */ export let bindTime = 0;
|
||||
|
||||
export const enum ModuleInstanceState {
|
||||
NonInstantiated = 0,
|
||||
@@ -25,7 +25,7 @@ module ts {
|
||||
}
|
||||
// 4. other uninstantiated module declarations.
|
||||
else if (node.kind === SyntaxKind.ModuleBlock) {
|
||||
var state = ModuleInstanceState.NonInstantiated;
|
||||
let state = ModuleInstanceState.NonInstantiated;
|
||||
forEachChild(node, n => {
|
||||
switch (getModuleInstanceState(n)) {
|
||||
case ModuleInstanceState.NonInstantiated:
|
||||
@@ -52,18 +52,18 @@ module ts {
|
||||
}
|
||||
|
||||
export function bindSourceFile(file: SourceFile): void {
|
||||
var start = new Date().getTime();
|
||||
let start = new Date().getTime();
|
||||
bindSourceFileWorker(file);
|
||||
bindTime += new Date().getTime() - start;
|
||||
}
|
||||
|
||||
function bindSourceFileWorker(file: SourceFile): void {
|
||||
var parent: Node;
|
||||
var container: Node;
|
||||
var blockScopeContainer: Node;
|
||||
var lastContainer: Node;
|
||||
var symbolCount = 0;
|
||||
var Symbol = objectAllocator.getSymbolConstructor();
|
||||
let parent: Node;
|
||||
let container: Node;
|
||||
let blockScopeContainer: Node;
|
||||
let lastContainer: Node;
|
||||
let symbolCount = 0;
|
||||
let Symbol = objectAllocator.getSymbolConstructor();
|
||||
|
||||
if (!file.locals) {
|
||||
file.locals = {};
|
||||
@@ -103,7 +103,7 @@ module ts {
|
||||
return '"' + (<LiteralExpression>node.name).text + '"';
|
||||
}
|
||||
if (node.name.kind === SyntaxKind.ComputedPropertyName) {
|
||||
var nameExpression = (<ComputedPropertyName>node.name).expression;
|
||||
let nameExpression = (<ComputedPropertyName>node.name).expression;
|
||||
Debug.assert(isWellKnownSymbolSyntactically(nameExpression));
|
||||
return getPropertyNameForKnownSymbolName((<PropertyAccessExpression>nameExpression).name.text);
|
||||
}
|
||||
@@ -120,6 +120,13 @@ module ts {
|
||||
return "__new";
|
||||
case SyntaxKind.IndexSignature:
|
||||
return "__index";
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
return "__export";
|
||||
case SyntaxKind.ExportAssignment:
|
||||
return "default";
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
return node.flags & NodeFlags.Default ? "default" : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,9 +137,12 @@ module ts {
|
||||
function declareSymbol(symbols: SymbolTable, parent: Symbol, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags): Symbol {
|
||||
Debug.assert(!hasDynamicName(node));
|
||||
|
||||
var name = getDeclarationName(node);
|
||||
// The exported symbol for an export default function/class node is always named "default"
|
||||
let name = node.flags & NodeFlags.Default && parent ? "default" : getDeclarationName(node);
|
||||
|
||||
let symbol: Symbol;
|
||||
if (name !== undefined) {
|
||||
var symbol = hasProperty(symbols, name) ? symbols[name] : (symbols[name] = createSymbol(0, name));
|
||||
symbol = hasProperty(symbols, name) ? symbols[name] : (symbols[name] = createSymbol(0, name));
|
||||
if (symbol.flags & excludes) {
|
||||
if (node.name) {
|
||||
node.name.parent = node;
|
||||
@@ -140,14 +150,14 @@ module ts {
|
||||
|
||||
// Report errors every position with duplicate declaration
|
||||
// Report errors on previous encountered declarations
|
||||
var message = symbol.flags & SymbolFlags.BlockScopedVariable
|
||||
let message = symbol.flags & SymbolFlags.BlockScopedVariable
|
||||
? Diagnostics.Cannot_redeclare_block_scoped_variable_0
|
||||
: Diagnostics.Duplicate_identifier_0;
|
||||
|
||||
forEach(symbol.declarations, declaration => {
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(declaration.name, message, getDisplayName(declaration)));
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration)));
|
||||
});
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(node.name, message, getDisplayName(node)));
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(node.name || node, message, getDisplayName(node)));
|
||||
|
||||
symbol = createSymbol(0, name);
|
||||
}
|
||||
@@ -163,7 +173,7 @@ module ts {
|
||||
// Every class automatically contains a static property member named 'prototype',
|
||||
// the type of which is an instantiation of the class type with type Any supplied as a type argument for each type parameter.
|
||||
// It is an error to explicitly declare a static property member with the name 'prototype'.
|
||||
var prototypeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Prototype, "prototype");
|
||||
let prototypeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Prototype, "prototype");
|
||||
if (hasProperty(symbol.exports, prototypeSymbol.name)) {
|
||||
if (node.name) {
|
||||
node.name.parent = node;
|
||||
@@ -187,8 +197,8 @@ module ts {
|
||||
}
|
||||
|
||||
function declareModuleMember(node: Declaration, symbolKind: SymbolFlags, symbolExcludes: SymbolFlags) {
|
||||
var hasExportModifier = getCombinedNodeFlags(node) & NodeFlags.Export;
|
||||
if (symbolKind & SymbolFlags.Import) {
|
||||
let hasExportModifier = getCombinedNodeFlags(node) & NodeFlags.Export;
|
||||
if (symbolKind & SymbolFlags.Alias) {
|
||||
if (node.kind === SyntaxKind.ExportSpecifier || (node.kind === SyntaxKind.ImportEqualsDeclaration && hasExportModifier)) {
|
||||
declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
|
||||
}
|
||||
@@ -209,10 +219,10 @@ module ts {
|
||||
// but return the export symbol (by calling getExportSymbolOfValueSymbolIfExported). That way
|
||||
// when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope.
|
||||
if (hasExportModifier || isAmbientContext(container)) {
|
||||
var exportKind = (symbolKind & SymbolFlags.Value ? SymbolFlags.ExportValue : 0) |
|
||||
let exportKind = (symbolKind & SymbolFlags.Value ? SymbolFlags.ExportValue : 0) |
|
||||
(symbolKind & SymbolFlags.Type ? SymbolFlags.ExportType : 0) |
|
||||
(symbolKind & SymbolFlags.Namespace ? SymbolFlags.ExportNamespace : 0);
|
||||
var local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes);
|
||||
let local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes);
|
||||
local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
|
||||
node.localSymbol = local;
|
||||
}
|
||||
@@ -229,9 +239,9 @@ module ts {
|
||||
node.locals = {};
|
||||
}
|
||||
|
||||
var saveParent = parent;
|
||||
var saveContainer = container;
|
||||
var savedBlockScopeContainer = blockScopeContainer;
|
||||
let saveParent = parent;
|
||||
let saveContainer = container;
|
||||
let savedBlockScopeContainer = blockScopeContainer;
|
||||
parent = node;
|
||||
if (symbolKind & SymbolFlags.IsContainer) {
|
||||
container = node;
|
||||
@@ -306,31 +316,25 @@ module ts {
|
||||
bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes, /*isBlockScopeContainer*/ true);
|
||||
}
|
||||
else {
|
||||
var state = getModuleInstanceState(node);
|
||||
let state = getModuleInstanceState(node);
|
||||
if (state === ModuleInstanceState.NonInstantiated) {
|
||||
bindDeclaration(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes, /*isBlockScopeContainer*/ true);
|
||||
}
|
||||
else {
|
||||
bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes, /*isBlockScopeContainer*/ true);
|
||||
if (state === ModuleInstanceState.ConstEnumOnly) {
|
||||
// mark value module as module that contains only enums
|
||||
node.symbol.constEnumOnlyModule = true;
|
||||
let currentModuleIsConstEnumOnly = state === ModuleInstanceState.ConstEnumOnly;
|
||||
if (node.symbol.constEnumOnlyModule === undefined) {
|
||||
// non-merged case - use the current state
|
||||
node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly;
|
||||
}
|
||||
else if (node.symbol.constEnumOnlyModule) {
|
||||
// const only value module was merged with instantiated module - reset flag
|
||||
node.symbol.constEnumOnlyModule = false;
|
||||
else {
|
||||
// merged case: module is const enum only if all its pieces are non-instantiated or const enum
|
||||
node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function bindExportDeclaration(node: ExportDeclaration) {
|
||||
if (!node.exportClause) {
|
||||
((<ExportContainer>container).exportStars || ((<ExportContainer>container).exportStars = [])).push(node);
|
||||
}
|
||||
bindChildren(node, 0, /*isBlockScopeContainer*/ false);
|
||||
}
|
||||
|
||||
function bindFunctionOrConstructorType(node: SignatureDeclaration) {
|
||||
// For a given function symbol "<...>(...) => T" we want to generate a symbol identical
|
||||
// to the one we would get for: { <...>(...): T }
|
||||
@@ -339,18 +343,18 @@ module ts {
|
||||
// symbol as its sole member. To the rest of the system, this symbol will be indistinguishable
|
||||
// from an actual type literal symbol you would have gotten had you used the long form.
|
||||
|
||||
var symbol = createSymbol(SymbolFlags.Signature, getDeclarationName(node));
|
||||
let symbol = createSymbol(SymbolFlags.Signature, getDeclarationName(node));
|
||||
addDeclarationToSymbol(symbol, node, SymbolFlags.Signature);
|
||||
bindChildren(node, SymbolFlags.Signature, /*isBlockScopeContainer:*/ false);
|
||||
|
||||
var typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type");
|
||||
let typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type");
|
||||
addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral);
|
||||
typeLiteralSymbol.members = {};
|
||||
typeLiteralSymbol.members[node.kind === SyntaxKind.FunctionType ? "__call" : "__new"] = symbol
|
||||
}
|
||||
|
||||
function bindAnonymousDeclaration(node: Declaration, symbolKind: SymbolFlags, name: string, isBlockScopeContainer: boolean) {
|
||||
var symbol = createSymbol(symbolKind, name);
|
||||
let symbol = createSymbol(symbolKind, name);
|
||||
addDeclarationToSymbol(symbol, node, symbolKind);
|
||||
bindChildren(node, symbolKind, isBlockScopeContainer);
|
||||
}
|
||||
@@ -484,19 +488,34 @@ module ts {
|
||||
case SyntaxKind.NamespaceImport:
|
||||
case SyntaxKind.ImportSpecifier:
|
||||
case SyntaxKind.ExportSpecifier:
|
||||
bindDeclaration(<Declaration>node, SymbolFlags.Import, SymbolFlags.ImportExcludes, /*isBlockScopeContainer*/ false);
|
||||
break;
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
bindExportDeclaration(<ExportDeclaration>node);
|
||||
bindDeclaration(<Declaration>node, SymbolFlags.Alias, SymbolFlags.AliasExcludes, /*isBlockScopeContainer*/ false);
|
||||
break;
|
||||
case SyntaxKind.ImportClause:
|
||||
if ((<ImportClause>node).name) {
|
||||
bindDeclaration(<Declaration>node, SymbolFlags.Import, SymbolFlags.ImportExcludes, /*isBlockScopeContainer*/ false);
|
||||
bindDeclaration(<Declaration>node, SymbolFlags.Alias, SymbolFlags.AliasExcludes, /*isBlockScopeContainer*/ false);
|
||||
}
|
||||
else {
|
||||
bindChildren(node, 0, /*isBlockScopeContainer*/ false);
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
if (!(<ExportDeclaration>node).exportClause) {
|
||||
// All export * declarations are collected in an __export symbol
|
||||
declareSymbol(container.symbol.exports, container.symbol, <Declaration>node, SymbolFlags.ExportStar, 0);
|
||||
}
|
||||
bindChildren(node, 0, /*isBlockScopeContainer*/ false);
|
||||
break;
|
||||
case SyntaxKind.ExportAssignment:
|
||||
if ((<ExportAssignment>node).expression && (<ExportAssignment>node).expression.kind === SyntaxKind.Identifier) {
|
||||
// An export default clause with an identifier exports all meanings of that identifier
|
||||
declareSymbol(container.symbol.exports, container.symbol, <Declaration>node, SymbolFlags.Alias, SymbolFlags.AliasExcludes);
|
||||
}
|
||||
else {
|
||||
// An export default clause with an expression exports a value
|
||||
declareSymbol(container.symbol.exports, container.symbol, <Declaration>node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
|
||||
}
|
||||
bindChildren(node, 0, /*isBlockScopeContainer*/ false);
|
||||
break;
|
||||
case SyntaxKind.SourceFile:
|
||||
if (isExternalModule(<SourceFile>node)) {
|
||||
bindAnonymousDeclaration(<SourceFile>node, SymbolFlags.ValueModule, '"' + removeFileExtension((<SourceFile>node).fileName) + '"', /*isBlockScopeContainer*/ true);
|
||||
@@ -508,20 +527,20 @@ module ts {
|
||||
// Otherwise this won't be considered as redeclaration of a block scoped local:
|
||||
// function foo() {
|
||||
// let x;
|
||||
// var x;
|
||||
// let x;
|
||||
// }
|
||||
// 'var x' will be placed into the function locals and 'let x' - into the locals of the block
|
||||
bindChildren(node, 0, /*isBlockScopeContainer*/ !isAnyFunction(node.parent));
|
||||
// 'let x' will be placed into the function locals and 'let x' - into the locals of the block
|
||||
bindChildren(node, 0, /*isBlockScopeContainer*/ !isFunctionLike(node.parent));
|
||||
break;
|
||||
case SyntaxKind.CatchClause:
|
||||
case SyntaxKind.ForStatement:
|
||||
case SyntaxKind.ForInStatement:
|
||||
case SyntaxKind.ForOfStatement:
|
||||
case SyntaxKind.SwitchStatement:
|
||||
case SyntaxKind.CaseBlock:
|
||||
bindChildren(node, 0, /*isBlockScopeContainer*/ true);
|
||||
break;
|
||||
default:
|
||||
var saveParent = parent;
|
||||
let saveParent = parent;
|
||||
parent = node;
|
||||
forEachChild(node, bind);
|
||||
parent = saveParent;
|
||||
@@ -542,7 +561,7 @@ module ts {
|
||||
node.parent.kind === SyntaxKind.Constructor &&
|
||||
node.parent.parent.kind === SyntaxKind.ClassDeclaration) {
|
||||
|
||||
var classDeclaration = <ClassDeclaration>node.parent.parent;
|
||||
let classDeclaration = <ClassDeclaration>node.parent.parent;
|
||||
declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
|
||||
}
|
||||
}
|
||||
|
||||
+1974
-1732
File diff suppressed because it is too large
Load Diff
@@ -140,6 +140,18 @@ module ts {
|
||||
description: Diagnostics.Do_not_emit_declarations_for_code_that_has_an_internal_annotation,
|
||||
experimental: true
|
||||
},
|
||||
{
|
||||
name: "preserveNewLines",
|
||||
type: "boolean",
|
||||
description: Diagnostics.Preserve_new_lines_when_emitting_code,
|
||||
experimental: true
|
||||
},
|
||||
{
|
||||
name: "cacheDownlevelForOfLength",
|
||||
type: "boolean",
|
||||
description: "Cache length access when downlevel emitting for-of statements",
|
||||
experimental: true,
|
||||
},
|
||||
{
|
||||
name: "target",
|
||||
shortName: "t",
|
||||
|
||||
+100
-91
@@ -25,8 +25,8 @@ module ts {
|
||||
|
||||
export function forEach<T, U>(array: T[], callback: (element: T, index: number) => U): U {
|
||||
if (array) {
|
||||
for (var i = 0, len = array.length; i < len; i++) {
|
||||
var result = callback(array[i], i);
|
||||
for (let i = 0, len = array.length; i < len; i++) {
|
||||
let result = callback(array[i], i);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
@@ -37,8 +37,8 @@ module ts {
|
||||
|
||||
export function contains<T>(array: T[], value: T): boolean {
|
||||
if (array) {
|
||||
for (var i = 0, len = array.length; i < len; i++) {
|
||||
if (array[i] === value) {
|
||||
for (let v of array) {
|
||||
if (v === value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ module ts {
|
||||
|
||||
export function indexOf<T>(array: T[], value: T): number {
|
||||
if (array) {
|
||||
for (var i = 0, len = array.length; i < len; i++) {
|
||||
for (let i = 0, len = array.length; i < len; i++) {
|
||||
if (array[i] === value) {
|
||||
return i;
|
||||
}
|
||||
@@ -58,10 +58,10 @@ module ts {
|
||||
}
|
||||
|
||||
export function countWhere<T>(array: T[], predicate: (x: T) => boolean): number {
|
||||
var count = 0;
|
||||
let count = 0;
|
||||
if (array) {
|
||||
for (var i = 0, len = array.length; i < len; i++) {
|
||||
if (predicate(array[i])) {
|
||||
for (let v of array) {
|
||||
if (predicate(v)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
@@ -69,11 +69,11 @@ module ts {
|
||||
return count;
|
||||
}
|
||||
|
||||
export function filter<T>(array: T[], f: (x: T) => boolean): T[] {
|
||||
export function filter<T>(array: T[], f: (x: T) => boolean): T[]{
|
||||
let result: T[];
|
||||
if (array) {
|
||||
var result: T[] = [];
|
||||
for (var i = 0, len = array.length; i < len; i++) {
|
||||
var item = array[i];
|
||||
result = [];
|
||||
for (let item of array) {
|
||||
if (f(item)) {
|
||||
result.push(item);
|
||||
}
|
||||
@@ -82,11 +82,12 @@ module ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function map<T, U>(array: T[], f: (x: T) => U): U[] {
|
||||
export function map<T, U>(array: T[], f: (x: T) => U): U[]{
|
||||
let result: U[];
|
||||
if (array) {
|
||||
var result: U[] = [];
|
||||
for (var i = 0, len = array.length; i < len; i++) {
|
||||
result.push(f(array[i]));
|
||||
result = [];
|
||||
for (let v of array) {
|
||||
result.push(f(v));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -99,28 +100,30 @@ module ts {
|
||||
return array1.concat(array2);
|
||||
}
|
||||
|
||||
export function deduplicate<T>(array: T[]): T[] {
|
||||
export function deduplicate<T>(array: T[]): T[]{
|
||||
let result: T[];
|
||||
if (array) {
|
||||
var result: T[] = [];
|
||||
for (var i = 0, len = array.length; i < len; i++) {
|
||||
var item = array[i];
|
||||
if (!contains(result, item)) result.push(item);
|
||||
result = [];
|
||||
for (let item of array) {
|
||||
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++) {
|
||||
result += array[i][prop];
|
||||
let result = 0;
|
||||
for (let v of array) {
|
||||
result += v[prop];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function addRange<T>(to: T[], from: T[]): void {
|
||||
for (var i = 0, n = from.length; i < n; i++) {
|
||||
to.push(from[i]);
|
||||
for (let v of from) {
|
||||
to.push(v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,12 +139,12 @@ module ts {
|
||||
}
|
||||
|
||||
export function binarySearch(array: number[], value: number): number {
|
||||
var low = 0;
|
||||
var high = array.length - 1;
|
||||
let low = 0;
|
||||
let high = array.length - 1;
|
||||
|
||||
while (low <= high) {
|
||||
var middle = low + ((high - low) >> 1);
|
||||
var midValue = array[middle];
|
||||
let middle = low + ((high - low) >> 1);
|
||||
let midValue = array[middle];
|
||||
|
||||
if (midValue === value) {
|
||||
return middle;
|
||||
@@ -157,7 +160,7 @@ module ts {
|
||||
return ~low;
|
||||
}
|
||||
|
||||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
let hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
|
||||
export function hasProperty<T>(map: Map<T>, key: string): boolean {
|
||||
return hasOwnProperty.call(map, key);
|
||||
@@ -168,7 +171,7 @@ module ts {
|
||||
}
|
||||
|
||||
export function isEmpty<T>(map: Map<T>) {
|
||||
for (var id in map) {
|
||||
for (let id in map) {
|
||||
if (hasProperty(map, id)) {
|
||||
return false;
|
||||
}
|
||||
@@ -177,19 +180,19 @@ module ts {
|
||||
}
|
||||
|
||||
export function clone<T>(object: T): T {
|
||||
var result: any = {};
|
||||
for (var id in object) {
|
||||
let result: any = {};
|
||||
for (let id in object) {
|
||||
result[id] = (<any>object)[id];
|
||||
}
|
||||
return <T>result;
|
||||
}
|
||||
|
||||
export function extend<T>(first: Map<T>, second: Map<T>): Map<T> {
|
||||
var result: Map<T> = {};
|
||||
for (var id in first) {
|
||||
let result: Map<T> = {};
|
||||
for (let id in first) {
|
||||
result[id] = first[id];
|
||||
}
|
||||
for (var id in second) {
|
||||
for (let id in second) {
|
||||
if (!hasProperty(result, id)) {
|
||||
result[id] = second[id];
|
||||
}
|
||||
@@ -198,16 +201,16 @@ module ts {
|
||||
}
|
||||
|
||||
export function forEachValue<T, U>(map: Map<T>, callback: (value: T) => U): U {
|
||||
var result: U;
|
||||
for (var id in map) {
|
||||
let result: U;
|
||||
for (let id in map) {
|
||||
if (result = callback(map[id])) break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function forEachKey<T, U>(map: Map<T>, callback: (key: string) => U): U {
|
||||
var result: U;
|
||||
for (var id in map) {
|
||||
let result: U;
|
||||
for (let id in map) {
|
||||
if (result = callback(id)) break;
|
||||
}
|
||||
return result;
|
||||
@@ -218,9 +221,9 @@ module ts {
|
||||
}
|
||||
|
||||
export function mapToArray<T>(map: Map<T>): T[] {
|
||||
var result: T[] = [];
|
||||
let result: T[] = [];
|
||||
|
||||
for (var id in map) {
|
||||
for (let id in map) {
|
||||
result.push(map[id]);
|
||||
}
|
||||
|
||||
@@ -228,7 +231,7 @@ module ts {
|
||||
}
|
||||
|
||||
export function copyMap<T>(source: Map<T>, target: Map<T>): void {
|
||||
for (var p in source) {
|
||||
for (let p in source) {
|
||||
target[p] = source[p];
|
||||
}
|
||||
}
|
||||
@@ -244,7 +247,7 @@ module ts {
|
||||
* index in the array will be the one associated with the produced key.
|
||||
*/
|
||||
export function arrayToMap<T>(array: T[], makeKey: (value: T) => string): Map<T> {
|
||||
var result: Map<T> = {};
|
||||
let result: Map<T> = {};
|
||||
|
||||
forEach(array, value => {
|
||||
result[makeKey(value)] = value;
|
||||
@@ -259,7 +262,7 @@ module ts {
|
||||
return text.replace(/{(\d+)}/g, (match, index?) => args[+index + baseIndex]);
|
||||
}
|
||||
|
||||
export var localizedDiagnosticMessages: Map<string> = undefined;
|
||||
export let localizedDiagnosticMessages: Map<string> = undefined;
|
||||
|
||||
export function getLocaleSpecificMessage(message: string) {
|
||||
return localizedDiagnosticMessages && localizedDiagnosticMessages[message]
|
||||
@@ -269,10 +272,14 @@ module ts {
|
||||
|
||||
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: any[]): Diagnostic;
|
||||
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): Diagnostic {
|
||||
let end = start + length;
|
||||
|
||||
Debug.assert(start >= 0, "start must be non-negative, is " + start);
|
||||
Debug.assert(length >= 0, "length must be non-negative, is " + length);
|
||||
Debug.assert(start <= file.text.length, `start must be within the bounds of the file. ${ start } > ${ file.text.length }`);
|
||||
Debug.assert(end <= file.text.length, `end must be the bounds of the file. ${ end } > ${ file.text.length }`);
|
||||
|
||||
var text = getLocaleSpecificMessage(message.key);
|
||||
let text = getLocaleSpecificMessage(message.key);
|
||||
|
||||
if (arguments.length > 4) {
|
||||
text = formatStringFromArgs(text, arguments, 4);
|
||||
@@ -291,7 +298,7 @@ module ts {
|
||||
|
||||
export function createCompilerDiagnostic(message: DiagnosticMessage, ...args: any[]): Diagnostic;
|
||||
export function createCompilerDiagnostic(message: DiagnosticMessage): Diagnostic {
|
||||
var text = getLocaleSpecificMessage(message.key);
|
||||
let text = getLocaleSpecificMessage(message.key);
|
||||
|
||||
if (arguments.length > 1) {
|
||||
text = formatStringFromArgs(text, arguments, 1);
|
||||
@@ -310,7 +317,7 @@ module ts {
|
||||
|
||||
export function chainDiagnosticMessages(details: DiagnosticMessageChain, message: DiagnosticMessage, ...args: any[]): DiagnosticMessageChain;
|
||||
export function chainDiagnosticMessages(details: DiagnosticMessageChain, message: DiagnosticMessage): DiagnosticMessageChain {
|
||||
var text = getLocaleSpecificMessage(message.key);
|
||||
let text = getLocaleSpecificMessage(message.key);
|
||||
|
||||
if (arguments.length > 2) {
|
||||
text = formatStringFromArgs(text, arguments, 2);
|
||||
@@ -354,10 +361,10 @@ module ts {
|
||||
function compareMessageText(text1: string | DiagnosticMessageChain, text2: string | DiagnosticMessageChain): Comparison {
|
||||
while (text1 && text2) {
|
||||
// We still have both chains.
|
||||
var string1 = typeof text1 === "string" ? text1 : text1.messageText;
|
||||
var string2 = typeof text2 === "string" ? text2 : text2.messageText;
|
||||
let string1 = typeof text1 === "string" ? text1 : text1.messageText;
|
||||
let string2 = typeof text2 === "string" ? text2 : text2.messageText;
|
||||
|
||||
var res = compareValues(string1, string2);
|
||||
let res = compareValues(string1, string2);
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
@@ -384,11 +391,11 @@ module ts {
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
var newDiagnostics = [diagnostics[0]];
|
||||
var previousDiagnostic = diagnostics[0];
|
||||
for (var i = 1; i < diagnostics.length; i++) {
|
||||
var currentDiagnostic = diagnostics[i];
|
||||
var isDupe = compareDiagnostics(currentDiagnostic, previousDiagnostic) === Comparison.EqualTo;
|
||||
let newDiagnostics = [diagnostics[0]];
|
||||
let previousDiagnostic = diagnostics[0];
|
||||
for (let i = 1; i < diagnostics.length; i++) {
|
||||
let currentDiagnostic = diagnostics[i];
|
||||
let isDupe = compareDiagnostics(currentDiagnostic, previousDiagnostic) === Comparison.EqualTo;
|
||||
if (!isDupe) {
|
||||
newDiagnostics.push(currentDiagnostic);
|
||||
previousDiagnostic = currentDiagnostic;
|
||||
@@ -406,9 +413,9 @@ module ts {
|
||||
export function getRootLength(path: string): number {
|
||||
if (path.charCodeAt(0) === CharacterCodes.slash) {
|
||||
if (path.charCodeAt(1) !== CharacterCodes.slash) return 1;
|
||||
var p1 = path.indexOf("/", 2);
|
||||
let p1 = path.indexOf("/", 2);
|
||||
if (p1 < 0) return 2;
|
||||
var p2 = path.indexOf("/", p1 + 1);
|
||||
let p2 = path.indexOf("/", p1 + 1);
|
||||
if (p2 < 0) return p1 + 1;
|
||||
return p2 + 1;
|
||||
}
|
||||
@@ -419,18 +426,21 @@ module ts {
|
||||
return 0;
|
||||
}
|
||||
|
||||
export var directorySeparator = "/";
|
||||
export let directorySeparator = "/";
|
||||
function getNormalizedParts(normalizedSlashedPath: string, rootLength: number) {
|
||||
var parts = normalizedSlashedPath.substr(rootLength).split(directorySeparator);
|
||||
var normalized: string[] = [];
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
var part = parts[i];
|
||||
let parts = normalizedSlashedPath.substr(rootLength).split(directorySeparator);
|
||||
let normalized: string[] = [];
|
||||
for (let part of parts) {
|
||||
if (part !== ".") {
|
||||
if (part === ".." && normalized.length > 0 && normalized[normalized.length - 1] !== "..") {
|
||||
normalized.pop();
|
||||
}
|
||||
else {
|
||||
normalized.push(part);
|
||||
// A part may be an empty string (which is 'falsy') if the path had consecutive slashes,
|
||||
// e.g. "path//file.ts". Drop these before re-joining the parts.
|
||||
if(part) {
|
||||
normalized.push(part);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -439,9 +449,9 @@ module ts {
|
||||
}
|
||||
|
||||
export function normalizePath(path: string): string {
|
||||
var path = normalizeSlashes(path);
|
||||
var rootLength = getRootLength(path);
|
||||
var normalized = getNormalizedParts(path, rootLength);
|
||||
path = normalizeSlashes(path);
|
||||
let rootLength = getRootLength(path);
|
||||
let normalized = getNormalizedParts(path, rootLength);
|
||||
return path.substr(0, rootLength) + normalized.join(directorySeparator);
|
||||
}
|
||||
|
||||
@@ -458,13 +468,13 @@ module ts {
|
||||
}
|
||||
|
||||
function normalizedPathComponents(path: string, rootLength: number) {
|
||||
var normalizedParts = getNormalizedParts(path, rootLength);
|
||||
let normalizedParts = getNormalizedParts(path, rootLength);
|
||||
return [path.substr(0, rootLength)].concat(normalizedParts);
|
||||
}
|
||||
|
||||
export function getNormalizedPathComponents(path: string, currentDirectory: string) {
|
||||
var path = normalizeSlashes(path);
|
||||
var rootLength = getRootLength(path);
|
||||
path = normalizeSlashes(path);
|
||||
let rootLength = getRootLength(path);
|
||||
if (rootLength == 0) {
|
||||
// If the path is not rooted it is relative to current directory
|
||||
path = combinePaths(normalizeSlashes(currentDirectory), path);
|
||||
@@ -489,9 +499,9 @@ module ts {
|
||||
// In this example the root is: http://www.website.com/
|
||||
// normalized path components should be ["http://www.website.com/", "folder1", "folder2"]
|
||||
|
||||
var urlLength = url.length;
|
||||
let urlLength = url.length;
|
||||
// Initial root length is http:// part
|
||||
var rootLength = url.indexOf("://") + "://".length;
|
||||
let rootLength = url.indexOf("://") + "://".length;
|
||||
while (rootLength < urlLength) {
|
||||
// Consume all immediate slashes in the protocol
|
||||
// eg.initial rootlength is just file:// but it needs to consume another "/" in file:///
|
||||
@@ -510,7 +520,7 @@ module ts {
|
||||
}
|
||||
|
||||
// Find the index of "/" after website.com so the root can be http://www.website.com/ (from existing http://)
|
||||
var indexOfNextSlash = url.indexOf(directorySeparator, rootLength);
|
||||
let indexOfNextSlash = url.indexOf(directorySeparator, rootLength);
|
||||
if (indexOfNextSlash !== -1) {
|
||||
// Found the "/" after the website.com so the root is length of http://www.website.com/
|
||||
// and get components afetr the root normally like any other folder components
|
||||
@@ -536,8 +546,8 @@ module ts {
|
||||
}
|
||||
|
||||
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);
|
||||
let pathComponents = getNormalizedPathOrUrlComponents(relativeOrAbsolutePath, currentDirectory);
|
||||
let 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 directory to be only till its name
|
||||
// that is ["test", "cases", ""] needs to be actually ["test", "cases"]
|
||||
@@ -553,8 +563,8 @@ module ts {
|
||||
|
||||
// Get the relative path
|
||||
if (joinStartIndex) {
|
||||
var relativePath = "";
|
||||
var relativePathComponents = pathComponents.slice(joinStartIndex, pathComponents.length);
|
||||
let relativePath = "";
|
||||
let relativePathComponents = pathComponents.slice(joinStartIndex, pathComponents.length);
|
||||
for (; joinStartIndex < directoryComponents.length; joinStartIndex++) {
|
||||
if (directoryComponents[joinStartIndex] !== "") {
|
||||
relativePath = relativePath + ".." + directorySeparator;
|
||||
@@ -565,7 +575,7 @@ module ts {
|
||||
}
|
||||
|
||||
// Cant find the relative path, get the absolute path
|
||||
var absolutePath = getNormalizedPathFromPathComponents(pathComponents);
|
||||
let absolutePath = getNormalizedPathFromPathComponents(pathComponents);
|
||||
if (isAbsolutePathAnUrl && isRootedDiskPath(absolutePath)) {
|
||||
absolutePath = "file:///" + absolutePath;
|
||||
}
|
||||
@@ -574,7 +584,7 @@ module ts {
|
||||
}
|
||||
|
||||
export function getBaseFileName(path: string) {
|
||||
var i = path.lastIndexOf(directorySeparator);
|
||||
let i = path.lastIndexOf(directorySeparator);
|
||||
return i < 0 ? path : path.substring(i + 1);
|
||||
}
|
||||
|
||||
@@ -587,16 +597,15 @@ module ts {
|
||||
}
|
||||
|
||||
export function fileExtensionIs(path: string, extension: string): boolean {
|
||||
var pathLen = path.length;
|
||||
var extLen = extension.length;
|
||||
let pathLen = path.length;
|
||||
let extLen = extension.length;
|
||||
return pathLen > extLen && path.substr(pathLen - extLen, extLen) === extension;
|
||||
}
|
||||
|
||||
var supportedExtensions = [".d.ts", ".ts", ".js"];
|
||||
let supportedExtensions = [".d.ts", ".ts", ".js"];
|
||||
|
||||
export function removeFileExtension(path: string): string {
|
||||
for (var i = 0; i < supportedExtensions.length; i++) {
|
||||
var ext = supportedExtensions[i];
|
||||
for (let ext of supportedExtensions) {
|
||||
|
||||
if (fileExtensionIs(path, ext)) {
|
||||
return path.substr(0, path.length - ext.length);
|
||||
@@ -606,9 +615,9 @@ module ts {
|
||||
return path;
|
||||
}
|
||||
|
||||
var backslashOrDoubleQuote = /[\"\\]/g;
|
||||
var escapedCharsRegExp = /[\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
|
||||
var escapedCharsMap: Map<string> = {
|
||||
let backslashOrDoubleQuote = /[\"\\]/g;
|
||||
let escapedCharsRegExp = /[\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
|
||||
let escapedCharsMap: Map<string> = {
|
||||
"\0": "\\0",
|
||||
"\t": "\\t",
|
||||
"\v": "\\v",
|
||||
@@ -647,7 +656,7 @@ module ts {
|
||||
function Signature(checker: TypeChecker) {
|
||||
}
|
||||
|
||||
export var objectAllocator: ObjectAllocator = {
|
||||
export let objectAllocator: ObjectAllocator = {
|
||||
getNodeConstructor: kind => {
|
||||
function Node() {
|
||||
}
|
||||
@@ -673,7 +682,7 @@ module ts {
|
||||
}
|
||||
|
||||
export module Debug {
|
||||
var currentAssertionLevel = AssertionLevel.None;
|
||||
let currentAssertionLevel = AssertionLevel.None;
|
||||
|
||||
export function shouldAssert(level: AssertionLevel): boolean {
|
||||
return currentAssertionLevel >= level;
|
||||
@@ -681,7 +690,7 @@ module ts {
|
||||
|
||||
export function assert(expression: boolean, message?: string, verboseDebugInfo?: () => string): void {
|
||||
if (!expression) {
|
||||
var verboseDebugString = "";
|
||||
let verboseDebugString = "";
|
||||
if (verboseDebugInfo) {
|
||||
verboseDebugString = "\r\nVerbose Debug Information: " + verboseDebugInfo();
|
||||
}
|
||||
|
||||
@@ -157,6 +157,11 @@ module ts {
|
||||
Catch_clause_variable_cannot_have_an_initializer: { code: 1197, category: DiagnosticCategory.Error, key: "Catch clause variable cannot have an initializer." },
|
||||
An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive: { code: 1198, category: DiagnosticCategory.Error, key: "An extended Unicode escape value must be between 0x0 and 0x10FFFF inclusive." },
|
||||
Unterminated_Unicode_escape_sequence: { code: 1199, category: DiagnosticCategory.Error, key: "Unterminated Unicode escape sequence." },
|
||||
Line_terminator_not_permitted_before_arrow: { code: 1200, category: DiagnosticCategory.Error, key: "Line terminator not permitted before arrow." },
|
||||
A_type_annotation_on_an_export_statement_is_only_allowed_in_an_ambient_external_module_declaration: { code: 1201, category: DiagnosticCategory.Error, key: "A type annotation on an export statement is only allowed in an ambient external module declaration." },
|
||||
Import_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_or_import_d_from_mod_instead: { code: 1202, category: DiagnosticCategory.Error, key: "Import assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'import * as ns from \"mod\"', 'import {a} from \"mod\"' or 'import d from \"mod\"' instead." },
|
||||
Export_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_export_default_instead: { code: 1203, category: DiagnosticCategory.Error, key: "Export assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'export default' instead." },
|
||||
Cannot_compile_external_modules_into_amd_or_commonjs_when_targeting_es6_or_higher: { code: 1204, category: DiagnosticCategory.Error, key: "Cannot compile external modules into amd or commonjs when targeting es6 or higher." },
|
||||
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." },
|
||||
@@ -327,7 +332,6 @@ module ts {
|
||||
Property_0_does_not_exist_on_const_enum_1: { code: 2479, category: DiagnosticCategory.Error, key: "Property '{0}' does not exist on 'const' enum '{1}'." },
|
||||
let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations: { code: 2480, category: DiagnosticCategory.Error, key: "'let' is not allowed to be used as a name in 'let' or 'const' declarations." },
|
||||
Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1: { code: 2481, category: DiagnosticCategory.Error, key: "Cannot initialize outer scoped variable '{0}' in the same scope as block scoped declaration '{1}'." },
|
||||
for_of_statements_are_only_available_when_targeting_ECMAScript_6_or_higher: { code: 2482, category: DiagnosticCategory.Error, key: "'for...of' statements are only available when targeting ECMAScript 6 or higher." },
|
||||
The_left_hand_side_of_a_for_of_statement_cannot_use_a_type_annotation: { code: 2483, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...of' statement cannot use a type annotation." },
|
||||
Export_declaration_conflicts_with_exported_declaration_of_0: { code: 2484, category: DiagnosticCategory.Error, key: "Export declaration conflicts with exported declaration of '{0}'" },
|
||||
The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant: { code: 2485, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...of' statement cannot be a previously defined constant." },
|
||||
@@ -337,6 +341,10 @@ module ts {
|
||||
The_iterator_returned_by_the_right_hand_side_of_a_for_of_statement_must_have_a_next_method: { code: 2489, category: DiagnosticCategory.Error, key: "The iterator returned by the right-hand side of a 'for...of' statement must have a 'next()' method." },
|
||||
The_type_returned_by_the_next_method_of_an_iterator_must_have_a_value_property: { code: 2490, category: DiagnosticCategory.Error, key: "The type returned by the 'next()' method of an iterator must have a 'value' property." },
|
||||
The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern: { code: 2491, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement cannot be a destructuring pattern." },
|
||||
Cannot_redeclare_identifier_0_in_catch_clause: { code: 2492, category: DiagnosticCategory.Error, key: "Cannot redeclare identifier '{0}' in catch clause" },
|
||||
Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2: { code: 2493, category: DiagnosticCategory.Error, key: "Tuple type '{0}' with length '{1}' cannot be assigned to tuple with length '{2}'." },
|
||||
Using_a_string_in_a_for_of_statement_is_only_supported_in_ECMAScript_5_and_higher: { code: 2494, category: DiagnosticCategory.Error, key: "Using a string in a 'for...of' statement is only supported in ECMAScript 5 and higher." },
|
||||
Type_0_is_not_an_array_type_or_a_string_type: { code: 2461, category: DiagnosticCategory.Error, key: "Type '{0}' is not an array type or a string type." },
|
||||
Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
|
||||
Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." },
|
||||
Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." },
|
||||
@@ -462,6 +470,7 @@ module ts {
|
||||
File_0_must_have_extension_ts_or_d_ts: { code: 6054, category: DiagnosticCategory.Error, key: "File '{0}' must have extension '.ts' or '.d.ts'." },
|
||||
Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures: { code: 6055, category: DiagnosticCategory.Message, key: "Suppress noImplicitAny errors for indexing objects lacking index signatures." },
|
||||
Do_not_emit_declarations_for_code_that_has_an_internal_annotation: { code: 6056, category: DiagnosticCategory.Message, key: "Do not emit declarations for code that has an '@internal' annotation." },
|
||||
Preserve_new_lines_when_emitting_code: { code: 6057, category: DiagnosticCategory.Message, key: "Preserve new-lines when emitting code." },
|
||||
Variable_0_implicitly_has_an_1_type: { code: 7005, category: DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." },
|
||||
Parameter_0_implicitly_has_an_1_type: { code: 7006, category: DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." },
|
||||
Member_0_implicitly_has_an_1_type: { code: 7008, category: DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." },
|
||||
|
||||
@@ -617,8 +617,29 @@
|
||||
},
|
||||
"Unterminated Unicode escape sequence.": {
|
||||
"category": "Error",
|
||||
"code": 1199
|
||||
"code": 1199
|
||||
},
|
||||
"Line terminator not permitted before arrow.": {
|
||||
"category": "Error",
|
||||
"code": 1200
|
||||
},
|
||||
"A type annotation on an export statement is only allowed in an ambient external module declaration.": {
|
||||
"category": "Error",
|
||||
"code": 1201
|
||||
},
|
||||
"Import assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'import * as ns from \"mod\"', 'import {a} from \"mod\"' or 'import d from \"mod\"' instead.": {
|
||||
"category": "Error",
|
||||
"code": 1202
|
||||
},
|
||||
"Export assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'export default' instead.": {
|
||||
"category": "Error",
|
||||
"code": 1203
|
||||
},
|
||||
"Cannot compile external modules into amd or commonjs when targeting es6 or higher.": {
|
||||
"category": "Error",
|
||||
"code": 1204
|
||||
},
|
||||
|
||||
"Duplicate identifier '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 2300
|
||||
@@ -1299,10 +1320,6 @@
|
||||
"category": "Error",
|
||||
"code": 2481
|
||||
},
|
||||
"'for...of' statements are only available when targeting ECMAScript 6 or higher.": {
|
||||
"category": "Error",
|
||||
"code": 2482
|
||||
},
|
||||
"The left-hand side of a 'for...of' statement cannot use a type annotation.": {
|
||||
"category": "Error",
|
||||
"code": 2483
|
||||
@@ -1339,6 +1356,22 @@
|
||||
"category": "Error",
|
||||
"code": 2491
|
||||
},
|
||||
"Cannot redeclare identifier '{0}' in catch clause": {
|
||||
"category": "Error",
|
||||
"code": 2492
|
||||
},
|
||||
"Tuple type '{0}' with length '{1}' cannot be assigned to tuple with length '{2}'.": {
|
||||
"category": "Error",
|
||||
"code": 2493
|
||||
},
|
||||
"Using a string in a 'for...of' statement is only supported in ECMAScript 5 and higher.": {
|
||||
"category": "Error",
|
||||
"code": 2494
|
||||
},
|
||||
"Type '{0}' is not an array type or a string type.": {
|
||||
"category": "Error",
|
||||
"code": 2461
|
||||
},
|
||||
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
@@ -1840,6 +1873,10 @@
|
||||
"category": "Message",
|
||||
"code": 6056
|
||||
},
|
||||
"Preserve new-lines when emitting code.": {
|
||||
"category": "Message",
|
||||
"code": 6057
|
||||
},
|
||||
|
||||
"Variable '{0}' implicitly has an '{1}' type.": {
|
||||
"category": "Error",
|
||||
|
||||
+1369
-699
File diff suppressed because it is too large
Load Diff
+534
-482
File diff suppressed because it is too large
Load Diff
+104
-84
@@ -2,12 +2,17 @@
|
||||
/// <reference path="emitter.ts" />
|
||||
|
||||
module ts {
|
||||
/* @internal */ export var emitTime = 0;
|
||||
/* @internal */ export var ioReadTime = 0;
|
||||
/* @internal */ export let programTime = 0;
|
||||
/* @internal */ export let emitTime = 0;
|
||||
/* @internal */ export let ioReadTime = 0;
|
||||
/* @internal */ export let ioWriteTime = 0;
|
||||
|
||||
/** The version of the TypeScript compiler release */
|
||||
export let version = "1.5.0.0";
|
||||
|
||||
export function createCompilerHost(options: CompilerOptions): CompilerHost {
|
||||
var currentDirectory: string;
|
||||
var existingDirectories: Map<boolean> = {};
|
||||
let currentDirectory: string;
|
||||
let existingDirectories: Map<boolean> = {};
|
||||
|
||||
function getCanonicalFileName(fileName: string): string {
|
||||
// if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
|
||||
@@ -16,12 +21,13 @@ module ts {
|
||||
}
|
||||
|
||||
// returned by CScript sys environment
|
||||
var unsupportedFileEncodingErrorCode = -2147024809;
|
||||
let unsupportedFileEncodingErrorCode = -2147024809;
|
||||
|
||||
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile {
|
||||
let text: string;
|
||||
try {
|
||||
var start = new Date().getTime();
|
||||
var text = sys.readFile(fileName, options.charset);
|
||||
let start = new Date().getTime();
|
||||
text = sys.readFile(fileName, options.charset);
|
||||
ioReadTime += new Date().getTime() - start;
|
||||
}
|
||||
catch (e) {
|
||||
@@ -32,33 +38,34 @@ module ts {
|
||||
}
|
||||
text = "";
|
||||
}
|
||||
|
||||
return text !== undefined ? createSourceFile(fileName, text, languageVersion) : undefined;
|
||||
}
|
||||
|
||||
function directoryExists(directoryPath: string): boolean {
|
||||
if (hasProperty(existingDirectories, directoryPath)) {
|
||||
return true;
|
||||
}
|
||||
if (sys.directoryExists(directoryPath)) {
|
||||
existingDirectories[directoryPath] = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function ensureDirectoriesExist(directoryPath: string) {
|
||||
if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
|
||||
let parentDirectory = getDirectoryPath(directoryPath);
|
||||
ensureDirectoriesExist(parentDirectory);
|
||||
sys.createDirectory(directoryPath);
|
||||
}
|
||||
}
|
||||
|
||||
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
|
||||
function directoryExists(directoryPath: string): boolean {
|
||||
if (hasProperty(existingDirectories, directoryPath)) {
|
||||
return true;
|
||||
}
|
||||
if (sys.directoryExists(directoryPath)) {
|
||||
existingDirectories[directoryPath] = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function ensureDirectoriesExist(directoryPath: string) {
|
||||
if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
|
||||
var parentDirectory = getDirectoryPath(directoryPath);
|
||||
ensureDirectoriesExist(parentDirectory);
|
||||
sys.createDirectory(directoryPath);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
var start = new Date().getTime();
|
||||
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
|
||||
sys.writeFile(fileName, data, writeByteOrderMark);
|
||||
ioWriteTime += new Date().getTime() - start;
|
||||
}
|
||||
catch (e) {
|
||||
if (onError) {
|
||||
@@ -79,7 +86,7 @@ module ts {
|
||||
}
|
||||
|
||||
export function getPreEmitDiagnostics(program: Program): Diagnostic[] {
|
||||
var diagnostics = program.getSyntacticDiagnostics().concat(program.getGlobalDiagnostics()).concat(program.getSemanticDiagnostics());
|
||||
let diagnostics = program.getSyntacticDiagnostics().concat(program.getGlobalDiagnostics()).concat(program.getSemanticDiagnostics());
|
||||
return sortAndDeduplicateDiagnostics(diagnostics);
|
||||
}
|
||||
|
||||
@@ -88,15 +95,15 @@ module ts {
|
||||
return messageText;
|
||||
}
|
||||
else {
|
||||
var diagnosticChain = messageText;
|
||||
var result = "";
|
||||
let diagnosticChain = messageText;
|
||||
let result = "";
|
||||
|
||||
var indent = 0;
|
||||
let indent = 0;
|
||||
while (diagnosticChain) {
|
||||
if (indent) {
|
||||
result += newLine;
|
||||
|
||||
for (var i = 0; i < indent; i++) {
|
||||
for (let i = 0; i < indent; i++) {
|
||||
result += " ";
|
||||
}
|
||||
}
|
||||
@@ -110,22 +117,25 @@ module ts {
|
||||
}
|
||||
|
||||
export function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost): Program {
|
||||
var program: Program;
|
||||
var files: SourceFile[] = [];
|
||||
var filesByName: Map<SourceFile> = {};
|
||||
var diagnostics = createDiagnosticCollection();
|
||||
var seenNoDefaultLib = options.noLib;
|
||||
var commonSourceDirectory: string;
|
||||
host = host || createCompilerHost(options);
|
||||
let program: Program;
|
||||
let files: SourceFile[] = [];
|
||||
let filesByName: Map<SourceFile> = {};
|
||||
let diagnostics = createDiagnosticCollection();
|
||||
let seenNoDefaultLib = options.noLib;
|
||||
let commonSourceDirectory: string;
|
||||
let diagnosticsProducingTypeChecker: TypeChecker;
|
||||
let noDiagnosticsTypeChecker: TypeChecker;
|
||||
|
||||
let start = new Date().getTime();
|
||||
|
||||
host = host || createCompilerHost(options);
|
||||
forEach(rootNames, name => processRootFile(name, false));
|
||||
if (!seenNoDefaultLib) {
|
||||
processRootFile(host.getDefaultLibFileName(options), true);
|
||||
}
|
||||
verifyCompilerOptions();
|
||||
|
||||
var diagnosticsProducingTypeChecker: TypeChecker;
|
||||
var noDiagnosticsTypeChecker: TypeChecker;
|
||||
programTime += new Date().getTime() - start;
|
||||
|
||||
program = {
|
||||
getSourceFile: getSourceFile,
|
||||
@@ -169,7 +179,7 @@ module ts {
|
||||
}
|
||||
|
||||
function getDeclarationDiagnostics(targetSourceFile: SourceFile): Diagnostic[] {
|
||||
var resolver = getDiagnosticsProducingTypeChecker().getEmitResolver(targetSourceFile);
|
||||
let resolver = getDiagnosticsProducingTypeChecker().getEmitResolver(targetSourceFile);
|
||||
return ts.getDeclarationDiagnostics(getEmitHost(), resolver, targetSourceFile);
|
||||
}
|
||||
|
||||
@@ -183,11 +193,11 @@ module ts {
|
||||
// Create the emit resolver outside of the "emitTime" tracking code below. That way
|
||||
// any cost associated with it (like type checking) are appropriate associated with
|
||||
// the type-checking counter.
|
||||
var emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile);
|
||||
let emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile);
|
||||
|
||||
var start = new Date().getTime();
|
||||
let start = new Date().getTime();
|
||||
|
||||
var emitResult = emitFiles(
|
||||
let emitResult = emitFiles(
|
||||
emitResolver,
|
||||
getEmitHost(writeFileCallback),
|
||||
sourceFile);
|
||||
@@ -206,7 +216,7 @@ module ts {
|
||||
return getDiagnostics(sourceFile);
|
||||
}
|
||||
|
||||
var allDiagnostics: Diagnostic[] = [];
|
||||
let allDiagnostics: Diagnostic[] = [];
|
||||
forEach(program.getSourceFiles(), sourceFile => {
|
||||
addRange(allDiagnostics, getDiagnostics(sourceFile));
|
||||
});
|
||||
@@ -227,20 +237,20 @@ module ts {
|
||||
}
|
||||
|
||||
function getSemanticDiagnosticsForFile(sourceFile: SourceFile): Diagnostic[] {
|
||||
var typeChecker = getDiagnosticsProducingTypeChecker();
|
||||
let typeChecker = getDiagnosticsProducingTypeChecker();
|
||||
|
||||
Debug.assert(!!sourceFile.bindDiagnostics);
|
||||
var bindDiagnostics = sourceFile.bindDiagnostics;
|
||||
var checkDiagnostics = typeChecker.getDiagnostics(sourceFile);
|
||||
var programDiagnostics = diagnostics.getDiagnostics(sourceFile.fileName);
|
||||
let bindDiagnostics = sourceFile.bindDiagnostics;
|
||||
let checkDiagnostics = typeChecker.getDiagnostics(sourceFile);
|
||||
let programDiagnostics = diagnostics.getDiagnostics(sourceFile.fileName);
|
||||
|
||||
return bindDiagnostics.concat(checkDiagnostics).concat(programDiagnostics);
|
||||
}
|
||||
|
||||
function getGlobalDiagnostics(): Diagnostic[] {
|
||||
var typeChecker = getDiagnosticsProducingTypeChecker();
|
||||
let typeChecker = getDiagnosticsProducingTypeChecker();
|
||||
|
||||
var allDiagnostics: Diagnostic[] = [];
|
||||
let allDiagnostics: Diagnostic[] = [];
|
||||
addRange(allDiagnostics, typeChecker.getGlobalDiagnostics());
|
||||
addRange(allDiagnostics, diagnostics.getGlobalDiagnostics());
|
||||
|
||||
@@ -256,11 +266,13 @@ module ts {
|
||||
}
|
||||
|
||||
function processSourceFile(fileName: string, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number) {
|
||||
let start: number;
|
||||
let length: number;
|
||||
if (refEnd !== undefined && refPos !== undefined) {
|
||||
var start = refPos;
|
||||
var length = refEnd - refPos;
|
||||
start = refPos;
|
||||
length = refEnd - refPos;
|
||||
}
|
||||
var diagnostic: DiagnosticMessage;
|
||||
let diagnostic: DiagnosticMessage;
|
||||
if (hasExtension(fileName)) {
|
||||
if (!options.allowNonTsExtensions && !fileExtensionIs(host.getCanonicalFileName(fileName), ".ts")) {
|
||||
diagnostic = Diagnostics.File_0_must_have_extension_ts_or_d_ts;
|
||||
@@ -294,20 +306,20 @@ module ts {
|
||||
|
||||
// Get source file from normalized fileName
|
||||
function findSourceFile(fileName: string, isDefaultLib: boolean, refFile?: SourceFile, refStart?: number, refLength?: number): SourceFile {
|
||||
var canonicalName = host.getCanonicalFileName(fileName);
|
||||
let canonicalName = host.getCanonicalFileName(fileName);
|
||||
if (hasProperty(filesByName, canonicalName)) {
|
||||
// We've already looked for this file, use cached result
|
||||
return getSourceFileFromCache(fileName, canonicalName, /*useAbsolutePath*/ false);
|
||||
}
|
||||
else {
|
||||
var normalizedAbsolutePath = getNormalizedAbsolutePath(fileName, host.getCurrentDirectory());
|
||||
var canonicalAbsolutePath = host.getCanonicalFileName(normalizedAbsolutePath);
|
||||
let normalizedAbsolutePath = getNormalizedAbsolutePath(fileName, host.getCurrentDirectory());
|
||||
let canonicalAbsolutePath = host.getCanonicalFileName(normalizedAbsolutePath);
|
||||
if (hasProperty(filesByName, canonicalAbsolutePath)) {
|
||||
return getSourceFileFromCache(normalizedAbsolutePath, canonicalAbsolutePath, /*useAbsolutePath*/ true);
|
||||
}
|
||||
|
||||
// We haven't looked for this file, do so now and cache result
|
||||
var file = filesByName[canonicalName] = host.getSourceFile(fileName, options.target, hostErrorMessage => {
|
||||
let file = filesByName[canonicalName] = host.getSourceFile(fileName, options.target, hostErrorMessage => {
|
||||
if (refFile) {
|
||||
diagnostics.add(createFileDiagnostic(refFile, refStart, refLength,
|
||||
Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
|
||||
@@ -323,7 +335,7 @@ module ts {
|
||||
filesByName[canonicalAbsolutePath] = file;
|
||||
|
||||
if (!options.noResolve) {
|
||||
var basePath = getDirectoryPath(fileName);
|
||||
let basePath = getDirectoryPath(fileName);
|
||||
processReferencedFiles(file, basePath);
|
||||
processImportedModules(file, basePath);
|
||||
}
|
||||
@@ -334,13 +346,14 @@ module ts {
|
||||
files.push(file);
|
||||
}
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
return file;
|
||||
|
||||
function getSourceFileFromCache(fileName: string, canonicalName: string, useAbsolutePath: boolean): SourceFile {
|
||||
var file = filesByName[canonicalName];
|
||||
let file = filesByName[canonicalName];
|
||||
if (file && host.useCaseSensitiveFileNames()) {
|
||||
var sourceFileName = useAbsolutePath ? getNormalizedAbsolutePath(file.fileName, host.getCurrentDirectory()) : file.fileName;
|
||||
let sourceFileName = useAbsolutePath ? getNormalizedAbsolutePath(file.fileName, host.getCurrentDirectory()) : file.fileName;
|
||||
if (canonicalName !== sourceFileName) {
|
||||
diagnostics.add(createFileDiagnostic(refFile, refStart, refLength,
|
||||
Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, fileName, sourceFileName));
|
||||
@@ -352,7 +365,7 @@ module ts {
|
||||
|
||||
function processReferencedFiles(file: SourceFile, basePath: string) {
|
||||
forEach(file.referencedFiles, ref => {
|
||||
var referencedFileName = isRootedDiskPath(ref.fileName) ? ref.fileName : combinePaths(basePath, ref.fileName);
|
||||
let referencedFileName = isRootedDiskPath(ref.fileName) ? ref.fileName : combinePaths(basePath, ref.fileName);
|
||||
processSourceFile(normalizePath(referencedFileName), /* isDefaultLib */ false, file, ref.pos, ref.end);
|
||||
});
|
||||
}
|
||||
@@ -360,17 +373,17 @@ module ts {
|
||||
function processImportedModules(file: SourceFile, basePath: string) {
|
||||
forEach(file.statements, node => {
|
||||
if (node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration || node.kind === SyntaxKind.ExportDeclaration) {
|
||||
var moduleNameExpr = getExternalModuleName(node);
|
||||
let moduleNameExpr = getExternalModuleName(node);
|
||||
if (moduleNameExpr && moduleNameExpr.kind === SyntaxKind.StringLiteral) {
|
||||
var moduleNameText = (<LiteralExpression>moduleNameExpr).text;
|
||||
let moduleNameText = (<LiteralExpression>moduleNameExpr).text;
|
||||
if (moduleNameText) {
|
||||
var searchPath = basePath;
|
||||
let searchPath = basePath;
|
||||
while (true) {
|
||||
var searchName = normalizePath(combinePaths(searchPath, moduleNameText));
|
||||
let searchName = normalizePath(combinePaths(searchPath, moduleNameText));
|
||||
if (findModuleSourceFile(searchName + ".ts", moduleNameExpr) || findModuleSourceFile(searchName + ".d.ts", moduleNameExpr)) {
|
||||
break;
|
||||
}
|
||||
var parentPath = getDirectoryPath(searchPath);
|
||||
let parentPath = getDirectoryPath(searchPath);
|
||||
if (parentPath === searchPath) {
|
||||
break;
|
||||
}
|
||||
@@ -389,14 +402,14 @@ module ts {
|
||||
if (isExternalModuleImportEqualsDeclaration(node) &&
|
||||
getExternalModuleImportEqualsDeclarationExpression(node).kind === SyntaxKind.StringLiteral) {
|
||||
|
||||
var nameLiteral = <LiteralExpression>getExternalModuleImportEqualsDeclarationExpression(node);
|
||||
var moduleName = nameLiteral.text;
|
||||
let nameLiteral = <LiteralExpression>getExternalModuleImportEqualsDeclarationExpression(node);
|
||||
let moduleName = nameLiteral.text;
|
||||
if (moduleName) {
|
||||
// TypeScript 1.0 spec (April 2014): 12.1.6
|
||||
// An ExternalImportDeclaration in anAmbientExternalModuleDeclaration may reference other external modules
|
||||
// only through top - level external module names. Relative external module names are not permitted.
|
||||
var searchName = normalizePath(combinePaths(basePath, moduleName));
|
||||
var tsFile = findModuleSourceFile(searchName + ".ts", nameLiteral);
|
||||
let searchName = normalizePath(combinePaths(basePath, moduleName));
|
||||
let tsFile = findModuleSourceFile(searchName + ".ts", nameLiteral);
|
||||
if (!tsFile) {
|
||||
findModuleSourceFile(searchName + ".d.ts", nameLiteral);
|
||||
}
|
||||
@@ -423,13 +436,20 @@ module ts {
|
||||
return;
|
||||
}
|
||||
|
||||
var firstExternalModule = forEach(files, f => isExternalModule(f) ? f : undefined);
|
||||
if (firstExternalModule && !options.module) {
|
||||
// We cannot use createDiagnosticFromNode because nodes do not have parents yet
|
||||
var externalModuleErrorSpan = getErrorSpanForNode(firstExternalModule.externalModuleIndicator);
|
||||
var errorStart = skipTrivia(firstExternalModule.text, externalModuleErrorSpan.pos);
|
||||
var errorLength = externalModuleErrorSpan.end - errorStart;
|
||||
diagnostics.add(createFileDiagnostic(firstExternalModule, errorStart, errorLength, Diagnostics.Cannot_compile_external_modules_unless_the_module_flag_is_provided));
|
||||
let languageVersion = options.target || ScriptTarget.ES3;
|
||||
|
||||
let firstExternalModuleSourceFile = forEach(files, f => isExternalModule(f) ? f : undefined);
|
||||
if (firstExternalModuleSourceFile && !options.module) {
|
||||
if (!options.module && languageVersion < ScriptTarget.ES6) {
|
||||
// We cannot use createDiagnosticFromNode because nodes do not have parents yet
|
||||
let span = getErrorSpanForNode(firstExternalModuleSourceFile, firstExternalModuleSourceFile.externalModuleIndicator);
|
||||
diagnostics.add(createFileDiagnostic(firstExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_external_modules_unless_the_module_flag_is_provided));
|
||||
}
|
||||
}
|
||||
|
||||
// Cannot specify module gen target when in es6 or above
|
||||
if (options.module && languageVersion >= ScriptTarget.ES6) {
|
||||
diagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_compile_external_modules_into_amd_or_commonjs_when_targeting_es6_or_higher));
|
||||
}
|
||||
|
||||
// there has to be common source directory if user specified --outdir || --sourcRoot
|
||||
@@ -437,17 +457,17 @@ module ts {
|
||||
if (options.outDir || // there is --outDir specified
|
||||
options.sourceRoot || // there is --sourceRoot specified
|
||||
(options.mapRoot && // there is --mapRoot Specified and there would be multiple js files generated
|
||||
(!options.out || firstExternalModule !== undefined))) {
|
||||
(!options.out || firstExternalModuleSourceFile !== undefined))) {
|
||||
|
||||
var commonPathComponents: string[];
|
||||
let commonPathComponents: string[];
|
||||
forEach(files, sourceFile => {
|
||||
// Each file contributes into common source file path
|
||||
if (!(sourceFile.flags & NodeFlags.DeclarationFile)
|
||||
&& !fileExtensionIs(sourceFile.fileName, ".js")) {
|
||||
var sourcePathComponents = getNormalizedPathComponents(sourceFile.fileName, host.getCurrentDirectory());
|
||||
let 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, sourcePathComponents.length); i++) {
|
||||
for (let i = 0; i < Math.min(commonPathComponents.length, sourcePathComponents.length); i++) {
|
||||
if (commonPathComponents[i] !== sourcePathComponents[i]) {
|
||||
if (i === 0) {
|
||||
diagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files));
|
||||
|
||||
+91
-91
File diff suppressed because one or more lines are too long
+7
-8
@@ -124,15 +124,14 @@ module ts {
|
||||
function visitDirectory(path: string) {
|
||||
var folder = fso.GetFolder(path || ".");
|
||||
var files = getNames(folder.files);
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var name = files[i];
|
||||
for (let name of files) {
|
||||
if (!extension || fileExtensionIs(name, extension)) {
|
||||
result.push(combinePaths(path, name));
|
||||
}
|
||||
}
|
||||
var subfolders = getNames(folder.subfolders);
|
||||
for (var i = 0; i < subfolders.length; i++) {
|
||||
visitDirectory(combinePaths(path, subfolders[i]));
|
||||
for (let current of subfolders) {
|
||||
visitDirectory(combinePaths(path, current));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -230,8 +229,8 @@ module ts {
|
||||
function visitDirectory(path: string) {
|
||||
var files = _fs.readdirSync(path || ".").sort();
|
||||
var directories: string[] = [];
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var name = combinePaths(path, files[i]);
|
||||
for (let current of files) {
|
||||
var name = combinePaths(path, current);
|
||||
var stat = _fs.lstatSync(name);
|
||||
if (stat.isFile()) {
|
||||
if (!extension || fileExtensionIs(name, extension)) {
|
||||
@@ -242,8 +241,8 @@ module ts {
|
||||
directories.push(name);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < directories.length; i++) {
|
||||
visitDirectory(directories[i]);
|
||||
for (let current of directories) {
|
||||
visitDirectory(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-32
@@ -2,8 +2,6 @@
|
||||
/// <reference path="commandLineParser.ts"/>
|
||||
|
||||
module ts {
|
||||
var version = "1.5.0.0";
|
||||
|
||||
export interface SourceFile {
|
||||
fileWatcher: FileWatcher;
|
||||
}
|
||||
@@ -178,7 +176,7 @@ module ts {
|
||||
}
|
||||
|
||||
if (commandLine.options.version) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Version_0, version));
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Version_0, ts.version));
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
@@ -250,7 +248,7 @@ module ts {
|
||||
|
||||
var compileResult = compile(rootFileNames, compilerOptions, compilerHost);
|
||||
|
||||
if (!commandLine.options.watch) {
|
||||
if (!compilerOptions.watch) {
|
||||
return sys.exit(compileResult.exitStatus);
|
||||
}
|
||||
|
||||
@@ -258,7 +256,7 @@ module ts {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Compilation_complete_Watching_for_file_changes));
|
||||
}
|
||||
|
||||
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void) {
|
||||
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError ?: (message: string) => void) {
|
||||
// Return existing SourceFile object if one is available
|
||||
if (cachedProgram) {
|
||||
var sourceFile = cachedProgram.getSourceFile(fileName);
|
||||
@@ -269,7 +267,7 @@ module ts {
|
||||
}
|
||||
// Use default host function
|
||||
var sourceFile = hostGetSourceFile(fileName, languageVersion, onError);
|
||||
if (sourceFile && commandLine.options.watch) {
|
||||
if (sourceFile && compilerOptions.watch) {
|
||||
// Attach a file watcher
|
||||
sourceFile.fileWatcher = sys.watchFile(sourceFile.fileName, () => sourceFileChanged(sourceFile));
|
||||
}
|
||||
@@ -322,22 +320,16 @@ module ts {
|
||||
}
|
||||
|
||||
function compile(fileNames: string[], compilerOptions: CompilerOptions, compilerHost: CompilerHost) {
|
||||
ts.ioReadTime = 0;
|
||||
ts.parseTime = 0;
|
||||
ts.bindTime = 0;
|
||||
ts.checkTime = 0;
|
||||
ts.emitTime = 0;
|
||||
|
||||
var start = new Date().getTime();
|
||||
ioReadTime = 0;
|
||||
ioWriteTime = 0;
|
||||
programTime = 0;
|
||||
bindTime = 0;
|
||||
checkTime = 0;
|
||||
emitTime = 0;
|
||||
|
||||
var program = createProgram(fileNames, compilerOptions, compilerHost);
|
||||
var programTime = new Date().getTime() - start;
|
||||
|
||||
var exitStatus = compileProgram();
|
||||
|
||||
var end = new Date().getTime() - start;
|
||||
var compileTime = end - programTime;
|
||||
|
||||
if (compilerOptions.listFiles) {
|
||||
forEach(program.getSourceFiles(), file => {
|
||||
sys.write(file.fileName + sys.newLine);
|
||||
@@ -358,19 +350,16 @@ module ts {
|
||||
}
|
||||
|
||||
// Individual component times.
|
||||
// Note: we output 'programTime' as parseTime to match the tsc 1.3 behavior. tsc 1.3
|
||||
// measured parse time along with read IO as a single counter. We preserve that
|
||||
// behavior so we can accurately compare times. For actual parse times (in isolation)
|
||||
// is reported below.
|
||||
// Note: To match the behavior of previous versions of the compiler, the reported parse time includes
|
||||
// I/O read time and processing time for triple-slash references and module imports, and the reported
|
||||
// emit time includes I/O write time. We preserve this behavior so we can accurately compare times.
|
||||
reportTimeStatistic("I/O read", ioReadTime);
|
||||
reportTimeStatistic("I/O write", ioWriteTime);
|
||||
reportTimeStatistic("Parse time", programTime);
|
||||
reportTimeStatistic("Bind time", ts.bindTime);
|
||||
reportTimeStatistic("Check time", ts.checkTime);
|
||||
reportTimeStatistic("Emit time", ts.emitTime);
|
||||
|
||||
reportTimeStatistic("Parse time w/o IO", ts.parseTime);
|
||||
reportTimeStatistic("IO read", ts.ioReadTime);
|
||||
reportTimeStatistic("Compile time", compileTime);
|
||||
reportTimeStatistic("Total time", end);
|
||||
reportTimeStatistic("Bind time", bindTime);
|
||||
reportTimeStatistic("Check time", checkTime);
|
||||
reportTimeStatistic("Emit time", emitTime);
|
||||
reportTimeStatistic("Total time", programTime + bindTime + checkTime + emitTime);
|
||||
}
|
||||
|
||||
return { program, exitStatus };
|
||||
@@ -411,7 +400,7 @@ module ts {
|
||||
// The emitter emitted something, inform the caller if that happened in the presence
|
||||
// of diagnostics or not.
|
||||
if (diagnostics.length > 0 || emitOutput.diagnostics.length > 0) {
|
||||
ExitStatus.DiagnosticsPresent_OutputsGenerated;
|
||||
return ExitStatus.DiagnosticsPresent_OutputsGenerated;
|
||||
}
|
||||
|
||||
return ExitStatus.Success;
|
||||
@@ -419,7 +408,7 @@ module ts {
|
||||
}
|
||||
|
||||
function printVersion() {
|
||||
sys.write(getDiagnosticText(Diagnostics.Version_0, version) + sys.newLine);
|
||||
sys.write(getDiagnosticText(Diagnostics.Version_0, ts.version) + sys.newLine);
|
||||
}
|
||||
|
||||
function printHelp() {
|
||||
|
||||
+67
-52
@@ -233,6 +233,7 @@ module ts {
|
||||
EnumDeclaration,
|
||||
ModuleDeclaration,
|
||||
ModuleBlock,
|
||||
CaseBlock,
|
||||
ImportEqualsDeclaration,
|
||||
ImportDeclaration,
|
||||
ImportClause,
|
||||
@@ -299,14 +300,15 @@ module ts {
|
||||
Private = 0x00000020, // Property/Method
|
||||
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
|
||||
Let = 0x00000800, // Variable declaration
|
||||
Const = 0x00001000, // Variable declaration
|
||||
OctalLiteral = 0x00002000,
|
||||
Default = 0x00000100, // Function/Class (export default declaration)
|
||||
MultiLine = 0x00000200, // Multi-line array or object literal
|
||||
Synthetic = 0x00000400, // Synthetic node (for full fidelity)
|
||||
DeclarationFile = 0x00000800, // Node is a .d.ts file
|
||||
Let = 0x00001000, // Variable declaration
|
||||
Const = 0x00002000, // Variable declaration
|
||||
OctalLiteral = 0x00004000,
|
||||
|
||||
Modifier = Export | Ambient | Public | Private | Protected | Static,
|
||||
Modifier = Export | Ambient | Public | Private | Protected | Static | Default,
|
||||
AccessibilityModifier = Public | Private | Protected,
|
||||
BlockScoped = Let | Const
|
||||
}
|
||||
@@ -327,7 +329,7 @@ module ts {
|
||||
|
||||
// If the parser encountered an error when parsing the code that created this node. Note
|
||||
// the parser only sets this directly on the node it creates right after encountering the
|
||||
// error.
|
||||
// error.
|
||||
ThisNodeHasError = 1 << 4,
|
||||
|
||||
// Context flags set directly by the parser.
|
||||
@@ -335,7 +337,7 @@ module ts {
|
||||
|
||||
// Context flags computed by aggregating child flags upwards.
|
||||
|
||||
// Used during incremental parsing to determine if this node or any of its children had an
|
||||
// Used during incremental parsing to determine if this node or any of its children had an
|
||||
// error. Computed only once and then cached.
|
||||
ThisNodeOrAnySubNodesHasError = 1 << 5,
|
||||
|
||||
@@ -352,7 +354,7 @@ module ts {
|
||||
export interface Node extends TextRange {
|
||||
kind: SyntaxKind;
|
||||
flags: NodeFlags;
|
||||
// Specific context the parser was in when this node was created. Normally undefined.
|
||||
// Specific context the parser was in when this node was created. Normally undefined.
|
||||
// Only set when the parser was in some interesting context (like async/yield).
|
||||
parserContextFlags?: ParserContextFlags;
|
||||
modifiers?: ModifiersArray; // Array of modifiers
|
||||
@@ -501,7 +503,7 @@ module ts {
|
||||
}
|
||||
|
||||
export interface FunctionDeclaration extends FunctionLikeDeclaration, Statement {
|
||||
name: Identifier;
|
||||
name?: Identifier;
|
||||
body?: Block;
|
||||
}
|
||||
|
||||
@@ -522,7 +524,7 @@ module ts {
|
||||
body?: Block;
|
||||
}
|
||||
|
||||
// See the comment on MethodDeclaration for the intuition behind AccessorDeclaration being a
|
||||
// See the comment on MethodDeclaration for the intuition behind AccessorDeclaration being a
|
||||
// ClassElement and an ObjectLiteralElement.
|
||||
export interface AccessorDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement {
|
||||
_accessorDeclarationBrand: any;
|
||||
@@ -573,12 +575,12 @@ module ts {
|
||||
|
||||
export interface StringLiteralTypeNode extends LiteralExpression, TypeNode { }
|
||||
|
||||
// Note: 'brands' in our syntax nodes serve to give us a small amount of nominal typing.
|
||||
// Note: 'brands' in our syntax nodes serve to give us a small amount of nominal typing.
|
||||
// Consider 'Expression'. Without the brand, 'Expression' is actually no different
|
||||
// (structurally) than 'Node'. Because of this you can pass any Node to a function that
|
||||
// takes an Expression without any error. By using the 'brands' we ensure that the type
|
||||
// checker actually thinks you have something of the right type. Note: the brands are
|
||||
// never actually given values. At runtime they have zero cost.
|
||||
// checker actually thinks you have something of the right type. Note: the brands are
|
||||
// never actually given values. At runtime they have zero cost.
|
||||
|
||||
export interface Expression extends Node {
|
||||
_expressionBrand: any;
|
||||
@@ -640,7 +642,9 @@ module ts {
|
||||
|
||||
export interface ConditionalExpression extends Expression {
|
||||
condition: Expression;
|
||||
questionToken: Node;
|
||||
whenTrue: Expression;
|
||||
colonToken: Node;
|
||||
whenFalse: Expression;
|
||||
}
|
||||
|
||||
@@ -649,6 +653,10 @@ module ts {
|
||||
body: Block | Expression; // Required, whereas the member inherited from FunctionDeclaration is optional
|
||||
}
|
||||
|
||||
export interface ArrowFunction extends Expression, FunctionLikeDeclaration {
|
||||
equalsGreaterThanToken: Node;
|
||||
}
|
||||
|
||||
// The text property of a LiteralExpression stores the interpreted value of the literal in text form. For a StringLiteral,
|
||||
// or any literal of a template, this means quotes have been removed and escapes have been converted to actual characters.
|
||||
// For a NumericLiteral, the stored value is the toString() representation of the number. For example 1, 1.00, and 1e0 are all stored as just "1".
|
||||
@@ -693,6 +701,7 @@ module ts {
|
||||
|
||||
export interface PropertyAccessExpression extends MemberExpression {
|
||||
expression: LeftHandSideExpression;
|
||||
dotToken: Node;
|
||||
name: Identifier;
|
||||
}
|
||||
|
||||
@@ -730,7 +739,7 @@ module ts {
|
||||
}
|
||||
|
||||
export interface VariableStatement extends Statement {
|
||||
declarationList: VariableDeclarationList;
|
||||
declarationList: VariableDeclarationList;
|
||||
}
|
||||
|
||||
export interface ExpressionStatement extends Statement {
|
||||
@@ -786,6 +795,10 @@ module ts {
|
||||
|
||||
export interface SwitchStatement extends Statement {
|
||||
expression: Expression;
|
||||
caseBlock: CaseBlock;
|
||||
}
|
||||
|
||||
export interface CaseBlock extends Node {
|
||||
clauses: NodeArray<CaseOrDefaultClause>;
|
||||
}
|
||||
|
||||
@@ -825,7 +838,7 @@ module ts {
|
||||
}
|
||||
|
||||
export interface ClassDeclaration extends Declaration, ModuleElement {
|
||||
name: Identifier;
|
||||
name?: Identifier;
|
||||
typeParameters?: NodeArray<TypeParameterDeclaration>;
|
||||
heritageClauses?: NodeArray<HeritageClause>;
|
||||
members: NodeArray<ClassElement>;
|
||||
@@ -864,11 +877,7 @@ module ts {
|
||||
members: NodeArray<EnumMember>;
|
||||
}
|
||||
|
||||
export interface ExportContainer {
|
||||
exportStars?: ExportDeclaration[]; // List of 'export *' statements (initialized by binding)
|
||||
}
|
||||
|
||||
export interface ModuleDeclaration extends Declaration, ModuleElement, ExportContainer {
|
||||
export interface ModuleDeclaration extends Declaration, ModuleElement {
|
||||
name: Identifier | LiteralExpression;
|
||||
body: ModuleBlock | ModuleDeclaration;
|
||||
}
|
||||
@@ -898,7 +907,7 @@ module ts {
|
||||
moduleSpecifier: Expression;
|
||||
}
|
||||
|
||||
// In case of:
|
||||
// In case of:
|
||||
// import d from "mod" => name = d, namedBinding = undefined
|
||||
// import * as ns from "mod" => name = undefined, namedBinding: NamespaceImport = { name: ns }
|
||||
// import d, * as ns from "mod" => name = d, namedBinding: NamespaceImport = { name: ns }
|
||||
@@ -913,7 +922,7 @@ module ts {
|
||||
name: Identifier;
|
||||
}
|
||||
|
||||
export interface ExportDeclaration extends Statement, ModuleElement {
|
||||
export interface ExportDeclaration extends Declaration, ModuleElement {
|
||||
exportClause?: NamedExports;
|
||||
moduleSpecifier?: Expression;
|
||||
}
|
||||
@@ -933,8 +942,10 @@ module ts {
|
||||
export type ImportSpecifier = ImportOrExportSpecifier;
|
||||
export type ExportSpecifier = ImportOrExportSpecifier;
|
||||
|
||||
export interface ExportAssignment extends Statement, ModuleElement {
|
||||
exportName: Identifier;
|
||||
export interface ExportAssignment extends Declaration, ModuleElement {
|
||||
isExportEquals?: boolean;
|
||||
expression?: Expression;
|
||||
type?: TypeNode;
|
||||
}
|
||||
|
||||
export interface FileReference extends TextRange {
|
||||
@@ -946,7 +957,7 @@ module ts {
|
||||
}
|
||||
|
||||
// Source files are declarations when they are external modules.
|
||||
export interface SourceFile extends Declaration, ExportContainer {
|
||||
export interface SourceFile extends Declaration {
|
||||
statements: NodeArray<ModuleElement>;
|
||||
endOfFileToken: Node;
|
||||
|
||||
@@ -963,7 +974,7 @@ module ts {
|
||||
externalModuleIndicator: Node;
|
||||
languageVersion: ScriptTarget;
|
||||
identifiers: Map<string>;
|
||||
|
||||
|
||||
/* @internal */ nodeCount: number;
|
||||
/* @internal */ identifierCount: number;
|
||||
/* @internal */ symbolCount: number;
|
||||
@@ -971,10 +982,10 @@ module ts {
|
||||
// File level diagnostics reported by the parser (includes diagnostics about /// references
|
||||
// as well as code diagnostics).
|
||||
/* @internal */ parseDiagnostics: Diagnostic[];
|
||||
|
||||
|
||||
// File level diagnostics reported by the binder.
|
||||
/* @internal */ bindDiagnostics: Diagnostic[];
|
||||
|
||||
|
||||
// Stores a line map for the file.
|
||||
// This field should never be used directly to obtain line map, use getLineMap function instead.
|
||||
/* @internal */ lineMap: number[];
|
||||
@@ -994,10 +1005,10 @@ module ts {
|
||||
getSourceFiles(): SourceFile[];
|
||||
|
||||
/**
|
||||
* Emits the javascript and declaration files. If targetSourceFile is not specified, then
|
||||
* Emits the javascript and declaration files. If targetSourceFile is not specified, then
|
||||
* the javascript and declaration files will be produced for all the files in this program.
|
||||
* If targetSourceFile is specified, then only the javascript and declaration for that
|
||||
* specific file will be generated.
|
||||
* specific file will be generated.
|
||||
*
|
||||
* If writeFile is not specified then the writeFile callback from the compiler host will be
|
||||
* used for writing the javascript and declaration files. Otherwise, the writeFile parameter
|
||||
@@ -1015,7 +1026,7 @@ module ts {
|
||||
|
||||
getCommonSourceDirectory(): string;
|
||||
|
||||
// For testing purposes only. Should not be used by any other consumers (including the
|
||||
// For testing purposes only. Should not be used by any other consumers (including the
|
||||
// language service).
|
||||
/* @internal */ getDiagnosticsProducingTypeChecker(): TypeChecker;
|
||||
|
||||
@@ -1052,7 +1063,7 @@ module ts {
|
||||
// when -version or -help was provided, or this was a normal compilation, no diagnostics
|
||||
// were produced, and all outputs were generated successfully.
|
||||
Success = 0,
|
||||
|
||||
|
||||
// Diagnostics were produced and because of them no code was generated.
|
||||
DiagnosticsPresent_OutputsSkipped = 1,
|
||||
|
||||
@@ -1162,12 +1173,12 @@ module ts {
|
||||
|
||||
// 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 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
|
||||
WriteTypeParametersOrArguments = 0x00000001,
|
||||
WriteTypeParametersOrArguments = 0x00000001,
|
||||
|
||||
// Use only external alias information to get the symbol name in the given context
|
||||
// eg. module m { export class c { } } import x = m.c;
|
||||
// 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
|
||||
UseOnlyExternalAliasing = 0x00000002,
|
||||
}
|
||||
@@ -1190,10 +1201,10 @@ module ts {
|
||||
}
|
||||
|
||||
export interface EmitResolver {
|
||||
getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration | ExportDeclaration): string;
|
||||
getGeneratedNameForNode(node: Node): string;
|
||||
getExpressionNameSubstitution(node: Identifier): string;
|
||||
getExportAssignmentName(node: SourceFile): string;
|
||||
isReferencedImportDeclaration(node: Node): boolean;
|
||||
hasExportDefaultValue(node: SourceFile): boolean;
|
||||
isReferencedAliasDeclaration(node: Node): boolean;
|
||||
isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean;
|
||||
getNodeCheckFlags(node: Node): NodeCheckFlags;
|
||||
isDeclarationVisible(node: Declaration): boolean;
|
||||
@@ -1229,18 +1240,17 @@ module ts {
|
||||
Signature = 0x00020000, // Call, construct, or index signature
|
||||
TypeParameter = 0x00040000, // Type parameter
|
||||
TypeAlias = 0x00080000, // Type alias
|
||||
|
||||
// Export markers (see comment in declareModuleMember in binder)
|
||||
ExportValue = 0x00100000, // Exported value marker
|
||||
ExportType = 0x00200000, // Exported type marker
|
||||
ExportNamespace = 0x00400000, // Exported namespace marker
|
||||
Import = 0x00800000, // Import
|
||||
ExportValue = 0x00100000, // Exported value marker (see comment in declareModuleMember in binder)
|
||||
ExportType = 0x00200000, // Exported type marker (see comment in declareModuleMember in binder)
|
||||
ExportNamespace = 0x00400000, // Exported namespace marker (see comment in declareModuleMember in binder)
|
||||
Alias = 0x00800000, // An alias for another symbol (see comment in isAliasSymbolDeclaration in checker)
|
||||
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)
|
||||
UnionProperty = 0x10000000, // Property in union type
|
||||
Optional = 0x20000000, // Optional property
|
||||
ExportStar = 0x40000000, // Export * declaration
|
||||
|
||||
Enum = RegularEnum | ConstEnum,
|
||||
Variable = FunctionScopedVariable | BlockScopedVariable,
|
||||
@@ -1273,9 +1283,9 @@ module ts {
|
||||
SetAccessorExcludes = Value & ~GetAccessor,
|
||||
TypeParameterExcludes = Type & ~TypeParameter,
|
||||
TypeAliasExcludes = Type,
|
||||
ImportExcludes = Import, // Imports collide with all other imports with the same name
|
||||
AliasExcludes = Alias,
|
||||
|
||||
ModuleMember = Variable | Function | Class | Interface | Enum | Module | TypeAlias | Import,
|
||||
ModuleMember = Variable | Function | Class | Interface | Enum | Module | TypeAlias | Alias,
|
||||
|
||||
ExportHasLocal = Function | Class | Enum | ValueModule,
|
||||
|
||||
@@ -1308,10 +1318,9 @@ module ts {
|
||||
declaredType?: Type; // Type of class, interface, enum, or type parameter
|
||||
mapper?: TypeMapper; // Type mapper for instantiation alias
|
||||
referenced?: boolean; // True if alias symbol has been referenced as a value
|
||||
exportAssignmentChecked?: boolean; // True if export assignment was checked
|
||||
exportAssignmentSymbol?: Symbol; // Symbol exported from external module
|
||||
unionType?: UnionType; // Containing union type for union property
|
||||
resolvedExports?: SymbolTable; // Resolved exports of module
|
||||
exportsChecked?: boolean; // True if exports of external module have been checked
|
||||
}
|
||||
|
||||
export interface TransientSymbol extends Symbol, SymbolLinks { }
|
||||
@@ -1478,11 +1487,15 @@ module ts {
|
||||
(t: Type): Type;
|
||||
}
|
||||
|
||||
// @internal
|
||||
export interface TypeInferences {
|
||||
primary: Type[]; // Inferences made directly to a type parameter
|
||||
secondary: Type[]; // Inferences made to a type parameter in a union type
|
||||
isFixed: boolean; // Whether the type parameter is fixed, as defined in section 4.12.2 of the TypeScript spec
|
||||
// If a type parameter is fixed, no more inferences can be made for the type parameter
|
||||
}
|
||||
|
||||
// @internal
|
||||
export interface InferenceContext {
|
||||
typeParameters: TypeParameter[]; // Type parameters for which inferences are made
|
||||
inferUnionTypes: boolean; // Infer union types for disjoint candidates (otherwise undefinedType)
|
||||
@@ -1554,7 +1567,9 @@ module ts {
|
||||
target?: ScriptTarget;
|
||||
version?: boolean;
|
||||
watch?: boolean;
|
||||
stripInternal?: boolean;
|
||||
/* @internal */ stripInternal?: boolean;
|
||||
/* @internal */ preserveNewLines?: boolean;
|
||||
/* @internal */ cacheDownlevelForOfLength?: boolean;
|
||||
[option: string]: string | number | boolean;
|
||||
}
|
||||
|
||||
@@ -1772,7 +1787,7 @@ module ts {
|
||||
// Gets a count of how many times this collection has been modified. This value changes
|
||||
// each time 'add' is called (regardless of whether or not an equivalent diagnostic was
|
||||
// already in the collection). As such, it can be used as a simple way to tell if any
|
||||
// operation caused diagnostics to be returned by storing and comparing the return value
|
||||
// operation caused diagnostics to be returned by storing and comparing the return value
|
||||
// of this method before/after the operation is performed.
|
||||
getModificationCount(): number;
|
||||
}
|
||||
|
||||
+157
-99
@@ -14,9 +14,8 @@ module ts {
|
||||
}
|
||||
|
||||
export function getDeclarationOfKind(symbol: Symbol, kind: SyntaxKind): Declaration {
|
||||
var declarations = symbol.declarations;
|
||||
for (var i = 0; i < declarations.length; i++) {
|
||||
var declaration = declarations[i];
|
||||
let declarations = symbol.declarations;
|
||||
for (let declaration of declarations) {
|
||||
if (declaration.kind === kind) {
|
||||
return declaration;
|
||||
}
|
||||
@@ -40,12 +39,12 @@ module ts {
|
||||
}
|
||||
|
||||
// Pool writers to avoid needing to allocate them for every symbol we write.
|
||||
var stringWriters: StringSymbolWriter[] = [];
|
||||
let stringWriters: StringSymbolWriter[] = [];
|
||||
export function getSingleLineStringWriter(): StringSymbolWriter {
|
||||
if (stringWriters.length == 0) {
|
||||
var str = "";
|
||||
let str = "";
|
||||
|
||||
var writeText: (text: string) => void = text => str += text;
|
||||
let writeText: (text: string) => void = text => str += text;
|
||||
return {
|
||||
string: () => str,
|
||||
writeKeyword: writeText,
|
||||
@@ -89,7 +88,7 @@ module ts {
|
||||
// A node is considered to contain a parse error if:
|
||||
// a) the parser explicitly marked that it had an error
|
||||
// b) any of it's children reported that it had an error.
|
||||
var thisNodeOrAnySubNodesHasError = ((node.parserContextFlags & ParserContextFlags.ThisNodeHasError) !== 0) ||
|
||||
let thisNodeOrAnySubNodesHasError = ((node.parserContextFlags & ParserContextFlags.ThisNodeHasError) !== 0) ||
|
||||
forEachChild(node, containsParseError);
|
||||
|
||||
// If so, mark ourselves accordingly.
|
||||
@@ -118,8 +117,8 @@ module ts {
|
||||
|
||||
// This is a useful function for debugging purposes.
|
||||
export function nodePosToString(node: Node): string {
|
||||
var file = getSourceFileOfNode(node);
|
||||
var loc = getLineAndCharacterOfPosition(file, node.pos);
|
||||
let file = getSourceFileOfNode(node);
|
||||
let loc = getLineAndCharacterOfPosition(file, node.pos);
|
||||
return `${ file.fileName }(${ loc.line + 1 },${ loc.character + 1 })`;
|
||||
}
|
||||
|
||||
@@ -133,7 +132,7 @@ module ts {
|
||||
// missing. This happens whenever the parser knows it needs to parse something, but can't
|
||||
// get anything in the source code that it expects at that location. For example:
|
||||
//
|
||||
// var a: ;
|
||||
// let a: ;
|
||||
//
|
||||
// Here, the Type in the Type-Annotation is not-optional (as there is a colon in the source
|
||||
// code). So the parser will attempt to parse out a type, and will create an actual node.
|
||||
@@ -166,7 +165,7 @@ module ts {
|
||||
return "";
|
||||
}
|
||||
|
||||
var text = sourceFile.text;
|
||||
let text = sourceFile.text;
|
||||
return text.substring(skipTrivia(text, node.pos), node.end);
|
||||
}
|
||||
|
||||
@@ -203,6 +202,33 @@ module ts {
|
||||
isCatchClauseVariableDeclaration(declaration);
|
||||
}
|
||||
|
||||
export function getEnclosingBlockScopeContainer(node: Node): Node {
|
||||
let current = node;
|
||||
while (current) {
|
||||
if (isFunctionLike(current)) {
|
||||
return current;
|
||||
}
|
||||
switch (current.kind) {
|
||||
case SyntaxKind.SourceFile:
|
||||
case SyntaxKind.CaseBlock:
|
||||
case SyntaxKind.CatchClause:
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
case SyntaxKind.ForStatement:
|
||||
case SyntaxKind.ForInStatement:
|
||||
case SyntaxKind.ForOfStatement:
|
||||
return current;
|
||||
case SyntaxKind.Block:
|
||||
// function block is not considered block-scope container
|
||||
// see comment in binder.ts: bind(...), case for SyntaxKind.Block
|
||||
if (!isFunctionLike(current.parent)) {
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
current = current.parent;
|
||||
}
|
||||
}
|
||||
|
||||
export function isCatchClauseVariableDeclaration(declaration: Declaration) {
|
||||
return declaration &&
|
||||
declaration.kind === SyntaxKind.VariableDeclaration &&
|
||||
@@ -218,32 +244,35 @@ module ts {
|
||||
}
|
||||
|
||||
export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): Diagnostic {
|
||||
node = getErrorSpanForNode(node);
|
||||
var file = getSourceFileOfNode(node);
|
||||
|
||||
var start = getTokenPosOfNode(node, file);
|
||||
var length = node.end - start;
|
||||
|
||||
return createFileDiagnostic(file, start, length, message, arg0, arg1, arg2);
|
||||
let sourceFile = getSourceFileOfNode(node);
|
||||
let span = getErrorSpanForNode(sourceFile, node);
|
||||
return createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
export function createDiagnosticForNodeFromMessageChain(node: Node, messageChain: DiagnosticMessageChain): Diagnostic {
|
||||
node = getErrorSpanForNode(node);
|
||||
var file = getSourceFileOfNode(node);
|
||||
var start = skipTrivia(file.text, node.pos);
|
||||
var length = node.end - start;
|
||||
let sourceFile = getSourceFileOfNode(node);
|
||||
let span = getErrorSpanForNode(sourceFile, node);
|
||||
return {
|
||||
file,
|
||||
start,
|
||||
length,
|
||||
file: sourceFile,
|
||||
start: span.start,
|
||||
length: span.length,
|
||||
code: messageChain.code,
|
||||
category: messageChain.category,
|
||||
messageText: messageChain.next ? messageChain : messageChain.messageText
|
||||
};
|
||||
}
|
||||
|
||||
export function getErrorSpanForNode(node: Node): Node {
|
||||
var errorSpan: Node;
|
||||
/* @internal */
|
||||
export function getSpanOfTokenAtPosition(sourceFile: SourceFile, pos: number): TextSpan {
|
||||
let scanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ true, sourceFile.text);
|
||||
scanner.setTextPos(pos);
|
||||
scanner.scan();
|
||||
let start = scanner.getTokenPos();
|
||||
return createTextSpanFromBounds(start, scanner.getTextPos());
|
||||
}
|
||||
|
||||
export function getErrorSpanForNode(sourceFile: SourceFile, node: Node): TextSpan {
|
||||
let errorNode = node;
|
||||
switch (node.kind) {
|
||||
// This list is a work in progress. Add missing node kinds to improve their error
|
||||
// spans.
|
||||
@@ -254,16 +283,23 @@ module ts {
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
case SyntaxKind.EnumMember:
|
||||
errorSpan = (<Declaration>node).name;
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
errorNode = (<Declaration>node).name;
|
||||
break;
|
||||
}
|
||||
|
||||
if (errorNode === undefined) {
|
||||
// If we don't have a better node, then just set the error on the first token of
|
||||
// construct.
|
||||
return getSpanOfTokenAtPosition(sourceFile, node.pos);
|
||||
}
|
||||
|
||||
// We now have the ideal error span, but it may be a node that is optional and absent
|
||||
// (e.g. the name of a function expression), in which case errorSpan will be undefined.
|
||||
// Alternatively, it might be required and missing (e.g. the name of a module), in which
|
||||
// case its pos will equal its end (length 0). In either of these cases, we should fall
|
||||
// back to the original node that the error was issued on.
|
||||
return errorSpan && errorSpan.pos < errorSpan.end ? errorSpan : node;
|
||||
let pos = nodeIsMissing(errorNode)
|
||||
? errorNode.pos
|
||||
: skipTrivia(sourceFile.text, errorNode.pos);
|
||||
|
||||
return createTextSpanFromBounds(pos, errorNode.end);
|
||||
}
|
||||
|
||||
export function isExternalModule(file: SourceFile): boolean {
|
||||
@@ -296,7 +332,7 @@ module ts {
|
||||
export function getCombinedNodeFlags(node: Node): NodeFlags {
|
||||
node = walkUpBindingElementsAndPatterns(node);
|
||||
|
||||
var flags = node.flags;
|
||||
let flags = node.flags;
|
||||
if (node.kind === SyntaxKind.VariableDeclaration) {
|
||||
node = node.parent;
|
||||
}
|
||||
@@ -353,7 +389,7 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
export var fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*<reference\s+path\s*=\s*)('|")(.+?)\2.*?\/>/
|
||||
export let fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*<reference\s+path\s*=\s*)('|")(.+?)\2.*?\/>/
|
||||
|
||||
|
||||
// Warning: This has the same semantics as the forEach family of functions,
|
||||
@@ -366,6 +402,7 @@ module ts {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ReturnStatement:
|
||||
return visitor(<ReturnStatement>node);
|
||||
case SyntaxKind.CaseBlock:
|
||||
case SyntaxKind.Block:
|
||||
case SyntaxKind.IfStatement:
|
||||
case SyntaxKind.DoStatement:
|
||||
@@ -385,7 +422,26 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function isAnyFunction(node: Node): boolean {
|
||||
/* @internal */
|
||||
export function isVariableLike(node: Node): boolean {
|
||||
if (node) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.BindingElement:
|
||||
case SyntaxKind.EnumMember:
|
||||
case SyntaxKind.Parameter:
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.PropertySignature:
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isFunctionLike(node: Node): boolean {
|
||||
if (node) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.Constructor:
|
||||
@@ -412,7 +468,7 @@ module ts {
|
||||
}
|
||||
|
||||
export function isFunctionBlock(node: Node) {
|
||||
return node && node.kind === SyntaxKind.Block && isAnyFunction(node.parent);
|
||||
return node && node.kind === SyntaxKind.Block && isFunctionLike(node.parent);
|
||||
}
|
||||
|
||||
export function isObjectLiteralMethod(node: Node) {
|
||||
@@ -422,7 +478,7 @@ module ts {
|
||||
export function getContainingFunction(node: Node): FunctionLikeDeclaration {
|
||||
while (true) {
|
||||
node = node.parent;
|
||||
if (!node || isAnyFunction(node)) {
|
||||
if (!node || isFunctionLike(node)) {
|
||||
return <FunctionLikeDeclaration>node;
|
||||
}
|
||||
}
|
||||
@@ -563,7 +619,7 @@ module ts {
|
||||
// fall through
|
||||
case SyntaxKind.NumericLiteral:
|
||||
case SyntaxKind.StringLiteral:
|
||||
var parent = node.parent;
|
||||
let parent = node.parent;
|
||||
switch (parent.kind) {
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
case SyntaxKind.Parameter:
|
||||
@@ -585,13 +641,13 @@ module ts {
|
||||
case SyntaxKind.SwitchStatement:
|
||||
return (<ExpressionStatement>parent).expression === node;
|
||||
case SyntaxKind.ForStatement:
|
||||
var forStatement = <ForStatement>parent;
|
||||
let forStatement = <ForStatement>parent;
|
||||
return (forStatement.initializer === node && forStatement.initializer.kind !== SyntaxKind.VariableDeclarationList) ||
|
||||
forStatement.condition === node ||
|
||||
forStatement.iterator === node;
|
||||
case SyntaxKind.ForInStatement:
|
||||
case SyntaxKind.ForOfStatement:
|
||||
var forInStatement = <ForInStatement | ForOfStatement>parent;
|
||||
let forInStatement = <ForInStatement | ForOfStatement>parent;
|
||||
return (forInStatement.initializer === node && forInStatement.initializer.kind !== SyntaxKind.VariableDeclarationList) ||
|
||||
forInStatement.expression === node;
|
||||
case SyntaxKind.TypeAssertionExpression:
|
||||
@@ -610,7 +666,7 @@ module ts {
|
||||
}
|
||||
|
||||
export function isInstantiatedModule(node: ModuleDeclaration, preserveConstEnums: boolean) {
|
||||
var moduleState = getModuleInstanceState(node)
|
||||
let moduleState = getModuleInstanceState(node)
|
||||
return moduleState === ModuleInstanceState.Instantiated ||
|
||||
(preserveConstEnums && moduleState === ModuleInstanceState.ConstEnumOnly);
|
||||
}
|
||||
@@ -633,7 +689,7 @@ module ts {
|
||||
return (<ImportDeclaration>node).moduleSpecifier;
|
||||
}
|
||||
if (node.kind === SyntaxKind.ImportEqualsDeclaration) {
|
||||
var reference = (<ImportEqualsDeclaration>node).moduleReference;
|
||||
let reference = (<ImportEqualsDeclaration>node).moduleReference;
|
||||
if (reference.kind === SyntaxKind.ExternalModuleReference) {
|
||||
return (<ExternalModuleReference>reference).expression;
|
||||
}
|
||||
@@ -764,7 +820,7 @@ module ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
var parent = name.parent;
|
||||
let parent = name.parent;
|
||||
if (parent.kind === SyntaxKind.ImportSpecifier || parent.kind === SyntaxKind.ExportSpecifier) {
|
||||
if ((<ImportOrExportSpecifier>parent).propertyName) {
|
||||
return true;
|
||||
@@ -779,25 +835,25 @@ module ts {
|
||||
}
|
||||
|
||||
export function getClassBaseTypeNode(node: ClassDeclaration) {
|
||||
var heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword);
|
||||
let heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword);
|
||||
return heritageClause && heritageClause.types.length > 0 ? heritageClause.types[0] : undefined;
|
||||
}
|
||||
|
||||
export function getClassImplementedTypeNodes(node: ClassDeclaration) {
|
||||
var heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ImplementsKeyword);
|
||||
let heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ImplementsKeyword);
|
||||
return heritageClause ? heritageClause.types : undefined;
|
||||
}
|
||||
|
||||
export function getInterfaceBaseTypeNodes(node: InterfaceDeclaration) {
|
||||
var heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword);
|
||||
let heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword);
|
||||
return heritageClause ? heritageClause.types : undefined;
|
||||
}
|
||||
|
||||
export function getHeritageClause(clauses: NodeArray<HeritageClause>, kind: SyntaxKind) {
|
||||
if (clauses) {
|
||||
for (var i = 0, n = clauses.length; i < n; i++) {
|
||||
if (clauses[i].token === kind) {
|
||||
return clauses[i];
|
||||
for (let clause of clauses) {
|
||||
if (clause.token === kind) {
|
||||
return clause;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -807,7 +863,7 @@ module ts {
|
||||
|
||||
export function tryResolveScriptReference(host: ScriptReferenceHost, sourceFile: SourceFile, reference: FileReference) {
|
||||
if (!host.getCompilerOptions().noResolve) {
|
||||
var referenceFileName = isRootedDiskPath(reference.fileName) ? reference.fileName : combinePaths(getDirectoryPath(sourceFile.fileName), reference.fileName);
|
||||
let referenceFileName = isRootedDiskPath(reference.fileName) ? reference.fileName : combinePaths(getDirectoryPath(sourceFile.fileName), reference.fileName);
|
||||
referenceFileName = getNormalizedAbsolutePath(referenceFileName, host.getCurrentDirectory());
|
||||
return host.getSourceFile(referenceFileName);
|
||||
}
|
||||
@@ -824,8 +880,8 @@ module ts {
|
||||
}
|
||||
|
||||
export function getFileReferenceFromReferencePath(comment: string, commentRange: CommentRange): ReferencePathMatchResult {
|
||||
var simpleReferenceRegEx = /^\/\/\/\s*<reference\s+/gim;
|
||||
var isNoDefaultLibRegEx = /^(\/\/\/\s*<reference\s+no-default-lib\s*=\s*)('|")(.+?)\2\s*\/>/gim;
|
||||
let simpleReferenceRegEx = /^\/\/\/\s*<reference\s+/gim;
|
||||
let isNoDefaultLibRegEx = /^(\/\/\/\s*<reference\s+no-default-lib\s*=\s*)('|")(.+?)\2\s*\/>/gim;
|
||||
if (simpleReferenceRegEx.exec(comment)) {
|
||||
if (isNoDefaultLibRegEx.exec(comment)) {
|
||||
return {
|
||||
@@ -833,10 +889,10 @@ module ts {
|
||||
}
|
||||
}
|
||||
else {
|
||||
var matchResult = fullTripleSlashReferencePathRegEx.exec(comment);
|
||||
let matchResult = fullTripleSlashReferencePathRegEx.exec(comment);
|
||||
if (matchResult) {
|
||||
var start = commentRange.pos;
|
||||
var end = commentRange.end;
|
||||
let start = commentRange.pos;
|
||||
let end = commentRange.end;
|
||||
return {
|
||||
fileReference: {
|
||||
pos: start,
|
||||
@@ -893,9 +949,9 @@ module ts {
|
||||
return (<Identifier | LiteralExpression>name).text;
|
||||
}
|
||||
if (name.kind === SyntaxKind.ComputedPropertyName) {
|
||||
var nameExpression = (<ComputedPropertyName>name).expression;
|
||||
let nameExpression = (<ComputedPropertyName>name).expression;
|
||||
if (isWellKnownSymbolSyntactically(nameExpression)) {
|
||||
var rightHandSideName = (<PropertyAccessExpression>nameExpression).name.text;
|
||||
let rightHandSideName = (<PropertyAccessExpression>nameExpression).name.text;
|
||||
return getPropertyNameForKnownSymbolName(rightHandSideName);
|
||||
}
|
||||
}
|
||||
@@ -923,6 +979,7 @@ module ts {
|
||||
case SyntaxKind.ExportKeyword:
|
||||
case SyntaxKind.DeclareKeyword:
|
||||
case SyntaxKind.ConstKeyword:
|
||||
case SyntaxKind.DefaultKeyword:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -946,14 +1003,14 @@ module ts {
|
||||
}
|
||||
|
||||
export function textSpanOverlapsWith(span: TextSpan, other: TextSpan) {
|
||||
var overlapStart = Math.max(span.start, other.start);
|
||||
var overlapEnd = Math.min(textSpanEnd(span), textSpanEnd(other));
|
||||
let overlapStart = Math.max(span.start, other.start);
|
||||
let overlapEnd = Math.min(textSpanEnd(span), textSpanEnd(other));
|
||||
return overlapStart < overlapEnd;
|
||||
}
|
||||
|
||||
export function textSpanOverlap(span1: TextSpan, span2: TextSpan) {
|
||||
var overlapStart = Math.max(span1.start, span2.start);
|
||||
var overlapEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2));
|
||||
let overlapStart = Math.max(span1.start, span2.start);
|
||||
let overlapEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2));
|
||||
if (overlapStart < overlapEnd) {
|
||||
return createTextSpanFromBounds(overlapStart, overlapEnd);
|
||||
}
|
||||
@@ -965,7 +1022,7 @@ module ts {
|
||||
}
|
||||
|
||||
export function textSpanIntersectsWith(span: TextSpan, start: number, length: number) {
|
||||
var end = start + length;
|
||||
let end = start + length;
|
||||
return start <= textSpanEnd(span) && end >= span.start;
|
||||
}
|
||||
|
||||
@@ -974,8 +1031,8 @@ module ts {
|
||||
}
|
||||
|
||||
export function textSpanIntersection(span1: TextSpan, span2: TextSpan) {
|
||||
var intersectStart = Math.max(span1.start, span2.start);
|
||||
var intersectEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2));
|
||||
let intersectStart = Math.max(span1.start, span2.start);
|
||||
let intersectEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2));
|
||||
if (intersectStart <= intersectEnd) {
|
||||
return createTextSpanFromBounds(intersectStart, intersectEnd);
|
||||
}
|
||||
@@ -1013,7 +1070,7 @@ module ts {
|
||||
return { span, newLength };
|
||||
}
|
||||
|
||||
export var unchangedTextChangeRange = createTextChangeRange(createTextSpan(0, 0), 0);
|
||||
export let unchangedTextChangeRange = createTextChangeRange(createTextSpan(0, 0), 0);
|
||||
|
||||
/**
|
||||
* Called to merge all the changes that occurred across several versions of a script snapshot
|
||||
@@ -1034,14 +1091,14 @@ module ts {
|
||||
|
||||
// We change from talking about { { oldStart, oldLength }, newLength } to { oldStart, oldEnd, newEnd }
|
||||
// as it makes things much easier to reason about.
|
||||
var change0 = changes[0];
|
||||
let change0 = changes[0];
|
||||
|
||||
var oldStartN = change0.span.start;
|
||||
var oldEndN = textSpanEnd(change0.span);
|
||||
var newEndN = oldStartN + change0.newLength;
|
||||
let oldStartN = change0.span.start;
|
||||
let oldEndN = textSpanEnd(change0.span);
|
||||
let newEndN = oldStartN + change0.newLength;
|
||||
|
||||
for (var i = 1; i < changes.length; i++) {
|
||||
var nextChange = changes[i];
|
||||
for (let i = 1; i < changes.length; i++) {
|
||||
let nextChange = changes[i];
|
||||
|
||||
// Consider the following case:
|
||||
// i.e. two edits. The first represents the text change range { { 10, 50 }, 30 }. i.e. The span starting
|
||||
@@ -1123,13 +1180,13 @@ module ts {
|
||||
// newEnd3 : Max(newEnd2, newEnd2 + (newEnd1 - oldEnd2))
|
||||
// }
|
||||
|
||||
var oldStart1 = oldStartN;
|
||||
var oldEnd1 = oldEndN;
|
||||
var newEnd1 = newEndN;
|
||||
let oldStart1 = oldStartN;
|
||||
let oldEnd1 = oldEndN;
|
||||
let newEnd1 = newEndN;
|
||||
|
||||
var oldStart2 = nextChange.span.start;
|
||||
var oldEnd2 = textSpanEnd(nextChange.span);
|
||||
var newEnd2 = oldStart2 + nextChange.newLength;
|
||||
let oldStart2 = nextChange.span.start;
|
||||
let oldEnd2 = textSpanEnd(nextChange.span);
|
||||
let newEnd2 = oldStart2 + nextChange.newLength;
|
||||
|
||||
oldStartN = Math.min(oldStart1, oldStart2);
|
||||
oldEndN = Math.max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1));
|
||||
@@ -1140,15 +1197,15 @@ module ts {
|
||||
}
|
||||
|
||||
export function nodeStartsNewLexicalEnvironment(n: Node): boolean {
|
||||
return isAnyFunction(n) || n.kind === SyntaxKind.ModuleDeclaration || n.kind === SyntaxKind.SourceFile;
|
||||
return isFunctionLike(n) || n.kind === SyntaxKind.ModuleDeclaration || n.kind === SyntaxKind.SourceFile;
|
||||
}
|
||||
|
||||
export function nodeIsSynthesized(node: Node): boolean {
|
||||
return node.pos === -1 && node.end === -1;
|
||||
return node.pos === -1;
|
||||
}
|
||||
|
||||
export function createSynthesizedNode(kind: SyntaxKind, startsOnNewLine?: boolean): Node {
|
||||
var node = <SynthesizedNode>createNode(kind);
|
||||
let node = <SynthesizedNode>createNode(kind);
|
||||
node.pos = -1;
|
||||
node.end = -1;
|
||||
node.startsOnNewLine = startsOnNewLine;
|
||||
@@ -1158,7 +1215,7 @@ module ts {
|
||||
export function generateUniqueName(baseName: string, isExistingName: (name: string) => boolean): string {
|
||||
// First try '_name'
|
||||
if (baseName.charCodeAt(0) !== CharacterCodes._) {
|
||||
var baseName = "_" + baseName;
|
||||
baseName = "_" + baseName;
|
||||
if (!isExistingName(baseName)) {
|
||||
return baseName;
|
||||
}
|
||||
@@ -1167,9 +1224,9 @@ module ts {
|
||||
if (baseName.charCodeAt(baseName.length - 1) !== CharacterCodes._) {
|
||||
baseName += "_";
|
||||
}
|
||||
var i = 1;
|
||||
let i = 1;
|
||||
while (true) {
|
||||
var name = baseName + i;
|
||||
let name = baseName + i;
|
||||
if (!isExistingName(name)) {
|
||||
return name;
|
||||
}
|
||||
@@ -1177,12 +1234,13 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
// @internal
|
||||
export function createDiagnosticCollection(): DiagnosticCollection {
|
||||
var nonFileDiagnostics: Diagnostic[] = [];
|
||||
var fileDiagnostics: Map<Diagnostic[]> = {};
|
||||
let nonFileDiagnostics: Diagnostic[] = [];
|
||||
let fileDiagnostics: Map<Diagnostic[]> = {};
|
||||
|
||||
var diagnosticsModified = false;
|
||||
var modificationCount = 0;
|
||||
let diagnosticsModified = false;
|
||||
let modificationCount = 0;
|
||||
|
||||
return {
|
||||
add,
|
||||
@@ -1196,7 +1254,7 @@ module ts {
|
||||
}
|
||||
|
||||
function add(diagnostic: Diagnostic): void {
|
||||
var diagnostics: Diagnostic[];
|
||||
let diagnostics: Diagnostic[];
|
||||
if (diagnostic.file) {
|
||||
diagnostics = fileDiagnostics[diagnostic.file.fileName];
|
||||
if (!diagnostics) {
|
||||
@@ -1224,14 +1282,14 @@ module ts {
|
||||
return fileDiagnostics[fileName] || [];
|
||||
}
|
||||
|
||||
var allDiagnostics: Diagnostic[] = [];
|
||||
let allDiagnostics: Diagnostic[] = [];
|
||||
function pushDiagnostic(d: Diagnostic) {
|
||||
allDiagnostics.push(d);
|
||||
}
|
||||
|
||||
forEach(nonFileDiagnostics, pushDiagnostic);
|
||||
|
||||
for (var key in fileDiagnostics) {
|
||||
for (let key in fileDiagnostics) {
|
||||
if (hasProperty(fileDiagnostics, key)) {
|
||||
forEach(fileDiagnostics[key], pushDiagnostic);
|
||||
}
|
||||
@@ -1248,7 +1306,7 @@ module ts {
|
||||
diagnosticsModified = false;
|
||||
nonFileDiagnostics = sortAndDeduplicateDiagnostics(nonFileDiagnostics);
|
||||
|
||||
for (var key in fileDiagnostics) {
|
||||
for (let key in fileDiagnostics) {
|
||||
if (hasProperty(fileDiagnostics, key)) {
|
||||
fileDiagnostics[key] = sortAndDeduplicateDiagnostics(fileDiagnostics[key]);
|
||||
}
|
||||
@@ -1261,8 +1319,8 @@ module ts {
|
||||
// the language service. These characters should be escaped when printing, and if any characters are added,
|
||||
// the map below must be updated. Note that this regexp *does not* include the 'delete' character.
|
||||
// There is no reason for this other than that JSON.stringify does not handle it either.
|
||||
var escapedCharsRegExp = /[\\\"\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
|
||||
var escapedCharsMap: Map<string> = {
|
||||
let escapedCharsRegExp = /[\\\"\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
|
||||
let escapedCharsMap: Map<string> = {
|
||||
"\0": "\\0",
|
||||
"\t": "\\t",
|
||||
"\v": "\\v",
|
||||
@@ -1293,12 +1351,12 @@ module ts {
|
||||
}
|
||||
|
||||
function get16BitUnicodeEscapeSequence(charCode: number): string {
|
||||
var hexCharCode = charCode.toString(16).toUpperCase();
|
||||
var paddedHexCode = ("0000" + hexCharCode).slice(-4);
|
||||
let hexCharCode = charCode.toString(16).toUpperCase();
|
||||
let paddedHexCode = ("0000" + hexCharCode).slice(-4);
|
||||
return "\\u" + paddedHexCode;
|
||||
}
|
||||
|
||||
var nonAsciiCharacters = /[^\u0000-\u007F]/g;
|
||||
let nonAsciiCharacters = /[^\u0000-\u007F]/g;
|
||||
export function escapeNonAsciiCharacters(s: string): string {
|
||||
// Replace non-ASCII characters with '\uNNNN' escapes if any exist.
|
||||
// Otherwise just return the original string.
|
||||
@@ -1306,4 +1364,4 @@ module ts {
|
||||
s.replace(nonAsciiCharacters, c => get16BitUnicodeEscapeSequence(c.charCodeAt(0))) :
|
||||
s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +152,6 @@ 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);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1621,8 +1621,9 @@ module FourSlash {
|
||||
this.taoInvalidReason = 'verifyIndentationAtCurrentPosition NYI';
|
||||
|
||||
var actual = this.getIndentation(this.activeFile.fileName, this.currentCaretPosition);
|
||||
if (actual != numberOfSpaces) {
|
||||
this.raiseError('verifyIndentationAtCurrentPosition failed - expected: ' + numberOfSpaces + ', actual: ' + actual);
|
||||
var lineCol = this.getLineColStringAtPosition(this.currentCaretPosition);
|
||||
if (actual !== numberOfSpaces) {
|
||||
this.raiseError('verifyIndentationAtCurrentPosition failed at ' + lineCol + ' - expected: ' + numberOfSpaces + ', actual: ' + actual);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1630,8 +1631,9 @@ module FourSlash {
|
||||
this.taoInvalidReason = 'verifyIndentationAtPosition NYI';
|
||||
|
||||
var actual = this.getIndentation(fileName, position);
|
||||
var lineCol = this.getLineColStringAtPosition(position);
|
||||
if (actual !== numberOfSpaces) {
|
||||
this.raiseError('verifyIndentationAtPosition failed - expected: ' + numberOfSpaces + ', actual: ' + actual);
|
||||
this.raiseError('verifyIndentationAtPosition failed at ' + lineCol + ' - expected: ' + numberOfSpaces + ', actual: ' + actual);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-12
@@ -835,7 +835,7 @@ module Harness {
|
||||
// Register input files
|
||||
function register(file: { unitName: string; content: string; }) {
|
||||
if (file.content !== undefined) {
|
||||
var fileName = ts.normalizeSlashes(file.unitName);
|
||||
var fileName = ts.normalizePath(file.unitName);
|
||||
filemap[getCanonicalFileName(fileName)] = createSourceFileAndAssertInvariants(fileName, file.content, scriptTarget);
|
||||
}
|
||||
};
|
||||
@@ -844,6 +844,7 @@ module Harness {
|
||||
return {
|
||||
getCurrentDirectory,
|
||||
getSourceFile: (fn, languageVersion) => {
|
||||
fn = ts.normalizePath(fn);
|
||||
if (Object.prototype.hasOwnProperty.call(filemap, getCanonicalFileName(fn))) {
|
||||
return filemap[getCanonicalFileName(fn)];
|
||||
}
|
||||
@@ -1007,6 +1008,10 @@ module Harness {
|
||||
options.outDir = setting.value;
|
||||
break;
|
||||
|
||||
case 'preservenewlines':
|
||||
options.preserveNewLines = !!setting.value;
|
||||
break;
|
||||
|
||||
case 'sourceroot':
|
||||
options.sourceRoot = setting.value;
|
||||
break;
|
||||
@@ -1074,16 +1079,6 @@ module Harness {
|
||||
}
|
||||
});
|
||||
|
||||
var filemap: { [name: string]: ts.SourceFile; } = {};
|
||||
var register = (file: { unitName: string; content: string; }) => {
|
||||
if (file.content !== undefined) {
|
||||
var fileName = ts.normalizeSlashes(file.unitName);
|
||||
filemap[getCanonicalFileName(fileName)] = createSourceFileAndAssertInvariants(fileName, file.content, options.target, assertInvariants);
|
||||
}
|
||||
};
|
||||
inputFiles.forEach(register);
|
||||
otherFiles.forEach(register);
|
||||
|
||||
var fileOutputs: GeneratedFile[] = [];
|
||||
|
||||
var programFiles = inputFiles.map(file => file.unitName);
|
||||
@@ -1470,7 +1465,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", "noemitonerror", "noimplicitany", "noresolve", "newline", "newlines", "emitbom", "errortruncation", "usecasesensitivefilenames", "preserveconstenums", "includebuiltfile", "suppressimplicitanyindexerrors", "stripinternal"];
|
||||
var fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outdir", "noemitonerror", "noimplicitany", "noresolve", "newline", "newlines", "emitbom", "errortruncation", "usecasesensitivefilenames", "preserveconstenums", "preservenewlines", "includebuiltfile", "suppressimplicitanyindexerrors", "stripinternal"];
|
||||
|
||||
function extractCompilerSettings(content: string): CompilerSetting[] {
|
||||
|
||||
|
||||
@@ -469,6 +469,7 @@ module Harness.LanguageService {
|
||||
this.writeMessage(message);
|
||||
}
|
||||
|
||||
|
||||
readFile(fileName: string): string {
|
||||
if (fileName.indexOf(Harness.Compiler.defaultLibFileName) >= 0) {
|
||||
fileName = Harness.Compiler.defaultLibFileName;
|
||||
@@ -526,6 +527,15 @@ module Harness.LanguageService {
|
||||
msg(message: string) {
|
||||
return this.host.log(message);
|
||||
}
|
||||
|
||||
loggingEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
isVerbose() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
endGroup(): void {
|
||||
}
|
||||
|
||||
Vendored
+9
-3
@@ -164,19 +164,19 @@ interface ObjectConstructor {
|
||||
* Prevents the modification of attributes of existing properties, and prevents the addition of new properties.
|
||||
* @param o Object on which to lock the attributes.
|
||||
*/
|
||||
seal(o: any): any;
|
||||
seal<T>(o: T): T;
|
||||
|
||||
/**
|
||||
* Prevents the modification of existing property attributes and values, and prevents the addition of new properties.
|
||||
* @param o Object on which to lock the attributes.
|
||||
*/
|
||||
freeze(o: any): any;
|
||||
freeze<T>(o: T): T;
|
||||
|
||||
/**
|
||||
* Prevents the addition of new properties to an object.
|
||||
* @param o Object to make non-extensible.
|
||||
*/
|
||||
preventExtensions(o: any): any;
|
||||
preventExtensions<T>(o: T): T;
|
||||
|
||||
/**
|
||||
* Returns true if existing property attributes cannot be modified in an object and new properties cannot be added to the object.
|
||||
@@ -410,6 +410,9 @@ interface String {
|
||||
*/
|
||||
substr(from: number, length?: number): string;
|
||||
|
||||
/** Returns the primitive value of the specified object. */
|
||||
valueOf(): string;
|
||||
|
||||
[index: number]: string;
|
||||
}
|
||||
|
||||
@@ -462,6 +465,9 @@ interface Number {
|
||||
* @param precision Number of significant digits. Must be in the range 1 - 21, inclusive.
|
||||
*/
|
||||
toPrecision(precision?: number): string;
|
||||
|
||||
/** Returns the primitive value of the specified object. */
|
||||
valueOf(): number;
|
||||
}
|
||||
|
||||
interface NumberConstructor {
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
module ts.server {
|
||||
export interface Logger {
|
||||
close(): void;
|
||||
isVerbose(): boolean;
|
||||
loggingEnabled(): boolean;
|
||||
perftrc(s: string): void;
|
||||
info(s: string): void;
|
||||
startGroup(): void;
|
||||
@@ -1071,6 +1073,7 @@ module ts.server {
|
||||
|
||||
static changeNumberThreshold = 8;
|
||||
static changeLengthThreshold = 256;
|
||||
static maxVersions = 8;
|
||||
|
||||
// REVIEW: can optimize by coalescing simple edits
|
||||
edit(pos: number, deleteLen: number, insertedText?: string) {
|
||||
@@ -1131,6 +1134,13 @@ module ts.server {
|
||||
this.currentVersion = snap.version;
|
||||
this.versions[snap.version] = snap;
|
||||
this.changes = [];
|
||||
if ((this.currentVersion - this.minVersion) >= ScriptVersionCache.maxVersions) {
|
||||
var oldMin = this.minVersion;
|
||||
this.minVersion = (this.currentVersion - ScriptVersionCache.maxVersions) + 1;
|
||||
for (var j = oldMin; j < this.minVersion; j++) {
|
||||
this.versions[j] = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
return snap;
|
||||
}
|
||||
|
||||
+59
-4
@@ -19,7 +19,7 @@ module ts.server {
|
||||
inGroup = false;
|
||||
firstInGroup = true;
|
||||
|
||||
constructor(public logFilename: string) {
|
||||
constructor(public logFilename: string, public level: string) {
|
||||
}
|
||||
|
||||
static padStringRight(str: string, padding: string) {
|
||||
@@ -51,9 +51,20 @@ module ts.server {
|
||||
this.firstInGroup = true;
|
||||
}
|
||||
|
||||
loggingEnabled() {
|
||||
return !!this.logFilename;
|
||||
}
|
||||
|
||||
isVerbose() {
|
||||
return this.loggingEnabled() && (this.level == "verbose");
|
||||
}
|
||||
|
||||
|
||||
msg(s: string, type = "Err") {
|
||||
if (this.fd < 0) {
|
||||
this.fd = fs.openSync(this.logFilename, "w");
|
||||
if (this.logFilename) {
|
||||
this.fd = fs.openSync(this.logFilename, "w");
|
||||
}
|
||||
}
|
||||
if (this.fd >= 0) {
|
||||
s = s + "\n";
|
||||
@@ -173,17 +184,61 @@ module ts.server {
|
||||
});
|
||||
|
||||
rl.on('close',() => {
|
||||
this.projectService.closeLog();
|
||||
this.projectService.log("Exiting...");
|
||||
this.projectService.closeLog();
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
interface LogOptions {
|
||||
file?: string;
|
||||
detailLevel?: string;
|
||||
}
|
||||
|
||||
function parseLoggingEnvironmentString(logEnvStr: string): LogOptions {
|
||||
var logEnv: LogOptions = {};
|
||||
var args = logEnvStr.split(' ');
|
||||
for (var i = 0, len = args.length; i < (len - 1); i += 2) {
|
||||
var option = args[i];
|
||||
var value = args[i + 1];
|
||||
if (option && value) {
|
||||
switch (option) {
|
||||
case "-file":
|
||||
logEnv.file = value;
|
||||
break;
|
||||
case "-level":
|
||||
logEnv.detailLevel = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return logEnv;
|
||||
}
|
||||
|
||||
// TSS_LOG "{ level: "normal | verbose | terse", file?: string}"
|
||||
function createLoggerFromEnv() {
|
||||
var fileName: string = undefined;
|
||||
var detailLevel = "normal";
|
||||
var logEnvStr = process.env["TSS_LOG"];
|
||||
if (logEnvStr) {
|
||||
var logEnv = parseLoggingEnvironmentString(logEnvStr);
|
||||
if (logEnv.file) {
|
||||
fileName = logEnv.file;
|
||||
}
|
||||
else {
|
||||
fileName = __dirname + "/.log" + process.pid.toString();
|
||||
}
|
||||
if (logEnv.detailLevel) {
|
||||
detailLevel = logEnv.detailLevel;
|
||||
}
|
||||
}
|
||||
return new Logger(fileName, detailLevel);
|
||||
}
|
||||
// This places log file in the directory containing editorServices.js
|
||||
// TODO: check that this location is writable
|
||||
var logger = new Logger(__dirname + "/.log" + process.pid.toString());
|
||||
|
||||
var logger = createLoggerFromEnv();
|
||||
|
||||
// REVIEW: for now this implementation uses polling.
|
||||
// The advantage of polling is that it works reliably
|
||||
|
||||
+61
-14
@@ -145,6 +145,9 @@ module ts.server {
|
||||
|
||||
send(msg: NodeJS._debugger.Message) {
|
||||
var json = JSON.stringify(msg);
|
||||
if (this.logger.isVerbose()) {
|
||||
this.logger.info(msg.type + ": " + json);
|
||||
}
|
||||
this.sendLineToClient('Content-Length: ' + (1 + Buffer.byteLength(json, 'utf8')) +
|
||||
'\r\n\r\n' + json);
|
||||
}
|
||||
@@ -461,19 +464,49 @@ module ts.server {
|
||||
var compilerService = project.compilerService;
|
||||
var position = compilerService.host.lineColToPosition(file, line, col);
|
||||
var edits = compilerService.languageService.getFormattingEditsAfterKeystroke(file, position, key,
|
||||
compilerService.formatCodeOptions);
|
||||
compilerService.formatCodeOptions);
|
||||
// Check whether we should auto-indent. This will be when
|
||||
// the position is on a line containing only whitespace.
|
||||
// This should leave the edits returned from
|
||||
// getFormattingEditsAfterKeytroke either empty or pertaining
|
||||
// only to the previous line. If all this is true, then
|
||||
// add edits necessary to properly indent the current line.
|
||||
if ((key == "\n") && ((!edits) || (edits.length == 0) || allEditsBeforePos(edits, position))) {
|
||||
// TODO: get these options from host
|
||||
var editorOptions: ts.EditorOptions = {
|
||||
IndentSize: 4,
|
||||
TabSize: 4,
|
||||
NewLineCharacter: "\n",
|
||||
ConvertTabsToSpaces: true,
|
||||
};
|
||||
var indentPosition = compilerService.languageService.getIndentationAtPosition(file, position, editorOptions);
|
||||
var spaces = generateSpaces(indentPosition);
|
||||
if (indentPosition > 0) {
|
||||
edits.push({ span: ts.createTextSpanFromBounds(position, position), newText: spaces });
|
||||
var scriptInfo = compilerService.host.getScriptInfo(file);
|
||||
if (scriptInfo) {
|
||||
var lineInfo = scriptInfo.getLineInfo(line);
|
||||
if (lineInfo && (lineInfo.leaf) && (lineInfo.leaf.text)) {
|
||||
var lineText = lineInfo.leaf.text;
|
||||
if (lineText.search("\\S") < 0) {
|
||||
// TODO: get these options from host
|
||||
var editorOptions: ts.EditorOptions = {
|
||||
IndentSize: 4,
|
||||
TabSize: 4,
|
||||
NewLineCharacter: "\n",
|
||||
ConvertTabsToSpaces: true,
|
||||
};
|
||||
var indentPosition =
|
||||
compilerService.languageService.getIndentationAtPosition(file, position, editorOptions);
|
||||
for (var i = 0, len = lineText.length; i < len; i++) {
|
||||
if (lineText.charAt(i) == " ") {
|
||||
indentPosition--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (indentPosition > 0) {
|
||||
var spaces = generateSpaces(indentPosition);
|
||||
edits.push({ span: ts.createTextSpanFromBounds(position, position), newText: spaces });
|
||||
}
|
||||
else if (indentPosition < 0) {
|
||||
edits.push({
|
||||
span: ts.createTextSpanFromBounds(position, position - indentPosition),
|
||||
newText: ""
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -491,7 +524,7 @@ module ts.server {
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
getCompletions(line: number, col: number, prefix: string, fileName: string): protocol.CompletionEntry[] {
|
||||
if (!prefix) {
|
||||
prefix = "";
|
||||
@@ -693,6 +726,10 @@ module ts.server {
|
||||
}
|
||||
|
||||
onMessage(message: string) {
|
||||
if (this.logger.isVerbose()) {
|
||||
this.logger.info("request: " + message);
|
||||
var start = process.hrtime();
|
||||
}
|
||||
try {
|
||||
var request = <protocol.Request>JSON.parse(message);
|
||||
var response: any;
|
||||
@@ -798,13 +835,23 @@ module ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.logger.isVerbose()) {
|
||||
var elapsed = process.hrtime(start);
|
||||
var seconds = elapsed[0]
|
||||
var nanoseconds = elapsed[1];
|
||||
var elapsedMs = ((1e9 * seconds) + nanoseconds)/1000000.0;
|
||||
var leader = "Elapsed time (in milliseconds)";
|
||||
if (!responseRequired) {
|
||||
leader = "Async elapsed time (in milliseconds)";
|
||||
}
|
||||
this.logger.msg(leader + ": " + elapsedMs.toFixed(4).toString(), "Perf");
|
||||
}
|
||||
if (response) {
|
||||
this.output(response, request.command, request.seq);
|
||||
}
|
||||
else if (responseRequired) {
|
||||
this.output(undefined, request.command, request.seq, "No content available.");
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
if (err instanceof OperationCanceledException) {
|
||||
// Handle cancellation exceptions
|
||||
|
||||
+29
-25
@@ -13,13 +13,13 @@ module ts.BreakpointResolver {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var tokenAtLocation = getTokenAtPosition(sourceFile, position);
|
||||
var lineOfPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
|
||||
let tokenAtLocation = getTokenAtPosition(sourceFile, position);
|
||||
let lineOfPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
|
||||
if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart()).line > lineOfPosition) {
|
||||
// Get previous token if the token is returned starts on new line
|
||||
// eg: var x =10; |--- cursor is here
|
||||
// var y = 10;
|
||||
// token at position will return var keyword on second line as the token but we would like to use
|
||||
// eg: let x =10; |--- cursor is here
|
||||
// let y = 10;
|
||||
// token at position will return let keyword on second line as the token but we would like to use
|
||||
// token on same line if trailing trivia (comments or white spaces on same line) part of the last token on that line
|
||||
tokenAtLocation = findPrecedingToken(tokenAtLocation.pos, sourceFile);
|
||||
|
||||
@@ -173,8 +173,12 @@ module ts.BreakpointResolver {
|
||||
return textSpan(node, (<ThrowStatement>node).expression);
|
||||
|
||||
case SyntaxKind.ExportAssignment:
|
||||
if (!(<ExportAssignment>node).expression) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// span on export = id
|
||||
return textSpan(node, (<ExportAssignment>node).exportName);
|
||||
return textSpan(node, (<ExportAssignment>node).expression);
|
||||
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
// import statement without including semicolon
|
||||
@@ -259,7 +263,7 @@ module ts.BreakpointResolver {
|
||||
}
|
||||
|
||||
// return type of function go to previous token
|
||||
if (isAnyFunction(node.parent) && (<FunctionLikeDeclaration>node.parent).type === node) {
|
||||
if (isFunctionLike(node.parent) && (<FunctionLikeDeclaration>node.parent).type === node) {
|
||||
return spanInPreviousNode(node);
|
||||
}
|
||||
|
||||
@@ -275,9 +279,9 @@ module ts.BreakpointResolver {
|
||||
return spanInNode(variableDeclaration.parent.parent);
|
||||
}
|
||||
|
||||
var isParentVariableStatement = variableDeclaration.parent.parent.kind === SyntaxKind.VariableStatement;
|
||||
var isDeclarationOfForStatement = variableDeclaration.parent.parent.kind === SyntaxKind.ForStatement && contains((<VariableDeclarationList>(<ForStatement>variableDeclaration.parent.parent).initializer).declarations, variableDeclaration);
|
||||
var declarations = isParentVariableStatement
|
||||
let isParentVariableStatement = variableDeclaration.parent.parent.kind === SyntaxKind.VariableStatement;
|
||||
let isDeclarationOfForStatement = variableDeclaration.parent.parent.kind === SyntaxKind.ForStatement && contains((<VariableDeclarationList>(<ForStatement>variableDeclaration.parent.parent).initializer).declarations, variableDeclaration);
|
||||
let declarations = isParentVariableStatement
|
||||
? (<VariableStatement>variableDeclaration.parent.parent).declarationList.declarations
|
||||
: isDeclarationOfForStatement
|
||||
? (<VariableDeclarationList>(<ForStatement>variableDeclaration.parent.parent).initializer).declarations
|
||||
@@ -287,12 +291,12 @@ module ts.BreakpointResolver {
|
||||
if (variableDeclaration.initializer || (variableDeclaration.flags & NodeFlags.Export)) {
|
||||
if (declarations && declarations[0] === variableDeclaration) {
|
||||
if (isParentVariableStatement) {
|
||||
// First declaration - include var keyword
|
||||
// First declaration - include let keyword
|
||||
return textSpan(variableDeclaration.parent, variableDeclaration);
|
||||
}
|
||||
else {
|
||||
Debug.assert(isDeclarationOfForStatement);
|
||||
// Include var keyword from for statement declarations in the span
|
||||
// Include let keyword from for statement declarations in the span
|
||||
return textSpan(findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent), variableDeclaration);
|
||||
}
|
||||
}
|
||||
@@ -303,7 +307,7 @@ module ts.BreakpointResolver {
|
||||
}
|
||||
else if (declarations && declarations[0] !== variableDeclaration) {
|
||||
// If we cant set breakpoint on this declaration, set it on previous one
|
||||
var indexOfCurrentDeclaration = indexOf(declarations, variableDeclaration);
|
||||
let indexOfCurrentDeclaration = indexOf(declarations, variableDeclaration);
|
||||
return spanInVariableDeclaration(declarations[indexOfCurrentDeclaration - 1]);
|
||||
}
|
||||
}
|
||||
@@ -319,8 +323,8 @@ module ts.BreakpointResolver {
|
||||
return textSpan(parameter);
|
||||
}
|
||||
else {
|
||||
var functionDeclaration = <FunctionLikeDeclaration>parameter.parent;
|
||||
var indexOfParameter = indexOf(functionDeclaration.parameters, parameter);
|
||||
let functionDeclaration = <FunctionLikeDeclaration>parameter.parent;
|
||||
let indexOfParameter = indexOf(functionDeclaration.parameters, parameter);
|
||||
if (indexOfParameter) {
|
||||
// Not a first parameter, go to previous parameter
|
||||
return spanInParameterDeclaration(functionDeclaration.parameters[indexOfParameter - 1]);
|
||||
@@ -353,7 +357,7 @@ module ts.BreakpointResolver {
|
||||
}
|
||||
|
||||
function spanInFunctionBlock(block: Block): TextSpan {
|
||||
var nodeForSpanInBlock = block.statements.length ? block.statements[0] : block.getLastToken();
|
||||
let nodeForSpanInBlock = block.statements.length ? block.statements[0] : block.getLastToken();
|
||||
if (canFunctionHaveSpanInWholeDeclaration(<FunctionLikeDeclaration>block.parent)) {
|
||||
return spanInNodeIfStartsOnSameLine(block.parent, nodeForSpanInBlock);
|
||||
}
|
||||
@@ -387,7 +391,7 @@ module ts.BreakpointResolver {
|
||||
function spanInForStatement(forStatement: ForStatement): TextSpan {
|
||||
if (forStatement.initializer) {
|
||||
if (forStatement.initializer.kind === SyntaxKind.VariableDeclarationList) {
|
||||
var variableDeclarationList = <VariableDeclarationList>forStatement.initializer;
|
||||
let variableDeclarationList = <VariableDeclarationList>forStatement.initializer;
|
||||
if (variableDeclarationList.declarations.length > 0) {
|
||||
return spanInNode(variableDeclarationList.declarations[0]);
|
||||
}
|
||||
@@ -409,15 +413,15 @@ module ts.BreakpointResolver {
|
||||
function spanInOpenBraceToken(node: Node): TextSpan {
|
||||
switch (node.parent.kind) {
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
var enumDeclaration = <EnumDeclaration>node.parent;
|
||||
let enumDeclaration = <EnumDeclaration>node.parent;
|
||||
return spanInNodeIfStartsOnSameLine(findPrecedingToken(node.pos, sourceFile, node.parent), enumDeclaration.members.length ? enumDeclaration.members[0] : enumDeclaration.getLastToken(sourceFile));
|
||||
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
var classDeclaration = <ClassDeclaration>node.parent;
|
||||
let classDeclaration = <ClassDeclaration>node.parent;
|
||||
return spanInNodeIfStartsOnSameLine(findPrecedingToken(node.pos, sourceFile, node.parent), classDeclaration.members.length ? classDeclaration.members[0] : classDeclaration.getLastToken(sourceFile));
|
||||
|
||||
case SyntaxKind.SwitchStatement:
|
||||
return spanInNodeIfStartsOnSameLine(node.parent, (<SwitchStatement>node.parent).clauses[0]);
|
||||
case SyntaxKind.CaseBlock:
|
||||
return spanInNodeIfStartsOnSameLine(node.parent.parent, (<CaseBlock>node.parent).clauses[0]);
|
||||
}
|
||||
|
||||
// Default to parent node
|
||||
@@ -447,10 +451,10 @@ module ts.BreakpointResolver {
|
||||
case SyntaxKind.CatchClause:
|
||||
return spanInNode((<Block>node.parent).statements[(<Block>node.parent).statements.length - 1]);;
|
||||
|
||||
case SyntaxKind.SwitchStatement:
|
||||
case SyntaxKind.CaseBlock:
|
||||
// breakpoint in last statement of the last clause
|
||||
var switchStatement = <SwitchStatement>node.parent;
|
||||
var lastClause = switchStatement.clauses[switchStatement.clauses.length - 1];
|
||||
let caseBlock = <CaseBlock>node.parent;
|
||||
let lastClause = caseBlock.clauses[caseBlock.clauses.length - 1];
|
||||
if (lastClause) {
|
||||
return spanInNode(lastClause.statements[lastClause.statements.length - 1]);
|
||||
}
|
||||
@@ -499,7 +503,7 @@ module ts.BreakpointResolver {
|
||||
|
||||
function spanInColonToken(node: Node): TextSpan {
|
||||
// Is this : specifying return annotation of the function declaration
|
||||
if (isAnyFunction(node.parent) || node.parent.kind === SyntaxKind.PropertyAssignment) {
|
||||
if (isFunctionLike(node.parent) || node.parent.kind === SyntaxKind.PropertyAssignment) {
|
||||
return spanInPreviousNode(node);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ module ts.formatting {
|
||||
* Indentation for the scope that can be dynamically recomputed.
|
||||
* i.e
|
||||
* while(true)
|
||||
* { var x;
|
||||
* { let x;
|
||||
* }
|
||||
* Normally indentation is applied only to the first token in line so at glance 'var' should not be touched.
|
||||
* However if some format rule adds new line between '}' and 'var' 'var' will become
|
||||
@@ -67,12 +67,12 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
export function formatOnEnter(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[] {
|
||||
var line = sourceFile.getLineAndCharacterOfPosition(position).line;
|
||||
let line = sourceFile.getLineAndCharacterOfPosition(position).line;
|
||||
if (line === 0) {
|
||||
return [];
|
||||
}
|
||||
// get the span for the previous\current line
|
||||
var span = {
|
||||
let span = {
|
||||
// get start position for the previous line
|
||||
pos: getStartPositionOfLine(line - 1, sourceFile),
|
||||
// get end position for the current line (end value is exclusive so add 1 to the result)
|
||||
@@ -90,7 +90,7 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
export function formatDocument(sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[] {
|
||||
var span = {
|
||||
let span = {
|
||||
pos: 0,
|
||||
end: sourceFile.text.length
|
||||
};
|
||||
@@ -99,7 +99,7 @@ module ts.formatting {
|
||||
|
||||
export function formatSelection(start: number, end: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[] {
|
||||
// format from the beginning of the line
|
||||
var span = {
|
||||
let span = {
|
||||
pos: getLineStartPositionForPosition(start, sourceFile),
|
||||
end: end
|
||||
};
|
||||
@@ -107,11 +107,11 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
function formatOutermostParent(position: number, expectedLastToken: SyntaxKind, sourceFile: SourceFile, options: FormatCodeOptions, rulesProvider: RulesProvider, requestKind: FormattingRequestKind): TextChange[] {
|
||||
var parent = findOutermostParent(position, expectedLastToken, sourceFile);
|
||||
let parent = findOutermostParent(position, expectedLastToken, sourceFile);
|
||||
if (!parent) {
|
||||
return [];
|
||||
}
|
||||
var span = {
|
||||
let span = {
|
||||
pos: getLineStartPositionForPosition(parent.getStart(sourceFile), sourceFile),
|
||||
end: parent.end
|
||||
};
|
||||
@@ -119,7 +119,7 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
function findOutermostParent(position: number, expectedTokenKind: SyntaxKind, sourceFile: SourceFile): Node {
|
||||
var precedingToken = findPrecedingToken(position, sourceFile);
|
||||
let precedingToken = findPrecedingToken(position, sourceFile);
|
||||
|
||||
// when it is claimed that trigger character was typed at given position
|
||||
// we verify that there is a token with a matching kind whose end is equal to position (because the character was just typed).
|
||||
@@ -134,13 +134,13 @@ module ts.formatting {
|
||||
// walk up and search for the parent node that ends at the same position with precedingToken.
|
||||
// for cases like this
|
||||
//
|
||||
// var x = 1;
|
||||
// let x = 1;
|
||||
// while (true) {
|
||||
// }
|
||||
// after typing close curly in while statement we want to reformat just the while statement.
|
||||
// However if we just walk upwards searching for the parent that has the same end value -
|
||||
// we'll end up with the whole source file. isListElement allows to stop on the list element level
|
||||
var current = precedingToken;
|
||||
let current = precedingToken;
|
||||
while (current &&
|
||||
current.parent &&
|
||||
current.parent.end === precedingToken.end &&
|
||||
@@ -159,7 +159,7 @@ module ts.formatting {
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
return rangeContainsRange((<InterfaceDeclaration>parent).members, node);
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
var body = (<ModuleDeclaration>parent).body;
|
||||
let body = (<ModuleDeclaration>parent).body;
|
||||
return body && body.kind === SyntaxKind.Block && rangeContainsRange((<Block>body).statements, node);
|
||||
case SyntaxKind.SourceFile:
|
||||
case SyntaxKind.Block:
|
||||
@@ -177,9 +177,9 @@ module ts.formatting {
|
||||
return find(sourceFile);
|
||||
|
||||
function find(n: Node): Node {
|
||||
var candidate = forEachChild(n, c => startEndContainsRange(c.getStart(sourceFile), c.end, range) && c);
|
||||
let candidate = forEachChild(n, c => startEndContainsRange(c.getStart(sourceFile), c.end, range) && c);
|
||||
if (candidate) {
|
||||
var result = find(candidate);
|
||||
let result = find(candidate);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
@@ -199,7 +199,7 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
// pick only errors that fall in range
|
||||
var sorted = errors
|
||||
let sorted = errors
|
||||
.filter(d => rangeOverlapsWithStartEnd(originalRange, d.start, d.start + d.length))
|
||||
.sort((e1, e2) => e1.start - e2.start);
|
||||
|
||||
@@ -207,7 +207,7 @@ module ts.formatting {
|
||||
return rangeHasNoErrors;
|
||||
}
|
||||
|
||||
var index = 0;
|
||||
let index = 0;
|
||||
|
||||
return r => {
|
||||
// in current implementation sequence of arguments [r1, r2...] is monotonically increasing.
|
||||
@@ -218,7 +218,7 @@ module ts.formatting {
|
||||
return false;
|
||||
}
|
||||
|
||||
var error = sorted[index];
|
||||
let error = sorted[index];
|
||||
if (r.end <= error.start) {
|
||||
// specified range ends before the error refered by 'index' - no error in range
|
||||
return false;
|
||||
@@ -244,12 +244,12 @@ module ts.formatting {
|
||||
* and return its end as start position for the scanner.
|
||||
*/
|
||||
function getScanStartPosition(enclosingNode: Node, originalRange: TextRange, sourceFile: SourceFile): number {
|
||||
var start = enclosingNode.getStart(sourceFile);
|
||||
let start = enclosingNode.getStart(sourceFile);
|
||||
if (start === originalRange.pos && enclosingNode.end === originalRange.end) {
|
||||
return start;
|
||||
}
|
||||
|
||||
var precedingToken = findPrecedingToken(originalRange.pos, sourceFile);
|
||||
let precedingToken = findPrecedingToken(originalRange.pos, sourceFile);
|
||||
if (!precedingToken) {
|
||||
// no preceding token found - start from the beginning of enclosing node
|
||||
return enclosingNode.pos;
|
||||
@@ -280,10 +280,10 @@ module ts.formatting {
|
||||
* to the initial indentation.
|
||||
*/
|
||||
function getOwnOrInheritedDelta(n: Node, options: FormatCodeOptions, sourceFile: SourceFile): number {
|
||||
var previousLine = Constants.Unknown;
|
||||
var childKind = SyntaxKind.Unknown;
|
||||
let previousLine = Constants.Unknown;
|
||||
let childKind = SyntaxKind.Unknown;
|
||||
while (n) {
|
||||
var line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line;
|
||||
let line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line;
|
||||
if (previousLine !== Constants.Unknown && line !== previousLine) {
|
||||
break;
|
||||
}
|
||||
@@ -305,30 +305,30 @@ module ts.formatting {
|
||||
rulesProvider: RulesProvider,
|
||||
requestKind: FormattingRequestKind): TextChange[] {
|
||||
|
||||
var rangeContainsError = prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange);
|
||||
let rangeContainsError = prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange);
|
||||
|
||||
// formatting context is used by rules provider
|
||||
var formattingContext = new FormattingContext(sourceFile, requestKind);
|
||||
let formattingContext = new FormattingContext(sourceFile, requestKind);
|
||||
|
||||
// find the smallest node that fully wraps the range and compute the initial indentation for the node
|
||||
var enclosingNode = findEnclosingNode(originalRange, sourceFile);
|
||||
let enclosingNode = findEnclosingNode(originalRange, sourceFile);
|
||||
|
||||
var formattingScanner = getFormattingScanner(sourceFile, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end);
|
||||
let formattingScanner = getFormattingScanner(sourceFile, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end);
|
||||
|
||||
var initialIndentation = SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, options);
|
||||
let initialIndentation = SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, options);
|
||||
|
||||
var previousRangeHasError: boolean;
|
||||
var previousRange: TextRangeWithKind;
|
||||
var previousParent: Node;
|
||||
var previousRangeStartLine: number;
|
||||
let previousRangeHasError: boolean;
|
||||
let previousRange: TextRangeWithKind;
|
||||
let previousParent: Node;
|
||||
let previousRangeStartLine: number;
|
||||
|
||||
var edits: TextChange[] = [];
|
||||
let edits: TextChange[] = [];
|
||||
|
||||
formattingScanner.advance();
|
||||
|
||||
if (formattingScanner.isOnToken()) {
|
||||
var startLine = sourceFile.getLineAndCharacterOfPosition(enclosingNode.getStart(sourceFile)).line;
|
||||
var delta = getOwnOrInheritedDelta(enclosingNode, options, sourceFile);
|
||||
let startLine = sourceFile.getLineAndCharacterOfPosition(enclosingNode.getStart(sourceFile)).line;
|
||||
let delta = getOwnOrInheritedDelta(enclosingNode, options, sourceFile);
|
||||
processNode(enclosingNode, enclosingNode, startLine, initialIndentation, delta);
|
||||
}
|
||||
|
||||
@@ -357,9 +357,9 @@ module ts.formatting {
|
||||
}
|
||||
}
|
||||
else {
|
||||
var startLine = sourceFile.getLineAndCharacterOfPosition(startPos).line;
|
||||
var startLinePosition = getLineStartPositionForPosition(startPos, sourceFile);
|
||||
var column = SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, startPos, sourceFile, options);
|
||||
let startLine = sourceFile.getLineAndCharacterOfPosition(startPos).line;
|
||||
let startLinePosition = getLineStartPositionForPosition(startPos, sourceFile);
|
||||
let column = SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, startPos, sourceFile, options);
|
||||
if (startLine !== parentStartLine || startPos === column) {
|
||||
return column
|
||||
}
|
||||
@@ -376,7 +376,7 @@ module ts.formatting {
|
||||
parentDynamicIndentation: DynamicIndentation,
|
||||
effectiveParentStartLine: number): Indentation {
|
||||
|
||||
var indentation = inheritedIndentation;
|
||||
let indentation = inheritedIndentation;
|
||||
if (indentation === Constants.Unknown) {
|
||||
if (isSomeBlock(node.kind)) {
|
||||
// blocks should be indented in
|
||||
@@ -475,7 +475,7 @@ module ts.formatting {
|
||||
return;
|
||||
}
|
||||
|
||||
var nodeDynamicIndentation = getDynamicIndentation(node, nodeStartLine, indentation, delta);
|
||||
let nodeDynamicIndentation = getDynamicIndentation(node, nodeStartLine, indentation, delta);
|
||||
|
||||
// a useful observations when tracking context node
|
||||
// /
|
||||
@@ -489,7 +489,7 @@ module ts.formatting {
|
||||
// context node is set to parent node value after processing every child node
|
||||
// context node is set to parent of the token after processing every token
|
||||
|
||||
var childContextNode = contextNode;
|
||||
let childContextNode = contextNode;
|
||||
|
||||
// if there are any tokens that logically belong to node and interleave child nodes
|
||||
// such tokens will be consumed in processChildNode for for the child that follows them
|
||||
@@ -504,7 +504,7 @@ module ts.formatting {
|
||||
|
||||
// proceed any tokens in the node that are located after child nodes
|
||||
while (formattingScanner.isOnToken()) {
|
||||
var tokenInfo = formattingScanner.readTokenInfo(node);
|
||||
let tokenInfo = formattingScanner.readTokenInfo(node);
|
||||
if (tokenInfo.token.end > node.end) {
|
||||
break;
|
||||
}
|
||||
@@ -519,12 +519,12 @@ module ts.formatting {
|
||||
parentStartLine: number,
|
||||
isListItem: boolean): number {
|
||||
|
||||
var childStartPos = child.getStart(sourceFile);
|
||||
let childStartPos = child.getStart(sourceFile);
|
||||
|
||||
var childStart = sourceFile.getLineAndCharacterOfPosition(childStartPos);
|
||||
let childStart = sourceFile.getLineAndCharacterOfPosition(childStartPos);
|
||||
|
||||
// if child is a list item - try to get its indentation
|
||||
var childIndentationAmount = Constants.Unknown;
|
||||
let childIndentationAmount = Constants.Unknown;
|
||||
if (isListItem) {
|
||||
childIndentationAmount = tryComputeIndentationForListItem(childStartPos, child.end, parentStartLine, originalRange, inheritedIndentation);
|
||||
if (childIndentationAmount !== Constants.Unknown) {
|
||||
@@ -543,7 +543,7 @@ module ts.formatting {
|
||||
|
||||
while (formattingScanner.isOnToken()) {
|
||||
// proceed any parent tokens that are located prior to child.getStart()
|
||||
var tokenInfo = formattingScanner.readTokenInfo(node);
|
||||
let tokenInfo = formattingScanner.readTokenInfo(node);
|
||||
if (tokenInfo.token.end > childStartPos) {
|
||||
// stop when formatting scanner advances past the beginning of the child
|
||||
break;
|
||||
@@ -558,13 +558,13 @@ module ts.formatting {
|
||||
|
||||
if (isToken(child)) {
|
||||
// if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules
|
||||
var tokenInfo = formattingScanner.readTokenInfo(child);
|
||||
let tokenInfo = formattingScanner.readTokenInfo(child);
|
||||
Debug.assert(tokenInfo.token.end === child.end);
|
||||
consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation);
|
||||
return inheritedIndentation;
|
||||
}
|
||||
|
||||
var childIndentation = computeIndentation(child, childStart.line, childIndentationAmount, node, parentDynamicIndentation, parentStartLine);
|
||||
let childIndentation = computeIndentation(child, childStart.line, childIndentationAmount, node, parentDynamicIndentation, parentStartLine);
|
||||
|
||||
processNode(child, childContextNode, childStart.line, childIndentation.indentation, childIndentation.delta);
|
||||
|
||||
@@ -578,16 +578,16 @@ module ts.formatting {
|
||||
parentStartLine: number,
|
||||
parentDynamicIndentation: DynamicIndentation): void {
|
||||
|
||||
var listStartToken = getOpenTokenForList(parent, nodes);
|
||||
var listEndToken = getCloseTokenForOpenToken(listStartToken);
|
||||
let listStartToken = getOpenTokenForList(parent, nodes);
|
||||
let listEndToken = getCloseTokenForOpenToken(listStartToken);
|
||||
|
||||
var listDynamicIndentation = parentDynamicIndentation;
|
||||
var startLine = parentStartLine;
|
||||
let listDynamicIndentation = parentDynamicIndentation;
|
||||
let startLine = parentStartLine;
|
||||
|
||||
if (listStartToken !== SyntaxKind.Unknown) {
|
||||
// introduce a new indentation scope for lists (including list start and end tokens)
|
||||
while (formattingScanner.isOnToken()) {
|
||||
var tokenInfo = formattingScanner.readTokenInfo(parent);
|
||||
let tokenInfo = formattingScanner.readTokenInfo(parent);
|
||||
if (tokenInfo.token.end > nodes.pos) {
|
||||
// stop when formatting scanner moves past the beginning of node list
|
||||
break;
|
||||
@@ -595,7 +595,7 @@ module ts.formatting {
|
||||
else if (tokenInfo.token.kind === listStartToken) {
|
||||
// consume list start token
|
||||
startLine = sourceFile.getLineAndCharacterOfPosition(tokenInfo.token.pos).line;
|
||||
var indentation =
|
||||
let indentation =
|
||||
computeIndentation(tokenInfo.token, startLine, Constants.Unknown, parent, parentDynamicIndentation, startLine);
|
||||
|
||||
listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentation.indentation, indentation.delta);
|
||||
@@ -608,14 +608,14 @@ module ts.formatting {
|
||||
}
|
||||
}
|
||||
|
||||
var inheritedIndentation = Constants.Unknown;
|
||||
for (var i = 0, len = nodes.length; i < len; ++i) {
|
||||
inheritedIndentation = processChildNode(nodes[i], inheritedIndentation, node, listDynamicIndentation, startLine, /*isListElement*/ true)
|
||||
let inheritedIndentation = Constants.Unknown;
|
||||
for (let child of nodes) {
|
||||
inheritedIndentation = processChildNode(child, inheritedIndentation, node, listDynamicIndentation, startLine, /*isListElement*/ true)
|
||||
}
|
||||
|
||||
if (listEndToken !== SyntaxKind.Unknown) {
|
||||
if (formattingScanner.isOnToken()) {
|
||||
var tokenInfo = formattingScanner.readTokenInfo(parent);
|
||||
let tokenInfo = formattingScanner.readTokenInfo(parent);
|
||||
// consume the list end token only if it is still belong to the parent
|
||||
// there might be the case when current token matches end token but does not considered as one
|
||||
// function (x: function) <--
|
||||
@@ -631,21 +631,21 @@ module ts.formatting {
|
||||
function consumeTokenAndAdvanceScanner(currentTokenInfo: TokenInfo, parent: Node, dynamicIndentation: DynamicIndentation): void {
|
||||
Debug.assert(rangeContainsRange(parent, currentTokenInfo.token));
|
||||
|
||||
var lastTriviaWasNewLine = formattingScanner.lastTrailingTriviaWasNewLine();
|
||||
var indentToken = false;
|
||||
let lastTriviaWasNewLine = formattingScanner.lastTrailingTriviaWasNewLine();
|
||||
let indentToken = false;
|
||||
|
||||
if (currentTokenInfo.leadingTrivia) {
|
||||
processTrivia(currentTokenInfo.leadingTrivia, parent, childContextNode, dynamicIndentation);
|
||||
}
|
||||
|
||||
var lineAdded: boolean;
|
||||
var isTokenInRange = rangeContainsRange(originalRange, currentTokenInfo.token);
|
||||
let lineAdded: boolean;
|
||||
let isTokenInRange = rangeContainsRange(originalRange, currentTokenInfo.token);
|
||||
|
||||
var tokenStart = sourceFile.getLineAndCharacterOfPosition(currentTokenInfo.token.pos);
|
||||
let tokenStart = sourceFile.getLineAndCharacterOfPosition(currentTokenInfo.token.pos);
|
||||
if (isTokenInRange) {
|
||||
var rangeHasError = rangeContainsError(currentTokenInfo.token);
|
||||
let rangeHasError = rangeContainsError(currentTokenInfo.token);
|
||||
// save prevStartLine since processRange will overwrite this value with current ones
|
||||
var prevStartLine = previousRangeStartLine;
|
||||
let prevStartLine = previousRangeStartLine;
|
||||
lineAdded = processRange(currentTokenInfo.token, tokenStart, parent, childContextNode, dynamicIndentation);
|
||||
if (rangeHasError) {
|
||||
// do not indent comments\token if token range overlaps with some error
|
||||
@@ -666,24 +666,23 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
if (indentToken) {
|
||||
var indentNextTokenOrTrivia = true;
|
||||
let indentNextTokenOrTrivia = true;
|
||||
if (currentTokenInfo.leadingTrivia) {
|
||||
for (var i = 0, len = currentTokenInfo.leadingTrivia.length; i < len; ++i) {
|
||||
var triviaItem = currentTokenInfo.leadingTrivia[i];
|
||||
for (let triviaItem of currentTokenInfo.leadingTrivia) {
|
||||
if (!rangeContainsRange(originalRange, triviaItem)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var triviaStartLine = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos).line;
|
||||
let triviaStartLine = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos).line;
|
||||
switch (triviaItem.kind) {
|
||||
case SyntaxKind.MultiLineCommentTrivia:
|
||||
var commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind);
|
||||
let commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind);
|
||||
indentMultilineComment(triviaItem, commentIndentation, /*firstLineIsIndented*/ !indentNextTokenOrTrivia);
|
||||
indentNextTokenOrTrivia = false;
|
||||
break;
|
||||
case SyntaxKind.SingleLineCommentTrivia:
|
||||
if (indentNextTokenOrTrivia) {
|
||||
var commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind);
|
||||
let commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind);
|
||||
insertIndentation(triviaItem.pos, commentIndentation, /*lineAdded*/ false);
|
||||
indentNextTokenOrTrivia = false;
|
||||
}
|
||||
@@ -697,7 +696,7 @@ module ts.formatting {
|
||||
|
||||
// indent token only if is it is in target range and does not overlap with any error ranges
|
||||
if (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) {
|
||||
var tokenIndentation = dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind);
|
||||
let tokenIndentation = dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind);
|
||||
insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAdded);
|
||||
}
|
||||
}
|
||||
@@ -709,10 +708,9 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
function processTrivia(trivia: TextRangeWithKind[], parent: Node, contextNode: Node, dynamicIndentation: DynamicIndentation): void {
|
||||
for (var i = 0, len = trivia.length; i < len; ++i) {
|
||||
var triviaItem = trivia[i];
|
||||
for (let triviaItem of trivia) {
|
||||
if (isComment(triviaItem.kind) && rangeContainsRange(originalRange, triviaItem)) {
|
||||
var triviaItemStart = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos);
|
||||
let triviaItemStart = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos);
|
||||
processRange(triviaItem, triviaItemStart, parent, contextNode, dynamicIndentation);
|
||||
}
|
||||
}
|
||||
@@ -724,12 +722,12 @@ module ts.formatting {
|
||||
contextNode: Node,
|
||||
dynamicIndentation: DynamicIndentation): boolean {
|
||||
|
||||
var rangeHasError = rangeContainsError(range);
|
||||
var lineAdded: boolean;
|
||||
let rangeHasError = rangeContainsError(range);
|
||||
let lineAdded: boolean;
|
||||
if (!rangeHasError && !previousRangeHasError) {
|
||||
if (!previousRange) {
|
||||
// trim whitespaces starting from the beginning of the span up to the current line
|
||||
var originalStart = sourceFile.getLineAndCharacterOfPosition(originalRange.pos);
|
||||
let originalStart = sourceFile.getLineAndCharacterOfPosition(originalRange.pos);
|
||||
trimTrailingWhitespacesForLines(originalStart.line, rangeStart.line);
|
||||
}
|
||||
else {
|
||||
@@ -757,10 +755,10 @@ module ts.formatting {
|
||||
|
||||
formattingContext.updateContext(previousItem, previousParent, currentItem, currentParent, contextNode);
|
||||
|
||||
var rule = rulesProvider.getRulesMap().GetRule(formattingContext);
|
||||
let rule = rulesProvider.getRulesMap().GetRule(formattingContext);
|
||||
|
||||
var trimTrailingWhitespaces: boolean;
|
||||
var lineAdded: boolean;
|
||||
let trimTrailingWhitespaces: boolean;
|
||||
let lineAdded: boolean;
|
||||
if (rule) {
|
||||
applyRuleEdits(rule, previousItem, previousStartLine, currentItem, currentStartLine);
|
||||
|
||||
@@ -800,16 +798,16 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
function insertIndentation(pos: number, indentation: number, lineAdded: boolean): void {
|
||||
var indentationString = getIndentationString(indentation, options);
|
||||
let indentationString = getIndentationString(indentation, options);
|
||||
if (lineAdded) {
|
||||
// new line is added before the token by the formatting rules
|
||||
// insert indentation string at the very beginning of the token
|
||||
recordReplace(pos, 0, indentationString);
|
||||
}
|
||||
else {
|
||||
var tokenStart = sourceFile.getLineAndCharacterOfPosition(pos);
|
||||
let tokenStart = sourceFile.getLineAndCharacterOfPosition(pos);
|
||||
if (indentation !== tokenStart.character) {
|
||||
var startLinePosition = getStartPositionOfLine(tokenStart.line, sourceFile);
|
||||
let startLinePosition = getStartPositionOfLine(tokenStart.line, sourceFile);
|
||||
recordReplace(startLinePosition, tokenStart.character, indentationString);
|
||||
}
|
||||
}
|
||||
@@ -817,9 +815,9 @@ module ts.formatting {
|
||||
|
||||
function indentMultilineComment(commentRange: TextRange, indentation: number, firstLineIsIndented: boolean) {
|
||||
// split comment in lines
|
||||
var startLine = sourceFile.getLineAndCharacterOfPosition(commentRange.pos).line;
|
||||
var endLine = sourceFile.getLineAndCharacterOfPosition(commentRange.end).line;
|
||||
|
||||
let startLine = sourceFile.getLineAndCharacterOfPosition(commentRange.pos).line;
|
||||
let endLine = sourceFile.getLineAndCharacterOfPosition(commentRange.end).line;
|
||||
let parts: TextRange[];
|
||||
if (startLine === endLine) {
|
||||
if (!firstLineIsIndented) {
|
||||
// treat as single line comment
|
||||
@@ -828,10 +826,10 @@ module ts.formatting {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
var parts: TextRange[] = [];
|
||||
var startPos = commentRange.pos;
|
||||
for (var line = startLine; line < endLine; ++line) {
|
||||
var endOfLine = getEndLinePosition(line, sourceFile);
|
||||
parts = [];
|
||||
let startPos = commentRange.pos;
|
||||
for (let line = startLine; line < endLine; ++line) {
|
||||
let endOfLine = getEndLinePosition(line, sourceFile);
|
||||
parts.push({ pos: startPos, end: endOfLine });
|
||||
startPos = getStartPositionOfLine(line + 1, sourceFile);
|
||||
}
|
||||
@@ -839,33 +837,33 @@ module ts.formatting {
|
||||
parts.push({ pos: startPos, end: commentRange.end });
|
||||
}
|
||||
|
||||
var startLinePos = getStartPositionOfLine(startLine, sourceFile);
|
||||
let startLinePos = getStartPositionOfLine(startLine, sourceFile);
|
||||
|
||||
var nonWhitespaceColumnInFirstPart =
|
||||
let nonWhitespaceColumnInFirstPart =
|
||||
SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(startLinePos, parts[0].pos, sourceFile, options);
|
||||
|
||||
if (indentation === nonWhitespaceColumnInFirstPart.column) {
|
||||
return;
|
||||
}
|
||||
|
||||
var startIndex = 0;
|
||||
let startIndex = 0;
|
||||
if (firstLineIsIndented) {
|
||||
startIndex = 1;
|
||||
startLine++;
|
||||
}
|
||||
|
||||
// shift all parts on the delta size
|
||||
var delta = indentation - nonWhitespaceColumnInFirstPart.column;
|
||||
for (var i = startIndex, len = parts.length; i < len; ++i, ++startLine) {
|
||||
var startLinePos = getStartPositionOfLine(startLine, sourceFile);
|
||||
var nonWhitespaceCharacterAndColumn =
|
||||
let delta = indentation - nonWhitespaceColumnInFirstPart.column;
|
||||
for (let i = startIndex, len = parts.length; i < len; ++i, ++startLine) {
|
||||
let startLinePos = getStartPositionOfLine(startLine, sourceFile);
|
||||
let nonWhitespaceCharacterAndColumn =
|
||||
i === 0
|
||||
? nonWhitespaceColumnInFirstPart
|
||||
: SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(parts[i].pos, parts[i].end, sourceFile, options);
|
||||
|
||||
var newIndentation = nonWhitespaceCharacterAndColumn.column + delta;
|
||||
let newIndentation = nonWhitespaceCharacterAndColumn.column + delta;
|
||||
if (newIndentation > 0) {
|
||||
var indentationString = getIndentationString(newIndentation, options);
|
||||
let indentationString = getIndentationString(newIndentation, options);
|
||||
recordReplace(startLinePos, nonWhitespaceCharacterAndColumn.character, indentationString);
|
||||
}
|
||||
else {
|
||||
@@ -875,16 +873,16 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
function trimTrailingWhitespacesForLines(line1: number, line2: number, range?: TextRangeWithKind) {
|
||||
for (var line = line1; line < line2; ++line) {
|
||||
var lineStartPosition = getStartPositionOfLine(line, sourceFile);
|
||||
var lineEndPosition = getEndLinePosition(line, sourceFile);
|
||||
for (let line = line1; line < line2; ++line) {
|
||||
let lineStartPosition = getStartPositionOfLine(line, sourceFile);
|
||||
let lineEndPosition = getEndLinePosition(line, sourceFile);
|
||||
|
||||
// do not trim whitespaces in comments
|
||||
if (range && isComment(range.kind) && range.pos <= lineEndPosition && range.end > lineEndPosition) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var pos = lineEndPosition;
|
||||
let pos = lineEndPosition;
|
||||
while (pos >= lineStartPosition && isWhiteSpace(sourceFile.text.charCodeAt(pos))) {
|
||||
pos--;
|
||||
}
|
||||
@@ -917,7 +915,7 @@ module ts.formatting {
|
||||
currentRange: TextRangeWithKind,
|
||||
currentStartLine: number): void {
|
||||
|
||||
var between: TextRange;
|
||||
let between: TextRange;
|
||||
switch (rule.Operation.Action) {
|
||||
case RuleAction.Ignore:
|
||||
// no action required
|
||||
@@ -937,7 +935,7 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
// edit should not be applied only if we have one line feed between elements
|
||||
var lineDelta = currentStartLine - previousStartLine;
|
||||
let lineDelta = currentStartLine - previousStartLine;
|
||||
if (lineDelta !== 1) {
|
||||
recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.NewLineCharacter);
|
||||
}
|
||||
@@ -948,7 +946,7 @@ module ts.formatting {
|
||||
return;
|
||||
}
|
||||
|
||||
var posDelta = currentRange.pos - previousRange.end;
|
||||
let posDelta = currentRange.pos - previousRange.end;
|
||||
if (posDelta !== 1 || sourceFile.text.charCodeAt(previousRange.end) !== CharacterCodes.space) {
|
||||
recordReplace(previousRange.end, currentRange.pos - previousRange.end, " ");
|
||||
}
|
||||
@@ -1010,15 +1008,25 @@ module ts.formatting {
|
||||
return SyntaxKind.Unknown;
|
||||
}
|
||||
|
||||
var internedSizes: { tabSize: number; indentSize: number };
|
||||
var internedTabsIndentation: string[];
|
||||
var internedSpacesIndentation: string[];
|
||||
|
||||
export function getIndentationString(indentation: number, options: FormatCodeOptions): string {
|
||||
if (!options.ConvertTabsToSpaces) {
|
||||
var tabs = Math.floor(indentation / options.TabSize);
|
||||
var spaces = indentation - tabs * options.TabSize;
|
||||
// reset interned strings if FormatCodeOptions were changed
|
||||
let resetInternedStrings =
|
||||
!internedSizes || (internedSizes.tabSize !== options.TabSize || internedSizes.indentSize !== options.IndentSize);
|
||||
|
||||
var tabString: string;
|
||||
if (resetInternedStrings) {
|
||||
internedSizes = { tabSize: options.TabSize, indentSize: options.IndentSize };
|
||||
internedTabsIndentation = internedSpacesIndentation = undefined;
|
||||
}
|
||||
|
||||
if (!options.ConvertTabsToSpaces) {
|
||||
let tabs = Math.floor(indentation / options.TabSize);
|
||||
let spaces = indentation - tabs * options.TabSize;
|
||||
|
||||
let tabString: string;
|
||||
if (!internedTabsIndentation) {
|
||||
internedTabsIndentation = [];
|
||||
}
|
||||
@@ -1033,9 +1041,9 @@ module ts.formatting {
|
||||
return spaces ? tabString + repeat(" ", spaces) : tabString;
|
||||
}
|
||||
else {
|
||||
var spacesString: string;
|
||||
var quotient = Math.floor(indentation / options.IndentSize);
|
||||
var remainder = indentation % options.IndentSize;
|
||||
let spacesString: string;
|
||||
let quotient = Math.floor(indentation / options.IndentSize);
|
||||
let remainder = indentation % options.IndentSize;
|
||||
if (!internedSpacesIndentation) {
|
||||
internedSpacesIndentation = [];
|
||||
}
|
||||
@@ -1048,13 +1056,12 @@ module ts.formatting {
|
||||
spacesString = internedSpacesIndentation[quotient];
|
||||
}
|
||||
|
||||
|
||||
return remainder ? spacesString + repeat(" ", remainder) : spacesString;
|
||||
}
|
||||
|
||||
function repeat(value: string, count: number): string {
|
||||
var s = "";
|
||||
for (var i = 0; i < count; ++i) {
|
||||
let s = "";
|
||||
for (let i = 0; i < count; ++i) {
|
||||
s += value;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,8 +71,8 @@ module ts.formatting {
|
||||
|
||||
public TokensAreOnSameLine(): boolean {
|
||||
if (this.tokensAreOnSameLine === undefined) {
|
||||
var startLine = this.sourceFile.getLineAndCharacterOfPosition(this.currentTokenSpan.pos).line;
|
||||
var endLine = this.sourceFile.getLineAndCharacterOfPosition(this.nextTokenSpan.pos).line;
|
||||
let startLine = this.sourceFile.getLineAndCharacterOfPosition(this.currentTokenSpan.pos).line;
|
||||
let endLine = this.sourceFile.getLineAndCharacterOfPosition(this.nextTokenSpan.pos).line;
|
||||
this.tokensAreOnSameLine = (startLine == endLine);
|
||||
}
|
||||
|
||||
@@ -96,17 +96,17 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
private NodeIsOnOneLine(node: Node): boolean {
|
||||
var startLine = this.sourceFile.getLineAndCharacterOfPosition(node.getStart(this.sourceFile)).line;
|
||||
var endLine = this.sourceFile.getLineAndCharacterOfPosition(node.getEnd()).line;
|
||||
let startLine = this.sourceFile.getLineAndCharacterOfPosition(node.getStart(this.sourceFile)).line;
|
||||
let endLine = this.sourceFile.getLineAndCharacterOfPosition(node.getEnd()).line;
|
||||
return startLine == endLine;
|
||||
}
|
||||
|
||||
private BlockIsOnOneLine(node: Node): boolean {
|
||||
var openBrace = findChildOfKind(node, SyntaxKind.OpenBraceToken, this.sourceFile);
|
||||
var closeBrace = findChildOfKind(node, SyntaxKind.CloseBraceToken, this.sourceFile);
|
||||
let openBrace = findChildOfKind(node, SyntaxKind.OpenBraceToken, this.sourceFile);
|
||||
let closeBrace = findChildOfKind(node, SyntaxKind.CloseBraceToken, this.sourceFile);
|
||||
if (openBrace && closeBrace) {
|
||||
var startLine = this.sourceFile.getLineAndCharacterOfPosition(openBrace.getEnd()).line;
|
||||
var endLine = this.sourceFile.getLineAndCharacterOfPosition(closeBrace.getStart(this.sourceFile)).line;
|
||||
let startLine = this.sourceFile.getLineAndCharacterOfPosition(openBrace.getEnd()).line;
|
||||
let endLine = this.sourceFile.getLineAndCharacterOfPosition(closeBrace.getStart(this.sourceFile)).line;
|
||||
return startLine === endLine;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/// <reference path="..\..\compiler\scanner.ts"/>
|
||||
|
||||
module ts.formatting {
|
||||
var scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false);
|
||||
let scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false);
|
||||
|
||||
export interface FormattingScanner {
|
||||
advance(): void;
|
||||
@@ -24,13 +24,13 @@ module ts.formatting {
|
||||
scanner.setText(sourceFile.text);
|
||||
scanner.setTextPos(startPos);
|
||||
|
||||
var wasNewLine: boolean = true;
|
||||
var leadingTrivia: TextRangeWithKind[];
|
||||
var trailingTrivia: TextRangeWithKind[];
|
||||
let wasNewLine: boolean = true;
|
||||
let leadingTrivia: TextRangeWithKind[];
|
||||
let trailingTrivia: TextRangeWithKind[];
|
||||
|
||||
var savedPos: number;
|
||||
var lastScanAction: ScanAction;
|
||||
var lastTokenInfo: TokenInfo;
|
||||
let savedPos: number;
|
||||
let lastScanAction: ScanAction;
|
||||
let lastTokenInfo: TokenInfo;
|
||||
|
||||
return {
|
||||
advance: advance,
|
||||
@@ -45,7 +45,7 @@ module ts.formatting {
|
||||
|
||||
function advance(): void {
|
||||
lastTokenInfo = undefined;
|
||||
var isStarted = scanner.getStartPos() !== startPos;
|
||||
let isStarted = scanner.getStartPos() !== startPos;
|
||||
|
||||
if (isStarted) {
|
||||
if (trailingTrivia) {
|
||||
@@ -64,19 +64,19 @@ module ts.formatting {
|
||||
scanner.scan();
|
||||
}
|
||||
|
||||
var t: SyntaxKind;
|
||||
var pos = scanner.getStartPos();
|
||||
let t: SyntaxKind;
|
||||
let pos = scanner.getStartPos();
|
||||
|
||||
// Read leading trivia and token
|
||||
while (pos < endPos) {
|
||||
var t = scanner.getToken();
|
||||
let t = scanner.getToken();
|
||||
if (!isTrivia(t)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// consume leading trivia
|
||||
scanner.scan();
|
||||
var item = {
|
||||
let item = {
|
||||
pos: pos,
|
||||
end: scanner.getStartPos(),
|
||||
kind: t
|
||||
@@ -133,7 +133,7 @@ module ts.formatting {
|
||||
|
||||
// normally scanner returns the smallest available token
|
||||
// check the kind of context node to determine if scanner should have more greedy behavior and consume more text.
|
||||
var expectedScanAction =
|
||||
let expectedScanAction =
|
||||
shouldRescanGreaterThanToken(n)
|
||||
? ScanAction.RescanGreaterThanToken
|
||||
: shouldRescanSlashToken(n)
|
||||
@@ -159,7 +159,7 @@ module ts.formatting {
|
||||
scanner.scan();
|
||||
}
|
||||
|
||||
var currentToken = scanner.getToken();
|
||||
let currentToken = scanner.getToken();
|
||||
|
||||
if (expectedScanAction === ScanAction.RescanGreaterThanToken && currentToken === SyntaxKind.GreaterThanToken) {
|
||||
currentToken = scanner.reScanGreaterToken();
|
||||
@@ -179,7 +179,7 @@ module ts.formatting {
|
||||
lastScanAction = ScanAction.Scan;
|
||||
}
|
||||
|
||||
var token: TextRangeWithKind = {
|
||||
let token: TextRangeWithKind = {
|
||||
pos: scanner.getStartPos(),
|
||||
end: scanner.getTextPos(),
|
||||
kind: currentToken
|
||||
@@ -194,7 +194,7 @@ module ts.formatting {
|
||||
if (!isTrivia(currentToken)) {
|
||||
break;
|
||||
}
|
||||
var trivia = {
|
||||
let trivia = {
|
||||
pos: scanner.getStartPos(),
|
||||
end: scanner.getTextPos(),
|
||||
kind: currentToken
|
||||
@@ -223,8 +223,8 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
function isOnToken(): boolean {
|
||||
var current = (lastTokenInfo && lastTokenInfo.token.kind) || scanner.getToken();
|
||||
var startPos = (lastTokenInfo && lastTokenInfo.token.pos) || scanner.getStartPos();
|
||||
let current = (lastTokenInfo && lastTokenInfo.token.kind) || scanner.getToken();
|
||||
let startPos = (lastTokenInfo && lastTokenInfo.token.pos) || scanner.getStartPos();
|
||||
return startPos < endPos && current !== SyntaxKind.EndOfFileToken && !isTrivia(current);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
module ts.formatting {
|
||||
|
||||
var internedTabsIndentation: string[];
|
||||
var internedSpacesIndentation: string[];
|
||||
|
||||
export function getIndentationString(indentation: number, options: FormatCodeOptions): string {
|
||||
if (!options.ConvertTabsToSpaces) {
|
||||
var tabs = Math.floor(indentation / options.TabSize);
|
||||
var spaces = indentation - tabs * options.TabSize;
|
||||
|
||||
var tabString: string;
|
||||
if (!internedTabsIndentation) {
|
||||
internedTabsIndentation = [];
|
||||
}
|
||||
|
||||
if (internedTabsIndentation[tabs] === undefined) {
|
||||
internedTabsIndentation[tabs] = tabString = repeat('\t', tabs);
|
||||
}
|
||||
else {
|
||||
tabString = internedTabsIndentation[tabs];
|
||||
}
|
||||
|
||||
return spaces ? tabString + repeat(" ", spaces) : tabString;
|
||||
}
|
||||
else {
|
||||
var spacesString: string;
|
||||
var quotient = Math.floor(indentation / options.IndentSize);
|
||||
var remainder = indentation % options.IndentSize;
|
||||
if (!internedSpacesIndentation) {
|
||||
internedSpacesIndentation = [];
|
||||
}
|
||||
|
||||
if (internedSpacesIndentation[quotient] === undefined) {
|
||||
spacesString = repeat(" ", options.IndentSize * quotient);
|
||||
internedSpacesIndentation[quotient] = spacesString;
|
||||
}
|
||||
else {
|
||||
spacesString = internedSpacesIndentation[quotient];
|
||||
}
|
||||
|
||||
|
||||
return remainder ? spacesString + repeat(" ", remainder) : spacesString;
|
||||
}
|
||||
|
||||
function repeat(value: string, count: number): string {
|
||||
var s = "";
|
||||
for (var i = 0; i < count; ++i) {
|
||||
s += value;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,8 +33,7 @@ module ts.formatting {
|
||||
return RuleDescriptor.create4(left, Shared.TokenRange.FromToken(right));
|
||||
}
|
||||
|
||||
static create3(left: SyntaxKind, right: Shared.TokenRange): RuleDescriptor
|
||||
{
|
||||
static create3(left: SyntaxKind, right: Shared.TokenRange): RuleDescriptor {
|
||||
return RuleDescriptor.create4(Shared.TokenRange.FromToken(left), right);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
static create2(context: RuleOperationContext, action: RuleAction) {
|
||||
var result = new RuleOperation();
|
||||
let result = new RuleOperation();
|
||||
result.Context = context;
|
||||
result.Action = action;
|
||||
return result;
|
||||
|
||||
@@ -36,8 +36,8 @@ module ts.formatting {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (var i = 0, len = this.customContextChecks.length; i < len; i++) {
|
||||
if (!this.customContextChecks[i](context)) {
|
||||
for (let check of this.customContextChecks) {
|
||||
if (!check(context)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
module ts.formatting {
|
||||
export class Rules {
|
||||
public getRuleName(rule: Rule) {
|
||||
var o: ts.Map<any> = <any>this;
|
||||
for (var name in o) {
|
||||
let o: ts.Map<any> = <any>this;
|
||||
for (let name in o) {
|
||||
if (o[name] === rule) {
|
||||
return name;
|
||||
}
|
||||
@@ -139,7 +139,7 @@ module ts.formatting {
|
||||
// Lambda expressions
|
||||
public SpaceAfterArrow: Rule;
|
||||
|
||||
// Optional parameters and var args
|
||||
// Optional parameters and let args
|
||||
public NoSpaceAfterEllipsis: Rule;
|
||||
public NoSpaceAfterOptionalParameters: Rule;
|
||||
|
||||
@@ -330,7 +330,7 @@ module ts.formatting {
|
||||
// Lambda expressions
|
||||
this.SpaceAfterArrow = new Rule(RuleDescriptor.create3(SyntaxKind.EqualsGreaterThanToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
|
||||
|
||||
// Optional parameters and var args
|
||||
// Optional parameters and let args
|
||||
this.NoSpaceAfterEllipsis = new Rule(RuleDescriptor.create1(SyntaxKind.DotDotDotToken, SyntaxKind.Identifier), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
|
||||
this.NoSpaceAfterOptionalParameters = new Rule(RuleDescriptor.create3(SyntaxKind.QuestionToken, Shared.TokenRange.FromTokens([SyntaxKind.CloseParenToken, SyntaxKind.CommaToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Delete));
|
||||
|
||||
@@ -462,7 +462,7 @@ module ts.formatting {
|
||||
|
||||
// equal in import a = module('a');
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
// equal in var a = 0;
|
||||
// equal in let a = 0;
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
// equal in p = 0;
|
||||
case SyntaxKind.Parameter:
|
||||
@@ -470,7 +470,7 @@ module ts.formatting {
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.PropertySignature:
|
||||
return context.currentTokenSpan.kind === SyntaxKind.EqualsToken || context.nextTokenSpan.kind === SyntaxKind.EqualsToken;
|
||||
// "in" keyword in for (var x in []) { }
|
||||
// "in" keyword in for (let x in []) { }
|
||||
case SyntaxKind.ForInStatement:
|
||||
return context.currentTokenSpan.kind === SyntaxKind.InKeyword || context.nextTokenSpan.kind === SyntaxKind.InKeyword;
|
||||
// Technically, "of" is not a binary operator, but format it the same way as "in"
|
||||
@@ -541,7 +541,7 @@ module ts.formatting {
|
||||
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.Block:
|
||||
case SyntaxKind.SwitchStatement:
|
||||
case SyntaxKind.CaseBlock:
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
case SyntaxKind.ModuleBlock:
|
||||
return true;
|
||||
|
||||
@@ -26,7 +26,7 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
static create(rules: Rule[]): RulesMap {
|
||||
var result = new RulesMap();
|
||||
let result = new RulesMap();
|
||||
result.Initialize(rules);
|
||||
return result;
|
||||
}
|
||||
@@ -36,7 +36,7 @@ module ts.formatting {
|
||||
this.map = <any> new Array(this.mapRowLength * this.mapRowLength);//new Array<RulesBucket>(this.mapRowLength * this.mapRowLength);
|
||||
|
||||
// This array is used only during construction of the rulesbucket in the map
|
||||
var rulesBucketConstructionStateList: RulesBucketConstructionState[] = <any> new Array(this.map.length);//new Array<RulesBucketConstructionState>(this.map.length);
|
||||
let rulesBucketConstructionStateList: RulesBucketConstructionState[] = <any> new Array(this.map.length);//new Array<RulesBucketConstructionState>(this.map.length);
|
||||
|
||||
this.FillRules(rules, rulesBucketConstructionStateList);
|
||||
return this.map;
|
||||
@@ -49,20 +49,20 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
private GetRuleBucketIndex(row: number, column: number): number {
|
||||
var rulesBucketIndex = (row * this.mapRowLength) + column;
|
||||
let rulesBucketIndex = (row * this.mapRowLength) + column;
|
||||
//Debug.Assert(rulesBucketIndex < this.map.Length, "Trying to access an index outside the array.");
|
||||
return rulesBucketIndex;
|
||||
}
|
||||
|
||||
private FillRule(rule: Rule, rulesBucketConstructionStateList: RulesBucketConstructionState[]): void {
|
||||
var specificRule = rule.Descriptor.LeftTokenRange != Shared.TokenRange.Any &&
|
||||
let specificRule = rule.Descriptor.LeftTokenRange != Shared.TokenRange.Any &&
|
||||
rule.Descriptor.RightTokenRange != Shared.TokenRange.Any;
|
||||
|
||||
rule.Descriptor.LeftTokenRange.GetTokens().forEach((left) => {
|
||||
rule.Descriptor.RightTokenRange.GetTokens().forEach((right) => {
|
||||
var rulesBucketIndex = this.GetRuleBucketIndex(left, right);
|
||||
let rulesBucketIndex = this.GetRuleBucketIndex(left, right);
|
||||
|
||||
var rulesBucket = this.map[rulesBucketIndex];
|
||||
let rulesBucket = this.map[rulesBucketIndex];
|
||||
if (rulesBucket == undefined) {
|
||||
rulesBucket = this.map[rulesBucketIndex] = new RulesBucket();
|
||||
}
|
||||
@@ -73,21 +73,21 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
public GetRule(context: FormattingContext): Rule {
|
||||
var bucketIndex = this.GetRuleBucketIndex(context.currentTokenSpan.kind, context.nextTokenSpan.kind);
|
||||
var bucket = this.map[bucketIndex];
|
||||
let bucketIndex = this.GetRuleBucketIndex(context.currentTokenSpan.kind, context.nextTokenSpan.kind);
|
||||
let bucket = this.map[bucketIndex];
|
||||
if (bucket != null) {
|
||||
for (var i = 0, len = bucket.Rules().length; i < len; i++) {
|
||||
var rule = bucket.Rules()[i];
|
||||
if (rule.Operation.Context.InContext(context))
|
||||
for (let rule of bucket.Rules()) {
|
||||
if (rule.Operation.Context.InContext(context)) {
|
||||
return rule;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
var MaskBitSize = 5;
|
||||
var Mask = 0x1f;
|
||||
let MaskBitSize = 5;
|
||||
let Mask = 0x1f;
|
||||
|
||||
export enum RulesPosition {
|
||||
IgnoreRulesSpecific = 0,
|
||||
@@ -121,10 +121,10 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
public GetInsertionIndex(maskPosition: RulesPosition): number {
|
||||
var index = 0;
|
||||
let index = 0;
|
||||
|
||||
var pos = 0;
|
||||
var indexBitmap = this.rulesInsertionIndexBitmap;
|
||||
let pos = 0;
|
||||
let indexBitmap = this.rulesInsertionIndexBitmap;
|
||||
|
||||
while (pos <= maskPosition) {
|
||||
index += (indexBitmap & Mask);
|
||||
@@ -136,11 +136,11 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
public IncreaseInsertionIndex(maskPosition: RulesPosition): void {
|
||||
var value = (this.rulesInsertionIndexBitmap >> maskPosition) & Mask;
|
||||
let value = (this.rulesInsertionIndexBitmap >> maskPosition) & Mask;
|
||||
value++;
|
||||
Debug.assert((value & Mask) == value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules.");
|
||||
|
||||
var temp = this.rulesInsertionIndexBitmap & ~(Mask << maskPosition);
|
||||
let temp = this.rulesInsertionIndexBitmap & ~(Mask << maskPosition);
|
||||
temp |= value << maskPosition;
|
||||
|
||||
this.rulesInsertionIndexBitmap = temp;
|
||||
@@ -159,7 +159,7 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
public AddRule(rule: Rule, specificTokens: boolean, constructionState: RulesBucketConstructionState[], rulesBucketIndex: number): void {
|
||||
var position: RulesPosition;
|
||||
let position: RulesPosition;
|
||||
|
||||
if (rule.Operation.Action == RuleAction.Ignore) {
|
||||
position = specificTokens ?
|
||||
@@ -177,11 +177,11 @@ module ts.formatting {
|
||||
RulesPosition.NoContextRulesAny;
|
||||
}
|
||||
|
||||
var state = constructionState[rulesBucketIndex];
|
||||
let state = constructionState[rulesBucketIndex];
|
||||
if (state === undefined) {
|
||||
state = constructionState[rulesBucketIndex] = new RulesBucketConstructionState();
|
||||
}
|
||||
var index = state.GetInsertionIndex(position);
|
||||
let index = state.GetInsertionIndex(position);
|
||||
this.rules.splice(index, 0, rule);
|
||||
state.IncreaseInsertionIndex(position);
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ module ts.formatting {
|
||||
|
||||
public ensureUpToDate(options: ts.FormatCodeOptions) {
|
||||
if (this.options == null || !ts.compareDataObjects(this.options, options)) {
|
||||
var activeRules = this.createActiveRules(options);
|
||||
var rulesMap = RulesMap.create(activeRules);
|
||||
let activeRules = this.createActiveRules(options);
|
||||
let rulesMap = RulesMap.create(activeRules);
|
||||
|
||||
this.activeRules = activeRules;
|
||||
this.rulesMap = rulesMap;
|
||||
@@ -50,7 +50,7 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
private createActiveRules(options: ts.FormatCodeOptions): Rule[] {
|
||||
var rules = this.globalRules.HighPriorityCommonRules.slice(0);
|
||||
let rules = this.globalRules.HighPriorityCommonRules.slice(0);
|
||||
|
||||
if (options.InsertSpaceAfterCommaDelimiter) {
|
||||
rules.push(this.globalRules.SpaceAfterComma);
|
||||
|
||||
@@ -12,13 +12,13 @@ module ts.formatting {
|
||||
return 0; // past EOF
|
||||
}
|
||||
|
||||
var precedingToken = findPrecedingToken(position, sourceFile);
|
||||
let precedingToken = findPrecedingToken(position, sourceFile);
|
||||
if (!precedingToken) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// no indentation in string \regex\template literals
|
||||
var precedingTokenIsLiteral =
|
||||
let precedingTokenIsLiteral =
|
||||
precedingToken.kind === SyntaxKind.StringLiteral ||
|
||||
precedingToken.kind === SyntaxKind.RegularExpressionLiteral ||
|
||||
precedingToken.kind === SyntaxKind.NoSubstitutionTemplateLiteral ||
|
||||
@@ -29,11 +29,11 @@ module ts.formatting {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var lineAtPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
|
||||
let lineAtPosition = sourceFile.getLineAndCharacterOfPosition(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);
|
||||
let actualIndentation = getActualIndentationForListItemBeforeComma(precedingToken, sourceFile, options);
|
||||
if (actualIndentation !== Value.Unknown) {
|
||||
return actualIndentation;
|
||||
}
|
||||
@@ -41,10 +41,10 @@ module ts.formatting {
|
||||
|
||||
// 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;
|
||||
let previous: Node;
|
||||
let current = precedingToken;
|
||||
let currentStart: LineAndCharacter;
|
||||
let indentationDelta: number;
|
||||
|
||||
while (current) {
|
||||
if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current.kind, previous ? previous.kind : SyntaxKind.Unknown)) {
|
||||
@@ -61,7 +61,7 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
// check if current node is a list item - if yes, take indentation from it
|
||||
var actualIndentation = getActualIndentationForListItem(current, sourceFile, options);
|
||||
let actualIndentation = getActualIndentationForListItem(current, sourceFile, options);
|
||||
if (actualIndentation !== Value.Unknown) {
|
||||
return actualIndentation;
|
||||
}
|
||||
@@ -79,7 +79,7 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
export function getIndentationForNode(n: Node, ignoreActualIndentationRange: TextRange, sourceFile: SourceFile, options: FormatCodeOptions): number {
|
||||
var start = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
|
||||
let start = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
|
||||
return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, /*indentationDelta*/ 0, sourceFile, options);
|
||||
}
|
||||
|
||||
@@ -91,33 +91,33 @@ module ts.formatting {
|
||||
sourceFile: SourceFile,
|
||||
options: EditorOptions): number {
|
||||
|
||||
var parent: Node = current.parent;
|
||||
var parentStart: LineAndCharacter;
|
||||
let parent: Node = current.parent;
|
||||
let 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) {
|
||||
var useActualIndentation = true;
|
||||
let useActualIndentation = true;
|
||||
if (ignoreActualIndentationRange) {
|
||||
var start = current.getStart(sourceFile);
|
||||
let start = current.getStart(sourceFile);
|
||||
useActualIndentation = start < ignoreActualIndentationRange.pos || start > ignoreActualIndentationRange.end;
|
||||
}
|
||||
|
||||
if (useActualIndentation) {
|
||||
// check if current node is a list item - if yes, take indentation from it
|
||||
var actualIndentation = getActualIndentationForListItem(current, sourceFile, options);
|
||||
let actualIndentation = getActualIndentationForListItem(current, sourceFile, options);
|
||||
if (actualIndentation !== Value.Unknown) {
|
||||
return actualIndentation + indentationDelta;
|
||||
}
|
||||
}
|
||||
parentStart = getParentStart(parent, current, sourceFile);
|
||||
var parentAndChildShareLine =
|
||||
let parentAndChildShareLine =
|
||||
parentStart.line === currentStart.line ||
|
||||
childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile);
|
||||
|
||||
if (useActualIndentation) {
|
||||
// try to fetch actual indentation for current node from source text
|
||||
var actualIndentation = getActualIndentationForNode(current, parent, currentStart, parentAndChildShareLine, sourceFile, options);
|
||||
let actualIndentation = getActualIndentationForNode(current, parent, currentStart, parentAndChildShareLine, sourceFile, options);
|
||||
if (actualIndentation !== Value.Unknown) {
|
||||
return actualIndentation + indentationDelta;
|
||||
}
|
||||
@@ -138,7 +138,7 @@ module ts.formatting {
|
||||
|
||||
|
||||
function getParentStart(parent: Node, child: Node, sourceFile: SourceFile): LineAndCharacter {
|
||||
var containingList = getContainingList(child, sourceFile);
|
||||
let containingList = getContainingList(child, sourceFile);
|
||||
if (containingList) {
|
||||
return sourceFile.getLineAndCharacterOfPosition(containingList.pos);
|
||||
}
|
||||
@@ -151,7 +151,7 @@ module ts.formatting {
|
||||
*/
|
||||
function getActualIndentationForListItemBeforeComma(commaToken: Node, sourceFile: SourceFile, options: EditorOptions): 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);
|
||||
let commaItemInfo = findListItemInfo(commaToken);
|
||||
if (commaItemInfo && commaItemInfo.listItemIndex > 0) {
|
||||
return deriveActualIndentationFromList(commaItemInfo.list.getChildren(), commaItemInfo.listItemIndex - 1, sourceFile, options);
|
||||
}
|
||||
@@ -174,7 +174,7 @@ module ts.formatting {
|
||||
// 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 =
|
||||
let useActualIndentation =
|
||||
(isDeclaration(current) || isStatement(current)) &&
|
||||
(parent.kind === SyntaxKind.SourceFile || !parentAndChildShareLine);
|
||||
|
||||
@@ -186,7 +186,7 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken: Node, current: Node, lineAtPosition: number, sourceFile: SourceFile): boolean {
|
||||
var nextToken = findNextToken(precedingToken, current);
|
||||
let nextToken = findNextToken(precedingToken, current);
|
||||
if (!nextToken) {
|
||||
return false;
|
||||
}
|
||||
@@ -205,7 +205,7 @@ module ts.formatting {
|
||||
// class A {
|
||||
// $}
|
||||
|
||||
var nextTokenStartLine = getStartLineAndCharacterForNode(nextToken, sourceFile).line;
|
||||
let nextTokenStartLine = getStartLineAndCharacterForNode(nextToken, sourceFile).line;
|
||||
return lineAtPosition === nextTokenStartLine;
|
||||
}
|
||||
|
||||
@@ -222,10 +222,10 @@ module ts.formatting {
|
||||
|
||||
export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFile): boolean {
|
||||
if (parent.kind === SyntaxKind.IfStatement && (<IfStatement>parent).elseStatement === child) {
|
||||
var elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile);
|
||||
let elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile);
|
||||
Debug.assert(elseKeyword !== undefined);
|
||||
|
||||
var elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line;
|
||||
let elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line;
|
||||
return elseKeywordStartLine === childStartLine;
|
||||
}
|
||||
|
||||
@@ -251,8 +251,8 @@ module ts.formatting {
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.MethodSignature:
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
var start = node.getStart(sourceFile);
|
||||
case SyntaxKind.ConstructSignature: {
|
||||
let start = node.getStart(sourceFile);
|
||||
if ((<SignatureDeclaration>node.parent).typeParameters &&
|
||||
rangeContainsStartEnd((<SignatureDeclaration>node.parent).typeParameters, start, node.getEnd())) {
|
||||
return (<SignatureDeclaration>node.parent).typeParameters;
|
||||
@@ -261,9 +261,10 @@ module ts.formatting {
|
||||
return (<SignatureDeclaration>node.parent).parameters;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.NewExpression:
|
||||
case SyntaxKind.CallExpression:
|
||||
var start = node.getStart(sourceFile);
|
||||
case SyntaxKind.CallExpression: {
|
||||
let start = node.getStart(sourceFile);
|
||||
if ((<CallExpression>node.parent).typeArguments &&
|
||||
rangeContainsStartEnd((<CallExpression>node.parent).typeArguments, start, node.getEnd())) {
|
||||
return (<CallExpression>node.parent).typeArguments;
|
||||
@@ -273,34 +274,35 @@ module ts.formatting {
|
||||
return (<CallExpression>node.parent).arguments;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getActualIndentationForListItem(node: Node, sourceFile: SourceFile, options: EditorOptions): number {
|
||||
var containingList = getContainingList(node, sourceFile);
|
||||
let containingList = getContainingList(node, sourceFile);
|
||||
return containingList ? getActualIndentationFromList(containingList) : Value.Unknown;
|
||||
|
||||
function getActualIndentationFromList(list: Node[]): number {
|
||||
var index = indexOf(list, node);
|
||||
let index = indexOf(list, node);
|
||||
return index !== -1 ? deriveActualIndentationFromList(list, index, sourceFile, options) : Value.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
function deriveActualIndentationFromList(list: Node[], index: number, sourceFile: SourceFile, options: EditorOptions): number {
|
||||
Debug.assert(index >= 0 && index < list.length);
|
||||
var node = list[index];
|
||||
let 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) {
|
||||
let lineAndCharacter = getStartLineAndCharacterForNode(node, sourceFile);
|
||||
for (let 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.getLineAndCharacterOfPosition(list[i].end).line;
|
||||
let prevEndLine = sourceFile.getLineAndCharacterOfPosition(list[i].end).line;
|
||||
if (prevEndLine !== lineAndCharacter.line) {
|
||||
return findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options);
|
||||
}
|
||||
@@ -311,7 +313,7 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter: LineAndCharacter, sourceFile: SourceFile, options: EditorOptions): number {
|
||||
var lineStart = sourceFile.getPositionOfLineAndCharacter(lineAndCharacter.line, 0);
|
||||
let lineStart = sourceFile.getPositionOfLineAndCharacter(lineAndCharacter.line, 0);
|
||||
return findFirstNonWhitespaceColumn(lineStart, lineStart + lineAndCharacter.character, sourceFile, options);
|
||||
}
|
||||
|
||||
@@ -323,10 +325,10 @@ module ts.formatting {
|
||||
value of 'column' for '$' is 6 (assuming that tab size is 4)
|
||||
*/
|
||||
export function findFirstNonWhitespaceCharacterAndColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorOptions) {
|
||||
var character = 0;
|
||||
var column = 0;
|
||||
for (var pos = startPos; pos < endPos; ++pos) {
|
||||
var ch = sourceFile.text.charCodeAt(pos);
|
||||
let character = 0;
|
||||
let column = 0;
|
||||
for (let pos = startPos; pos < endPos; ++pos) {
|
||||
let ch = sourceFile.text.charCodeAt(pos);
|
||||
if (!isWhiteSpace(ch)) {
|
||||
break;
|
||||
}
|
||||
@@ -357,7 +359,8 @@ module ts.formatting {
|
||||
case SyntaxKind.ModuleBlock:
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.SwitchStatement:
|
||||
case SyntaxKind.TupleType:
|
||||
case SyntaxKind.CaseBlock:
|
||||
case SyntaxKind.DefaultClause:
|
||||
case SyntaxKind.CaseClause:
|
||||
case SyntaxKind.ParenthesizedExpression:
|
||||
@@ -368,6 +371,8 @@ module ts.formatting {
|
||||
case SyntaxKind.ExportAssignment:
|
||||
case SyntaxKind.ReturnStatement:
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -388,6 +393,7 @@ module ts.formatting {
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.MethodSignature:
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
case SyntaxKind.Constructor:
|
||||
case SyntaxKind.GetAccessor:
|
||||
@@ -403,9 +409,9 @@ module ts.formatting {
|
||||
* 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);
|
||||
let children = n.getChildren(sourceFile);
|
||||
if (children.length) {
|
||||
var last = children[children.length - 1];
|
||||
let last = children[children.length - 1];
|
||||
if (last.kind === expectedLastToken) {
|
||||
return true;
|
||||
}
|
||||
@@ -429,47 +435,93 @@ module ts.formatting {
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.Block:
|
||||
case SyntaxKind.ModuleBlock:
|
||||
case SyntaxKind.SwitchStatement:
|
||||
case SyntaxKind.CaseBlock:
|
||||
return nodeEndsWith(n, SyntaxKind.CloseBraceToken, sourceFile);
|
||||
case SyntaxKind.CatchClause:
|
||||
return isCompletedNode((<CatchClause>n).block, sourceFile);
|
||||
case SyntaxKind.ParenthesizedExpression:
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.NewExpression:
|
||||
if (!(<NewExpression>n).arguments) {
|
||||
return true;
|
||||
}
|
||||
// fall through
|
||||
case SyntaxKind.CallExpression:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
case SyntaxKind.ParenthesizedExpression:
|
||||
case SyntaxKind.ParenthesizedType:
|
||||
return nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile);
|
||||
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.ConstructorType:
|
||||
return isCompletedNode((<SignatureDeclaration>n).type, sourceFile);
|
||||
|
||||
case SyntaxKind.Constructor:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.MethodSignature:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return !(<FunctionLikeDeclaration>n).body || isCompletedNode((<FunctionLikeDeclaration>n).body, sourceFile);
|
||||
if ((<FunctionLikeDeclaration>n).body) {
|
||||
return isCompletedNode((<FunctionLikeDeclaration>n).body, sourceFile);
|
||||
}
|
||||
|
||||
if ((<FunctionLikeDeclaration>n).type) {
|
||||
return isCompletedNode((<FunctionLikeDeclaration>n).type, sourceFile);
|
||||
}
|
||||
|
||||
// Even though type parameters can be unclosed, we can get away with
|
||||
// having at least a closing paren.
|
||||
return hasChildOfKind(n, SyntaxKind.CloseParenToken, 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.ArrayLiteralExpression:
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
case SyntaxKind.ComputedPropertyName:
|
||||
case SyntaxKind.TupleType:
|
||||
return nodeEndsWith(n, SyntaxKind.CloseBracketToken, sourceFile);
|
||||
|
||||
case SyntaxKind.IndexSignature:
|
||||
if ((<IndexSignatureDeclaration>n).type) {
|
||||
return isCompletedNode((<IndexSignatureDeclaration>n).type, sourceFile);
|
||||
}
|
||||
|
||||
return hasChildOfKind(n, SyntaxKind.CloseBracketToken, sourceFile);
|
||||
|
||||
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
|
||||
// there is no such thing as terminator token for CaseClause/DefaultClause so for simplicitly always consider them non-completed
|
||||
return false;
|
||||
|
||||
case SyntaxKind.ForStatement:
|
||||
case SyntaxKind.ForInStatement:
|
||||
case SyntaxKind.ForOfStatement:
|
||||
case SyntaxKind.WhileStatement:
|
||||
return isCompletedNode((<WhileStatement>n).statement, sourceFile);
|
||||
return isCompletedNode((<IterationStatement>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);
|
||||
let hasWhileKeyword = findChildOfKind(n, SyntaxKind.WhileKeyword, sourceFile);
|
||||
if (hasWhileKeyword) {
|
||||
return nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile);
|
||||
}
|
||||
return isCompletedNode((<DoStatement>n).statement, sourceFile);
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ module ts.formatting {
|
||||
|
||||
constructor(from: SyntaxKind, to: SyntaxKind, except: SyntaxKind[]) {
|
||||
this.tokens = [];
|
||||
for (var token = from; token <= to; token++) {
|
||||
for (let token = from; token <= to; token++) {
|
||||
if (except.indexOf(token) < 0) {
|
||||
this.tokens.push(token);
|
||||
}
|
||||
@@ -74,8 +74,8 @@ module ts.formatting {
|
||||
|
||||
export class TokenAllAccess implements ITokenAccess {
|
||||
public GetTokens(): SyntaxKind[] {
|
||||
var result: SyntaxKind[] = [];
|
||||
for (var token = SyntaxKind.FirstToken; token <= SyntaxKind.LastToken; token++) {
|
||||
let result: SyntaxKind[] = [];
|
||||
for (let token = SyntaxKind.FirstToken; token <= SyntaxKind.LastToken; token++) {
|
||||
result.push(token);
|
||||
}
|
||||
return result;
|
||||
|
||||
+23
-24
@@ -2,22 +2,21 @@ module ts.NavigateTo {
|
||||
type RawNavigateToItem = { name: string; fileName: string; matchKind: PatternMatchKind; isCaseSensitive: boolean; declaration: Declaration };
|
||||
|
||||
export function getNavigateToItems(program: Program, cancellationToken: CancellationTokenObject, searchValue: string, maxResultCount: number): NavigateToItem[] {
|
||||
var patternMatcher = createPatternMatcher(searchValue);
|
||||
var rawItems: RawNavigateToItem[] = [];
|
||||
let patternMatcher = createPatternMatcher(searchValue);
|
||||
let rawItems: RawNavigateToItem[] = [];
|
||||
|
||||
// Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[]
|
||||
forEach(program.getSourceFiles(), sourceFile => {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
var declarations = sourceFile.getNamedDeclarations();
|
||||
for (var i = 0, n = declarations.length; i < n; i++) {
|
||||
var declaration = declarations[i];
|
||||
let declarations = sourceFile.getNamedDeclarations();
|
||||
for (let declaration of declarations) {
|
||||
var name = getDeclarationName(declaration);
|
||||
if (name !== undefined) {
|
||||
|
||||
// First do a quick check to see if the name of the declaration matches the
|
||||
// last portion of the (possibly) dotted name they're searching for.
|
||||
var matches = patternMatcher.getMatchesForLastSegmentOfPattern(name);
|
||||
let matches = patternMatcher.getMatchesForLastSegmentOfPattern(name);
|
||||
|
||||
if (!matches) {
|
||||
continue;
|
||||
@@ -26,7 +25,7 @@ module ts.NavigateTo {
|
||||
// It was a match! If the pattern has dots in it, then also see if hte
|
||||
// declaration container matches as well.
|
||||
if (patternMatcher.patternContainsDots) {
|
||||
var containers = getContainers(declaration);
|
||||
let containers = getContainers(declaration);
|
||||
if (!containers) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -38,8 +37,8 @@ module ts.NavigateTo {
|
||||
}
|
||||
}
|
||||
|
||||
var fileName = sourceFile.fileName;
|
||||
var matchKind = bestMatchKind(matches);
|
||||
let fileName = sourceFile.fileName;
|
||||
let matchKind = bestMatchKind(matches);
|
||||
rawItems.push({ name, fileName, matchKind, isCaseSensitive: allMatchesAreCaseSensitive(matches), declaration });
|
||||
}
|
||||
}
|
||||
@@ -50,7 +49,7 @@ module ts.NavigateTo {
|
||||
rawItems = rawItems.slice(0, maxResultCount);
|
||||
}
|
||||
|
||||
var items = map(rawItems, createNavigateToItem);
|
||||
let items = map(rawItems, createNavigateToItem);
|
||||
|
||||
return items;
|
||||
|
||||
@@ -58,8 +57,8 @@ module ts.NavigateTo {
|
||||
Debug.assert(matches.length > 0);
|
||||
|
||||
// This is a case sensitive match, only if all the submatches were case sensitive.
|
||||
for (var i = 0, n = matches.length; i < n; i++) {
|
||||
if (!matches[i].isCaseSensitive) {
|
||||
for (let match of matches) {
|
||||
if (!match.isCaseSensitive) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -68,13 +67,13 @@ module ts.NavigateTo {
|
||||
}
|
||||
|
||||
function getDeclarationName(declaration: Declaration): string {
|
||||
var result = getTextOfIdentifierOrLiteral(declaration.name);
|
||||
let result = getTextOfIdentifierOrLiteral(declaration.name);
|
||||
if (result !== undefined) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (declaration.name.kind === SyntaxKind.ComputedPropertyName) {
|
||||
var expr = (<ComputedPropertyName>declaration.name).expression;
|
||||
let expr = (<ComputedPropertyName>declaration.name).expression;
|
||||
if (expr.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
return (<PropertyAccessExpression>expr).name.text;
|
||||
}
|
||||
@@ -98,7 +97,7 @@ module ts.NavigateTo {
|
||||
|
||||
function tryAddSingleDeclarationName(declaration: Declaration, containers: string[]) {
|
||||
if (declaration && declaration.name) {
|
||||
var text = getTextOfIdentifierOrLiteral(declaration.name);
|
||||
let text = getTextOfIdentifierOrLiteral(declaration.name);
|
||||
if (text !== undefined) {
|
||||
containers.unshift(text);
|
||||
}
|
||||
@@ -118,7 +117,7 @@ module ts.NavigateTo {
|
||||
//
|
||||
// [X.Y.Z]() { }
|
||||
function tryAddComputedPropertyName(expression: Expression, containers: string[], includeLastPortion: boolean): boolean {
|
||||
var text = getTextOfIdentifierOrLiteral(expression);
|
||||
let text = getTextOfIdentifierOrLiteral(expression);
|
||||
if (text !== undefined) {
|
||||
if (includeLastPortion) {
|
||||
containers.unshift(text);
|
||||
@@ -127,7 +126,7 @@ module ts.NavigateTo {
|
||||
}
|
||||
|
||||
if (expression.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
var propertyAccess = <PropertyAccessExpression>expression;
|
||||
let propertyAccess = <PropertyAccessExpression>expression;
|
||||
if (includeLastPortion) {
|
||||
containers.unshift(propertyAccess.name.text);
|
||||
}
|
||||
@@ -139,7 +138,7 @@ module ts.NavigateTo {
|
||||
}
|
||||
|
||||
function getContainers(declaration: Declaration) {
|
||||
var containers: string[] = [];
|
||||
let containers: string[] = [];
|
||||
|
||||
// First, if we started with a computed property name, then add all but the last
|
||||
// portion into the container array.
|
||||
@@ -165,10 +164,10 @@ module ts.NavigateTo {
|
||||
|
||||
function bestMatchKind(matches: PatternMatch[]) {
|
||||
Debug.assert(matches.length > 0);
|
||||
var bestMatchKind = PatternMatchKind.camelCase;
|
||||
let bestMatchKind = PatternMatchKind.camelCase;
|
||||
|
||||
for (var i = 0, n = matches.length; i < n; i++) {
|
||||
var kind = matches[i].kind;
|
||||
for (let match of matches) {
|
||||
let kind = match.kind;
|
||||
if (kind < bestMatchKind) {
|
||||
bestMatchKind = kind;
|
||||
}
|
||||
@@ -178,7 +177,7 @@ module ts.NavigateTo {
|
||||
}
|
||||
|
||||
// This means "compare in a case insensitive manner."
|
||||
var baseSensitivity: Intl.CollatorOptions = { sensitivity: "base" };
|
||||
let baseSensitivity: Intl.CollatorOptions = { sensitivity: "base" };
|
||||
function compareNavigateToItems(i1: RawNavigateToItem, i2: RawNavigateToItem) {
|
||||
// TODO(cyrusn): get the gamut of comparisons that VS already uses here.
|
||||
// Right now we just sort by kind first, and then by name of the item.
|
||||
@@ -190,8 +189,8 @@ module ts.NavigateTo {
|
||||
}
|
||||
|
||||
function createNavigateToItem(rawItem: RawNavigateToItem): NavigateToItem {
|
||||
var declaration = rawItem.declaration;
|
||||
var container = <Declaration>getContainerNode(declaration);
|
||||
let declaration = rawItem.declaration;
|
||||
let container = <Declaration>getContainerNode(declaration);
|
||||
return {
|
||||
name: rawItem.name,
|
||||
kind: getNodeKind(declaration),
|
||||
|
||||
@@ -4,16 +4,16 @@ 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;
|
||||
let 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;
|
||||
let indent = hasGlobalNode ? 1 : 0;
|
||||
|
||||
var current = node.parent;
|
||||
let current = node.parent;
|
||||
while (current) {
|
||||
switch (current.kind) {
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
@@ -39,7 +39,7 @@ module ts.NavigationBar {
|
||||
}
|
||||
|
||||
function getChildNodes(nodes: Node[]): Node[] {
|
||||
var childNodes: Node[] = [];
|
||||
let childNodes: Node[] = [];
|
||||
|
||||
function visit(node: Node) {
|
||||
switch (node.kind) {
|
||||
@@ -60,7 +60,7 @@ module ts.NavigationBar {
|
||||
break;
|
||||
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
var importClause = (<ImportDeclaration>node).importClause;
|
||||
let importClause = (<ImportDeclaration>node).importClause;
|
||||
if (importClause) {
|
||||
// Handle default import case e.g.:
|
||||
// import d from "mod";
|
||||
@@ -102,8 +102,8 @@ module ts.NavigationBar {
|
||||
}
|
||||
}
|
||||
|
||||
//for (var i = 0, n = nodes.length; i < n; i++) {
|
||||
// var node = nodes[i];
|
||||
//for (let i = 0, n = nodes.length; i < n; i++) {
|
||||
// let node = nodes[i];
|
||||
|
||||
// if (node.kind === SyntaxKind.ClassDeclaration ||
|
||||
// node.kind === SyntaxKind.EnumDeclaration ||
|
||||
@@ -122,7 +122,7 @@ module ts.NavigationBar {
|
||||
}
|
||||
|
||||
function getTopLevelNodes(node: SourceFile): Node[] {
|
||||
var topLevelNodes: Node[] = [];
|
||||
let topLevelNodes: Node[] = [];
|
||||
topLevelNodes.push(node);
|
||||
|
||||
addTopLevelNodes(node.statements, topLevelNodes);
|
||||
@@ -150,8 +150,7 @@ module ts.NavigationBar {
|
||||
function addTopLevelNodes(nodes: Node[], topLevelNodes: Node[]): void {
|
||||
nodes = sortNodes(nodes);
|
||||
|
||||
for (var i = 0, n = nodes.length; i < n; i++) {
|
||||
var node = nodes[i];
|
||||
for (let node of nodes) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
@@ -160,13 +159,13 @@ module ts.NavigationBar {
|
||||
break;
|
||||
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
var moduleDeclaration = <ModuleDeclaration>node;
|
||||
let moduleDeclaration = <ModuleDeclaration>node;
|
||||
topLevelNodes.push(node);
|
||||
addTopLevelNodes((<Block>getInnermostModule(moduleDeclaration).body).statements, topLevelNodes);
|
||||
break;
|
||||
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
var functionDeclaration = <FunctionLikeDeclaration>node;
|
||||
let functionDeclaration = <FunctionLikeDeclaration>node;
|
||||
if (isTopLevelFunctionDeclaration(functionDeclaration)) {
|
||||
topLevelNodes.push(node);
|
||||
addTopLevelNodes((<Block>functionDeclaration.body).statements, topLevelNodes);
|
||||
@@ -200,18 +199,17 @@ module ts.NavigationBar {
|
||||
}
|
||||
|
||||
function getItemsWorker(nodes: Node[], createItem: (n: Node) => ts.NavigationBarItem): ts.NavigationBarItem[] {
|
||||
var items: ts.NavigationBarItem[] = [];
|
||||
let items: ts.NavigationBarItem[] = [];
|
||||
|
||||
var keyToItem: Map<NavigationBarItem> = {};
|
||||
let keyToItem: Map<NavigationBarItem> = {};
|
||||
|
||||
for (var i = 0, n = nodes.length; i < n; i++) {
|
||||
var child = nodes[i];
|
||||
var item = createItem(child);
|
||||
for (let child of nodes) {
|
||||
let item = createItem(child);
|
||||
if (item !== undefined) {
|
||||
if (item.text.length > 0) {
|
||||
var key = item.text + "-" + item.kind + "-" + item.indent;
|
||||
let key = item.text + "-" + item.kind + "-" + item.indent;
|
||||
|
||||
var itemWithSameName = keyToItem[key];
|
||||
let itemWithSameName = keyToItem[key];
|
||||
if (itemWithSameName) {
|
||||
// We had an item with the same name. Merge these items together.
|
||||
merge(itemWithSameName, item);
|
||||
@@ -238,12 +236,8 @@ module ts.NavigationBar {
|
||||
|
||||
// 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];
|
||||
|
||||
for (let sourceChild of source.childItems) {
|
||||
for (let targetChild of target.childItems) {
|
||||
if (targetChild.text === sourceChild.text && targetChild.kind === sourceChild.kind) {
|
||||
// Found a match. merge them.
|
||||
merge(targetChild, sourceChild);
|
||||
@@ -299,8 +293,8 @@ module ts.NavigationBar {
|
||||
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
case SyntaxKind.BindingElement:
|
||||
var variableDeclarationNode: Node;
|
||||
var name: Node;
|
||||
let variableDeclarationNode: Node;
|
||||
let name: Node;
|
||||
|
||||
if (node.kind === SyntaxKind.BindingElement) {
|
||||
name = (<BindingElement>node).name;
|
||||
@@ -397,7 +391,7 @@ module ts.NavigationBar {
|
||||
}
|
||||
|
||||
// Otherwise, we need to aggregate each identifier to build up the qualified name.
|
||||
var result: string[] = [];
|
||||
let result: string[] = [];
|
||||
|
||||
result.push(moduleDeclaration.name.text);
|
||||
|
||||
@@ -411,9 +405,9 @@ module ts.NavigationBar {
|
||||
}
|
||||
|
||||
function createModuleItem(node: ModuleDeclaration): NavigationBarItem {
|
||||
var moduleName = getModuleName(node);
|
||||
let moduleName = getModuleName(node);
|
||||
|
||||
var childItems = getItemsWorker(getChildNodes((<Block>getInnermostModule(node).body).statements), createChildItem);
|
||||
let childItems = getItemsWorker(getChildNodes((<Block>getInnermostModule(node).body).statements), createChildItem);
|
||||
|
||||
return getNavigationBarItem(moduleName,
|
||||
ts.ScriptElementKind.moduleElement,
|
||||
@@ -424,10 +418,10 @@ module ts.NavigationBar {
|
||||
}
|
||||
|
||||
function createFunctionItem(node: FunctionDeclaration) {
|
||||
if (node.name && node.body && node.body.kind === SyntaxKind.Block) {
|
||||
var childItems = getItemsWorker(sortNodes((<Block>node.body).statements), createChildItem);
|
||||
if ((node.name || node.flags & NodeFlags.Default) && node.body && node.body.kind === SyntaxKind.Block) {
|
||||
let childItems = getItemsWorker(sortNodes((<Block>node.body).statements), createChildItem);
|
||||
|
||||
return getNavigationBarItem(node.name.text,
|
||||
return getNavigationBarItem((!node.name && node.flags & NodeFlags.Default) ? "default": node.name.text ,
|
||||
ts.ScriptElementKind.functionElement,
|
||||
getNodeModifiers(node),
|
||||
[getNodeSpan(node)],
|
||||
@@ -439,14 +433,14 @@ module ts.NavigationBar {
|
||||
}
|
||||
|
||||
function createSourceFileItem(node: SourceFile): ts.NavigationBarItem {
|
||||
var childItems = getItemsWorker(getChildNodes(node.statements), createChildItem);
|
||||
let childItems = getItemsWorker(getChildNodes(node.statements), createChildItem);
|
||||
|
||||
if (childItems === undefined || childItems.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
hasGlobalNode = true;
|
||||
var rootName = isExternalModule(node)
|
||||
let rootName = isExternalModule(node)
|
||||
? "\"" + escapeString(getBaseFileName(removeFileExtension(normalizePath(node.fileName)))) + "\""
|
||||
: "<global>"
|
||||
|
||||
@@ -458,26 +452,28 @@ module ts.NavigationBar {
|
||||
}
|
||||
|
||||
function createClassItem(node: ClassDeclaration): ts.NavigationBarItem {
|
||||
var childItems: NavigationBarItem[];
|
||||
let childItems: NavigationBarItem[];
|
||||
|
||||
if (node.members) {
|
||||
var constructor = <ConstructorDeclaration>forEach(node.members, member => {
|
||||
let 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).
|
||||
// Note that *all non-binding pattern named* parameters will be added to the nodes array, but parameters that
|
||||
// are not properties will be filtered out later by createChildItem.
|
||||
var nodes: Node[] = removeDynamicallyNamedProperties(node);
|
||||
let nodes: Node[] = removeDynamicallyNamedProperties(node);
|
||||
if (constructor) {
|
||||
nodes.push.apply(nodes, filter(constructor.parameters, p => !isBindingPattern(p.name)));
|
||||
}
|
||||
|
||||
var childItems = getItemsWorker(sortNodes(nodes), createChildItem);
|
||||
childItems = getItemsWorker(sortNodes(nodes), createChildItem);
|
||||
}
|
||||
|
||||
var nodeName = !node.name && (node.flags & NodeFlags.Default) ? "default" : node.name.text;
|
||||
|
||||
return getNavigationBarItem(
|
||||
node.name.text,
|
||||
nodeName,
|
||||
ts.ScriptElementKind.classElement,
|
||||
getNodeModifiers(node),
|
||||
[getNodeSpan(node)],
|
||||
@@ -486,7 +482,7 @@ module ts.NavigationBar {
|
||||
}
|
||||
|
||||
function createEnumItem(node: EnumDeclaration): ts.NavigationBarItem {
|
||||
var childItems = getItemsWorker(sortNodes(removeComputedProperties(node)), createChildItem);
|
||||
let childItems = getItemsWorker(sortNodes(removeComputedProperties(node)), createChildItem);
|
||||
return getNavigationBarItem(
|
||||
node.name.text,
|
||||
ts.ScriptElementKind.enumElement,
|
||||
@@ -497,7 +493,7 @@ module ts.NavigationBar {
|
||||
}
|
||||
|
||||
function createIterfaceItem(node: InterfaceDeclaration): ts.NavigationBarItem {
|
||||
var childItems = getItemsWorker(sortNodes(removeDynamicallyNamedProperties(node)), createChildItem);
|
||||
let childItems = getItemsWorker(sortNodes(removeDynamicallyNamedProperties(node)), createChildItem);
|
||||
return getNavigationBarItem(
|
||||
node.name.text,
|
||||
ts.ScriptElementKind.interfaceElement,
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
module ts {
|
||||
export module OutliningElementsCollector {
|
||||
export function collectElements(sourceFile: SourceFile): OutliningSpan[] {
|
||||
var elements: OutliningSpan[] = [];
|
||||
var collapseText = "...";
|
||||
let elements: OutliningSpan[] = [];
|
||||
let collapseText = "...";
|
||||
|
||||
function addOutliningSpan(hintSpanNode: Node, startElement: Node, endElement: Node, autoCollapse: boolean) {
|
||||
if (hintSpanNode && startElement && endElement) {
|
||||
var span: OutliningSpan = {
|
||||
let span: OutliningSpan = {
|
||||
textSpan: createTextSpanFromBounds(startElement.pos, endElement.end),
|
||||
hintSpan: createTextSpanFromBounds(hintSpanNode.getStart(), hintSpanNode.end),
|
||||
bannerText: collapseText,
|
||||
@@ -35,8 +35,8 @@ module ts {
|
||||
return isFunctionBlock(node) && node.parent.kind !== SyntaxKind.ArrowFunction;
|
||||
}
|
||||
|
||||
var depth = 0;
|
||||
var maxDepth = 20;
|
||||
let depth = 0;
|
||||
let maxDepth = 20;
|
||||
function walk(n: Node): void {
|
||||
if (depth > maxDepth) {
|
||||
return;
|
||||
@@ -44,9 +44,9 @@ module ts {
|
||||
switch (n.kind) {
|
||||
case SyntaxKind.Block:
|
||||
if (!isFunctionBlock(n)) {
|
||||
var parent = n.parent;
|
||||
var openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile);
|
||||
var closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile);
|
||||
let parent = n.parent;
|
||||
let openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile);
|
||||
let 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
|
||||
@@ -66,13 +66,13 @@ module ts {
|
||||
|
||||
if (parent.kind === SyntaxKind.TryStatement) {
|
||||
// Could be the try-block, or the finally-block.
|
||||
var tryStatement = <TryStatement>parent;
|
||||
let tryStatement = <TryStatement>parent;
|
||||
if (tryStatement.tryBlock === n) {
|
||||
addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n));
|
||||
break;
|
||||
}
|
||||
else if (tryStatement.finallyBlock === n) {
|
||||
var finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile);
|
||||
let finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile);
|
||||
if (finallyKeyword) {
|
||||
addOutliningSpan(finallyKeyword, openBrace, closeBrace, autoCollapse(n));
|
||||
break;
|
||||
@@ -84,7 +84,7 @@ module ts {
|
||||
|
||||
// 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 = createTextSpanFromBounds(n.getStart(), n.end);
|
||||
let span = createTextSpanFromBounds(n.getStart(), n.end);
|
||||
elements.push({
|
||||
textSpan: span,
|
||||
hintSpan: span,
|
||||
@@ -95,23 +95,25 @@ module ts {
|
||||
}
|
||||
// Fallthrough.
|
||||
|
||||
case SyntaxKind.ModuleBlock:
|
||||
var openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile);
|
||||
var closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile);
|
||||
case SyntaxKind.ModuleBlock: {
|
||||
let openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile);
|
||||
let 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.ObjectLiteralExpression:
|
||||
case SyntaxKind.SwitchStatement:
|
||||
var openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile);
|
||||
var closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile);
|
||||
case SyntaxKind.CaseBlock: {
|
||||
let openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile);
|
||||
let closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile);
|
||||
addOutliningSpan(n, openBrace, closeBrace, autoCollapse(n));
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
var openBracket = findChildOfKind(n, SyntaxKind.OpenBracketToken, sourceFile);
|
||||
var closeBracket = findChildOfKind(n, SyntaxKind.CloseBracketToken, sourceFile);
|
||||
let openBracket = findChildOfKind(n, SyntaxKind.OpenBracketToken, sourceFile);
|
||||
let closeBracket = findChildOfKind(n, SyntaxKind.CloseBracketToken, sourceFile);
|
||||
addOutliningSpan(n, openBracket, closeBracket, autoCollapse(n));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -112,13 +112,13 @@ module ts {
|
||||
// we see the name of a module that is used everywhere, or the name of an overload). As
|
||||
// such, we cache the information we compute about the candidate for the life of this
|
||||
// pattern matcher so we don't have to compute it multiple times.
|
||||
var stringToWordSpans: Map<TextSpan[]> = {};
|
||||
let stringToWordSpans: Map<TextSpan[]> = {};
|
||||
|
||||
pattern = pattern.trim();
|
||||
|
||||
var fullPatternSegment = createSegment(pattern);
|
||||
var dotSeparatedSegments = pattern.split(".").map(p => createSegment(p.trim()));
|
||||
var invalidPattern = dotSeparatedSegments.length === 0 || forEach(dotSeparatedSegments, segmentIsInvalid);
|
||||
let fullPatternSegment = createSegment(pattern);
|
||||
let dotSeparatedSegments = pattern.split(".").map(p => createSegment(p.trim()));
|
||||
let invalidPattern = dotSeparatedSegments.length === 0 || forEach(dotSeparatedSegments, segmentIsInvalid);
|
||||
|
||||
return {
|
||||
getMatches,
|
||||
@@ -147,7 +147,7 @@ module ts {
|
||||
// First, check that the last part of the dot separated pattern matches the name of the
|
||||
// candidate. If not, then there's no point in proceeding and doing the more
|
||||
// expensive work.
|
||||
var candidateMatch = matchSegment(candidate, lastOrUndefined(dotSeparatedSegments));
|
||||
let candidateMatch = matchSegment(candidate, lastOrUndefined(dotSeparatedSegments));
|
||||
if (!candidateMatch) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -164,16 +164,16 @@ module ts {
|
||||
|
||||
// So far so good. Now break up the container for the candidate and check if all
|
||||
// the dotted parts match up correctly.
|
||||
var totalMatch = candidateMatch;
|
||||
let totalMatch = candidateMatch;
|
||||
|
||||
for (var i = dotSeparatedSegments.length - 2, j = candidateContainers.length - 1;
|
||||
for (let i = dotSeparatedSegments.length - 2, j = candidateContainers.length - 1;
|
||||
i >= 0;
|
||||
i--, j--) {
|
||||
|
||||
var segment = dotSeparatedSegments[i];
|
||||
var containerName = candidateContainers[j];
|
||||
let segment = dotSeparatedSegments[i];
|
||||
let containerName = candidateContainers[j];
|
||||
|
||||
var containerMatch = matchSegment(containerName, segment);
|
||||
let containerMatch = matchSegment(containerName, segment);
|
||||
if (!containerMatch) {
|
||||
// This container didn't match the pattern piece. So there's no match at all.
|
||||
return undefined;
|
||||
@@ -196,7 +196,7 @@ module ts {
|
||||
}
|
||||
|
||||
function matchTextChunk(candidate: string, chunk: TextChunk, punctuationStripped: boolean): PatternMatch {
|
||||
var index = indexOfIgnoringCase(candidate, chunk.textLowerCase);
|
||||
let index = indexOfIgnoringCase(candidate, chunk.textLowerCase);
|
||||
if (index === 0) {
|
||||
if (chunk.text.length === candidate.length) {
|
||||
// a) Check if the part matches the candidate entirely, in an case insensitive or
|
||||
@@ -210,7 +210,7 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
var isLowercase = chunk.isLowerCase;
|
||||
let isLowercase = chunk.isLowerCase;
|
||||
if (isLowercase) {
|
||||
if (index > 0) {
|
||||
// c) If the part is entirely lowercase, then check if it is contained anywhere in the
|
||||
@@ -220,9 +220,8 @@ module ts {
|
||||
// Note: We only have a substring match if the lowercase part is prefix match of some
|
||||
// word part. That way we don't match something like 'Class' when the user types 'a'.
|
||||
// But we would match 'FooAttribute' (since 'Attribute' starts with 'a').
|
||||
var wordSpans = getWordSpans(candidate);
|
||||
for (var i = 0, n = wordSpans.length; i < n; i++) {
|
||||
var span = wordSpans[i]
|
||||
let wordSpans = getWordSpans(candidate);
|
||||
for (let span of wordSpans) {
|
||||
if (partStartsWith(candidate, span, chunk.text, /*ignoreCase:*/ true)) {
|
||||
return createPatternMatch(PatternMatchKind.substring, punctuationStripped,
|
||||
/*isCaseSensitive:*/ partStartsWith(candidate, span, chunk.text, /*ignoreCase:*/ false));
|
||||
@@ -242,8 +241,8 @@ module ts {
|
||||
if (!isLowercase) {
|
||||
// e) If the part was not entirely lowercase, then attempt a camel cased match as well.
|
||||
if (chunk.characterSpans.length > 0) {
|
||||
var candidateParts = getWordSpans(candidate);
|
||||
var camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ false);
|
||||
let candidateParts = getWordSpans(candidate);
|
||||
let camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ false);
|
||||
if (camelCaseWeight !== undefined) {
|
||||
return createPatternMatch(PatternMatchKind.camelCase, punctuationStripped, /*isCaseSensitive:*/ true, /*camelCaseWeight:*/ camelCaseWeight);
|
||||
}
|
||||
@@ -274,8 +273,8 @@ module ts {
|
||||
}
|
||||
|
||||
function containsSpaceOrAsterisk(text: string): boolean {
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
var ch = text.charCodeAt(i);
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
let ch = text.charCodeAt(i);
|
||||
if (ch === CharacterCodes.space || ch === CharacterCodes.asterisk) {
|
||||
return true;
|
||||
}
|
||||
@@ -293,7 +292,7 @@ module ts {
|
||||
// Note: if the segment contains a space or an asterisk then we must assume that it's a
|
||||
// multi-word segment.
|
||||
if (!containsSpaceOrAsterisk(segment.totalTextChunk.text)) {
|
||||
var match = matchTextChunk(candidate, segment.totalTextChunk, /*punctuationStripped:*/ false);
|
||||
let match = matchTextChunk(candidate, segment.totalTextChunk, /*punctuationStripped:*/ false);
|
||||
if (match) {
|
||||
return [match];
|
||||
}
|
||||
@@ -336,14 +335,12 @@ module ts {
|
||||
//
|
||||
// Only if all words have some sort of match is the pattern considered matched.
|
||||
|
||||
var subWordTextChunks = segment.subWordTextChunks;
|
||||
var matches: PatternMatch[] = undefined;
|
||||
|
||||
for (var i = 0, n = subWordTextChunks.length; i < n; i++) {
|
||||
var subWordTextChunk = subWordTextChunks[i];
|
||||
let subWordTextChunks = segment.subWordTextChunks;
|
||||
let matches: PatternMatch[] = undefined;
|
||||
|
||||
for (let subWordTextChunk of subWordTextChunks) {
|
||||
// Try to match the candidate with this word
|
||||
var result = matchTextChunk(candidate, subWordTextChunk, /*punctuationStripped:*/ true);
|
||||
let result = matchTextChunk(candidate, subWordTextChunk, /*punctuationStripped:*/ true);
|
||||
if (!result) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -356,8 +353,8 @@ module ts {
|
||||
}
|
||||
|
||||
function partStartsWith(candidate: string, candidateSpan: TextSpan, pattern: string, ignoreCase: boolean, patternSpan?: TextSpan): boolean {
|
||||
var patternPartStart = patternSpan ? patternSpan.start : 0;
|
||||
var patternPartLength = patternSpan ? patternSpan.length : pattern.length;
|
||||
let patternPartStart = patternSpan ? patternSpan.start : 0;
|
||||
let patternPartLength = patternSpan ? patternSpan.length : pattern.length;
|
||||
|
||||
if (patternPartLength > candidateSpan.length) {
|
||||
// Pattern part is longer than the candidate part. There can never be a match.
|
||||
@@ -365,18 +362,18 @@ module ts {
|
||||
}
|
||||
|
||||
if (ignoreCase) {
|
||||
for (var i = 0; i < patternPartLength; i++) {
|
||||
var ch1 = pattern.charCodeAt(patternPartStart + i);
|
||||
var ch2 = candidate.charCodeAt(candidateSpan.start + i);
|
||||
for (let i = 0; i < patternPartLength; i++) {
|
||||
let ch1 = pattern.charCodeAt(patternPartStart + i);
|
||||
let ch2 = candidate.charCodeAt(candidateSpan.start + i);
|
||||
if (toLowerCase(ch1) !== toLowerCase(ch2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (var i = 0; i < patternPartLength; i++) {
|
||||
var ch1 = pattern.charCodeAt(patternPartStart + i);
|
||||
var ch2 = candidate.charCodeAt(candidateSpan.start + i);
|
||||
for (let i = 0; i < patternPartLength; i++) {
|
||||
let ch1 = pattern.charCodeAt(patternPartStart + i);
|
||||
let ch2 = candidate.charCodeAt(candidateSpan.start + i);
|
||||
if (ch1 !== ch2) {
|
||||
return false;
|
||||
}
|
||||
@@ -387,23 +384,23 @@ module ts {
|
||||
}
|
||||
|
||||
function tryCamelCaseMatch(candidate: string, candidateParts: TextSpan[], chunk: TextChunk, ignoreCase: boolean): number {
|
||||
var chunkCharacterSpans = chunk.characterSpans;
|
||||
let chunkCharacterSpans = chunk.characterSpans;
|
||||
|
||||
// Note: we may have more pattern parts than candidate parts. This is because multiple
|
||||
// pattern parts may match a candidate part. For example "SiUI" against "SimpleUI".
|
||||
// We'll have 3 pattern parts Si/U/I against two candidate parts Simple/UI. However, U
|
||||
// and I will both match in UI.
|
||||
|
||||
var currentCandidate = 0;
|
||||
var currentChunkSpan = 0;
|
||||
var firstMatch: number = undefined;
|
||||
var contiguous: boolean = undefined;
|
||||
let currentCandidate = 0;
|
||||
let currentChunkSpan = 0;
|
||||
let firstMatch: number = undefined;
|
||||
let contiguous: boolean = undefined;
|
||||
|
||||
while (true) {
|
||||
// Let's consider our termination cases
|
||||
if (currentChunkSpan === chunkCharacterSpans.length) {
|
||||
// We did match! We shall assign a weight to this
|
||||
var weight = 0;
|
||||
let weight = 0;
|
||||
|
||||
// Was this contiguous?
|
||||
if (contiguous) {
|
||||
@@ -422,15 +419,15 @@ module ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var candidatePart = candidateParts[currentCandidate];
|
||||
var gotOneMatchThisCandidate = false;
|
||||
let candidatePart = candidateParts[currentCandidate];
|
||||
let gotOneMatchThisCandidate = false;
|
||||
|
||||
// Consider the case of matching SiUI against SimpleUIElement. The candidate parts
|
||||
// will be Simple/UI/Element, and the pattern parts will be Si/U/I. We'll match 'Si'
|
||||
// against 'Simple' first. Then we'll match 'U' against 'UI'. However, we want to
|
||||
// still keep matching pattern parts against that candidate part.
|
||||
for (; currentChunkSpan < chunkCharacterSpans.length; currentChunkSpan++) {
|
||||
var chunkCharacterSpan = chunkCharacterSpans[currentChunkSpan];
|
||||
let chunkCharacterSpan = chunkCharacterSpans[currentChunkSpan];
|
||||
|
||||
if (gotOneMatchThisCandidate) {
|
||||
// We've already gotten one pattern part match in this candidate. We will
|
||||
@@ -540,7 +537,7 @@ module ts {
|
||||
|
||||
// TODO: find a way to determine this for any unicode characters in a
|
||||
// non-allocating manner.
|
||||
var str = String.fromCharCode(ch);
|
||||
let str = String.fromCharCode(ch);
|
||||
return str === str.toUpperCase();
|
||||
}
|
||||
|
||||
@@ -557,12 +554,12 @@ module ts {
|
||||
|
||||
// TODO: find a way to determine this for any unicode characters in a
|
||||
// non-allocating manner.
|
||||
var str = String.fromCharCode(ch);
|
||||
let str = String.fromCharCode(ch);
|
||||
return str === str.toLowerCase();
|
||||
}
|
||||
|
||||
function containsUpperCaseLetter(string: string): boolean {
|
||||
for (var i = 0, n = string.length; i < n; i++) {
|
||||
for (let i = 0, n = string.length; i < n; i++) {
|
||||
if (isUpperCaseLetter(string.charCodeAt(i))) {
|
||||
return true;
|
||||
}
|
||||
@@ -572,7 +569,7 @@ module ts {
|
||||
}
|
||||
|
||||
function startsWith(string: string, search: string) {
|
||||
for (var i = 0, n = search.length; i < n; i++) {
|
||||
for (let i = 0, n = search.length; i < n; i++) {
|
||||
if (string.charCodeAt(i) !== search.charCodeAt(i)) {
|
||||
return false;
|
||||
}
|
||||
@@ -583,7 +580,7 @@ module ts {
|
||||
|
||||
// Assumes 'value' is already lowercase.
|
||||
function indexOfIgnoringCase(string: string, value: string): number {
|
||||
for (var i = 0, n = string.length - value.length; i <= n; i++) {
|
||||
for (let i = 0, n = string.length - value.length; i <= n; i++) {
|
||||
if (startsWithIgnoringCase(string, value, i)) {
|
||||
return i;
|
||||
}
|
||||
@@ -594,9 +591,9 @@ module ts {
|
||||
|
||||
// Assumes 'value' is already lowercase.
|
||||
function startsWithIgnoringCase(string: string, value: string, start: number): boolean {
|
||||
for (var i = 0, n = value.length; i < n; i++) {
|
||||
var ch1 = toLowerCase(string.charCodeAt(i + start));
|
||||
var ch2 = value.charCodeAt(i);
|
||||
for (let i = 0, n = value.length; i < n; i++) {
|
||||
let ch1 = toLowerCase(string.charCodeAt(i + start));
|
||||
let ch2 = value.charCodeAt(i);
|
||||
|
||||
if (ch1 !== ch2) {
|
||||
return false;
|
||||
@@ -631,12 +628,12 @@ module ts {
|
||||
}
|
||||
|
||||
function breakPatternIntoTextChunks(pattern: string): TextChunk[] {
|
||||
var result: TextChunk[] = [];
|
||||
var wordStart = 0;
|
||||
var wordLength = 0;
|
||||
let result: TextChunk[] = [];
|
||||
let wordStart = 0;
|
||||
let wordLength = 0;
|
||||
|
||||
for (var i = 0; i < pattern.length; i++) {
|
||||
var ch = pattern.charCodeAt(i);
|
||||
for (let i = 0; i < pattern.length; i++) {
|
||||
let ch = pattern.charCodeAt(i);
|
||||
if (isWordChar(ch)) {
|
||||
if (wordLength++ === 0) {
|
||||
wordStart = i;
|
||||
@@ -658,7 +655,7 @@ module ts {
|
||||
}
|
||||
|
||||
function createTextChunk(text: string): TextChunk {
|
||||
var textLowerCase = text.toLowerCase();
|
||||
let textLowerCase = text.toLowerCase();
|
||||
return {
|
||||
text,
|
||||
textLowerCase,
|
||||
@@ -676,15 +673,15 @@ module ts {
|
||||
}
|
||||
|
||||
function breakIntoSpans(identifier: string, word: boolean): TextSpan[] {
|
||||
var result: TextSpan[] = [];
|
||||
let result: TextSpan[] = [];
|
||||
|
||||
var wordStart = 0;
|
||||
for (var i = 1, n = identifier.length; i < n; i++) {
|
||||
var lastIsDigit = isDigit(identifier.charCodeAt(i - 1));
|
||||
var currentIsDigit = isDigit(identifier.charCodeAt(i));
|
||||
let wordStart = 0;
|
||||
for (let i = 1, n = identifier.length; i < n; i++) {
|
||||
let lastIsDigit = isDigit(identifier.charCodeAt(i - 1));
|
||||
let currentIsDigit = isDigit(identifier.charCodeAt(i));
|
||||
|
||||
var hasTransitionFromLowerToUpper = transitionFromLowerToUpper(identifier, word, i);
|
||||
var hasTransitionFromUpperToLower = transitionFromUpperToLower(identifier, word, i, wordStart);
|
||||
let hasTransitionFromLowerToUpper = transitionFromLowerToUpper(identifier, word, i);
|
||||
let hasTransitionFromUpperToLower = transitionFromUpperToLower(identifier, word, i, wordStart);
|
||||
|
||||
if (charIsPunctuation(identifier.charCodeAt(i - 1)) ||
|
||||
charIsPunctuation(identifier.charCodeAt(i)) ||
|
||||
@@ -739,8 +736,8 @@ module ts {
|
||||
}
|
||||
|
||||
function isAllPunctuation(identifier: string, start: number, end: number): boolean {
|
||||
for (var i = start; i < end; i++) {
|
||||
var ch = identifier.charCodeAt(i);
|
||||
for (let i = start; i < end; i++) {
|
||||
let ch = identifier.charCodeAt(i);
|
||||
|
||||
// We don't consider _ or $ as punctuation as there may be things with that name.
|
||||
if (!charIsPunctuation(ch) || ch === CharacterCodes._ || ch === CharacterCodes.$) {
|
||||
@@ -761,8 +758,8 @@ module ts {
|
||||
// etc.
|
||||
if (index != wordStart &&
|
||||
index + 1 < identifier.length) {
|
||||
var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index));
|
||||
var nextIsLower = isLowerCaseLetter(identifier.charCodeAt(index + 1));
|
||||
let currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index));
|
||||
let nextIsLower = isLowerCaseLetter(identifier.charCodeAt(index + 1));
|
||||
|
||||
if (currentIsUpper && nextIsLower) {
|
||||
// We have a transition from an upper to a lower letter here. But we only
|
||||
@@ -773,7 +770,7 @@ module ts {
|
||||
// that follows. Note: this will make the following not split properly:
|
||||
// "HELLOthere". However, these sorts of names do not show up in .Net
|
||||
// programs.
|
||||
for (var i = wordStart; i < index; i++) {
|
||||
for (let i = wordStart; i < index; i++) {
|
||||
if (!isUpperCaseLetter(identifier.charCodeAt(i))) {
|
||||
return false;
|
||||
}
|
||||
@@ -788,8 +785,8 @@ module ts {
|
||||
}
|
||||
|
||||
function transitionFromLowerToUpper(identifier: string, word: boolean, index: number): boolean {
|
||||
var lastIsUpper = isUpperCaseLetter(identifier.charCodeAt(index - 1));
|
||||
var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index));
|
||||
let lastIsUpper = isUpperCaseLetter(identifier.charCodeAt(index - 1));
|
||||
let currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index));
|
||||
|
||||
// See if the casing indicates we're starting a new word. Note: if we're breaking on
|
||||
// words, then just seeing an upper case character isn't enough. Instead, it has to
|
||||
@@ -804,7 +801,7 @@ module ts {
|
||||
// on characters would be: A M
|
||||
//
|
||||
// We break the search string on characters. But we break the symbol name on words.
|
||||
var transition = word
|
||||
let transition = word
|
||||
? (currentIsUpper && !lastIsUpper)
|
||||
: currentIsUpper;
|
||||
return transition;
|
||||
|
||||
+486
-484
File diff suppressed because it is too large
Load Diff
@@ -833,3 +833,5 @@ module ts {
|
||||
module TypeScript.Services {
|
||||
export var TypeScriptServicesFactory = ts.TypeScriptServicesFactory;
|
||||
}
|
||||
|
||||
let toolsVersion = "1.4";
|
||||
|
||||
+119
-80
@@ -8,15 +8,15 @@ module ts.SignatureHelp {
|
||||
// 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);
|
||||
// let 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;
|
||||
// let stack = 0;
|
||||
// let argumentIndex = 0;
|
||||
|
||||
// whileLoop:
|
||||
// while (token) {
|
||||
@@ -24,7 +24,7 @@ module ts.SignatureHelp {
|
||||
// case TypeScript.SyntaxKind.LessThanToken:
|
||||
// if (stack === 0) {
|
||||
// // Found the beginning of the generic argument expression
|
||||
// var lessThanToken = token;
|
||||
// let lessThanToken = token;
|
||||
// token = previousToken(token, /*includeSkippedTokens*/ true);
|
||||
// if (!token || token.kind() !== TypeScript.SyntaxKind.IdentifierName) {
|
||||
// break whileLoop;
|
||||
@@ -64,7 +64,7 @@ module ts.SignatureHelp {
|
||||
|
||||
// case TypeScript.SyntaxKind.CloseBraceToken:
|
||||
// // This can be object type, skip untill we find the matching open brace token
|
||||
// var unmatchedOpenBraceTokens = 0;
|
||||
// let unmatchedOpenBraceTokens = 0;
|
||||
|
||||
// // Skip untill the matching open brace token
|
||||
// token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, TypeScript.SyntaxKind.CloseBraceToken, TypeScript.SyntaxKind.OpenBraceToken);
|
||||
@@ -135,7 +135,7 @@ module ts.SignatureHelp {
|
||||
// // Skip the current token
|
||||
// token = previousToken(token, /*includeSkippedTokens*/ true);
|
||||
|
||||
// var stack = 0;
|
||||
// let stack = 0;
|
||||
|
||||
// while (token) {
|
||||
// if (token.kind() === matchingTokenKind) {
|
||||
@@ -162,7 +162,7 @@ module ts.SignatureHelp {
|
||||
// // Did not find matching token
|
||||
// return null;
|
||||
//}
|
||||
var emptyArray: any[] = [];
|
||||
let emptyArray: any[] = [];
|
||||
|
||||
const enum ArgumentListKind {
|
||||
TypeArguments,
|
||||
@@ -180,13 +180,13 @@ module ts.SignatureHelp {
|
||||
|
||||
export function getSignatureHelpItems(sourceFile: SourceFile, position: number, typeInfoResolver: TypeChecker, cancellationToken: CancellationTokenObject): SignatureHelpItems {
|
||||
// Decide whether to show signature help
|
||||
var startingToken = findTokenOnLeftOfPosition(sourceFile, position);
|
||||
let startingToken = findTokenOnLeftOfPosition(sourceFile, position);
|
||||
if (!startingToken) {
|
||||
// We are at the beginning of the file
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var argumentInfo = getContainingArgumentInfo(startingToken);
|
||||
let argumentInfo = getContainingArgumentInfo(startingToken);
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
// Semantic filtering of signature help
|
||||
@@ -194,9 +194,9 @@ module ts.SignatureHelp {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var call = argumentInfo.invocation;
|
||||
var candidates = <Signature[]>[];
|
||||
var resolvedSignature = typeInfoResolver.getResolvedSignature(call, candidates);
|
||||
let call = argumentInfo.invocation;
|
||||
let candidates = <Signature[]>[];
|
||||
let resolvedSignature = typeInfoResolver.getResolvedSignature(call, candidates);
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
if (!candidates.length) {
|
||||
@@ -211,7 +211,7 @@ module ts.SignatureHelp {
|
||||
*/
|
||||
function getImmediatelyContainingArgumentInfo(node: Node): ArgumentListInfo {
|
||||
if (node.parent.kind === SyntaxKind.CallExpression || node.parent.kind === SyntaxKind.NewExpression) {
|
||||
var callExpression = <CallExpression>node.parent;
|
||||
let callExpression = <CallExpression>node.parent;
|
||||
// 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
|
||||
@@ -230,15 +230,15 @@ module ts.SignatureHelp {
|
||||
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(callExpression, node, sourceFile);
|
||||
var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
|
||||
let list = getChildListThatStartsWithOpenerToken(callExpression, node, sourceFile);
|
||||
let isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
|
||||
Debug.assert(list !== undefined);
|
||||
return {
|
||||
kind: isTypeArgList ? ArgumentListKind.TypeArguments : ArgumentListKind.CallArguments,
|
||||
invocation: callExpression,
|
||||
argumentsSpan: getApplicableSpanForArguments(list),
|
||||
argumentIndex: 0,
|
||||
argumentCount: getCommaBasedArgCount(list)
|
||||
argumentCount: getArgumentCount(list)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -248,28 +248,23 @@ module ts.SignatureHelp {
|
||||
// - Between the type arguments and the arguments (greater than token)
|
||||
// - On the target of the call (parent.func)
|
||||
// - On the 'new' keyword in a 'new' expression
|
||||
var listItemInfo = findListItemInfo(node);
|
||||
let listItemInfo = findListItemInfo(node);
|
||||
if (listItemInfo) {
|
||||
var list = listItemInfo.list;
|
||||
var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
|
||||
let list = listItemInfo.list;
|
||||
let isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
|
||||
|
||||
// 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 = (listItemInfo.listItemIndex + 1) >> 1;
|
||||
let argumentIndex = getArgumentIndex(list, node);
|
||||
let argumentCount = getArgumentCount(list);
|
||||
|
||||
Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount,
|
||||
`argumentCount < argumentIndex, ${argumentCount} < ${argumentIndex}`);
|
||||
|
||||
return {
|
||||
kind: isTypeArgList ? ArgumentListKind.TypeArguments : ArgumentListKind.CallArguments,
|
||||
invocation: callExpression,
|
||||
argumentsSpan: getApplicableSpanForArguments(list),
|
||||
argumentIndex: argumentIndex,
|
||||
argumentCount: getCommaBasedArgCount(list)
|
||||
argumentCount: argumentCount
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -281,18 +276,18 @@ module ts.SignatureHelp {
|
||||
}
|
||||
}
|
||||
else if (node.kind === SyntaxKind.TemplateHead && node.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) {
|
||||
var templateExpression = <TemplateExpression>node.parent;
|
||||
var tagExpression = <TaggedTemplateExpression>templateExpression.parent;
|
||||
let templateExpression = <TemplateExpression>node.parent;
|
||||
let tagExpression = <TaggedTemplateExpression>templateExpression.parent;
|
||||
Debug.assert(templateExpression.kind === SyntaxKind.TemplateExpression);
|
||||
|
||||
var argumentIndex = isInsideTemplateLiteral(<LiteralExpression>node, position) ? 0 : 1;
|
||||
let argumentIndex = isInsideTemplateLiteral(<LiteralExpression>node, position) ? 0 : 1;
|
||||
|
||||
return getArgumentListInfoForTemplate(tagExpression, argumentIndex);
|
||||
}
|
||||
else if (node.parent.kind === SyntaxKind.TemplateSpan && node.parent.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) {
|
||||
var templateSpan = <TemplateSpan>node.parent;
|
||||
var templateExpression = <TemplateExpression>templateSpan.parent;
|
||||
var tagExpression = <TaggedTemplateExpression>templateExpression.parent;
|
||||
let templateSpan = <TemplateSpan>node.parent;
|
||||
let templateExpression = <TemplateExpression>templateSpan.parent;
|
||||
let tagExpression = <TaggedTemplateExpression>templateExpression.parent;
|
||||
Debug.assert(templateExpression.kind === SyntaxKind.TemplateExpression);
|
||||
|
||||
// If we're just after a template tail, don't show signature help.
|
||||
@@ -300,8 +295,8 @@ module ts.SignatureHelp {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var spanIndex = templateExpression.templateSpans.indexOf(templateSpan);
|
||||
var argumentIndex = getArgumentIndexForTemplatePiece(spanIndex, node);
|
||||
let spanIndex = templateExpression.templateSpans.indexOf(templateSpan);
|
||||
let argumentIndex = getArgumentIndexForTemplatePiece(spanIndex, node);
|
||||
|
||||
return getArgumentListInfoForTemplate(tagExpression, argumentIndex);
|
||||
}
|
||||
@@ -309,12 +304,52 @@ module ts.SignatureHelp {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getCommaBasedArgCount(argumentsList: Node) {
|
||||
// The number of arguments is the number of commas plus one, unless the list
|
||||
// is completely empty, in which case there are 0 arguments.
|
||||
return argumentsList.getChildCount() === 0
|
||||
? 0
|
||||
: 1 + countWhere(argumentsList.getChildren(), arg => arg.kind === SyntaxKind.CommaToken);
|
||||
function getArgumentIndex(argumentsList: Node, node: Node) {
|
||||
// The list we got back can include commas. In the presence of errors it may
|
||||
// also just have nodes without commas. For example "Foo(a b c)" will have 3
|
||||
// args without commas. We want to find what index we're at. So we count
|
||||
// forward until we hit ourselves, only incrementing the index if it isn't a
|
||||
// comma.
|
||||
//
|
||||
// Note: the subtlety around trailing commas (in getArgumentCount) does not apply
|
||||
// here. That's because we're only walking forward until we hit the node we're
|
||||
// on. In that case, even if we're after the trailing comma, we'll still see
|
||||
// that trailing comma in the list, and we'll have generated the appropriate
|
||||
// arg index.
|
||||
let argumentIndex = 0;
|
||||
let listChildren = argumentsList.getChildren();
|
||||
for (let child of listChildren) {
|
||||
if (child === node) {
|
||||
break;
|
||||
}
|
||||
if (child.kind !== SyntaxKind.CommaToken) {
|
||||
argumentIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
return argumentIndex;
|
||||
}
|
||||
|
||||
function getArgumentCount(argumentsList: Node) {
|
||||
// The argument count for a list is normally the number of non-comma children it has.
|
||||
// For example, if you have "Foo(a,b)" then there will be three children of the arg
|
||||
// list 'a' '<comma>' 'b'. So, in this case the arg count will be 2. However, there
|
||||
// is a small subtlety. If you have "Foo(a,)", then the child list will just have
|
||||
// 'a' '<comma>'. So, in the case where the last child is a comma, we increase the
|
||||
// arg count by one to compensate.
|
||||
//
|
||||
// Note: this subtlety only applies to the last comma. If you had "Foo(a,," then
|
||||
// we'll have: 'a' '<comma>' '<missing>'
|
||||
// That will give us 2 non-commas. We then add one for the last comma, givin us an
|
||||
// arg count of 3.
|
||||
let listChildren = argumentsList.getChildren();
|
||||
|
||||
let argumentCount = countWhere(listChildren, arg => arg.kind !== SyntaxKind.CommaToken);
|
||||
if (listChildren.length > 0 && lastOrUndefined(listChildren).kind === SyntaxKind.CommaToken) {
|
||||
argumentCount++;
|
||||
}
|
||||
|
||||
return argumentCount;
|
||||
}
|
||||
|
||||
// spanIndex is either the index for a given template span.
|
||||
@@ -343,10 +378,12 @@ module ts.SignatureHelp {
|
||||
|
||||
function getArgumentListInfoForTemplate(tagExpression: TaggedTemplateExpression, argumentIndex: number): ArgumentListInfo {
|
||||
// argumentCount is either 1 or (numSpans + 1) to account for the template strings array argument.
|
||||
var argumentCount = tagExpression.template.kind === SyntaxKind.NoSubstitutionTemplateLiteral
|
||||
let argumentCount = tagExpression.template.kind === SyntaxKind.NoSubstitutionTemplateLiteral
|
||||
? 1
|
||||
: (<TemplateExpression>tagExpression.template).templateSpans.length + 1;
|
||||
|
||||
Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, `argumentCount < argumentIndex, ${argumentCount} < ${argumentIndex}`);
|
||||
|
||||
return {
|
||||
kind: ArgumentListKind.TaggedTemplateArguments,
|
||||
invocation: tagExpression,
|
||||
@@ -365,15 +402,15 @@ module ts.SignatureHelp {
|
||||
//
|
||||
// The applicable span is from the first bar to the second bar (inclusive,
|
||||
// but not including parentheses)
|
||||
var applicableSpanStart = argumentsList.getFullStart();
|
||||
var applicableSpanEnd = skipTrivia(sourceFile.text, argumentsList.getEnd(), /*stopAfterLineBreak*/ false);
|
||||
let applicableSpanStart = argumentsList.getFullStart();
|
||||
let applicableSpanEnd = skipTrivia(sourceFile.text, argumentsList.getEnd(), /*stopAfterLineBreak*/ false);
|
||||
return createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
|
||||
}
|
||||
|
||||
function getApplicableSpanForTaggedTemplate(taggedTemplate: TaggedTemplateExpression): TextSpan {
|
||||
var template = taggedTemplate.template;
|
||||
var applicableSpanStart = template.getStart();
|
||||
var applicableSpanEnd = template.getEnd();
|
||||
let template = taggedTemplate.template;
|
||||
let applicableSpanStart = template.getStart();
|
||||
let applicableSpanEnd = template.getEnd();
|
||||
|
||||
// We need to adjust the end position for the case where the template does not have a tail.
|
||||
// Otherwise, we will not show signature help past the expression.
|
||||
@@ -385,7 +422,7 @@ module ts.SignatureHelp {
|
||||
// This is because a Missing node has no width. However, what we actually want is to include trivia
|
||||
// leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail.
|
||||
if (template.kind === SyntaxKind.TemplateExpression) {
|
||||
var lastSpan = lastOrUndefined((<TemplateExpression>template).templateSpans);
|
||||
let lastSpan = lastOrUndefined((<TemplateExpression>template).templateSpans);
|
||||
if (lastSpan.literal.getFullWidth() === 0) {
|
||||
applicableSpanEnd = skipTrivia(sourceFile.text, applicableSpanEnd, /*stopAfterLineBreak*/ false);
|
||||
}
|
||||
@@ -395,7 +432,7 @@ module ts.SignatureHelp {
|
||||
}
|
||||
|
||||
function getContainingArgumentInfo(node: Node): ArgumentListInfo {
|
||||
for (var n = node; n.kind !== SyntaxKind.SourceFile; n = n.parent) {
|
||||
for (let n = node; n.kind !== SyntaxKind.SourceFile; n = n.parent) {
|
||||
if (isFunctionBlock(n)) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -406,7 +443,7 @@ module ts.SignatureHelp {
|
||||
Debug.fail("Node of kind " + n.kind + " is not a subspan of its parent of kind " + n.parent.kind);
|
||||
}
|
||||
|
||||
var argumentInfo = getImmediatelyContainingArgumentInfo(n);
|
||||
let argumentInfo = getImmediatelyContainingArgumentInfo(n);
|
||||
if (argumentInfo) {
|
||||
return argumentInfo;
|
||||
}
|
||||
@@ -418,8 +455,8 @@ module ts.SignatureHelp {
|
||||
}
|
||||
|
||||
function getChildListThatStartsWithOpenerToken(parent: Node, openerToken: Node, sourceFile: SourceFile): Node {
|
||||
var children = parent.getChildren(sourceFile);
|
||||
var indexOfOpenerToken = children.indexOf(openerToken);
|
||||
let children = parent.getChildren(sourceFile);
|
||||
let indexOfOpenerToken = children.indexOf(openerToken);
|
||||
Debug.assert(indexOfOpenerToken >= 0 && children.length > indexOfOpenerToken + 1);
|
||||
return children[indexOfOpenerToken + 1];
|
||||
}
|
||||
@@ -433,10 +470,10 @@ module ts.SignatureHelp {
|
||||
* 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];
|
||||
let maxParamsSignatureIndex = -1;
|
||||
let maxParams = -1;
|
||||
for (let i = 0; i < candidates.length; i++) {
|
||||
let candidate = candidates[i];
|
||||
|
||||
if (candidate.hasRestParameter || candidate.parameters.length >= argumentCount) {
|
||||
return i;
|
||||
@@ -452,17 +489,17 @@ module ts.SignatureHelp {
|
||||
}
|
||||
|
||||
function createSignatureHelpItems(candidates: Signature[], bestSignature: Signature, argumentListInfo: ArgumentListInfo): SignatureHelpItems {
|
||||
var applicableSpan = argumentListInfo.argumentsSpan;
|
||||
var isTypeParameterList = argumentListInfo.kind === ArgumentListKind.TypeArguments;
|
||||
let applicableSpan = argumentListInfo.argumentsSpan;
|
||||
let isTypeParameterList = argumentListInfo.kind === ArgumentListKind.TypeArguments;
|
||||
|
||||
var invocation = argumentListInfo.invocation;
|
||||
var callTarget = getInvokedExpression(invocation)
|
||||
var callTargetSymbol = typeInfoResolver.getSymbolAtLocation(callTarget);
|
||||
var callTargetDisplayParts = callTargetSymbol && symbolToDisplayParts(typeInfoResolver, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined);
|
||||
var items: SignatureHelpItem[] = map(candidates, candidateSignature => {
|
||||
var signatureHelpParameters: SignatureHelpParameter[];
|
||||
var prefixDisplayParts: SymbolDisplayPart[] = [];
|
||||
var suffixDisplayParts: SymbolDisplayPart[] = [];
|
||||
let invocation = argumentListInfo.invocation;
|
||||
let callTarget = getInvokedExpression(invocation)
|
||||
let callTargetSymbol = typeInfoResolver.getSymbolAtLocation(callTarget);
|
||||
let callTargetDisplayParts = callTargetSymbol && symbolToDisplayParts(typeInfoResolver, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined);
|
||||
let items: SignatureHelpItem[] = map(candidates, candidateSignature => {
|
||||
let signatureHelpParameters: SignatureHelpParameter[];
|
||||
let prefixDisplayParts: SymbolDisplayPart[] = [];
|
||||
let suffixDisplayParts: SymbolDisplayPart[] = [];
|
||||
|
||||
if (callTargetDisplayParts) {
|
||||
prefixDisplayParts.push.apply(prefixDisplayParts, callTargetDisplayParts);
|
||||
@@ -470,25 +507,25 @@ module ts.SignatureHelp {
|
||||
|
||||
if (isTypeParameterList) {
|
||||
prefixDisplayParts.push(punctuationPart(SyntaxKind.LessThanToken));
|
||||
var typeParameters = candidateSignature.typeParameters;
|
||||
let typeParameters = candidateSignature.typeParameters;
|
||||
signatureHelpParameters = typeParameters && typeParameters.length > 0 ? map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray;
|
||||
suffixDisplayParts.push(punctuationPart(SyntaxKind.GreaterThanToken));
|
||||
var parameterParts = mapToDisplayParts(writer =>
|
||||
let parameterParts = mapToDisplayParts(writer =>
|
||||
typeInfoResolver.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.parameters, writer, invocation));
|
||||
suffixDisplayParts.push.apply(suffixDisplayParts, parameterParts);
|
||||
}
|
||||
else {
|
||||
var typeParameterParts = mapToDisplayParts(writer =>
|
||||
let typeParameterParts = mapToDisplayParts(writer =>
|
||||
typeInfoResolver.getSymbolDisplayBuilder().buildDisplayForTypeParametersAndDelimiters(candidateSignature.typeParameters, writer, invocation));
|
||||
prefixDisplayParts.push.apply(prefixDisplayParts, typeParameterParts);
|
||||
prefixDisplayParts.push(punctuationPart(SyntaxKind.OpenParenToken));
|
||||
|
||||
var parameters = candidateSignature.parameters;
|
||||
let parameters = candidateSignature.parameters;
|
||||
signatureHelpParameters = parameters.length > 0 ? map(parameters, createSignatureHelpParameterForParameter) : emptyArray;
|
||||
suffixDisplayParts.push(punctuationPart(SyntaxKind.CloseParenToken));
|
||||
}
|
||||
|
||||
var returnTypeParts = mapToDisplayParts(writer =>
|
||||
let returnTypeParts = mapToDisplayParts(writer =>
|
||||
typeInfoResolver.getSymbolDisplayBuilder().buildReturnTypeDisplay(candidateSignature, writer, invocation));
|
||||
suffixDisplayParts.push.apply(suffixDisplayParts, returnTypeParts);
|
||||
|
||||
@@ -502,16 +539,18 @@ module ts.SignatureHelp {
|
||||
};
|
||||
});
|
||||
|
||||
var argumentIndex = argumentListInfo.argumentIndex;
|
||||
let argumentIndex = argumentListInfo.argumentIndex;
|
||||
|
||||
// argumentCount is the *apparent* number of arguments.
|
||||
var argumentCount = argumentListInfo.argumentCount;
|
||||
let argumentCount = argumentListInfo.argumentCount;
|
||||
|
||||
var selectedItemIndex = candidates.indexOf(bestSignature);
|
||||
let selectedItemIndex = candidates.indexOf(bestSignature);
|
||||
if (selectedItemIndex < 0) {
|
||||
selectedItemIndex = selectBestInvalidOverloadIndex(candidates, argumentCount);
|
||||
}
|
||||
|
||||
Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, `argumentCount < argumentIndex, ${argumentCount} < ${argumentIndex}`);
|
||||
|
||||
return {
|
||||
items,
|
||||
applicableSpan,
|
||||
@@ -521,10 +560,10 @@ module ts.SignatureHelp {
|
||||
};
|
||||
|
||||
function createSignatureHelpParameterForParameter(parameter: Symbol): SignatureHelpParameter {
|
||||
var displayParts = mapToDisplayParts(writer =>
|
||||
let displayParts = mapToDisplayParts(writer =>
|
||||
typeInfoResolver.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, invocation));
|
||||
|
||||
var isOptional = hasQuestionToken(parameter.valueDeclaration);
|
||||
let isOptional = hasQuestionToken(parameter.valueDeclaration);
|
||||
|
||||
return {
|
||||
name: parameter.name,
|
||||
@@ -535,7 +574,7 @@ module ts.SignatureHelp {
|
||||
}
|
||||
|
||||
function createSignatureHelpParameterForTypeParameter(typeParameter: TypeParameter): SignatureHelpParameter {
|
||||
var displayParts = mapToDisplayParts(writer =>
|
||||
let displayParts = mapToDisplayParts(writer =>
|
||||
typeInfoResolver.getSymbolDisplayBuilder().buildTypeParameterDisplay(typeParameter, writer, invocation));
|
||||
|
||||
return {
|
||||
|
||||
+48
-43
@@ -7,18 +7,18 @@ module ts {
|
||||
|
||||
export function getEndLinePosition(line: number, sourceFile: SourceFile): number {
|
||||
Debug.assert(line >= 0);
|
||||
var lineStarts = sourceFile.getLineStarts();
|
||||
let lineStarts = sourceFile.getLineStarts();
|
||||
|
||||
var lineIndex = line;
|
||||
let lineIndex = line;
|
||||
if (lineIndex + 1 === lineStarts.length) {
|
||||
// last line - return EOF
|
||||
return sourceFile.text.length - 1;
|
||||
}
|
||||
else {
|
||||
// current line start
|
||||
var start = lineStarts[lineIndex];
|
||||
let start = lineStarts[lineIndex];
|
||||
// take the start position of the next line -1 = it should be some line break
|
||||
var pos = lineStarts[lineIndex + 1] - 1;
|
||||
let pos = lineStarts[lineIndex + 1] - 1;
|
||||
Debug.assert(isLineBreak(sourceFile.text.charCodeAt(pos)));
|
||||
// walk backwards skipping line breaks, stop the the beginning of current line.
|
||||
// i.e:
|
||||
@@ -32,8 +32,8 @@ module ts {
|
||||
}
|
||||
|
||||
export function getLineStartPositionForPosition(position: number, sourceFile: SourceFile): number {
|
||||
var lineStarts = sourceFile.getLineStarts();
|
||||
var line = sourceFile.getLineAndCharacterOfPosition(position).line;
|
||||
let lineStarts = sourceFile.getLineStarts();
|
||||
let line = sourceFile.getLineAndCharacterOfPosition(position).line;
|
||||
return lineStarts[line];
|
||||
}
|
||||
|
||||
@@ -54,13 +54,13 @@ module ts {
|
||||
}
|
||||
|
||||
export function startEndOverlapsWithStartEnd(start1: number, end1: number, start2: number, end2: number) {
|
||||
var start = Math.max(start1, start2);
|
||||
var end = Math.min(end1, end2);
|
||||
let start = Math.max(start1, start2);
|
||||
let end = Math.min(end1, end2);
|
||||
return start < end;
|
||||
}
|
||||
|
||||
export function findListItemInfo(node: Node): ListItemInfo {
|
||||
var list = findContainingList(node);
|
||||
let list = findContainingList(node);
|
||||
|
||||
// It is possible at this point for syntaxList to be undefined, either if
|
||||
// node.parent had no list child, or if none of its list children contained
|
||||
@@ -70,8 +70,8 @@ module ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var children = list.getChildren();
|
||||
var listItemIndex = indexOf(children, node);
|
||||
let children = list.getChildren();
|
||||
let listItemIndex = indexOf(children, node);
|
||||
|
||||
return {
|
||||
listItemIndex,
|
||||
@@ -79,6 +79,10 @@ module ts {
|
||||
};
|
||||
}
|
||||
|
||||
export function hasChildOfKind(n: Node, kind: SyntaxKind, sourceFile?: SourceFile): boolean {
|
||||
return !!findChildOfKind(n, kind, sourceFile);
|
||||
}
|
||||
|
||||
export function findChildOfKind(n: Node, kind: SyntaxKind, sourceFile?: SourceFile): Node {
|
||||
return forEach(n.getChildren(sourceFile), c => c.kind === kind && c);
|
||||
}
|
||||
@@ -88,13 +92,15 @@ module ts {
|
||||
// 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 => {
|
||||
let 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;
|
||||
}
|
||||
});
|
||||
|
||||
// Either we didn't find an appropriate list, or the list must contain us.
|
||||
Debug.assert(!syntaxList || contains(syntaxList.getChildren(), node));
|
||||
return syntaxList;
|
||||
}
|
||||
|
||||
@@ -124,7 +130,7 @@ module ts {
|
||||
|
||||
/** 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;
|
||||
let current: Node = sourceFile;
|
||||
outer: while (true) {
|
||||
if (isToken(current)) {
|
||||
// exit early
|
||||
@@ -132,17 +138,17 @@ module ts {
|
||||
}
|
||||
|
||||
// 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);
|
||||
for (let i = 0, n = current.getChildCount(sourceFile); i < n; i++) {
|
||||
let child = current.getChildAt(i);
|
||||
let start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile);
|
||||
if (start <= position) {
|
||||
var end = child.getEnd();
|
||||
let end = child.getEnd();
|
||||
if (position < end || (position === end && child.kind === SyntaxKind.EndOfFileToken)) {
|
||||
current = child;
|
||||
continue outer;
|
||||
}
|
||||
else if (includeItemAtEndPosition && end === position) {
|
||||
var previousToken = findPrecedingToken(position, sourceFile, child);
|
||||
let previousToken = findPrecedingToken(position, sourceFile, child);
|
||||
if (previousToken && includeItemAtEndPosition(previousToken)) {
|
||||
return previousToken;
|
||||
}
|
||||
@@ -164,7 +170,7 @@ module ts {
|
||||
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);
|
||||
let tokenAtPosition = getTokenAtPosition(file, position);
|
||||
if (isToken(tokenAtPosition) && position > tokenAtPosition.getStart(file) && position < tokenAtPosition.getEnd()) {
|
||||
return tokenAtPosition;
|
||||
}
|
||||
@@ -181,10 +187,9 @@ module ts {
|
||||
return n;
|
||||
}
|
||||
|
||||
var children = n.getChildren();
|
||||
for (var i = 0, len = children.length; i < len; ++i) {
|
||||
var child = children[i];
|
||||
var shouldDiveInChildNode =
|
||||
let children = n.getChildren();
|
||||
for (let child of children) {
|
||||
let 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
|
||||
@@ -207,8 +212,8 @@ module ts {
|
||||
return n;
|
||||
}
|
||||
|
||||
var children = n.getChildren();
|
||||
var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length);
|
||||
let children = n.getChildren();
|
||||
let candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length);
|
||||
return candidate && findRightmostToken(candidate);
|
||||
|
||||
}
|
||||
@@ -218,14 +223,14 @@ module ts {
|
||||
return n;
|
||||
}
|
||||
|
||||
var children = n.getChildren();
|
||||
for (var i = 0, len = children.length; i < len; ++i) {
|
||||
var child = children[i];
|
||||
let children = n.getChildren();
|
||||
for (let i = 0, len = children.length; i < len; i++) {
|
||||
let 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);
|
||||
let candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i);
|
||||
return candidate && findRightmostToken(candidate)
|
||||
}
|
||||
else {
|
||||
@@ -243,14 +248,14 @@ module ts {
|
||||
// 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);
|
||||
let 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) {
|
||||
for (let i = exclusiveStartPosition - 1; i >= 0; --i) {
|
||||
if (nodeHasTokens(children[i])) {
|
||||
return children[i];
|
||||
}
|
||||
@@ -265,8 +270,8 @@ module ts {
|
||||
}
|
||||
|
||||
export function getNodeModifiers(node: Node): string {
|
||||
var flags = getCombinedNodeFlags(node);
|
||||
var result: string[] = [];
|
||||
let flags = getCombinedNodeFlags(node);
|
||||
let result: string[] = [];
|
||||
|
||||
if (flags & NodeFlags.Private) result.push(ScriptElementKindModifier.privateMemberModifier);
|
||||
if (flags & NodeFlags.Protected) result.push(ScriptElementKindModifier.protectedMemberModifier);
|
||||
@@ -283,7 +288,7 @@ module ts {
|
||||
return (<CallExpression>node).typeArguments;
|
||||
}
|
||||
|
||||
if (isAnyFunction(node) || node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.InterfaceDeclaration) {
|
||||
if (isFunctionLike(node) || node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.InterfaceDeclaration) {
|
||||
return (<FunctionLikeDeclaration>node).typeParameters;
|
||||
}
|
||||
|
||||
@@ -316,7 +321,7 @@ module ts {
|
||||
}
|
||||
|
||||
export function compareDataObjects(dst: any, src: any): boolean {
|
||||
for (var e in dst) {
|
||||
for (let e in dst) {
|
||||
if (typeof dst[e] === "object") {
|
||||
if (!compareDataObjects(dst[e], src[e])) {
|
||||
return false;
|
||||
@@ -338,11 +343,11 @@ module ts {
|
||||
return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === SyntaxKind.Parameter;
|
||||
}
|
||||
|
||||
var displayPartWriter = getDisplayPartWriter();
|
||||
let displayPartWriter = getDisplayPartWriter();
|
||||
function getDisplayPartWriter(): DisplayPartsSymbolWriter {
|
||||
var displayParts: SymbolDisplayPart[];
|
||||
var lineStart: boolean;
|
||||
var indent: number;
|
||||
let displayParts: SymbolDisplayPart[];
|
||||
let lineStart: boolean;
|
||||
let indent: number;
|
||||
|
||||
resetWriter();
|
||||
return {
|
||||
@@ -363,7 +368,7 @@ module ts {
|
||||
|
||||
function writeIndent() {
|
||||
if (lineStart) {
|
||||
var indentString = getIndentString(indent);
|
||||
let indentString = getIndentString(indent);
|
||||
if (indentString) {
|
||||
displayParts.push(displayPart(indentString, SymbolDisplayPartKind.space));
|
||||
}
|
||||
@@ -397,7 +402,7 @@ module ts {
|
||||
return displayPart(text, displayPartKind(symbol), symbol);
|
||||
|
||||
function displayPartKind(symbol: Symbol): SymbolDisplayPartKind {
|
||||
var flags = symbol.flags;
|
||||
let flags = symbol.flags;
|
||||
|
||||
if (flags & SymbolFlags.Variable) {
|
||||
return isFirstDeclarationOfSymbolParameter(symbol) ? SymbolDisplayPartKind.parameterName : SymbolDisplayPartKind.localName;
|
||||
@@ -414,7 +419,7 @@ module ts {
|
||||
else if (flags & SymbolFlags.Method) { return SymbolDisplayPartKind.methodName; }
|
||||
else if (flags & SymbolFlags.TypeParameter) { return SymbolDisplayPartKind.typeParameterName; }
|
||||
else if (flags & SymbolFlags.TypeAlias) { return SymbolDisplayPartKind.aliasName; }
|
||||
else if (flags & SymbolFlags.Import) { return SymbolDisplayPartKind.aliasName; }
|
||||
else if (flags & SymbolFlags.Alias) { return SymbolDisplayPartKind.aliasName; }
|
||||
|
||||
|
||||
return SymbolDisplayPartKind.text;
|
||||
@@ -454,7 +459,7 @@ module ts {
|
||||
|
||||
export function mapToDisplayParts(writeDisplayParts: (writer: DisplayPartsSymbolWriter) => void): SymbolDisplayPart[] {
|
||||
writeDisplayParts(displayPartWriter);
|
||||
var result = displayPartWriter.displayParts();
|
||||
let result = displayPartWriter.displayParts();
|
||||
displayPartWriter.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user