You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beam.apache.org by pa...@apache.org on 2023/06/20 20:22:39 UTC

[beam] branch master updated: [Code Completion Plugin] Define Element Pattern for java sdk

This is an automated email from the ASF dual-hosted git repository.

pabloem pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git


The following commit(s) were added to refs/heads/master by this push:
     new ef24b6a0aa2 [Code Completion Plugin] Define Element Pattern for java sdk
     new 08d49f0e0eb Merge pull request #27093 from sultanalieva-s/code-completion-plugin-element-pattern
ef24b6a0aa2 is described below

commit ef24b6a0aa29562da976794669904d36cb92b06d
Author: sultanalieva-s <sa...@gmail.com>
AuthorDate: Sat Jun 3 20:28:42 2023 +0500

    [Code Completion Plugin] Define Element Pattern for java sdk
---
 .../beam-code-completion-plugin/build.gradle.kts   |  1 +
 ...KPattern.java => BeamCompletionConfidence.java} | 19 ++---
 .../src/main/java/BeamCompletionContributor.java   | 81 +++++++++++++++++-----
 .../src/main/resources/META-INF/plugin.xml         |  4 +-
 .../java/BeamCompletionContributorTestCase.java    | 60 ++++++++++++++++
 .../testData/TestCompletions.java}                 | 30 ++++----
 .../TestCompletionsWrongClass.java}                | 21 ++++--
 .../testData/TestCompletionsWrongMethod.java}      | 29 ++++----
 8 files changed, 186 insertions(+), 59 deletions(-)

diff --git a/plugins/beam-code-completion-plugin/build.gradle.kts b/plugins/beam-code-completion-plugin/build.gradle.kts
index b8c10cf8d1f..cff54b9458f 100644
--- a/plugins/beam-code-completion-plugin/build.gradle.kts
+++ b/plugins/beam-code-completion-plugin/build.gradle.kts
@@ -65,5 +65,6 @@ tasks {
 }
 
 tasks.test {
+  systemProperty("idea.home.path", System.getenv("INTELLIJ_IDEA_SOURCES"))
   useJUnit()
 }
diff --git a/plugins/beam-code-completion-plugin/src/main/java/BeamJavaSDKPattern.java b/plugins/beam-code-completion-plugin/src/main/java/BeamCompletionConfidence.java
similarity index 62%
copy from plugins/beam-code-completion-plugin/src/main/java/BeamJavaSDKPattern.java
copy to plugins/beam-code-completion-plugin/src/main/java/BeamCompletionConfidence.java
index e60f76237d0..8ed107c5ee8 100644
--- a/plugins/beam-code-completion-plugin/src/main/java/BeamJavaSDKPattern.java
+++ b/plugins/beam-code-completion-plugin/src/main/java/BeamCompletionConfidence.java
@@ -16,19 +16,20 @@
  * limitations under the License.
  */
 
-import com.intellij.patterns.PatternCondition;
+import com.intellij.codeInsight.completion.CompletionConfidence;
 import com.intellij.psi.PsiElement;
-import com.intellij.util.ProcessingContext;
+import com.intellij.psi.PsiFile;
+import com.intellij.util.ThreeState;
 import org.jetbrains.annotations.NotNull;
 
 
