mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-10 15:25:54 -06:00
Merge pull request #724 from Microsoft/braceYourselves
Moved brace matching functionality to use the new syntax tree
This commit is contained in:
commit
e20b6713d8
@ -1661,9 +1661,9 @@ module FourSlash {
|
||||
}
|
||||
|
||||
var actualMatchPosition = -1;
|
||||
if (bracePosition >= actual[0].start() && bracePosition <= actual[0].end()) {
|
||||
if (bracePosition === actual[0].start()) {
|
||||
actualMatchPosition = actual[1].start();
|
||||
} else if (bracePosition >= actual[1].start() && bracePosition <= actual[1].end()) {
|
||||
} else if (bracePosition === actual[1].start()) {
|
||||
actualMatchPosition = actual[0].start();
|
||||
} else {
|
||||
throw new Error('verifyMatchingBracePosition failed - could not find the brace position: ' + bracePosition + ' in the returned list: (' + actual[0].start() + ',' + actual[0].end() + ') and (' + actual[1].start() + ',' + actual[1].end() + ')');
|
||||
|
||||
@ -1,73 +0,0 @@
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
///<reference path='references.ts' />
|
||||
|
||||
module TypeScript.Services {
|
||||
export class BraceMatcher {
|
||||
|
||||
// Given a script name and position in the script, return a pair of text range if the
|
||||
// position corresponds to a "brace matchin" characters (e.g. "{" or "(", etc.)
|
||||
// If the position is not on any range, return an empty set.
|
||||
public static getMatchSpans(syntaxTree: TypeScript.SyntaxTree, position: number): TypeScript.TextSpan[] {
|
||||
var result: TypeScript.TextSpan[] = [];
|
||||
|
||||
var token = findToken(syntaxTree.sourceUnit(), position);
|
||||
|
||||
if (start(token) === position) {
|
||||
var matchKind = BraceMatcher.getMatchingTokenKind(token);
|
||||
|
||||
if (matchKind !== null) {
|
||||
var parentElement = token.parent;
|
||||
|
||||
for (var i = 0, n = childCount(parentElement); i < n; i++) {
|
||||
var current = childAt(parentElement, i);
|
||||
|
||||
if (current !== null && fullWidth(current) > 0) {
|
||||
if (current.kind() === matchKind) {
|
||||
var range1 = new TypeScript.TextSpan(start(token), width(token));
|
||||
var range2 = new TypeScript.TextSpan(start(current), width(current));
|
||||
if (range1.start() < range2.start()) {
|
||||
result.push(range1, range2);
|
||||
}
|
||||
else {
|
||||
result.push(range2, range1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static getMatchingTokenKind(token: TypeScript.ISyntaxToken): TypeScript.SyntaxKind {
|
||||
switch (token.kind()) {
|
||||
case TypeScript.SyntaxKind.OpenBraceToken: return TypeScript.SyntaxKind.CloseBraceToken
|
||||
case TypeScript.SyntaxKind.OpenParenToken: return TypeScript.SyntaxKind.CloseParenToken;
|
||||
case TypeScript.SyntaxKind.OpenBracketToken: return TypeScript.SyntaxKind.CloseBracketToken;
|
||||
case TypeScript.SyntaxKind.LessThanToken: return TypeScript.SyntaxKind.GreaterThanToken;
|
||||
case TypeScript.SyntaxKind.CloseBraceToken: return TypeScript.SyntaxKind.OpenBraceToken
|
||||
case TypeScript.SyntaxKind.CloseParenToken: return TypeScript.SyntaxKind.OpenParenToken;
|
||||
case TypeScript.SyntaxKind.CloseBracketToken: return TypeScript.SyntaxKind.OpenBracketToken;
|
||||
case TypeScript.SyntaxKind.GreaterThanToken: return TypeScript.SyntaxKind.LessThanToken;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7,7 +7,6 @@
|
||||
/// <reference path='syntax\incrementalParser.ts' />
|
||||
/// <reference path='outliningElementsCollector.ts' />
|
||||
/// <reference path='getScriptLexicalStructureWalker.ts' />
|
||||
/// <reference path='braceMatcher.ts' />
|
||||
/// <reference path='breakpoints.ts' />
|
||||
/// <reference path='indentation.ts' />
|
||||
/// <reference path='formatting\formatting.ts' />
|
||||
@ -2111,7 +2110,7 @@ module ts {
|
||||
if (child.getFullStart() <= position && position < child.getEnd()) {
|
||||
current = child;
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
@ -3759,14 +3758,61 @@ module ts {
|
||||
}
|
||||
|
||||
function getBraceMatchingAtPosition(filename: string, position: number) {
|
||||
filename = TypeScript.switchToForwardSlashes(filename);
|
||||
var syntaxTree = getSyntaxTree(filename);
|
||||
return TypeScript.Services.BraceMatcher.getMatchSpans(syntaxTree, position);
|
||||
var sourceFile = getCurrentSourceFile(filename);
|
||||
var result: TypeScript.TextSpan[] = [];
|
||||
|
||||
var token = getTokenAtPosition(sourceFile, position);
|
||||
|
||||
if (token.getStart(sourceFile) === position) {
|
||||
var matchKind = getMatchingTokenKind(token);
|
||||
|
||||
// Ensure that there is a corresponding token to match ours.
|
||||
if (matchKind) {
|
||||
var parentElement = token.parent;
|
||||
|
||||
var childNodes = parentElement.getChildren(sourceFile);
|
||||
for (var i = 0, n = childNodes.length; i < n; i++) {
|
||||
var current = childNodes[i];
|
||||
|
||||
if (current.kind === matchKind) {
|
||||
var range1 = new TypeScript.TextSpan(token.getStart(sourceFile), token.getWidth(sourceFile));
|
||||
var range2 = new TypeScript.TextSpan(current.getStart(sourceFile), current.getWidth(sourceFile));
|
||||
|
||||
// We want to order the braces when we return the result.
|
||||
if (range1.start() < range2.start()) {
|
||||
result.push(range1, range2);
|
||||
}
|
||||
else {
|
||||
result.push(range2, range1);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
function getMatchingTokenKind(token: Node): ts.SyntaxKind {
|
||||
switch (token.kind) {
|
||||
case ts.SyntaxKind.OpenBraceToken: return ts.SyntaxKind.CloseBraceToken
|
||||
case ts.SyntaxKind.OpenParenToken: return ts.SyntaxKind.CloseParenToken;
|
||||
case ts.SyntaxKind.OpenBracketToken: return ts.SyntaxKind.CloseBracketToken;
|
||||
case ts.SyntaxKind.LessThanToken: return ts.SyntaxKind.GreaterThanToken;
|
||||
case ts.SyntaxKind.CloseBraceToken: return ts.SyntaxKind.OpenBraceToken
|
||||
case ts.SyntaxKind.CloseParenToken: return ts.SyntaxKind.OpenParenToken;
|
||||
case ts.SyntaxKind.CloseBracketToken: return ts.SyntaxKind.OpenBracketToken;
|
||||
case ts.SyntaxKind.GreaterThanToken: return ts.SyntaxKind.LessThanToken;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function getIndentationAtPosition(filename: string, position: number, editorOptions: EditorOptions) {
|
||||
filename = TypeScript.switchToForwardSlashes(filename);
|
||||
|
||||
|
||||
var sourceFile = getCurrentSourceFile(filename);
|
||||
var options = new TypeScript.FormattingOptions(!editorOptions.ConvertTabsToSpaces, editorOptions.TabSize, editorOptions.IndentSize, editorOptions.NewLineCharacter)
|
||||
|
||||
|
||||
@ -38,6 +38,6 @@
|
||||
////}
|
||||
|
||||
test.ranges().forEach((range) => {
|
||||
verify.matchingBracePositionInCurrentFile(range.start, range.end - 1);
|
||||
verify.matchingBracePositionInCurrentFile(range.end - 1, range.start);
|
||||
});
|
||||
verify.matchingBracePositionInCurrentFile(range.start, range.end - 1);
|
||||
verify.matchingBracePositionInCurrentFile(range.end - 1, range.start);
|
||||
});
|
||||
9
tests/cases/fourslash/getMatchingBracesAdjacentBraces.ts
Normal file
9
tests/cases/fourslash/getMatchingBracesAdjacentBraces.ts
Normal file
@ -0,0 +1,9 @@
|
||||
////function f[|<T>|][|(x: T)|][|{
|
||||
//// return x;
|
||||
////}|]
|
||||
|
||||
// If there is an adjacent opening and closing brace,
|
||||
// then only the opening brace should get highlighted.
|
||||
test.ranges().forEach(range => {
|
||||
verify.matchingBracePositionInCurrentFile(range.start, range.end - 1);
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user