in ReSharper.FSharp/src/FSharp/FSharp.Psi/src/CodeFormatter/FSharpCodeFormatterInfoProvider.cs [1223:1293]
private void DescribeLineBreakInDeclarationWithEquals(string name,
IBuilderAction<IBlankWithSinglePattern> declarationPattern,
ChildBuilder<IBlankWithSinglePattern, NodePatternBlank> afterEqualsNodesPattern) =>
DescribeLineBreakInNode(name, declarationPattern, afterEqualsNodesPattern.Satisfies((node, _) =>
node.GetPreviousMeaningfulSibling().GetTokenType() == FSharpTokenType.EQUALS),
// Uncomment this line to take END_OF_LINE/NEXT_LINE brace style into account
// Don't forget to change
// .FormatBeforeLBrace(false)
// to
// .FormatBeforeLBrace(false, formatBeforeLBraceUnlessSingleLine: true)
// node.GetPreviousMeaningfulSibling().GetTokenType() == FSharpTokenType.EQUALS && node.FirstChild.NodeType != FSharpTokenType.LBRACE),
key => key.DeclarationBodyOnTheSameLine, key => key.KeepExistingLineBreakBeforeDeclarationBody);
private void DescribeLineBreakInNode(string name,
IBuilderAction<IBlankWithSinglePattern> containingNodesPattern,
IBuilderAction<IBlankWithSinglePattern> afterEqualsNodesPattern,
Expression<Func<FSharpFormatSettingsKey, object>> onSameLine,
Expression<Func<FSharpFormatSettingsKey, object>> keepExistingLineBreak)
{
var containingNodes = containingNodesPattern.BuildBlank();
var equalsBeforeNodes = afterEqualsNodesPattern.BuildBlank();
Describe<WrapRule>()
.Name($"{name}Wrap")
.Where(Node().Is(containingNodes))
.Switch(keepExistingLineBreak,
When(false).Switch(onSameLine,
When(PlaceOnSameLineAsOwner.IF_OWNER_IS_SINGLE_LINE)
.Return(WrapType.Chop | WrapType.PseudoStartBeforeExternal)))
.Build();
Describe<FormattingRule>()
.Name($"{name}NewLine")
.Where(
Parent().Is(containingNodes),
Right().Is(equalsBeforeNodes))
.Group(LineBreaksRuleGroup | WrapRuleGroup)
.Switch(keepExistingLineBreak,
When(true)
.Switch(onSameLine,
When(PlaceOnSameLineAsOwner.NEVER).Return(IntervalFormatType.NewLine),
When(PlaceOnSameLineAsOwner.ALWAYS, PlaceOnSameLineAsOwner.IF_OWNER_IS_SINGLE_LINE)
.Return(IntervalFormatType.DoNotRemoveUserNewLines)),
When(false)
.Switch(onSameLine,
When(PlaceOnSameLineAsOwner.NEVER).Return(IntervalFormatType.NewLine),
When(PlaceOnSameLineAsOwner.ALWAYS).Return(IntervalFormatType.RemoveUserNewLines),
When(PlaceOnSameLineAsOwner.IF_OWNER_IS_SINGLE_LINE)
.Return(IntervalFormatType.RemoveUserNewLines | IntervalFormatType.InsertNewLineConditionally)))
.Build();
// initial impl (keeps formatting instead of keeping existing line break only):
// .Switch(keepExistingLineBreak,
// When(true).Return(IntervalFormatType.DoNotRemoveUserNewLines),
// When(false)
// .Switch(onSameLine,
// When(PlaceOnSameLineAsOwner.NEVER).Return(IntervalFormatType.NewLine),
// When(PlaceOnSameLineAsOwner.ALWAYS).Return(IntervalFormatType.RemoveUserNewLines),
// When(PlaceOnSameLineAsOwner.IF_OWNER_IS_SINGLE_LINE)
// .Return(IntervalFormatType.RemoveUserNewLines | IntervalFormatType.InsertNewLineConditionally)))
Describe<FormattingRule>()
.Name($"{name}Space")
.Where(
Parent().Is(containingNodes),
Right().Is(equalsBeforeNodes))
.Group(SpaceRuleGroup)
.Return(IntervalFormatType.Space)
.Priority(3)
.Build();
}