enable completion hints for Java constructor calls

prerequisite: showing of constructor variants in lookup (enabled in registry - java.completion.show.constructors)
This commit is contained in:
Dmitry Batrak
2017-12-25 15:43:38 +03:00
parent 6e4695f770
commit 75cf36a7a1
3 changed files with 73 additions and 21 deletions
@@ -1,17 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed 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.
* Copyright 2000-2017 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.
*/
package com.intellij.codeInsight.completion;
@@ -20,6 +8,7 @@ import com.intellij.codeInsight.lookup.LookupElementDecorator;
import com.intellij.codeInsight.lookup.LookupElementPresentation;
import com.intellij.codeInsight.lookup.TypedLookupItem;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
@@ -64,6 +53,22 @@ public class JavaConstructorCallElement extends LookupElementDecorator<LookupEle
public void handleInsert(InsertionContext context) {
markClassItemWrapped(getDelegate());
super.handleInsert(context);
context.commitDocument();
PsiCallExpression callExpression = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(),
PsiCallExpression.class, false);
// make sure this is the constructor call we've just added, not the enclosing method/constructor call
if (callExpression != null) {
PsiElement completedElement = callExpression instanceof PsiNewExpression ?
((PsiNewExpression)callExpression).getClassOrAnonymousClassReference() : null;
TextRange completedElementRange = completedElement == null ? null : completedElement.getTextRange();
if (completedElementRange == null || completedElementRange.getStartOffset() != context.getStartOffset()) {
callExpression = null;
}
}
if (callExpression != null) {
JavaMethodCallElement.showParameterHints(context, myConstructor, callExpression);
}
}
@NotNull
@@ -1,4 +1,6 @@
// Copyright 2000-2017 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-2017 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.
*/
package com.intellij.codeInsight.hint.api.impls;
import com.intellij.codeInsight.AnnotationTargetUtil;
@@ -81,12 +83,12 @@ public class MethodParameterInfoHandler implements ParameterInfoHandlerWithTabAc
private PsiExpressionList findArgumentList(final PsiFile file, int offset, int parameterStart, boolean allowOuter) {
PsiExpressionList argumentList = ParameterInfoUtils.findArgumentList(file, offset, parameterStart, this, allowOuter);
if (argumentList == null && allowOuter) {
final PsiMethodCallExpression methodCall = ParameterInfoUtils.findParentOfTypeWithStopElements(file, offset,
PsiMethodCallExpression.class,
PsiMethod.class);
if (methodCall != null) {
argumentList = methodCall.getArgumentList();
PsiCall call = ParameterInfoUtils.findParentOfTypeWithStopElements(file, offset, PsiMethodCallExpression.class, PsiMethod.class);
if (call == null) {
call = ParameterInfoUtils.findParentOfTypeWithStopElements(file, offset, PsiNewExpression.class, PsiMethod.class);
}
if (call != null) {
argumentList = call.getArgumentList();
}
}
return argumentList;
@@ -1,4 +1,6 @@
// Copyright 2000-2017 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-2017 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.
*/
package com.intellij.java.codeInsight.completion;
import com.intellij.codeInsight.AutoPopupController;
@@ -16,6 +18,8 @@ import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.psi.JavaCodeFragmentFactory;
import com.intellij.psi.PsiExpressionCodeFragment;
import com.intellij.testFramework.fixtures.EditorHintFixture;
@@ -789,6 +793,47 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
checkHintContents("<html><b>String</b>&nbsp;&nbsp;<i> A format string </i></html>");
}
public void testBasicScenarioForConstructor() throws Exception {
enableConstructorVariantsCompletion();
// check hints appearance on completion
configureJava("class C { C(int a, int b) {} void m() { new C<caret> } }");
complete("C(int a, int b)");
checkResultWithInlays("class C { C(int a, int b) {} void m() { new C(<HINT text=\"a:\"/><caret>, <hint text=\"b:\"/>) } }");
// check that hints don't disappear after daemon highlighting passes
waitForAllAsyncStuff();
checkResultWithInlays("class C { C(int a, int b) {} void m() { new C(<HINT text=\"a:\"/><caret>, <hint text=\"b:\"/>) } }");
// test Tab/Shift+Tab navigation
next();
waitForAllAsyncStuff();
checkResultWithInlays("class C { C(int a, int b) {} void m() { new C(<hint text=\"a:\"/>, <HINT text=\"b:\"/><caret>) } }");
prev();
waitForAllAsyncStuff();
checkResultWithInlays("class C { C(int a, int b) {} void m() { new C(<HINT text=\"a:\"/><caret>, <hint text=\"b:\"/>) } }");
// test hints remain shown while entering parameter values
myFixture.type("1");
next();
myFixture.type("2");
waitForAllAsyncStuff();
checkResultWithInlays("class C { C(int a, int b) {} void m() { new C(<hint text=\"a:\"/>1, <HINT text=\"b:\"/>2<caret>) } }");
// test hints don't disappear when caret moves out of parameter list
right();
right();
right();
right();
waitForAllAsyncStuff();
checkResultWithInlays("class C { C(int a, int b) {} void m() { new C(<hint text=\"a:\"/>1, <hint text=\"b:\"/>2) } <caret>}");
}
private void enableConstructorVariantsCompletion() {
Registry.get("java.completion.show.constructors").setValue(true);
Disposer.register(myFixture.getTestRootDisposable(), () -> Registry.get("java.completion.show.constructors").setValue(false));
}
private void checkResult(String text) {
myFixture.checkResult(text);
}