openrewrite / rewrite Goto Github PK
View Code? Open in Web Editor NEWAutomated mass refactoring of source code.
Home Page: https://docs.openrewrite.org
License: Apache License 2.0
Automated mass refactoring of source code.
Home Page: https://docs.openrewrite.org
License: Apache License 2.0
Inspired by forgetting to make a class intended to be part of our public API public
:
We could create a visitor which is configured with one or more package names and a visibility modifier public
/protected
/package
/private
. It would then ensure that every class in that package always has the appropriate visibility modifier.
I mainly anticipate this being used in two ways:
I'm not sure exactly where this visitor should live. Rewrite-java is probably fine.
I am trying to reproduce this example: https://docs.openrewrite.org/java/refactoring-java-source-code/usestaticimport
I created single class in project:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Assertions;
class Sample {
@Test
void sample() {
Assertions.assertEquals(42, 21*2);
}
}
Then I created in the root of the project rewrite.yml:
---
type: specs.org.openrewrite.org/v1beta/visitor
name: io.moderne.UseStaticJUnitAsserts
visitors:
- org.openrewrite.java.UseStaticImport:
method: 'org.junit.jupiter.api.Assertions assert*(..)'
My pom also contains plugin:
<build>
<plugins>
<plugin>
<groupId>org.openrewrite.maven</groupId>
<artifactId>rewrite-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<configLocation>rewrite.yml</configLocation>
</configuration>
</plugin>
</plugins>
</build>
But I don't get expected result when I run the command: ./mvnw rewrite:fix
// What I expected to see
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class Sample {
@Test
void sample() {
assertEquals(42, 21*2);
}
}
More over I noticed that when I remove rewrite.yml it doesn't affect anything. Build status is always "SUCCESS".
Also when I change rewrite.yml in https://github.com/openrewrite/spring-petclinic-migration it always applies the same changes(even when I remove rewrite.yml).
Did I miss something? Seems like I don't understand something...
I think this is something we need because it can help replace one annotation to another one using combination of RemoveAnnotation
and AddAnnotation
. I will try to implement this by myself
By specifying a groupId and artifactId pair, ExcludeDependency
should locate first order dependencies whose transitive dependency tree includes a dependency matching this pair and add excludes to them.
Add the exclude as the last item in <exclusions>
if such a tag already exists.
Add <exclusions>
to the dependency if it does not already exist.
The standard advice we've been giving is that for a visitor to delete a source file it should return null from the highest-level tree element (in the case of Java, this is CompilationUnit
). But if you actually try to return null
from any visit method SourceVisitor.reduce() will discard it.
So as it stands there is not currently a way for a visitor to delete a tree it encounters.
How would I get the classpath of a Maven project with a help of OpenRewrite?
Currently we're performing the following:
List<Maven.Pom> mavenPoms = MavenParser
.builder()
.resolveDependencies(true)
.build()
.parse(List.of(buildFilePath), null);
Then on the resultant Pom object we'd call getModel().getTransitiveDependenciesByScope()
and get all scopes dependencies.
These however seem to be more than project's classpath and computation of transitive dependencies (with resolveDependencies flag on) takes ~20s for the project attached below. Transitive dependencies number is huge. Note that all jars are in the local maven repo and are not downloaded.
Whenever, I try to use https://github.com/shrinkwrap/resolver to compute the classpath of the project below it takes less than a second or around a second and return much less dependencies (but their are the same as M2Es in Eclipse).
What is the purpose of transitive dependencies on the MavenModel in OpenRewrite? Is it the classpath or is meant for something else?
In this test project https://github.com/Guseyn/rewrite-java-definitions, I've created following class with regular and static methods:
package org.openrewrite.classes;
public class ClassWithMethods {
public void foo() {}
public void bar() {}
public static void fooStatic() {}
public static void barStatic() {}
}
I decided to include package names since I think it can be important.
Then I've created following test class E
that contains the class above:
package org.openrewrite.before;
import org.openrewrite.classes.ClassWithMethods;
public class E {
void foo() {
new ClassWithMethods().foo();
ClassWithMethods.fooStatic();
}
}
My Java Definition for E
class:
ChangeMethodName cmn = new ChangeMethodName();
cmn.setMethod("org.openrewrite.classes.ClassWithMethods foo()");
cmn.setName("bar");
ChangeMethodName cmnStatic = new ChangeMethodName();
cmnStatic.setMethod("org.openrewrite.classes.ClassWithMethods fooStatic()");
cmnStatic.setName("barStatic");
ChangePackageName cpn = new ChangePackageName();
cpn.setNewPackageName("org.openrewrite.after");
List<RefactorVisitor<?>> visitors = new ArrayList<>(){{
add(cmn);
add(cmnStatic);
add(cpn);
}};
RefactorProcessor.run(visitors, "E.java");
I explain how RefactorProcessor
in readme of the project: https://github.com/Guseyn/rewrite-java-definitions
When I run the this Java Definition, I get error:
Exception in thread "main" java.lang.NoSuchMethodError: org.openrewrite.java.tree.J$NewClass.<init>(Ljava/util/UUID;Lorg/openrewrite/java/tree/J$Ident;Lorg/openrewrite/java/tree/J$NewClass$New;Lorg/openrewrite/java/tree/TypeTree;Lorg/openrewrite/java/tree/J$NewClass$Arguments;Lorg/openrewrite/java/tree/J$Block;Lorg/openrewrite/java/tree/JavaType;Lorg/openrewrite/Formatting;)V
at org.openrewrite.java.Java11ParserVisitor.visitNewClass(Java11ParserVisitor.java:945)
at org.openrewrite.java.Java11ParserVisitor.visitNewClass(Java11ParserVisitor.java:56)
at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCNewClass.accept(JCTree.java:1711)
at jdk.compiler/com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:82)
at org.openrewrite.java.Java11ParserVisitor.convert(Java11ParserVisitor.java:1278)
at org.openrewrite.java.Java11ParserVisitor.visitMethodInvocation(Java11ParserVisitor.java:734)
When I comment regular method:
package org.openrewrite.before;
import org.openrewrite.classes.ClassWithMethods;
public class E {
void foo() {
// new ClassWithMethods().foo();
ClassWithMethods.fooStatic();
}
}
and run the definition again, I get expected result:
package org.openrewrite.after;
import org.openrewrite.classes.ClassWithMethods;
public class E {
void foo() {
// new ClassWithMethods().foo();
ClassWithMethods.barStatic();
}
}
It seems to me that this visitor works only with static method, otherwise I get weird parsing error.
As can be seen in our documented example for AddField it accepts a String
which is parsed into the initialization expression for the field. When this string is parsed into an AST, it is unlikely to come out type-attributed. This leads to subtle problems running subsequent visitors which might be looking for that type.
AddField, and any other older visitors which accept a String that gets parsed into AST elements, should be updated to instead accept AST elements. The expectation then is that users would then use TreeBuilder
to construct type-attributed ASTs.
As part of fixing this, the docs for AddField should be updated and other visitors in rewrite-java should be spot checked to see if they have similar issues.
Currently we recognize a few license name texts, like "Apache License, Version 2.0" and "GPL", but there is much more variety in the wild west of Maven Central. Any unrecognized name is mapped to Unknown
.
Also, remove Other
since it is redundant with Unknown
.
Given input like:
public class D {public String foo() {String foo = "foo";foo = foo + foo;return foo;}}
I expect AutoFormat to produce output like:
public class D {
public String foo() {
String foo = "foo";
foo = foo + foo;
return foo;
}
}
Instead its actual output is:
public class D {
public String foo() {String foo = "foo"; foo = foo + foo;return foo;}}
Run AutoFormatTest.separatesStatementsWithEmptyFormatting() to reproduce this issue
Is there any plan to add support to kotlin method usage search and refactor?
When generating PRs, the PR should represent a set of file changes for those pieces of a refactoring operation that we can do automatically plus review comments on lines that require manual intervention. So it is enough to define a refactoring visitor that paints an AST element that requires manual intervention with RequiresManualIntervention
.
The PR generator can then use LineNumber
to identify the line number of the source file to add a review comment to (see #81).
When the following is parsed, "\npublic"
is included in the prefix of class
rather than being parsed as a modifier. This behavior only occurs with single line comments.
@Category()
// Some comment
public class B {
}
To recreate this behavior reference singleLineCommentParsingError.
Should have instructions on how to build from source, with recommended JDK version, IDE version, IDE plugin version, to invoke gradle via the wrapper, etc.
Much as the tests have been updated in the test module, also update the tests in the maven, xml, yaml, properties modules to fit the RefactorVistorTest
pattern established elsewhere.
We tried to fix it with this commit, but as this CI failure shows it's still an issue.
Disabling the test for now.
Lots of Java recipes need to add/remove imports. But where in the list of imports should the new one go?
There are many different common answers.
To deal with this, some currently not-entirely-known set of style information must be provided.
For Java that definitely includes import ordering, but what else?
For Yaml? Maven poms?
We should try to clarify what is mandatory up-front as early as possible, since making a new piece of style information mandatory later would be one of the obnoxious breaking changes we're trying to save our industry from.
When attempting to use the ChangeType recipe to swap org.mockito.Matchers
(used in mockito 1) with org.mockito.ArgumentMatchers
(used in mockito 2+) I observed that the import statements in the resulting code are missing the "org.mockito" bit.
Here's an example of the visitor:
@AutoConfigure
public class ReplaceMatchersWithArgumentMatchers extends JavaRefactorVisitor {
private final ChangeType changeAny = new ChangeType();
public ReplaceMatchersWithArgumentMatchers() {
changeAny.setType("org.mockito.Matchers");
changeAny.setTargetType("org.mockito.ArgumentMatchers");
}
@Override
public J visitCompilationUnit(J.CompilationUnit cu) {
return changeAny.visitCompilationUnit(cu);
}
}
Operating on code with imports like these:
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
Produces these invalid import statements:
import static ArgumentMatchers.any;
import static ArgumentMatchers.anyBoolean;
This isn't specific to the imports being static, all imports are affected.
This transformation should produce import statements like:
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
J.printAST()
should operate similarly to the print()
method in that it returns a String representation of the AST element which includes all of its children.
Unlike print()
, printAST()
is not expected to return Java source code, but instead directly transcribe the AST itself. The intended purpose of this is as a debugging tool for our own convenience as the developers of this software.
Implementing printAST()
will likely involve creating a PrintJavaAST
class that operates similarly to the existing org.openrewrite.java.internal.PrintJava
class.
One thing I've grappled with trying to work on this codebase is thinking in terms of the AST, rather than in terms of the source code. I suspect that easily being able to interrogate any such AST element for both its source code representation and its AST representation will be a useful debugging and onboarding-to-the-concepts tool.
The output of this method may resemble JSON, yaml, or a similar data format.
So for java source like:
package a;
public class A {
public void nonStatic() {}
}
Example output of printAST(), in a pseudo-JSON-ish format, may resemble something along these lines:
{ CompilationUnit :
sourcePath: "A.java"
imports: []
classes: [
{ ClassDecl:
name: { Ident(A)}
annotations: []
modifiers: [ {Modifier.Public} ]
typeParameters: null
extendings: null
body: { Block:
statik: null
statements: [
{ MethodDecl:
annotations: []
modifiers: [ { Modifier.Public }]
typeParameters: null
returnTypeExpr: { Primitive:
type: { "Void" }
}
params: { MethodDecl.Parameters
params: [ Empty ]
}
throwz: null
defaultValue: null
body: {
statik: null
statements: []
}
}
]
}
}
]
}
Should be updated in code, rewrite config files, documentation, and the projects that consume this one within openrewrite.
Optional Stretch goal: Include a "recipe" that operates on rewrite yaml configuration files and updates them to say "recipe" and "activeRecipes" instead of "profile" and "activeProfile".
Recipes are currently called "profiles" until #13 is complete
Remove any notion of recipes extending or inheriting from one another. This includes removing any mention of the "default" recipe, a concept which will no longer exist.
Remove any notion of recipes being defined in pieces across many places and merged together based on having the same name
No recipe should be executed unless the user has configured it as being among the active recipes via build tool plugin
CompositeSourceVisitor
delegates for default but not for visit
.
At instantiation of an inner classes, specifically when we have a .
expression with the new
keyword (e.g.,this.new B()
), Java8Parser adds the new
keyword at the beginning of the expression.
Consider the following as the original code,
class A {
void bar(B b, C c) {}
void foo() {
bar(this.new B(), this.new C());
}
class B { }
class C { }
}
And now just by parsing the above code without applying any change, I get the following output,
class A {
void bar(B b, C c) {}
void foo() {
bar(newthis.new B(), newthis.new C());
}
class B { }
class C { }
}
Here is the code I used to produce the above output,
JavaParser parser =
Java8Parser.builder()
.relaxedClassTypeMatching(true)
.logCompilationWarningsAndErrors(false)
.build();
String uri = "PATH_TO_FILE";
ArrayList<Path> p = new ArrayList<>();
p.add(Paths.get(uri));
ArrayList<J.CompilationUnit> trees = (ArrayList<J.CompilationUnit>) parser.parse(p);
J.CompilationUnit tree = trees.get(0);
System.out.println(tree.print());
As far as I understand maybeAddImport
adds imports only if it's really needed unlike simple addImport
. But in this example: https://docs.openrewrite.org/java/refactoring-java-source-code/addfield maybeAddImport
actually does not add import org.slf4j.LoggerFactory
, although it's need to be added since it's missing in the original code.
There are a couple of different situations where an unnecessary newline is being added to the name of the method and/or to the return type of the method. Only the first modifier, return type or name should have a prefix containing a newline, not multiple.
Reference AddAnnotationTest.addAnnotationToMethod() to recreate this behavior.
J.FieldAccess.isFullyQualifiedClassReference(MethodMatcher) allows for comparison between a FieldAccess
and a MethodMatcher
to see if they are describing the same fully qualified type or not.
But MethodMatcher
s can contain patterns/wildcards like "com.*.Bar" instead of something concrete like "com.foo.Bar". Currently isFullyQualifiedFieldAccess
will always return false
when comparing such MethodMatcher
s.
If a FieldReference to something like "com.foo.Bar" is compared against a MethodMatcher
that contains something like "com.*.Bar", isFullyQualifiedReference()
should return true
.
Recipes are currently called "profiles" until #13 is complete
We've decided that the user home is a valid place to store style information, like preferred import ordering, but defining any recipes/visitors there should not be allowed.
At the time of writing this issue I'm not actually sure if we are actively checking a user's home directory for anything or if that was just the plan. If we don't currently actively check the home directory for recipes, then this issue can be closed for now and we'll revisit later when we have a somewhat more rigorous concept of what a "Style" is.
Hi there!
I'm using the AddImport
java refactor visitor in a library refactoring I'm building. AddImport
delegates to OrderImports
in order to reorder the imports.
A few things:
AddImport
to disable reordering imports after adding an import (just a setter on the AddImport
object)?Layout
is be configurable from the AddImport
call? Our company style prefers explict imports, rather than wildcarded imports, so we'd prefer to be able to disable wildcard importing if we do end up wanting to re-order imports.Let me know what you think!
Thanks for openrewrite, we're just starting to use it for some large-scale library refactorings, and are enjoying it so far!
We are using annotations as an example, but this is being proposed for wherever there is a collection of elements in an AST to make creating, updating and deleting from these collections a better experience for the user.
J.Annotation newAnnot = buildAnnotation(formatting);
List<J.Annotation> annots = new ArrayList<>(c.getAnnotations());
annots.add(newAnnot);
c = c.withAnnotations(annots);
c = c.withNewAnnotation(newAnnot); // adds to the end
c = c.withNewAnnotation(newAnnot, 0); // adds to the start
public J.Annotation doSomethingWithAnnotation(J.Annotation annot) { ... }
public Stream<J.Annotation> returnsManyAnnotations(J.Annotation annot) { ... }
List<J.Annotation> annots = new ArrayList<>(c.getAnnotations());
annots = annots.stream()
.map(annot -> doSomethingWithAnnotation(annot))
.collect(toList());
c = c.withAnnotations(annots);
c = c.mapAnnotations(annot -> doSomethingWithAnnotation(annot));
c = c.flatMapAnnotations( annot -> Stream.of(doSomethingWithAnnotation(annot)));
c = c.flatMapAnnotations( annot -> returnsManyAnnotations(annot));
List<J.Annotation> annots = new ArrayList<>(c.getAnnotations());
annots = annots.stream()
.filter(annot -> annot == something)
.collect(toList());
c = c.withAnnotations(annots);
c = c.filterAnnotations(annot -> annot == something)
Given these sources:
package com.foo;
public class A {
public static int one() { return 1;}
public static int plusOne(int n) { return n + 1; }
}
package com.foo;
public class B {
public static int two() { return 2; }
public static int multiply(int n, int n2) { return n * n2; }
}
And this class that uses them:
package org.bar;
import static com.foo.A.one;
import static com.foo.A.plusOne;
import static com.foo.B.two;
import static com.foo.B.multiply;
public class C {
void c() {
multiply(plusOne(one()), two());
}
}
Visiting C
with OrderImports
should result in all four import statements still being present.
Instead this is the result:
package org.bar;
import static com.foo.A.one;
import static com.foo.A.plusOne;
public class C {
void c() {
multiply(plusOne(one()), two());
}
}
This happens whether or not removeUnused is set to true
or false
.
I haven't fully debugged but, for some reason, none of the import "blocks" accept the imports from "B". It's also peculiar that the imports from "A" end up in different blocks.
OrderImportsTest.moreStaticImportFun() reproduces this issue
Recipes are currently called "profiles" until #13 is complete
Right now recipes can have simple names like "mockito" or "spring".
With #16 removing the concept of recipes being assembled from multiple pieces based on their name, it becomes an error to have multiple recipes with the same name.
To save us all from runtime errors due to name collision, let's go ahead and require recipe names to be fully qualified with a package-prefix.
This applies to all existing recipes as well as all new ones. No special treatment for anything org.openrewrite.
When applying a MethodMatcher like new MethodMatcher("a.A foo(int[])")
to methods like these:
package a;
class A {
// Should match this, but does not
void foo(int[] arg) { }
// Should not match this, but does
void foo(int arg)
}
It does not match the foo
with argument of type int[]
, which it should.
And it does match the foo
with argument of type int
, which it should not.
To reproduce this issue, un-@Disable
MethodMatcherTest.matchesPrimitiveArgument() test.
In this test project (https://github.com/guseyn/rewrite-java-definitions), I've create following example:
public class InsertMethodArgumentExample {
public static void main(String... args) throws IOException {
InsertMethodArgument ima = new InsertMethodArgument();
ima.setMethod("org.slf4j.Logger debug(String,..)");
ima.setIndex(0);
ima.setSource("MarkerFactory.getMarker(\"CONFIDENTIAL\")");
ChangePackageName cpn = new ChangePackageName();
cpn.setNewPackageName("org.openrewrite.after");
AddImport adi = new AddImport();
adi.setType("MarkerFactory");
adi.setOnlyIfReferenced(false);
RefactorProcessor.run(new ArrayList<RefactorVisitor<?>>(){{
add(ima);
add(adi);
add(cpn);
}}, "I.java");
}
}
RefactorProcessor.run()
takes file I.java
from folder before
, applies visitors which is in ArrayList
(as first argument) and then puts updated I.java
into after
folder.
This is how I.java
looks before:
package org.openrewrite.before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class I {
public void foo() {
Logger logger = LoggerFactory.getLogger(G.class);
logger.debug("message");
}
}
And this is how it looks after:
package org.openrewrite.after;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class I {
public void foo() {
Logger logger = LoggerFactory.getLogger(G.class);
logger.debug(MarkerFactory.getMarker("CONFIDENTIAL"), "message");
}
}
As you can see, import org.slf4j.MarkerFactory;
is missing although I've explicitly created new AddImport()
visitor.
- org.openrewrite.java.ChangeMethodName:
method: org.mockito.Matchers anyVararg()
name: any
Should turn import static org.mockito.Matchers.anyVararg;
into import static org.mockito.Matchers.any;
Anything extending from JavaRefactorVisitor
has visit
methods which return a J
, the abstract type from which all Java AST elements extend.
This is a very flexible API, as it allows you to do things like visit a field and return a method declaration.
In practice, few visitors need this flexibility, and those that don't would be less verbose and easier to work with if they were constrained. Each visit method only returning the same type it accepts as an argument would make the API easier to work with and require less casting.
Create a new subtype of JavaRefactorVisitor
where visitField
only returns fields, visitMethod
only returns methods, etc.
This new subtype of JavaRefactorVisitor
can be called JavaIsomorphicRefactorVisitor
(name not final).
This issue does not include migrating all of the existing visitors that could be isomorphic visitors to the new class. That can be a separate issue.
No changes need to be made to JavaRefactorVisitor
itself. There are visitors which do require its flexibility.
We created RefactorVisitorTest to provide a convenient, declarative syntax for writing tests of Rewrite Visitors. Many of the tests under rewrite-test predate RefactorVisitorTest and therefore don't take advantage of it and are written in an older style.
The task is to update all of the older style visitor tests to use the new form.
Using AddImportTest.addNamedImport() as an example, currently it looks like this:
@Test
fun addNamedImport(jp: JavaParser) {
"class A {}"
.whenParsedBy(jp)
.whenVisitedBy(AddImport().apply { setType("java.util.List"); setOnlyIfReferenced(false) })
.isRefactoredTo("""
import java.util.List;
class A {}
""")
}
Rewritten as a RefactorVisitorTest that same test case would look like:
@Test
fun addNamedImport2(jp: JavaParser) = assertRefactored(jp,
visitors = listOf(AddImport().apply { setType("java.util.List"); setOnlyIfReferenced(false) }),
before = """
class A {}
""",
after = """
import java.util.List;
class A {}
"""
)
The following annotations are semantically equal, but because the first would be an Ident and the second would be an Assign, they would not be considered equal. This edge case needs to be implemented in SemanticallyEqual.
Example 1:
@ExampleAnnotation("a value")
@ExampleAnnotation(value = "a value")
Example 2:
@ExampleAnnotation({"a value"})
@ExampleAnnotation(value = {"a value"})
J.NewClass represents the invocation of a constructor, e.g.: new String("foo")
. This is understandable as at the call site the names of the arguments are not present.
But it would be useful for recipes which operate on constructors to have this information.
This can be worked around with TypeUtils.asClass(newClass.getType()).getConstructors()
J.NewClass should have an Arguments
field the same as MethodInvocation does.
If we find any repository URLs encoded in old POMs, replace them before fetching dependencies:
<url>http://dl.bintray.com/andsel/maven/</url>
Should only add a dependency if the dependency is not already effectively on the classpath either directly as a first order dependency or as a transitive dependency in a matching scope or lower scope.
In Java static methods are often used to provide access to instance creation when directly using new
is, for a variety of possible reasons, undesirable or impractical.
Implementing a JavaRefactorVisitor
that overrides visitNewClass
and returns a J.MethodInvocation instead of the J.NewClass that originally represented the constructor invocation had an unexpected result.
Input, attempting to swap "new A()" with a call to A.factory():
class B {
public static void foo() {
A a = new A();
}
}
Output:
class B {
public static void foo() {
A a = A factory()();
}
}
This replacement should instead result in:
class B {
public static void foo() {
A a = A.factory();
}
}
At some point openrewrite.org will be a real website and we will have formal specifications for concepts like "visitor" available there under openrewrite.org/spec//
This is conceptually similar to how xml documents provide URLs to their schema definitions.
Currently recipe types look like: beta.openrewrite.org/v1/visitor
Instead they should be: openrewrite.org/spec/v1beta/visitor
This includes having rewrite core reject rule types that include openrewrite.org but are missing /
No particular requirement is placed on non-openrewrite.org type urls
I think we need a visitor that changes package name in classes, it's very useful and as I can see it's not implemented yet.
Given an static utility class like this one:
package com.foo;
public class A {
public static void foo(String bar) {}
public static String stringify(Integer baz) { return baz.toString(); }
public static Integer numberOne() { return 1; }
}
And a usage like:
package org.bar;
import static com.foo.A.*;
class B {
void bar() {
foo(stringify(numberOne()));
}
}
When visited by RemoveUnusedImports
(or OrderImports
with removeUnused = true
) the result will be:
package org.bar;
import static com.foo.A.foo;
class B {
void bar() {
foo(stringify(numberOne()));
}
}
Which will result in stringify()
and numberOne()
being unknown symbols.
OrderImportsTest.preservesStaticMethodArguments exercises this issue
ChangeType currently assumes that its from/to types are JavaType.Class
es. I've confirmed that it doesn't work for int
-> Integer
or for Integer
-> int
, although the failure mode differs.
I've added disabled tests to ChangeTypeTest to reproduce this issue.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.