[java-intentions] Improve create method preview

GitOrigin-RevId: 9121bbda07694cdacab3508a83a08ba10e465d28
This commit is contained in:
Bart van Helvert
2022-10-31 16:34:06 +01:00
committed by intellij-monorepo-bot
parent 772791c821
commit e5fd0db64d
82 changed files with 103 additions and 95 deletions

View File

@@ -9,17 +9,18 @@ import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils.setupE
import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils.setupMethodBody
import com.intellij.codeInsight.daemon.impl.quickfix.GuessTypeParameters
import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo
import com.intellij.codeInsight.intention.preview.IntentionPreviewUtils
import com.intellij.codeInsight.template.Template
import com.intellij.codeInsight.template.TemplateBuilder
import com.intellij.codeInsight.template.TemplateBuilderImpl
import com.intellij.codeInsight.template.TemplateEditingAdapter
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.lang.java.request.CreateMethodFromJavaUsageRequest
import com.intellij.lang.jvm.JvmModifier
import com.intellij.lang.jvm.actions.*
import com.intellij.openapi.command.WriteCommandAction.runWriteCommandAction
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Computable
import com.intellij.psi.*
import com.intellij.psi.presentation.java.ClassPresentationUtil.getNameForClass
import com.intellij.psi.util.JavaElementKind
@@ -52,15 +53,17 @@ internal class CreateMethodAction(
return message("create.element.in.class", kind.`object`(), what, where)
}
private fun methodRenderer(project: Project) = JavaMethodRenderer(project, abstract, target, request)
override fun generatePreview(project: Project, editor: Editor, file: PsiFile): IntentionPreviewInfo {
val method = methodRenderer(project).renderMethod()
return IntentionPreviewInfo.CustomDiff(JavaFileType.INSTANCE, "", method.text)
val copyClass = PsiTreeUtil.findSameElementInCopy(target, file)
val physicalRequest = request as? CreateMethodFromJavaUsageRequest ?: return IntentionPreviewInfo.EMPTY
val copyCall = PsiTreeUtil.findSameElementInCopy(physicalRequest.call, file)
val copyRequest = CreateMethodFromJavaUsageRequest(copyCall, physicalRequest.modifiers)
JavaMethodRenderer(project, abstract, copyClass, copyRequest).doMagic()
return IntentionPreviewInfo.DIFF
}
override fun invoke(project: Project, editor: Editor?, file: PsiFile?) {
methodRenderer(project).doMagic()
JavaMethodRenderer(project, abstract, target, request).doMagic()
}
}
@@ -152,13 +155,18 @@ private class MyMethodBodyListener(val project: Project, val editor: Editor, val
override fun templateFinished(template: Template, brokenOff: Boolean) {
if (brokenOff) return
runWriteCommandAction(project) {
PsiDocumentManager.getInstance(project).commitDocument(editor.document)
val offset = editor.caretModel.offset
PsiTreeUtil.findElementOfClassAtOffset(file, offset - 1, PsiMethod::class.java, false)?.let { method ->
setupMethodBody(method)
setupEditor(method, editor)
}
PsiDocumentManager.getInstance(project).commitDocument(editor.document)
val offset = editor.caretModel.offset
val method = PsiTreeUtil.findElementOfClassAtOffset(file, offset - 1, PsiMethod::class.java, false) ?: return
if (IntentionPreviewUtils.isIntentionPreviewActive()) {
finishTemplate(method)
} else {
WriteCommandAction.runWriteCommandAction(project, Computable { finishTemplate(method) })
}
}
private fun finishTemplate(method: PsiMethod) {
setupMethodBody(method)
setupEditor(method, editor)
}
}

View File

@@ -20,7 +20,7 @@ internal abstract class CreateExecutableFromJavaUsageRequest<out T : PsiCall>(
private val psiManager = call.manager
private val project = psiManager.project
private val callPointer: SmartPsiElementPointer<T> = call.createSmartPointer(project)
protected val call: T get() = callPointer.element ?: error("dead pointer")
internal val call: T get() = callPointer.element ?: error("dead pointer")
override fun isValid() = callPointer.element != null

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
public Test() {
test();

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
public Test() {
test();

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
public Test() {
test();

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
public Test() {
test();

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
static void test(int i) {}
public Test() {

View File

@@ -1,4 +1,4 @@
// "Create abstract method 'foo'" "true"
// "Create abstract method 'foo'" "true-preview"
class Usage {
void usage(Target t) {
t.foo();

View File

@@ -1,4 +1,4 @@
// "Create abstract method 'foo'" "true"
// "Create abstract method 'foo'" "true-preview"
class Usage {
void usage(Target t) {
t.foo();

View File

@@ -1,4 +1,4 @@
// "Create abstract method 'foo' in 'A'" "true"
// "Create abstract method 'foo' in 'A'" "true-preview"
abstract class A {
void usage() {
foo();

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
public Test() {
byte[] bytes = new byte[0];

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
class A {
{
assert false: f();

View File

@@ -1,4 +1,4 @@
// "Create method 'makeOp'" "true"
// "Create method 'makeOp'" "true-preview"
class Base<T> {
Base(Factory<T> factory, Operator<T> operator) {
}

View File

@@ -1,4 +1,4 @@
// "Create method 'getPreloadKeys'" "true"
// "Create method 'getPreloadKeys'" "true-preview"
import java.util.*;
class X {

View File

@@ -1,4 +1,4 @@
// "Create method 'getPreloadKeys'" "true"
// "Create method 'getPreloadKeys'" "true-preview"
import java.util.*;
class Foo<T>{

View File

@@ -1,4 +1,4 @@
// "Create method 'bar'" "true"
// "Create method 'bar'" "true-preview"
public class Test {
<T extends String> void foo (T t1, T t2) {
bar (t1, t2);

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
public Test() {
assert test();

View File

@@ -1,4 +1,4 @@
// "Create method 'toMulti'" "true"
// "Create method 'toMulti'" "true-preview"
import java.util.Map;
class BrokenCreateMethod {

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
void test(boolean b, Object obj) {
if (b || test() == obj) {

View File

@@ -1,4 +1,4 @@
// "Create method 'doSomething' in 'Test'" "true"
// "Create method 'doSomething' in 'Test'" "true-preview"
public class Test {
public static void main(String[] args) {
blaat(new Runnable() {

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public interface Test {
void test();

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
class A {
{
f(() -> {});

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
class A {
{
f(A::foo);

View File

@@ -1,4 +1,4 @@
// "Create method 'foo'" "true"
// "Create method 'foo'" "true-preview"
class Test {
<R, D> R foo(T<R, D> t, D data) {
return t.foo(this, data);

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
class A {
<T> T foo(){
B<T> x = f();

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
public class CreateMethodTest {
public <T> T aMethod(T t) {
T result = f(t);

View File

@@ -1,4 +1,4 @@
// "Create method 'f' in 'Nested" "true"
// "Create method 'f' in 'Nested" "true-preview"
public class CreateMethodTest {
public <T> void aMethod(final T t) {
class Nested {

View File

@@ -1,4 +1,4 @@
// "Create method 'bar'" "true"
// "Create method 'bar'" "true-preview"
class A {
public void foo() {
Object x = bar();

View File

@@ -1,4 +1,4 @@
// "Create method 'run'" "true"
// "Create method 'run'" "true-preview"
class Bug {
interface Foo<X> {

View File

@@ -1,4 +1,4 @@
// "Create method 'foo'" "true"
// "Create method 'foo'" "true-preview"
class A {
private List<? extends CharSequence> sequences = null;

View File

@@ -1,4 +1,4 @@
// "Create method 'test2'" "true"
// "Create method 'test2'" "true-preview"
class Foo {
static String FOO_BAR = "Bar";
void test1() { test2(FOO_BAR); }

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
class Test {
{
long l = f(1) + f(2);

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
class A {
{
double d = -f();

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
class A {
{
-f();

View File

@@ -1,4 +1,4 @@
// "Create method 'someMethod'" "true"
// "Create method 'someMethod'" "true-preview"
public class Test {
public Object get() {

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
class A {
{
new Runnable() {

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
public Test(Impl impl) {
impl.test(test());

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
interface X {
public static void m() {
f();

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
interface I {}
class A implements I {
{

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
public class A {
public A() {
this(f());

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
import java.util.List;
public class Test {
<T> void f(List<? extends T> l) {

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
{
int i = (Integer)test();

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
public Test() {
te<caret>st();

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
public Test() {
test(<caret>);

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
public Test() {
test()<caret>;

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
public Test() {
test();<caret>

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
static void test(int i) {}
public Test() {

View File

@@ -1,4 +1,4 @@
// "Create abstract method 'foo'" "true"
// "Create abstract method 'foo'" "true-preview"
class Usage {
void usage(Target t) {
t.<caret>foo();

View File

@@ -1,4 +1,4 @@
// "Create abstract method 'foo'" "true"
// "Create abstract method 'foo'" "true-preview"
class Usage {
void usage(Target t) {
t.<caret>foo();

View File

@@ -1,4 +1,4 @@
// "Create abstract method 'foo' in 'A'" "true"
// "Create abstract method 'foo' in 'A'" "true-preview"
abstract class A {
void usage() {
<caret>foo();

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
public Test() {
byte[] bytes = new byte[0];

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
class A {
{
assert false: f<caret>();

View File

@@ -1,4 +1,4 @@
// "Create method 'makeOp'" "true"
// "Create method 'makeOp'" "true-preview"
class Base<T> {
Base(Factory<T> factory, Operator<T> operator) {
}

View File

@@ -1,4 +1,4 @@
// "Create method 'getPreloadKeys'" "true"
// "Create method 'getPreloadKeys'" "true-preview"
import java.util.*;
class X {

View File

@@ -1,4 +1,4 @@
// "Create method 'getPreloadKeys'" "true"
// "Create method 'getPreloadKeys'" "true-preview"
import java.util.*;
class Foo<T>{

View File

@@ -1,4 +1,4 @@
// "Create method 'bar'" "true"
// "Create method 'bar'" "true-preview"
public class Test {
<T extends String> void foo (T t1, T t2) {
<caret>bar (t1, t2);

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
public Test() {
assert <caret>test();

View File

@@ -1,4 +1,4 @@
// "Create method 'toMulti'" "true"
// "Create method 'toMulti'" "true-preview"
import java.util.Map;
class BrokenCreateMethod {

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
void test(boolean b, Object obj) {
if (b || te<caret>st() == obj) {

View File

@@ -1,4 +1,4 @@
// "Create method 'doSomething' in 'Test'" "true"
// "Create method 'doSomething' in 'Test'" "true-preview"
public class Test {
public static void main(String[] args) {
blaat(new Runnable() {

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public interface Test {
}

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
class A {
{
f<caret>(() -> {});

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
class A {
{
f<caret>(A::foo);

View File

@@ -1,4 +1,4 @@
// "Create method 'foo'" "true"
// "Create method 'foo'" "true-preview"
class Test {
<R, D> R foo(T<R, D> t, D data) {
return t.f<caret>oo(this, data);

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
class A {
<T> T foo(){
B<T> x = f<caret>();

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
public class CreateMethodTest {
public <T> T aMethod(T t) {
T result = f<caret>(t);

View File

@@ -1,4 +1,4 @@
// "Create method 'f' in 'Nested" "true"
// "Create method 'f' in 'Nested" "true-preview"
public class CreateMethodTest {
public <T> void aMethod(final T t) {
class Nested {

View File

@@ -1,4 +1,4 @@
// "Create method 'bar'" "true"
// "Create method 'bar'" "true-preview"
class A {
public void foo() {
Object x = <caret>bar();

View File

@@ -1,4 +1,4 @@
// "Create method 'run'" "true"
// "Create method 'run'" "true-preview"
class Bug {
interface Foo<X> {

View File

@@ -1,4 +1,4 @@
// "Create method 'foo'" "true"
// "Create method 'foo'" "true-preview"
class A {
private List<? extends CharSequence> sequences = null;

View File

@@ -1,4 +1,4 @@
// "Create method 'test2'" "true"
// "Create method 'test2'" "true-preview"
class Foo {
static String FOO_BAR = "Bar";
void test1() { tes<caret>t2(FOO_BAR); }

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
class Test {
{
long l = f(1) + <caret>f(2);

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
class A {
{
double d = -f<caret>();

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
class A {
{
-f<caret>();

View File

@@ -1,4 +1,4 @@
// "Create method 'someMethod'" "true"
// "Create method 'someMethod'" "true-preview"
public class Test {
public Object get() {

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
class A {
{
new Runnable() {

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
public Test(Impl impl) {
impl.test(te<caret>st());

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
interface X {
public static void m() {
f<caret>();

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
interface I {}
class A implements I {
{

View File

@@ -1,4 +1,4 @@
// "Create method 'f'" "true"
// "Create method 'f'" "true-preview"
public class A {
public A() {
this(<caret>f());

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
import java.util.List;
public class Test {
<T> void f(List<? extends T> l) {

View File

@@ -1,4 +1,4 @@
// "Create method 'test'" "true"
// "Create method 'test'" "true-preview"
public class Test {
{
int i = (Integer)te<caret>st();