less dummy identifier hacks in smart completion cast processing

This commit is contained in:
peter
2015-08-13 18:22:55 +02:00
parent a509139159
commit b08a6b5f07
3 changed files with 48 additions and 41 deletions
@@ -285,9 +285,9 @@ public class JavaCompletionContributor extends CompletionContributor {
result.stopHere();
}
private void addExpressionVariants(@NotNull CompletionParameters parameters, PsiElement position, CompletionResultSet result) {
private static void addExpressionVariants(@NotNull CompletionParameters parameters, PsiElement position, CompletionResultSet result) {
if (JavaSmartCompletionContributor.INSIDE_EXPRESSION.accepts(position) &&
!JavaCompletionData.AFTER_DOT.accepts(position)) {
!JavaCompletionData.AFTER_DOT.accepts(position) && !SmartCastProvider.shouldSuggestCast(parameters)) {
JavaCompletionData.addExpectedTypeMembers(parameters, result);
if (SameSignatureCallParametersProvider.IN_CALL_ARGUMENT.accepts(position)) {
new SameSignatureCallParametersProvider().addCompletions(parameters, new ProcessingContext(), result);
@@ -481,7 +481,7 @@ public class JavaCompletionContributor extends CompletionContributor {
private static void completeAnnotationAttributeName(CompletionResultSet result, PsiElement insertedElement,
CompletionParameters parameters) {
PsiNameValuePair pair = PsiTreeUtil.getParentOfType(insertedElement, PsiNameValuePair.class);
PsiAnnotationParameterList parameterList = (PsiAnnotationParameterList)ObjectUtils.assertNotNull(pair).getParent();
PsiAnnotationParameterList parameterList = (PsiAnnotationParameterList)assertNotNull(pair).getParent();
PsiAnnotation anno = (PsiAnnotation)parameterList.getParent();
boolean showClasses = psiElement().afterLeaf("(").accepts(insertedElement);
PsiClass annoClass = null;
@@ -129,7 +129,7 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
public JavaSmartCompletionContributor() {
extend(CompletionType.SMART, SmartCastProvider.INSIDE_TYPECAST_TYPE, new SmartCastProvider());
extend(CompletionType.SMART, SmartCastProvider.TYPECAST_TYPE_CANDIDATE, new SmartCastProvider());
extend(CompletionType.SMART, SameSignatureCallParametersProvider.IN_CALL_ARGUMENT, new SameSignatureCallParametersProvider());
@@ -172,6 +172,8 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
extend(CompletionType.SMART, psiElement(), new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result) {
if (SmartCastProvider.shouldSuggestCast(parameters)) return;
final PsiElement element = parameters.getPosition();
final PsiReference reference = element.getContainingFile().findReferenceAt(parameters.getOffset());
if (reference != null) {
@@ -215,6 +217,8 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
extend(CompletionType.SMART, INSIDE_EXPRESSION, new ExpectedTypeBasedCompletionProvider() {
@Override
protected void addCompletions(final CompletionParameters params, final CompletionResultSet result, final Collection<ExpectedTypeInfo> _infos) {
if (SmartCastProvider.shouldSuggestCast(params)) return;
Consumer<LookupElement> noTypeCheck = decorateWithoutTypeCheck(result, _infos);
THashSet<ExpectedTypeInfo> mergedInfos = new THashSet<ExpectedTypeInfo>(_infos, EXPECTED_TYPE_INFO_STRATEGY);
@@ -525,16 +529,10 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
}
PsiElement lastElement = context.getFile().findElementAt(context.getStartOffset() - 1);
if (lastElement != null && lastElement.getText().equals("(")) {
final PsiElement parent = lastElement.getParent();
if (parent instanceof PsiTypeCastExpression) {
context.setDummyIdentifier("");
return;
}
if (parent instanceof PsiParenthesizedExpression) {
context.setDummyIdentifier(CompletionUtil.DUMMY_IDENTIFIER_TRIMMED + ")" + CompletionUtil.DUMMY_IDENTIFIER_TRIMMED + " "); // to handle type cast
return;
}
if (lastElement != null && lastElement.getText().equals("(") && lastElement.getParent() instanceof PsiParenthesizedExpression) {
// don't trim dummy identifier or we won't be able to determine the type of the expression after '('
// which is needed to insert correct cast
return;
}
context.setDummyIdentifier(CompletionUtil.DUMMY_IDENTIFIER_TRIMMED);
}
@@ -11,8 +11,7 @@ import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.patterns.PsiElementPattern;
import com.intellij.patterns.ElementPattern;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
@@ -22,20 +21,38 @@ import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static com.intellij.patterns.PlatformPatterns.psiElement;
/**
* @author peter
*/
class SmartCastProvider extends CompletionProvider<CompletionParameters> {
static final PsiElementPattern.Capture<PsiElement> INSIDE_TYPECAST_TYPE = PlatformPatterns.psiElement().afterLeaf(
PlatformPatterns.psiElement().withText("(").withParent(
PsiTypeCastExpression.class));
static final ElementPattern<PsiElement> TYPECAST_TYPE_CANDIDATE = psiElement().afterLeaf("(");
static boolean shouldSuggestCast(CompletionParameters parameters) {
PsiElement position = parameters.getPosition();
PsiElement parent = getParenthesisOwner(position);
if (parent instanceof PsiTypeCastExpression) return true;
if (parent instanceof PsiParenthesizedExpression) {
return parameters.getOffset() == position.getTextRange().getStartOffset();
}
return false;
}
private static PsiElement getParenthesisOwner(PsiElement position) {
PsiElement lParen = PsiTreeUtil.prevVisibleLeaf(position);
return lParen == null || !lParen.textMatches("(") ? null : lParen.getParent();
}
@Override
protected void addCompletions(@NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result) {
if (!shouldSuggestCast(parameters)) return;
PsiElement position = parameters.getPosition();
PsiElement parenthesisOwner = getParenthesisOwner(position);
final boolean overwrite = parenthesisOwner instanceof PsiTypeCastExpression;
for (final ExpectedTypeInfo info : JavaSmartCompletionContributor.getExpectedTypes(parameters)) {
final PsiElement originalPosition = parameters.getOriginalPosition();
final boolean overwrite = INSIDE_TYPECAST_TYPE.accepts(originalPosition);
PsiType type = info.getDefaultType();
if (type instanceof PsiWildcardType) {
type = ((PsiWildcardType)type).getBound();
@@ -45,42 +62,34 @@ class SmartCastProvider extends CompletionProvider<CompletionParameters> {
continue;
}
result.addElement(createSmartCastElement(parameters, overwrite, type));
if (type instanceof PsiPrimitiveType) {
final PsiType castedType = getCastedExpressionType(originalPosition);
final PsiType castedType = getCastedExpressionType(parenthesisOwner);
if (castedType != null && !(castedType instanceof PsiPrimitiveType)) {
final PsiClassType boxedType = ((PsiPrimitiveType)type).getBoxedType(originalPosition);
final PsiClassType boxedType = ((PsiPrimitiveType)type).getBoxedType(position);
if (boxedType != null) {
result.addElement(createSmartCastElement(parameters, overwrite, boxedType));
type = boxedType;
}
}
}
result.addElement(createSmartCastElement(parameters, overwrite, type));
}
}
@Nullable
private static PsiType getCastedExpressionType(PsiElement originalPosition) {
if (INSIDE_TYPECAST_TYPE.accepts(originalPosition)) {
final PsiTypeCastExpression cast = PsiTreeUtil.getParentOfType(originalPosition, PsiTypeCastExpression.class);
if (cast != null) {
final PsiExpression operand = cast.getOperand();
return operand == null ? null : operand.getType();
}
private static PsiType getCastedExpressionType(PsiElement parenthesisOwner) {
if (parenthesisOwner instanceof PsiTypeCastExpression) {
final PsiExpression operand = ((PsiTypeCastExpression)parenthesisOwner).getOperand();
return operand == null ? null : operand.getType();
}
final PsiParenthesizedExpression parens = PsiTreeUtil.getParentOfType(originalPosition, PsiParenthesizedExpression.class, true, PsiStatement.class);
if (parens != null) {
final PsiExpression rightSide = parens.getExpression();
if (rightSide != null) {
return rightSide.getType();
}
PsiElement next = parens.getNextSibling();
if (parenthesisOwner instanceof PsiParenthesizedExpression) {
PsiElement next = parenthesisOwner.getNextSibling();
while (next != null && (next instanceof PsiEmptyExpressionImpl || next instanceof PsiErrorElement || next instanceof PsiWhiteSpace)) {
next = next.getNextSibling();
}
if (next instanceof PsiExpression) {
return ((PsiExpression)next).getType();
}
return null;
}
return null;
}