diff --git a/rewrite-core/src/main/java/org/openrewrite/marker/TypeReference.java b/rewrite-core/src/main/java/org/openrewrite/marker/TypeReference.java
new file mode 100644
index 00000000000..ebe88df0884
--- /dev/null
+++ b/rewrite-core/src/main/java/org/openrewrite/marker/TypeReference.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.openrewrite.marker;
+
+import lombok.Value;
+import lombok.With;
+
+import java.util.UUID;
+
+@Value
+@With
+public class TypeReference implements Marker {
+ UUID id;
+ String language;
+}
diff --git a/rewrite-xml/src/main/java/org/openrewrite/xml/XmlParser.java b/rewrite-xml/src/main/java/org/openrewrite/xml/XmlParser.java
index f99abd38118..055a02424dd 100755
--- a/rewrite-xml/src/main/java/org/openrewrite/xml/XmlParser.java
+++ b/rewrite-xml/src/main/java/org/openrewrite/xml/XmlParser.java
@@ -23,6 +23,7 @@
import org.openrewrite.Parser;
import org.openrewrite.SourceFile;
import org.openrewrite.internal.EncodingDetectingInputStream;
+import org.openrewrite.marker.TypeReference;
import org.openrewrite.tree.ParseError;
import org.openrewrite.tree.ParsingEventListener;
import org.openrewrite.tree.ParsingExecutionContextView;
@@ -33,6 +34,7 @@
import java.nio.file.Path;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Stream;
@@ -94,6 +96,9 @@ public Stream parseInputs(Iterable sourceFiles, @Nullable Pat
is.isCharsetBomMarked()
).visitDocument(parser.document());
parsingListener.parsed(input, document);
+ if (isSpringXmlDocument(document)) {
+ document = (Xml.Document) addJavaTypeOrPackageMarkers().visitDocument(document, ctx);
+ }
return requirePrintEqualsInput(document, input, relativeTo, ctx);
} catch (Throwable t) {
ctx.getOnError().accept(t);
@@ -102,6 +107,15 @@ public Stream parseInputs(Iterable sourceFiles, @Nullable Pat
});
}
+ private boolean isSpringXmlDocument(Xml.Document document) {
+ for (Xml.Attribute attrib : document.getRoot().getAttributes()) {
+ if (attrib.getKeyAsString().equals("xsi:schemaLocation") && attrib.getValueAsString().contains("www.springframework.org/schema/beans")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public Stream parse(@Language("xml") String... sources) {
return parse(new InMemoryExecutionContext(), sources);
@@ -161,4 +175,34 @@ public String getDslName() {
return "xml";
}
}
+
+ private XmlVisitor addJavaTypeOrPackageMarkers() {
+ XPathMatcher classXPath = new XPathMatcher("//@class[contains(., '.')]");
+ XPathMatcher typeXPath = new XPathMatcher("//@type[contains(., '.')]");
+ XPathMatcher tags = new XPathMatcher("//value[contains(text(), '.')]");
+
+ return new XmlVisitor() {
+
+ @Override
+ public Xml visitAttribute(Xml.Attribute attribute, ExecutionContext ctx) {
+ Xml.Attribute attrib = (Xml.Attribute) super.visitAttribute(attribute, ctx);
+ if (classXPath.matches(getCursor()) || typeXPath.matches(getCursor())) {
+ return attrib.withMarkers(attrib.getMarkers().withMarkers(Collections.singletonList(new TypeReference(attrib.getId(), "Java"))));
+
+ }
+ return attrib;
+ }
+
+ @Override
+ public Xml visitTag(Xml.Tag tag, ExecutionContext ctx) {
+ Xml.Tag tg = (Xml.Tag) super.visitTag(tag, ctx);
+ if (tags.matches(getCursor())) {
+ if (tg.getValue().isPresent()) {
+ return tg.withMarkers(tg.getMarkers().withMarkers(Collections.singletonList(new TypeReference(tg.getId(), "Java"))));
+ }
+ }
+ return tg;
+ }
+ };
+ }
}
diff --git a/rewrite-xml/src/test/java/org/openrewrite/xml/XmlParserTest.java b/rewrite-xml/src/test/java/org/openrewrite/xml/XmlParserTest.java
index 1c7449d6639..f2ccda6627f 100755
--- a/rewrite-xml/src/test/java/org/openrewrite/xml/XmlParserTest.java
+++ b/rewrite-xml/src/test/java/org/openrewrite/xml/XmlParserTest.java
@@ -22,6 +22,7 @@
import org.junit.jupiter.params.provider.ValueSource;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Issue;
+import org.openrewrite.marker.TypeReference;
import org.openrewrite.test.RecipeSpec;
import org.openrewrite.test.RewriteTest;
import org.openrewrite.xml.tree.Xml;
@@ -30,6 +31,7 @@
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.openrewrite.test.RewriteTest.toRecipe;
import static org.openrewrite.xml.Assertions.xml;
@@ -397,6 +399,41 @@ void preserveWhitespaceOnEntities() {
);
}
+ @Test
+ void springXmlMarkers() {
+ rewriteRun(
+ xml(
+ """
+
+
+
+
+
+
+
+
+ java.lang.String
+
+
+
+
+
+ """,
+ spec -> spec.afterRecipe(after -> {
+ Xml.Tag testBean = ((Xml.Tag) after.getRoot().getContent().get(0));
+ assertTrue(testBean.getAttributes().get(1).getMarkers().getMarkers().stream().anyMatch(TypeReference.class::isInstance));
+ Xml.Tag unnamedBeanInSiblingProperty = ((Xml.Tag) ((Xml.Tag) testBean.getContent().get(1)).getContent().get(0));
+ assertTrue(unnamedBeanInSiblingProperty.getAttributes().get(0).getMarkers().getMarkers().stream().anyMatch(TypeReference.class::isInstance));
+ Xml.Tag ageProperty = ((Xml.Tag) unnamedBeanInSiblingProperty.getContent().get(0));
+ assertTrue(ageProperty.getAttributes().get(2).getMarkers().getMarkers().stream().anyMatch(TypeReference.class::isInstance));
+ Xml.Tag someNameValue = (Xml.Tag) ((Xml.Tag) unnamedBeanInSiblingProperty.getContent().get(1)).getContent().get(0);
+ assertTrue(someNameValue.getMarkers().getMarkers().stream().anyMatch(TypeReference.class::isInstance));
+ })
+ )
+ );
+ }
+
@DisabledOnOs(OS.WINDOWS)
@ParameterizedTest
@ValueSource(strings = {