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); } }
@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); } }
private static void replaceByTagContent(Project project, XmlTag tagToReplace, XmlTag tagToInline) throws AndroidRefactoringErrorException { final ASTNode node = tagToInline.getNode(); if (node == null) { throw new AndroidRefactoringErrorException(); } final ASTNode startTagEnd = XmlChildRole.START_TAG_END_FINDER.findChild(node); final ASTNode closingTagStart = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(node); if (startTagEnd == null || closingTagStart == null) { throw new AndroidRefactoringErrorException(); } final int contentStart = startTagEnd.getTextRange().getEndOffset(); final int contentEnd = closingTagStart.getTextRange().getStartOffset(); if (contentStart < 0 || contentEnd < 0 || contentStart >= contentEnd) { throw new AndroidRefactoringErrorException(); } final PsiFile file = tagToInline.getContainingFile(); if (file == null) { throw new AndroidRefactoringErrorException(); } final String textToInline = file.getText().substring(contentStart, contentEnd).trim(); final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project); final Document document = documentManager.getDocument(tagToReplace.getContainingFile()); if (document == null) { throw new AndroidRefactoringErrorException(); } final TextRange range = tagToReplace.getTextRange(); document.replaceString(range.getStartOffset(), range.getEndOffset(), textToInline); documentManager.commitDocument(document); }
private void doIndentCommenting(Commenter commenter) { CharSequence chars = myDocument.getCharsSequence(); final FileType fileType = myFile.getFileType(); Indent minIndent = computeMinIndent(myStartLine, myEndLine, chars, myCodeStyleManager, fileType); for (int line = myEndLine; line >= myStartLine; line--) { int lineStart = myDocument.getLineStartOffset(line); int offset = lineStart; final StringBuilder buffer = StringBuilderSpinAllocator.alloc(); try { while (true) { String space = buffer.toString(); Indent indent = myCodeStyleManager.getIndent(space, fileType); if (indent.isGreaterThan(minIndent) || indent.equals(minIndent)) break; char c = chars.charAt(offset); if (c != ' ' && c != '\t') { String newSpace = myCodeStyleManager.fillIndent(minIndent, fileType); myDocument.replaceString(lineStart, offset, newSpace); offset = lineStart + newSpace.length(); break; } buffer.append(c); offset++; } } finally { StringBuilderSpinAllocator.dispose(buffer); } commentLine(line, offset, commenter); } }
private void handleNoSelection(Editor editor) { CaretModel caretModel = editor.getCaretModel(); Document doc = editor.getDocument(); if ((caretModel == null) || (doc == null) || (doc.getTextLength() == 0)) { return; } char[] allChars = doc.getChars(); int maxOffset = allChars.length; int startOffset = caretModel.getOffset(); while ((startOffset < maxOffset) && (!Character.isLetterOrDigit(allChars[startOffset]))) { startOffset++; } StringBuffer word = new StringBuffer(); int i = startOffset; while ((i < maxOffset) && (Character.isLetterOrDigit(allChars[i]))) { word.append(allChars[i]); i++; } if (word.length() > 0) { this.m_transformer.transform(word); int newOffset = startOffset + word.length(); doc.replaceString(startOffset, newOffset, word.toString()); caretModel.moveToOffset(newOffset); } }
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { PsiElement element = descriptor.getPsiElement(); PsiStatement anchorStatement = PsiTreeUtil.getParentOfType(element, PsiStatement.class); LOG.assertTrue(anchorStatement != null); Editor editor = getEditor(project, element); if (editor == null) return; PsiFile file = element.getContainingFile(); PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project); Document document = documentManager.getDocument(file); if (!CodeInsightUtilBase.prepareFileForWrite(file)) return; PsiElement[] elements = {anchorStatement}; PsiElement prev = PsiTreeUtil.skipSiblingsBackward(anchorStatement, PsiWhiteSpace.class); if (prev instanceof PsiComment && SuppressManager.getInstance().getSuppressedInspectionIdsIn(prev) != null) { elements = new PsiElement[] {prev, anchorStatement}; } try { TextRange textRange = new JavaWithIfSurrounder().surroundElements(project, editor, elements); if (textRange == null) return; @NonNls String newText = myText + " != null"; document.replaceString(textRange.getStartOffset(), textRange.getEndOffset(), newText); editor.getCaretModel().moveToOffset(textRange.getEndOffset() + newText.length()); editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); } catch (IncorrectOperationException e) { LOG.error(e); } }
private void updateDocumentFromPropertyValue( final String value, final Document document, final PropertiesFile propertiesFile) { @NonNls String text = value; if (myBackSlashPressed.contains(propertiesFile)) { text += "\\"; } document.replaceString(0, document.getTextLength(), text); }
public void testPersistentMarkerDoesntImpactNormalMarkers() { Document doc = new DocumentImpl("text"); RangeMarker normal = doc.createRangeMarker(1, 3); RangeMarker persistent = doc.createRangeMarker(1, 3, true); doc.replaceString(0, 4, "before\ntext\nafter"); assertTrue(persistent.isValid()); assertFalse(normal.isValid()); }
@Override public void reparseRange(PsiFile file, int startOffset, int endOffset, CharSequence newTextS) throws IncorrectOperationException { LOG.assertTrue(file.isValid()); final PsiFileImpl psiFile = (PsiFileImpl) file; final Document document = psiFile.getViewProvider().getDocument(); assert document != null; document.replaceString(startOffset, endOffset, newTextS); PsiDocumentManager.getInstance(psiFile.getProject()).commitDocument(document); }
public void testPersistent() throws Exception { String text = "xxx\nzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"; Document document = EditorFactory.getInstance().createDocument(text); int startOffset = text.indexOf('z'); int endOffset = text.lastIndexOf('z'); RangeMarker marker = document.createRangeMarker(startOffset, endOffset, true); document.replaceString(startOffset + 1, endOffset - 1, "ccc"); assertTrue(marker.isValid()); }
private void extractExpectedLineMarkerSet(Document document) { String text = document.getText(); String pat = ".*?((<" + LINE_MARKER + ")(?: descr=\"((?:[^\"\\\\]|\\\\\")*)\")?>)(.*)"; final Pattern p = Pattern.compile(pat, Pattern.DOTALL); final Pattern pat2 = Pattern.compile("(.*?)(</" + LINE_MARKER + ">)(.*)", Pattern.DOTALL); while (true) { Matcher m = p.matcher(text); if (!m.matches()) break; int startOffset = m.start(1); final String descr = m.group(3) != null ? m.group(3) : ANY_TEXT; String rest = m.group(4); document.replaceString(startOffset, m.end(1), ""); final Matcher matcher2 = pat2.matcher(rest); LOG.assertTrue(matcher2.matches(), "Cannot find closing </" + LINE_MARKER + ">"); String content = matcher2.group(1); int endOffset = startOffset + matcher2.start(3); String endTag = matcher2.group(2); document.replaceString(startOffset, endOffset, content); endOffset -= endTag.length(); LineMarkerInfo markerInfo = new LineMarkerInfo<PsiElement>( myFile, new TextRange(startOffset, endOffset), null, Pass.LINE_MARKERS, new ConstantFunction<>(descr), null, GutterIconRenderer.Alignment.RIGHT); myLineMarkerInfos.put(document.createRangeMarker(startOffset, endOffset), markerInfo); text = document.getText(); } }
protected void runOverEditor( @NotNull final Project project, @NotNull final Editor editor, @NotNull final PsiFile psiFile) { final Document document = editor.getDocument(); if (!ReadonlyStatusHandler.ensureDocumentWritable(project, document)) return; final Runnable runnable = () -> { final int caretOffset = editor.getCaretModel().getOffset(); final int lineLength = getRightMargin(project); DartAnalysisServerService.getInstance().updateFilesContent(); DartAnalysisServerService.FormatResult formatResult = DartAnalysisServerService.getInstance() .edit_format(psiFile.getVirtualFile(), caretOffset, 0, lineLength); if (formatResult == null) { showHintLater(editor, DartBundle.message("dart.style.hint.failed"), true); LOG.warn("Unexpected response from edit_format, formatResult is null"); return; } final List<SourceEdit> edits = formatResult.getEdits(); if (edits == null || edits.size() == 0) { showHintLater(editor, DartBundle.message("dart.style.hint.already.good"), false); } else if (edits.size() == 1) { final String replacement = StringUtil.convertLineSeparators(edits.get(0).getReplacement()); document.replaceString(0, document.getTextLength(), replacement); final int offset = DartAnalysisServerService.getInstance() .getConvertedOffset(psiFile.getVirtualFile(), formatResult.getOffset()); editor.getCaretModel().moveToOffset(offset); showHintLater(editor, DartBundle.message("dart.style.hint.success"), false); } else { showHintLater(editor, DartBundle.message("dart.style.hint.failed"), true); LOG.warn( "Unexpected response from edit_format, formatResult.getEdits().size() = " + edits.size()); } }; ApplicationManager.getApplication() .runWriteAction( () -> CommandProcessor.getInstance() .executeCommand( project, runnable, DartBundle.message("dart.style.action.name"), null)); }
@Override protected void doFix(Project project, ProblemDescriptor descriptor) { final TextRange textRange = descriptor.getTextRangeInElement(); final PsiElement element = descriptor.getPsiElement(); if (!(element instanceof PsiFile)) { return; } final PsiFile file = (PsiFile) element; final Document document = PsiDocumentManager.getInstance(project).getDocument(file); if (document == null) { return; } document.replaceString( textRange.getStartOffset(), textRange.getEndOffset(), String.valueOf(c)); }
public boolean process( @NotNull final Project project, @NotNull final Editor editor, @NotNull final PsiFile psiFile) { final Document document = editor.getDocument(); final String textForRollback = document.getText(); try { editor.putUserData(SMART_ENTER_TIMESTAMP, editor.getDocument().getModificationStamp()); myFirstErrorOffset = Integer.MAX_VALUE; process(project, editor, psiFile, 0); } catch (TooManyAttemptsException e) { document.replaceString(0, document.getTextLength(), textForRollback); } finally { editor.putUserData(SMART_ENTER_TIMESTAMP, null); } return true; }
private void replaceString( Project project, Document document, String replaceText, int startOffset, int endOffset) { CommandProcessor.getInstance() .executeCommand( project, (Runnable) () -> { ApplicationManager.getApplication() .runWriteAction( (Runnable) () -> { document.replaceString(startOffset, endOffset, replaceText); }); }, "Auto-Align", this); }
private static void adjustIndentationInRange( final PsiFile file, final Document document, final TextRange[] indents, final int indentAdjustment) { final CharSequence charsSequence = document.getCharsSequence(); for (final TextRange indent : indents) { final String oldIndentStr = charsSequence.subSequence(indent.getStartOffset() + 1, indent.getEndOffset()).toString(); final int oldIndent = IndentHelperImpl.getIndent(file.getProject(), file.getFileType(), oldIndentStr, true); final String newIndentStr = IndentHelperImpl.fillIndent( file.getProject(), file.getFileType(), Math.max(oldIndent + indentAdjustment, 0)); document.replaceString(indent.getStartOffset() + 1, indent.getEndOffset(), newIndentStr); } }
public static void renameNonCodeUsages( @NotNull Project project, @NotNull NonCodeUsageInfo[] usages) { PsiDocumentManager.getInstance(project).commitAllDocuments(); Map<Document, List<UsageOffset>> docsToOffsetsMap = new HashMap<Document, List<UsageOffset>>(); final PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project); for (NonCodeUsageInfo usage : usages) { PsiElement element = usage.getElement(); if (element == null) continue; element = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(element, true); if (element == null) continue; final ProperTextRange rangeInElement = usage.getRangeInElement(); if (rangeInElement == null) continue; final PsiFile containingFile = element.getContainingFile(); final Document document = psiDocumentManager.getDocument(containingFile); final Segment segment = usage.getSegment(); LOG.assertTrue(segment != null); int fileOffset = segment.getStartOffset(); List<UsageOffset> list = docsToOffsetsMap.get(document); if (list == null) { list = new ArrayList<UsageOffset>(); docsToOffsetsMap.put(document, list); } list.add(new UsageOffset(fileOffset, fileOffset + rangeInElement.getLength(), usage.newText)); } for (Document document : docsToOffsetsMap.keySet()) { List<UsageOffset> list = docsToOffsetsMap.get(document); LOG.assertTrue(list != null, document); UsageOffset[] offsets = list.toArray(new UsageOffset[list.size()]); Arrays.sort(offsets); for (int i = offsets.length - 1; i >= 0; i--) { UsageOffset usageOffset = offsets[i]; document.replaceString(usageOffset.startOffset, usageOffset.endOffset, usageOffset.newText); } PsiDocumentManager.getInstance(project).commitDocument(document); } PsiDocumentManager.getInstance(project).commitAllDocuments(); }
public static void addImportDirectiveOrChangeToFqName( @NotNull FqName importFqn, @NotNull JetFile file, int refOffset, @NotNull PsiElement targetElement) { PsiReference reference = file.findReferenceAt(refOffset); if (reference instanceof JetPsiReference) { PsiElement target = reference.resolve(); if (target != null) { boolean same = file.getManager().areElementsEquivalent(target, targetElement); if (!same) { same = target instanceof PsiClass && importFqn.getFqName().equals(((PsiClass) target).getQualifiedName()); } if (!same) { if (target instanceof PsiMethod) { PsiMethod method = (PsiMethod) target; same = (method.isConstructor() && file.getManager() .areElementsEquivalent(method.getContainingClass(), targetElement)); } } if (!same) { if (target instanceof JetObjectDeclarationName) { same = file.getManager().areElementsEquivalent(target.getParent(), targetElement); } } if (!same) { Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file); TextRange refRange = reference.getElement().getTextRange(); document.replaceString( refRange.getStartOffset(), refRange.getEndOffset(), importFqn.getFqName()); } return; } } addImportDirective(new ImportPath(importFqn, false), null, file); }
private int doBoundCommentingAndGetShift( int offset, String commented, int skipLength, String toInsert, boolean skipBrace, TextRange selection) { if (commented == null && (offset == selection.getStartOffset() || offset + (skipBrace ? skipLength : 0) == selection.getEndOffset())) { return 0; } if (commented == null) { myDocument.insertString(offset + (skipBrace ? skipLength : 0), toInsert); return toInsert.length(); } else { myDocument.replaceString(offset, offset + skipLength, commented); return commented.length() - skipLength; } }
private void handleSelection(Editor editor, SelectionModel selectionModel) { Document doc = editor.getDocument(); if (doc == null) { return; } int start = selectionModel.getSelectionStart(); int end = selectionModel.getSelectionEnd(); char[] allChars = doc.getChars(); StringBuffer selection = new StringBuffer(); selection.append(allChars, start, end - start); this.m_transformer.transform(selection); doc.replaceString(start, end, selection.toString()); selectionModel.setSelection(start, start + selection.length()); }
@NotNull protected String doExtract( final PsiDirectory targetDirectory, final String targetfileName, final T first, final T last, final Language includingLanguage) throws IncorrectOperationException { final PsiFile file = targetDirectory.createFile(targetfileName); Project project = targetDirectory.getProject(); final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project); final Document document = documentManager.getDocument(file); document.replaceString(0, document.getTextLength(), first.getText().trim()); documentManager.commitDocument(document); CodeStyleManager.getInstance(PsiManager.getInstance(project).getProject()) .reformat(file); // TODO: adjustLineIndent final String relativePath = PsiFileSystemItemUtil.getRelativePath(first.getContainingFile(), file); if (relativePath == null) throw new IncorrectOperationException("Cannot extract!"); return relativePath; }
private static void doAddImport(GoFile file, Editor editor, String pathToImport) { GoImportDeclarations[] ids = file.getImportDeclarations(); Document document = editor.getDocument(); if (ids.length == 0) { addImportUnderPackage(file, document, pathToImport); return; } GoImportDeclarations importDeclarations = ids[ids.length - 1]; GoImportDeclaration[] imports = importDeclarations.getDeclarations(); if (imports.length == 0) { addImportUnderPackage(file, document, pathToImport); return; } GoImportDeclaration lastImport = imports[imports.length - 1]; PsiElement lastChild = getPrevSiblingIfItsWhiteSpaceOrComment(importDeclarations.getLastChild()); if (lastChild == null) { addImportUnderPackage(file, document, pathToImport); return; } if (")".equals(lastChild.getText())) { document.insertString(lastChild.getTextOffset(), "\"" + pathToImport + "\"\n"); int line = document.getLineNumber(lastChild.getTextOffset()); reformatLines(file, editor, line, line); } else { String oldImport = lastImport.getText(); int start = lastImport.getTextOffset(); int end = start + lastImport.getTextLength(); String declarations = String.format("(\n%s\n\"%s\"\n)", oldImport, pathToImport); document.replaceString(start, end, declarations); reformatPositions(file, start, start + declarations.length()); } }
private static VirtualFile getCopyWithAnswers( @NotNull final VirtualFile taskDir, @NotNull final VirtualFile file, @NotNull final TaskFile source, @NotNull final TaskFile target) { VirtualFile copy = null; try { copy = file.copy( taskDir, taskDir, file.getNameWithoutExtension() + EduNames.ANSWERS_POSTFIX + "." + file.getExtension()); final FileDocumentManager documentManager = FileDocumentManager.getInstance(); final Document document = documentManager.getDocument(copy); if (document != null) { TaskFile.copy(source, target); EduDocumentListener listener = new EduDocumentListener(target); document.addDocumentListener(listener); for (AnswerPlaceholder answerPlaceholder : target.getAnswerPlaceholders()) { final int start = answerPlaceholder.getOffset(); final int end = start + answerPlaceholder.getRealLength(); final String text = answerPlaceholder.getPossibleAnswer(); document.replaceString(start, end, text); } ApplicationManager.getApplication() .runWriteAction(() -> documentManager.saveDocument(document)); } } catch (IOException e) { LOG.error(e); } return copy; }
@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(), "!"); } } }
private static void fixDocumentQuotes(Document doc, int offset) { if (doc.getCharsSequence().charAt(offset) == '\'') { doc.replaceString(offset, offset + 1, "\""); } }
public void patch(final FlooPatch res) { final TextBuf b = this; Flog.info("Got _on_patch"); String text; String md5FromDoc; final Document d; String oldText = buf; VirtualFile virtualFile = b.getVirtualFile(); if (virtualFile == null) { Flog.warn("VirtualFile is null, no idea what do do. Aborting everything %s", this); getBuf(); return; } d = Buf.getDocumentForVirtualFile(virtualFile); if (d == null) { Flog.warn("Document not found for %s", virtualFile); getBuf(); return; } String viewText; if (virtualFile.exists()) { viewText = d.getText(); if (viewText.equals(oldText)) { b.forced_patch = false; } else if (!b.forced_patch) { b.forced_patch = true; oldText = viewText; b.send_patch(viewText); Flog.warn("Sending force patch for %s. this is dangerous!", b.path); } } else { viewText = oldText; } b.cancelTimeout(); String md5Before = DigestUtils.md5Hex(viewText); if (!md5Before.equals(res.md5_before)) { Flog.warn("starting md5s don't match for %s. this is dangerous!", b.path); } List<diff_match_patch.Patch> patches = dmp.patch_fromText(res.patch); final Object[] results = dmp.patch_apply((LinkedList<diff_match_patch.Patch>) patches, oldText); final String patchedContents = (String) results[0]; final boolean[] patchesClean = (boolean[]) results[1]; final FlooPatchPosition[] positions = (FlooPatchPosition[]) results[2]; for (boolean clean : patchesClean) { if (!clean) { Flog.log("Patch not clean for %s. Sending get_buf and setting readonly.", d); getBuf(); return; } } // XXX: If patchedContents have carriage returns this will be a problem: String md5After = DigestUtils.md5Hex(patchedContents); if (!md5After.equals(res.md5_after)) { Flog.info("MD5 after mismatch (ours %s remote %s)", md5After, res.md5_after); } if (!d.isWritable()) { d.setReadOnly(false); } if (!ReadonlyStatusHandler.ensureDocumentWritable(context.project, d)) { Flog.info("Document: %s is not writable.", d); return; } final Editor[] editors = EditorFactory.getInstance().getEditors(d, context.project); final HashMap<ScrollingModel, Integer[]> original = new HashMap<ScrollingModel, Integer[]>(); for (Editor editor : editors) { if (editor.isDisposed()) { continue; } ScrollingModel scrollingModel = editor.getScrollingModel(); original.put( scrollingModel, new Integer[] { scrollingModel.getHorizontalScrollOffset(), scrollingModel.getVerticalScrollOffset() }); } for (FlooPatchPosition flooPatchPosition : positions) { int start = Math.max(0, flooPatchPosition.start); int end_ld = Math.max(start + flooPatchPosition.end, start); end_ld = Math.min(end_ld, d.getTextLength()); String contents = NEW_LINE.matcher(flooPatchPosition.text).replaceAll("\n"); Throwable e = null; try { Listener.flooDisable(); d.replaceString(start, end_ld, contents); } catch (Throwable exception) { e = exception; } finally { Listener.flooEnable(); } if (e != null) { Flog.warn(e); getBuf(); return; } } text = d.getText(); md5FromDoc = DigestUtils.md5Hex(text); if (!md5FromDoc.equals(res.md5_after)) { Flog.info("md5FromDoc mismatch (ours %s remote %s)", md5FromDoc, res.md5_after); b.setGetBufTimeout(); } for (Map.Entry<ScrollingModel, Integer[]> entry : original.entrySet()) { ScrollingModel model = entry.getKey(); Integer[] offsets = entry.getValue(); model.scrollHorizontally(offsets[0]); model.scrollVertically(offsets[1]); } b.set(text, md5FromDoc); Flog.log("Patched %s", res.path); }
static void commentNestedComments( @NotNull Document document, TextRange range, Commenter commenter) { final int offset = range.getStartOffset(); final IntArrayList toReplaceWithComments = new IntArrayList(); final IntArrayList prefixes = new IntArrayList(); final String text = document .getCharsSequence() .subSequence(range.getStartOffset(), range.getEndOffset()) .toString(); final String commentedPrefix = commenter.getCommentedBlockCommentPrefix(); final String commentedSuffix = commenter.getCommentedBlockCommentSuffix(); final String commentPrefix = commenter.getBlockCommentPrefix(); final String commentSuffix = commenter.getBlockCommentSuffix(); int nearestSuffix = getNearest(text, commentedSuffix, 0); int nearestPrefix = getNearest(text, commentedPrefix, 0); int level = 0; int lastSuffix = -1; for (int i = Math.min(nearestPrefix, nearestSuffix); i < text.length(); i = Math.min(nearestPrefix, nearestSuffix)) { if (i > nearestPrefix) { nearestPrefix = getNearest(text, commentedPrefix, i); continue; } if (i > nearestSuffix) { nearestSuffix = getNearest(text, commentedSuffix, i); continue; } if (i == nearestPrefix) { if (level <= 0) { if (lastSuffix != -1) { toReplaceWithComments.add(lastSuffix); } level = 1; lastSuffix = -1; toReplaceWithComments.add(i); prefixes.add(i); } else { level++; } nearestPrefix = getNearest(text, commentedPrefix, nearestPrefix + 1); } else { lastSuffix = i; level--; nearestSuffix = getNearest(text, commentedSuffix, nearestSuffix + 1); } } if (lastSuffix != -1) { toReplaceWithComments.add(lastSuffix); } int prefixIndex = prefixes.size() - 1; for (int i = toReplaceWithComments.size() - 1; i >= 0; i--) { int position = toReplaceWithComments.get(i); if (prefixIndex >= 0 && position == prefixes.get(prefixIndex)) { prefixIndex--; document.replaceString( offset + position, offset + position + commentedPrefix.length(), commentPrefix); } else { document.replaceString( offset + position, offset + position + commentedSuffix.length(), commentSuffix); } } }
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; }
private void commentLine(int line, int offset, @Nullable Commenter commenter) { if (commenter == null) commenter = findCommenter(line); if (commenter == null) return; if (commenter instanceof SelfManagingCommenter) { final SelfManagingCommenter selfManagingCommenter = (SelfManagingCommenter) commenter; selfManagingCommenter.commentLine( line, offset, myDocument, myCommenterStateMap.get(selfManagingCommenter)); return; } String prefix = commenter.getLineCommentPrefix(); if (prefix != null) { if (commenter instanceof CommenterWithLineSuffix) { int endOffset = myDocument.getLineEndOffset(line); endOffset = CharArrayUtil.shiftBackward(myDocument.getCharsSequence(), endOffset, " \t"); int shiftedStartOffset = CharArrayUtil.shiftForward(myDocument.getCharsSequence(), offset, " \t"); String lineSuffix = ((CommenterWithLineSuffix) commenter).getLineCommentSuffix(); if (!CharArrayUtil.regionMatches( myDocument.getCharsSequence(), shiftedStartOffset, prefix)) { if (!CharArrayUtil.regionMatches( myDocument.getCharsSequence(), endOffset - lineSuffix.length(), lineSuffix)) { myDocument.insertString(endOffset, lineSuffix); } myDocument.insertString(offset, prefix); } } else { myDocument.insertString(offset, prefix); } } else { prefix = commenter.getBlockCommentPrefix(); String suffix = commenter.getBlockCommentSuffix(); if (prefix == null || suffix == null) return; int endOffset = myDocument.getLineEndOffset(line); if (endOffset == offset && myStartLine != myEndLine) return; final int textLength = myDocument.getTextLength(); final CharSequence chars = myDocument.getCharsSequence(); offset = CharArrayUtil.shiftForward(chars, offset, " \t"); if (endOffset == textLength) { final int shifted = CharArrayUtil.shiftBackward(chars, textLength - 1, " \t"); if (shifted < textLength - 1) endOffset = shifted; } else { endOffset = CharArrayUtil.shiftBackward(chars, endOffset, " \t"); } if (endOffset < offset || offset == textLength - 1 && line != myDocument.getLineCount() - 1) { return; } final String text = chars.subSequence(offset, endOffset).toString(); final IntArrayList prefixes = new IntArrayList(); final IntArrayList suffixes = new IntArrayList(); final String commentedSuffix = commenter.getCommentedBlockCommentSuffix(); final String commentedPrefix = commenter.getCommentedBlockCommentPrefix(); for (int position = 0; position < text.length(); ) { int nearestPrefix = text.indexOf(prefix, position); if (nearestPrefix == -1) { nearestPrefix = text.length(); } int nearestSuffix = text.indexOf(suffix, position); if (nearestSuffix == -1) { nearestSuffix = text.length(); } if (Math.min(nearestPrefix, nearestSuffix) == text.length()) { break; } if (nearestPrefix < nearestSuffix) { prefixes.add(nearestPrefix); position = nearestPrefix + prefix.length(); } else { suffixes.add(nearestSuffix); position = nearestSuffix + suffix.length(); } } if (!(commentedSuffix == null && !suffixes.isEmpty() && offset + suffixes.get(suffixes.size() - 1) + suffix.length() >= endOffset)) { myDocument.insertString(endOffset, suffix); } int nearestPrefix = prefixes.size() - 1; int nearestSuffix = suffixes.size() - 1; while (nearestPrefix >= 0 || nearestSuffix >= 0) { if (nearestSuffix == -1 || nearestPrefix != -1 && prefixes.get(nearestPrefix) > suffixes.get(nearestSuffix)) { final int position = prefixes.get(nearestPrefix); nearestPrefix--; if (commentedPrefix != null) { myDocument.replaceString( offset + position, offset + position + prefix.length(), commentedPrefix); } else if (position != 0) { myDocument.insertString(offset + position, suffix); } } else { final int position = suffixes.get(nearestSuffix); nearestSuffix--; if (commentedSuffix != null) { myDocument.replaceString( offset + position, offset + position + suffix.length(), commentedSuffix); } else if (offset + position + suffix.length() < endOffset) { myDocument.insertString(offset + position + suffix.length(), prefix); } } } if (!(commentedPrefix == null && !prefixes.isEmpty() && prefixes.get(0) == 0)) { myDocument.insertString(offset, prefix); } } }