[java-completion] IDEA-363369 Postfix completion for conversion

- more pairs
- tests
- statistics
- improve view

GitOrigin-RevId: ac9cca85b73d10a7593c14520601ad7a4f22c0a4
This commit is contained in:
Mikhail Pyltsin
2024-11-19 10:44:09 +00:00
committed by intellij-monorepo-bot
parent 732018d4f2
commit 12e87dec87
18 changed files with 191 additions and 12 deletions
@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// 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.internal.statistic.eventLog.EventLogGroup;
@@ -17,11 +17,12 @@ import java.util.List;
public final class JavaContributorCollectors extends CounterUsagesCollector {
public static final String TAG_TYPE = "tag";
public static final String STATIC_QUALIFIER_TYPE = "static_qualifier";
public static final String POSTFIX_TAG = "postfix_tag";
private static final EventLogGroup ourGroup = new EventLogGroup("java.completion.contributors", 2);
private static final EventLogGroup ourGroup = new EventLogGroup("java.completion.contributors", 3);
private static final EventField<String>
TYPE_CONTRIBUTOR_FIELD = EventFields.String("type_contributor", List.of(TAG_TYPE, STATIC_QUALIFIER_TYPE));
TYPE_CONTRIBUTOR_FIELD = EventFields.String("type_contributor", List.of(TAG_TYPE, STATIC_QUALIFIER_TYPE, POSTFIX_TAG));
private static final EventField<String> TYPE_COMPLETION_FIELD =
EventFields.String("type_completion", List.of(CompletionType.SMART.name(), CompletionType.BASIC.name()));
@@ -1,6 +1,8 @@
// 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.template.postfix.templates;
import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.codeInsight.completion.JavaContributorCollectors;
import com.intellij.codeInsight.lookup.LookupElementPresentation;
import com.intellij.codeInsight.template.impl.TemplateImpl;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaEditablePostfixTemplate;
@@ -15,6 +17,8 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
import static com.intellij.codeInsight.completion.JavaContributorCollectors.POSTFIX_TAG;
@SuppressWarnings("PostfixTemplateDescriptionNotFound")
public class JavaEditableTaggedPostfixTemplate extends JavaEditablePostfixTemplate implements CustomizableLookupElementTemplate {
@@ -26,9 +30,6 @@ public class JavaEditableTaggedPostfixTemplate extends JavaEditablePostfixTempla
@NotNull
private final String myExample;
@NotNull
private final String myTemplateName;
public @NotNull String @NotNull [] getTags() {
return myTags;
}
@@ -57,10 +58,10 @@ public class JavaEditableTaggedPostfixTemplate extends JavaEditablePostfixTempla
boolean useTopmostExpression,
@NotNull String @NotNull [] tags,
@NotNull PostfixTemplateProvider provider) {
super(templateId, templateName, liveTemplate, example.replace(EXPR_$, "expr"), expressionConditions, minimumLanguageLevel, useTopmostExpression, provider);
super(templateId, templateName, liveTemplate, example.replace(EXPR_$, "expr"), expressionConditions, minimumLanguageLevel,
useTopmostExpression, provider);
myTags = tags;
myExample = example;
myTemplateName= templateName;
}
@@ -77,7 +78,7 @@ public class JavaEditableTaggedPostfixTemplate extends JavaEditablePostfixTempla
public void renderElement(@NotNull LookupElementPresentation presentation) {
String exp = myText;
String templateText = myExample;
if (exp == null || templateText.length() + exp.length() >= 50 || !templateText.contains(EXPR_$)) {
if (exp == null || templateText.length() + exp.length() >= 100 || !templateText.contains(EXPR_$)) {
return;
}
String withExp = templateText.replace(EXPR_$, exp);
@@ -103,4 +104,10 @@ public class JavaEditableTaggedPostfixTemplate extends JavaEditablePostfixTempla
public Collection<String> getAllLookupStrings() {
return Arrays.asList(myTags);
}
@Override
protected @NotNull TextRange getRangeToRemove(@NotNull PsiElement element) {
JavaContributorCollectors.logInsertHandle(element.getProject(), POSTFIX_TAG, CompletionType.BASIC);
return super.getRangeToRemove(element);
}
}
@@ -76,7 +76,9 @@ public class JavaPostfixTemplateProvider implements PostfixTemplateProvider {
new AsListToListPostfixTemplate(this),
new ListOfToListPostfixTemplate(this),
new NewArrayListToListPostfixTemplate(this),
new NewHashSetToSetPostfixTemplate(this)
new NewHashSetToSetPostfixTemplate(this),
new LocalDateToJavaSqlDatePostfixTemplate(this),
new JavaUtilDateToLocalDatePostfixTemplate(this)
);
@Override
@@ -0,0 +1,26 @@
// 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.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class JavaUtilDateToLocalDatePostfixTemplate extends JavaEditableTaggedPostfixTemplate implements DumbAware {
public JavaUtilDateToLocalDatePostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("LocalDate.ofInstant(exp.toInstant(), zoneId) java.sql.Date.valueOf(exp)",
"toLocalDate",
"java.time.LocalDate.ofInstant($EXPR$.toInstant(), $END$)",
"LocalDate.ofInstant($EXPR$.toInstant(), zoneId)",
Collections.singleton(
new JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateExpressionFqnCondition("java.util.Date")),
LanguageLevel.JDK_1_8, false, new String[]{".asLocalDate"}, provider);
}
@Override
public boolean isBuiltin() {
return true;
}
}
@@ -0,0 +1,26 @@
// 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.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class LocalDateToJavaSqlDatePostfixTemplate extends JavaEditableTaggedPostfixTemplate implements DumbAware {
public LocalDateToJavaSqlDatePostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("java.sql.Date.valueOf(exp)",
"sqlValueOf",
"java.sql.Date.valueOf($EXPR$)$END$",
"java.sql.Date.valueOf($EXPR$)",
Collections.singleton(
new JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateExpressionFqnCondition("java.time.LocalDate")),
LanguageLevel.JDK_1_8, false, new String[]{".toSqlDate"}, provider);
}
@Override
public boolean isBuiltin() {
return true;
}
}
@@ -0,0 +1,3 @@
public void m(Date value) {
LocalDate.ofInstant(value.toInstant(), <spot></spot>)
}
@@ -0,0 +1,3 @@
public void m(Date value) {
<spot>value</spot>$key
}
@@ -0,0 +1,6 @@
<html>
<body>
Creates a <code>LocalDate</code> with call <code>LocalDate.ofInstant</code> for a <code>java.util.Date</code> expression.
It is necessary to define <code>ZoneId</code>.
</body>
</html>
@@ -0,0 +1,3 @@
public void m(LocalDate value) {
java.sql.Date(value)<spot></spot>
}
@@ -0,0 +1,3 @@
public void m(LocalDate value) {
<spot>value</spot>$key
}
@@ -0,0 +1,6 @@
<html>
<body>
Creates a <code>java.sql.Date.valueOf</code> call for a <code>java.time.LocalDate</code> expression.
</body>
</html>
@@ -0,0 +1,7 @@
import java.util.Date;
public class Foo {
void m(Date o) {
o.toLocalDate<caret>
}
}
@@ -0,0 +1,8 @@
import java.time.LocalDate;
import java.util.Date;
public class Foo {
void m(Date o) {
LocalDate.ofInstant(o.toInstant(), <caret>)
}
}
@@ -0,0 +1,7 @@
import java.time.LocalDate;
public class Foo {
void m(LocalDate o) {
o.toSqlDate<caret>
}
}
@@ -0,0 +1,8 @@
import java.sql.Date;
import java.time.LocalDate;
public class Foo {
void m(LocalDate o) {
Date.valueOf(o)<caret>
}
}
@@ -0,0 +1,28 @@
// 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.template.postfix.templates;
import com.intellij.testFramework.LightProjectDescriptor;
import org.jetbrains.annotations.NotNull;
public class JavaUtilDateToLocalDatePostfixTemplateTest extends PostfixTemplateTestCase {
@Override
protected @NotNull LightProjectDescriptor getProjectDescriptor() {
return JAVA_8;
}
@NotNull
@Override
protected String getSuffix() {
return "toLocalDate";
}
public void testSimple() {
myFixture.addClass("""
package java.time;
public final class LocalDate { }
""");
doTestCompletion("toLocalDate");
}
}
@@ -0,0 +1,35 @@
// 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.template.postfix.templates;
import com.intellij.testFramework.LightProjectDescriptor;
import org.jetbrains.annotations.NotNull;
public class LocalDateToJavaSqlDatePostfixTemplateTest extends PostfixTemplateTestCase {
@Override
protected @NotNull LightProjectDescriptor getProjectDescriptor() {
return JAVA_8;
}
@NotNull
@Override
protected String getSuffix() {
return "toSqlDate";
}
public void testSimple() {
myFixture.addClass("""
package java.time;
public final class LocalDate { }
""");
myFixture.addClass("""
package java.sql;
import java.time.LocalDate;
public final class Date {\s
public static Date valueOf(LocalDate date) { return null; }
}
""");
doTestCompletion("toSqlDate");
}
}
@@ -1,4 +1,4 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// 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.stats.completion.tracker
import com.intellij.codeInsight.lookup.LookupElement
@@ -64,7 +64,7 @@ class CompletionEventsLoggingTest : CompletionLoggingTestBase() {
myFixture.type('u')
myFixture.type('x')
lookup.hide() //figure out why needed here
lookup?.hide() //figure out why needed here
trackedEvents.assertOrder(
COMPLETION_STARTED,