Fix semicolon removal before comments

This commit is contained in:
Andrew Branch
2019-09-11 14:19:12 -07:00
parent e27bc9646a
commit ae9a234de0
4 changed files with 78 additions and 59 deletions
+61 -57
View File
@@ -317,63 +317,6 @@ namespace ts.formatting {
rule("OptionalSemicolon", anyToken, anyTokenIncludingEOF, [isOptionEnabled("insertTrailingSemicolon"), isSemicolonInsertionContext], RuleAction.TrailingSemicolon),
];
function isSemicolonDeletionContext(context: FormattingContext): boolean {
if (context.TokensAreOnSameLine()) {
return context.nextTokenSpan.kind === SyntaxKind.CloseBraceToken
|| context.nextTokenSpan.kind === SyntaxKind.EndOfFileToken;
}
if (context.nextTokenSpan.kind === SyntaxKind.SemicolonClassElement ||
context.nextTokenSpan.kind === SyntaxKind.SemicolonToken
) {
return false;
}
if (context.contextNode.kind === SyntaxKind.InterfaceDeclaration ||
context.contextNode.kind === SyntaxKind.TypeAliasDeclaration
) {
// Can’t remove semicolon after `foo`; it would parse as a
// method declaration:
// interface I {
// foo;
// (): void
// }
return !(isPropertySignature(context.currentTokenParent)
&& !context.currentTokenParent.type
&& context.nextTokenSpan.kind === SyntaxKind.OpenParenToken);
}
if (isPropertyDeclaration(context.currentTokenParent)) {
return !context.currentTokenParent.initializer;
}
return context.currentTokenParent.kind !== SyntaxKind.ForStatement
&& context.currentTokenParent.kind !== SyntaxKind.EmptyStatement
&& context.currentTokenParent.kind !== SyntaxKind.SemicolonClassElement
&& context.nextTokenSpan.kind !== SyntaxKind.OpenBracketToken
&& context.nextTokenSpan.kind !== SyntaxKind.OpenParenToken
&& context.nextTokenSpan.kind !== SyntaxKind.PlusToken
&& context.nextTokenSpan.kind !== SyntaxKind.MinusToken
&& context.nextTokenSpan.kind !== SyntaxKind.SlashToken
&& context.nextTokenSpan.kind !== SyntaxKind.RegularExpressionLiteral
&& context.nextTokenSpan.kind !== SyntaxKind.CommaToken
&& context.nextTokenSpan.kind !== SyntaxKind.TemplateExpression
&& context.nextTokenSpan.kind !== SyntaxKind.TemplateHead
&& context.nextTokenSpan.kind !== SyntaxKind.NoSubstitutionTemplateLiteral
&& context.nextTokenSpan.kind !== SyntaxKind.DotToken;
}
function isSemicolonInsertionContext(context: FormattingContext): boolean {
const contextAncestor = findAncestor(context.currentTokenParent, ancestor => {
if (ancestor.end !== context.currentTokenSpan.end) {
return "quit";
}
return syntaxMayBeASICandidate(ancestor.kind);
});
return !!contextAncestor && isASICandidate(contextAncestor);
}
// These rules are lower in priority than user-configurable. Rules earlier in this list have priority over rules later in the list.
const lowPriorityCommonRules = [
// Space after keyword but not before ; or : or ?
@@ -833,4 +776,65 @@ namespace ts.formatting {
function isNonNullAssertionContext(context: FormattingContext): boolean {
return context.contextNode.kind === SyntaxKind.NonNullExpression;
}
function isSemicolonDeletionContext(context: FormattingContext): boolean {
if (context.TokensAreOnSameLine()) {
return context.nextTokenSpan.kind === SyntaxKind.CloseBraceToken
|| context.nextTokenSpan.kind === SyntaxKind.EndOfFileToken;
}
const nextToken = isTrivia(context.nextTokenSpan.kind)
? context.nextTokenParent.getChildAt(0)
: context.nextTokenSpan;
if (nextToken.kind === SyntaxKind.SemicolonClassElement ||
nextToken.kind === SyntaxKind.SemicolonToken
) {
return false;
}
if (context.contextNode.kind === SyntaxKind.InterfaceDeclaration ||
context.contextNode.kind === SyntaxKind.TypeAliasDeclaration
) {
// Can’t remove semicolon after `foo`; it would parse as a method declaration:
//
// interface I {
// foo;
// (): void
// }
return !(isPropertySignature(context.currentTokenParent)
&& !context.currentTokenParent.type
&& nextToken.kind === SyntaxKind.OpenParenToken);
}
if (isPropertyDeclaration(context.currentTokenParent)) {
return !context.currentTokenParent.initializer;
}
return context.currentTokenParent.kind !== SyntaxKind.ForStatement
&& context.currentTokenParent.kind !== SyntaxKind.EmptyStatement
&& context.currentTokenParent.kind !== SyntaxKind.SemicolonClassElement
&& nextToken.kind !== SyntaxKind.OpenBracketToken
&& nextToken.kind !== SyntaxKind.OpenParenToken
&& nextToken.kind !== SyntaxKind.PlusToken
&& nextToken.kind !== SyntaxKind.MinusToken
&& nextToken.kind !== SyntaxKind.SlashToken
&& nextToken.kind !== SyntaxKind.RegularExpressionLiteral
&& nextToken.kind !== SyntaxKind.CommaToken
&& nextToken.kind !== SyntaxKind.TemplateExpression
&& nextToken.kind !== SyntaxKind.TemplateHead
&& nextToken.kind !== SyntaxKind.NoSubstitutionTemplateLiteral
&& nextToken.kind !== SyntaxKind.DotToken;
}
function isSemicolonInsertionContext(context: FormattingContext): boolean {
const contextAncestor = findAncestor(context.currentTokenParent, ancestor => {
if (ancestor.end !== context.currentTokenSpan.end) {
return "quit";
}
return syntaxMayBeASICandidate(ancestor.kind);
});
return !!contextAncestor && isASICandidate(contextAncestor);
}
}
+1 -1
View File
@@ -16,7 +16,7 @@ namespace ts.formatting {
function getRuleActionExclusion(ruleAction: RuleAction): RuleAction {
let mask: RuleAction = 0;
if (ruleAction & RuleAction.Ignore) {
return -1;
mask |= RuleAction.TriviaAction;
}
if (ruleAction & RuleAction.TriviaAction) {
mask |= RuleAction.TriviaAction;
+1 -1
View File
@@ -758,7 +758,7 @@ namespace ts {
insertSpaceBeforeFunctionParenthesis: false,
placeOpenBraceOnNewLineForFunctions: false,
placeOpenBraceOnNewLineForControlBlocks: false,
// insertTrailingSemicolon: true,
// insertTrailingSemicolon: false,
};
}
@@ -0,0 +1,15 @@
/// <reference path="fourslash.ts" />
////interface I {
//// a: string;
//// /** @internal */
//// b: string;
////}
format.setFormatOptions({ ...format.copyFormatOptions(), insertTrailingSemicolon: false });
format.document();
verify.currentFileContentIs(`interface I {
a: string
/** @internal */
b: string
}`);