diff --git a/.gitignore b/.gitignore
index 11cfefed5f2..a05a65c95c1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,4 +36,5 @@ tests/*.d.ts
*.config
scripts/debug.bat
scripts/run.bat
+scripts/word2md.js
coverage/
diff --git a/Jakefile b/Jakefile
index 04049837f6e..db8d670b0bf 100644
--- a/Jakefile
+++ b/Jakefile
@@ -2,6 +2,7 @@
var fs = require("fs");
var path = require("path");
+var child_process = require("child_process");
// Variables
var compilerDirectory = "src/compiler/";
@@ -9,6 +10,7 @@ var servicesDirectory = "src/services/";
var harnessDirectory = "src/harness/";
var libraryDirectory = "src/lib/";
var scriptsDirectory = "scripts/";
+var docDirectory = "doc/";
var builtDirectory = "built/";
var builtLocalDirectory = "built/local/";
@@ -260,6 +262,38 @@ task("clean", function() {
jake.rmRf(builtDirectory);
});
+// Generate Markdown spec
+var word2mdJs = path.join(scriptsDirectory, "word2md.js");
+var word2mdTs = path.join(scriptsDirectory, "word2md.ts");
+var specWord = path.join(docDirectory, "TypeScript Language Specification.docx");
+var specMd = path.join(docDirectory, "spec.md");
+var headerMd = path.join(docDirectory, "header.md");
+
+file(word2mdTs);
+
+// word2md script
+compileFile(word2mdJs,
+ [word2mdTs],
+ [word2mdTs],
+ [],
+ false);
+
+// The generated spec.md; built for the 'generate-spec' task
+file(specMd, [word2mdJs, specWord], function () {
+ jake.cpR(headerMd, specMd, {silent: true});
+ var specWordFullPath = path.resolve(specWord);
+ var cmd = "cscript //nologo " + word2mdJs + ' "' + specWordFullPath + '" >>' + specMd;
+ console.log(cmd);
+ child_process.exec(cmd, function () {
+ complete();
+ });
+}, {async: true})
+
+
+desc("Generates a Markdown version of the Language Specification");
+task("generate-spec", [specMd])
+
+
// Makes a new LKG. This target does not build anything, but errors if not all the outputs are present in the built/local directory
desc("Makes a new LKG out of the built js files");
task("LKG", libraryTargets, function() {
diff --git a/doc/TypeScript Language Specification.docx b/doc/TypeScript Language Specification.docx
index 403daa64ad1..d3a189853c5 100644
Binary files a/doc/TypeScript Language Specification.docx and b/doc/TypeScript Language Specification.docx differ
diff --git a/doc/spec.md b/doc/spec.md
index 50f4c07fb00..aff7e06f469 100644
--- a/doc/spec.md
+++ b/doc/spec.md
@@ -102,9 +102,9 @@ TypeScript is a trademark of Microsoft Corporation.
* [4.14.5 The void Operator](#4.14.5)
* [4.14.6 The typeof Operator](#4.14.6)
* [4.15 Binary Operators](#4.15)
- * [4.15.1 The *, /, %, –, <<, >>, >>>, &, ^, and | operators](#4.15.1)
+ * [4.15.1 The *, /, %, –, <<, >>, >>>, &, ^, and | operators](#4.15.1)
* [4.15.2 The + operator](#4.15.2)
- * [4.15.3 The <, >, <=, >=, ==, !=, ===, and !== operators](#4.15.3)
+ * [4.15.3 The <, >, <=, >=, ==, !=, ===, and !== operators](#4.15.3)
* [4.15.4 The instanceof operator](#4.15.4)
* [4.15.5 The in operator](#4.15.5)
* [4.15.6 The && operator](#4.15.6)
@@ -1088,7 +1088,7 @@ Since a type parameter represents a multitude of different type arguments, type
### 3.4.1 Type Parameter Lists
-Class, interface, and function declarations may optionally include lists of type parameters enclosed in < and > brackets. Type parameters are also permitted in call signatures of object, function, and constructor type literals.
+Class, interface, and function declarations may optionally include lists of type parameters enclosed in < and > brackets. Type parameters are also permitted in call signatures of object, function, and constructor type literals.
*TypeParameters:*
`<` *TypeParameterList* `>`
@@ -1149,7 +1149,7 @@ Given the declaration
interface G { }
```
-a type reference of the form ‘G’ places no requirements on ‘A’ but requires ‘B’ to be assignable to ‘Function’.
+a type reference of the form ‘G<A, B>’ places no requirements on ‘A’ but requires ‘B’ to be assignable to ‘Function’.
The process of substituting type arguments for type parameters in a generic type or generic signature is known as ***instantiating*** the generic type or signature. Instantiation of a generic type or signature can fail if the supplied type arguments do not satisfy the constraints of their corresponding type parameters.
@@ -1354,13 +1354,13 @@ Object type literals are the primary form of type literals and are described in
As the table above illustrates, an array type literal is shorthand for a reference to the generic interface type ‘Array’ in the global module, a function type literal is shorthand for an object type containing a single call signature, and a constructor type literal is shorthand for an object type containing a single construct signature. Note that function and constructor types with multiple call or construct signatures cannot be written as function or constructor type literals but must instead be written as object type literals.
-In order to avoid grammar ambiguities, array type literals permit only a restricted set of notations for the element type. Specifically, an A*rrayType* cannot start with a *FunctionType* or *ConstructorType*. To use one of those forms for the element type, an array type must be written using the ‘Array’ notation. For example, the type
+In order to avoid grammar ambiguities, array type literals permit only a restricted set of notations for the element type. Specifically, an *ArrayType* cannot start with a *FunctionType* or *ConstructorType*. To use one of those forms for the element type, an array type must be written using the ‘Array<T>’ notation. For example, the type
```TypeScript
() => string[]
```
-denotes a function returning a string array, not an array of functions returning string. The latter can be expressed using ‘Array’ notation
+denotes a function returning a string array, not an array of functions returning string. The latter can be expressed using ‘Array<T>’ notation
```TypeScript
Array<() => string>
@@ -1833,7 +1833,7 @@ interface List {
}
```
-‘List’ has a member ‘owner’ of type ‘List>’, which has a member ‘owner’ of type ‘List>>’, which has a member ‘owner’ of type ‘List>>>’ and so on, ad infinitum. Since type relationships are determined structurally, possibly exploring the constituent types to their full depth, in order to determine type relationships involving infinitely expanding generic types it may be necessary for the compiler to terminate the recursion at some point with the assumption that no further exploration will change the outcome.
+‘List<T>’ has a member ‘owner’ of type ‘List<List<T>>’, which has a member ‘owner’ of type ‘List<List<List<T>>>’, which has a member ‘owner’ of type ‘List<List<List<List<T>>>>’ and so on, ad infinitum. Since type relationships are determined structurally, possibly exploring the constituent types to their full depth, in order to determine type relationships involving infinitely expanding generic types it may be necessary for the compiler to terminate the recursion at some point with the assumption that no further exploration will change the outcome.
## 3.9 Widened Types
@@ -2247,7 +2247,7 @@ A signature is said to be an ***applicable signature*** with respect to an argum
### 4.12.2 Type Argument Inference
-Given a signature < *T1* , *T2* , … , *Tn* > ( *p1* : *P1* , *p2* : *P2* , … , *pm* : *Pm* ), where each parameter type *P* references zero or more of the type parameters *T*, and an argument list ( *e1* , *e2* , … , *em* ), the task of type argument inference is to find a set of type arguments *A1*…*An* to substitute for *T1*…*Tn* such that the argument list becomes an applicable signature.
+Given a signature < *T1* , *T2* , … , *Tn* > ( *p1* : *P1* , *p2* : *P2* , … , *pm* : *Pm* ), where each parameter type *P* references zero or more of the type parameters *T*, and an argument list ( *e1* , *e2* , … , *em* ), the task of type argument inference is to find a set of type arguments *A1*…*An* to substitute for *T1*…*Tn* such that the argument list becomes an applicable signature.
The inferred type argument for a particular type parameter is determined from a set of candidate types. Given a type parameter *T*, let *C* denote the widened form (section [3.9](#3.9)) of the best common type (section [3.10](#3.10)) of the set of candidate types *T*. Then,
@@ -2337,7 +2337,7 @@ The inclusion of type arguments in the *Arguments* production (section [4.12](#4
f(g(7));
```
-could be interpreted as a call to ‘f’ with two arguments, ‘g < A’ and ‘B > (7)’. Alternatively, it could be interpreted as a call to ‘f’ with one argument, which is a call to a generic function ‘g’ with two type arguments and one regular argument.
+could be interpreted as a call to ‘f’ with two arguments, ‘g < A’ and ‘B > (7)’. Alternatively, it could be interpreted as a call to ‘f’ with one argument, which is a call to a generic function ‘g’ with two type arguments and one regular argument.
The grammar ambiguity is resolved as follows: In a context where one possible interpretation of a sequence of tokens is an *Arguments* production, if the initial sequence of tokens forms a syntactically correct *TypeArguments* production and is followed by a ‘`(`‘ token, then the sequence of tokens is processed an *Arguments* production, and any other possible interpretation is discarded. Otherwise, the sequence of tokens is not considered an *Arguments* production.
@@ -2449,7 +2449,7 @@ In the example above,
The subsections that follow specify the compile-time processing rules of the binary operators. In general, if the operands of a binary operator do not meet the stated requirements, a compile-time error occurs and the result of the operation defaults to type any in further processing. Tables that summarize the compile-time processing rules for operands of the Any type, the Boolean, Number, and String primitive types, and all object types and type parameters (the Object column in the tables) are provided.
-### 4.15.1 The *, /, %, –, <<, >>, >>>, &, ^, and | operators
+### 4.15.1 The *, /, %, –, <<, >>, >>>, &, ^, and | operators
These operators require their operands to be of type Any, the Number primitive type, or an enum type. Operands of an enum type are treated as having the primitive type Number. If one operand is the `null` or `undefine``d` value, it is treated as having the type of the other operand. The result is always of the Number primitive type.
@@ -2483,7 +2483,7 @@ var s = getValue() + "";
The example above converts the result of ‘getValue()’ to a string if it isn’t a string already. The type inferred for ‘s’ is the String primitive type regardless of the return type of ‘getValue’.
-### 4.15.3 The <, >, <=, >=, ==, !=, ===, and !== operators
+### 4.15.3 The <, >, <=, >=, ==, !=, ===, and !== operators
These operators require one operand type to be identical to or a subtype of the other operand type. The result is always of the Boolean primitive type.
@@ -4398,7 +4398,7 @@ The source elements permitted in a TypeScript implementation source file are a s
Declaration source files are restricted to contain declarations only. Declaration source files can be used to declare the static type information associated with existing JavaScript code in an adjunct manner. They are entirely optional but enable the TypeScript compiler and tools to provide better verification and assistance when integrating existing JavaScript code and libraries in a TypeScript application.
-Implementation and declaration source files that contain no import or export declarations form the single ***global module***. Entities declared in the global module are in scope everywhere in a program. Initialization order of the source files that make up the global module ultimately depends on the order in which the generated JavaScript files are loaded at run-time (which, for example, may be controlled by tags that reference the generated JavaScript files).
+Implementation and declaration source files that contain no import or export declarations form the single ***global module***. Entities declared in the global module are in scope everywhere in a program. Initialization order of the source files that make up the global module ultimately depends on the order in which the generated JavaScript files are loaded at run-time (which, for example, may be controlled by <script/> tags that reference the generated JavaScript files).
Implementation and declaration source files that contain at least one external import declaration, export assignment, or top-level exported declaration are considered separate ***external modules***. Entities declared in an external module are in scope only in that module, but exported entities can be imported into other modules using import declarations. Initialization order of external modules is determined by the module loader being and is not specified by the TypeScript language. However, it is generally the case that non-circularly dependent modules are automatically loaded and initialized in the correct order.
@@ -4408,7 +4408,7 @@ External modules can additionally be declared using *AmbientExternalModuleDeclar
The TypeScript compiler automatically determines a source file’s dependencies and includes those dependencies in the program being compiled. The determination is made from “reference comments” and external import declarations as follows:
-* A comment of the form /// adds a dependency on the source file specified in the path argument. The path is resolved relative to the directory of the containing source file.
+* A comment of the form /// <reference path="…"/> adds a dependency on the source file specified in the path argument. The path is resolved relative to the directory of the containing source file.
* An external import declaration that specifies a relative external module name (section [11.2.1](#11.2.1)) resolves the name relative to the directory of the containing source file. If a source file with the resulting path and file extension ‘.ts’ exists, that file is added as a dependency. Otherwise, if a source file with the resulting path and file extension ‘.d.ts’ exists, that file is added as a dependency.
* An external import declaration that specifies a top-level external module name (section [11.2.1](#11.2.1)) resolves the name in a host dependent manner (typically by resolving the name relative to a module name space root or searching for the name in a series of directories). If a source file with extension ‘.ts’ or ‘.d.ts’ corresponding to the reference is located, that file is added as a dependency.
@@ -4619,7 +4619,7 @@ The special
# 12 Ambients
-Ambient declarations are used to provide static typing over existing JavaScript code. Ambient declarations differ from regular declarations in that no JavaScript code is emitted for them. Instead of introducing new variables, functions, classes, enums, or modules, ambient declarations provide type information for entities that exist “ambiently” and are included in a program by external means, for example by referencing a JavaScript library in a tag.
+Ambient declarations are used to provide static typing over existing JavaScript code. Ambient declarations differ from regular declarations in that no JavaScript code is emitted for them. Instead of introducing new variables, functions, classes, enums, or modules, ambient declarations provide type information for entities that exist “ambiently” and are included in a program by external means, for example by referencing a JavaScript library in a <script/> tag.
## 12.1 Ambient Declarations
diff --git a/scripts/word2md.js b/scripts/word2md.js
index b09b14c2373..8f9cd276f95 100644
--- a/scripts/word2md.js
+++ b/scripts/word2md.js
@@ -1,11 +1,3 @@
-// word2md - Word to Markdown conversion tool
-//
-// word2md converts a Microsoft Word document to Markdown formatted text. The tool uses the
-// Word Automation APIs to start an instance of Word and access the contents of the document
-// being converted. The tool must be run using the cscript.exe script host and requires Word
-// to be installed on the target machine. The name of the document to convert must be specified
-// as a command line argument and the resulting Markdown is written to standard output. The
-// tool recognizes the specific Word styles used in the TypeScript Language Specification.
var sys = (function () {
var args = [];
for (var i = 0; i < WScript.Arguments.length; i++) {
@@ -37,13 +29,13 @@ function convertDocumentToMarkdown(doc) {
}
}
}
- function findReplace(findText, findProps, replaceText, replaceProps) {
+ function findReplace(findText, findOptions, replaceText, replaceOptions) {
var find = doc.range().find;
find.clearFormatting();
- setProperties(find, findProps);
+ setProperties(find, findOptions);
var replace = find.replacement;
replace.clearFormatting();
- setProperties(replace, replaceProps);
+ setProperties(replace, replaceOptions);
find.execute(findText, false, false, false, false, false, true, 0, true, replaceText, 2);
}
function write(s) {
@@ -162,10 +154,14 @@ function convertDocumentToMarkdown(doc) {
}
writeBlockEnd();
}
+ findReplace("<", {}, "<", {});
+ findReplace("<", { style: "Code" }, "<", {});
+ findReplace("<", { style: "Code Fragment" }, "<", {});
+ findReplace("<", { style: "Terminal" }, "<", {});
findReplace("", { font: { subscript: true } }, "^&", { font: { subscript: false } });
- findReplace("", { style: "Code Fragment" }, "`^&`", { style: -66 /* default font */ });
- findReplace("", { style: "Production" }, "*^&*", { style: -66 /* default font */ });
- findReplace("", { style: "Terminal" }, "`^&`", { style: -66 /* default font */ });
+ findReplace("", { style: "Code Fragment" }, "`^&`", { style: -66 });
+ findReplace("", { style: "Production" }, "*^&*", { style: -66 });
+ findReplace("", { style: "Terminal" }, "`^&`", { style: -66 });
findReplace("", { font: { bold: true, italic: true } }, "***^&***", { font: { bold: false, italic: false } });
findReplace("", { font: { italic: true } }, "*^&*", { font: { italic: false } });
doc.fields.toggleShowCodes();
diff --git a/scripts/word2md.ts b/scripts/word2md.ts
index 75a6e4eb35b..b1bc50b0cb9 100644
--- a/scripts/word2md.ts
+++ b/scripts/word2md.ts
@@ -97,7 +97,7 @@ module Word {
}
export interface Fields extends Collection {
- toggleShowCodes();
+ toggleShowCodes(): void;
}
export interface Document {
@@ -129,6 +129,15 @@ var sys = (function () {
};
})();
+interface FindReplaceOptions {
+ style?: any;
+ font?: {
+ bold?: boolean;
+ italic?: boolean;
+ subscript?: boolean;
+ };
+}
+
function convertDocumentToMarkdown(doc: Word.Document): string {
var result: string = "";
@@ -138,7 +147,7 @@ function convertDocumentToMarkdown(doc: Word.Document): string {
var tableCellIndex: number;
var columnAlignment: number[] = [];
- function setProperties(target: {}, properties: {}) {
+ function setProperties(target: any, properties: any) {
for (var name in properties) {
if (properties.hasOwnProperty(name)) {
var value = properties[name];
@@ -152,13 +161,13 @@ function convertDocumentToMarkdown(doc: Word.Document): string {
}
}
- function findReplace(findText: string, findProps: {}, replaceText: string, replaceProps: {}) {
+ function findReplace(findText: string, findOptions: FindReplaceOptions, replaceText: string, replaceOptions: FindReplaceOptions) {
var find = doc.range().find;
find.clearFormatting();
- setProperties(find, findProps);
+ setProperties(find, findOptions);
var replace = find.replacement;
replace.clearFormatting();
- setProperties(replace, replaceProps);
+ setProperties(replace, replaceOptions);
find.execute(findText, false, false, false, false, false, true, 0, true, replaceText, 2);
}
@@ -295,6 +304,10 @@ function convertDocumentToMarkdown(doc: Word.Document): string {
writeBlockEnd();
}
+ findReplace("<", {}, "<", {});
+ findReplace("<", { style: "Code" }, "<", {});
+ findReplace("<", { style: "Code Fragment" }, "<", {});
+ findReplace("<", { style: "Terminal" }, "<", {});
findReplace("", { font: { subscript: true } }, "^&", { font: { subscript: false } });
findReplace("", { style: "Code Fragment" }, "`^&`", { style: -66 /* default font */ });
findReplace("", { style: "Production" }, "*^&*", { style: -66 /* default font */});
diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts
index af1851d6a75..b06326f6925 100644
--- a/src/compiler/parser.ts
+++ b/src/compiler/parser.ts
@@ -648,6 +648,10 @@ module ts {
return SyntaxKind.FirstKeyword <= token && token <= SyntaxKind.LastKeyword;
}
+ export function isTrivia(token: SyntaxKind) {
+ return SyntaxKind.FirstTriviaToken <= token && token <= SyntaxKind.LastTriviaToken;
+ }
+
export function isModifier(token: SyntaxKind): boolean {
switch (token) {
case SyntaxKind.PublicKeyword:
diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts
index 1e499fd79be..a97319ff332 100644
--- a/src/harness/fourslash.ts
+++ b/src/harness/fourslash.ts
@@ -959,10 +959,9 @@ module FourSlash {
var help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
var item = help.items[help.selectedItemIndex];
- var state = this.languageService.getSignatureHelpCurrentArgumentState(this.activeFile.fileName, this.currentCaretPosition, help.applicableSpan.start());
-
+
// Same logic as in getActiveSignatureHelp - this value might be -1 until a parameter value actually gets typed
- var currentParam = state === undefined ? 0 : state.argumentIndex;
+ var currentParam = help.argumentIndex < 0 ? 0 : help.argumentIndex;
return item.parameters[currentParam];
}
diff --git a/src/harness/unittestrunner.ts b/src/harness/unittestrunner.ts
index c91b82a0d96..95c90415409 100644
--- a/src/harness/unittestrunner.ts
+++ b/src/harness/unittestrunner.ts
@@ -7,7 +7,7 @@ class UnitTestRunner extends RunnerBase {
}
public initializeTests() {
- this.tests = this.enumerateFiles('tests/cases/unittests/services');
+ this.tests = this.enumerateFiles('tests/cases/unittests/services', /\.ts/i);
var outfile = new Harness.Compiler.WriterAggregator()
var outerr = new Harness.Compiler.WriterAggregator();
diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts
index 8021a47cee7..79b238c893d 100644
--- a/src/services/formatting/smartIndenter.ts
+++ b/src/services/formatting/smartIndenter.ts
@@ -174,7 +174,7 @@ module ts.formatting {
function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: Node, childStartLine: number, sourceFile: SourceFile): boolean {
if (parent.kind === SyntaxKind.IfStatement && (parent).elseStatement === child) {
- var elseKeyword = forEach(parent.getChildren(), c => c.kind === SyntaxKind.ElseKeyword && c);
+ var elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile);
Debug.assert(elseKeyword);
var elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line;
@@ -383,7 +383,7 @@ module ts.formatting {
return isCompletedNode((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 = forEach(n.getChildren(), c => c.kind === SyntaxKind.WhileKeyword && c);
+ var hasWhileKeyword = findChildOfKind(n, SyntaxKind.WhileKeyword, sourceFile);
if(hasWhileKeyword) {
return nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile);
}
diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts
index 2a303108c15..134508bc067 100644
--- a/src/services/outliningElementsCollector.ts
+++ b/src/services/outliningElementsCollector.ts
@@ -60,18 +60,24 @@ module ts {
case SyntaxKind.TryBlock:
case SyntaxKind.CatchBlock:
case SyntaxKind.FinallyBlock:
- var openBrace = forEach(n.getChildren(), c => c.kind === SyntaxKind.OpenBraceToken && c);
- var closeBrace = forEach(n.getChildren(), c => c.kind === SyntaxKind.CloseBraceToken && c);
+ var openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile);
+ var closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile);
addOutlineRange(n.parent, openBrace, closeBrace);
break;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.ObjectLiteral:
- var openBrace = forEach(n.getChildren(), c => c.kind === SyntaxKind.OpenBraceToken && c);
- var closeBrace = forEach(n.getChildren(), c => c.kind === SyntaxKind.CloseBraceToken && c);
+ case SyntaxKind.SwitchStatement:
+ var openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile);
+ var closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile);
addOutlineRange(n, openBrace, closeBrace);
break;
+ case SyntaxKind.ArrayLiteral:
+ var openBracket = findChildOfKind(n, SyntaxKind.OpenBracketToken, sourceFile);
+ var closeBracket = findChildOfKind(n, SyntaxKind.CloseBracketToken, sourceFile);
+ addOutlineRange(n, openBracket, closeBracket);
+ break;
}
depth++;
forEachChild(n, walk);
diff --git a/src/services/services.ts b/src/services/services.ts
index 7d11d9ab32d..3e222450aa7 100644
--- a/src/services/services.ts
+++ b/src/services/services.ts
@@ -651,16 +651,18 @@ module ts {
getCompletionsAtPosition(fileName: string, position: number, isMemberCompletion: boolean): CompletionInfo;
getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails;
- getTypeAtPosition(fileName: string, position: number): TypeInfo;
getQuickInfoAtPosition(fileName: string, position: number): QuickInfo;
+ // Obsolete. Use getQuickInfoAtPosition instead.
+ getTypeAtPosition(fileName: string, position: number): TypeInfo;
+
getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TypeScript.TextSpan;
getBreakpointStatementAtPosition(fileName: string, position: number): TypeScript.TextSpan;
getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems;
- getSignatureHelpCurrentArgumentState(fileName: string, position: number, applicableSpanStart: number): SignatureHelpState;
+ // Obsolete. Use getSignatureHelpItems instead.
getSignatureAtPosition(fileName: string, position: number): SignatureInfo;
getRenameInfo(fileName: string, position: number): RenameInfo;
@@ -861,9 +863,6 @@ module ts {
items: SignatureHelpItem[];
applicableSpan: TypeScript.TextSpan;
selectedItemIndex: number;
- }
-
- export interface SignatureHelpState {
argumentIndex: number;
argumentCount: number;
}
@@ -1032,6 +1031,7 @@ module ts {
static none = "";
static publicMemberModifier = "public";
static privateMemberModifier = "private";
+ static protectedMemberModifier = "protected";
static exportedModifier = "export";
static ambientModifier = "declare";
static staticModifier = "static";
@@ -2354,6 +2354,7 @@ module ts {
var result: string[] = [];
if (flags & NodeFlags.Private) result.push(ScriptElementKindModifier.privateMemberModifier);
+ if (flags & NodeFlags.Protected) result.push(ScriptElementKindModifier.protectedMemberModifier);
if (flags & NodeFlags.Public) result.push(ScriptElementKindModifier.publicMemberModifier);
if (flags & NodeFlags.Static) result.push(ScriptElementKindModifier.staticModifier);
if (flags & NodeFlags.Export) result.push(ScriptElementKindModifier.exportedModifier);
@@ -3765,16 +3766,6 @@ module ts {
return SignatureHelp.getSignatureHelpItems(sourceFile, position, typeInfoResolver, cancellationToken);
}
- /**
- * This is a syntactic operation
- */
- function getSignatureHelpCurrentArgumentState(fileName: string, position: number, applicableSpanStart: number): SignatureHelpState {
- fileName = TypeScript.switchToForwardSlashes(fileName);
- var sourceFile = getCurrentSourceFile(fileName);
-
- return SignatureHelp.getSignatureHelpCurrentArgumentState(sourceFile, position, applicableSpanStart);
- }
-
function getSignatureAtPosition(filename: string, position: number): SignatureInfo {
var signatureHelpItems = getSignatureHelpItems(filename, position);
@@ -3782,7 +3773,7 @@ module ts {
return undefined;
}
- var currentArguemntState = getSignatureHelpCurrentArgumentState(filename, position, signatureHelpItems.applicableSpan.start());
+ var currentArgumentState = { argumentIndex: signatureHelpItems.argumentIndex, argumentCount: signatureHelpItems.argumentCount };
var formalSignatures: FormalSignatureItemInfo[] = [];
forEach(signatureHelpItems.items, signature => {
@@ -3827,7 +3818,7 @@ module ts {
parameterMinChar: signatureHelpItems.applicableSpan.start(),
parameterLimChar: signatureHelpItems.applicableSpan.end(),
currentParameterIsTypeParameter: false,
- currentParameter: currentArguemntState.argumentIndex
+ currentParameter: currentArgumentState.argumentIndex
};
return {
@@ -4465,7 +4456,6 @@ module ts {
getCompletionEntryDetails: getCompletionEntryDetails,
getTypeAtPosition: getTypeAtPosition,
getSignatureHelpItems: getSignatureHelpItems,
- getSignatureHelpCurrentArgumentState: getSignatureHelpCurrentArgumentState,
getQuickInfoAtPosition: getQuickInfoAtPosition,
getDefinitionAtPosition: getDefinitionAtPosition,
getReferencesAtPosition: getReferencesAtPosition,
@@ -4550,17 +4540,16 @@ module ts {
do {
token = scanner.scan();
- if ((token === SyntaxKind.SlashToken || token === SyntaxKind.SlashEqualsToken) && !noRegexTable[lastNonTriviaToken]) {
- if (scanner.reScanSlashToken() === SyntaxKind.RegularExpressionLiteral) {
- token = SyntaxKind.RegularExpressionLiteral;
+ if (!isTrivia(token)) {
+ if ((token === SyntaxKind.SlashToken || token === SyntaxKind.SlashEqualsToken) && !noRegexTable[lastNonTriviaToken]) {
+ if (scanner.reScanSlashToken() === SyntaxKind.RegularExpressionLiteral) {
+ token = SyntaxKind.RegularExpressionLiteral;
+ }
+ }
+ else if (lastNonTriviaToken === SyntaxKind.DotToken && isKeyword(token)) {
+ token = SyntaxKind.Identifier;
}
- }
- else if (lastNonTriviaToken === SyntaxKind.DotToken) {
- token = SyntaxKind.Identifier;
- }
- // Only recall the token if it was *not* trivia.
- if (!(SyntaxKind.FirstTriviaToken <= token && token <= SyntaxKind.LastTriviaToken)) {
lastNonTriviaToken = token;
}
diff --git a/src/services/shims.ts b/src/services/shims.ts
index 111b203b704..a1e616f6c77 100644
--- a/src/services/shims.ts
+++ b/src/services/shims.ts
@@ -84,14 +84,16 @@ module ts {
getCompletionEntryDetails(fileName: string, position: number, entryName: string): string;
getQuickInfoAtPosition(fileName: string, position: number): string;
+
+ // Obsolete. Use getQuickInfoAtPosition instead.
getTypeAtPosition(fileName: string, position: number): string;
getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): string;
getBreakpointStatementAtPosition(fileName: string, position: number): string;
getSignatureHelpItems(fileName: string, position: number): string;
- getSignatureHelpCurrentArgumentState(fileName: string, position: number, applicableSpanStart: number): string;
+ // Obsolete. Use getSignatureHelpItems instead.
getSignatureAtPosition(fileName: string, position: number): string;
/**
@@ -617,15 +619,6 @@ module ts {
});
}
- public getSignatureHelpCurrentArgumentState(fileName: string, position: number, applicableSpanStart: number): string {
- return this.forwardJSONCall(
- "getSignatureHelpCurrentArgumentState('" + fileName + "', " + position + ", " + applicableSpanStart + ")",
- () => {
- var signatureHelpState = this.languageService.getSignatureHelpCurrentArgumentState(fileName, position, applicableSpanStart);
- return signatureHelpState;
- });
- }
-
public getSignatureAtPosition(fileName: string, position: number): string {
return this.forwardJSONCall(
"getSignatureAtPosition('" + fileName + "', " + position + ")",
diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts
index 4a02c99204d..796472c030e 100644
--- a/src/services/signatureHelp.ts
+++ b/src/services/signatureHelp.ts
@@ -337,15 +337,19 @@ module ts.SignatureHelp {
var applicableSpanStart = argumentListOrTypeArgumentList.getFullStart();
var applicableSpanEnd = skipTrivia(sourceFile.text, argumentListOrTypeArgumentList.end, /*stopAfterLineBreak*/ false);
var applicableSpan = new TypeScript.TextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
+
+ var state = getSignatureHelpCurrentArgumentState(sourceFile, position, applicableSpanStart);
return {
items: items,
applicableSpan: applicableSpan,
- selectedItemIndex: selectedItemIndex
+ selectedItemIndex: selectedItemIndex,
+ argumentIndex: state.argumentIndex,
+ argumentCount: state.argumentCount
};
}
}
- export function getSignatureHelpCurrentArgumentState(sourceFile: SourceFile, position: number, applicableSpanStart: number): SignatureHelpState {
+ function getSignatureHelpCurrentArgumentState(sourceFile: SourceFile, position: number, applicableSpanStart: number): { argumentIndex: number; argumentCount: number } {
var tokenPrecedingSpanStart = findPrecedingToken(applicableSpanStart, sourceFile);
if (!tokenPrecedingSpanStart) {
return undefined;
diff --git a/src/services/utilities.ts b/src/services/utilities.ts
index 2824ab5d2da..9e68ef1a7aa 100644
--- a/src/services/utilities.ts
+++ b/src/services/utilities.ts
@@ -16,6 +16,10 @@ module ts {
};
}
+ export function findChildOfKind(n: Node, kind: SyntaxKind, sourceFile?: SourceFile): Node {
+ return forEach(n.getChildren(sourceFile), c => c.kind === kind && c);
+ }
+
export function findContainingList(node: Node): Node {
// The node might be a list element (nonsynthetic) or a comma (synthetic). Either way, it will
// be parented by the container of the SyntaxList, not the SyntaxList itself.
diff --git a/tests/cases/fourslash/getOutliningSpans.ts b/tests/cases/fourslash/getOutliningSpans.ts
index d672ba20ac4..93665889eb4 100644
--- a/tests/cases/fourslash/getOutliningSpans.ts
+++ b/tests/cases/fourslash/getOutliningSpans.ts
@@ -25,6 +25,14 @@
////
//// }|]
////}|]
+////switch(1)[| {
+//// case 1: break;
+////}|]
+////
+////var array =[| [
+//// 1,
+//// 2
+////]|]
////
////// modules
////module m1[| {
diff --git a/tests/cases/unittests/services/colorization.ts b/tests/cases/unittests/services/colorization.ts
index 0a5ce1f0310..d89cf702693 100644
--- a/tests/cases/unittests/services/colorization.ts
+++ b/tests/cases/unittests/services/colorization.ts
@@ -189,6 +189,21 @@ describe('Colorization', function () {
identifier("var"));
});
+ it("correctly classifies a string literal after a dot", function () {
+ test("a.\"var\"",
+ ts.EndOfLineState.Start,
+ stringLiteral("\"var\""));
+ });
+
+ it("correctly classifies a keyword after a dot separated by comment trivia", function () {
+ test("a./*hello world*/ var",
+ ts.EndOfLineState.Start,
+ identifier("a"),
+ punctuation("."),
+ comment("/*hello world*/"),
+ identifier("var"));
+ });
+
it("classifies a property access with whitespace around the dot", function () {
test(" x .\tfoo ()",
ts.EndOfLineState.Start,