|
| 1 | +/* formatter.vala |
| 2 | + * |
| 3 | + * Copyright 2022 JCWasmx86 <[email protected]> |
| 4 | + * |
| 5 | + * This file is free software; you can redistribute it and/or modify it |
| 6 | + * under the terms of the GNU Lesser General Public License as |
| 7 | + * published by the Free Software Foundation; either version 3 of the |
| 8 | + * License, or (at your option) any later version. |
| 9 | + * |
| 10 | + * This file is distributed in the hope that it will be useful, but |
| 11 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 13 | + * Lesser General Public License for more details. |
| 14 | + * |
| 15 | + * You should have received a copy of the GNU Lesser General Public |
| 16 | + * License along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | + * |
| 18 | + * SPDX-License-Identifier: LGPL-3.0-or-later |
| 19 | + */ |
| 20 | + |
| 21 | +using Gee; |
| 22 | +using Lsp; |
| 23 | + |
| 24 | +errordomain FormattingError { |
| 25 | + FORMAT, |
| 26 | + READ |
| 27 | +} |
| 28 | + |
| 29 | +namespace Vls.Formatter { |
| 30 | + TextEdit format (FormattingOptions options, CodeStyleAnalyzer analyzed_style, Vala.SourceFile source, Cancellable? cancellable = null) throws FormattingError, Error { |
| 31 | + // SEARCH_PATH_FROM_ENVP does not seem to be available even in quite fast distros like Fedora 35, |
| 32 | + // so we have to use a SubprocessLauncher and call set_environ() |
| 33 | + var launcher = new SubprocessLauncher (SubprocessFlags.STDERR_PIPE | SubprocessFlags.STDOUT_PIPE | SubprocessFlags.STDIN_PIPE); |
| 34 | + launcher.set_environ (Environ.get ()); |
| 35 | + Subprocess subprocess = launcher.spawnv (get_uncrustify_args (source, options, analyzed_style)); |
| 36 | + string? stdout_buf = null, stderr_buf = null; |
| 37 | + subprocess.communicate_utf8 (source.content, cancellable, out stdout_buf, out stderr_buf); |
| 38 | + if (!subprocess.get_successful ()) { |
| 39 | + if (stderr_buf != null && stderr_buf.strip ().length > 0) { |
| 40 | + throw new FormattingError.FORMAT ("%s", stderr_buf); |
| 41 | + } else { |
| 42 | + throw new FormattingError.READ ("uncrustify failed with error code %d", subprocess.get_exit_status ()); |
| 43 | + } |
| 44 | + } |
| 45 | + int last_nl_pos; |
| 46 | + uint nl_count = Util.count_chars_in_string (source.content, '\n', out last_nl_pos); |
| 47 | + return new TextEdit () { |
| 48 | + range = new Range () { |
| 49 | + start = new Position () { |
| 50 | + line = 0, |
| 51 | + character = 0 |
| 52 | + }, |
| 53 | + end = new Position () { |
| 54 | + line = nl_count + 1, |
| 55 | + // handle trailing newline |
| 56 | + character = last_nl_pos == source.content.length - 1 ? 1 : 0 |
| 57 | + } |
| 58 | + }, |
| 59 | + newText = stdout_buf |
| 60 | + }; |
| 61 | + } |
| 62 | + |
| 63 | + string[] get_uncrustify_args (Vala.SourceFile source, FormattingOptions options, CodeStyleAnalyzer analyzed_style) { |
| 64 | + var conf = new HashMap<string, string> (); |
| 65 | + // https://github.com/uncrustify/uncrustify/blob/master/documentation/htdocs/default.cfg |
| 66 | + conf["indent_with_tabs"] = "%d".printf (options.insertSpaces ? 0 : 1); |
| 67 | + conf["nl_end_of_file"] = options.insertFinalNewline ? "force" : "remove"; |
| 68 | + conf["nl_end_of_file_min"] = "%d".printf (options.trimFinalNewlines ? 1 : 0); |
| 69 | + conf["output_tab_size"] = "%u".printf (options.tabSize); |
| 70 | + conf["indent_columns"] = "4"; |
| 71 | + conf["indent_align_string"] = "true"; |
| 72 | + conf["indent_xml_string"] = "4"; |
| 73 | + conf["indent_namespace"] = "true"; |
| 74 | + conf["indent_class"] = "true"; |
| 75 | + conf["indent_var_def_cont"] = "true"; |
| 76 | + conf["indent_func_def_param"] = "true"; |
| 77 | + conf["indent_func_proto_param"] = "true"; |
| 78 | + conf["indent_func_class_param"] = "true"; |
| 79 | + conf["indent_func_ctor_var_param"] = "true"; |
| 80 | + conf["indent_template_param"] = "true"; |
| 81 | + conf["indent_member"] = "1"; |
| 82 | + conf["indent_paren_close"] = "2"; |
| 83 | + conf["indent_align_assign"] = "false"; |
| 84 | + conf["indent_oc_block_msg_xcode_style"] = "true"; |
| 85 | + conf["indent_oc_block_msg_from_keyword"] = "true"; |
| 86 | + conf["indent_oc_block_msg_from_colon"] = "true"; |
| 87 | + conf["indent_oc_block_msg_from_caret"] = "true"; |
| 88 | + conf["indent_oc_block_msg_from_brace"] = "true"; |
| 89 | + conf["newlines"] = "auto"; |
| 90 | + conf["sp_arith"] = "force"; |
| 91 | + conf["sp_assign"] = "force"; |
| 92 | + conf["sp_assign_default"] = "force"; |
| 93 | + conf["sp_before_assign"] = "force"; |
| 94 | + conf["sp_after_assign"] = "force"; |
| 95 | + conf["sp_enum_assign"] = "force"; |
| 96 | + conf["sp_enum_after_assign"] = "force"; |
| 97 | + conf["sp_bool"] = "force"; |
| 98 | + conf["sp_compare"] = "force"; |
| 99 | + conf["sp_inside_paren"] = "remove"; |
| 100 | + conf["sp_paren_paren"] = "remove"; |
| 101 | + conf["sp_cparen_oparen"] = "force"; |
| 102 | + conf["sp_paren_brace"] = "force"; |
| 103 | + conf["sp_before_ptr_star"] = "remove"; |
| 104 | + conf["sp_before_unnamed_ptr_star"] = "remove"; |
| 105 | + conf["sp_between_ptr_star"] = "force"; |
| 106 | + conf["sp_after_ptr_star"] = "force"; |
| 107 | + conf["sp_after_ptr_star_func"] = "force"; |
| 108 | + conf["sp_ptr_star_paren"] = "force"; |
| 109 | + conf["sp_before_ptr_star_func"] = "force"; |
| 110 | + conf["sp_before_byref"] = "force"; |
| 111 | + conf["sp_after_byref_func"] = "remove"; |
| 112 | + conf["sp_before_byref_func"] = "force"; |
| 113 | + conf["sp_before_angle"] = "remove"; |
| 114 | + conf["sp_inside_angle"] = "remove"; |
| 115 | + conf["sp_after_angle"] = "remove"; |
| 116 | + conf["sp_angle_paren"] = "force"; |
| 117 | + conf["sp_angle_word"] = "force"; |
| 118 | + conf["sp_before_sparen"] = "force"; |
| 119 | + conf["sp_inside_sparen"] = "remove"; |
| 120 | + conf["sp_after_sparen"] = "remove"; |
| 121 | + conf["sp_sparen_brace"] = "force"; |
| 122 | + conf["sp_special_semi"] = "remove"; |
| 123 | + conf["sp_before_semi_for"] = "remove"; |
| 124 | + conf["sp_before_semi_for_empty"] = "force"; |
| 125 | + conf["sp_after_semi_for_empty"] = "force"; |
| 126 | + conf["sp_before_square"] = "remove"; |
| 127 | + conf["sp_before_squares"] = "remove"; |
| 128 | + conf["sp_inside_square"] = "remove"; |
| 129 | + conf["sp_after_comma"] = "force"; |
| 130 | + conf["sp_before_ellipsis"] = "remove"; |
| 131 | + conf["sp_after_class_colon"] = "force"; |
| 132 | + conf["sp_before_class_colon"] = "force"; |
| 133 | + conf["sp_after_constr_colon"] = "ignore"; |
| 134 | + conf["sp_before_constr_colon"] = "ignore"; |
| 135 | + conf["sp_after_operator"] = "force"; |
| 136 | + conf["sp_after_cast"] = "force"; |
| 137 | + conf["sp_inside_paren_cast"] = "remove"; |
| 138 | + conf["sp_sizeof_paren"] = "force"; |
| 139 | + conf["sp_inside_braces_enum"] = "force"; |
| 140 | + conf["sp_inside_braces_struct"] = "force"; |
| 141 | + conf["sp_inside_braces"] = "force"; |
| 142 | + conf["sp_inside_braces_empty"] = "remove"; |
| 143 | + conf["sp_type_func"] = "remove"; |
| 144 | + conf["sp_inside_fparens"] = "remove"; |
| 145 | + conf["sp_inside_fparen"] = "remove"; |
| 146 | + conf["sp_inside_tparen"] = "remove"; |
| 147 | + conf["sp_after_tparen_close"] = "remove"; |
| 148 | + conf["sp_square_fparen"] = "force"; |
| 149 | + conf["sp_fparen_brace"] = "force"; |
| 150 | + if (analyzed_style.average_spacing_before_parens > 0) { |
| 151 | + conf["sp_func_proto_paren"] = "force"; |
| 152 | + conf["sp_func_def_paren"] = "force"; |
| 153 | + conf["sp_func_class_paren"] = "force"; |
| 154 | + conf["sp_func_call_paren"] = "force"; |
| 155 | + } else { |
| 156 | + conf["sp_func_proto_paren"] = "remove"; |
| 157 | + conf["sp_func_def_paren"] = "remove"; |
| 158 | + conf["sp_func_class_paren"] = "remove"; |
| 159 | + conf["sp_func_call_paren"] = "remove"; |
| 160 | + } |
| 161 | + conf["sp_func_call_paren_empty"] = "ignore"; |
| 162 | + // It is really "set func_call_user _" |
| 163 | + // conf["set func_call_user"] = "C_ NC_ N_ Q_ _"; |
| 164 | + conf["sp_return_paren"] = "force"; |
| 165 | + conf["sp_attribute_paren"] = "force"; |
| 166 | + conf["sp_defined_paren"] = "force"; |
| 167 | + conf["sp_throw_paren"] = "force"; |
| 168 | + conf["sp_after_throw"] = "force"; |
| 169 | + conf["sp_catch_paren"] = "force"; |
| 170 | + conf["sp_else_brace"] = "force"; |
| 171 | + conf["sp_brace_else"] = "force"; |
| 172 | + conf["sp_brace_typedef"] = "force"; |
| 173 | + conf["sp_catch_brace"] = "force"; |
| 174 | + conf["sp_brace_catch"] = "force"; |
| 175 | + conf["sp_finally_brace"] = "force"; |
| 176 | + conf["sp_brace_finally"] = "force"; |
| 177 | + conf["sp_try_brace"] = "force"; |
| 178 | + conf["sp_getset_brace"] = "force"; |
| 179 | + conf["sp_word_brace_ns"] = "force"; |
| 180 | + conf["sp_before_dc"] = "remove"; |
| 181 | + conf["sp_after_dc"] = "remove"; |
| 182 | + conf["sp_cond_colon"] = "force"; |
| 183 | + conf["sp_cond_colon_before"] = "force"; |
| 184 | + conf["sp_cond_question"] = "force"; |
| 185 | + conf["sp_cond_question_after"] = "force"; |
| 186 | + conf["sp_cond_ternary_short"] = "force"; |
| 187 | + conf["sp_case_label"] = "force"; |
| 188 | + conf["sp_cmt_cpp_start"] = "force"; |
| 189 | + conf["sp_endif_cmt"] = "remove"; |
| 190 | + conf["sp_after_new"] = "force"; |
| 191 | + conf["sp_before_tr_cmt"] = "force"; |
| 192 | + conf["align_keep_extra_space"] = "true"; |
| 193 | + conf["nl_assign_leave_one_liners"] = "true"; |
| 194 | + conf["nl_class_leave_one_liners"] = "true"; |
| 195 | + conf["nl_enum_brace"] = "remove"; |
| 196 | + conf["nl_struct_brace"] = "remove"; |
| 197 | + conf["nl_union_brace"] = "remove"; |
| 198 | + conf["nl_if_brace"] = "remove"; |
| 199 | + conf["nl_brace_else"] = "remove"; |
| 200 | + conf["nl_elseif_brace"] = "remove"; |
| 201 | + conf["nl_else_brace"] = "remove"; |
| 202 | + conf["nl_else_if"] = "remove"; |
| 203 | + conf["nl_brace_finally"] = "remove"; |
| 204 | + conf["nl_finally_brace"] = "remove"; |
| 205 | + conf["nl_try_brace"] = "remove"; |
| 206 | + conf["nl_getset_brace"] = "remove"; |
| 207 | + conf["nl_for_brace"] = "remove"; |
| 208 | + conf["nl_catch_brace"] = "remove"; |
| 209 | + conf["nl_brace_catch"] = "remove"; |
| 210 | + conf["nl_brace_square"] = "remove"; |
| 211 | + conf["nl_brace_fparen"] = "remove"; |
| 212 | + conf["nl_while_brace"] = "remove"; |
| 213 | + conf["nl_using_brace"] = "remove"; |
| 214 | + conf["nl_do_brace"] = "remove"; |
| 215 | + conf["nl_brace_while"] = "remove"; |
| 216 | + conf["nl_switch_brace"] = "remove"; |
| 217 | + conf["nl_before_throw"] = "remove"; |
| 218 | + conf["nl_namespace_brace"] = "remove"; |
| 219 | + conf["nl_class_brace"] = "remove"; |
| 220 | + conf["nl_class_init_args"] = "remove"; |
| 221 | + conf["nl_class_init_args"] = "remove"; |
| 222 | + conf["nl_func_type_name"] = "remove"; |
| 223 | + conf["nl_func_type_name_class"] = "remove"; |
| 224 | + conf["nl_func_proto_type_name"] = "remove"; |
| 225 | + conf["nl_func_paren"] = "remove"; |
| 226 | + conf["nl_func_def_paren"] = "remove"; |
| 227 | + conf["nl_func_decl_start"] = "remove"; |
| 228 | + conf["nl_func_def_start"] = "remove"; |
| 229 | + conf["nl_func_decl_end"] = "remove"; |
| 230 | + conf["nl_func_def_end"] = "remove"; |
| 231 | + conf["nl_func_decl_empty"] = "remove"; |
| 232 | + conf["nl_func_def_empty"] = "remove"; |
| 233 | + conf["nl_fdef_brace"] = "remove"; |
| 234 | + conf["nl_return_expr"] = "remove"; |
| 235 | + conf["nl_after_func_proto_group"] = "2"; |
| 236 | + conf["nl_after_func_body"] = "2"; |
| 237 | + conf["nl_after_func_body_class"] = "2"; |
| 238 | + conf["eat_blanks_before_close_brace"] = "true"; |
| 239 | + conf["pp_indent_count"] = "0"; |
| 240 | + string[] args = { "uncrustify", "-c", "-", "--assume", source.filename, "-q" }; |
| 241 | + foreach (var entry in conf.entries) { |
| 242 | + args += "--set"; |
| 243 | + args += @"$(entry.key)=$(entry.value)"; |
| 244 | + } |
| 245 | + return args; |
| 246 | + } |
| 247 | +} |
0 commit comments