in ReSharper.FSharp/src/FSharp/FSharp.Psi/src/CodeFormatter/FSharpCodeFormatterInfoProvider.cs [1102:1210]
private void DescribeEmptyOnlyFormatting(IBuilderAction<IBlankWithSinglePattern> parent, NodeType left,
NodeType right) =>
Describe<FormattingRule>()
.Name("SpaceInLists")
.Group(SpaceRuleGroup)
.Where(parent, Left().In(left), Right().In(right))
.Return(IntervalFormatType.OnlyEmpty)
.Build();
private void DescribeEmptyOnlyFormatting(NodeType parent, NodeType left, NodeType right) =>
DescribeEmptyOnlyFormatting(Parent().In(parent), left, right);
private void BlankLines()
{
var declarations =
ElementBitsets.MODULE_MEMBER_BIT_SET
.Union(ElementBitsets.BINDING_BIT_SET)
.Union(ElementBitsets.ENUM_CASE_LIKE_DECLARATION_BIT_SET)
.Union(ElementType.F_SHARP_TYPE_DECLARATION)
.Union(ElementBitsets.MODULE_MEMBER_BIT_SET)
.Union(ElementBitsets.F_SHARP_TYPE_MEMBER_DECLARATION_BIT_SET)
.Union(ElementBitsets.TYPE_REPRESENTATION_BIT_SET);
var noBlankLineAfterNodeTypes =
new NodeTypeSet(
FSharpTokenType.EQUALS,
FSharpTokenType.IDENTIFIER,
FSharpTokenType.CLASS,
FSharpTokenType.INTERFACE,
FSharpTokenType.STRUCT,
FSharpTokenType.WITH,
FSharpTokenType.PRIVATE,
FSharpTokenType.INTERNAL,
FSharpTokenType.PUBLIC
);
var noBlankLineBeforeNodeTypes =
ElementBitsets.TYPE_REPRESENTATION_BIT_SET
.Union(
FSharpTokenType.RBRACE
);
// todo: group member kinds, check same group instead
bool AllowsNoBlankLine(NodeType nodeType, NodeType nextNodeType)
{
return nodeType == ElementType.LET_BINDINGS_DECLARATION && nextNodeType == ElementType.EXPRESSION_STATEMENT ||
nodeType == ElementType.EXPRESSION_STATEMENT&& nextNodeType == ElementType.LET_BINDINGS_DECLARATION ||
nodeType == ElementType.ABSTRACT_MEMBER_DECLARATION && nextNodeType == ElementType.MEMBER_DECLARATION;
}
Describe<BlankLinesAroundNodeRule>()
.AddNodesToGroupBefore(Node().In(Comments))
.AddNodesToGroupAfter(Node().In(Comments))
.AllowedNodesBefore(Node().Satisfies((node, _) => !noBlankLineAfterNodeTypes[node.NodeType]))
.AllowedNodesAfter(Node().Satisfies((node, _) => !noBlankLineBeforeNodeTypes[node.NodeType]))
.Priority(1)
.StartAlternating()
.Name("BlankLinesAroundDeclarations")
.Where(Node().In(declarations))
.MinBlankLines(it => it.BlankLinesAroundMultilineModuleMembers)
.MinBlankLinesForSingleLine(it => it.BlankLinesAroundSingleLineModuleMember)
.Build()
.Name("BlankLinesAroundDifferentModuleMemberKinds")
.Where(Node().In(declarations))
.MinBlankLines(it => it.BlankLinesAroundDifferentModuleMemberKinds)
.AdditionalCheckForBlankLineAfter((node, _) =>
node.GetNextMeaningfulSibling().NodeType is var nextNodeType &&
nextNodeType != node.NodeType &&
!AllowsNoBlankLine(node.NodeType, nextNodeType) &&
declarations[nextNodeType])
.AdditionalCheckForBlankLineBefore((node, _) =>
node.GetPreviousMeaningfulSibling().NodeType is var prevNodeType &&
!AllowsNoBlankLine(prevNodeType, node.NodeType) &&
prevNodeType != node.NodeType && declarations[prevNodeType])
.Build()
.AllowedNodesBefore(Node().Satisfies((_, _) => true))
.Name("BlankLinesBeforeFirstTopLevelModuleMember")
.Where(
Parent().In(ElementBitsets.TOP_LEVEL_MODULE_LIKE_DECLARATION_BIT_SET),
Node().In(ElementBitsets.MODULE_MEMBER_BIT_SET)
.Satisfies(IsFirstNodeOfTypeSet(ElementBitsets.MODULE_MEMBER_BIT_SET, false)))
.MinBlankLinesBefore(it => it.BlankLinesBeforeFirstModuleMemberInTopLevelModule)
.Build()
.AllowedNodesBefore(Node().Satisfies((_, _) => true))
.Name("BlankLinesBeforeFirstNestedModuleMember")
.Where(
Parent().In(ElementType.NESTED_MODULE_DECLARATION),
Node().In(ElementBitsets.MODULE_MEMBER_BIT_SET)
.Satisfies(IsFirstNodeOfTypeSet(ElementBitsets.MODULE_MEMBER_BIT_SET, false)))
.MinBlankLinesBefore(it => it.BlankLinesBeforeFirstModuleMemberInNestedModule)
.Build()
.Name("BlankLinesAroundModules")
.Where(Node().In(ElementBitsets.TOP_LEVEL_MODULE_LIKE_DECLARATION_BIT_SET))
.MinBlankLines(it => it.BlankLineAroundTopLevelModules)
.Build();
// todo: test sig files
Describe<BlankLinesRule>()
.Name("BlankLinesInDecls")
.Group(MaxLineBreaks)
.Where(Parent().In(ElementBitsets.MODULE_LIKE_DECLARATION_BIT_SET.Union(ElementBitsets.F_SHARP_FILE_BIT_SET)))
.SwitchBlankLines(it => it.KeepMaxBlankLineAroundModuleMembers, true, BlankLineLimitKind.LimitMaximumMild)
.Build();
}