QuickEditHandler( Project project, @NotNull PsiFile injectedFile, final PsiFile origFile, Editor editor, QuickEditAction action) { myProject = project; myEditor = editor; myAction = action; myOrigDocument = editor.getDocument(); Place shreds = InjectedLanguageUtil.getShreds(injectedFile); FileType fileType = injectedFile.getFileType(); Language language = injectedFile.getLanguage(); PsiLanguageInjectionHost.Shred firstShred = ContainerUtil.getFirstItem(shreds); PsiFileFactory factory = PsiFileFactory.getInstance(project); String text = InjectedLanguageManager.getInstance(project).getUnescapedText(injectedFile); String newFileName = StringUtil.notNullize(language.getDisplayName(), "Injected") + " Fragment " + "(" + origFile.getName() + ":" + firstShred.getHost().getTextRange().getStartOffset() + ")" + "." + fileType.getDefaultExtension(); // preserve \r\n as it is done in MultiHostRegistrarImpl myNewFile = factory.createFileFromText(newFileName, language, text, true, false); myNewVirtualFile = ObjectUtils.assertNotNull((LightVirtualFile) myNewFile.getVirtualFile()); myNewVirtualFile.setOriginalFile(origFile.getVirtualFile()); assert myNewFile != null : "PSI file is null"; assert myNewFile.getTextLength() == myNewVirtualFile.getContent().length() : "PSI / Virtual file text mismatch"; myNewVirtualFile.setOriginalFile(origFile.getVirtualFile()); // suppress possible errors as in injected mode myNewFile.putUserData( InjectedLanguageUtil.FRANKENSTEIN_INJECTION, injectedFile.getUserData(InjectedLanguageUtil.FRANKENSTEIN_INJECTION)); myNewFile.putUserData(FileContextUtil.INJECTED_IN_ELEMENT, shreds.getHostPointer()); myNewDocument = PsiDocumentManager.getInstance(project).getDocument(myNewFile); assert myNewDocument != null; EditorActionManager.getInstance() .setReadonlyFragmentModificationHandler(myNewDocument, new MyQuietHandler()); myOrigCreationStamp = myOrigDocument.getModificationStamp(); // store creation stamp for UNDO tracking myOrigDocument.addDocumentListener(this, this); myNewDocument.addDocumentListener(this, this); EditorFactory editorFactory = ObjectUtils.assertNotNull(EditorFactory.getInstance()); // not FileEditorManager listener because of RegExp checker and alike editorFactory.addEditorFactoryListener( new EditorFactoryAdapter() { int useCount; @Override public void editorCreated(@NotNull EditorFactoryEvent event) { if (event.getEditor().getDocument() != myNewDocument) return; useCount++; } @Override public void editorReleased(@NotNull EditorFactoryEvent event) { if (event.getEditor().getDocument() != myNewDocument) return; if (--useCount > 0) return; if (Boolean.TRUE.equals( myNewVirtualFile.getUserData(FileEditorManagerImpl.CLOSING_TO_REOPEN))) return; Disposer.dispose(QuickEditHandler.this); } }, this); if ("JAVA".equals(firstShred.getHost().getLanguage().getID())) { PsiLanguageInjectionHost.Shred lastShred = ContainerUtil.getLastItem(shreds); myAltFullRange = myOrigDocument.createRangeMarker( firstShred.getHostRangeMarker().getStartOffset(), lastShred.getHostRangeMarker().getEndOffset()); myAltFullRange.setGreedyToLeft(true); myAltFullRange.setGreedyToRight(true); initGuardedBlocks(shreds); myInjectedFile = null; } else { initMarkers(shreds); myAltFullRange = null; myInjectedFile = injectedFile; } }
private static boolean isCommentComplete( PsiComment comment, CodeDocumentationAwareCommenter commenter, Editor editor) { for (CommentCompleteHandler handler : Extensions.getExtensions(CommentCompleteHandler.EP_NAME)) { if (handler.isApplicable(comment, commenter)) { return handler.isCommentComplete(comment, commenter, editor); } } String commentText = comment.getText(); final boolean docComment = isDocComment(comment, commenter); final String expectedCommentEnd = docComment ? commenter.getDocumentationCommentSuffix() : commenter.getBlockCommentSuffix(); if (!commentText.endsWith(expectedCommentEnd)) return false; final PsiFile containingFile = comment.getContainingFile(); final Language language = containingFile.getLanguage(); ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(language); if (parserDefinition == null) { return true; } Lexer lexer = parserDefinition.createLexer(containingFile.getProject()); final String commentPrefix = docComment ? commenter.getDocumentationCommentPrefix() : commenter.getBlockCommentPrefix(); lexer.start( commentText, commentPrefix == null ? 0 : commentPrefix.length(), commentText.length()); QuoteHandler fileTypeHandler = TypedHandler.getQuoteHandler(containingFile, editor); JavaLikeQuoteHandler javaLikeQuoteHandler = fileTypeHandler instanceof JavaLikeQuoteHandler ? (JavaLikeQuoteHandler) fileTypeHandler : null; while (true) { IElementType tokenType = lexer.getTokenType(); if (tokenType == null) { return false; } if (javaLikeQuoteHandler != null && javaLikeQuoteHandler.getStringTokenTypes() != null && javaLikeQuoteHandler.getStringTokenTypes().contains(tokenType)) { String text = commentText.substring(lexer.getTokenStart(), lexer.getTokenEnd()); int endOffset = comment.getTextRange().getEndOffset(); if (text.endsWith(expectedCommentEnd) && endOffset < containingFile.getTextLength() && containingFile.getText().charAt(endOffset) == '\n') { return true; } } if (tokenType == commenter.getDocumentationCommentTokenType() || tokenType == commenter.getBlockCommentTokenType()) { return false; } if (tokenType == commenter.getLineCommentTokenType() && lexer.getTokenText().contains(commentPrefix)) { return false; } if (lexer.getTokenEnd() == commentText.length()) { if (tokenType == commenter.getLineCommentTokenType()) { String prefix = commenter.getLineCommentPrefix(); lexer.start( commentText, lexer.getTokenStart() + (prefix == null ? 0 : prefix.length()), commentText.length()); lexer.advance(); continue; } else if (isInvalidPsi(comment)) { return false; } return true; } lexer.advance(); } }