Skip to content

Commit

Permalink
Add initial support for java references for yaml (#4698)
Browse files Browse the repository at this point in the history
* Add initial support for java references for yaml scalars

* Add incubation annotation

* Add extra test

* Add rename support in YamlReference

* Add NullMarked Package info

* Restrict to application files and rename provider

* Fix paths in tests

* Apply suggestions from code review

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Knut Wannheden <[email protected]>

* Minimize diff between Yaml and Properties type references

---------

Co-authored-by: Tim te Beek <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Knut Wannheden <[email protected]>
  • Loading branch information
4 people authored Dec 6, 2024
1 parent 4e723d8 commit 104f705
Show file tree
Hide file tree
Showing 9 changed files with 329 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import static org.openrewrite.java.Assertions.java;
import static org.openrewrite.properties.Assertions.properties;
import static org.openrewrite.xml.Assertions.xml;
import static org.openrewrite.yaml.Assertions.yaml;

@SuppressWarnings("ConstantConditions")
class ChangePackageTest implements RewriteTest {
Expand Down Expand Up @@ -430,11 +431,11 @@ class A {
}
""",
"""
import org.openrewrite.test.other.Test;
class A {
Test test = null;
}
""",
import org.openrewrite.test.other.Test;
class A {
Test test = null;
}
""",
spec -> spec.afterRecipe(cu -> {
assertThat(cu.findType("org.openrewrite.other.Test")).isEmpty();
assertThat(cu.findType("org.openrewrite.test.other.Test")).isNotEmpty();
Expand Down Expand Up @@ -488,11 +489,11 @@ class A {
}
""",
"""
import org.openrewrite.test.other.Test;
class A {
Test test = null;
}
""",
import org.openrewrite.test.other.Test;
class A {
Test test = null;
}
""",
spec -> spec.afterRecipe(cu -> {
assertThat(cu.findType("org.openrewrite.other.Test")).isEmpty();
assertThat(cu.findType("org.openrewrite.test.other.Test")).isNotEmpty();
Expand Down Expand Up @@ -546,11 +547,11 @@ class A {
}
""",
"""
import org.openrewrite.test.other.Test;
class A {
Test test = null;
}
""",
import org.openrewrite.test.other.Test;
class A {
Test test = null;
}
""",
spec -> spec.afterRecipe(cu -> {
assertThat(cu.findType("org.openrewrite.other.Test")).isEmpty();
assertThat(cu.findType("org.openrewrite.test.other.Test")).isNotEmpty();
Expand Down Expand Up @@ -705,7 +706,7 @@ void method() {}
void annotationArgument() {
rewriteRun(
java(
"""
"""
package org.openrewrite;
public class Argument {}
""",
Expand Down Expand Up @@ -757,7 +758,7 @@ void method() {}
void annotationArgumentNamed() {
rewriteRun(
java(
"""
"""
package org.openrewrite;
public class Argument {}
""",
Expand Down Expand Up @@ -807,7 +808,7 @@ void method() {}
void annotationArgumentFullyQualified() {
rewriteRun(
java(
"""
"""
package org.openrewrite;
public class Argument {}
""",
Expand Down Expand Up @@ -855,7 +856,7 @@ void method() {}
void annotationArgumentNamedFullyQualified() {
rewriteRun(
java(
"""
"""
package org.openrewrite;
public class Argument {}
""",
Expand Down Expand Up @@ -1439,7 +1440,7 @@ void staticImport() {
java(
"""
import static org.openrewrite.Test.stat;
public class B {
public void test() {
stat();
Expand All @@ -1448,7 +1449,7 @@ public void test() {
""",
"""
import static org.openrewrite.test.Test.stat;
public class B {
public void test() {
stat();
Expand Down Expand Up @@ -1724,7 +1725,6 @@ void changePackageInSpringXml() {
"""
)
);

}

@Test
Expand All @@ -1741,7 +1741,30 @@ void changeTypeInPropertiesFile() {
a.property=java.cool.String
b.property=java.cool.test.String
c.property=String
""", spec -> spec.path("application.properties"))
""",
spec -> spec.path("application.properties"))
);
}

@Test
void changePackageInYaml() {
rewriteRun(
spec -> spec.recipe(new ChangePackage("java.lang", "java.cool", true)),
yaml(
"""
root:
a: java.lang.String
b: java.lang.test.String
c: String
""",
"""
root:
a: java.cool.String
b: java.cool.test.String
c: String
""",
spec -> spec.path("application.yaml")
)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import static org.openrewrite.java.Assertions.java;
import static org.openrewrite.properties.Assertions.properties;
import static org.openrewrite.xml.Assertions.xml;
import static org.openrewrite.yaml.Assertions.yaml;

@SuppressWarnings("ConstantConditions")
class ChangeTypeTest implements RewriteTest {
Expand Down Expand Up @@ -2079,4 +2080,28 @@ void changeTypeInPropertiesFile() {
""", spec -> spec.path("application.properties"))
);
}

@Test
void changeTypeInYaml() {
rewriteRun(
spec -> spec.recipe(new ChangeType("java.lang.String", "java.lang.Integer", true)),
yaml(
"""
root:
a: java.lang.String
b: java.lang.StringBuilder
c: java.lang.test.String
d: String
""",
"""
root:
a: java.lang.Integer
b: java.lang.StringBuilder
c: java.lang.test.String
d: String
""",
spec -> spec.path("application.yaml")
)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,5 +119,4 @@ public boolean matchesReference(Reference reference) {
public Reference.Renamer createRenamer(String newName) {
return reference -> newName;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,6 @@ public boolean supportsRename() {
return true;
}

/**
* {@inheritDoc}
*/
@Override
public Tree rename(Renamer renamer, Cursor cursor, ExecutionContext ctx) {
Tree tree = cursor.getValue();
Expand All @@ -67,15 +64,15 @@ public Tree rename(Renamer renamer, Cursor cursor, ExecutionContext ctx) {
return tree;
}

public static class Matcher extends SimpleTraitMatcher<PropertiesReference> {
private static class Matcher extends SimpleTraitMatcher<PropertiesReference> {
private static final Predicate<String> javaFullyQualifiedTypeMatcher = Pattern.compile(
"\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*\\.\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*(?:\\.\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*)*").asPredicate();

@Override
protected @Nullable PropertiesReference test(Cursor cursor) {
Object value = cursor.getValue();
if (value instanceof Properties.Entry &&
javaFullyQualifiedTypeMatcher.test(((Properties.Entry) value).getValue().getText())) {
javaFullyQualifiedTypeMatcher.test(((Properties.Entry) value).getValue().getText())) {
return new PropertiesReference(cursor, determineKind(((Properties.Entry) value).getValue().getText()));
}
return null;
Expand All @@ -88,8 +85,14 @@ private Kind determineKind(String value) {

@SuppressWarnings("unused")
public static class Provider implements Reference.Provider {

private static final Predicate<String> applicationPropertiesMatcher = Pattern.compile("^application(-\\w+)?\\.properties$").asPredicate();

@Override
public boolean isAcceptable(SourceFile sourceFile) {
return sourceFile instanceof Properties.File && applicationPropertiesMatcher.test(sourceFile.getSourcePath().getFileName().toString());
}

@Override
public Set<Reference> getReferences(SourceFile sourceFile) {
Set<Reference> references = new HashSet<>();
Expand All @@ -99,10 +102,5 @@ public Set<Reference> getReferences(SourceFile sourceFile) {
}).visit(sourceFile, 0);
return references;
}

@Override
public boolean isAcceptable(SourceFile sourceFile) {
return sourceFile instanceof Properties.File && applicationPropertiesMatcher.test(sourceFile.getSourcePath().getFileName().toString());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* 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
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.yaml.trait;

import lombok.Value;
import org.jspecify.annotations.Nullable;
import org.openrewrite.Cursor;
import org.openrewrite.ExecutionContext;
import org.openrewrite.SourceFile;
import org.openrewrite.Tree;
import org.openrewrite.trait.Reference;
import org.openrewrite.trait.SimpleTraitMatcher;
import org.openrewrite.yaml.tree.Yaml;

import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;
import java.util.regex.Pattern;

@Value
public class YamlReference implements Reference {
Cursor cursor;
Kind kind;

@Override
public Kind getKind() {
return kind;
}

@Override
public String getValue() {
if (getTree() instanceof Yaml.Scalar) {
return ((Yaml.Scalar) getTree()).getValue();
}
throw new IllegalArgumentException("getTree() must be an Yaml.Scalar: " + getTree().getClass());
}

@Override
public boolean supportsRename() {
return true;
}

@Override
public Tree rename(Renamer renamer, Cursor cursor, ExecutionContext ctx) {
Tree tree = cursor.getValue();
if (tree instanceof Yaml.Scalar) {
return ((Yaml.Scalar) tree).withValue(renamer.rename(this));
}
throw new IllegalArgumentException("cursor.getValue() must be an Yaml.Scalar but is: " + tree.getClass());
}

private static class Matcher extends SimpleTraitMatcher<YamlReference> {
private static final Predicate<String> javaFullyQualifiedTypePattern = Pattern.compile(
"\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*\\.\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*(?:\\.\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*)*")
.asPredicate();

@Override
protected @Nullable YamlReference test(Cursor cursor) {
Object value = cursor.getValue();
if (value instanceof Yaml.Scalar &&
javaFullyQualifiedTypePattern.test(((Yaml.Scalar) value).getValue())) {
return new YamlReference(cursor, determineKind(((Yaml.Scalar) value).getValue()));
}
return null;
}

private Kind determineKind(String value) {
return Character.isUpperCase(value.charAt(value.lastIndexOf('.') + 1)) ? Kind.TYPE : Kind.PACKAGE;
}
}

@SuppressWarnings("unused")
public static class Provider implements Reference.Provider {

private static final Predicate<String> applicationPropertiesMatcher = Pattern.compile("^application(-\\w+)?\\.(yaml|yml)$").asPredicate();

@Override
public boolean isAcceptable(SourceFile sourceFile) {
return sourceFile instanceof Yaml.Documents && applicationPropertiesMatcher.test(sourceFile.getSourcePath().getFileName().toString());
}

@Override
public Set<Reference> getReferences(SourceFile sourceFile) {
Set<Reference> references = new HashSet<>();
new Matcher().asVisitor(reference -> {
references.add(reference);
return reference.getTree();
}).visit(sourceFile, 0);
return references;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* 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
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.
*/
@NullMarked
@NonNullFields
package org.openrewrite.yaml.trait;

import org.jspecify.annotations.NullMarked;
import org.openrewrite.internal.lang.NonNullFields;
Loading

0 comments on commit 104f705

Please sign in to comment.