Merge branch 'master' into transforms

This commit is contained in:
Ron Buckton
2016-05-31 18:43:51 -07:00
178 changed files with 6261 additions and 2058 deletions
+6
View File
@@ -81,6 +81,12 @@ namespace ts.formatting {
while (isWhiteSpace(sourceFile.text.charCodeAt(endOfFormatSpan)) && !isLineBreak(sourceFile.text.charCodeAt(endOfFormatSpan))) {
endOfFormatSpan--;
}
// if the character at the end of the span is a line break, we shouldn't include it, because it indicates we don't want to
// touch the current line at all. Also, on some OSes the line break consists of two characters (\r\n), we should test if the
// previous character before the end of format span is line break character as well.
if (isLineBreak(sourceFile.text.charCodeAt(endOfFormatSpan))) {
endOfFormatSpan--;
}
const span = {
// get start position for the previous line
pos: getStartPositionOfLine(line - 1, sourceFile),
+70 -34
View File
@@ -9,16 +9,10 @@ namespace ts.NavigationBar {
return getJsNavigationBarItems(sourceFile, compilerOptions);
}
// If the source file has any child items, then it included in the tree
// and takes lexical ownership of all other top-level items.
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.
let indent = hasGlobalNode ? 1 : 0;
let indent = 1; // Global node is the only one with indent 0.
let current = node.parent;
while (current) {
@@ -104,6 +98,7 @@ namespace ts.NavigationBar {
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.ImportSpecifier:
case SyntaxKind.ExportSpecifier:
case SyntaxKind.TypeAliasDeclaration:
childNodes.push(node);
break;
}
@@ -140,7 +135,7 @@ namespace ts.NavigationBar {
function sortNodes(nodes: Node[]): Node[] {
return nodes.slice(0).sort((n1: Declaration, n2: Declaration) => {
if (n1.name && n2.name) {
return getPropertyNameForPropertyNameNode(n1.name).localeCompare(getPropertyNameForPropertyNameNode(n2.name));
return localeCompareFix(getPropertyNameForPropertyNameNode(n1.name), getPropertyNameForPropertyNameNode(n2.name));
}
else if (n1.name) {
return 1;
@@ -152,6 +147,16 @@ namespace ts.NavigationBar {
return n1.kind - n2.kind;
}
});
// node 0.10 treats "a" as greater than "B".
// For consistency, sort alphabetically, falling back to which is lower-case.
function localeCompareFix(a: string, b: string) {
const cmp = a.toLowerCase().localeCompare(b.toLowerCase());
if (cmp !== 0)
return cmp;
// Return the *opposite* of the `<` operator, which works the same in node 0.10 and 6.0.
return a < b ? 1 : a > b ? -1 : 0;
}
}
function addTopLevelNodes(nodes: Node[], topLevelNodes: Node[]): void {
@@ -320,9 +325,15 @@ namespace ts.NavigationBar {
case SyntaxKind.EnumMember:
return createItem(node, getTextOfNode((<EnumMember>node).name), ts.ScriptElementKind.memberVariableElement);
case SyntaxKind.ModuleDeclaration:
return createItem(node, getModuleName(<ModuleDeclaration>node), ts.ScriptElementKind.moduleElement);
case SyntaxKind.InterfaceDeclaration:
return createItem(node, getTextOfNode((<InterfaceDeclaration>node).name), ts.ScriptElementKind.interfaceElement);
case SyntaxKind.TypeAliasDeclaration:
return createItem(node, getTextOfNode((<TypeAliasDeclaration>node).name), ts.ScriptElementKind.typeElement);
case SyntaxKind.CallSignature:
return createItem(node, "()", ts.ScriptElementKind.callSignatureElement);
@@ -333,6 +344,9 @@ namespace ts.NavigationBar {
case SyntaxKind.PropertySignature:
return createItem(node, getTextOfNode((<PropertyDeclaration>node).name), ts.ScriptElementKind.memberVariableElement);
case SyntaxKind.ClassDeclaration:
return createItem(node, getTextOfNode((<ClassDeclaration>node).name), ts.ScriptElementKind.classElement);
case SyntaxKind.FunctionDeclaration:
return createItem(node, getTextOfNode((<FunctionLikeDeclaration>node).name), ts.ScriptElementKind.functionElement);
@@ -436,26 +450,6 @@ namespace ts.NavigationBar {
return undefined;
function getModuleName(moduleDeclaration: ModuleDeclaration): string {
// We want to maintain quotation marks.
if (isAmbientModule(moduleDeclaration)) {
return getTextOfNode(moduleDeclaration.name);
}
// Otherwise, we need to aggregate each identifier to build up the qualified name.
const result: string[] = [];
result.push(moduleDeclaration.name.text);
while (moduleDeclaration.body && moduleDeclaration.body.kind === SyntaxKind.ModuleDeclaration) {
moduleDeclaration = <ModuleDeclaration>moduleDeclaration.body;
result.push(moduleDeclaration.name.text);
}
return result.join(".");
}
function createModuleItem(node: ModuleDeclaration): NavigationBarItem {
const moduleName = getModuleName(node);
@@ -521,11 +515,6 @@ namespace ts.NavigationBar {
function createSourceFileItem(node: SourceFile): ts.NavigationBarItem {
const childItems = getItemsWorker(getChildNodes(node.statements), createChildItem);
if (childItems === undefined || childItems.length === 0) {
return undefined;
}
hasGlobalNode = true;
const rootName = isExternalModule(node)
? "\"" + escapeString(getBaseFileName(removeFileExtension(normalizePath(node.fileName)))) + "\""
: "<global>";
@@ -590,6 +579,26 @@ namespace ts.NavigationBar {
}
}
function getModuleName(moduleDeclaration: ModuleDeclaration): string {
// We want to maintain quotation marks.
if (isAmbientModule(moduleDeclaration)) {
return getTextOfNode(moduleDeclaration.name);
}
// Otherwise, we need to aggregate each identifier to build up the qualified name.
const result: string[] = [];
result.push(moduleDeclaration.name.text);
while (moduleDeclaration.body && moduleDeclaration.body.kind === SyntaxKind.ModuleDeclaration) {
moduleDeclaration = <ModuleDeclaration>moduleDeclaration.body;
result.push(moduleDeclaration.name.text);
}
return result.join(".");
}
function removeComputedProperties(node: EnumDeclaration): Declaration[] {
return filter<Declaration>(node.members, member => member.name === undefined || member.name.kind !== SyntaxKind.ComputedPropertyName);
}
@@ -643,6 +652,12 @@ namespace ts.NavigationBar {
topItem.childItems.push(newItem);
}
if (node.jsDocComments && node.jsDocComments.length > 0) {
for (const jsDocComment of node.jsDocComments) {
visitNode(jsDocComment);
}
}
// Add a level if traversing into a container
if (newItem && (isFunctionLike(node) || isClassLike(node))) {
const lastTop = topItem;
@@ -722,6 +737,27 @@ namespace ts.NavigationBar {
}
const declName = declarationNameToString(decl.name);
return getNavBarItem(declName, ScriptElementKind.constElement, [getNodeSpan(node)]);
case SyntaxKind.JSDocTypedefTag:
if ((<JSDocTypedefTag>node).name) {
return getNavBarItem(
(<JSDocTypedefTag>node).name.text,
ScriptElementKind.typeElement,
[getNodeSpan(node)]);
}
else {
const parentNode = node.parent && node.parent.parent;
if (parentNode && parentNode.kind === SyntaxKind.VariableStatement) {
if ((<VariableStatement>parentNode).declarationList.declarations.length > 0) {
const nameIdentifier = (<VariableStatement>parentNode).declarationList.declarations[0].name;
if (nameIdentifier.kind === SyntaxKind.Identifier) {
return getNavBarItem(
(<Identifier>nameIdentifier).text,
ScriptElementKind.typeElement,
[getNodeSpan(node)]);
}
}
}
}
default:
return undefined;
}
@@ -792,7 +828,7 @@ namespace ts.NavigationBar {
}
function getNodeSpan(node: Node) {
return node.kind === SyntaxKind.SourceFile
return node.kind === SyntaxKind.SourceFile
? createTextSpanFromBounds(node.getFullStart(), node.getEnd())
: createTextSpanFromBounds(node.getStart(), node.getEnd());
}
+30 -11
View File
@@ -20,7 +20,7 @@ namespace ts {
getChildCount(sourceFile?: SourceFile): number;
getChildAt(index: number, sourceFile?: SourceFile): Node;
getChildren(sourceFile?: SourceFile): Node[];
getStart(sourceFile?: SourceFile): number;
getStart(sourceFile?: SourceFile, includeJsDocComment?: boolean): number;
getFullStart(): number;
getEnd(): number;
getWidth(sourceFile?: SourceFile): number;
@@ -172,6 +172,9 @@ namespace ts {
"static",
"throws",
"type",
"typedef",
"property",
"prop",
"version"
];
let jsDocCompletionEntries: CompletionEntry[];
@@ -189,6 +192,7 @@ namespace ts {
public end: number;
public flags: NodeFlags;
public parent: Node;
public jsDocComments: JSDocComment[];
public original: Node;
public transformFlags: TransformFlags;
public excludeTransformFlags: TransformFlags;
@@ -209,8 +213,8 @@ namespace ts {
return getSourceFileOfNode(this);
}
public getStart(sourceFile?: SourceFile): number {
return getTokenPosOfNode(this, sourceFile);
public getStart(sourceFile?: SourceFile, includeJsDocComment?: boolean): number {
return getTokenPosOfNode(this, sourceFile, includeJsDocComment);
}
public getFullStart(): number {
@@ -241,12 +245,14 @@ namespace ts {
return (sourceFile || this.getSourceFile()).text.substring(this.getStart(), this.getEnd());
}
private addSyntheticNodes(nodes: Node[], pos: number, end: number): number {
private addSyntheticNodes(nodes: Node[], pos: number, end: number, useJSDocScanner?: boolean): number {
scanner.setTextPos(pos);
while (pos < end) {
const token = scanner.scan();
const token = useJSDocScanner ? scanner.scanJSDocToken() : scanner.scan();
const textPos = scanner.getTextPos();
nodes.push(createNode(token, pos, textPos, 0, this));
if (textPos <= end) {
nodes.push(createNode(token, pos, textPos, 0, this));
}
pos = textPos;
}
return pos;
@@ -276,20 +282,27 @@ namespace ts {
scanner.setText((sourceFile || this.getSourceFile()).text);
children = [];
let pos = this.pos;
const useJSDocScanner = this.kind >= SyntaxKind.FirstJSDocTagNode && this.kind <= SyntaxKind.LastJSDocTagNode;
const processNode = (node: Node) => {
if (pos < node.pos) {
pos = this.addSyntheticNodes(children, pos, node.pos);
pos = this.addSyntheticNodes(children, pos, node.pos, useJSDocScanner);
}
children.push(node);
pos = node.end;
};
const processNodes = (nodes: NodeArray<Node>) => {
if (pos < nodes.pos) {
pos = this.addSyntheticNodes(children, pos, nodes.pos);
pos = this.addSyntheticNodes(children, pos, nodes.pos, useJSDocScanner);
}
children.push(this.createSyntaxList(<NodeArray<Node>>nodes));
pos = nodes.end;
};
// jsDocComments need to be the first children
if (this.jsDocComments) {
for (const jsDocComment of this.jsDocComments) {
processNode(jsDocComment);
}
}
forEachChild(this, processNode, processNodes);
if (pos < this.end) {
this.addSyntheticNodes(children, pos, this.end);
@@ -5643,7 +5656,7 @@ namespace ts {
const sourceFile = getValidSourceFile(fileName);
const node = getTouchingPropertyName(sourceFile, position);
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
if (node === sourceFile) {
return undefined;
}
@@ -6005,7 +6018,8 @@ namespace ts {
const sourceFile = container.getSourceFile();
const tripleSlashDirectivePrefixRegex = /^\/\/\/\s*</;
const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, container.getStart(), container.getEnd());
const start = findInComments ? container.getFullStart() : container.getStart();
const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, start, container.getEnd());
if (possiblePositions.length) {
// Build the set of symbols to search for, initially it has only the current symbol
@@ -7835,7 +7849,7 @@ namespace ts {
const defaultLibFileName = host.getDefaultLibFileName(host.getCompilationSettings());
const canonicalDefaultLibName = getCanonicalFileName(ts.normalizePath(defaultLibFileName));
const node = getTouchingWord(sourceFile, position);
const node = getTouchingWord(sourceFile, position, /*includeJsDocComment*/ true);
// Can only rename an identifier.
if (node) {
@@ -8005,6 +8019,11 @@ namespace ts {
break;
default:
forEachChild(node, walk);
if (node.jsDocComments) {
for (const jsDocComment of node.jsDocComments) {
forEachChild(jsDocComment, walk);
}
}
}
}
}
+46 -16
View File
@@ -234,29 +234,29 @@ namespace ts {
/* Gets the token whose text has range [start, end) and
* position >= start and (position < end or (position === end && token is keyword or identifier))
*/
export function getTouchingWord(sourceFile: SourceFile, position: number): Node {
return getTouchingToken(sourceFile, position, n => isWord(n.kind));
export function getTouchingWord(sourceFile: SourceFile, position: number, includeJsDocComment = false): Node {
return getTouchingToken(sourceFile, position, n => isWord(n.kind), includeJsDocComment);
}
/* Gets the token whose text has range [start, end) and position >= start
* and (position < end or (position === end && token is keyword or identifier or numeric/string literal))
*/
export function getTouchingPropertyName(sourceFile: SourceFile, position: number): Node {
return getTouchingToken(sourceFile, position, n => isPropertyName(n.kind));
export function getTouchingPropertyName(sourceFile: SourceFile, position: number, includeJsDocComment = false): Node {
return getTouchingToken(sourceFile, position, n => isPropertyName(n.kind), includeJsDocComment);
}
/** Returns the token if position is in [start, end) or if position === end and includeItemAtEndPosition(token) === true */
export function getTouchingToken(sourceFile: SourceFile, position: number, includeItemAtEndPosition?: (n: Node) => boolean): Node {
return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, includeItemAtEndPosition);
export function getTouchingToken(sourceFile: SourceFile, position: number, includeItemAtEndPosition?: (n: Node) => boolean, includeJsDocComment = false): Node {
return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, includeItemAtEndPosition, includeJsDocComment);
}
/** Returns a token if position is in [start-of-leading-trivia, end) */
export function getTokenAtPosition(sourceFile: SourceFile, position: number): Node {
return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includeItemAtEndPosition*/ undefined);
export function getTokenAtPosition(sourceFile: SourceFile, position: number, includeJsDocComment = false): Node {
return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includeItemAtEndPosition*/ undefined, includeJsDocComment);
}
/** Get the token whose text contains the position */
function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allowPositionInLeadingTrivia: boolean, includeItemAtEndPosition: (n: Node) => boolean): Node {
function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allowPositionInLeadingTrivia: boolean, includeItemAtEndPosition: (n: Node) => boolean, includeJsDocComment = false): Node {
let current: Node = sourceFile;
outer: while (true) {
if (isToken(current)) {
@@ -264,10 +264,34 @@ namespace ts {
return current;
}
if (includeJsDocComment) {
const jsDocChildren = ts.filter(current.getChildren(), isJSDocNode);
for (const jsDocChild of jsDocChildren) {
const start = allowPositionInLeadingTrivia ? jsDocChild.getFullStart() : jsDocChild.getStart(sourceFile, includeJsDocComment);
if (start <= position) {
const end = jsDocChild.getEnd();
if (position < end || (position === end && jsDocChild.kind === SyntaxKind.EndOfFileToken)) {
current = jsDocChild;
continue outer;
}
else if (includeItemAtEndPosition && end === position) {
const previousToken = findPrecedingToken(position, sourceFile, jsDocChild);
if (previousToken && includeItemAtEndPosition(previousToken)) {
return previousToken;
}
}
}
}
}
// find the child that contains 'position'
for (let i = 0, n = current.getChildCount(sourceFile); i < n; i++) {
const child = current.getChildAt(i);
const start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile);
// all jsDocComment nodes were already visited
if (isJSDocNode(child)) {
continue;
}
const start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile, includeJsDocComment);
if (start <= position) {
const end = child.getEnd();
if (position < end || (position === end && child.kind === SyntaxKind.EndOfFileToken)) {
@@ -282,6 +306,7 @@ namespace ts {
}
}
}
return current;
}
}
@@ -420,6 +445,10 @@ namespace ts {
return false;
}
if (token.kind === SyntaxKind.JsxText) {
return true;
}
// <div>Hello |</div>
if (token.kind === SyntaxKind.LessThanToken && token.parent.kind === SyntaxKind.JsxText) {
return true;
@@ -430,7 +459,7 @@ namespace ts {
return true;
}
// <div> {
// <div> {
// |
// } < /div>
if (token && token.kind === SyntaxKind.CloseBraceToken && token.parent.kind === SyntaxKind.JsxExpression) {
@@ -515,11 +544,12 @@ namespace ts {
}
if (node) {
const jsDocComment = node.jsDocComment;
if (jsDocComment) {
for (const tag of jsDocComment.tags) {
if (tag.pos <= position && position <= tag.end) {
return tag;
if (node.jsDocComments) {
for (const jsDocComment of node.jsDocComments) {
for (const tag of jsDocComment.tags) {
if (tag.pos <= position && position <= tag.end) {
return tag;
}
}
}
}