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.