-public class BeamJavaSDKPattern extends PatternCondition<PsiElement> {
-    BeamJavaSDKPattern() {
-        super("javaSDKPattern()");
-    }
-
+/**
+ * The `BeamCompletionConfidence` class is a subclass of `CompletionConfidence` that determines whether autopopup
+ * completion should be skipped for BeamCompletionContributor.
+ */
+public class BeamCompletionConfidence extends CompletionConfidence {
     @Override
-    public boolean accepts(@NotNull PsiElement psiElement, ProcessingContext context) {
-        return false;
+    public ThreeState shouldSkipAutopopup(@NotNull PsiElement contextElement, @NotNull PsiFile psiFile, int offset) {
+        return ThreeState.NO;
     }
 }
diff --git a/plugins/beam-code-completion-plugin/src/main/java/BeamCompletionContributor.java b/plugins/beam-code-completion-plugin/src/main/java/BeamCompletionContributor.java
index 969af4c1fe4..579aa750fd2 100644
--- a/plugins/beam-code-completion-plugin/src/main/java/BeamCompletionContributor.java
+++ b/plugins/beam-code-completion-plugin/src/main/java/BeamCompletionContributor.java
@@ -15,28 +15,75 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+import com.intellij.codeInsight.completion.*;
 
-
-import com.intellij.codeInsight.completion.CompletionContributor;
-import com.intellij.codeInsight.completion.CompletionType;
+import com.intellij.patterns.PatternCondition;
+import com.intellij.patterns.PsiJavaElementPattern;
 import com.intellij.patterns.PsiJavaPatterns;
-import com.intellij.psi.PsiElement;
-import org.jetbrains.annotations.NotNull;
+import static com.intellij.patterns.PlatformPatterns.psiElement;
 
+import com.intellij.psi.*;
+
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.util.ProcessingContext;
+import org.jetbrains.annotations.NotNull;
 
+/**
+ * The `BeamCompletionContributor` class is a subclass of `CompletionContributor` that provides code completion
+ * suggestions specifically for Apache Beam pipelines.
+ */
 public class BeamCompletionContributor extends CompletionContributor {
-    public BeamCompletionContributor() {
-        // completions for java files
-        extend(
-                CompletionType.BASIC,
-                PsiJavaPatterns.psiElement(),
-                new BeamCompletionProvider()
-        );
-    }
+    /**
+     * A pattern condition that matches method call expressions with the name "apply" in the context of the
+     * Apache Beam `Pipeline` class.
+     */
+    public static final PatternCondition<PsiMethodCallExpression> APPLY_METHOD_PATTERN = new PatternCondition<>("") {
+        @Override
+        public boolean accepts(@NotNull PsiMethodCallExpression psiMethodCallExpression, ProcessingContext context) {
+            String referenceName = psiMethodCallExpression.getMethodExpression().getReferenceName();
+            if (referenceName != null){
+                if (!referenceName.equals("apply")) {
+                    return false;
+                }
+                PsiMethod resolvedMethod = psiMethodCallExpression.resolveMethod();
+                if (resolvedMethod != null){
+                    PsiClass containingClass = resolvedMethod.getContainingClass();
+                    if (containingClass != null){
+                        return "org.apache.beam.sdk.Pipeline".equals(containingClass.getQualifiedName()) ||
+                                "org.apache.beam.sdk.values.PCollection".equals(containingClass.getQualifiedName());
+                    }
+                }
+            }
+            return false;
+        }
+    };
+
+    /**
+     * A pattern that matches an identifier after a method call expression that satisfies the `APPLY_METHOD_PATTERN`.
+     */
+    private static final PsiJavaElementPattern.Capture<PsiIdentifier> AFTER_METHOD_CALL_PATTERN =
+            PsiJavaPatterns.psiElement(PsiIdentifier.class)
+                    .withParent(
+                            psiElement(PsiReferenceExpression.class)
+                                    .withParent(
+                                            psiElement(PsiExpressionList.class)
+                                                    .withParent(
+                                                            psiElement(PsiMethodCallExpression.class)
+                                                                    .with(APPLY_METHOD_PATTERN)
+                                                    )
+                                    )
+                    );
+
+    /**
+     * Fills the completion variants for the given completion parameters and result set.
+     */
     @Override
-    public boolean invokeAutoPopup(@NotNull PsiElement position, char typeChar)
-    {
-        if (typeChar == '.'){return true;}
-        return false;
+    public void fillCompletionVariants(@NotNull final CompletionParameters parameters, @NotNull CompletionResultSet result) {
+        final PsiElement position = parameters.getPosition();
+        PrefixMatcher matcher = result.getPrefixMatcher();
+        PsiElement parent = position.getParent();
+        if (AFTER_METHOD_CALL_PATTERN.accepts(parameters.getPosition())){
+            result.addElement(LookupElementBuilder.create("TestCompletionElement"));
+        }
     }
 }
diff --git a/plugins/beam-code-completion-plugin/src/main/resources/META-INF/plugin.xml b/plugins/beam-code-completion-plugin/src/main/resources/META-INF/plugin.xml
index 361a5076cdd..c85dfcec2cc 100644
--- a/plugins/beam-code-completion-plugin/src/main/resources/META-INF/plugin.xml
+++ b/plugins/beam-code-completion-plugin/src/main/resources/META-INF/plugin.xml
@@ -43,7 +43,9 @@
   <!-- Extension points defined by the plugin.
        Read more: https://plugins.jetbrains.com/docs/intellij/plugin-extension-points.html -->
   <extensions defaultExtensionNs="com.intellij">
-    <completion.contributor language="JAVA"
+    <completion.contributor language="JAVA" order="first"
                             implementationClass="BeamCompletionContributor"></completion.contributor>
+
+    <completion.confidence  language="JAVA" order="first" implementationClass="BeamCompletionConfidence"></completion.confidence>
   </extensions>
 </idea-plugin>
diff --git a/plugins/beam-code-completion-plugin/src/test/java/BeamCompletionContributorTestCase.java b/plugins/beam-code-completion-plugin/src/test/java/BeamCompletionContributorTestCase.java
new file mode 100644
index 00000000000..8237238755d
--- /dev/null
+++ b/plugins/beam-code-completion-plugin/src/test/java/BeamCompletionContributorTestCase.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import com.intellij.codeInsight.completion.CompletionType;
+import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
+import org.jetbrains.annotations.NotNull;
+import com.intellij.testFramework.LightProjectDescriptor;
+import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor;
+
+import java.util.List;
+
+public class BeamCompletionContributorTestCase extends LightJavaCodeInsightFixtureTestCase {
+    @Override
+    protected String getTestDataPath() {
+        return "src/test/testData";
+    }
+
+    @Override
+    protected @NotNull LightProjectDescriptor getProjectDescriptor() {
+        return new DefaultLightProjectDescriptor().withRepositoryLibrary("org.apache.beam:beam-sdks-java-core:2.48.0");
+    }
+
+    public void testElementPatternIsTriggered() {
+        myFixture.configureByFile("TestCompletions.java");
+        myFixture.complete(CompletionType.BASIC);
+        List<String> lookupElementStrings = myFixture.getLookupElementStrings();
+        assertNotNull(lookupElementStrings);
+        assertEquals(lookupElementStrings.get(0), "TestCompletionElement");
+    }
+
+    public void testElementPatternWrongClass() {
+        myFixture.configureByFile("TestCompletionsWrongClass.java");
+        myFixture.complete(CompletionType.BASIC);
+        List<String> lookupElementStrings = myFixture.getLookupElementStrings();
+        assertNotNull(lookupElementStrings);
+        assertNotSame(lookupElementStrings.get(0), "TestCompletionElement");
+    }
+
+    public void testElementPatternWrongMethod() {
+        myFixture.configureByFile("TestCompletionsWrongMethod.java");
+        myFixture.complete(CompletionType.BASIC);
+        List<String> lookupElementStrings = myFixture.getLookupElementStrings();
+        assertNotNull(lookupElementStrings);
+        assertNotSame(lookupElementStrings.get(0), "TestCompletionElement");
+    }
+}
diff --git a/plugins/beam-code-completion-plugin/src/main/java/BeamJavaSDKPattern.java b/plugins/beam-code-completion-plugin/src/test/testData/TestCompletions.java
similarity index 53%
copy from plugins/beam-code-completion-plugin/src/main/java/BeamJavaSDKPattern.java
copy to plugins/beam-code-completion-plugin/src/test/testData/TestCompletions.java
index e60f76237d0..c211f12c8a2 100644
--- a/plugins/beam-code-completion-plugin/src/main/java/BeamJavaSDKPattern.java
+++ b/plugins/beam-code-completion-plugin/src/test/testData/TestCompletions.java
@@ -16,19 +16,23 @@
  * limitations under the License.
  */
 
-import com.intellij.patterns.PatternCondition;
-import com.intellij.psi.PsiElement;
-import com.intellij.util.ProcessingContext;
-import org.jetbrains.annotations.NotNull;
+import java.util.Arrays;
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.io.TextIO;
+import org.apache.beam.sdk.options.PipelineOptions;
+import org.apache.beam.sdk.options.PipelineOptionsFactory;
+import org.apache.beam.sdk.transforms.Count;
+import org.apache.beam.sdk.transforms.Filter;
+import org.apache.beam.sdk.transforms.FlatMapElements;
+import org.apache.beam.sdk.transforms.MapElements;
+import org.apache.beam.sdk.values.KV;
+import org.apache.beam.sdk.values.TypeDescriptors;
 
-
-public class BeamJavaSDKPattern extends PatternCondition<PsiElement> {
-    BeamJavaSDKPattern() {
-        super("javaSDKPattern()");
-    }
-
-    @Override
-    public boolean accepts(@NotNull PsiElement psiElement, ProcessingContext context) {
-        return false;
+public class TestCompletions {
+    public static void main(String[] args) {
+        PipelineOptions options = PipelineOptionsFactory.create();
+        Pipeline p = Pipeline.create(options);
+        p.apply(T<caret>);
     }
 }
+
diff --git a/plugins/beam-code-completion-plugin/src/test/java/BeamCompletionContributorTestcase.java b/plugins/beam-code-completion-plugin/src/test/testData/TestCompletionsWrongClass.java
similarity index 55%
rename from plugins/beam-code-completion-plugin/src/test/java/BeamCompletionContributorTestcase.java
rename to plugins/beam-code-completion-plugin/src/test/testData/TestCompletionsWrongClass.java
index 630ed795caa..5f882b3d5b3 100644
--- a/plugins/beam-code-completion-plugin/src/test/java/BeamCompletionContributorTestcase.java
+++ b/plugins/beam-code-completion-plugin/src/test/testData/TestCompletionsWrongClass.java
@@ -16,12 +16,21 @@
  * limitations under the License.
  */
 
+import java.util.Arrays;
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.io.TextIO;
+import org.apache.beam.sdk.options.PipelineOptions;
+import org.apache.beam.sdk.options.PipelineOptionsFactory;
+import org.apache.beam.sdk.transforms.Count;
+import org.apache.beam.sdk.transforms.Filter;
+import org.apache.beam.sdk.transforms.FlatMapElements;
+import org.apache.beam.sdk.transforms.MapElements;
+import org.apache.beam.sdk.values.KV;
+import org.apache.beam.sdk.values.TypeDescriptors;
 
-import com.intellij.testFramework.fixtures.BasePlatformTestCase;
-import org.junit.Assert;
-
-public class BeamCompletionContributorTestcase extends BasePlatformTestCase {
-    public void testAutoPopupCompletions() {
-        Assert.assertEquals(2,2);
+public class TestCompletionsWrongClass {
+    public static void main(String[] args) {
+        String test = "Test";
+        test.apply(T<caret>);
     }
 }
diff --git a/plugins/beam-code-completion-plugin/src/main/java/BeamJavaSDKPattern.java b/plugins/beam-code-completion-plugin/src/test/testData/TestCompletionsWrongMethod.java
similarity index 54%
rename from plugins/beam-code-completion-plugin/src/main/java/BeamJavaSDKPattern.java
rename to plugins/beam-code-completion-plugin/src/test/testData/TestCompletionsWrongMethod.java
index e60f76237d0..74feeaa9ded 100644
--- a/plugins/beam-code-completion-plugin/src/main/java/BeamJavaSDKPattern.java
+++ b/plugins/beam-code-completion-plugin/src/test/testData/TestCompletionsWrongMethod.java
@@ -16,19 +16,22 @@
  * limitations under the License.
  */
 
-import com.intellij.patterns.PatternCondition;
-import com.intellij.psi.PsiElement;
-import com.intellij.util.ProcessingContext;
-import org.jetbrains.annotations.NotNull;
+import java.util.Arrays;
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.io.TextIO;
+import org.apache.beam.sdk.options.PipelineOptions;
+import org.apache.beam.sdk.options.PipelineOptionsFactory;
+import org.apache.beam.sdk.transforms.Count;
+import org.apache.beam.sdk.transforms.Filter;
+import org.apache.beam.sdk.transforms.FlatMapElements;
+import org.apache.beam.sdk.transforms.MapElements;
+import org.apache.beam.sdk.values.KV;
+import org.apache.beam.sdk.values.TypeDescriptors;
 
-
-public class BeamJavaSDKPattern extends PatternCondition<PsiElement> {
-    BeamJavaSDKPattern() {
-        super("javaSDKPattern()");
-    }
-
-    @Override
-    public boolean accepts(@NotNull PsiElement psiElement, ProcessingContext context) {
-        return false;
+public class TestCompletions {
+    public static void main(String[] args) {
+        PipelineOptions options = PipelineOptionsFactory.create();
+        Pipeline p = Pipeline.create(o<caret>);
     }
 }
+