xref: /libCEED/julia/LibCEED.jl/.style/ceed_style.jl (revision 60801d19602b94955220fc3cc63a65b52bc34d1e)
1ee83402cSWill Paznerusing JuliaFormatter, CSTParser, Tokenize
2ee83402cSWill Pazner
3ee83402cSWill Paznerfor name in names(JuliaFormatter, all=true)
4bf185410SWill Pazner    if name != :include && name != :eval && name != Base.Docs.META
5*cdf95791SWill Pazner        @eval using JuliaFormatter: $name
6ee83402cSWill Pazner    end
7ee83402cSWill Paznerend
8ee83402cSWill Pazner
9ee83402cSWill Pazner# Same as DefaultStyle, but no space in between operators with precedence CSTParser.TimesOp
10ee83402cSWill Paznerstruct CeedStyle <: AbstractStyle end
11*cdf95791SWill Pazner@inline JuliaFormatter.getstyle(s::CeedStyle) = s
12ee83402cSWill Pazner
13*cdf95791SWill Paznerfunction JuliaFormatter.p_binaryopcall(
14*cdf95791SWill Pazner    ds::CeedStyle,
15ee83402cSWill Pazner    cst::CSTParser.EXPR,
16ee83402cSWill Pazner    s::State;
17ee83402cSWill Pazner    nonest=false,
18ee83402cSWill Pazner    nospace=false,
19ee83402cSWill Pazner)
20*cdf95791SWill Pazner    style = getstyle(ds)
21*cdf95791SWill Pazner    t = FST(Binary, cst, nspaces(s))
22ee83402cSWill Pazner    op = cst[2]
23*cdf95791SWill Pazner
24*cdf95791SWill Pazner    nonest = nonest || CSTParser.is_colon(op)
25*cdf95791SWill Pazner
26*cdf95791SWill Pazner    if CSTParser.iscurly(cst.parent) &&
27*cdf95791SWill Pazner       (op.val == "<:" || op.val == ">:") &&
28ee83402cSWill Pazner       !s.opts.whitespace_typedefs
29ee83402cSWill Pazner        nospace = true
30*cdf95791SWill Pazner    elseif CSTParser.is_colon(op)
31ee83402cSWill Pazner        nospace = true
32ee83402cSWill Pazner    end
33ee83402cSWill Pazner    nospace_args = s.opts.whitespace_ops_in_indices ? false : nospace
34ee83402cSWill Pazner
35ee83402cSWill Pazner    if is_opcall(cst[1])
36ee83402cSWill Pazner        n = pretty(style, cst[1], s, nonest=nonest, nospace=nospace_args)
37ee83402cSWill Pazner    else
38ee83402cSWill Pazner        n = pretty(style, cst[1], s)
39ee83402cSWill Pazner    end
40ee83402cSWill Pazner
41*cdf95791SWill Pazner    if CSTParser.is_colon(op) &&
42ee83402cSWill Pazner       s.opts.whitespace_ops_in_indices &&
43ee83402cSWill Pazner       !is_leaf(cst[1]) &&
44ee83402cSWill Pazner       !is_iterable(cst[1])
45*cdf95791SWill Pazner        paren = FST(PUNCTUATION, -1, n.startline, n.startline, "(")
46ee83402cSWill Pazner        add_node!(t, paren, s)
47ee83402cSWill Pazner        add_node!(t, n, s, join_lines=true)
48*cdf95791SWill Pazner        paren = FST(PUNCTUATION, -1, n.startline, n.startline, ")")
49ee83402cSWill Pazner        add_node!(t, paren, s, join_lines=true)
50ee83402cSWill Pazner    else
51ee83402cSWill Pazner        add_node!(t, n, s)
52ee83402cSWill Pazner    end
53ee83402cSWill Pazner
54ee83402cSWill Pazner    nrhs = nest_rhs(cst)
55ee83402cSWill Pazner    nrhs && (t.nest_behavior = AlwaysNest)
56*cdf95791SWill Pazner    nest = (is_binaryop_nestable(style, cst) && !nonest) || nrhs
57ee83402cSWill Pazner
58ee83402cSWill Pazner    if op.fullspan == 0
59ee83402cSWill Pazner        # Do nothing - represents a binary op with no textual representation.
60ee83402cSWill Pazner        # For example: `2a`, which is equivalent to `2 * a`.
61*cdf95791SWill Pazner    elseif CSTParser.is_exor(op)
62ee83402cSWill Pazner        add_node!(t, pretty(style, op, s), s, join_lines=true)
63*cdf95791SWill Pazner    elseif (CSTParser.isnumber(cst[1]) || is_circumflex_accent(op)) &&
64*cdf95791SWill Pazner           CSTParser.isdotted(op)
65ee83402cSWill Pazner        add_node!(t, Whitespace(1), s)
66ee83402cSWill Pazner        add_node!(t, pretty(style, op, s), s, join_lines=true)
67ee83402cSWill Pazner        nest ? add_node!(t, Placeholder(1), s) : add_node!(t, Whitespace(1), s)
68*cdf95791SWill Pazner    elseif !(CSTParser.is_in(op) || CSTParser.is_elof(op)) && (
69ee83402cSWill Pazner        nospace || (
70*cdf95791SWill Pazner            !CSTParser.is_anon_func(op) && precedence(op) in (
71ee83402cSWill Pazner                CSTParser.PowerOp,
72ee83402cSWill Pazner                CSTParser.DeclarationOp,
73ee83402cSWill Pazner                CSTParser.DotOp,
74ee83402cSWill Pazner                CSTParser.TimesOp,
75ee83402cSWill Pazner            )
76ee83402cSWill Pazner        )
77ee83402cSWill Pazner    )
78ee83402cSWill Pazner        add_node!(t, pretty(style, op, s), s, join_lines=true)
79*cdf95791SWill Pazner    elseif op.val in RADICAL_OPS
80*cdf95791SWill Pazner        add_node!(t, pretty(style, op, s), s, join_lines=true)
81ee83402cSWill Pazner    else
82ee83402cSWill Pazner        add_node!(t, Whitespace(1), s)
83ee83402cSWill Pazner        add_node!(t, pretty(style, op, s), s, join_lines=true)
84ee83402cSWill Pazner        nest ? add_node!(t, Placeholder(1), s) : add_node!(t, Whitespace(1), s)
85ee83402cSWill Pazner    end
86ee83402cSWill Pazner
87ee83402cSWill Pazner    if is_opcall(cst[3])
88ee83402cSWill Pazner        n = pretty(style, cst[3], s, nonest=nonest, nospace=nospace_args)
89ee83402cSWill Pazner    else
90ee83402cSWill Pazner        n = pretty(style, cst[3], s)
91ee83402cSWill Pazner    end
92ee83402cSWill Pazner
93*cdf95791SWill Pazner    if CSTParser.is_colon(op) &&
94ee83402cSWill Pazner       s.opts.whitespace_ops_in_indices &&
95ee83402cSWill Pazner       !is_leaf(cst[3]) &&
96ee83402cSWill Pazner       !is_iterable(cst[3])
97*cdf95791SWill Pazner        paren = FST(PUNCTUATION, -1, n.startline, n.startline, "(")
98ee83402cSWill Pazner        add_node!(t, paren, s, join_lines=true)
99*cdf95791SWill Pazner        add_node!(t, n, s, join_lines=true, override_join_lines_based_on_source=!nest)
100*cdf95791SWill Pazner        paren = FST(PUNCTUATION, -1, n.startline, n.startline, ")")
101ee83402cSWill Pazner        add_node!(t, paren, s, join_lines=true)
102ee83402cSWill Pazner    else
103*cdf95791SWill Pazner        add_node!(t, n, s, join_lines=true, override_join_lines_based_on_source=!nest)
104ee83402cSWill Pazner    end
105ee83402cSWill Pazner
106ee83402cSWill Pazner    if nest
107ee83402cSWill Pazner        # for indent, will be converted to `indent` if needed
108ee83402cSWill Pazner        insert!(t.nodes, length(t.nodes), Placeholder(0))
109ee83402cSWill Pazner    end
110ee83402cSWill Pazner
111ee83402cSWill Pazner    t
112ee83402cSWill Paznerend
113ee83402cSWill Pazner
114*cdf95791SWill Paznerfunction JuliaFormatter.p_chainopcall(
115*cdf95791SWill Pazner    ds::CeedStyle,
116ee83402cSWill Pazner    cst::CSTParser.EXPR,
117ee83402cSWill Pazner    s::State;
118ee83402cSWill Pazner    nonest=false,
119ee83402cSWill Pazner    nospace=false,
120ee83402cSWill Pazner)
121*cdf95791SWill Pazner    style = getstyle(ds)
122*cdf95791SWill Pazner    t = FST(Chain, cst, nspaces(s))
123ee83402cSWill Pazner
124ee83402cSWill Pazner    # Check if there's a number literal on the LHS of a dot operator.
125ee83402cSWill Pazner    # In this case we need to surround the dot operator with whitespace
126ee83402cSWill Pazner    # in order to avoid ambiguity.
127ee83402cSWill Pazner    for (i, a) in enumerate(cst)
128*cdf95791SWill Pazner        if CSTParser.isoperator(a) && CSTParser.isdotted(a) && CSTParser.isnumber(cst[i-1])
129ee83402cSWill Pazner            nospace = false
130ee83402cSWill Pazner            break
131ee83402cSWill Pazner        end
132ee83402cSWill Pazner    end
133ee83402cSWill Pazner
134ee83402cSWill Pazner    nws = nospace ? 0 : 1
135ee83402cSWill Pazner    for (i, a) in enumerate(cst)
136*cdf95791SWill Pazner        nws_op = precedence(a) == CSTParser.TimesOp ? 0 : nws
137*cdf95791SWill Pazner        if CSTParser.isoperator(a)
138ee83402cSWill Pazner            add_node!(t, Whitespace(nws_op), s)
139ee83402cSWill Pazner            add_node!(t, pretty(style, a, s), s, join_lines=true)
140ee83402cSWill Pazner            if nonest
141ee83402cSWill Pazner                add_node!(t, Whitespace(nws_op), s)
142ee83402cSWill Pazner            else
143ee83402cSWill Pazner                add_node!(t, Placeholder(nws_op), s)
144ee83402cSWill Pazner            end
145ee83402cSWill Pazner        elseif is_opcall(a)
146ee83402cSWill Pazner            add_node!(
147ee83402cSWill Pazner                t,
148ee83402cSWill Pazner                pretty(style, a, s, nospace=nospace, nonest=nonest),
149ee83402cSWill Pazner                s,
150ee83402cSWill Pazner                join_lines=true,
151ee83402cSWill Pazner            )
152ee83402cSWill Pazner        elseif i == length(cst) - 1 && is_punc(a) && is_punc(cst[i+1])
153ee83402cSWill Pazner            add_node!(t, pretty(style, a, s), s, join_lines=true)
154ee83402cSWill Pazner        else
155ee83402cSWill Pazner            add_node!(t, pretty(style, a, s), s, join_lines=true)
156ee83402cSWill Pazner        end
157ee83402cSWill Pazner    end
158ee83402cSWill Pazner    t
159ee83402cSWill Paznerend
160ee83402cSWill Pazner
161ee83402cSWill Paznerprefix_path(fname) = joinpath(@__DIR__, "..", fname)
162ee83402cSWill Paznerformat(
163ee83402cSWill Pazner    prefix_path.(["src", "test", "examples", ".style"]),
164ee83402cSWill Pazner    style=CeedStyle(),
165ee83402cSWill Pazner    indent=4,
166ee83402cSWill Pazner    margin=92,
167ee83402cSWill Pazner    remove_extra_newlines=true,
168ee83402cSWill Pazner    whitespace_in_kwargs=false,
169ee83402cSWill Pazner)
170