From 42ad12d40203144c8f9f3735cbffddeb73864dd2 Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Tue, 16 Apr 2019 19:30:29 +0300 Subject: [PATCH] Add indent options to common editorconfig part and skip matching options in languages --- .../testData/codeStyle/jsonExport.j2ee.json | 272 ------------------ .../codeStyle/JavaCodeStyleSettingsTest.java | 12 +- .../GeneralCodeStylePropertyMapper.java | 18 +- .../LanguageCodeStylePropertyMapper.java | 9 +- .../testData/codeStyle/json/exportToJson.json | 4 + .../src/org/editorconfig/Utils.java | 34 ++- .../export/EditorConfigSettingsWriter.java | 135 +++++---- .../extended/IntellijPropertyKindMap.java | 2 +- .../export/EditorConfigExportTest.java | 52 +++- 9 files changed, 179 insertions(+), 359 deletions(-) delete mode 100644 java/java-tests/testData/codeStyle/jsonExport.j2ee.json diff --git a/java/java-tests/testData/codeStyle/jsonExport.j2ee.json b/java/java-tests/testData/codeStyle/jsonExport.j2ee.json deleted file mode 100644 index e675bb1d6ad6..000000000000 --- a/java/java-tests/testData/codeStyle/jsonExport.j2ee.json +++ /dev/null @@ -1,272 +0,0 @@ -{ - "schemeName": "Test", - "version": "1.0", - "codeStyle": { - "java": { - "align_consecutive_assignments": false, - "align_consecutive_variable_declarations": false, - "align_group_field_declarations": false, - "align_multiline_annotation_parameters": false, - "align_multiline_array_initializer_expression": false, - "align_multiline_assignment": false, - "align_multiline_binary_operation": false, - "align_multiline_chained_methods": false, - "align_multiline_extends_list": false, - "align_multiline_for": true, - "align_multiline_method_parentheses": false, - "align_multiline_parameters": true, - "align_multiline_parameters_in_calls": false, - "align_multiline_parenthesized_expression": false, - "align_multiline_resources": true, - "align_multiline_ternary_operation": false, - "align_multiline_throws_list": false, - "align_subsequent_simple_methods": false, - "align_throws_keyword": false, - "annotation_parameter_wrap": "off", - "array_initializer_new_line_after_left_brace": false, - "array_initializer_right_brace_on_new_line": false, - "array_initializer_wrap": "off", - "assert_statement_colon_on_next_line": false, - "assert_statement_wrap": "off", - "assignment_wrap": "off", - "binary_operation_sign_on_next_line": false, - "binary_operation_wrap": "off", - "blank_lines_after_anonymous_class_header": 0, - "blank_lines_after_class_header": 0, - "blank_lines_after_imports": 1, - "blank_lines_after_package": 1, - "blank_lines_around_class": 1, - "blank_lines_around_field": 0, - "blank_lines_around_field_in_interface": 0, - "blank_lines_around_initializer": 1, - "blank_lines_around_method": 1, - "blank_lines_around_method_in_interface": 1, - "blank_lines_before_class_end": 0, - "blank_lines_before_imports": 1, - "blank_lines_before_method_body": 0, - "blank_lines_before_package": 0, - "block_comment_at_first_column": true, - "brace_style": "end_of_line", - "call_parameters_new_line_after_left_paren": false, - "call_parameters_right_paren_on_new_line": false, - "call_parameters_wrap": "on_every_item", - "case_statement_on_separate_line": true, - "catch_on_new_line": false, - "class_annotation_wrap": "split_into_lines", - "class_brace_style": "end_of_line", - "class_count_to_use_import_on_demand": 5, - "class_names_in_javadoc": 1, - "continuation_indent_size": 8, - "do_not_indent_top_level_class_members": false, - "do_not_wrap_after_single_annotation": false, - "do_while_brace_force": "never", - "doc_add_blank_line_after_description": true, - "doc_add_blank_line_after_param_comments": false, - "doc_add_blank_line_after_return": false, - "doc_add_p_tag_on_empty_lines": true, - "doc_align_exception_comments": true, - "doc_align_param_comments": true, - "doc_do_not_wrap_if_one_line": false, - "doc_enable_formatting": true, - "doc_enable_leading_asterisks": true, - "doc_indent_on_continuation": false, - "doc_keep_empty_lines": true, - "doc_keep_empty_parameter_tag": true, - "doc_keep_empty_return_tag": true, - "doc_keep_empty_throws_tag": true, - "doc_keep_invalid_tags": true, - "doc_param_description_on_new_line": false, - "doc_preserve_line_breaks": false, - "doc_use_throws_not_exception_tag": true, - "else_on_new_line": false, - "entity_dd_suffix": "EJB", - "entity_eb_suffix": "Bean", - "entity_hi_suffix": "Home", - "entity_lhi_prefix": "Local", - "entity_lhi_suffix": "Home", - "entity_li_prefix": "Local", - "entity_pk_class": "java.lang.String", - "entity_vo_suffix": "VO", - "enum_constants_wrap": "off", - "extends_keyword_wrap": "off", - "extends_list_wrap": "off", - "field_annotation_wrap": "split_into_lines", - "field_name_prefix": "m_", - "finally_on_new_line": false, - "for_brace_force": "never", - "for_statement_new_line_after_left_paren": false, - "for_statement_right_paren_on_new_line": false, - "for_statement_wrap": "off", - "generate_final_locals": false, - "generate_final_parameters": false, - "if_brace_force": "never", - "imports_layout": [ - "*", - "blank_line", - "javax.**", - "java.**", - "blank_line", - "static *" - ], - "indent_case_from_switch": true, - "indent_size": 4, - "indent_style": "space", - "insert_inner_class_imports": false, - "insert_override_annotation": true, - "keep_blank_lines_before_right_brace": 2, - "keep_blank_lines_between_package_declaration_and_header": 2, - "keep_blank_lines_in_code": 2, - "keep_blank_lines_in_declarations": 2, - "keep_control_statement_in_one_line": true, - "keep_first_column_comment": true, - "keep_indents_on_empty_lines": false, - "keep_line_breaks": true, - "keep_multiple_expressions_in_one_line": false, - "keep_simple_blocks_in_one_line": false, - "keep_simple_classes_in_one_line": false, - "keep_simple_lambdas_in_one_line": false, - "keep_simple_methods_in_one_line": false, - "lambda_brace_style": "end_of_line", - "layout_static_imports_separately": true, - "line_comment_add_space": false, - "line_comment_at_first_column": true, - "message_dd_suffix": "EJB", - "message_eb_suffix": "Bean", - "method_annotation_wrap": "split_into_lines", - "method_brace_style": "next_line_if_wrapped", - "method_call_chain_wrap": "off", - "method_parameters_new_line_after_left_paren": false, - "method_parameters_right_paren_on_new_line": false, - "method_parameters_wrap": "normal", - "modifier_list_wrap": false, - "names_count_to_use_import_on_demand": 3, - "packages_to_use_import_on_demand": [ - "java.awt.*", - "javax.swing.*" - ], - "parameter_annotation_wrap": "off", - "parentheses_expression_new_line_after_left_paren": false, - "parentheses_expression_right_paren_on_new_line": false, - "place_assignment_sign_on_next_line": false, - "prefer_longer_names": true, - "prefer_parameters_wrap": false, - "repeat_annotations": [ - "com.jetbrains.First", - "com.jetbrains.Second" - ], - "repeat_synchronized": true, - "replace_instanceof_and_cast": false, - "replace_null_check": true, - "replace_sum_lambda_with_method_ref": true, - "resource_list_new_line_after_left_paren": false, - "resource_list_right_paren_on_new_line": false, - "resource_list_wrap": "off", - "session_dd_suffix": "EJB", - "session_eb_suffix": "Bean", - "session_hi_suffix": "Home", - "session_lhi_prefix": "Local", - "session_lhi_suffix": "Home", - "session_li_prefix": "Local", - "session_si_suffix": "Service", - "smart_tabs": false, - "space_after_closing_angle_bracket_in_type_argument": false, - "space_after_colon": true, - "space_after_comma": true, - "space_after_comma_in_type_arguments": true, - "space_after_for_semicolon": true, - "space_after_quest": true, - "space_after_type_cast": true, - "space_before_annotation_array_initializer_left_brace": false, - "space_before_annotation_parameter_list": false, - "space_before_array_initializer_left_brace": false, - "space_before_catch_keyword": true, - "space_before_catch_left_brace": true, - "space_before_catch_parentheses": true, - "space_before_class_left_brace": true, - "space_before_colon": true, - "space_before_colon_in_foreach": true, - "space_before_comma": false, - "space_before_do_left_brace": true, - "space_before_else_keyword": true, - "space_before_else_left_brace": true, - "space_before_finally_keyword": true, - "space_before_finally_left_brace": true, - "space_before_for_left_brace": true, - "space_before_for_parentheses": true, - "space_before_for_semicolon": false, - "space_before_if_left_brace": true, - "space_before_if_parentheses": true, - "space_before_method_call_parentheses": false, - "space_before_method_left_brace": true, - "space_before_method_parentheses": false, - "space_before_opening_angle_bracket_in_type_parameter": false, - "space_before_quest": true, - "space_before_switch_left_brace": true, - "space_before_switch_parentheses": true, - "space_before_synchronized_left_brace": true, - "space_before_synchronized_parentheses": true, - "space_before_try_left_brace": true, - "space_before_try_parentheses": true, - "space_before_type_parameter_list": false, - "space_before_while_keyword": true, - "space_before_while_left_brace": true, - "space_before_while_parentheses": true, - "space_inside_one_line_enum_braces": false, - "space_within_empty_array_initializer_braces": false, - "space_within_empty_method_call_parentheses": false, - "space_within_empty_method_parentheses": false, - "spaces_around_additive_operators": true, - "spaces_around_assignment_operators": true, - "spaces_around_bitwise_operators": true, - "spaces_around_equality_operators": true, - "spaces_around_lambda_arrow": true, - "spaces_around_logical_operators": true, - "spaces_around_method_ref_dbl_colon": false, - "spaces_around_multiplicative_operators": true, - "spaces_around_relational_operators": true, - "spaces_around_shift_operators": true, - "spaces_around_type_bounds_in_type_parameters": true, - "spaces_around_unary_operator": false, - "spaces_within_angle_brackets": false, - "spaces_within_annotation_parentheses": false, - "spaces_within_array_initializer_braces": false, - "spaces_within_braces": false, - "spaces_within_brackets": false, - "spaces_within_cast_parentheses": false, - "spaces_within_catch_parentheses": false, - "spaces_within_for_parentheses": false, - "spaces_within_if_parentheses": false, - "spaces_within_method_call_parentheses": false, - "spaces_within_method_parentheses": false, - "spaces_within_parentheses": false, - "spaces_within_switch_parentheses": false, - "spaces_within_synchronized_parentheses": false, - "spaces_within_try_parentheses": false, - "spaces_within_while_parentheses": false, - "special_else_if_treatment": true, - "static_field_name_suffix": "_s", - "subclass_name_suffix": "Impl", - "tab_width": 4, - "ternary_operation_signs_on_next_line": false, - "ternary_operation_wrap": "off", - "test_name_suffix": "Test", - "throws_keyword_wrap": "off", - "throws_list_wrap": "off", - "use_external_annotations": false, - "use_fq_class_names": false, - "use_single_class_imports": true, - "variable_annotation_wrap": "off", - "visibility": "public", - "visual_guides": [ - 11, - 22 - ], - "while_brace_force": "never", - "while_on_new_line": false, - "wrap_comments": false, - "wrap_first_method_in_call_chain": false, - "wrap_long_lines": false, - "wrap_on_typing": true - } - } -} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/psi/codeStyle/JavaCodeStyleSettingsTest.java b/java/java-tests/testSrc/com/intellij/java/psi/codeStyle/JavaCodeStyleSettingsTest.java index f77159d4a268..d4e5de961e87 100644 --- a/java/java-tests/testSrc/com/intellij/java/psi/codeStyle/JavaCodeStyleSettingsTest.java +++ b/java/java-tests/testSrc/com/intellij/java/psi/codeStyle/JavaCodeStyleSettingsTest.java @@ -97,17 +97,7 @@ public class JavaCodeStyleSettingsTest extends CodeStyleTestCase { CodeStyleSchemeJsonExporter exporter = new CodeStyleSchemeJsonExporter(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); exporter.exportScheme(testScheme, outputStream, Collections.singletonList("java")); - compareWithExpected(outputStream.toString(), j2eeProviderExists() ? "j2ee.json" : "json"); - } - - private static boolean j2eeProviderExists() { - List providers = CodeStyleSettingsProvider.EXTENSION_POINT_NAME.getExtensionList(); - for (CodeStyleSettingsProvider provider : providers) { - if (provider.getClass().getName().equals("com.intellij.javaee.JavaeeCodeStyleSettingsProvider")) { - return true; - } - } - return false; + compareWithExpected(outputStream.toString(), "json"); } public void testSetProperties() { diff --git a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/GeneralCodeStylePropertyMapper.java b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/GeneralCodeStylePropertyMapper.java index 21b9cdcf501d..0195a95eef24 100644 --- a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/GeneralCodeStylePropertyMapper.java +++ b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/GeneralCodeStylePropertyMapper.java @@ -5,15 +5,13 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.OptionsBundle; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.reflect.Field; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; public class GeneralCodeStylePropertyMapper extends AbstractCodeStylePropertyMapper { private static final Logger LOG = Logger.getInstance(AbstractCodeStylePropertyMapper.class); @@ -30,6 +28,13 @@ public class GeneralCodeStylePropertyMapper extends AbstractCodeStylePropertyMap "FORMATTER_TAGS_ACCEPT_REGEXP" ); + private final static Set INDENT_FIELDS = ContainerUtil.newHashSet( + "INDENT_SIZE", + "USE_TAB_CHARACTER", + "TAB_SIZE", + "SMART_TABS" + ); + public GeneralCodeStylePropertyMapper(@NotNull CodeStyleSettings settings) { super(settings); } @@ -37,7 +42,10 @@ public class GeneralCodeStylePropertyMapper extends AbstractCodeStylePropertyMap @NotNull @Override protected List getSupportedFields() { - return Collections.singletonList(new CodeStyleObjectDescriptor(getRootSettings(), GENERAL_FIELDS)); + List supportedFields = new ArrayList<>(2); + supportedFields.add(new CodeStyleObjectDescriptor(getRootSettings(), GENERAL_FIELDS)); + supportedFields.add(new CodeStyleObjectDescriptor(getRootSettings().OTHER_INDENT_OPTIONS, INDENT_FIELDS)); + return supportedFields; } @Override diff --git a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/LanguageCodeStylePropertyMapper.java b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/LanguageCodeStylePropertyMapper.java index 7fc5ac750403..931a0fe8aa22 100644 --- a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/LanguageCodeStylePropertyMapper.java +++ b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/LanguageCodeStylePropertyMapper.java @@ -4,6 +4,7 @@ package com.intellij.application.options.codeStyle.properties; import com.intellij.application.options.IndentOptionsEditor; import com.intellij.application.options.SmartIndentOptionsEditor; import com.intellij.lang.Language; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.options.OptionsBundle; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsProvider; @@ -94,7 +95,7 @@ public final class LanguageCodeStylePropertyMapper extends AbstractCodeStyleProp @NotNull CodeStyleSettings rootSettings, @NotNull List providerList) { for (CodeStyleSettingsProvider provider : providerList) { - if (provider.getLanguage() == myLanguage) { + if (provider.getLanguage() == myLanguage && isEnabled(provider)) { CustomCodeStyleSettings customSettingsTemplate = provider.createCustomSettings(rootSettings); if (customSettingsTemplate != null) { CustomCodeStyleSettings customSettings = rootSettings.getCustomSettings(customSettingsTemplate.getClass()); @@ -104,6 +105,12 @@ public final class LanguageCodeStylePropertyMapper extends AbstractCodeStyleProp } } + private static boolean isEnabled(@NotNull CodeStyleSettingsProvider provider) { + // Enable only providers defining a main language configurable in unit test mode, skip any secondary contributors + // to avoid test flickering on different class paths. + return !ApplicationManager.getApplication().isUnitTestMode() || provider.hasSettingsPage(); + } + private Set getSupportedIndentOptions() { LanguageCodeStyleSettingsProvider provider = LanguageCodeStyleSettingsProvider.forLanguage(myLanguage); if (provider == null) return Collections.emptySet(); diff --git a/platform/platform-tests/testData/codeStyle/json/exportToJson.json b/platform/platform-tests/testData/codeStyle/json/exportToJson.json index 75dad39a3ec0..fa04bcd09306 100644 --- a/platform/platform-tests/testData/codeStyle/json/exportToJson.json +++ b/platform/platform-tests/testData/codeStyle/json/exportToJson.json @@ -7,7 +7,11 @@ "formatter_on_tag": "@formatter:on", "formatter_tags_accept_regexp": false, "formatter_tags_enabled": false, + "indent_size": 4, + "indent_style": "space", "max_line_length": 120, + "smart_tabs": false, + "tab_width": 4, "visual_guides": [ 42, 62 diff --git a/plugins/editorconfig/src/org/editorconfig/Utils.java b/plugins/editorconfig/src/org/editorconfig/Utils.java index c4f8607146b4..a67bb5fa5391 100644 --- a/plugins/editorconfig/src/org/editorconfig/Utils.java +++ b/plugins/editorconfig/src/org/editorconfig/Utils.java @@ -96,10 +96,10 @@ public class Utils { final CodeStyleSettings settings = CodeStyle.getSettings(project); final CommonCodeStyleSettings.IndentOptions commonIndentOptions = settings.getIndentOptions(); StringBuilder result = new StringBuilder(); - addIndentOptions(result, "*", commonIndentOptions, getEncoding(project) + - getLineEndings(project) + - getTrailingSpaces() + - getEndOfFile()); + addIndentOptions(result, "*", commonIndentOptions, getEncodingLine(project) + + getLineEndings(project) + + getTrailingSpacesLine() + + getEndOfFileLine()); for (FileType fileType : FileTypeManager.getInstance().getRegisteredFileTypes()) { if (!FileTypeIndex.containsFileOfType(fileType, GlobalSearchScope.allScope(project))) continue; @@ -130,16 +130,22 @@ public class Utils { } @NotNull - public static String getEndOfFile() { + private static String getEndOfFileLine() { return StandardEditorConfigProperties.INSERT_FINAL_NEWLINE + "=" + EditorSettingsExternalizable.getInstance().isEnsureNewLineAtEOF() + "\n"; } @NotNull - public static String getTrailingSpaces() { + private static String getTrailingSpacesLine() { + final Boolean trimTrailingSpaces = getTrimTrailingSpaces(); + return trimTrailingSpaces != null ? StandardEditorConfigProperties.TRIM_TRAILING_WHITESPACE + "=" + trimTrailingSpaces : ""; + } + + @Nullable + public static Boolean getTrimTrailingSpaces() { final String spaces = EditorSettingsExternalizable.getInstance().getStripTrailingSpaces(); - if (EditorSettingsExternalizable.STRIP_TRAILING_SPACES_NONE.equals(spaces)) return StandardEditorConfigProperties.TRIM_TRAILING_WHITESPACE + "=false\n"; - if (EditorSettingsExternalizable.STRIP_TRAILING_SPACES_WHOLE.equals(spaces)) return StandardEditorConfigProperties.TRIM_TRAILING_WHITESPACE + "=true\n"; - return ""; + if (EditorSettingsExternalizable.STRIP_TRAILING_SPACES_NONE.equals(spaces)) return false; + if (EditorSettingsExternalizable.STRIP_TRAILING_SPACES_WHOLE.equals(spaces)) return true; + return null; } @NotNull @@ -161,14 +167,20 @@ public class Utils { } @NotNull + public static String getEncodingLine(@NotNull Project project) { + String encoding = getEncoding(project); + return encoding != null ? EncodingManager.charsetKey + "=" + encoding : ""; + } + + @Nullable public static String getEncoding(@NotNull Project project) { final Charset charset = EncodingProjectManager.getInstance(project).getDefaultCharset(); for (Map.Entry entry : EncodingManager.encodingMap.entrySet()) { if (entry.getValue() == charset) { - return EncodingManager.charsetKey + "=" + entry.getKey() + "\n"; + return entry.getKey(); } } - return ""; + return null; } @NotNull diff --git a/plugins/editorconfig/src/org/editorconfig/configmanagement/export/EditorConfigSettingsWriter.java b/plugins/editorconfig/src/org/editorconfig/configmanagement/export/EditorConfigSettingsWriter.java index 55a7842009e8..1b5d8fd3a2ae 100644 --- a/plugins/editorconfig/src/org/editorconfig/configmanagement/export/EditorConfigSettingsWriter.java +++ b/plugins/editorconfig/src/org/editorconfig/configmanagement/export/EditorConfigSettingsWriter.java @@ -3,12 +3,15 @@ package org.editorconfig.configmanagement.export; import com.intellij.application.options.codeStyle.properties.*; import com.intellij.lang.Language; +import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.psi.codeStyle.CodeStyleSettings; import org.editorconfig.Utils; +import org.editorconfig.configmanagement.EncodingManager; import org.editorconfig.configmanagement.LineEndingsManager; +import org.editorconfig.configmanagement.StandardEditorConfigProperties; import org.editorconfig.configmanagement.extended.EditorConfigIntellijNameUtil; import org.editorconfig.configmanagement.extended.EditorConfigPropertyKind; import org.editorconfig.configmanagement.extended.IntellijPropertyKindMap; @@ -20,12 +23,21 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; import java.util.*; +import java.util.stream.Collectors; import static org.editorconfig.core.EditorConfig.OutPair; public class EditorConfigSettingsWriter extends OutputStreamWriter { - private final CodeStyleSettings mySettings; - private final @Nullable Project myProject; + private final CodeStyleSettings mySettings; + private final @Nullable Project myProject; + private final Map myGeneralOptions = new HashMap<>(); + + private final static Comparator PAIR_COMPARATOR = (pair1, pair2) -> { + EditorConfigPropertyKind pKind1 = getPropertyKind(pair1.getKey()); + EditorConfigPropertyKind pKind2 = getPropertyKind(pair2.getKey()); + if (!pKind1.equals(pKind2)) return Comparing.compare(pKind2, pKind1); // in reversed order + return Comparing.compare(pair1.getKey(), pair2.getKey()); + }; // region Filters private Set myLanguages; @@ -36,6 +48,30 @@ public class EditorConfigSettingsWriter extends OutputStreamWriter { super(out, StandardCharsets.UTF_8); mySettings = settings; myProject = project; + fillGeneralOptions(); + } + + private void fillGeneralOptions() { + for (OutPair pair : getKeyValuePairs(new GeneralCodeStylePropertyMapper(mySettings))) { + myGeneralOptions.put(pair.getKey(), pair.getVal()); + } + myGeneralOptions.put("ij_continuation_indent_size", String.valueOf(mySettings.OTHER_INDENT_OPTIONS.CONTINUATION_INDENT_SIZE)); + if (myProject != null) { + String encoding = Utils.getEncoding(myProject); + if (encoding != null) { + myGeneralOptions.put(EncodingManager.charsetKey, encoding); + } + } + String lineSeparator = Utils.getLineSeparatorString(mySettings.getLineSeparator()); + if (lineSeparator != null) { + myGeneralOptions.put(LineEndingsManager.lineEndingsKey, lineSeparator); + } + myGeneralOptions.put(StandardEditorConfigProperties.INSERT_FINAL_NEWLINE, + String.valueOf(EditorSettingsExternalizable.getInstance().isEnsureNewLineAtEOF())); + Boolean trimSpaces = Utils.getTrimTrailingSpaces(); + if (trimSpaces != null) { + myGeneralOptions.put(StandardEditorConfigProperties.TRIM_TRAILING_WHITESPACE, String.valueOf(trimSpaces)); + } } public EditorConfigSettingsWriter forLanguages(Language... languages) { @@ -52,40 +88,34 @@ public class EditorConfigSettingsWriter extends OutputStreamWriter { public void writeSettings() throws IOException { final List mappers = new ArrayList<>(); - writeGeneralSection(new GeneralCodeStylePropertyMapper(mySettings)); + writeGeneralSection(); CodeStylePropertiesUtil.collectMappers(mySettings, mapper -> mappers.add(mapper)); for (AbstractCodeStylePropertyMapper mapper : mappers) { - writeLangSection(mapper); + if (mapper instanceof LanguageCodeStylePropertyMapper) { + writeLangSection((LanguageCodeStylePropertyMapper)mapper); + } } } - private void writeGeneralSection(@NotNull GeneralCodeStylePropertyMapper mapper) throws IOException { + private void writeGeneralSection() throws IOException { write("[*]\n"); - if (myPropertyKinds.contains(EditorConfigPropertyKind.EDITOR_CONFIG_STANDARD)) { - if (myProject != null) { - write(Utils.getEncoding(myProject)); - } - String lineSeparator = Utils.getLineSeparatorString(mySettings.getLineSeparator()); - if (lineSeparator != null) { - write(LineEndingsManager.lineEndingsKey + " = " + lineSeparator + "\n"); - } - write(Utils.getEndOfFile()); - write(Utils.getTrailingSpaces()); - } - writeProperties(getKeyValuePairs(mapper)); + List pairs = myGeneralOptions.keySet().stream() + .map(key -> new OutPair(key, myGeneralOptions.get(key))) + .filter(pair -> isNameAllowed(pair.getKey())) + .sorted(PAIR_COMPARATOR).collect(Collectors.toList()); + writeProperties(pairs); } - private void writeLangSection(@NotNull AbstractCodeStylePropertyMapper mapper) throws IOException { - if (mapper instanceof LanguageCodeStylePropertyMapper) { - Language language = ((LanguageCodeStylePropertyMapper)mapper).getLanguage(); - if (myLanguages == null || myLanguages.contains(language)) { - FileType fileType = language.getAssociatedFileType(); - if (fileType != null) { - List optionValueList = getKeyValuePairs(mapper); - if (!optionValueList.isEmpty()) { - write("\n[" + Utils.buildPattern(fileType) + "]\n"); - writeProperties(optionValueList); - } + private void writeLangSection(@NotNull LanguageCodeStylePropertyMapper mapper) throws IOException { + Language language = mapper.getLanguage(); + if (myLanguages == null || myLanguages.contains(language)) { + FileType fileType = language.getAssociatedFileType(); + if (fileType != null) { + List optionValueList = getKeyValuePairs(mapper); + if (!optionValueList.isEmpty()) { + write("\n[" + Utils.buildPattern(fileType) + "]\n"); + Collections.sort(optionValueList, PAIR_COMPARATOR); + writeProperties(optionValueList); } } } @@ -93,27 +123,38 @@ public class EditorConfigSettingsWriter extends OutputStreamWriter { private List getKeyValuePairs(@NotNull AbstractCodeStylePropertyMapper mapper) { List optionValueList = new ArrayList<>(); - for (String property : orderOptions(mapper.enumProperties())) { + for (String property : mapper.enumProperties()) { CodeStylePropertyAccessor accessor = mapper.getAccessor(property); - EditorConfigPropertyKind propertyKind = IntellijPropertyKindMap.getPropertyKind(property); - boolean isIntelliJProperty = !propertyKind.equals(EditorConfigPropertyKind.EDITOR_CONFIG_STANDARD); - if ( - isIntelliJProperty && myPropertyKinds.contains(EditorConfigPropertyKind.LANGUAGE) || - !isIntelliJProperty && myPropertyKinds.contains(EditorConfigPropertyKind.EDITOR_CONFIG_STANDARD) - ) { - String name = getEditorConfigName(mapper, property); - if (name != null) { - String value = accessor.getAsString(); - if (value != null && !value.trim().isEmpty() && isAllowed(value)) { - optionValueList.add(new OutPair(name, value)); - } + String name = getEditorConfigName(mapper, property); + if (isNameAllowed(name)) { + String value = accessor.getAsString(); + if (isValueAllowed(value) && (!(mapper instanceof LanguageCodeStylePropertyMapper && matchesGeneral(name, value)))) { + optionValueList.add(new OutPair(name, value)); } } } return optionValueList; } - private static boolean isAllowed(@NotNull String value) { + private boolean matchesGeneral(@NotNull String name, @NotNull String value) { + String generalValue = myGeneralOptions.get(name); + return generalValue != null && generalValue.equals(value); + } + + private boolean isNameAllowed(@Nullable String ecName) { + if (ecName != null) { + return myPropertyKinds.contains(getPropertyKind(ecName)); + } + return false; + } + + private static EditorConfigPropertyKind getPropertyKind(@NotNull String ecName) { + String ijName = EditorConfigIntellijNameUtil.toIntellijName(ecName); + return IntellijPropertyKindMap.getPropertyKind(ijName); + } + + private static boolean isValueAllowed(@Nullable String value) { + if (value == null || value.trim().isEmpty()) return false; // TODO REMOVE THE HACK // EditorConfig implementation doesn't allow dots. We need to skip such values till the parser issue is fixed. return !value.contains("."); @@ -125,16 +166,6 @@ public class EditorConfigSettingsWriter extends OutputStreamWriter { } } - private static List orderOptions(@NotNull List propertyList) { - Collections.sort(propertyList, (name1, name2) -> { - EditorConfigPropertyKind pKind1 = IntellijPropertyKindMap.getPropertyKind(name1); - EditorConfigPropertyKind pKind2 = IntellijPropertyKindMap.getPropertyKind(name2); - if (!pKind1.equals(pKind2)) return Comparing.compare(pKind2, pKind1); // in reversed order - return Comparing.compare(name1, name2); - }); - return propertyList; - } - @Nullable private static String getEditorConfigName(@NotNull AbstractCodeStylePropertyMapper mapper, @NotNull String propertyName) { List editorConfigNames = EditorConfigIntellijNameUtil.toEditorConfigNames(mapper, propertyName); diff --git a/plugins/editorconfig/src/org/editorconfig/configmanagement/extended/IntellijPropertyKindMap.java b/plugins/editorconfig/src/org/editorconfig/configmanagement/extended/IntellijPropertyKindMap.java index 4d63a6df4c67..51ad96e13857 100644 --- a/plugins/editorconfig/src/org/editorconfig/configmanagement/extended/IntellijPropertyKindMap.java +++ b/plugins/editorconfig/src/org/editorconfig/configmanagement/extended/IntellijPropertyKindMap.java @@ -22,7 +22,7 @@ public class IntellijPropertyKindMap { PROPERTY_KIND_MAP.put("max_line_length", EDITOR_CONFIG_STANDARD); PROPERTY_KIND_MAP.put("indent_size", EDITOR_CONFIG_STANDARD); PROPERTY_KIND_MAP.put("indent_style", EDITOR_CONFIG_STANDARD); - PROPERTY_KIND_MAP.put("insert_final_new_line", EDITOR_CONFIG_STANDARD); + PROPERTY_KIND_MAP.put("insert_final_newline", EDITOR_CONFIG_STANDARD); PROPERTY_KIND_MAP.put("end_of_line", EDITOR_CONFIG_STANDARD); PROPERTY_KIND_MAP.put("trim_trailing_whitespace", EDITOR_CONFIG_STANDARD); PROPERTY_KIND_MAP.put("tab_width", EDITOR_CONFIG_STANDARD); diff --git a/plugins/editorconfig/test/org/editorconfig/configmanagement/export/EditorConfigExportTest.java b/plugins/editorconfig/test/org/editorconfig/configmanagement/export/EditorConfigExportTest.java index 782a38f44e2c..aec4bd7fe0d1 100644 --- a/plugins/editorconfig/test/org/editorconfig/configmanagement/export/EditorConfigExportTest.java +++ b/plugins/editorconfig/test/org/editorconfig/configmanagement/export/EditorConfigExportTest.java @@ -1,6 +1,7 @@ // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.editorconfig.configmanagement.export; +import com.intellij.lang.xml.XMLLanguage; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.testFramework.LightPlatformTestCase; import com.intellij.util.LineSeparator; @@ -15,21 +16,34 @@ public class EditorConfigExportTest extends LightPlatformTestCase { CodeStyleSettings setting = CodeStyleSettings.getDefaults().clone(); setting.LINE_SEPARATOR = LineSeparator.CRLF.getSeparatorString(); ByteArrayOutputStream output = new ByteArrayOutputStream(); - try (EditorConfigSettingsWriter writer = new EditorConfigSettingsWriter(getProject(), output, setting).forLanguages(EditorConfigLanguage.INSTANCE)) { + try (EditorConfigSettingsWriter writer = + new EditorConfigSettingsWriter(getProject(), output, setting) + .forLanguages(EditorConfigLanguage.INSTANCE, XMLLanguage.INSTANCE)) { writer.writeSettings(); } String result = output.toString("UTF-8"); + result = result.replaceAll("\\[.*\\.xml.*]", "[*.xml]"); // Leave only XML assertEquals( "[*]\n" + - "charset=utf-8\n" + + "charset = utf-8\n" + "end_of_line = crlf\n" + - "insert_final_newline=false\n" + + "indent_size = 4\n" + + "indent_style = space\n" + + "insert_final_newline = false\n" + "max_line_length = 120\n" + + "tab_width = 4\n" + + "ij_continuation_indent_size = 8\n" + "ij_formatter_off_tag = @formatter:off\n" + "ij_formatter_on_tag = @formatter:on\n" + "ij_formatter_tags_enabled = false\n" + + "ij_smart_tabs = false\n" + "ij_wrap_on_typing = false\n" + "\n" + + "[*.xml]\n" + + "ij_xml_block_comment_at_first_column = true\n" + + "ij_xml_keep_indents_on_empty_lines = false\n" + + "ij_xml_line_comment_at_first_column = true\n" + + "\n" + "[.editorconfig]\n" + "ij_editorconfig_align_group_field_declarations = false\n" + "ij_editorconfig_space_after_colon = false\n" + @@ -41,6 +55,29 @@ public class EditorConfigExportTest extends LightPlatformTestCase { result); } + public void testSkipEmptySection() throws IOException { + CodeStyleSettings setting = CodeStyleSettings.getDefaults().clone(); + setting.LINE_SEPARATOR = LineSeparator.CRLF.getSeparatorString(); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + try (EditorConfigSettingsWriter writer = new EditorConfigSettingsWriter(getProject(), output, setting) + .forLanguages(EditorConfigLanguage.INSTANCE, XMLLanguage.INSTANCE) + .forPropertyKinds(EditorConfigPropertyKind.EDITOR_CONFIG_STANDARD)) { + writer.writeSettings(); + } + String result = output.toString("UTF-8"); + assertEquals( + "[*]\n" + + "charset = utf-8\n" + + "end_of_line = crlf\n" + + "indent_size = 4\n" + + "indent_style = space\n" + + "insert_final_newline = false\n" + + "max_line_length = 120\n" + + "tab_width = 4\n", + + result); + } + public void testFilterByPropertyKind() throws IOException { CodeStyleSettings setting = CodeStyleSettings.getDefaults().clone(); setting.LINE_SEPARATOR = LineSeparator.CRLF.getSeparatorString(); @@ -54,10 +91,13 @@ public class EditorConfigExportTest extends LightPlatformTestCase { String result = output.toString("UTF-8"); assertEquals( "[*]\n" + - "charset=utf-8\n" + + "charset = utf-8\n" + "end_of_line = crlf\n" + - "insert_final_newline=false\n" + - "max_line_length = 120\n", + "indent_size = 4\n" + + "indent_style = space\n" + + "insert_final_newline = false\n" + + "max_line_length = 120\n" + + "tab_width = 4\n", result); }