mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 04:43:37 -05:00
Merge pull request #1535 from Microsoft/mergeMarkers1
Provide better error recovery when we encounter merge markers in the source.
This commit is contained in:
@@ -23,10 +23,10 @@ module ts {
|
||||
|
||||
export interface StringSet extends Map<any> { }
|
||||
|
||||
export function forEach<T, U>(array: T[], callback: (element: T) => U): U {
|
||||
export function forEach<T, U>(array: T[], callback: (element: T, index: number) => U): U {
|
||||
if (array) {
|
||||
for (var i = 0, len = array.length; i < len; i++) {
|
||||
var result = callback(array[i]);
|
||||
var result = callback(array[i], i);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -7,10 +7,6 @@ module ts {
|
||||
(message: DiagnosticMessage, length: number): void;
|
||||
}
|
||||
|
||||
export interface CommentCallback {
|
||||
(pos: number, end: number): void;
|
||||
}
|
||||
|
||||
export interface Scanner {
|
||||
getStartPos(): number;
|
||||
getToken(): SyntaxKind;
|
||||
@@ -396,8 +392,10 @@ module ts {
|
||||
var mergeConflictMarkerLength = "<<<<<<<".length;
|
||||
|
||||
function isConflictMarkerTrivia(text: string, pos: number) {
|
||||
Debug.assert(pos >= 0);
|
||||
|
||||
// Conflict markers must be at the start of a line.
|
||||
if (pos > 0 && isLineBreak(text.charCodeAt(pos - 1))) {
|
||||
if (pos === 0 || isLineBreak(text.charCodeAt(pos - 1))) {
|
||||
var ch = text.charCodeAt(pos);
|
||||
|
||||
if ((pos + mergeConflictMarkerLength) < text.length) {
|
||||
@@ -415,10 +413,31 @@ module ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function scanConflictMarkerTrivia(text: string, pos: number) {
|
||||
function scanConflictMarkerTrivia(text: string, pos: number, error?: ErrorCallback) {
|
||||
if (error) {
|
||||
error(Diagnostics.Merge_conflict_marker_encountered, mergeConflictMarkerLength);
|
||||
}
|
||||
|
||||
var ch = text.charCodeAt(pos);
|
||||
var len = text.length;
|
||||
while (pos < len && !isLineBreak(text.charCodeAt(pos))) {
|
||||
pos++;
|
||||
|
||||
if (ch === CharacterCodes.lessThan || ch === CharacterCodes.greaterThan) {
|
||||
while (pos < len && !isLineBreak(text.charCodeAt(pos))) {
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Debug.assert(ch === CharacterCodes.equals);
|
||||
// Consume everything from the start of the mid-conlict marker to the start of the next
|
||||
// end-conflict marker.
|
||||
while (pos < len) {
|
||||
var ch = text.charCodeAt(pos);
|
||||
if (ch === CharacterCodes.greaterThan && isConflictMarkerTrivia(text, pos)) {
|
||||
break;
|
||||
}
|
||||
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
@@ -1057,8 +1076,7 @@ module ts {
|
||||
return pos++, token = SyntaxKind.SemicolonToken;
|
||||
case CharacterCodes.lessThan:
|
||||
if (isConflictMarkerTrivia(text, pos)) {
|
||||
mergeConflictError();
|
||||
pos = scanConflictMarkerTrivia(text, pos);
|
||||
pos = scanConflictMarkerTrivia(text, pos, error);
|
||||
if (skipTrivia) {
|
||||
continue;
|
||||
}
|
||||
@@ -1079,8 +1097,7 @@ module ts {
|
||||
return pos++, token = SyntaxKind.LessThanToken;
|
||||
case CharacterCodes.equals:
|
||||
if (isConflictMarkerTrivia(text, pos)) {
|
||||
mergeConflictError();
|
||||
pos = scanConflictMarkerTrivia(text, pos);
|
||||
pos = scanConflictMarkerTrivia(text, pos, error);
|
||||
if (skipTrivia) {
|
||||
continue;
|
||||
}
|
||||
@@ -1101,8 +1118,7 @@ module ts {
|
||||
return pos++, token = SyntaxKind.EqualsToken;
|
||||
case CharacterCodes.greaterThan:
|
||||
if (isConflictMarkerTrivia(text, pos)) {
|
||||
mergeConflictError();
|
||||
pos = scanConflictMarkerTrivia(text, pos);
|
||||
pos = scanConflictMarkerTrivia(text, pos, error);
|
||||
if (skipTrivia) {
|
||||
continue;
|
||||
}
|
||||
@@ -1171,10 +1187,6 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function mergeConflictError() {
|
||||
error(Diagnostics.Merge_conflict_marker_encountered, mergeConflictMarkerLength);
|
||||
}
|
||||
|
||||
function reScanGreaterToken(): SyntaxKind {
|
||||
if (token === SyntaxKind.GreaterThanToken) {
|
||||
if (text.charCodeAt(pos) === CharacterCodes.greaterThan) {
|
||||
|
||||
@@ -16,6 +16,8 @@ module ts {
|
||||
MultiLineCommentTrivia,
|
||||
NewLineTrivia,
|
||||
WhitespaceTrivia,
|
||||
// We detect and provide better error recovery when we encounter a git merge marker. This
|
||||
// allows us to edit files with git-conflict markers in them in a much more pleasant manner.
|
||||
ConflictMarkerTrivia,
|
||||
// Literals
|
||||
NumericLiteral,
|
||||
@@ -272,8 +274,6 @@ module ts {
|
||||
LastLiteralToken = NoSubstitutionTemplateLiteral,
|
||||
FirstTemplateToken = NoSubstitutionTemplateLiteral,
|
||||
LastTemplateToken = TemplateTail,
|
||||
FirstOperator = SemicolonToken,
|
||||
LastOperator = CaretEqualsToken,
|
||||
FirstBinaryOperator = LessThanToken,
|
||||
LastBinaryOperator = CaretEqualsToken,
|
||||
FirstNode = QualifiedName,
|
||||
|
||||
@@ -125,10 +125,8 @@ module ts.formatting {
|
||||
static Any: TokenRange = TokenRange.AllTokens();
|
||||
static AnyIncludingMultilineComments = TokenRange.FromTokens(TokenRange.Any.GetTokens().concat([SyntaxKind.MultiLineCommentTrivia]));
|
||||
static Keywords = TokenRange.FromRange(SyntaxKind.FirstKeyword, SyntaxKind.LastKeyword);
|
||||
static Operators = TokenRange.FromRange(SyntaxKind.FirstOperator, SyntaxKind.LastOperator);
|
||||
static BinaryOperators = TokenRange.FromRange(SyntaxKind.FirstBinaryOperator, SyntaxKind.LastBinaryOperator);
|
||||
static BinaryKeywordOperators = TokenRange.FromTokens([SyntaxKind.InKeyword, SyntaxKind.InstanceOfKeyword]);
|
||||
static ReservedKeywords = TokenRange.FromRange(SyntaxKind.FirstFutureReservedWord, SyntaxKind.LastFutureReservedWord);
|
||||
static UnaryPrefixOperators = TokenRange.FromTokens([SyntaxKind.PlusPlusToken, SyntaxKind.MinusMinusToken, SyntaxKind.TildeToken, SyntaxKind.ExclamationToken]);
|
||||
static UnaryPrefixExpressions = TokenRange.FromTokens([SyntaxKind.NumericLiteral, SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, SyntaxKind.OpenBraceToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]);
|
||||
static UnaryPreincrementExpressions = TokenRange.FromTokens([SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]);
|
||||
|
||||
@@ -2155,7 +2155,7 @@ module ts {
|
||||
// invalid identifier name. We need to check if whatever was inside the quotes is actually a valid identifier name.
|
||||
displayName = displayName.substring(1, displayName.length - 1);
|
||||
}
|
||||
|
||||
|
||||
var isValid = isIdentifierStart(displayName.charCodeAt(0), target);
|
||||
for (var i = 1, n = displayName.length; isValid && i < n; i++) {
|
||||
isValid = isIdentifierPart(displayName.charCodeAt(i), target);
|
||||
@@ -2206,7 +2206,7 @@ module ts {
|
||||
// Completion not allowed inside comments, bail out if this is the case
|
||||
var insideComment = isInsideComment(sourceFile, currentToken, position);
|
||||
host.log("getCompletionsAtPosition: Is inside comment: " + (new Date().getTime() - start));
|
||||
|
||||
|
||||
if (insideComment) {
|
||||
host.log("Returning an empty list because completion was inside a comment.");
|
||||
return undefined;
|
||||
@@ -2593,7 +2593,7 @@ module ts {
|
||||
if (flags & SymbolFlags.TypeAlias) return ScriptElementKind.typeElement;
|
||||
if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement;
|
||||
if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
|
||||
|
||||
|
||||
var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, typeResolver, location);
|
||||
if (result === ScriptElementKind.unknown) {
|
||||
if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
|
||||
@@ -2656,7 +2656,7 @@ module ts {
|
||||
|
||||
return ScriptElementKind.unknown;
|
||||
}
|
||||
|
||||
|
||||
function getTypeKind(type: Type): string {
|
||||
var flags = type.getFlags();
|
||||
|
||||
@@ -2730,7 +2730,7 @@ module ts {
|
||||
if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
var right = (<PropertyAccessExpression>location.parent).name;
|
||||
// Either the location is on the right of a property access, or on the left and the right is missing
|
||||
if (right === location || (right && right.getFullWidth() === 0)){
|
||||
if (right === location || (right && right.getFullWidth() === 0)) {
|
||||
location = location.parent;
|
||||
}
|
||||
}
|
||||
@@ -2974,7 +2974,7 @@ module ts {
|
||||
symbolFlags & SymbolFlags.Method ||
|
||||
symbolFlags & SymbolFlags.Constructor ||
|
||||
symbolFlags & SymbolFlags.Signature ||
|
||||
symbolFlags & SymbolFlags.Accessor ||
|
||||
symbolFlags & SymbolFlags.Accessor ||
|
||||
symbolKind === ScriptElementKind.memberFunctionElement) {
|
||||
var allSignatures = type.getCallSignatures();
|
||||
addSignatureDisplayParts(allSignatures[0], allSignatures);
|
||||
@@ -3333,7 +3333,7 @@ module ts {
|
||||
if (!hasKind(ifStatement.elseStatement, SyntaxKind.IfStatement)) {
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
ifStatement = <IfStatement>ifStatement.elseStatement;
|
||||
}
|
||||
|
||||
@@ -3355,7 +3355,7 @@ module ts {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (shouldHighlightNextKeyword) {
|
||||
result.push({
|
||||
fileName: filename,
|
||||
@@ -3394,7 +3394,7 @@ module ts {
|
||||
|
||||
return map(keywords, getReferenceEntryFromNode);
|
||||
}
|
||||
|
||||
|
||||
function getThrowOccurrences(throwStatement: ThrowStatement) {
|
||||
var owner = getThrowStatementOwner(throwStatement);
|
||||
|
||||
@@ -3403,7 +3403,7 @@ module ts {
|
||||
}
|
||||
|
||||
var keywords: Node[] = [];
|
||||
|
||||
|
||||
forEach(aggregateOwnedThrowStatements(owner), throwStatement => {
|
||||
pushKeywordIf(keywords, throwStatement.getFirstToken(), SyntaxKind.ThrowKeyword);
|
||||
});
|
||||
@@ -3415,7 +3415,7 @@ module ts {
|
||||
pushKeywordIf(keywords, returnStatement.getFirstToken(), SyntaxKind.ReturnKeyword);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return map(keywords, getReferenceEntryFromNode);
|
||||
}
|
||||
|
||||
@@ -3551,7 +3551,7 @@ module ts {
|
||||
return map(keywords, getReferenceEntryFromNode);
|
||||
}
|
||||
|
||||
function getBreakOrContinueStatementOccurences(breakOrContinueStatement: BreakOrContinueStatement): ReferenceEntry[]{
|
||||
function getBreakOrContinueStatementOccurences(breakOrContinueStatement: BreakOrContinueStatement): ReferenceEntry[] {
|
||||
var owner = getBreakOrContinueOwner(breakOrContinueStatement);
|
||||
|
||||
if (owner) {
|
||||
@@ -3599,7 +3599,7 @@ module ts {
|
||||
if (statement.kind === SyntaxKind.ContinueStatement) {
|
||||
continue;
|
||||
}
|
||||
// Fall through.
|
||||
// Fall through.
|
||||
case SyntaxKind.ForStatement:
|
||||
case SyntaxKind.ForInStatement:
|
||||
case SyntaxKind.WhileStatement:
|
||||
@@ -4024,13 +4024,13 @@ module ts {
|
||||
* searchLocation: a node where the search value
|
||||
*/
|
||||
function getReferencesInNode(container: Node,
|
||||
searchSymbol: Symbol,
|
||||
searchText: string,
|
||||
searchLocation: Node,
|
||||
searchMeaning: SemanticMeaning,
|
||||
findInStrings: boolean,
|
||||
findInComments: boolean,
|
||||
result: ReferenceEntry[]): void {
|
||||
searchSymbol: Symbol,
|
||||
searchText: string,
|
||||
searchLocation: Node,
|
||||
searchMeaning: SemanticMeaning,
|
||||
findInStrings: boolean,
|
||||
findInComments: boolean,
|
||||
result: ReferenceEntry[]): void {
|
||||
var sourceFile = container.getSourceFile();
|
||||
var tripleSlashDirectivePrefixRegex = /^\/\/\/\s*</
|
||||
|
||||
@@ -4110,7 +4110,7 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getReferencesForSuperKeyword(superKeyword: Node): ReferenceEntry[]{
|
||||
function getReferencesForSuperKeyword(superKeyword: Node): ReferenceEntry[] {
|
||||
var searchSpaceNode = getSuperContainer(superKeyword);
|
||||
if (!searchSpaceNode) {
|
||||
return undefined;
|
||||
@@ -4184,7 +4184,7 @@ module ts {
|
||||
if (isExternalModule(<SourceFile>searchSpaceNode)) {
|
||||
return undefined;
|
||||
}
|
||||
// Fall through
|
||||
// Fall through
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
break;
|
||||
@@ -4861,26 +4861,105 @@ module ts {
|
||||
fileName = normalizeSlashes(fileName);
|
||||
var sourceFile = getCurrentSourceFile(fileName);
|
||||
|
||||
// Make a scanner we can get trivia from.
|
||||
var triviaScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.text);
|
||||
var mergeConflictScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.text);
|
||||
|
||||
var result: ClassifiedSpan[] = [];
|
||||
processElement(sourceFile);
|
||||
|
||||
return result;
|
||||
|
||||
function classifyComment(comment: CommentRange) {
|
||||
var width = comment.end - comment.pos;
|
||||
if (textSpanIntersectsWith(span, comment.pos, width)) {
|
||||
function classifyLeadingTrivia(token: Node): void {
|
||||
var tokenStart = skipTrivia(sourceFile.text, token.pos, /*stopAfterLineBreak:*/ false);
|
||||
if (tokenStart === token.pos) {
|
||||
return;
|
||||
}
|
||||
|
||||
// token has trivia. Classify them appropriately.
|
||||
triviaScanner.setTextPos(token.pos);
|
||||
while (true) {
|
||||
var start = triviaScanner.getTextPos();
|
||||
var kind = triviaScanner.scan();
|
||||
var end = triviaScanner.getTextPos();
|
||||
var width = end - start;
|
||||
|
||||
if (textSpanIntersectsWith(span, start, width)) {
|
||||
if (!isTrivia(kind)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isComment(kind)) {
|
||||
// Simple comment. Just add as is.
|
||||
result.push({
|
||||
textSpan: createTextSpan(start, width),
|
||||
classificationType: ClassificationTypeNames.comment
|
||||
})
|
||||
continue;
|
||||
}
|
||||
|
||||
if (kind === SyntaxKind.ConflictMarkerTrivia) {
|
||||
var text = sourceFile.text;
|
||||
var ch = text.charCodeAt(start);
|
||||
|
||||
// for the <<<<<<< and >>>>>>> markers, we just add them in as comments
|
||||
// in the classification stream.
|
||||
if (ch === CharacterCodes.lessThan || ch === CharacterCodes.greaterThan) {
|
||||
result.push({
|
||||
textSpan: createTextSpan(start, width),
|
||||
classificationType: ClassificationTypeNames.comment
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
// for the ======== add a comment for the first line, and then lex all
|
||||
// subsequent lines up until the end of the conflict marker.
|
||||
Debug.assert(ch === CharacterCodes.equals);
|
||||
classifyDisabledMergeCode(text, start, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function classifyDisabledMergeCode(text: string, start: number, end: number) {
|
||||
// Classify the line that the ======= marker is on as a comment. Then just lex
|
||||
// all further tokens and add them to the result.
|
||||
for (var i = start; i < end; i++) {
|
||||
if (isLineBreak(text.charCodeAt(i))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
result.push({
|
||||
textSpan: createTextSpanFromBounds(start, i),
|
||||
classificationType: ClassificationTypeNames.comment
|
||||
});
|
||||
|
||||
mergeConflictScanner.setTextPos(i);
|
||||
|
||||
while (mergeConflictScanner.getTextPos() < end) {
|
||||
classifyDisabledCodeToken();
|
||||
}
|
||||
}
|
||||
|
||||
function classifyDisabledCodeToken() {
|
||||
var start = mergeConflictScanner.getTextPos();
|
||||
var tokenKind = mergeConflictScanner.scan();
|
||||
var end = mergeConflictScanner.getTextPos();
|
||||
|
||||
var type = classifyTokenType(tokenKind);
|
||||
if (type) {
|
||||
result.push({
|
||||
textSpan: createTextSpan(comment.pos, width),
|
||||
classificationType: ClassificationTypeNames.comment
|
||||
textSpan: createTextSpanFromBounds(start, end),
|
||||
classificationType: type
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function classifyToken(token: Node): void {
|
||||
forEach(getLeadingCommentRanges(sourceFile.text, token.getFullStart()), classifyComment);
|
||||
classifyLeadingTrivia(token);
|
||||
|
||||
if (token.getWidth() > 0) {
|
||||
var type = classifyTokenType(token);
|
||||
var type = classifyTokenType(token.kind, token);
|
||||
if (type) {
|
||||
result.push({
|
||||
textSpan: createTextSpan(token.getStart(), token.getWidth()),
|
||||
@@ -4888,12 +4967,12 @@ module ts {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
forEach(getTrailingCommentRanges(sourceFile.text, token.getEnd()), classifyComment);
|
||||
}
|
||||
|
||||
function classifyTokenType(token: Node): string {
|
||||
var tokenKind = token.kind;
|
||||
// for accurate classification, the actual token should be passed in. however, for
|
||||
// cases like 'disabled merge code' classification, we just get the token kind and
|
||||
// classify based on that instead.
|
||||
function classifyTokenType(tokenKind: SyntaxKind, token?: Node): string {
|
||||
if (isKeyword(tokenKind)) {
|
||||
return ClassificationTypeNames.keyword;
|
||||
}
|
||||
@@ -4903,23 +4982,31 @@ module ts {
|
||||
if (tokenKind === SyntaxKind.LessThanToken || tokenKind === SyntaxKind.GreaterThanToken) {
|
||||
// If the node owning the token has a type argument list or type parameter list, then
|
||||
// we can effectively assume that a '<' and '>' belong to those lists.
|
||||
if (getTypeArgumentOrTypeParameterList(token.parent)) {
|
||||
if (token && getTypeArgumentOrTypeParameterList(token.parent)) {
|
||||
return ClassificationTypeNames.punctuation;
|
||||
}
|
||||
}
|
||||
|
||||
if (isPunctuation(token.kind)) {
|
||||
// the '=' in a variable declaration is special cased here.
|
||||
if (token.parent.kind === SyntaxKind.BinaryExpression ||
|
||||
token.parent.kind === SyntaxKind.VariableDeclaration ||
|
||||
token.parent.kind === SyntaxKind.PrefixUnaryExpression ||
|
||||
token.parent.kind === SyntaxKind.PostfixUnaryExpression ||
|
||||
token.parent.kind === SyntaxKind.ConditionalExpression) {
|
||||
return ClassificationTypeNames.operator;
|
||||
}
|
||||
else {
|
||||
return ClassificationTypeNames.punctuation;
|
||||
if (isPunctuation(tokenKind)) {
|
||||
if (token) {
|
||||
if (tokenKind === SyntaxKind.EqualsToken) {
|
||||
// the '=' in a variable declaration is special cased here.
|
||||
if (token.parent.kind === SyntaxKind.VariableDeclaration ||
|
||||
token.parent.kind === SyntaxKind.PropertyDeclaration ||
|
||||
token.parent.kind === SyntaxKind.Parameter) {
|
||||
return ClassificationTypeNames.operator;
|
||||
}
|
||||
}
|
||||
|
||||
if (token.parent.kind === SyntaxKind.BinaryExpression ||
|
||||
token.parent.kind === SyntaxKind.PrefixUnaryExpression ||
|
||||
token.parent.kind === SyntaxKind.PostfixUnaryExpression ||
|
||||
token.parent.kind === SyntaxKind.ConditionalExpression) {
|
||||
return ClassificationTypeNames.operator;
|
||||
}
|
||||
}
|
||||
|
||||
return ClassificationTypeNames.punctuation;
|
||||
}
|
||||
else if (tokenKind === SyntaxKind.NumericLiteral) {
|
||||
return ClassificationTypeNames.numericLiteral;
|
||||
@@ -4936,35 +5023,37 @@ module ts {
|
||||
return ClassificationTypeNames.stringLiteral;
|
||||
}
|
||||
else if (tokenKind === SyntaxKind.Identifier) {
|
||||
switch (token.parent.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
if ((<ClassDeclaration>token.parent).name === token) {
|
||||
return ClassificationTypeNames.className;
|
||||
}
|
||||
return;
|
||||
case SyntaxKind.TypeParameter:
|
||||
if ((<TypeParameterDeclaration>token.parent).name === token) {
|
||||
return ClassificationTypeNames.typeParameterName;
|
||||
}
|
||||
return;
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
if ((<InterfaceDeclaration>token.parent).name === token) {
|
||||
return ClassificationTypeNames.interfaceName;
|
||||
}
|
||||
return;
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
if ((<EnumDeclaration>token.parent).name === token) {
|
||||
return ClassificationTypeNames.enumName;
|
||||
}
|
||||
return;
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
if ((<ModuleDeclaration>token.parent).name === token) {
|
||||
return ClassificationTypeNames.moduleName;
|
||||
}
|
||||
return;
|
||||
default:
|
||||
return ClassificationTypeNames.text;
|
||||
if (token) {
|
||||
switch (token.parent.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
if ((<ClassDeclaration>token.parent).name === token) {
|
||||
return ClassificationTypeNames.className;
|
||||
}
|
||||
return;
|
||||
case SyntaxKind.TypeParameter:
|
||||
if ((<TypeParameterDeclaration>token.parent).name === token) {
|
||||
return ClassificationTypeNames.typeParameterName;
|
||||
}
|
||||
return;
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
if ((<InterfaceDeclaration>token.parent).name === token) {
|
||||
return ClassificationTypeNames.interfaceName;
|
||||
}
|
||||
return;
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
if ((<EnumDeclaration>token.parent).name === token) {
|
||||
return ClassificationTypeNames.enumName;
|
||||
}
|
||||
return;
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
if ((<ModuleDeclaration>token.parent).name === token) {
|
||||
return ClassificationTypeNames.moduleName;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return ClassificationTypeNames.text;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5493,7 +5582,6 @@ module ts {
|
||||
var start = scanner.getTokenPos();
|
||||
var end = scanner.getTextPos();
|
||||
|
||||
// add the token
|
||||
addResult(end - start, classFromKind(token));
|
||||
|
||||
if (end >= text.length) {
|
||||
|
||||
@@ -1,24 +1,18 @@
|
||||
tests/cases/compiler/conflictMarkerTrivia1.ts(2,1): error TS1185: Merge conflict marker encountered.
|
||||
tests/cases/compiler/conflictMarkerTrivia1.ts(3,5): error TS2300: Duplicate identifier 'v'.
|
||||
tests/cases/compiler/conflictMarkerTrivia1.ts(4,1): error TS1185: Merge conflict marker encountered.
|
||||
tests/cases/compiler/conflictMarkerTrivia1.ts(5,5): error TS2300: Duplicate identifier 'v'.
|
||||
tests/cases/compiler/conflictMarkerTrivia1.ts(6,1): error TS1185: Merge conflict marker encountered.
|
||||
|
||||
|
||||
==== tests/cases/compiler/conflictMarkerTrivia1.ts (5 errors) ====
|
||||
==== tests/cases/compiler/conflictMarkerTrivia1.ts (3 errors) ====
|
||||
class C {
|
||||
<<<<<<< HEAD
|
||||
~~~~~~~
|
||||
!!! error TS1185: Merge conflict marker encountered.
|
||||
v = 1;
|
||||
~
|
||||
!!! error TS2300: Duplicate identifier 'v'.
|
||||
=======
|
||||
~~~~~~~
|
||||
!!! error TS1185: Merge conflict marker encountered.
|
||||
v = 2;
|
||||
~
|
||||
!!! error TS2300: Duplicate identifier 'v'.
|
||||
>>>>>>> Branch-a
|
||||
~~~~~~~
|
||||
!!! error TS1185: Merge conflict marker encountered.
|
||||
|
||||
28
tests/baselines/reference/conflictMarkerTrivia2.errors.txt
Normal file
28
tests/baselines/reference/conflictMarkerTrivia2.errors.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
tests/cases/compiler/conflictMarkerTrivia2.ts(3,1): error TS1185: Merge conflict marker encountered.
|
||||
tests/cases/compiler/conflictMarkerTrivia2.ts(4,6): error TS2304: Cannot find name 'a'.
|
||||
tests/cases/compiler/conflictMarkerTrivia2.ts(6,1): error TS1185: Merge conflict marker encountered.
|
||||
tests/cases/compiler/conflictMarkerTrivia2.ts(9,1): error TS1185: Merge conflict marker encountered.
|
||||
|
||||
|
||||
==== tests/cases/compiler/conflictMarkerTrivia2.ts (4 errors) ====
|
||||
class C {
|
||||
foo() {
|
||||
<<<<<<< B
|
||||
~~~~~~~
|
||||
!!! error TS1185: Merge conflict marker encountered.
|
||||
a();
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'a'.
|
||||
}
|
||||
=======
|
||||
~~~~~~~
|
||||
!!! error TS1185: Merge conflict marker encountered.
|
||||
b();
|
||||
}
|
||||
>>>>>>> A
|
||||
~~~~~~~
|
||||
!!! error TS1185: Merge conflict marker encountered.
|
||||
|
||||
public bar() { }
|
||||
}
|
||||
|
||||
12
tests/cases/compiler/conflictMarkerTrivia2.ts
Normal file
12
tests/cases/compiler/conflictMarkerTrivia2.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
class C {
|
||||
foo() {
|
||||
<<<<<<< B
|
||||
a();
|
||||
}
|
||||
=======
|
||||
b();
|
||||
}
|
||||
>>>>>>> A
|
||||
|
||||
public bar() { }
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
////class C {
|
||||
////<<<<<<< HEAD
|
||||
//// v = 1;
|
||||
////v = 1;
|
||||
////=======
|
||||
////v = 2;
|
||||
////>>>>>>> Branch - a
|
||||
@@ -13,6 +13,6 @@ verify.currentFileContentIs("class C {\r\n\
|
||||
<<<<<<< HEAD\r\n\
|
||||
v = 1;\r\n\
|
||||
=======\r\n\
|
||||
v = 2;\r\n\
|
||||
v = 2;\r\n\
|
||||
>>>>>>> Branch - a\r\n\
|
||||
}");
|
||||
@@ -0,0 +1,19 @@
|
||||
/// <reference path="fourslash.ts"/>
|
||||
|
||||
////class C {
|
||||
////<<<<<<< HEAD
|
||||
//// v = 1;
|
||||
////=======
|
||||
//// v = 2;
|
||||
////>>>>>>> Branch - a
|
||||
////}
|
||||
debugger;
|
||||
var c = classification;
|
||||
verify.syntacticClassificationsAre(
|
||||
c.keyword("class"), c.className("C"), c.punctuation("{"),
|
||||
c.comment("<<<<<<< HEAD"),
|
||||
c.text("v"), c.operator("="), c.numericLiteral("1"), c.punctuation(";"),
|
||||
c.comment("======="),
|
||||
c.text("v"), c.punctuation("="), c.numericLiteral("2"), c.punctuation(";"),
|
||||
c.comment(">>>>>>> Branch - a"),
|
||||
c.punctuation("}"));
|
||||
@@ -0,0 +1,15 @@
|
||||
/// <reference path="fourslash.ts"/>
|
||||
|
||||
////<<<<<<< HEAD
|
||||
////class C { }
|
||||
////=======
|
||||
////class D { }
|
||||
////>>>>>>> Branch - a
|
||||
|
||||
var c = classification;
|
||||
verify.syntacticClassificationsAre(
|
||||
c.comment("<<<<<<< HEAD"),
|
||||
c.keyword("class"), c.className("C"), c.punctuation("{"), c.punctuation("}"),
|
||||
c.comment("======="),
|
||||
c.keyword("class"), c.text("D"), c.punctuation("{"), c.punctuation("}"),
|
||||
c.comment(">>>>>>> Branch - a"));
|
||||
@@ -21,7 +21,7 @@ describe('Colorization', function () {
|
||||
var mytypescriptLS = new Harness.LanguageService.TypeScriptLS();
|
||||
var myclassifier = mytypescriptLS.getClassifier();
|
||||
|
||||
function getClassifications(code: string, initialEndOfLineState: ts.EndOfLineState = ts.EndOfLineState.Start): ClassiferResult {
|
||||
function getLexicalClassifications(code: string, initialEndOfLineState: ts.EndOfLineState = ts.EndOfLineState.Start): ClassiferResult {
|
||||
var classResult = myclassifier.getClassificationsForLine(code, initialEndOfLineState).split('\n');
|
||||
var tuples: Classification[] = [];
|
||||
var i = 0;
|
||||
@@ -71,8 +71,8 @@ describe('Colorization', function () {
|
||||
function regExpLiteral(text: string) { return { value: text, class: ts.TokenClass.RegExpLiteral }; }
|
||||
function finalEndOfLineState(value: number) { return { value: value, class: <ts.TokenClass>undefined }; }
|
||||
|
||||
function test(text: string, initialEndOfLineState: ts.EndOfLineState, ...expectedEntries: ClassificationEntry[]): void {
|
||||
var result = getClassifications(text, initialEndOfLineState);
|
||||
function testLexicalClassification(text: string, initialEndOfLineState: ts.EndOfLineState, ...expectedEntries: ClassificationEntry[]): void {
|
||||
var result = getLexicalClassifications(text, initialEndOfLineState);
|
||||
|
||||
for (var i = 0, n = expectedEntries.length; i < n; i++) {
|
||||
var expectedEntry = expectedEntries[i];
|
||||
@@ -95,7 +95,7 @@ describe('Colorization', function () {
|
||||
|
||||
describe("test getClassifications", function () {
|
||||
it("Returns correct token classes", function () {
|
||||
test("var x: string = \"foo\"; //Hello",
|
||||
testLexicalClassification("var x: string = \"foo\"; //Hello",
|
||||
ts.EndOfLineState.Start,
|
||||
keyword("var"),
|
||||
whitespace(" "),
|
||||
@@ -109,7 +109,7 @@ describe('Colorization', function () {
|
||||
});
|
||||
|
||||
it("correctly classifies a comment after a divide operator", function () {
|
||||
test("1 / 2 // comment",
|
||||
testLexicalClassification("1 / 2 // comment",
|
||||
ts.EndOfLineState.Start,
|
||||
numberLiteral("1"),
|
||||
whitespace(" "),
|
||||
@@ -119,7 +119,7 @@ describe('Colorization', function () {
|
||||
});
|
||||
|
||||
it("correctly classifies a literal after a divide operator", function () {
|
||||
test("1 / 2, 3 / 4",
|
||||
testLexicalClassification("1 / 2, 3 / 4",
|
||||
ts.EndOfLineState.Start,
|
||||
numberLiteral("1"),
|
||||
whitespace(" "),
|
||||
@@ -131,131 +131,131 @@ describe('Colorization', function () {
|
||||
});
|
||||
|
||||
it("correctly classifies a multi-line string with one backslash", function () {
|
||||
test("'line1\\",
|
||||
testLexicalClassification("'line1\\",
|
||||
ts.EndOfLineState.Start,
|
||||
stringLiteral("'line1\\"),
|
||||
finalEndOfLineState(ts.EndOfLineState.InSingleQuoteStringLiteral));
|
||||
});
|
||||
|
||||
it("correctly classifies a multi-line string with three backslashes", function () {
|
||||
test("'line1\\\\\\",
|
||||
testLexicalClassification("'line1\\\\\\",
|
||||
ts.EndOfLineState.Start,
|
||||
stringLiteral("'line1\\\\\\"),
|
||||
finalEndOfLineState(ts.EndOfLineState.InSingleQuoteStringLiteral));
|
||||
});
|
||||
|
||||
it("correctly classifies an unterminated single-line string with no backslashes", function () {
|
||||
test("'line1",
|
||||
testLexicalClassification("'line1",
|
||||
ts.EndOfLineState.Start,
|
||||
stringLiteral("'line1"),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
});
|
||||
|
||||
it("correctly classifies an unterminated single-line string with two backslashes", function () {
|
||||
test("'line1\\\\",
|
||||
testLexicalClassification("'line1\\\\",
|
||||
ts.EndOfLineState.Start,
|
||||
stringLiteral("'line1\\\\"),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
});
|
||||
|
||||
it("correctly classifies an unterminated single-line string with four backslashes", function () {
|
||||
test("'line1\\\\\\\\",
|
||||
testLexicalClassification("'line1\\\\\\\\",
|
||||
ts.EndOfLineState.Start,
|
||||
stringLiteral("'line1\\\\\\\\"),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
});
|
||||
|
||||
it("correctly classifies the continuing line of a multi-line string ending in one backslash", function () {
|
||||
test("\\",
|
||||
testLexicalClassification("\\",
|
||||
ts.EndOfLineState.InDoubleQuoteStringLiteral,
|
||||
stringLiteral("\\"),
|
||||
finalEndOfLineState(ts.EndOfLineState.InDoubleQuoteStringLiteral));
|
||||
});
|
||||
|
||||
it("correctly classifies the continuing line of a multi-line string ending in three backslashes", function () {
|
||||
test("\\",
|
||||
testLexicalClassification("\\",
|
||||
ts.EndOfLineState.InDoubleQuoteStringLiteral,
|
||||
stringLiteral("\\"),
|
||||
finalEndOfLineState(ts.EndOfLineState.InDoubleQuoteStringLiteral));
|
||||
});
|
||||
|
||||
it("correctly classifies the last line of an unterminated multi-line string ending in no backslashes", function () {
|
||||
test(" ",
|
||||
testLexicalClassification(" ",
|
||||
ts.EndOfLineState.InDoubleQuoteStringLiteral,
|
||||
stringLiteral(" "),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
});
|
||||
|
||||
it("correctly classifies the last line of an unterminated multi-line string ending in two backslashes", function () {
|
||||
test("\\\\",
|
||||
testLexicalClassification("\\\\",
|
||||
ts.EndOfLineState.InDoubleQuoteStringLiteral,
|
||||
stringLiteral("\\\\"),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
});
|
||||
|
||||
it("correctly classifies the last line of an unterminated multi-line string ending in four backslashes", function () {
|
||||
test("\\\\\\\\",
|
||||
testLexicalClassification("\\\\\\\\",
|
||||
ts.EndOfLineState.InDoubleQuoteStringLiteral,
|
||||
stringLiteral("\\\\\\\\"),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
});
|
||||
|
||||
it("correctly classifies the last line of a multi-line string", function () {
|
||||
test("'",
|
||||
testLexicalClassification("'",
|
||||
ts.EndOfLineState.InSingleQuoteStringLiteral,
|
||||
stringLiteral("'"),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
});
|
||||
|
||||
it("correctly classifies an unterminated multiline comment", function () {
|
||||
test("/*",
|
||||
testLexicalClassification("/*",
|
||||
ts.EndOfLineState.Start,
|
||||
comment("/*"),
|
||||
finalEndOfLineState(ts.EndOfLineState.InMultiLineCommentTrivia));
|
||||
});
|
||||
|
||||
it("correctly classifies the termination of a multiline comment", function () {
|
||||
test(" */ ",
|
||||
testLexicalClassification(" */ ",
|
||||
ts.EndOfLineState.InMultiLineCommentTrivia,
|
||||
comment(" */"),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
});
|
||||
|
||||
it("correctly classifies the continuation of a multiline comment", function () {
|
||||
test("LOREM IPSUM DOLOR ",
|
||||
testLexicalClassification("LOREM IPSUM DOLOR ",
|
||||
ts.EndOfLineState.InMultiLineCommentTrivia,
|
||||
comment("LOREM IPSUM DOLOR "),
|
||||
finalEndOfLineState(ts.EndOfLineState.InMultiLineCommentTrivia));
|
||||
});
|
||||
|
||||
it("correctly classifies an unterminated multiline comment on a line ending in '/*/'", function () {
|
||||
test(" /*/",
|
||||
testLexicalClassification(" /*/",
|
||||
ts.EndOfLineState.Start,
|
||||
comment("/*/"),
|
||||
finalEndOfLineState(ts.EndOfLineState.InMultiLineCommentTrivia));
|
||||
});
|
||||
|
||||
it("correctly classifies an unterminated multiline comment with trailing space", function () {
|
||||
test("/* ",
|
||||
testLexicalClassification("/* ",
|
||||
ts.EndOfLineState.Start,
|
||||
comment("/* "),
|
||||
finalEndOfLineState(ts.EndOfLineState.InMultiLineCommentTrivia));
|
||||
});
|
||||
|
||||
it("correctly classifies a keyword after a dot", function () {
|
||||
test("a.var",
|
||||
testLexicalClassification("a.var",
|
||||
ts.EndOfLineState.Start,
|
||||
identifier("var"));
|
||||
});
|
||||
|
||||
it("correctly classifies a string literal after a dot", function () {
|
||||
test("a.\"var\"",
|
||||
testLexicalClassification("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",
|
||||
testLexicalClassification("a./*hello world*/ var",
|
||||
ts.EndOfLineState.Start,
|
||||
identifier("a"),
|
||||
punctuation("."),
|
||||
@@ -264,27 +264,27 @@ describe('Colorization', function () {
|
||||
});
|
||||
|
||||
it("classifies a property access with whitespace around the dot", function () {
|
||||
test(" x .\tfoo ()",
|
||||
testLexicalClassification(" x .\tfoo ()",
|
||||
ts.EndOfLineState.Start,
|
||||
identifier("x"),
|
||||
identifier("foo"));
|
||||
});
|
||||
|
||||
it("classifies a keyword after a dot on previous line", function () {
|
||||
test("var",
|
||||
testLexicalClassification("var",
|
||||
ts.EndOfLineState.Start,
|
||||
keyword("var"),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
});
|
||||
|
||||
it("classifies multiple keywords properly", function () {
|
||||
test("public static",
|
||||
testLexicalClassification("public static",
|
||||
ts.EndOfLineState.Start,
|
||||
keyword("public"),
|
||||
keyword("static"),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
|
||||
test("public var",
|
||||
testLexicalClassification("public var",
|
||||
ts.EndOfLineState.Start,
|
||||
keyword("public"),
|
||||
identifier("var"),
|
||||
@@ -292,7 +292,7 @@ describe('Colorization', function () {
|
||||
});
|
||||
|
||||
it("classifies partially written generics correctly.", function () {
|
||||
test("Foo<number",
|
||||
testLexicalClassification("Foo<number",
|
||||
ts.EndOfLineState.Start,
|
||||
identifier("Foo"),
|
||||
operator("<"),
|
||||
@@ -300,14 +300,14 @@ describe('Colorization', function () {
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
|
||||
// Looks like a cast, should get classified as a keyword.
|
||||
test("<number",
|
||||
testLexicalClassification("<number",
|
||||
ts.EndOfLineState.Start,
|
||||
operator("<"),
|
||||
keyword("number"),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
|
||||
// handle nesting properly.
|
||||
test("Foo<Foo,Foo<number",
|
||||
testLexicalClassification("Foo<Foo,Foo<number",
|
||||
ts.EndOfLineState.Start,
|
||||
identifier("Foo"),
|
||||
operator("<"),
|
||||
@@ -319,19 +319,11 @@ describe('Colorization', function () {
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
});
|
||||
|
||||
it("ClassifiesConflictTokens", () => {
|
||||
// no longer in something that looks generic.
|
||||
test("Foo<Foo> number",
|
||||
ts.EndOfLineState.Start,
|
||||
identifier("Foo"),
|
||||
operator("<"),
|
||||
identifier("Foo"),
|
||||
operator(">"),
|
||||
keyword("number"),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
it("LexicallyClassifiesConflictTokens", () => {
|
||||
debugger;
|
||||
|
||||
// Test conflict markers.
|
||||
test(
|
||||
testLexicalClassification(
|
||||
"class C {\r\n\
|
||||
<<<<<<< HEAD\r\n\
|
||||
v = 1;\r\n\
|
||||
@@ -348,14 +340,26 @@ describe('Colorization', function () {
|
||||
operator("="),
|
||||
numberLiteral("1"),
|
||||
punctuation(";"),
|
||||
comment("======="),
|
||||
identifier("v"),
|
||||
operator("="),
|
||||
numberLiteral("2"),
|
||||
punctuation(";"),
|
||||
comment("=======\r\n v = 2;\r\n"),
|
||||
comment(">>>>>>> Branch - a"),
|
||||
punctuation("}"),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
|
||||
testLexicalClassification(
|
||||
"<<<<<<< HEAD\r\n\
|
||||
class C { }\r\n\
|
||||
=======\r\n\
|
||||
class D { }\r\n\
|
||||
>>>>>>> Branch - a\r\n",
|
||||
ts.EndOfLineState.Start,
|
||||
comment("<<<<<<< HEAD"),
|
||||
keyword("class"),
|
||||
identifier("C"),
|
||||
punctuation("{"),
|
||||
punctuation("}"),
|
||||
comment("=======\r\nclass D { }\r\n"),
|
||||
comment(">>>>>>> Branch - a"),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user