mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 15:19:59 +07:00
[java, completion] generate a provider method while using jigsaw services IDEA-347698
GitOrigin-RevId: 146fa445dcb5426eba5d8fa1d4e1a61d892cee18
This commit is contained in:
committed by
intellij-monorepo-bot
parent
9760eeb0e6
commit
3d708aa8d7
@@ -1383,6 +1383,7 @@
|
||||
implementationClass="com.intellij.codeInsight.completion.JShellCompletionContributor"/>
|
||||
|
||||
<completion.contributor language="JAVA" id="jvmLogger" implementationClass="com.intellij.codeInsight.completion.JvmLoggerCompletionContributor"/>
|
||||
<completion.contributor language="JAVA" id="jigsaw" implementationClass="com.intellij.codeInsight.completion.JigsawCompletionContributor"/>
|
||||
<weigher implementationClass="com.intellij.codeInsight.completion.LoggerWeigher" key="completion" id="logger"/>
|
||||
|
||||
<completion.confidence language="JAVA" implementationClass="com.intellij.psi.impl.source.resolve.reference.impl.JavaReflectionCompletionConfidence" id="javaReflection" />
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.template.JavaCodeContextType;
|
||||
import com.intellij.codeInsight.template.TemplateActionContext;
|
||||
import com.intellij.codeInsight.template.impl.TemplateContextTypes;
|
||||
import com.intellij.codeInspection.jigsaw.JigsawUtil;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.patterns.PsiJavaPatterns;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiIdentifier;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class JigsawCompletionContributor extends CompletionContributor {
|
||||
public JigsawCompletionContributor() {
|
||||
extend(CompletionType.BASIC, PsiJavaPatterns.psiElement(PsiIdentifier.class)
|
||||
.inside(PsiClass.class)
|
||||
.withLanguage(JavaLanguage.INSTANCE), new CompletionProvider<>() {
|
||||
@Override
|
||||
public void addCompletions(@NotNull CompletionParameters parameters,
|
||||
@NotNull ProcessingContext context,
|
||||
@NotNull CompletionResultSet resultSet) {
|
||||
TemplateActionContext templateActionContext = TemplateActionContext.create(parameters.getOriginalFile(),
|
||||
parameters.getEditor(),
|
||||
parameters.getOffset() - 1,
|
||||
parameters.getOffset() - 1, false);
|
||||
JavaCodeContextType declaration = TemplateContextTypes.getByClass(JavaCodeContextType.Declaration.class);
|
||||
if (!declaration.isInContext(templateActionContext)) return;
|
||||
|
||||
PsiElement element = parameters.getPosition();
|
||||
PsiClass targetClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
|
||||
|
||||
if (!JigsawUtil.checkProviderMethodAccessible(targetClass)) return;
|
||||
|
||||
String className = targetClass.getName();
|
||||
if (className == null) return;
|
||||
|
||||
resultSet.addElement(new JigsawProviderLookupElement(targetClass));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementPresentation;
|
||||
import com.intellij.codeInspection.jigsaw.JigsawApiConstants;
|
||||
import com.intellij.codeInspection.jigsaw.JigsawUtil;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class JigsawProviderLookupElement extends LookupElement {
|
||||
private final PsiClass myPsiClass;
|
||||
|
||||
public JigsawProviderLookupElement(PsiClass aClass) { myPsiClass = aClass; }
|
||||
|
||||
@Override
|
||||
public @NotNull String getLookupString() {
|
||||
return JigsawApiConstants.PROVIDER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderElement(@NotNull LookupElementPresentation presentation) {
|
||||
super.renderElement(presentation);
|
||||
presentation.setTypeText("provider() method declaration");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleInsert(@NotNull InsertionContext context) {
|
||||
int selectionLength = context.getSelectionEndOffset() - context.getStartOffset();
|
||||
JigsawUtil.addProviderMethod(myPsiClass, context.getEditor(), context.getStartOffset(),
|
||||
(offset, content) -> context.getDocument().replaceString(offset, offset + selectionLength,
|
||||
content));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.generation;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightActionHandler;
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInspection.jigsaw.JigsawUtil;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiJavaFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class GenerateProviderMethodHandler implements CodeInsightActionHandler {
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
|
||||
if (!(file instanceof PsiJavaFile)) return;
|
||||
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
PsiElement context = getContext(file.findElementAt(offset));
|
||||
if (context == null) return;
|
||||
|
||||
PsiClass targetClass = PsiTreeUtil.getParentOfType(context, PsiClass.class, false);
|
||||
|
||||
if (!JigsawUtil.checkProviderMethodAccessible(targetClass)) return;
|
||||
if (!FileModificationService.getInstance().preparePsiElementsForWrite(targetClass)) return;
|
||||
|
||||
WriteCommandAction.writeCommandAction(project, file)
|
||||
.run(() -> JigsawUtil.addProviderMethod(targetClass, editor, getOffset(context, offset),
|
||||
(currentOffset, content) -> editor.getDocument().insertString(currentOffset, content)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the context of a given PsiElement.
|
||||
* The context refers to the nearest parent that is a PsiClass.
|
||||
*
|
||||
* @param context the initial PsiElement
|
||||
* @return the context PsiElement, or null if no context is found
|
||||
*/
|
||||
@Nullable
|
||||
private static PsiElement getContext(@Nullable PsiElement context) {
|
||||
while (context != null && !(context.getParent() instanceof PsiClass)) {
|
||||
context = context.getParent();
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
private static int getOffset(@NotNull PsiElement context, int defaultOffset) {
|
||||
PsiElement child = context.getFirstChild();
|
||||
return child != null ? child.getTextOffset() : defaultOffset;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.generation.actions;
|
||||
|
||||
import com.intellij.codeInsight.generation.GenerateProviderMethodHandler;
|
||||
import com.intellij.codeInspection.jigsaw.JigsawUtil;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.psi.PsiClass;
|
||||
|
||||
public class GenerateProviderMethodAction extends BaseGenerateAction implements DumbAware {
|
||||
public GenerateProviderMethodAction() {
|
||||
super(new GenerateProviderMethodHandler());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValidForClass(PsiClass targetClass) {
|
||||
if (!super.isValidForClass(targetClass)) return false;
|
||||
if (!targetClass.isWritable()) return false;
|
||||
return JigsawUtil.checkProviderMethodAccessible(targetClass);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInspection.jigsaw;
|
||||
|
||||
public interface JigsawApiConstants {
|
||||
String PROVIDER = "provider";
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInspection.jigsaw;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
|
||||
import com.intellij.lang.jvm.JvmMethod;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.impl.light.LightJavaModule;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public final class JigsawUtil {
|
||||
private JigsawUtil() { }
|
||||
|
||||
public static void addProviderMethod(@NotNull PsiClass targetClass,
|
||||
@NotNull Editor editor,
|
||||
int startOffset,
|
||||
@NotNull BiConsumer<Integer, String> setMethod) {
|
||||
String className = targetClass.getName();
|
||||
if (className == null) return;
|
||||
|
||||
String methodStringBeforeCursor = "public static " + className + " " + JigsawApiConstants.PROVIDER + "() {" +
|
||||
"return new " + className + "(";
|
||||
String methodStringAfterCursor = ");}";
|
||||
|
||||
Document document = editor.getDocument();
|
||||
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(targetClass.getProject());
|
||||
|
||||
setMethod.accept(startOffset, methodStringBeforeCursor + methodStringAfterCursor);
|
||||
|
||||
editor.getCaretModel().moveToOffset(startOffset + methodStringBeforeCursor.length());
|
||||
documentManager.commitDocument(document);
|
||||
documentManager.doPostponedOperationsAndUnblockDocument(document);
|
||||
|
||||
PsiFile psiFile = documentManager.getPsiFile(document);
|
||||
if (psiFile != null) {
|
||||
CodeStyleManager.getInstance(targetClass.getProject())
|
||||
.reformatText(psiFile, startOffset, startOffset + methodStringBeforeCursor.length() + methodStringAfterCursor.length() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Contract("null -> false")
|
||||
public static boolean checkProviderMethodAccessible(@Nullable PsiClass targetClass) {
|
||||
if (targetClass == null || targetClass.getName() == null) return false;
|
||||
JvmMethod[] methods = targetClass.findMethodsByName(JigsawApiConstants.PROVIDER);
|
||||
for (JvmMethod method : methods) {
|
||||
if (!method.hasParameters()) return false;
|
||||
}
|
||||
PsiJavaModule descriptor = JavaModuleGraphUtil.findDescriptorByElement(targetClass.getContainingFile().getOriginalFile());
|
||||
if (descriptor == null || descriptor instanceof LightJavaModule) return false;
|
||||
|
||||
Iterable<PsiProvidesStatement> providers = descriptor.getProvides();
|
||||
for (PsiProvidesStatement provider : providers) {
|
||||
PsiReferenceList implementations = provider.getImplementationList();
|
||||
if (implementations == null) continue;
|
||||
for (PsiClassType type : implementations.getReferencedTypes()) {
|
||||
if (targetClass.isEquivalentTo(type.resolve())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
6
java/java-tests/testData/codeInsight/completion/providerMethod/after/.idea/misc.xml
generated
Normal file
6
java/java-tests/testData/codeInsight/completion/providerMethod/after/.idea/misc.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
9
java/java-tests/testData/codeInsight/completion/providerMethod/after/.idea/modules.xml
generated
Normal file
9
java/java-tests/testData/codeInsight/completion/providerMethod/after/.idea/modules.xml
generated
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/providers.iml" filepath="$PROJECT_DIR$/providers.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/sub/sub.iml" filepath="$PROJECT_DIR$/sub/sub.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="sub" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,18 @@
|
||||
import org.jetbrains.providers.MyProviderImpl;
|
||||
import org.jetbrains.providers.MySuperClass.MySubProviderImpl;
|
||||
import org.jetbrains.providers.MyRecord;
|
||||
import org.jetbrains.providers.WithProvider;
|
||||
import org.jetbrains.providers.WrongPlace;
|
||||
import org.jetbrains.providers.WrongPlace2;
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
module my.providers {
|
||||
uses MyProviderInterface;
|
||||
requires sub.module;
|
||||
provides MyProviderInterface with MyProviderImpl,
|
||||
MySubProviderImpl,
|
||||
MyRecord,
|
||||
WithProvider,
|
||||
WrongPlace,
|
||||
WrongPlace2;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public class MyProviderImpl implements MyProviderInterface {
|
||||
public static MyProviderImpl provider() {
|
||||
return new MyProviderImpl(<caret>);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public record MyRecord(String a) implements MyProviderInterface {
|
||||
public static MyRecord provider() {
|
||||
return new MyRecord(<caret>);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
public class MySuperClass {
|
||||
public static class MySubProviderImpl extends MyProviderImpl {
|
||||
public MySubProviderImpl() {
|
||||
}
|
||||
|
||||
public static MySubProviderImpl provider() {
|
||||
return new MySubProviderImpl(<caret>);
|
||||
}
|
||||
|
||||
public static void method() {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public class SimpleClass implements MyProviderInterface {
|
||||
pr<caret>
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public class WithProvider implements MyProviderInterface {
|
||||
pr<caret>
|
||||
public static WithProvider provider() {
|
||||
return new WithProvider();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public class WrongPlace implements MyProviderInterface {
|
||||
public static void method() {
|
||||
pr<caret>
|
||||
}
|
||||
|
||||
private static void program() {
|
||||
|
||||
}
|
||||
|
||||
private static void process() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public class WrongPlace2 implements MyProviderInterface {
|
||||
public static void pr<caret> method() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
module sub.module {
|
||||
exports org.jetbraons.api;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package org.jetbraons.api;
|
||||
|
||||
public interface MyProviderInterface {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
6
java/java-tests/testData/codeInsight/completion/providerMethod/before/.idea/misc.xml
generated
Normal file
6
java/java-tests/testData/codeInsight/completion/providerMethod/before/.idea/misc.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
9
java/java-tests/testData/codeInsight/completion/providerMethod/before/.idea/modules.xml
generated
Normal file
9
java/java-tests/testData/codeInsight/completion/providerMethod/before/.idea/modules.xml
generated
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/providers.iml" filepath="$PROJECT_DIR$/providers.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/sub/sub.iml" filepath="$PROJECT_DIR$/sub/sub.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="sub" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,18 @@
|
||||
import org.jetbrains.providers.MyProviderImpl;
|
||||
import org.jetbrains.providers.MySuperClass.MySubProviderImpl;
|
||||
import org.jetbrains.providers.MyRecord;
|
||||
import org.jetbrains.providers.WithProvider;
|
||||
import org.jetbrains.providers.WrongPlace;
|
||||
import org.jetbrains.providers.WrongPlace2;
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
module my.providers {
|
||||
uses MyProviderInterface;
|
||||
requires sub.module;
|
||||
provides MyProviderInterface with MyProviderImpl,
|
||||
MySubProviderImpl,
|
||||
MyRecord,
|
||||
WithProvider,
|
||||
WrongPlace,
|
||||
WrongPlace2;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public class MyProviderImpl implements MyProviderInterface {
|
||||
pr<caret>
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public record MyRecord(String a) implements MyProviderInterface {
|
||||
pr<caret>
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
public class MySuperClass {
|
||||
public static class MySubProviderImpl extends MyProviderImpl {
|
||||
public MySubProviderImpl() {
|
||||
}
|
||||
|
||||
pr<caret>public static void method() {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public class SimpleClass implements MyProviderInterface {
|
||||
pr<caret>
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public class WithProvider implements MyProviderInterface {
|
||||
pr<caret>
|
||||
public static WithProvider provider() {
|
||||
return new WithProvider();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public class WrongPlace implements MyProviderInterface {
|
||||
public static void method() {
|
||||
pr<caret>
|
||||
}
|
||||
|
||||
private static void program() {
|
||||
|
||||
}
|
||||
|
||||
private static void process() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public class WrongPlace2 implements MyProviderInterface {
|
||||
public static void pr<caret> method() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
module sub.module {
|
||||
exports org.jetbraons.api;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package org.jetbraons.api;
|
||||
|
||||
public interface MyProviderInterface {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
6
java/java-tests/testData/codeInsight/generateProviderMethod/after/.idea/misc.xml
generated
Normal file
6
java/java-tests/testData/codeInsight/generateProviderMethod/after/.idea/misc.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
9
java/java-tests/testData/codeInsight/generateProviderMethod/after/.idea/modules.xml
generated
Normal file
9
java/java-tests/testData/codeInsight/generateProviderMethod/after/.idea/modules.xml
generated
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/providers.iml" filepath="$PROJECT_DIR$/providers.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/sub/sub.iml" filepath="$PROJECT_DIR$/sub/sub.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="sub" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,11 @@
|
||||
import org.jetbrains.providers.MyProviderImpl;
|
||||
import org.jetbrains.providers.MySuperClass.MySubProviderImpl;
|
||||
import org.jetbrains.providers.MyRecord;
|
||||
import org.jetbrains.providers.WithProvider;
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
module my.providers {
|
||||
uses MyProviderInterface;
|
||||
requires sub.module;
|
||||
provides MyProviderInterface with MyProviderImpl, MySubProviderImpl, MyRecord, WithProvider;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public class MyProviderImpl implements MyProviderInterface {
|
||||
public static MyProviderImpl provider() {
|
||||
return new MyProviderImpl(<caret>);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public record MyRecord(String a) implements MyProviderInterface {
|
||||
public static MyRecord provider() {
|
||||
return new MyRecord(<caret>);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
public class MySuperClass {
|
||||
public static class MySubProviderImpl extends MyProviderImpl {
|
||||
public static MySubProviderImpl provider() {
|
||||
return new MySubProviderImpl(<caret>);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public class SimpleClass implements MyProviderInterface {
|
||||
<caret>
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public class WithProvider implements MyProviderInterface {
|
||||
<caret>
|
||||
public static WithProvider provider() {
|
||||
return new WithProvider();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public class WrongPlace implements MyProviderInterface {
|
||||
private static int a = 0;
|
||||
|
||||
public static WrongPlace provider() {
|
||||
return new WrongPlace(<caret>);
|
||||
}
|
||||
|
||||
public WrongPlace() {}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
module sub.module {
|
||||
exports org.jetbraons.api;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package org.jetbraons.api;
|
||||
|
||||
public interface MyProviderInterface {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
6
java/java-tests/testData/codeInsight/generateProviderMethod/before/.idea/misc.xml
generated
Normal file
6
java/java-tests/testData/codeInsight/generateProviderMethod/before/.idea/misc.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
9
java/java-tests/testData/codeInsight/generateProviderMethod/before/.idea/modules.xml
generated
Normal file
9
java/java-tests/testData/codeInsight/generateProviderMethod/before/.idea/modules.xml
generated
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/providers.iml" filepath="$PROJECT_DIR$/providers.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/sub/sub.iml" filepath="$PROJECT_DIR$/sub/sub.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="sub" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,12 @@
|
||||
import org.jetbrains.providers.MyProviderImpl;
|
||||
import org.jetbrains.providers.MySuperClass.MySubProviderImpl;
|
||||
import org.jetbrains.providers.MyRecord;
|
||||
import org.jetbrains.providers.WithProvider;
|
||||
import org.jetbrains.providers.WrongPlace;
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
module my.providers {
|
||||
uses MyProviderInterface;
|
||||
requires sub.module;
|
||||
provides MyProviderInterface with MyProviderImpl, MySubProviderImpl, MyRecord, WithProvider, WrongPlace;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public class MyProviderImpl implements MyProviderInterface {
|
||||
<caret>
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public record MyRecord(String a) implements MyProviderInterface {
|
||||
<caret>
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
public class MySuperClass {
|
||||
public static class MySubProviderImpl extends MyProviderImpl {
|
||||
<caret>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public class SimpleClass implements MyProviderInterface {
|
||||
<caret>
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public class WithProvider implements MyProviderInterface {
|
||||
<caret>
|
||||
public static WithProvider provider() {
|
||||
return new WithProvider();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.jetbrains.providers;
|
||||
|
||||
import org.jetbraons.api.MyProviderInterface;
|
||||
|
||||
public class WrongPlace implements MyProviderInterface {
|
||||
private static int a = 0;
|
||||
|
||||
public WrongPlace() {<caret>}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
module sub.module {
|
||||
exports org.jetbraons.api;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package org.jetbraons.api;
|
||||
|
||||
public interface MyProviderInterface {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.codeInsight;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.completion.LightFixtureCompletionTestCase;
|
||||
import com.intellij.codeInsight.generation.GenerateProviderMethodHandler;
|
||||
import com.intellij.java.testFramework.fixtures.MultiModuleProjectDescriptor;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.NeedsIndex;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
|
||||
@NeedsIndex.SmartMode(reason = "Provider method completion is not supported in the dumb mode")
|
||||
public class GenerateProviderMethodTest extends LightFixtureCompletionTestCase {
|
||||
|
||||
private MultiModuleProjectDescriptor myDescriptor;
|
||||
|
||||
@Override
|
||||
protected @NotNull LightProjectDescriptor getProjectDescriptor() {
|
||||
return myDescriptor == null
|
||||
? myDescriptor =
|
||||
new MultiModuleProjectDescriptor(Paths.get(getTestDataPath()), "providers", null)
|
||||
: myDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return JavaTestUtil.getJavaTestDataPath() + "/codeInsight/generateProviderMethod";
|
||||
}
|
||||
|
||||
public void testNonModuleClass() {
|
||||
doTest("src/org/jetbrains/providers/SimpleClass.java");
|
||||
}
|
||||
|
||||
public void testSimpleProvider() {
|
||||
doTest("src/org/jetbrains/providers/MyProviderImpl.java");
|
||||
}
|
||||
|
||||
public void testWithRecord() {
|
||||
doTest("src/org/jetbrains/providers/MyRecord.java");
|
||||
}
|
||||
|
||||
public void testWithProvider() {
|
||||
doTest("src/org/jetbrains/providers/WithProvider.java");
|
||||
}
|
||||
|
||||
public void testSubClass() {
|
||||
doTest("src/org/jetbrains/providers/MySuperClass.java");
|
||||
}
|
||||
|
||||
public void testWrongPlace() {
|
||||
doTest("src/org/jetbrains/providers/WrongPlace.java");
|
||||
}
|
||||
|
||||
private void doTest(@NotNull String path) {
|
||||
VirtualFile file = getModule().getModuleFile().getParent().findFileByRelativePath(path);
|
||||
myFixture.configureFromExistingVirtualFile(file);
|
||||
|
||||
new GenerateProviderMethodHandler().invoke(getProject(), getEditor(), PsiManager.getInstance(getProject()).findFile(file));
|
||||
|
||||
checkResultByFile("after/" + path);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.codeInsight.completion;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.completion.LightFixtureCompletionTestCase;
|
||||
import com.intellij.codeInsight.lookup.Lookup;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.impl.LookupImpl;
|
||||
import com.intellij.java.testFramework.fixtures.MultiModuleProjectDescriptor;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.NeedsIndex;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Optional;
|
||||
|
||||
@NeedsIndex.SmartMode(reason = "Provider method completion is not supported in the dumb mode")
|
||||
public class ProviderMethodCompletionTest extends LightFixtureCompletionTestCase {
|
||||
private MultiModuleProjectDescriptor myDescriptor;
|
||||
|
||||
@Override
|
||||
protected @NotNull LightProjectDescriptor getProjectDescriptor() {
|
||||
return myDescriptor == null
|
||||
? myDescriptor =
|
||||
new MultiModuleProjectDescriptor(Paths.get(getTestDataPath()), "providers", null)
|
||||
: myDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return JavaTestUtil.getJavaTestDataPath() + "/codeInsight/completion/providerMethod";
|
||||
}
|
||||
|
||||
public void testNonModuleClass() {
|
||||
doTest("src/org/jetbrains/providers/SimpleClass.java", "private",
|
||||
"protected");
|
||||
}
|
||||
|
||||
public void testSimpleProvider() {
|
||||
doTest("src/org/jetbrains/providers/MyProviderImpl.java", "provider",
|
||||
"private",
|
||||
"protected");
|
||||
}
|
||||
|
||||
public void testWithRecord() {
|
||||
doTest("src/org/jetbrains/providers/MyRecord.java", "provider",
|
||||
"private",
|
||||
"protected");
|
||||
}
|
||||
|
||||
public void testWithProvider() {
|
||||
doTest("src/org/jetbrains/providers/WithProvider.java", "private",
|
||||
"protected");
|
||||
}
|
||||
|
||||
public void testSubClass() {
|
||||
doTest("src/org/jetbrains/providers/MySuperClass.java", "provider",
|
||||
"private",
|
||||
"protected");
|
||||
}
|
||||
|
||||
public void testWrongPlace() {
|
||||
doTest("src/org/jetbrains/providers/WrongPlace.java", "process", "program");
|
||||
}
|
||||
|
||||
public void testWrongPlace2() {
|
||||
doTest("src/org/jetbrains/providers/WrongPlace2.java");
|
||||
}
|
||||
|
||||
private void doTest(String path, String... names) {
|
||||
VirtualFile file = getModule().getModuleFile().getParent().findFileByRelativePath(path);
|
||||
myFixture.configureFromExistingVirtualFile(file);
|
||||
myFixture.completeBasic();
|
||||
|
||||
if (names.length != 0) {
|
||||
assertStringItems(names);
|
||||
|
||||
Optional<LookupElement> item = getLookup().getItems().stream().filter(le -> "provider".equals(le.getLookupString())).findFirst();
|
||||
if (item.isPresent()) {
|
||||
myFixture.getLookup().setCurrentItem(item.get());
|
||||
myFixture.finishLookup(Lookup.NORMAL_SELECT_CHAR);
|
||||
}
|
||||
}
|
||||
else {
|
||||
LookupImpl lookup = getLookup();
|
||||
if (lookup != null) {
|
||||
assertStringItems(names);
|
||||
}
|
||||
}
|
||||
checkResultByFile("after/" + path);
|
||||
}
|
||||
}
|
||||
@@ -237,6 +237,8 @@ action.GenerateGetter.text=Getter
|
||||
action.GenerateGetter.description=Generate getter
|
||||
action.GenerateSetter.text=Setter
|
||||
action.GenerateSetter.description=Generate setter
|
||||
action.GenerateProviderMethod.text=provider()
|
||||
action.GenerateProviderMethod.description=Generate provider method
|
||||
action.GenerateGetterAndSetter.text=Getter and Setter
|
||||
action.GenerateGetterAndSetter.description=Generate getter and setter
|
||||
action.GenerateEquals.text=equals() and hashCode()
|
||||
|
||||
@@ -288,6 +288,7 @@
|
||||
<action id="GenerateEquals" class="com.intellij.codeInsight.generation.actions.GenerateEqualsAction"/>
|
||||
<action id="Actions.ActionsPlugin.GenerateToString" class="org.jetbrains.java.generate.GenerateToStringAction"/>
|
||||
<action id="GenerateCreateUI" class="com.intellij.codeInsight.generation.actions.GenerateCreateUIAction"/>
|
||||
<action id="GenerateProviderMethod" class="com.intellij.codeInsight.generation.actions.GenerateProviderMethodAction"/>
|
||||
<add-to-group group-id="GenerateGroup" anchor="first"/>
|
||||
</group>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user