diff --git a/CHANGELOG.md b/CHANGELOG.md index aed50e73..a28d6f81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # CheckStyle-IDEA Changelog +* **5.95.0** Fixed: Improved property substitution for code-style importer (#651). * **5.95.0** New: Added CheckStyle 10.18.1. * **5.94.1** Fixed: Error on case-sensitive FSs due to change in plugin directory name with new build plugin (#650). * **5.94.0** New: Added CheckStyle 10.18.0. diff --git a/src/main/java/org/infernus/idea/checkstyle/importer/CheckStyleCodeStyleImporter.java b/src/main/java/org/infernus/idea/checkstyle/importer/CheckStyleCodeStyleImporter.java index fb147ee6..15f4edc5 100644 --- a/src/main/java/org/infernus/idea/checkstyle/importer/CheckStyleCodeStyleImporter.java +++ b/src/main/java/org/infernus/idea/checkstyle/importer/CheckStyleCodeStyleImporter.java @@ -11,9 +11,20 @@ import org.infernus.idea.checkstyle.CheckstyleProjectService; import org.infernus.idea.checkstyle.csapi.CheckstyleInternalObject; import org.infernus.idea.checkstyle.exception.CheckStylePluginException; +import org.infernus.idea.checkstyle.model.ConfigurationLocation; +import org.infernus.idea.checkstyle.model.ConfigurationLocationFactory; +import org.infernus.idea.checkstyle.model.ConfigurationType; +import org.infernus.idea.checkstyle.model.NamedScopeHelper; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collections; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; + +import static java.util.function.Function.identity; + /** * Imports code style settings from check style configuration file. * Registered as {@code schemeImporter} in plugin.xml. @@ -67,6 +78,10 @@ private CheckstyleProjectService checkstyleProjectService(@NotNull final Project return project.getService(CheckstyleProjectService.class); } + private ConfigurationLocationFactory configurationLocationFactory(@NotNull final Project project) { + return project.getService(ConfigurationLocationFactory.class); + } + @Nullable @Override public String getAdditionalImportInfo(@NotNull final CodeStyleScheme scheme) { @@ -79,9 +94,30 @@ private CheckstyleInternalObject loadConfiguration(@NotNull final Project projec @NotNull final VirtualFile selectedFile) { return checkstyleProjectService(project) .getCheckstyleInstance() - .loadConfiguration(selectedFile, null); + .loadConfiguration(selectedFile, defaultPropertiesForFile(project, selectedFile)); } + @NotNull + private Map defaultPropertiesForFile(@NotNull final Project project, + @NotNull final VirtualFile selectedFile) { + try { + ConfigurationLocation codeImportHolder = configurationLocationFactory(project).create( + project, + UUID.randomUUID().toString(), + ConfigurationType.LOCAL_FILE, + selectedFile.getPath(), + "Code Import Holder", + NamedScopeHelper.getDefaultScope(project)); + codeImportHolder.resolve(checkstyleProjectService(project).underlyingClassLoader()); + final Map properties = codeImportHolder.getProperties(); + return properties.keySet().stream(). + collect(Collectors.toMap(identity(), k -> properties.getOrDefault(k, ""))); + + } catch (Exception e) { + LOG.error("Unable to construct defaulted properties", e); + return Collections.emptyMap(); + } + } void importConfiguration(@NotNull final CheckstyleProjectService checkstyleProjectService, @NotNull final CheckstyleInternalObject configuration, diff --git a/src/main/java/org/infernus/idea/checkstyle/model/ConfigurationLocation.java b/src/main/java/org/infernus/idea/checkstyle/model/ConfigurationLocation.java index 337d1362..848ec09c 100644 --- a/src/main/java/org/infernus/idea/checkstyle/model/ConfigurationLocation.java +++ b/src/main/java/org/infernus/idea/checkstyle/model/ConfigurationLocation.java @@ -13,6 +13,7 @@ import org.infernus.idea.checkstyle.checker.CheckerFactoryCache; import org.infernus.idea.checkstyle.util.CheckStyleEntityResolver; import org.infernus.idea.checkstyle.util.Objects; +import org.infernus.idea.checkstyle.util.Pair; import org.infernus.idea.checkstyle.util.ProjectPaths; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -20,7 +21,6 @@ import javax.xml.namespace.QName; import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.events.Attribute; import javax.xml.stream.events.StartElement; import javax.xml.stream.events.XMLEvent; import java.io.File; @@ -171,11 +171,11 @@ public synchronized void reset() { unblock(); } - private List extractProperties(@Nullable final InputStream inputStream, + private Map extractProperties(@Nullable final InputStream inputStream, @NotNull final ClassLoader checkstyleClassLoader) { if (inputStream != null) { try { - final List propertyNames = new ArrayList<>(); + final Map propertiesAndDefaults = new HashMap<>(); final XMLInputFactory factory = XMLInputFactory.newInstance(); factory.setXMLResolver(new CheckStyleEntityResolver(this, checkstyleClassLoader)); @@ -185,32 +185,38 @@ private List extractProperties(@Nullable final InputStream inputStream, final XMLEvent event = eventReader.nextEvent(); if (event.isStartElement()) { - final String propertyName = extractNameIfPropertyElement((StartElement) event); - if (propertyName != null) { - propertyNames.add(propertyName); + final var property = extractNameAndDefaultIfPropertyElement((StartElement) event); + if (property != null) { + propertiesAndDefaults.put(property.first(), property.second()); } } } - return propertyNames; + return propertiesAndDefaults; } catch (Exception e) { LOG.warn("CheckStyle file could not be parsed for properties.", e); } } - return new ArrayList<>(); + return Collections.emptyMap(); } - private static String extractNameIfPropertyElement(final StartElement startElement) { + private static Pair extractNameAndDefaultIfPropertyElement(final StartElement startElement) { if ("property".equals(startElement.getName().getLocalPart())) { - final Attribute valueAttribute = startElement.getAttributeByName(new QName("value")); + final var valueAttribute = startElement.getAttributeByName(new QName("value")); if (valueAttribute != null) { final String value = valueAttribute.getValue(); final int propertyStart = value.indexOf("${"); final int propertyEnd = value.indexOf('}'); if (propertyStart >= 0 && propertyEnd >= 0) { - return value.substring(propertyStart + 2, propertyEnd); + final String propertyName = value.substring(propertyStart + 2, propertyEnd); + + final var defaultAttribute = startElement.getAttributeByName(new QName("default")); + if (defaultAttribute != null) { + return Pair.of(propertyName, defaultAttribute.getValue()); + } + return Pair.of(propertyName, ""); } } } @@ -230,15 +236,15 @@ public synchronized InputStream resolve(@NotNull final ClassLoader checkstyleCla InputStream is = resolveFile(checkstyleClassLoader); if (!propertiesCheckedThisSession) { - final List propertiesInFile = extractProperties(is, checkstyleClassLoader); + final Map propertiesInFile = extractProperties(is, checkstyleClassLoader); - for (final String propertyName : propertiesInFile) { + for (final String propertyName : propertiesInFile.keySet()) { if (!properties.containsKey(propertyName)) { - properties.put(propertyName, ""); + properties.put(propertyName, propertiesInFile.getOrDefault(propertyName, "")); } } - properties.keySet().removeIf(propertyName -> !propertiesInFile.contains(propertyName)); + properties.keySet().removeIf(propertyName -> !propertiesInFile.keySet().contains(propertyName)); try { is.reset(); diff --git a/src/main/java/org/infernus/idea/checkstyle/util/Pair.java b/src/main/java/org/infernus/idea/checkstyle/util/Pair.java new file mode 100644 index 00000000..f31a631f --- /dev/null +++ b/src/main/java/org/infernus/idea/checkstyle/util/Pair.java @@ -0,0 +1,12 @@ +package org.infernus.idea.checkstyle.util; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public record Pair(K first, V second) { + + public static Pair of(@NotNull final K first, @Nullable final V second) { + return new Pair<>(first, second); + } + +} diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 42688e60..50f8718d 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -25,6 +25,7 @@ +
  • 5.95.0: Fixed: Improved property substitution for code-style importer (#651).
  • 5.95.0: New: Added Checkstyle 10.18.1.
  • 5.94.1: Fixed: Error on case-sensitive FSs due to change in plugin directory name with new build plugin (#650).
  • 5.94.0: New: Added Checkstyle 10.18.0.