mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
merge conflicts
This commit is contained in:
@@ -16,7 +16,7 @@ namespace ts.BreakpointResolver {
|
||||
|
||||
let tokenAtLocation = getTokenAtPosition(sourceFile, position);
|
||||
let lineOfPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
|
||||
if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart()).line > lineOfPosition) {
|
||||
if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart(sourceFile)).line > lineOfPosition) {
|
||||
// Get previous token if the token is returned starts on new line
|
||||
// eg: let x =10; |--- cursor is here
|
||||
// let y = 10;
|
||||
@@ -39,16 +39,23 @@ namespace ts.BreakpointResolver {
|
||||
return spanInNode(tokenAtLocation);
|
||||
|
||||
function textSpan(startNode: Node, endNode?: Node) {
|
||||
return createTextSpanFromBounds(startNode.getStart(), (endNode || startNode).getEnd());
|
||||
const start = startNode.decorators ?
|
||||
skipTrivia(sourceFile.text, startNode.decorators.end) :
|
||||
startNode.getStart(sourceFile);
|
||||
return createTextSpanFromBounds(start, (endNode || startNode).getEnd());
|
||||
}
|
||||
|
||||
function spanInNodeIfStartsOnSameLine(node: Node, otherwiseOnNode?: Node): TextSpan {
|
||||
if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart()).line) {
|
||||
if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line) {
|
||||
return spanInNode(node);
|
||||
}
|
||||
return spanInNode(otherwiseOnNode);
|
||||
}
|
||||
|
||||
function spanInNodeArray<T>(nodeArray: NodeArray<T>) {
|
||||
return createTextSpanFromBounds(skipTrivia(sourceFile.text, nodeArray.pos), nodeArray.end);
|
||||
}
|
||||
|
||||
function spanInPreviousNode(node: Node): TextSpan {
|
||||
return spanInNode(findPrecedingToken(node.pos, sourceFile));
|
||||
}
|
||||
@@ -65,6 +72,11 @@ namespace ts.BreakpointResolver {
|
||||
return spanInPreviousNode(node);
|
||||
}
|
||||
|
||||
if (node.parent.kind === SyntaxKind.Decorator) {
|
||||
// Set breakpoint on the decorator emit
|
||||
return spanInNode(node.parent);
|
||||
}
|
||||
|
||||
if (node.parent.kind === SyntaxKind.ForStatement) {
|
||||
// For now lets set the span on this expression, fix it later
|
||||
return textSpan(node);
|
||||
@@ -207,6 +219,9 @@ namespace ts.BreakpointResolver {
|
||||
// span in statement
|
||||
return spanInNode((<WithStatement>node).statement);
|
||||
|
||||
case SyntaxKind.Decorator:
|
||||
return spanInNodeArray(node.parent.decorators);
|
||||
|
||||
// No breakpoint in interface, type alias
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
@@ -446,7 +461,7 @@ namespace ts.BreakpointResolver {
|
||||
// fall through.
|
||||
|
||||
case SyntaxKind.CatchClause:
|
||||
return spanInNode(lastOrUndefined((<Block>node.parent).statements));;
|
||||
return spanInNode(lastOrUndefined((<Block>node.parent).statements));
|
||||
|
||||
case SyntaxKind.CaseBlock:
|
||||
// breakpoint in last statement of the last clause
|
||||
@@ -493,9 +508,6 @@ namespace ts.BreakpointResolver {
|
||||
default:
|
||||
return spanInNode(node.parent);
|
||||
}
|
||||
|
||||
// Default to parent node
|
||||
return spanInNode(node.parent);
|
||||
}
|
||||
|
||||
function spanInColonToken(node: Node): TextSpan {
|
||||
|
||||
@@ -31,8 +31,8 @@ namespace ts.formatting {
|
||||
* the first token in line so it should be indented
|
||||
*/
|
||||
interface DynamicIndentation {
|
||||
getIndentationForToken(tokenLine: number, tokenKind: SyntaxKind): number;
|
||||
getIndentationForComment(owningToken: SyntaxKind, tokenIndentation: number): number;
|
||||
getIndentationForToken(tokenLine: number, tokenKind: SyntaxKind, container: Node): number;
|
||||
getIndentationForComment(owningToken: SyntaxKind, tokenIndentation: number, container: Node): number;
|
||||
/**
|
||||
* Indentation for open and close tokens of the node if it is block or another node that needs special indentation
|
||||
* ... {
|
||||
@@ -54,7 +54,7 @@ namespace ts.formatting {
|
||||
* so bar inherits indentation from foo and bar.delta will be 4
|
||||
*
|
||||
*/
|
||||
getDelta(): number;
|
||||
getDelta(child: TextRangeWithKind): number;
|
||||
/**
|
||||
* Formatter calls this function when rule adds or deletes new lines from the text
|
||||
* so indentation scope can adjust values of indentation and delta.
|
||||
@@ -282,19 +282,19 @@ namespace ts.formatting {
|
||||
*/
|
||||
function getOwnOrInheritedDelta(n: Node, options: FormatCodeOptions, sourceFile: SourceFile): number {
|
||||
let previousLine = Constants.Unknown;
|
||||
let childKind = SyntaxKind.Unknown;
|
||||
let child: Node;
|
||||
while (n) {
|
||||
let line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line;
|
||||
if (previousLine !== Constants.Unknown && line !== previousLine) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (SmartIndenter.shouldIndentChildNode(n.kind, childKind)) {
|
||||
if (SmartIndenter.shouldIndentChildNode(n, child)) {
|
||||
return options.IndentSize;
|
||||
}
|
||||
|
||||
previousLine = line;
|
||||
childKind = n.kind;
|
||||
child = n;
|
||||
n = n.parent;
|
||||
}
|
||||
return 0;
|
||||
@@ -325,7 +325,7 @@ namespace ts.formatting {
|
||||
|
||||
let lastIndentedLine: number;
|
||||
let indentationOnLastIndentedLine: number;
|
||||
|
||||
|
||||
let edits: TextChange[] = [];
|
||||
|
||||
formattingScanner.advance();
|
||||
@@ -354,15 +354,15 @@ namespace ts.formatting {
|
||||
* If list element is in the range - its indentation will be equal
|
||||
* to inherited indentation from its predecessors.
|
||||
*/
|
||||
function tryComputeIndentationForListItem(startPos: number,
|
||||
endPos: number,
|
||||
parentStartLine: number,
|
||||
range: TextRange,
|
||||
function tryComputeIndentationForListItem(startPos: number,
|
||||
endPos: number,
|
||||
parentStartLine: number,
|
||||
range: TextRange,
|
||||
inheritedIndentation: number): number {
|
||||
|
||||
if (rangeOverlapsWithStartEnd(range, startPos, endPos) ||
|
||||
rangeContainsStartEnd(range, startPos, endPos) /* Not to miss zero-range nodes e.g. JsxText */) {
|
||||
|
||||
|
||||
if (inheritedIndentation !== Constants.Unknown) {
|
||||
return inheritedIndentation;
|
||||
}
|
||||
@@ -378,7 +378,7 @@ namespace ts.formatting {
|
||||
|
||||
return Constants.Unknown;
|
||||
}
|
||||
|
||||
|
||||
function computeIndentation(
|
||||
node: TextRangeWithKind,
|
||||
startLine: number,
|
||||
@@ -388,48 +388,26 @@ namespace ts.formatting {
|
||||
effectiveParentStartLine: number): Indentation {
|
||||
|
||||
let indentation = inheritedIndentation;
|
||||
if (indentation === Constants.Unknown) {
|
||||
if (parent.kind === SyntaxKind.JsxElement && node.kind === SyntaxKind.JsxClosingElement) {
|
||||
// JsxClosingElement should not be indented
|
||||
indentation = parentDynamicIndentation.getIndentation();
|
||||
}
|
||||
else if (isSomeBlock(node.kind)) {
|
||||
// blocks should be indented in
|
||||
// - other blocks
|
||||
// - source file
|
||||
// - switch\default clauses
|
||||
if (isSomeBlock(parent.kind) ||
|
||||
parent.kind === SyntaxKind.SourceFile ||
|
||||
parent.kind === SyntaxKind.CaseClause ||
|
||||
parent.kind === SyntaxKind.DefaultClause) {
|
||||
|
||||
indentation = parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta();
|
||||
}
|
||||
else {
|
||||
indentation = parentDynamicIndentation.getIndentation();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile)) {
|
||||
indentation = parentDynamicIndentation.getIndentation();
|
||||
}
|
||||
else {
|
||||
indentation = parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var delta = SmartIndenter.shouldIndentChildNode(node.kind, SyntaxKind.Unknown) ? options.IndentSize : 0;
|
||||
var delta = SmartIndenter.shouldIndentChildNode(node) ? options.IndentSize : 0;
|
||||
|
||||
if (effectiveParentStartLine === startLine) {
|
||||
// if node is located on the same line with the parent
|
||||
// - inherit indentation from the parent
|
||||
// - push children if either parent of node itself has non-zero delta
|
||||
indentation = startLine === lastIndentedLine
|
||||
? indentationOnLastIndentedLine
|
||||
indentation = startLine === lastIndentedLine
|
||||
? indentationOnLastIndentedLine
|
||||
: parentDynamicIndentation.getIndentation();
|
||||
delta = Math.min(options.IndentSize, parentDynamicIndentation.getDelta() + delta);
|
||||
delta = Math.min(options.IndentSize, parentDynamicIndentation.getDelta(node) + delta);
|
||||
}
|
||||
else if (indentation === Constants.Unknown) {
|
||||
if (SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile)) {
|
||||
indentation = parentDynamicIndentation.getIndentation();
|
||||
}
|
||||
else {
|
||||
indentation = parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta(node);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
indentation,
|
||||
delta
|
||||
@@ -461,7 +439,7 @@ namespace ts.formatting {
|
||||
|
||||
function getDynamicIndentation(node: Node, nodeStartLine: number, indentation: number, delta: number): DynamicIndentation {
|
||||
return {
|
||||
getIndentationForComment: (kind, tokenIndentation) => {
|
||||
getIndentationForComment: (kind, tokenIndentation, container) => {
|
||||
switch (kind) {
|
||||
// preceding comment to the token that closes the indentation scope inherits the indentation from the scope
|
||||
// .. {
|
||||
@@ -470,11 +448,11 @@ namespace ts.formatting {
|
||||
case SyntaxKind.CloseBraceToken:
|
||||
case SyntaxKind.CloseBracketToken:
|
||||
case SyntaxKind.CloseParenToken:
|
||||
return indentation + delta;
|
||||
return indentation + getEffectiveDelta(delta, container);
|
||||
}
|
||||
return tokenIndentation !== Constants.Unknown ? tokenIndentation : indentation;
|
||||
},
|
||||
getIndentationForToken: (line, kind) => {
|
||||
getIndentationForToken: (line, kind, container) => {
|
||||
if (nodeStartLine !== line && node.decorators) {
|
||||
if (kind === getFirstNonDecoratorTokenOfNode(node)) {
|
||||
// if this token is the first token following the list of decorators, we do not need to indent
|
||||
@@ -495,13 +473,13 @@ namespace ts.formatting {
|
||||
return indentation;
|
||||
default:
|
||||
// if token line equals to the line of containing node (this is a first token in the node) - use node indentation
|
||||
return nodeStartLine !== line ? indentation + delta : indentation;
|
||||
return nodeStartLine !== line ? indentation + getEffectiveDelta(delta, container) : indentation;
|
||||
}
|
||||
},
|
||||
getIndentation: () => indentation,
|
||||
getDelta: () => delta,
|
||||
getDelta: child => getEffectiveDelta(delta, child),
|
||||
recomputeIndentation: lineAdded => {
|
||||
if (node.parent && SmartIndenter.shouldIndentChildNode(node.parent.kind, node.kind)) {
|
||||
if (node.parent && SmartIndenter.shouldIndentChildNode(node.parent, node)) {
|
||||
if (lineAdded) {
|
||||
indentation += options.IndentSize;
|
||||
}
|
||||
@@ -509,14 +487,19 @@ namespace ts.formatting {
|
||||
indentation -= options.IndentSize;
|
||||
}
|
||||
|
||||
if (SmartIndenter.shouldIndentChildNode(node.kind, SyntaxKind.Unknown)) {
|
||||
if (SmartIndenter.shouldIndentChildNode(node)) {
|
||||
delta = options.IndentSize;
|
||||
}
|
||||
else {
|
||||
delta = 0;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function getEffectiveDelta(delta: number, child: TextRangeWithKind) {
|
||||
// Delta value should be zero when the node explicitly prevents indentation of the child node
|
||||
return SmartIndenter.nodeWillIndentChild(node, child, true) ? delta : 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -592,7 +575,7 @@ namespace ts.formatting {
|
||||
if (!rangeOverlapsWithStartEnd(originalRange, child.pos, child.end)) {
|
||||
return inheritedIndentation;
|
||||
}
|
||||
|
||||
|
||||
if (child.getFullWidth() === 0) {
|
||||
return inheritedIndentation;
|
||||
}
|
||||
@@ -616,7 +599,7 @@ namespace ts.formatting {
|
||||
// if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules
|
||||
let tokenInfo = formattingScanner.readTokenInfo(child);
|
||||
Debug.assert(tokenInfo.token.end === child.end);
|
||||
consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation);
|
||||
consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, child);
|
||||
return inheritedIndentation;
|
||||
}
|
||||
|
||||
@@ -630,8 +613,8 @@ namespace ts.formatting {
|
||||
return inheritedIndentation;
|
||||
}
|
||||
|
||||
function processChildNodes(nodes: NodeArray<Node>,
|
||||
parent: Node,
|
||||
function processChildNodes(nodes: NodeArray<Node>,
|
||||
parent: Node,
|
||||
parentStartLine: number,
|
||||
parentDynamicIndentation: DynamicIndentation): void {
|
||||
|
||||
@@ -685,7 +668,7 @@ namespace ts.formatting {
|
||||
}
|
||||
}
|
||||
|
||||
function consumeTokenAndAdvanceScanner(currentTokenInfo: TokenInfo, parent: Node, dynamicIndentation: DynamicIndentation): void {
|
||||
function consumeTokenAndAdvanceScanner(currentTokenInfo: TokenInfo, parent: Node, dynamicIndentation: DynamicIndentation, container?: Node): void {
|
||||
Debug.assert(rangeContainsRange(parent, currentTokenInfo.token));
|
||||
|
||||
let lastTriviaWasNewLine = formattingScanner.lastTrailingTriviaWasNewLine();
|
||||
@@ -701,8 +684,8 @@ namespace ts.formatting {
|
||||
let tokenStart = sourceFile.getLineAndCharacterOfPosition(currentTokenInfo.token.pos);
|
||||
if (isTokenInRange) {
|
||||
let rangeHasError = rangeContainsError(currentTokenInfo.token);
|
||||
// save prevStartLine since processRange will overwrite this value with current ones
|
||||
let prevStartLine = previousRangeStartLine;
|
||||
// save previousRange since processRange will overwrite this value with current one
|
||||
let savePreviousRange = previousRange;
|
||||
lineAdded = processRange(currentTokenInfo.token, tokenStart, parent, childContextNode, dynamicIndentation);
|
||||
if (rangeHasError) {
|
||||
// do not indent comments\token if token range overlaps with some error
|
||||
@@ -713,7 +696,9 @@ namespace ts.formatting {
|
||||
indentToken = lineAdded;
|
||||
}
|
||||
else {
|
||||
indentToken = lastTriviaWasNewLine && tokenStart.line !== prevStartLine;
|
||||
// indent token only if end line of previous range does not match start line of the token
|
||||
const prevEndLine = savePreviousRange && sourceFile.getLineAndCharacterOfPosition(savePreviousRange.end).line;
|
||||
indentToken = lastTriviaWasNewLine && tokenStart.line !== prevEndLine;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -724,11 +709,11 @@ namespace ts.formatting {
|
||||
|
||||
if (indentToken) {
|
||||
let tokenIndentation = (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) ?
|
||||
dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind) :
|
||||
dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind, container) :
|
||||
Constants.Unknown;
|
||||
|
||||
if (currentTokenInfo.leadingTrivia) {
|
||||
let commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind, tokenIndentation);
|
||||
let commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind, tokenIndentation, container);
|
||||
let indentNextTokenOrTrivia = true;
|
||||
|
||||
for (let triviaItem of currentTokenInfo.leadingTrivia) {
|
||||
@@ -757,7 +742,7 @@ namespace ts.formatting {
|
||||
// indent token only if is it is in target range and does not overlap with any error ranges
|
||||
if (tokenIndentation !== Constants.Unknown) {
|
||||
insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAdded);
|
||||
|
||||
|
||||
lastIndentedLine = tokenStart.line;
|
||||
indentationOnLastIndentedLine = tokenIndentation;
|
||||
}
|
||||
@@ -778,12 +763,12 @@ namespace ts.formatting {
|
||||
}
|
||||
}
|
||||
|
||||
function processRange(range: TextRangeWithKind,
|
||||
rangeStart: LineAndCharacter,
|
||||
parent: Node,
|
||||
contextNode: Node,
|
||||
function processRange(range: TextRangeWithKind,
|
||||
rangeStart: LineAndCharacter,
|
||||
parent: Node,
|
||||
contextNode: Node,
|
||||
dynamicIndentation: DynamicIndentation): boolean {
|
||||
|
||||
|
||||
let rangeHasError = rangeContainsError(range);
|
||||
let lineAdded: boolean;
|
||||
if (!rangeHasError && !previousRangeHasError) {
|
||||
@@ -793,7 +778,7 @@ namespace ts.formatting {
|
||||
trimTrailingWhitespacesForLines(originalStart.line, rangeStart.line);
|
||||
}
|
||||
else {
|
||||
lineAdded =
|
||||
lineAdded =
|
||||
processPair(range, rangeStart.line, parent, previousRange, previousRangeStartLine, previousParent, contextNode, dynamicIndentation)
|
||||
}
|
||||
}
|
||||
@@ -939,8 +924,8 @@ namespace ts.formatting {
|
||||
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) {
|
||||
// do not trim whitespaces in comments or template expression
|
||||
if (range && (isComment(range.kind) || isStringOrRegularExpressionOrTemplateLiteral(range.kind)) && range.pos <= lineEndPosition && range.end > lineEndPosition) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,14 @@
|
||||
|
||||
/* @internal */
|
||||
namespace ts.formatting {
|
||||
let scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false);
|
||||
|
||||
const standardScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, LanguageVariant.Standard);
|
||||
const jsxScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, LanguageVariant.JSX);
|
||||
|
||||
/**
|
||||
* Scanner that is currently used for formatting
|
||||
*/
|
||||
let scanner: Scanner;
|
||||
|
||||
export interface FormattingScanner {
|
||||
advance(): void;
|
||||
isOnToken(): boolean;
|
||||
@@ -22,6 +28,8 @@ namespace ts.formatting {
|
||||
}
|
||||
|
||||
export function getFormattingScanner(sourceFile: SourceFile, startPos: number, endPos: number): FormattingScanner {
|
||||
Debug.assert(scanner === undefined);
|
||||
scanner = sourceFile.languageVariant === LanguageVariant.JSX ? jsxScanner : standardScanner;
|
||||
|
||||
scanner.setText(sourceFile.text);
|
||||
scanner.setTextPos(startPos);
|
||||
@@ -40,12 +48,17 @@ namespace ts.formatting {
|
||||
isOnToken: isOnToken,
|
||||
lastTrailingTriviaWasNewLine: () => wasNewLine,
|
||||
close: () => {
|
||||
Debug.assert(scanner !== undefined);
|
||||
|
||||
lastTokenInfo = undefined;
|
||||
scanner.setText(undefined);
|
||||
scanner = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function advance(): void {
|
||||
Debug.assert(scanner !== undefined);
|
||||
|
||||
lastTokenInfo = undefined;
|
||||
let isStarted = scanner.getStartPos() !== startPos;
|
||||
|
||||
@@ -138,6 +151,8 @@ namespace ts.formatting {
|
||||
}
|
||||
|
||||
function readTokenInfo(n: Node): TokenInfo {
|
||||
Debug.assert(scanner !== undefined);
|
||||
|
||||
if (!isOnToken()) {
|
||||
// scanner is not on the token (either advance was not called yet or scanner is already past the end position)
|
||||
return {
|
||||
@@ -245,6 +260,8 @@ namespace ts.formatting {
|
||||
}
|
||||
|
||||
function isOnToken(): boolean {
|
||||
Debug.assert(scanner !== undefined);
|
||||
|
||||
let current = (lastTokenInfo && lastTokenInfo.token.kind) || scanner.getToken();
|
||||
let startPos = (lastTokenInfo && lastTokenInfo.token.pos) || scanner.getStartPos();
|
||||
return startPos < endPos && current !== SyntaxKind.EndOfFileToken && !isTrivia(current);
|
||||
|
||||
@@ -123,6 +123,7 @@ namespace ts.formatting {
|
||||
public SpaceAfterModuleName: Rule;
|
||||
|
||||
// Lambda expressions
|
||||
public SpaceBeforeArrow: Rule;
|
||||
public SpaceAfterArrow: Rule;
|
||||
|
||||
// Optional parameters and let args
|
||||
@@ -213,27 +214,14 @@ namespace ts.formatting {
|
||||
public NoSpaceBetweenYieldKeywordAndStar: Rule;
|
||||
public SpaceBetweenYieldOrYieldStarAndOperand: Rule;
|
||||
|
||||
// Async-await
|
||||
// Async functions
|
||||
public SpaceBetweenAsyncAndOpenParen: Rule;
|
||||
public SpaceBetweenAsyncAndFunctionKeyword: Rule;
|
||||
public NoSpaceBetweenAsyncAndFunctionKeyword: Rule;
|
||||
public SpaceAfterAwaitKeyword: Rule;
|
||||
public NoSpaceAfterAwaitKeyword: Rule;
|
||||
|
||||
// Type alias declaration
|
||||
public SpaceAfterTypeKeyword: Rule;
|
||||
public NoSpaceAfterTypeKeyword: Rule;
|
||||
|
||||
// Tagged template string
|
||||
// Template strings
|
||||
public SpaceBetweenTagAndTemplateString: Rule;
|
||||
public NoSpaceBetweenTagAndTemplateString: Rule;
|
||||
|
||||
// Type operation
|
||||
public SpaceBeforeBar: Rule;
|
||||
public NoSpaceBeforeBar: Rule;
|
||||
public SpaceAfterBar: Rule;
|
||||
public NoSpaceAfterBar: Rule;
|
||||
public SpaceBeforeAmpersand: Rule;
|
||||
public SpaceAfterAmpersand: Rule;
|
||||
public NoSpaceAfterTemplateHeadAndMiddle: Rule;
|
||||
public NoSpaceBeforeTemplateMiddleAndTail: Rule;
|
||||
|
||||
constructor() {
|
||||
///
|
||||
@@ -267,7 +255,7 @@ namespace ts.formatting {
|
||||
|
||||
// No space before and after indexer
|
||||
this.NoSpaceBeforeOpenBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.OpenBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
|
||||
this.NoSpaceAfterCloseBracket = new Rule(RuleDescriptor.create3(SyntaxKind.CloseBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBeforeBlockInFunctionDeclarationContext ), RuleAction.Delete));
|
||||
this.NoSpaceAfterCloseBracket = new Rule(RuleDescriptor.create3(SyntaxKind.CloseBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBeforeBlockInFunctionDeclarationContext), RuleAction.Delete));
|
||||
|
||||
// Place a space before open brace in a function declaration
|
||||
this.FunctionOpenBraceLeftTokenRange = Shared.TokenRange.AnyIncludingMultilineComments;
|
||||
@@ -315,7 +303,7 @@ namespace ts.formatting {
|
||||
|
||||
this.NoSpaceBeforeComma = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CommaToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
|
||||
|
||||
this.SpaceAfterCertainKeywords = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.VarKeyword, SyntaxKind.ThrowKeyword, SyntaxKind.NewKeyword, SyntaxKind.DeleteKeyword, SyntaxKind.ReturnKeyword, SyntaxKind.TypeOfKeyword]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
|
||||
this.SpaceAfterCertainKeywords = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.VarKeyword, SyntaxKind.ThrowKeyword, SyntaxKind.NewKeyword, SyntaxKind.DeleteKeyword, SyntaxKind.ReturnKeyword, SyntaxKind.TypeOfKeyword, SyntaxKind.AwaitKeyword]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
|
||||
this.SpaceAfterLetConstInVariableDeclaration = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.LetKeyword, SyntaxKind.ConstKeyword]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsStartOfVariableDeclarationList), RuleAction.Space));
|
||||
this.NoSpaceBeforeOpenParenInFuncCall = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsFunctionCallOrNewContext, Rules.IsPreviousTokenNotComma), RuleAction.Delete));
|
||||
this.SpaceAfterFunctionInFuncDecl = new Rule(RuleDescriptor.create3(SyntaxKind.FunctionKeyword, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext), RuleAction.Space));
|
||||
@@ -348,13 +336,14 @@ namespace ts.formatting {
|
||||
this.NoSpaceAfterModuleImport = new Rule(RuleDescriptor.create2(Shared.TokenRange.FromTokens([SyntaxKind.ModuleKeyword, SyntaxKind.RequireKeyword]), SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
|
||||
|
||||
// Add a space around certain TypeScript keywords
|
||||
this.SpaceAfterCertainTypeScriptKeywords = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.AbstractKeyword, SyntaxKind.ClassKeyword, SyntaxKind.DeclareKeyword, SyntaxKind.DefaultKeyword, SyntaxKind.EnumKeyword, SyntaxKind.ExportKeyword, SyntaxKind.ExtendsKeyword, SyntaxKind.GetKeyword, SyntaxKind.ImplementsKeyword, SyntaxKind.ImportKeyword, SyntaxKind.InterfaceKeyword, SyntaxKind.ModuleKeyword, SyntaxKind.NamespaceKeyword, SyntaxKind.PrivateKeyword, SyntaxKind.PublicKeyword, SyntaxKind.ProtectedKeyword, SyntaxKind.SetKeyword, SyntaxKind.StaticKeyword]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
|
||||
this.SpaceAfterCertainTypeScriptKeywords = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.AbstractKeyword, SyntaxKind.ClassKeyword, SyntaxKind.DeclareKeyword, SyntaxKind.DefaultKeyword, SyntaxKind.EnumKeyword, SyntaxKind.ExportKeyword, SyntaxKind.ExtendsKeyword, SyntaxKind.GetKeyword, SyntaxKind.ImplementsKeyword, SyntaxKind.ImportKeyword, SyntaxKind.InterfaceKeyword, SyntaxKind.ModuleKeyword, SyntaxKind.NamespaceKeyword, SyntaxKind.PrivateKeyword, SyntaxKind.PublicKeyword, SyntaxKind.ProtectedKeyword, SyntaxKind.SetKeyword, SyntaxKind.StaticKeyword, SyntaxKind.TypeKeyword]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
|
||||
this.SpaceBeforeCertainTypeScriptKeywords = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.FromTokens([SyntaxKind.ExtendsKeyword, SyntaxKind.ImplementsKeyword])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
|
||||
|
||||
// Treat string literals in module names as identifiers, and add a space between the literal and the opening Brace braces, e.g.: module "m2" {
|
||||
this.SpaceAfterModuleName = new Rule(RuleDescriptor.create1(SyntaxKind.StringLiteral, SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsModuleDeclContext), RuleAction.Space));
|
||||
|
||||
// Lambda expressions
|
||||
this.SpaceBeforeArrow = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.EqualsGreaterThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
|
||||
this.SpaceAfterArrow = new Rule(RuleDescriptor.create3(SyntaxKind.EqualsGreaterThanToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
|
||||
|
||||
// Optional parameters and let args
|
||||
@@ -383,30 +372,16 @@ namespace ts.formatting {
|
||||
this.SpaceBetweenYieldOrYieldStarAndOperand = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.YieldKeyword, SyntaxKind.AsteriskToken]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsYieldOrYieldStarWithOperand), RuleAction.Space));
|
||||
|
||||
// Async-await
|
||||
this.SpaceBetweenAsyncAndOpenParen = new Rule(RuleDescriptor.create1(SyntaxKind.AsyncKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsArrowFunctionContext, Rules.IsSameLineTokenContext), RuleAction.Space));
|
||||
this.SpaceBetweenAsyncAndFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.AsyncKeyword, SyntaxKind.FunctionKeyword), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
|
||||
this.NoSpaceBetweenAsyncAndFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.AsyncKeyword, SyntaxKind.FunctionKeyword), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
|
||||
this.SpaceAfterAwaitKeyword = new Rule(RuleDescriptor.create3(SyntaxKind.AwaitKeyword, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
|
||||
this.NoSpaceAfterAwaitKeyword = new Rule(RuleDescriptor.create3(SyntaxKind.AwaitKeyword, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
|
||||
|
||||
// Type alias declaration
|
||||
this.SpaceAfterTypeKeyword = new Rule(RuleDescriptor.create3(SyntaxKind.TypeKeyword, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
|
||||
this.NoSpaceAfterTypeKeyword = new Rule(RuleDescriptor.create3(SyntaxKind.TypeKeyword, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
|
||||
|
||||
// template string
|
||||
this.SpaceBetweenTagAndTemplateString = new Rule(RuleDescriptor.create3(SyntaxKind.Identifier, Shared.TokenRange.FromTokens([SyntaxKind.NoSubstitutionTemplateLiteral, SyntaxKind.TemplateHead])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
|
||||
this.NoSpaceBetweenTagAndTemplateString = new Rule(RuleDescriptor.create3(SyntaxKind.Identifier, Shared.TokenRange.FromTokens([SyntaxKind.NoSubstitutionTemplateLiteral, SyntaxKind.TemplateHead])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
|
||||
|
||||
// type operation
|
||||
this.SpaceBeforeBar = new Rule(RuleDescriptor.create3(SyntaxKind.BarToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
|
||||
this.NoSpaceBeforeBar = new Rule(RuleDescriptor.create3(SyntaxKind.BarToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
|
||||
this.SpaceAfterBar = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.BarToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
|
||||
this.NoSpaceAfterBar = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.BarToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
|
||||
this.SpaceBeforeAmpersand = new Rule(RuleDescriptor.create3(SyntaxKind.AmpersandToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
|
||||
this.SpaceAfterAmpersand = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.AmpersandToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
|
||||
this.NoSpaceAfterTemplateHeadAndMiddle = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.TemplateHead, SyntaxKind.TemplateMiddle]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
|
||||
this.NoSpaceBeforeTemplateMiddleAndTail = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.FromTokens([SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
|
||||
|
||||
// These rules are higher in priority than user-configurable rules.
|
||||
this.HighPriorityCommonRules =
|
||||
[
|
||||
this.HighPriorityCommonRules = [
|
||||
this.IgnoreBeforeComment, this.IgnoreAfterLineComment,
|
||||
this.NoSpaceBeforeColon, this.SpaceAfterColon, this.NoSpaceBeforeQuestionMark, this.SpaceAfterQuestionMarkInConditionalOperator,
|
||||
this.NoSpaceAfterQuestionMark,
|
||||
@@ -430,18 +405,14 @@ namespace ts.formatting {
|
||||
this.NoSpaceBeforeOpenParenInFuncCall,
|
||||
this.SpaceBeforeBinaryKeywordOperator, this.SpaceAfterBinaryKeywordOperator,
|
||||
this.SpaceAfterVoidOperator,
|
||||
this.SpaceBetweenAsyncAndFunctionKeyword, this.NoSpaceBetweenAsyncAndFunctionKeyword,
|
||||
this.SpaceAfterAwaitKeyword, this.NoSpaceAfterAwaitKeyword,
|
||||
this.SpaceAfterTypeKeyword, this.NoSpaceAfterTypeKeyword,
|
||||
this.SpaceBetweenTagAndTemplateString, this.NoSpaceBetweenTagAndTemplateString,
|
||||
this.SpaceBeforeBar, this.NoSpaceBeforeBar, this.SpaceAfterBar, this.NoSpaceAfterBar,
|
||||
this.SpaceBeforeAmpersand, this.SpaceAfterAmpersand,
|
||||
this.SpaceBetweenAsyncAndOpenParen, this.SpaceBetweenAsyncAndFunctionKeyword,
|
||||
this.SpaceBetweenTagAndTemplateString, this.NoSpaceAfterTemplateHeadAndMiddle, this.NoSpaceBeforeTemplateMiddleAndTail,
|
||||
|
||||
// TypeScript-specific rules
|
||||
this.NoSpaceAfterConstructor, this.NoSpaceAfterModuleImport,
|
||||
this.SpaceAfterCertainTypeScriptKeywords, this.SpaceBeforeCertainTypeScriptKeywords,
|
||||
this.SpaceAfterModuleName,
|
||||
this.SpaceAfterArrow,
|
||||
this.SpaceBeforeArrow, this.SpaceAfterArrow,
|
||||
this.NoSpaceAfterEllipsis,
|
||||
this.NoSpaceAfterOptionalParameters,
|
||||
this.NoSpaceBetweenEmptyInterfaceBraceBrackets,
|
||||
@@ -457,8 +428,7 @@ namespace ts.formatting {
|
||||
];
|
||||
|
||||
// These rules are lower in priority than user-configurable rules.
|
||||
this.LowPriorityCommonRules =
|
||||
[
|
||||
this.LowPriorityCommonRules = [
|
||||
this.NoSpaceBeforeSemicolon,
|
||||
this.SpaceBeforeOpenBraceInControl, this.SpaceBeforeOpenBraceInFunction, this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock,
|
||||
this.NoSpaceBeforeComma,
|
||||
@@ -539,6 +509,8 @@ namespace ts.formatting {
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
case SyntaxKind.AsExpression:
|
||||
case SyntaxKind.TypePredicate:
|
||||
case SyntaxKind.UnionType:
|
||||
case SyntaxKind.IntersectionType:
|
||||
return true;
|
||||
|
||||
// equals in binding elements: function foo([[x, y] = [1, 2]])
|
||||
@@ -733,6 +705,10 @@ namespace ts.formatting {
|
||||
return context.currentTokenSpan.kind !== SyntaxKind.CommaToken;
|
||||
}
|
||||
|
||||
static IsArrowFunctionContext(context: FormattingContext): boolean {
|
||||
return context.contextNode.kind === SyntaxKind.ArrowFunction;
|
||||
}
|
||||
|
||||
static IsSameLineTokenContext(context: FormattingContext): boolean {
|
||||
return context.TokensAreOnSameLine();
|
||||
}
|
||||
@@ -756,7 +732,7 @@ namespace ts.formatting {
|
||||
}
|
||||
|
||||
static IsStartOfVariableDeclarationList(context: FormattingContext): boolean {
|
||||
return context.currentTokenParent.kind === SyntaxKind.VariableDeclarationList &&
|
||||
return context.currentTokenParent.kind === SyntaxKind.VariableDeclarationList &&
|
||||
context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,25 +13,45 @@ namespace ts.formatting {
|
||||
return 0; // past EOF
|
||||
}
|
||||
|
||||
// no indentation when the indent style is set to none,
|
||||
// so we can return fast
|
||||
if (options.IndentStyle === IndentStyle.None) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let precedingToken = findPrecedingToken(position, sourceFile);
|
||||
if (!precedingToken) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// no indentation in string \regex\template literals
|
||||
let precedingTokenIsLiteral =
|
||||
precedingToken.kind === SyntaxKind.StringLiteral ||
|
||||
precedingToken.kind === SyntaxKind.RegularExpressionLiteral ||
|
||||
precedingToken.kind === SyntaxKind.NoSubstitutionTemplateLiteral ||
|
||||
precedingToken.kind === SyntaxKind.TemplateHead ||
|
||||
precedingToken.kind === SyntaxKind.TemplateMiddle ||
|
||||
precedingToken.kind === SyntaxKind.TemplateTail;
|
||||
let precedingTokenIsLiteral = isStringOrRegularExpressionOrTemplateLiteral(precedingToken.kind);
|
||||
if (precedingTokenIsLiteral && precedingToken.getStart(sourceFile) <= position && precedingToken.end > position) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let lineAtPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
|
||||
|
||||
// indentation is first non-whitespace character in a previous line
|
||||
// for block indentation, we should look for a line which contains something that's not
|
||||
// whitespace.
|
||||
if (options.IndentStyle === IndentStyle.Block) {
|
||||
|
||||
// move backwards until we find a line with a non-whitespace character,
|
||||
// then find the first non-whitespace character for that line.
|
||||
let current = position;
|
||||
while (current > 0){
|
||||
let char = sourceFile.text.charCodeAt(current);
|
||||
if (!isWhiteSpace(char) && !isLineBreak(char)) {
|
||||
break;
|
||||
}
|
||||
current--;
|
||||
}
|
||||
|
||||
let lineStart = ts.getLineStartPositionForPosition(current, sourceFile);
|
||||
return SmartIndenter.findFirstNonWhitespaceColumn(lineStart, current, sourceFile, options);
|
||||
}
|
||||
|
||||
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
|
||||
let actualIndentation = getActualIndentationForListItemBeforeComma(precedingToken, sourceFile, options);
|
||||
@@ -48,7 +68,7 @@ namespace ts.formatting {
|
||||
let indentationDelta: number;
|
||||
|
||||
while (current) {
|
||||
if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current.kind, previous ? previous.kind : SyntaxKind.Unknown)) {
|
||||
if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current, previous)) {
|
||||
currentStart = getStartLineAndCharacterForNode(current, sourceFile);
|
||||
|
||||
if (nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile)) {
|
||||
@@ -133,7 +153,7 @@ namespace ts.formatting {
|
||||
}
|
||||
|
||||
// increase indentation if parent node wants its content to be indented and parent and child nodes don't start on the same line
|
||||
if (shouldIndentChildNode(parent.kind, current.kind) && !parentAndChildShareLine) {
|
||||
if (shouldIndentChildNode(parent, current) && !parentAndChildShareLine) {
|
||||
indentationDelta += options.IndentSize;
|
||||
}
|
||||
|
||||
@@ -224,7 +244,7 @@ namespace ts.formatting {
|
||||
function getStartLineAndCharacterForNode(n: Node, sourceFile: SourceFile): LineAndCharacter {
|
||||
return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
|
||||
}
|
||||
|
||||
|
||||
export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFile): boolean {
|
||||
if (parent.kind === SyntaxKind.IfStatement && (<IfStatement>parent).elseStatement === child) {
|
||||
let elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile);
|
||||
@@ -325,7 +345,7 @@ namespace ts.formatting {
|
||||
}
|
||||
|
||||
return Value.Unknown;
|
||||
|
||||
|
||||
function getStartingExpression(node: PropertyAccessExpression | CallExpression | ElementAccessExpression) {
|
||||
while (true) {
|
||||
switch (node.kind) {
|
||||
@@ -340,7 +360,6 @@ namespace ts.formatting {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,6 +424,7 @@ namespace ts.formatting {
|
||||
|
||||
function nodeContentIsAlwaysIndented(kind: SyntaxKind): boolean {
|
||||
switch (kind) {
|
||||
case SyntaxKind.ExpressionStatement:
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.ClassExpression:
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
@@ -443,16 +463,15 @@ namespace ts.formatting {
|
||||
case SyntaxKind.ParenthesizedType:
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
case SyntaxKind.AwaitExpression:
|
||||
case SyntaxKind.NamedImports:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function shouldIndentChildNode(parent: SyntaxKind, child: SyntaxKind): boolean {
|
||||
if (nodeContentIsAlwaysIndented(parent)) {
|
||||
return true;
|
||||
}
|
||||
switch (parent) {
|
||||
|
||||
export function nodeWillIndentChild(parent: TextRangeWithKind, child: TextRangeWithKind, indentByDefault: boolean) {
|
||||
let childKind = child ? child.kind : SyntaxKind.Unknown;
|
||||
switch (parent.kind) {
|
||||
case SyntaxKind.DoStatement:
|
||||
case SyntaxKind.WhileStatement:
|
||||
case SyntaxKind.ForInStatement:
|
||||
@@ -466,10 +485,17 @@ namespace ts.formatting {
|
||||
case SyntaxKind.Constructor:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
return child !== SyntaxKind.Block;
|
||||
default:
|
||||
return false;
|
||||
return childKind !== SyntaxKind.Block;
|
||||
}
|
||||
// No explicit rule for given nodes so the result will follow the default value argument
|
||||
return indentByDefault;
|
||||
}
|
||||
|
||||
/*
|
||||
Function returns true when the parent node should indent the given child by an explicit rule
|
||||
*/
|
||||
export function shouldIndentChildNode(parent: TextRangeWithKind, child?: TextRangeWithKind): boolean {
|
||||
return nodeContentIsAlwaysIndented(parent.kind) || nodeWillIndentChild(parent, child, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace ts.formatting {
|
||||
constructor(from: SyntaxKind, to: SyntaxKind, except: SyntaxKind[]) {
|
||||
this.tokens = [];
|
||||
for (let token = from; token <= to; token++) {
|
||||
if (except.indexOf(token) < 0) {
|
||||
if (ts.indexOf(except, token) < 0) {
|
||||
this.tokens.push(token);
|
||||
}
|
||||
}
|
||||
@@ -123,4 +123,4 @@ namespace ts.formatting {
|
||||
static TypeNames = TokenRange.FromTokens([SyntaxKind.Identifier, SyntaxKind.NumberKeyword, SyntaxKind.StringKeyword, SyntaxKind.BooleanKeyword, SyntaxKind.SymbolKeyword, SyntaxKind.VoidKeyword, SyntaxKind.AnyKeyword]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ namespace ts.NavigateTo {
|
||||
let patternMatcher = createPatternMatcher(searchValue);
|
||||
let rawItems: RawNavigateToItem[] = [];
|
||||
|
||||
// This means "compare in a case insensitive manner."
|
||||
let baseSensitivity: Intl.CollatorOptions = { sensitivity: "base" };
|
||||
|
||||
// Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[]
|
||||
forEach(program.getSourceFiles(), sourceFile => {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
@@ -162,8 +165,6 @@ namespace ts.NavigateTo {
|
||||
return bestMatchKind;
|
||||
}
|
||||
|
||||
// This means "compare in a case insensitive manner."
|
||||
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.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
/* @internal */
|
||||
namespace ts.NavigationBar {
|
||||
export function getNavigationBarItems(sourceFile: SourceFile): ts.NavigationBarItem[] {
|
||||
export function getNavigationBarItems(sourceFile: SourceFile, compilerOptions: CompilerOptions): 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.
|
||||
let hasGlobalNode = false;
|
||||
|
||||
+602
-481
File diff suppressed because it is too large
Load Diff
+16
-9
@@ -273,7 +273,7 @@ namespace ts {
|
||||
private loggingEnabled = false;
|
||||
private tracingEnabled = false;
|
||||
|
||||
public resolveModuleNames: (moduleName: string[], containingFile: string) => string[];
|
||||
public resolveModuleNames: (moduleName: string[], containingFile: string) => ResolvedModule[];
|
||||
|
||||
constructor(private shimHost: LanguageServiceShimHost) {
|
||||
// if shimHost is a COM object then property check will become method call with no arguments.
|
||||
@@ -281,7 +281,10 @@ namespace ts {
|
||||
if ("getModuleResolutionsForFile" in this.shimHost) {
|
||||
this.resolveModuleNames = (moduleNames: string[], containingFile: string) => {
|
||||
let resolutionsInFile = <Map<string>>JSON.parse(this.shimHost.getModuleResolutionsForFile(containingFile));
|
||||
return map(moduleNames, name => lookUp(resolutionsInFile, name));
|
||||
return map(moduleNames, name => {
|
||||
const result = lookUp(resolutionsInFile, name);
|
||||
return result ? { resolvedFileName: result } : undefined;
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -320,7 +323,6 @@ namespace ts {
|
||||
// TODO: should this be '==='?
|
||||
if (settingsJson == null || settingsJson == "") {
|
||||
throw Error("LanguageServiceShimHostAdapter.getCompilationSettings: empty compilationSettings");
|
||||
return null;
|
||||
}
|
||||
return <CompilerOptions>JSON.parse(settingsJson);
|
||||
}
|
||||
@@ -942,7 +944,11 @@ namespace ts {
|
||||
public resolveModuleName(fileName: string, moduleName: string, compilerOptionsJson: string): string {
|
||||
return this.forwardJSONCall(`resolveModuleName('${fileName}')`, () => {
|
||||
let compilerOptions = <CompilerOptions>JSON.parse(compilerOptionsJson);
|
||||
return resolveModuleName(moduleName, normalizeSlashes(fileName), compilerOptions, this.host);
|
||||
const result = resolveModuleName(moduleName, normalizeSlashes(fileName), compilerOptions, this.host);
|
||||
return {
|
||||
resolvedFileName: result.resolvedModule ? result.resolvedModule.resolvedFileName: undefined,
|
||||
failedLookupLocations: result.failedLookupLocations
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -950,7 +956,8 @@ namespace ts {
|
||||
return this.forwardJSONCall(
|
||||
"getPreProcessedFileInfo('" + fileName + "')",
|
||||
() => {
|
||||
var result = preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength()));
|
||||
// for now treat files as JavaScript
|
||||
var result = preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength()), /* readImportFiles */ true, /* detectJavaScriptImports */ true);
|
||||
var convertResult = {
|
||||
referencedFiles: <IFileReference[]>[],
|
||||
importedFiles: <IFileReference[]>[],
|
||||
@@ -983,7 +990,7 @@ namespace ts {
|
||||
() => {
|
||||
let text = sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength());
|
||||
|
||||
let result = parseConfigFileText(fileName, text);
|
||||
let result = parseConfigFileTextToJson(fileName, text);
|
||||
|
||||
if (result.error) {
|
||||
return {
|
||||
@@ -993,7 +1000,7 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
var configFile = parseConfigFile(result.config, this.host, getDirectoryPath(normalizeSlashes(fileName)));
|
||||
var configFile = parseJsonConfigFileContent(result.config, this.host, getDirectoryPath(normalizeSlashes(fileName)));
|
||||
|
||||
return {
|
||||
options: configFile.options,
|
||||
@@ -1026,7 +1033,7 @@ namespace ts {
|
||||
public createLanguageServiceShim(host: LanguageServiceShimHost): LanguageServiceShim {
|
||||
try {
|
||||
if (this.documentRegistry === undefined) {
|
||||
this.documentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames());
|
||||
this.documentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory());
|
||||
}
|
||||
var hostAdapter = new LanguageServiceShimHostAdapter(host);
|
||||
var languageService = createLanguageService(hostAdapter, this.documentRegistry);
|
||||
@@ -1062,7 +1069,7 @@ namespace ts {
|
||||
public close(): void {
|
||||
// Forget all the registered shims
|
||||
this._shims = [];
|
||||
this.documentRegistry = createDocumentRegistry();
|
||||
this.documentRegistry = undefined;
|
||||
}
|
||||
|
||||
public registerShim(shim: Shim): void {
|
||||
|
||||
@@ -204,7 +204,7 @@ namespace ts.SignatureHelp {
|
||||
if (!candidates.length) {
|
||||
// We didn't have any sig help items produced by the TS compiler. If this is a JS
|
||||
// file, then see if we can figure out anything better.
|
||||
if (isJavaScript(sourceFile.fileName)) {
|
||||
if (isSourceFileJavaScript(sourceFile)) {
|
||||
return createJavaScriptSignatureHelpItems(argumentInfo);
|
||||
}
|
||||
|
||||
|
||||
+28
-16
@@ -9,7 +9,7 @@ namespace ts {
|
||||
export function getEndLinePosition(line: number, sourceFile: SourceFile): number {
|
||||
Debug.assert(line >= 0);
|
||||
let lineStarts = sourceFile.getLineStarts();
|
||||
|
||||
|
||||
let lineIndex = line;
|
||||
if (lineIndex + 1 === lineStarts.length) {
|
||||
// last line - return EOF
|
||||
@@ -128,7 +128,8 @@ namespace ts {
|
||||
return isCompletedNode((<IfStatement>n).thenStatement, sourceFile);
|
||||
|
||||
case SyntaxKind.ExpressionStatement:
|
||||
return isCompletedNode((<ExpressionStatement>n).expression, sourceFile);
|
||||
return isCompletedNode((<ExpressionStatement>n).expression, sourceFile) ||
|
||||
hasChildOfKind(n, SyntaxKind.SemicolonToken);
|
||||
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
@@ -170,7 +171,7 @@ namespace ts {
|
||||
case SyntaxKind.VoidExpression:
|
||||
case SyntaxKind.YieldExpression:
|
||||
case SyntaxKind.SpreadElementExpression:
|
||||
let unaryWordExpression = (<TypeOfExpression|DeleteExpression|VoidExpression|YieldExpression|SpreadElementExpression>n);
|
||||
let unaryWordExpression = (<TypeOfExpression | DeleteExpression | VoidExpression | YieldExpression | SpreadElementExpression>n);
|
||||
return isCompletedNode(unaryWordExpression.expression, sourceFile);
|
||||
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
@@ -252,18 +253,18 @@ namespace ts {
|
||||
});
|
||||
|
||||
// Either we didn't find an appropriate list, or the list must contain us.
|
||||
Debug.assert(!syntaxList || contains(syntaxList.getChildren(), node));
|
||||
Debug.assert(!syntaxList || contains(syntaxList.getChildren(), node));
|
||||
return syntaxList;
|
||||
}
|
||||
|
||||
/* Gets the token whose text has range [start, end) and
|
||||
/* 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));
|
||||
}
|
||||
|
||||
/* Gets the token whose text has range [start, end) and position >= start
|
||||
/* Gets the token whose text has range [start, end) and position >= start
|
||||
* and (position < end or (position === end && token is keyword or identifier or numeric\string litera))
|
||||
*/
|
||||
export function getTouchingPropertyName(sourceFile: SourceFile, position: number): Node {
|
||||
@@ -388,10 +389,10 @@ namespace ts {
|
||||
// if this is the case - then we should assume that token in question is located in previous child.
|
||||
if (position < child.end && (nodeHasTokens(child) || child.kind === SyntaxKind.JsxText)) {
|
||||
const start = child.getStart(sourceFile);
|
||||
const lookInPreviousChild =
|
||||
const lookInPreviousChild =
|
||||
(start >= position) || // cursor in the leading trivia
|
||||
(child.kind === SyntaxKind.JsxText && start === child.end); // whitespace only JsxText
|
||||
|
||||
(child.kind === SyntaxKind.JsxText && start === child.end); // whitespace only JsxText
|
||||
|
||||
if (lookInPreviousChild) {
|
||||
// actual start of the node is past the position - previous token should be at the end of previous child
|
||||
let candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i);
|
||||
@@ -406,7 +407,7 @@ namespace ts {
|
||||
|
||||
Debug.assert(startNode !== undefined || n.kind === SyntaxKind.SourceFile);
|
||||
|
||||
// Here we know that none of child token nodes embrace the position,
|
||||
// Here we know that none of child token nodes embrace the position,
|
||||
// the only known case is when position is at the end of the file.
|
||||
// Try to find the rightmost token in the file without filtering.
|
||||
// Namely we are skipping the check: 'position < node.end'
|
||||
@@ -425,10 +426,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function isInString(sourceFile: SourceFile, position: number) {
|
||||
let token = getTokenAtPosition(sourceFile, position);
|
||||
return token && token.kind === SyntaxKind.StringLiteral && position > token.getStart();
|
||||
return token && (token.kind === SyntaxKind.StringLiteral || token.kind === SyntaxKind.StringLiteralType) && position > token.getStart();
|
||||
}
|
||||
|
||||
export function isInComment(sourceFile: SourceFile, position: number) {
|
||||
@@ -444,7 +445,7 @@ namespace ts {
|
||||
|
||||
if (token && position <= token.getStart()) {
|
||||
let commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos);
|
||||
|
||||
|
||||
// The end marker of a single-line comment does not include the newline character.
|
||||
// In the following case, we are inside a comment (^ denotes the cursor position):
|
||||
//
|
||||
@@ -473,7 +474,7 @@ namespace ts {
|
||||
let commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos);
|
||||
|
||||
return forEach(commentRanges, jsDocPrefix);
|
||||
|
||||
|
||||
function jsDocPrefix(c: CommentRange): boolean {
|
||||
var text = sourceFile.text;
|
||||
return text.length >= c.pos + 3 && text[c.pos] === '/' && text[c.pos + 1] === '*' && text[c.pos + 2] === '*';
|
||||
@@ -562,6 +563,16 @@ namespace ts {
|
||||
return kind === SyntaxKind.SingleLineCommentTrivia || kind === SyntaxKind.MultiLineCommentTrivia;
|
||||
}
|
||||
|
||||
export function isStringOrRegularExpressionOrTemplateLiteral(kind: SyntaxKind): boolean {
|
||||
if (kind === SyntaxKind.StringLiteral
|
||||
|| kind === SyntaxKind.StringLiteralType
|
||||
|| kind === SyntaxKind.RegularExpressionLiteral
|
||||
|| isTemplateLiteralKind(kind)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isPunctuation(kind: SyntaxKind): boolean {
|
||||
return SyntaxKind.FirstPunctuation <= kind && kind <= SyntaxKind.LastPunctuation;
|
||||
}
|
||||
@@ -626,7 +637,8 @@ namespace ts {
|
||||
increaseIndent: () => { indent++; },
|
||||
decreaseIndent: () => { indent--; },
|
||||
clear: resetWriter,
|
||||
trackSymbol: () => { }
|
||||
trackSymbol: () => { },
|
||||
reportInaccessibleThisError: () => { }
|
||||
};
|
||||
|
||||
function writeIndent() {
|
||||
@@ -689,7 +701,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function displayPart(text: string, kind: SymbolDisplayPartKind, symbol?: Symbol): SymbolDisplayPart {
|
||||
return <SymbolDisplayPart> {
|
||||
return <SymbolDisplayPart>{
|
||||
text: text,
|
||||
kind: SymbolDisplayPartKind[kind]
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user