private void altCommitToOriginal(@NotNull DocumentEvent e) { final PsiFile origPsiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(myOrigDocument); String newText = myNewDocument.getText(); // prepare guarded blocks LinkedHashMap<String, String> replacementMap = new LinkedHashMap<String, String>(); int count = 0; for (RangeMarker o : ContainerUtil.reverse(((DocumentEx) myNewDocument).getGuardedBlocks())) { String replacement = o.getUserData(REPLACEMENT_KEY); String tempText = "REPLACE" + (count++) + Long.toHexString(StringHash.calc(replacement)); newText = newText.substring(0, o.getStartOffset()) + tempText + newText.substring(o.getEndOffset()); replacementMap.put(tempText, replacement); } // run preformat processors final int hostStartOffset = myAltFullRange.getStartOffset(); myEditor.getCaretModel().moveToOffset(hostStartOffset); for (CopyPastePreProcessor preProcessor : Extensions.getExtensions(CopyPastePreProcessor.EP_NAME)) { newText = preProcessor.preprocessOnPaste(myProject, origPsiFile, myEditor, newText, null); } myOrigDocument.replaceString(hostStartOffset, myAltFullRange.getEndOffset(), newText); // replace temp strings for guarded blocks for (String tempText : replacementMap.keySet()) { int idx = CharArrayUtil.indexOf( myOrigDocument.getCharsSequence(), tempText, hostStartOffset, myAltFullRange.getEndOffset()); myOrigDocument.replaceString(idx, idx + tempText.length(), replacementMap.get(tempText)); } // JAVA: fix occasional char literal concatenation fixDocumentQuotes(myOrigDocument, hostStartOffset - 1); fixDocumentQuotes(myOrigDocument, myAltFullRange.getEndOffset()); // reformat PsiDocumentManager.getInstance(myProject).commitDocument(myOrigDocument); Runnable task = () -> { try { CodeStyleManager.getInstance(myProject) .reformatRange(origPsiFile, hostStartOffset, myAltFullRange.getEndOffset(), true); } catch (IncorrectOperationException e1) { // LOG.error(e); } }; DocumentUtil.executeInBulk(myOrigDocument, true, task); PsiElement newInjected = InjectedLanguageManager.getInstance(myProject) .findInjectedElementAt(origPsiFile, hostStartOffset); DocumentWindow documentWindow = newInjected == null ? null : InjectedLanguageUtil.getDocumentWindow(newInjected); if (documentWindow != null) { myEditor.getCaretModel().moveToOffset(documentWindow.injectedToHost(e.getOffset())); myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); } }
private void commitToOriginalInner() { final String text = myNewDocument.getText(); final Map< PsiLanguageInjectionHost, Set<Trinity<RangeMarker, RangeMarker, SmartPsiElementPointer>>> map = ContainerUtil.classify( myMarkers.iterator(), new Convertor< Trinity<RangeMarker, RangeMarker, SmartPsiElementPointer>, PsiLanguageInjectionHost>() { @Override public PsiLanguageInjectionHost convert( final Trinity<RangeMarker, RangeMarker, SmartPsiElementPointer> o) { final PsiElement element = o.third.getElement(); return (PsiLanguageInjectionHost) element; } }); PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject); documentManager.commitDocument(myOrigDocument); // commit here and after each manipulator update int localInsideFileCursor = 0; for (PsiLanguageInjectionHost host : map.keySet()) { if (host == null) continue; String hostText = host.getText(); ProperTextRange insideHost = null; StringBuilder sb = new StringBuilder(); for (Trinity<RangeMarker, RangeMarker, SmartPsiElementPointer> entry : map.get(host)) { RangeMarker origMarker = entry.first; // check for validity? int hostOffset = host.getTextRange().getStartOffset(); ProperTextRange localInsideHost = new ProperTextRange( origMarker.getStartOffset() - hostOffset, origMarker.getEndOffset() - hostOffset); RangeMarker rangeMarker = entry.second; ProperTextRange localInsideFile = new ProperTextRange( Math.max(localInsideFileCursor, rangeMarker.getStartOffset()), rangeMarker.getEndOffset()); if (insideHost != null) { // append unchanged inter-markers fragment sb.append( hostText.substring(insideHost.getEndOffset(), localInsideHost.getStartOffset())); } sb.append( localInsideFile.getEndOffset() <= text.length() && !localInsideFile.isEmpty() ? localInsideFile.substring(text) : ""); localInsideFileCursor = localInsideFile.getEndOffset(); insideHost = insideHost == null ? localInsideHost : insideHost.union(localInsideHost); } assert insideHost != null; ElementManipulators.getManipulator(host).handleContentChange(host, insideHost, sb.toString()); documentManager.commitDocument(myOrigDocument); } }
public int compareTo(PostprocessFormattingTask o) { RangeMarker o1 = myRange; RangeMarker o2 = o.myRange; if (o1.equals(o2)) return 0; final int diff = o2.getEndOffset() - o1.getEndOffset(); if (diff == 0) { if (o1.getStartOffset() == o2.getStartOffset()) return 0; if (o1.getStartOffset() == o1.getEndOffset()) return -1; // empty ranges first if (o2.getStartOffset() == o2.getEndOffset()) return 1; // empty ranges first return o1.getStartOffset() - o2.getStartOffset(); } return diff; }
public void initMarkers(Place shreds) { SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(myProject); int curOffset = -1; for (PsiLanguageInjectionHost.Shred shred : shreds) { final RangeMarker rangeMarker = myNewDocument.createRangeMarker( shred.getRange().getStartOffset() + shred.getPrefix().length(), shred.getRange().getEndOffset() - shred.getSuffix().length()); final TextRange rangeInsideHost = shred.getRangeInsideHost(); PsiLanguageInjectionHost host = shred.getHost(); RangeMarker origMarker = myOrigDocument.createRangeMarker( rangeInsideHost.shiftRight(host.getTextRange().getStartOffset())); SmartPsiElementPointer<PsiLanguageInjectionHost> elementPointer = smartPointerManager.createSmartPsiElementPointer(host); Trinity<RangeMarker, RangeMarker, SmartPsiElementPointer> markers = Trinity.<RangeMarker, RangeMarker, SmartPsiElementPointer>create( origMarker, rangeMarker, elementPointer); myMarkers.add(markers); origMarker.setGreedyToRight(true); rangeMarker.setGreedyToRight(true); if (origMarker.getStartOffset() > curOffset) { origMarker.setGreedyToLeft(true); rangeMarker.setGreedyToLeft(true); } curOffset = origMarker.getEndOffset(); } initGuardedBlocks(shreds); }
public TextRange surroundExpression( final Project project, final Editor editor, PsiExpression expr) throws IncorrectOperationException { assert expr.isValid(); PsiType[] types = GuessManager.getInstance(project).guessTypeToCast(expr); final boolean parenthesesNeeded = expr instanceof PsiPolyadicExpression || expr instanceof PsiConditionalExpression || expr instanceof PsiAssignmentExpression; String exprText = parenthesesNeeded ? "(" + expr.getText() + ")" : expr.getText(); final Template template = generateTemplate(project, exprText, types); TextRange range; if (expr.isPhysical()) { range = expr.getTextRange(); } else { final RangeMarker rangeMarker = expr.getUserData(ElementToWorkOn.TEXT_RANGE); if (rangeMarker == null) return null; range = new TextRange(rangeMarker.getStartOffset(), rangeMarker.getEndOffset()); } editor.getDocument().deleteString(range.getStartOffset(), range.getEndOffset()); editor.getCaretModel().moveToOffset(range.getStartOffset()); editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); TemplateManager.getInstance(project).startTemplate(editor, template); return null; }
public void testCreation() throws Exception { RangeMarker marker = createMarker("0123456789", 2, 5); assertEquals(2, marker.getStartOffset()); assertEquals(5, marker.getEndOffset()); assertTrue(marker.isValid()); }
public void testInsertIntoEnd() throws Exception { RangeMarker marker = createMarker("0123456789", 2, 5); marker.getDocument().insertString(5, "xxx"); assertEquals(2, marker.getStartOffset()); assertEquals(5, marker.getEndOffset()); assertTrue(marker.isValid()); }
public void testDeleteBeforeStart() throws Exception { RangeMarker marker = createMarker("01[234]56789"); marker.getDocument().deleteString(0, 1); assertEquals(1, marker.getStartOffset()); assertEquals(4, marker.getEndOffset()); assertTrue(marker.isValid()); }
public void testNested3() { RangeMarker marker1 = createMarker("01[23]4567890123"); DocumentEx document = (DocumentEx) marker1.getDocument(); RangeMarker marker2 = document.createRangeMarker(9, 11); RangeMarker marker3 = document.createRangeMarker(1, 12); marker3.dispose(); document.deleteString(marker1.getEndOffset(), marker2.getStartOffset()); }
private void doEnter(PsiElement atCaret, Editor editor) throws IncorrectOperationException { final PsiFile psiFile = atCaret.getContainingFile(); final RangeMarker rangeMarker = createRangeMarker(atCaret); if (myFirstErrorOffset != Integer.MAX_VALUE) { editor.getCaretModel().moveToOffset(myFirstErrorOffset); reformat(atCaret); return; } reformat(atCaret); commit(editor); atCaret = GroovyRefactoringUtil.findElementInRange( ((GroovyFileBase) psiFile), rangeMarker.getStartOffset(), rangeMarker.getEndOffset(), atCaret.getClass()); // atCaret = CodeInsightUtil.findElementInRange(psiFile, rangeMarker.getStartOffset(), // rangeMarker.getEndOffset(), atCaret.getClass()); for (EnterProcessor processor : ourEnterProcessors) { if (atCaret == null) { // Can't restore element at caret after enter processor execution! break; } if (processor.doEnter(editor, atCaret, isModified(editor))) return; } if (!isModified(editor)) { plainEnter(editor); } else { if (myFirstErrorOffset == Integer.MAX_VALUE) { editor.getCaretModel().moveToOffset(rangeMarker.getEndOffset()); } else { editor.getCaretModel().moveToOffset(myFirstErrorOffset); } } }
public void testInsertIntoStartExpandToLeft() throws Exception { RangeMarker marker = createMarker("0123456789", 2, 5); marker.setGreedyToLeft(true); marker.getDocument().insertString(2, "xxx"); assertEquals(2, marker.getStartOffset()); assertEquals(8, marker.getEndOffset()); assertTrue(marker.isValid()); }
static TextRange processDocument( Document document, RangeMarker marker, Commenter commenter, boolean escape) { if (commenter instanceof EscapingCommenter) { if (escape) { ((EscapingCommenter) commenter).escape(document, marker); } else { ((EscapingCommenter) commenter).unescape(document, marker); } } return TextRange.create(marker.getStartOffset(), marker.getEndOffset()); }
public void testUpdateInvalid() throws Exception { RangeMarker marker = createMarker("01[]23456789"); marker.getDocument().deleteString(1, 3); assertFalse(marker.isValid()); marker.getDocument().insertString(2, "xxx"); assertEquals(2, marker.getStartOffset()); assertEquals(2, marker.getEndOffset()); assertFalse(marker.isValid()); }
public boolean changesRange(TextRange range) { if (myAltFullRange != null) { return range.intersects(myAltFullRange.getStartOffset(), myAltFullRange.getEndOffset()); } else if (!myMarkers.isEmpty()) { TextRange hostRange = TextRange.create( myMarkers.get(0).first.getStartOffset(), myMarkers.get(myMarkers.size() - 1).first.getEndOffset()); return range.intersects(hostRange); } return false; }
protected Document createCopy() { final Document originalDocument = myRangeMarker.getDocument(); String textInRange = originalDocument .getCharsSequence() .subSequence(myRangeMarker.getStartOffset(), myRangeMarker.getEndOffset()) .toString(); final Document result = EditorFactory.getInstance().createDocument(textInRange); result.setReadOnly(!originalDocument.isWritable()); result.putUserData(ORIGINAL_DOCUMENT, originalDocument); return result; }
private void collectRangeMarker( RangeMarker rangeMarker, int lineOffset, Collection<RangeMarker> leftGreedyMarkers, Collection<RangeMarker> emptyMarkers) { if (rangeMarker.getStartOffset() == lineOffset && rangeMarker.isGreedyToLeft()) { leftGreedyMarkers.add(rangeMarker); } if (rangeMarker.getStartOffset() == lineOffset && rangeMarker.getEndOffset() == lineOffset && !rangeMarker.isGreedyToRight()) { emptyMarkers.add(rangeMarker); } }
public void execute(FileViewProvider viewProvider) { final Document document = viewProvider.getDocument(); final PsiFile psiFile = viewProvider.getPsi(viewProvider.getBaseLanguage()); for (Pair<Integer, RangeMarker> integerRangeMarkerPair : myRangesToReindent) { RangeMarker marker = integerRangeMarkerPair.second; final CharSequence charsSequence = document.getCharsSequence().subSequence(marker.getStartOffset(), marker.getEndOffset()); final int oldIndent = integerRangeMarkerPair.first; final TextRange[] whitespaces = CharArrayUtil.getIndents(charsSequence, marker.getStartOffset()); final int indentAdjustment = getNewIndent(psiFile, marker.getStartOffset()) - oldIndent; if (indentAdjustment != 0) adjustIndentationInRange(psiFile, document, whitespaces, indentAdjustment); } }
private void surroundWithCodeBlock(@NotNull final MoveInfo info, final boolean down) { try { final Document document = PsiDocumentManager.getInstance(statementToSurroundWithCodeBlock.getProject()) .getDocument(statementToSurroundWithCodeBlock.getContainingFile()); int startOffset = document.getLineStartOffset(info.toMove.startLine); int endOffset = getLineStartSafeOffset(document, info.toMove.endLine); if (document.getText().charAt(endOffset - 1) == '\n') endOffset--; final RangeMarker lineRangeMarker = document.createRangeMarker(startOffset, endOffset); final PsiElementFactory factory = JavaPsiFacade.getInstance(statementToSurroundWithCodeBlock.getProject()) .getElementFactory(); PsiCodeBlock codeBlock = factory.createCodeBlock(); codeBlock.add(statementToSurroundWithCodeBlock); final PsiBlockStatement blockStatement = (PsiBlockStatement) factory.createStatementFromText("{}", statementToSurroundWithCodeBlock); blockStatement.getCodeBlock().replace(codeBlock); PsiBlockStatement newStatement = (PsiBlockStatement) statementToSurroundWithCodeBlock.replace(blockStatement); newStatement = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(newStatement); info.toMove = new LineRange( document.getLineNumber(lineRangeMarker.getStartOffset()), document.getLineNumber(lineRangeMarker.getEndOffset()) + 1); PsiCodeBlock newCodeBlock = newStatement.getCodeBlock(); if (down) { PsiElement blockChild = firstNonWhiteElement(newCodeBlock.getFirstBodyElement(), true); if (blockChild == null) blockChild = newCodeBlock.getRBrace(); info.toMove2 = new LineRange( info.toMove2 .startLine, // document.getLineNumber(newCodeBlock.getParent().getTextRange().getStartOffset()), document.getLineNumber(blockChild.getTextRange().getStartOffset())); } else { int start = document.getLineNumber(newCodeBlock.getRBrace().getTextRange().getStartOffset()); int end = info.toMove.startLine; if (start > end) end = start; info.toMove2 = new LineRange(start, end); } } catch (IncorrectOperationException e) { LOG.error(e); } }
private static void indentLinesIn( final Editor editor, final PsiFile file, final Document document, final Project project, RangeMarker range) { final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project); int line1 = editor.offsetToLogicalPosition(range.getStartOffset()).line; int line2 = editor.offsetToLogicalPosition(range.getEndOffset()).line; while (!lineContainsNonSpaces(document, line1) && line1 < line2) line1++; while (!lineContainsNonSpaces(document, line2) && line1 < line2) line2--; final FileViewProvider provider = file.getViewProvider(); PsiFile rootToAdjustIndentIn = provider.getPsi(provider.getBaseLanguage()); codeStyleManager.adjustLineIndent( rootToAdjustIndentIn, new TextRange(document.getLineStartOffset(line1), document.getLineStartOffset(line2))); }
private static boolean isOffsetInsideHighlightInfo( int offset, HighlightInfo info, boolean includeFixRange) { RangeHighlighterEx highlighter = info.highlighter; if (highlighter == null || !highlighter.isValid()) return false; int startOffset = highlighter.getStartOffset(); int endOffset = highlighter.getEndOffset(); if (startOffset <= offset && offset <= endOffset) { return true; } if (!includeFixRange) return false; RangeMarker fixMarker = info.fixMarker; if (fixMarker != null) { // null means its range is the same as highlighter if (!fixMarker.isValid()) return false; startOffset = fixMarker.getStartOffset(); endOffset = fixMarker.getEndOffset(); return startOffset <= offset && offset <= endOffset; } return false; }
private void refreshLineMarkers() { for (Map.Entry<RangeMarker, LineMarkerInfo> entry : myLineMarkerInfos.entrySet()) { RangeMarker rangeMarker = entry.getKey(); int startOffset = rangeMarker.getStartOffset(); int endOffset = rangeMarker.getEndOffset(); LineMarkerInfo value = entry.getValue(); PsiElement element = value.getElement(); assert element != null : value; TextRange range = new TextRange(startOffset, endOffset); final String tooltip = value.getLineMarkerTooltip(); LineMarkerInfo markerInfo = new LineMarkerInfo<>( element, range, null, value.updatePass, e -> tooltip, null, GutterIconRenderer.Alignment.RIGHT); entry.setValue(markerInfo); } }
private void refreshLineMarkers() { for (Map.Entry<RangeMarker, LineMarkerInfo> entry : lineMarkerInfos.entrySet()) { RangeMarker rangeMarker = entry.getKey(); int startOffset = rangeMarker.getStartOffset(); int endOffset = rangeMarker.getEndOffset(); final LineMarkerInfo value = entry.getValue(); LineMarkerInfo markerInfo = new LineMarkerInfo<PsiElement>( value.getElement(), new TextRange(startOffset, endOffset), null, value.updatePass, new Function<PsiElement, String>() { @Override public String fun(PsiElement psiElement) { return value.getLineMarkerTooltip(); } }, null, GutterIconRenderer.Alignment.RIGHT); entry.setValue(markerInfo); } }
private static void indentLinesIn( final Editor editor, final PsiFile file, final Document document, final Project project, RangeMarker range) { final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project); int line1 = editor.offsetToLogicalPosition(range.getStartOffset()).line; int line2 = editor.offsetToLogicalPosition(range.getEndOffset()).line; /* if (PsiUtil.isInJspFile(file)) { // This version is slow because of each moved line cause commit // and right now we unable to fix JSP formatter quickly // TODO: remove this code for (int line = line1; line <= line2; line++) { if (lineContainsNonSpaces(document, line)) { int lineStart = document.getLineStartOffset(line); codeStyleManager.adjustLineIndent(document, lineStart); } } } else {*/ while (!lineContainsNonSpaces(document, line1) && line1 <= line2) line1++; while (!lineContainsNonSpaces(document, line2) && line2 > line1) line2--; try { final FileViewProvider provider = file.getViewProvider(); PsiFile rootToAdjustIndentIn = provider.getPsi(provider.getBaseLanguage()); codeStyleManager.adjustLineIndent( rootToAdjustIndentIn, new TextRange(document.getLineStartOffset(line1), document.getLineStartOffset(line2))); } catch (IncorrectOperationException ex) { throw new RuntimeException(ex); } /* } */ }
public int getEndOffset() { return myRange.getEndOffset(); }
/** * Allows to check if text range defined by the given range marker completely contains text range * of the given fold region. * * @param rangeMarker range marker to check * @param foldRegion fold region to check * @return <code>true</code> if text range defined by the given range marker completely contains * text range of the given fold region; <code>false</code> otherwise */ private static boolean contains( @NotNull RangeMarker rangeMarker, @NotNull FoldRegion foldRegion) { return rangeMarker.getStartOffset() <= foldRegion.getStartOffset() && rangeMarker.getEndOffset() >= foldRegion.getEndOffset(); }
@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(), "!"); } } }
public static int insertClassReference( PsiClass psiClass, PsiFile file, int startOffset, int endOffset) { final Project project = file.getProject(); PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project); documentManager.commitAllDocuments(); final PsiManager manager = file.getManager(); final Document document = FileDocumentManager.getInstance().getDocument(file.getViewProvider().getVirtualFile()); final PsiReference reference = file.findReferenceAt(startOffset); if (reference != null) { final PsiElement resolved = reference.resolve(); if (resolved instanceof PsiClass) { if (((PsiClass) resolved).getQualifiedName() == null || manager.areElementsEquivalent(psiClass, resolved)) { return endOffset; } } } String name = psiClass.getName(); if (name == null) { return endOffset; } assert document != null; document.replaceString(startOffset, endOffset, name); int newEndOffset = startOffset + name.length(); final RangeMarker toDelete = insertTemporary(newEndOffset, document, " "); documentManager.commitAllDocuments(); PsiElement element = file.findElementAt(startOffset); if (element instanceof PsiIdentifier) { PsiElement parent = element.getParent(); if (parent instanceof PsiJavaCodeReferenceElement && !((PsiJavaCodeReferenceElement) parent).isQualified() && !(parent.getParent() instanceof PsiPackageStatement)) { PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement) parent; if (psiClass.isValid() && !psiClass.getManager().areElementsEquivalent(psiClass, resolveReference(ref))) { final boolean staticImport = ref instanceof PsiImportStaticReferenceElement; PsiElement newElement; try { newElement = staticImport ? ((PsiImportStaticReferenceElement) ref).bindToTargetClass(psiClass) : ref.bindToElement(psiClass); } catch (IncorrectOperationException e) { return endOffset; // can happen if fqn contains reserved words, for example } final RangeMarker rangeMarker = document.createRangeMarker(newElement.getTextRange()); documentManager.doPostponedOperationsAndUnblockDocument(document); documentManager.commitDocument(document); newElement = CodeInsightUtilCore.findElementInRange( file, rangeMarker.getStartOffset(), rangeMarker.getEndOffset(), PsiJavaCodeReferenceElement.class, JavaLanguage.INSTANCE); rangeMarker.dispose(); if (newElement != null) { newEndOffset = newElement.getTextRange().getEndOffset(); if (!(newElement instanceof PsiReferenceExpression)) { PsiReferenceParameterList parameterList = ((PsiJavaCodeReferenceElement) newElement).getParameterList(); if (parameterList != null) { newEndOffset = parameterList.getTextRange().getStartOffset(); } } if (!staticImport && !psiClass .getManager() .areElementsEquivalent(psiClass, resolveReference((PsiReference) newElement)) && !PsiUtil.isInnerClass(psiClass)) { final String qName = psiClass.getQualifiedName(); if (qName != null) { document.replaceString( newElement.getTextRange().getStartOffset(), newEndOffset, qName); newEndOffset = newElement.getTextRange().getStartOffset() + qName.length(); } } } } } } if (toDelete.isValid()) { document.deleteString(toDelete.getStartOffset(), toDelete.getEndOffset()); } return newEndOffset; }
@Override public void writeExternal(Element element) throws WriteExternalException { PsiDocumentManager.getInstance(myProject).commitAllDocuments(); if (myPsiElements.isEmpty() && myRangeMarkers.isEmpty() && mySerializedElements.isEmpty()) { throw new WriteExternalException(); } if (mySerializedElements.isEmpty()) { for (SmartPsiElementPointer<PsiElement> ptr : myPsiElements) { PsiElement psiElement = ptr.getElement(); if (psiElement == null || !psiElement.isValid()) { continue; } FoldingInfo fi = psiElement.getUserData(FOLDING_INFO_KEY); boolean state = fi != null && fi.expanded; String signature = FoldingPolicy.getSignature(psiElement); if (signature == null) { continue; } PsiFile containingFile = psiElement.getContainingFile(); PsiElement restoredElement = FoldingPolicy.restoreBySignature(containingFile, signature); if (!psiElement.equals(restoredElement)) { StringBuilder trace = new StringBuilder(); PsiElement restoredAgain = FoldingPolicy.restoreBySignature(containingFile, signature, trace); LOG.error( "element: " + psiElement + "(" + psiElement.getText() + "); restoredElement: " + restoredElement + "; signature: '" + signature + "'; file: " + containingFile + "; injected: " + InjectedLanguageManager.getInstance(myProject) .isInjectedFragment(containingFile) + "; languages: " + containingFile.getViewProvider().getLanguages() + "; restored again: " + restoredAgain + "; restore produces same results: " + (restoredAgain == restoredElement) + "; trace:\n" + trace); } Element e = new Element(ELEMENT_TAG); e.setAttribute(SIGNATURE_ATT, signature); e.setAttribute(EXPANDED_ATT, Boolean.toString(state)); element.addContent(e); } } else { // get back postponed state (before folding initialization) for (SerializedPsiElement entry : mySerializedElements) { Element e = new Element(ELEMENT_TAG); e.setAttribute(SIGNATURE_ATT, entry.mySerializedElement); e.setAttribute(EXPANDED_ATT, Boolean.toString(entry.myFoldingInfo.getExpanded())); element.addContent(e); } } String date = null; for (RangeMarker marker : myRangeMarkers) { FoldingInfo fi = marker.getUserData(FOLDING_INFO_KEY); boolean state = fi != null && fi.expanded; Element e = new Element(MARKER_TAG); if (date == null) { date = getTimeStamp(); } if (date.isEmpty()) { continue; } e.setAttribute(DATE_ATT, date); e.setAttribute(EXPANDED_ATT, Boolean.toString(state)); String signature = Integer.valueOf(marker.getStartOffset()) + ":" + Integer.valueOf(marker.getEndOffset()); e.setAttribute(SIGNATURE_ATT, signature); String placeHolderText = fi == null ? DEFAULT_PLACEHOLDER : fi.placeHolder; e.setAttribute(PLACEHOLDER_ATT, placeHolderText); element.addContent(e); } }
@Override public void setToEditor(@NotNull final Editor editor) { assertDispatchThread(); final PsiManager psiManager = PsiManager.getInstance(myProject); if (psiManager.isDisposed()) return; if (!myFile.isValid()) return; final PsiFile psiFile = psiManager.findFile(myFile); if (psiFile == null) return; if (!mySerializedElements.isEmpty()) { // Restore postponed state assert myPsiElements.isEmpty() : "Sequential deserialization"; for (SerializedPsiElement entry : mySerializedElements) { PsiElement restoredElement = FoldingPolicy.restoreBySignature(psiFile, entry.mySerializedElement); if (restoredElement != null && restoredElement.isValid()) { myPsiElements.add( SmartPointerManager.getInstance(myProject) .createSmartPsiElementPointer(restoredElement)); restoredElement.putUserData(FOLDING_INFO_KEY, entry.myFoldingInfo); } } mySerializedElements.clear(); } Map<PsiElement, FoldingDescriptor> ranges = null; for (SmartPsiElementPointer<PsiElement> ptr : myPsiElements) { PsiElement element = ptr.getElement(); if (element == null || !element.isValid()) { continue; } if (ranges == null) { ranges = buildRanges(editor, psiFile); } FoldingDescriptor descriptor = ranges.get(element); if (descriptor == null) { continue; } TextRange range = descriptor.getRange(); FoldRegion region = FoldingUtil.findFoldRegion(editor, range.getStartOffset(), range.getEndOffset()); if (region != null) { FoldingInfo fi = element.getUserData(FOLDING_INFO_KEY); boolean state = fi != null && fi.expanded; region.setExpanded(state); } } for (RangeMarker marker : myRangeMarkers) { if (!marker.isValid()) { continue; } FoldRegion region = FoldingUtil.findFoldRegion(editor, marker.getStartOffset(), marker.getEndOffset()); FoldingInfo info = marker.getUserData(FOLDING_INFO_KEY); if (region == null) { if (info != null) { region = editor .getFoldingModel() .addFoldRegion(marker.getStartOffset(), marker.getEndOffset(), info.placeHolder); } if (region == null) { return; } } boolean state = info != null && info.expanded; region.setExpanded(state); } }
@Override protected void invokeImpl(PsiClass targetClass) { final PsiFile callSite = myMethodCall.getContainingFile(); final Project project = myMethodCall.getProject(); PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory(); IdeDocumentHistory.getInstance(project).includeCurrentPlaceAsChangePlace(); try { PsiMethod constructor = elementFactory.createConstructor(); constructor = (PsiMethod) targetClass.add(constructor); final TemplateBuilderImpl templateBuilder = new TemplateBuilderImpl(constructor); CreateFromUsageUtils.setupMethodParameters( constructor, templateBuilder, myMethodCall.getArgumentList(), getTargetSubstitutor(myMethodCall)); final PsiFile psiFile = myMethodCall.getContainingFile(); templateBuilder.setEndVariableAfter(constructor.getBody().getLBrace()); final RangeMarker rangeMarker = psiFile.getViewProvider().getDocument().createRangeMarker(myMethodCall.getTextRange()); constructor = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(constructor); targetClass = constructor.getContainingClass(); myMethodCall = CodeInsightUtil.findElementInRange( psiFile, rangeMarker.getStartOffset(), rangeMarker.getEndOffset(), myMethodCall.getClass()); rangeMarker.dispose(); Template template = templateBuilder.buildTemplate(); final Editor editor = positionCursor(project, targetClass.getContainingFile(), targetClass); if (editor == null) return; final TextRange textRange = constructor.getTextRange(); final PsiFile file = targetClass.getContainingFile(); editor.getDocument().deleteString(textRange.getStartOffset(), textRange.getEndOffset()); editor.getCaretModel().moveToOffset(textRange.getStartOffset()); startTemplate( editor, template, project, new TemplateEditingAdapter() { @Override public void templateFinished(Template template, boolean brokenOff) { ApplicationManager.getApplication() .runWriteAction( new Runnable() { @Override public void run() { try { PsiDocumentManager.getInstance(project) .commitDocument(editor.getDocument()); final int offset = editor.getCaretModel().getOffset(); PsiMethod constructor = PsiTreeUtil.findElementOfClassAtOffset( file, offset, PsiMethod.class, false); CreateFromUsageUtils.setupMethodBody(constructor); CreateFromUsageUtils.setupEditor(constructor, editor); UndoUtil.markPsiFileForUndo(callSite); } catch (IncorrectOperationException e) { LOG.error(e); } } }); } }); } catch (IncorrectOperationException e) { LOG.error(e); } }