private static void makeVariableFinalIfNeeded( InsertionContext context, @Nullable PsiReferenceExpression ref) { if (!Registry.is("java.completion.make.outer.variables.final") || ref == null || PsiUtil.isLanguageLevel8OrHigher(ref) || JspPsiUtil.isInJspFile(ref)) { return; } PsiElement target = ref.resolve(); if (target instanceof PsiLocalVariable || target instanceof PsiParameter) { PsiClass placeClass = PsiTreeUtil.findElementOfClassAtOffset( context.getFile(), context.getTailOffset() - 1, PsiClass.class, false); if (placeClass != null && !PsiTreeUtil.isAncestor(placeClass, target, true) && !HighlightControlFlowUtil.isReassigned( (PsiVariable) target, new HashMap<PsiElement, Collection<ControlFlowUtil.VariableInfo>>())) { PsiModifierList modifierList = ((PsiVariable) target).getModifierList(); if (modifierList != null) { modifierList.setModifierProperty(PsiModifier.FINAL, true); } } } }
public static void addImportForItem(InsertionContext context, PsiClass aClass) { if (aClass.getQualifiedName() == null) return; PsiFile file = context.getFile(); int startOffset = context.getStartOffset(); int tail = context.getTailOffset(); int newTail = JavaCompletionUtil.insertClassReference(aClass, file, startOffset, tail); if (newTail > context.getDocument().getTextLength() || newTail < 0) { LOG.error( LogMessageEx.createEvent( "Invalid offset after insertion ", "offset=" + newTail + "\n" + "start=" + startOffset + "\n" + "tail=" + tail + "\n" + "file.length=" + file.getTextLength() + "\n" + "document=" + context.getDocument() + "\n" + DebugUtil.currentStackTrace(), AttachmentFactory.createAttachment(context.getDocument()))); return; } context.setTailOffset(newTail); JavaCompletionUtil.shortenReference(file, context.getStartOffset()); PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting(); }
private static boolean isAtTokenNeeded(InsertionContext myContext) { HighlighterIterator iterator = ((EditorEx) myContext.getEditor()) .getHighlighter() .createIterator(myContext.getStartOffset()); LOG.assertTrue(iterator.getTokenType() == JavaTokenType.IDENTIFIER); iterator.retreat(); if (iterator.getTokenType() == TokenType.WHITE_SPACE) iterator.retreat(); return iterator.getTokenType() != JavaTokenType.AT && iterator.getTokenType() != JavaTokenType.DOT; }
public String calcGenerics(@NotNull PsiElement context, InsertionContext insertionContext) { if (insertionContext.getCompletionChar() == '<') { return ""; } assert context.isValid(); if (myDiamond) { return "<>"; } if (getObject() instanceof PsiClass) { PsiClass psiClass = (PsiClass) getObject(); PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(psiClass.getProject()).getResolveHelper(); PsiSubstitutor substitutor = getSubstitutor(); StringBuilder builder = new StringBuilder(); for (PsiTypeParameter parameter : psiClass.getTypeParameters()) { PsiType substitute = substitutor.substitute(parameter); if (substitute == null || (PsiUtil.resolveClassInType(substitute) == parameter && resolveHelper.resolveReferencedClass(parameter.getName(), context) != CompletionUtil.getOriginalOrSelf(parameter))) { return ""; } if (builder.length() > 0) { builder.append(", "); } builder.append(substitute.getCanonicalText()); } if (builder.length() > 0) { return "<" + builder + ">"; } } return ""; }
private static void qualifyFieldReference(InsertionContext context, PsiField field) { context.commitDocument(); PsiFile file = context.getFile(); final PsiReference reference = file.findReferenceAt(context.getStartOffset()); if (reference instanceof PsiJavaCodeReferenceElement && ((PsiJavaCodeReferenceElement) reference).isQualified()) { return; } PsiClass containingClass = field.getContainingClass(); if (containingClass != null && containingClass.getName() != null) { OffsetKey oldStart = context.trackOffset(context.getStartOffset(), true); JavaCompletionUtil.insertClassReference(containingClass, file, context.getStartOffset()); context.getDocument().insertString(context.getOffsetMap().getOffset(oldStart), "."); PsiDocumentManager.getInstance(context.getProject()).commitDocument(context.getDocument()); } }
private static boolean insertingAnnotation(InsertionContext context, LookupElement item) { final Object obj = item.getObject(); if (!(obj instanceof PsiClass) || !((PsiClass) obj).isAnnotationType()) return false; final Document document = context.getEditor().getDocument(); PsiDocumentManager.getInstance(context.getProject()).commitDocument(document); final int offset = context.getStartOffset(); final PsiFile file = context.getFile(); if (PsiTreeUtil.findElementOfClassAtOffset(file, offset, PsiImportStatement.class, false) != null) return false; // outside of any class: we are surely inserting an annotation if (PsiTreeUtil.findElementOfClassAtOffset(file, offset, PsiClass.class, false) == null) return true; // the easiest check that there's a @ before the identifier return PsiTreeUtil.findElementOfClassAtOffset(file, offset, PsiAnnotation.class, false) != null; }
private static void insertGenerationInfos( InsertionContext context, List<PsiGenerationInfo<PsiMethod>> infos) { List<PsiGenerationInfo<PsiMethod>> newInfos = GenerateMembersUtil.insertMembersAtOffset( context.getFile(), context.getStartOffset(), infos); if (!newInfos.isEmpty()) { final List<PsiElement> elements = new ArrayList<PsiElement>(); for (GenerationInfo member : newInfos) { if (!(member instanceof TemplateGenerationInfo)) { final PsiMember psiMember = member.getPsiMember(); if (psiMember != null) { elements.add(psiMember); } } } GlobalInspectionContextBase.cleanupElements( context.getProject(), null, elements.toArray(new PsiElement[elements.size()])); newInfos.get(0).positionCaret(context.getEditor(), true); } }
private boolean shouldQualify(PsiField field, InsertionContext context) { if (myHelper != null && !myHelper.willBeImported()) { return true; } if (getAttribute(FORCE_QUALIFY) != null) { return true; } PsiReference reference = context.getFile().findReferenceAt(context.getStartOffset()); if (reference instanceof PsiReferenceExpression && !((PsiReferenceExpression) reference).isQualified()) { final PsiVariable target = JavaPsiFacade.getInstance(context.getProject()) .getResolveHelper() .resolveReferencedVariable(field.getName(), (PsiElement) reference); return !field .getManager() .areElementsEquivalent(target, CompletionUtil.getOriginalOrSelf(field)); } return false; }
private static boolean insertingAnnotationWithParameters( InsertionContext context, LookupElement item) { if (insertingAnnotation(context, item)) { final Document document = context.getEditor().getDocument(); PsiDocumentManager.getInstance(context.getProject()).commitDocument(document); PsiElement elementAt = context.getFile().findElementAt(context.getStartOffset()); if (elementAt instanceof PsiIdentifier) { final PsiModifierListOwner parent = PsiTreeUtil.getParentOfType( elementAt, PsiModifierListOwner.class, false, PsiCodeBlock.class); if (parent != null) { for (PsiMethod m : ((PsiClass) item.getObject()).getMethods()) { if (!(m instanceof PsiAnnotationMethod)) continue; final PsiAnnotationMemberValue defaultValue = ((PsiAnnotationMethod) m).getDefaultValue(); if (defaultValue == null) return true; } } } } return false; }
@Override public void handleInsert(InsertionContext context) { context .getDocument() .replaceString(context.getStartOffset(), context.getTailOffset(), getInsertString()); context.commitDocument(); PsiMethodCallExpression call = PsiTreeUtil.findElementOfClassAtOffset( context.getFile(), context.getStartOffset(), PsiMethodCallExpression.class, false); if (call == null) return; PsiExpression[] args = call.getArgumentList().getExpressions(); if (args.length != 1 || !(args[0] instanceof PsiMethodCallExpression)) return; JavaCodeStyleManager.getInstance(context.getProject()).shortenClassReferences(args[0]); }
public static boolean promptTypeArgs(InsertionContext context, int offset) { if (offset < 0) { return false; } OffsetKey key = context.trackOffset(offset, false); PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting(); offset = context.getOffset(key); if (offset < 0) { return false; } String open = escapeXmlIfNeeded(context, "<"); context.getDocument().insertString(offset, open); context.getEditor().getCaretModel().moveToOffset(offset + open.length()); context.getDocument().insertString(offset + open.length(), escapeXmlIfNeeded(context, ">")); context.setAddCompletionChar(false); return true; }
public static boolean insertTail( InsertionContext context, LookupElement item, TailType tailType, boolean hasTail) { TailType toInsert = tailType; LookupItem<?> lookupItem = item.as(LookupItem.CLASS_CONDITION_KEY); if (lookupItem == null || lookupItem.getAttribute(LookupItem.TAIL_TYPE_ATTR) != TailType.UNKNOWN) { if (!hasTail && item.getObject() instanceof PsiMethod && ((PsiMethod) item.getObject()).getReturnType() == PsiType.VOID) { PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments(); if (psiElement() .beforeLeaf(psiElement().withText(".")) .accepts(context.getFile().findElementAt(context.getTailOffset() - 1))) { return false; } boolean insertAdditionalSemicolon = true; final PsiReferenceExpression referenceExpression = PsiTreeUtil.getTopmostParentOfType( context.getFile().findElementAt(context.getStartOffset()), PsiReferenceExpression.class); if (referenceExpression instanceof PsiMethodReferenceExpression && LambdaHighlightingUtil.insertSemicolon(referenceExpression.getParent())) { insertAdditionalSemicolon = false; } else if (referenceExpression != null) { PsiElement parent = referenceExpression.getParent(); if (parent instanceof PsiMethodCallExpression) { parent = parent.getParent(); } if (parent instanceof PsiLambdaExpression && !LambdaHighlightingUtil.insertSemicolonAfter((PsiLambdaExpression) parent)) { insertAdditionalSemicolon = false; } } if (insertAdditionalSemicolon) { toInsert = TailType.SEMICOLON; } } } toInsert.processTail(context.getEditor(), context.getTailOffset()); return true; }
public static String escapeXmlIfNeeded(InsertionContext context, String generics) { if (context.getFile().getViewProvider().getBaseLanguage() == StdLanguages.JSPX) { return StringUtil.escapeXml(generics); } return generics; }
@Override public void handleInsert(InsertionContext context) { context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset()); for (int i = 0; i < myTypeItems.size(); i++) { PsiTypeLookupItem typeItem = myTypeItems.get(i); CompletionUtil.emulateInsertion(context, context.getTailOffset(), typeItem); if (context.getTailOffset() < 0) { LOG.error("tail offset spoiled by " + typeItem); return; } context.setTailOffset( getTail(i == myTypeItems.size() - 1) .processTail(context.getEditor(), context.getTailOffset())); } context.setAddCompletionChar(false); context.commitDocument(); PsiElement leaf = context.getFile().findElementAt(context.getTailOffset() - 1); if (psiElement() .withParents( PsiReferenceParameterList.class, PsiJavaCodeReferenceElement.class, PsiNewExpression.class) .accepts(leaf)) { ParenthesesInsertHandler.getInstance(myHasParameters).handleInsert(context, this); myGlobalTail.processTail(context.getEditor(), context.getTailOffset()); } }
@Override protected TailType computeTailType(InsertionContext context) { return context.shouldAddCompletionChar() ? TailType.NONE : myTail; }
@Override public void handleInsert(InsertionContext context) { PsiVariable variable = getObject(); Document document = context.getDocument(); document.replaceString(context.getStartOffset(), context.getTailOffset(), variable.getName()); context.commitDocument(); if (variable instanceof PsiField) { if (willBeImported()) { RangeMarker toDelete = JavaCompletionUtil.insertTemporary(context.getTailOffset(), document, " "); context.commitDocument(); final PsiReferenceExpression ref = PsiTreeUtil.findElementOfClassAtOffset( context.getFile(), context.getStartOffset(), PsiReferenceExpression.class, false); if (ref != null) { ref.bindToElementViaStaticImport(((PsiField) variable).getContainingClass()); PostprocessReformattingAspect.getInstance(ref.getProject()).doPostponedFormatting(); } if (toDelete.isValid()) { document.deleteString(toDelete.getStartOffset(), toDelete.getEndOffset()); } context.commitDocument(); } else if (shouldQualify((PsiField) variable, context)) { qualifyFieldReference(context, (PsiField) variable); } } PsiReferenceExpression ref = PsiTreeUtil.findElementOfClassAtOffset( context.getFile(), context.getTailOffset() - 1, PsiReferenceExpression.class, false); if (ref != null) { JavaCodeStyleManager.getInstance(context.getProject()).shortenClassReferences(ref); } ref = PsiTreeUtil.findElementOfClassAtOffset( context.getFile(), context.getTailOffset() - 1, PsiReferenceExpression.class, false); makeVariableFinalIfNeeded(context, ref); final char completionChar = context.getCompletionChar(); if (completionChar == '=') { context.setAddCompletionChar(false); TailType.EQ.processTail(context.getEditor(), context.getTailOffset()); } else if (completionChar == ',' && getAttribute(LookupItem.TAIL_TYPE_ATTR) != TailType.UNKNOWN) { context.setAddCompletionChar(false); TailType.COMMA.processTail(context.getEditor(), context.getTailOffset()); AutoPopupController.getInstance(context.getProject()) .autoPopupParameterInfo(context.getEditor(), null); } else if (completionChar == ':') { context.setAddCompletionChar(false); TailType.COND_EXPR_COLON.processTail(context.getEditor(), context.getTailOffset()); } else if (completionChar == '.') { AutoPopupController.getInstance(context.getProject()) .autoPopupMemberLookup(context.getEditor(), null); } else if (completionChar == '!' && PsiType.BOOLEAN.isAssignableFrom(variable.getType())) { context.setAddCompletionChar(false); if (ref != null) { FeatureUsageTracker.getInstance() .triggerFeatureUsed(CodeCompletionFeatures.EXCLAMATION_FINISH); document.insertString(ref.getTextRange().getStartOffset(), "!"); } } }
@Override public void handleInsert(InsertionContext context) { myImportFixer.handleInsert(context, this); PsiElement position = context.getFile().findElementAt(context.getStartOffset()); if (position != null) { int genericsStart = context.getTailOffset(); context .getDocument() .insertString( genericsStart, JavaCompletionUtil.escapeXmlIfNeeded(context, calcGenerics(position, context))); JavaCompletionUtil.shortenReference(context.getFile(), genericsStart - 1); } int tail = context.getTailOffset(); String braces = StringUtil.repeat("[]", getBracketsCount()); Editor editor = context.getEditor(); if (!braces.isEmpty()) { if (myAddArrayInitializer) { context.getDocument().insertString(tail, braces + "{}"); editor.getCaretModel().moveToOffset(tail + braces.length() + 1); } else { context.getDocument().insertString(tail, braces); editor.getCaretModel().moveToOffset(tail + 1); if (context.getCompletionChar() == '[') { context.setAddCompletionChar(false); } } } else { editor.getCaretModel().moveToOffset(tail); } editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); InsertHandler handler = getInsertHandler(); if (handler != null) { //noinspection unchecked handler.handleInsert(context, this); } }
private static void removeLookupString(InsertionContext context) { context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset()); context.commitDocument(); }
@Override public void handleInsert(InsertionContext context) { final Document document = context.getEditor().getDocument(); document.replaceString(context.getStartOffset(), context.getTailOffset(), ";"); final InsertionContext qualifierContext = CompletionUtil.emulateInsertion(context, context.getStartOffset(), myQualifier); OffsetKey oldStart = context.trackOffset(context.getStartOffset(), false); int start = CharArrayUtil.shiftForward( context.getDocument().getCharsSequence(), context.getStartOffset(), " \t\n"); if (shouldParenthesizeQualifier(context.getFile(), start, qualifierContext.getTailOffset())) { final String space = CodeStyleSettingsManager.getSettings(qualifierContext.getProject()) .SPACE_WITHIN_PARENTHESES ? " " : ""; document.insertString(start, "(" + space); document.insertString(qualifierContext.getTailOffset(), space + ")"); } final char atTail = document.getCharsSequence().charAt(context.getTailOffset() - 1); if (atTail != ';') { LOG.error( LogMessageEx.createEvent( "Unexpected character", "atTail=" + atTail + "\n" + "offset=" + context.getTailOffset() + "\n" + "item=" + this + "\n" + "item.class=" + this.getClass() + "\n" + DebugUtil.currentStackTrace(), AttachmentFactory.createAttachment(context.getDocument()))); } document.replaceString(context.getTailOffset() - 1, context.getTailOffset(), "."); CompletionUtil.emulateInsertion(getDelegate(), context.getTailOffset(), context); context.commitDocument(); int formatStart = context.getOffset(oldStart); int formatEnd = context.getTailOffset(); if (formatStart >= 0 && formatEnd >= 0) { CodeStyleManager.getInstance(context.getProject()) .reformatText(context.getFile(), formatStart, formatEnd); } }
public void handleInsert( final InsertionContext context, final JavaPsiClassReferenceElement item) { final char c = context.getCompletionChar(); int offset = context.getTailOffset() - 1; final PsiFile file = context.getFile(); if (PsiTreeUtil.findElementOfClassAtOffset(file, offset, PsiImportStatementBase.class, false) != null) { final PsiJavaCodeReferenceElement ref = PsiTreeUtil.findElementOfClassAtOffset( file, offset, PsiJavaCodeReferenceElement.class, false); final String qname = item.getQualifiedName(); if (qname != null && (ref == null || !qname.equals(ref.getCanonicalText()))) { AllClassesGetter.INSERT_FQN.handleInsert(context, item); } return; } PsiElement position = file.findElementAt(offset); PsiClass psiClass = item.getObject(); final Project project = context.getProject(); final boolean annotation = insertingAnnotation(context, item); final Editor editor = context.getEditor(); if (c == '#') { context.setLaterRunnable( new Runnable() { public void run() { new CodeCompletionHandlerBase(CompletionType.BASIC).invokeCompletion(project, editor); } }); } else if (c == '.' && PsiTreeUtil.getParentOfType(position, PsiParameterList.class) == null) { AutoPopupController.getInstance(context.getProject()) .autoPopupMemberLookup(context.getEditor(), null); } if (position != null) { PsiElement parent = position.getParent(); if (parent instanceof PsiJavaCodeReferenceElement) { final PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement) parent; if (PsiTreeUtil.getParentOfType(position, PsiDocTag.class) != null && ref.isReferenceTo(psiClass)) { return; } } } OffsetKey refEnd = context.trackOffset(context.getTailOffset(), false); boolean fillTypeArgs = context.getCompletionChar() == '<'; if (fillTypeArgs) { context.setAddCompletionChar(false); } if (shouldInsertParentheses(psiClass, position)) { if (ConstructorInsertHandler.insertParentheses(context, item, psiClass, false)) { fillTypeArgs |= psiClass.hasTypeParameters() && PsiUtil.getLanguageLevel(file).isAtLeast(LanguageLevel.JDK_1_5); } } else if (insertingAnnotationWithParameters(context, item)) { JavaCompletionUtil.insertParentheses(context, item, false, true); AutoPopupController.getInstance(project).autoPopupParameterInfo(editor, null); } LOG.assertTrue(context.getTailOffset() >= 0); String docText = context.getDocument().getText(); DefaultInsertHandler.addImportForItem(context, item); if (context.getTailOffset() < 0) { LOG.error( LogMessageEx.createEvent( "Tail offset degraded after insertion", "start=" + context.getStartOffset(), new Attachment( context.getFile().getViewProvider().getVirtualFile().getPath(), docText))); } if (annotation) { // Check if someone inserts annotation class that require @ PsiElement elementAt = file.findElementAt(context.getStartOffset()); final PsiElement parentElement = elementAt != null ? elementAt.getParent() : null; if (elementAt instanceof PsiIdentifier && (PsiTreeUtil.getParentOfType(elementAt, PsiAnnotationParameterList.class) != null || parentElement instanceof PsiErrorElement && parentElement.getParent() instanceof PsiJavaFile // top level annotation without @ ) && isAtTokenNeeded(context)) { int expectedOffsetForAtToken = elementAt.getTextRange().getStartOffset(); context.getDocument().insertString(expectedOffsetForAtToken, "@"); } } if (fillTypeArgs) { PostprocessReformattingAspect.getInstance(project).doPostponedFormatting(); int typeArgs = context.getOffset(refEnd); if (typeArgs >= 0) { context.getDocument().insertString(typeArgs, "<>"); context.getEditor().getCaretModel().moveToOffset(typeArgs + 1); } } }
public static void insertParentheses( final InsertionContext context, final LookupElement item, boolean overloadsMatter, boolean hasParams, final boolean forceClosingParenthesis) { final Editor editor = context.getEditor(); final char completionChar = context.getCompletionChar(); final PsiFile file = context.getFile(); final TailType tailType = completionChar == '(' ? TailType.NONE : completionChar == ':' ? TailType.COND_EXPR_COLON : LookupItem.handleCompletionChar(context.getEditor(), item, completionChar); final boolean hasTail = tailType != TailType.NONE && tailType != TailType.UNKNOWN; final boolean smart = completionChar == Lookup.COMPLETE_STATEMENT_SELECT_CHAR; if (completionChar == '(' || completionChar == '.' || completionChar == ',' || completionChar == ';' || completionChar == ':' || completionChar == ' ') { context.setAddCompletionChar(false); } if (hasTail) { hasParams = false; } final boolean needRightParenth = forceClosingParenthesis || !smart && (CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET || !hasParams && completionChar != '('); context.commitDocument(); final CommonCodeStyleSettings styleSettings = context.getCodeStyleSettings(); final PsiElement elementAt = file.findElementAt(context.getStartOffset()); if (elementAt == null || !(elementAt.getParent() instanceof PsiMethodReferenceExpression)) { ParenthesesInsertHandler.getInstance( hasParams, styleSettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES, styleSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES && hasParams, needRightParenth, styleSettings.METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE) .handleInsert(context, item); } if (hasParams) { // Invoke parameters popup AutoPopupController.getInstance(file.getProject()) .autoPopupParameterInfo(editor, overloadsMatter ? null : (PsiElement) item.getObject()); } if (smart || !needRightParenth || !insertTail(context, item, tailType, hasTail)) { return; } if (completionChar == '.') { AutoPopupController.getInstance(file.getProject()) .autoPopupMemberLookup(context.getEditor(), null); } else if (completionChar == ',') { AutoPopupController.getInstance(file.getProject()) .autoPopupParameterInfo(context.getEditor(), null); } }