1 module dls.tools.format_tool;
2 
3 import dfmt.config : BraceStyle, TemplateConstraintStyle;
4 import dfmt.editorconfig : EOL;
5 import dls.tools.configuration : Configuration;
6 import dls.tools.tool : Tool;
7 
8 private immutable EOL[Configuration.FormatConfiguration.EndOfLine] eolMap;
9 private immutable BraceStyle[Configuration.FormatConfiguration.BraceStyle] braceStyleMap;
10 private immutable TemplateConstraintStyle[Configuration.FormatConfiguration.TemplateConstraintStyle] templateConstraintStyleMap;
11 
12 shared static this()
13 {
14     //dfmt off
15     eolMap = [
16         Configuration.FormatConfiguration.EndOfLine.lf   : EOL.lf,
17         Configuration.FormatConfiguration.EndOfLine.cr   : EOL.cr,
18         Configuration.FormatConfiguration.EndOfLine.crlf : EOL.crlf
19     ];
20 
21     braceStyleMap = [
22         Configuration.FormatConfiguration.BraceStyle.allman     : BraceStyle.allman,
23         Configuration.FormatConfiguration.BraceStyle.otbs       : BraceStyle.otbs,
24         Configuration.FormatConfiguration.BraceStyle.stroustrup : BraceStyle.stroustrup
25     ];
26 
27     templateConstraintStyleMap = [
28         Configuration.FormatConfiguration.TemplateConstraintStyle.conditionalNewlineIndent : TemplateConstraintStyle.conditional_newline_indent,
29         Configuration.FormatConfiguration.TemplateConstraintStyle.conditionalNewline       : TemplateConstraintStyle.conditional_newline,
30         Configuration.FormatConfiguration.TemplateConstraintStyle.alwaysNewline            : TemplateConstraintStyle.always_newline,
31         Configuration.FormatConfiguration.TemplateConstraintStyle.alwaysNewlineIndent      : TemplateConstraintStyle.always_newline_indent
32     ];
33     //dfmt on
34 }
35 
36 class FormatTool : Tool
37 {
38     import dls.protocol.definitions : TextEdit;
39     import dls.protocol.interfaces : FormattingOptions;
40     import dls.util.uri : Uri;
41 
42     TextEdit[] formatting(Uri uri, FormattingOptions options)
43     {
44         import dfmt.config : Config;
45         import dfmt.editorconfig : IndentStyle, OptionalBoolean;
46         import dfmt.formatter : format;
47         import dls.protocol.definitions : Position, Range;
48         import dls.util.document : Document;
49         import std.outbuffer : OutBuffer;
50 
51         const document = Document[uri];
52         auto contents = cast(ubyte[]) document.toString();
53         auto config = Config();
54 
55         OptionalBoolean toOptBool(bool b)
56         {
57             return b ? OptionalBoolean.t : OptionalBoolean.f;
58         }
59 
60         config.initializeWithDefaults();
61         config.end_of_line = eolMap[_configuration.format.endOfLine];
62         config.indent_style = options.insertSpaces ? IndentStyle.space : IndentStyle.tab;
63         config.indent_size = cast(typeof(config.indent_size)) options.tabSize;
64         config.tab_width = config.indent_size;
65         config.max_line_length = _configuration.format.maxLineLength;
66         config.dfmt_align_switch_statements = toOptBool(
67                 _configuration.format.dfmtAlignSwitchStatements);
68         config.dfmt_brace_style = braceStyleMap[_configuration.format.dfmtBraceStyle];
69         config.dfmt_outdent_attributes = toOptBool(_configuration.format.dfmtOutdentAttributes);
70         config.dfmt_soft_max_line_length = _configuration.format.dfmtSoftMaxLineLength;
71         config.dfmt_space_after_cast = toOptBool(_configuration.format.dfmtSpaceAfterCast);
72         config.dfmt_space_after_keywords = toOptBool(_configuration.format.dfmtSpaceAfterKeywords);
73         config.dfmt_space_before_function_parameters = toOptBool(
74                 _configuration.format.dfmtSpaceBeforeFunctionParameters);
75         config.dfmt_split_operator_at_line_end = toOptBool(
76                 _configuration.format.dfmtSplitOperatorAtLineEnd);
77         config.dfmt_selective_import_space = toOptBool(
78                 _configuration.format.dfmtSelectiveImportSpace);
79         config.dfmt_compact_labeled_statements = _configuration.format.dfmtCompactLabeledStatements
80             ? OptionalBoolean.t : OptionalBoolean.f;
81         config.dfmt_template_constraint_style
82             = templateConstraintStyleMap[_configuration.format.dfmtTemplateConstraintStyle];
83         config.dfmt_single_template_constraint_indent = toOptBool(
84                 _configuration.format.dfmtSingleTemplateConstraintIndent);
85 
86         auto buffer = new OutBuffer();
87         format(uri, contents, buffer, &config);
88         auto range = new Range(new Position(0, 0),
89                 new Position(document.lines.length, document.lines[$ - 1].length));
90         return [new TextEdit(range, buffer.toString())];
91     }
92 }