@Override public void tokenize(@NotNull PsiLiteralExpression element, TokenConsumer consumer) { PsiLiteralExpressionImpl literalExpression = (PsiLiteralExpressionImpl)element; if (literalExpression.getLiteralElementType() != JavaTokenType.STRING_LITERAL) return; // not a string literal String text = literalExpression.getInnerText(); if (StringUtil.isEmpty(text) || text.length() <= 2) { // optimisation to avoid expensive injection check return; } if (InjectedLanguageUtil.hasInjections(literalExpression)) return; final PsiModifierListOwner listOwner = PsiTreeUtil.getParentOfType(element, PsiModifierListOwner.class); if (listOwner != null && AnnotationUtil.isAnnotated(listOwner, Collections.singleton(AnnotationUtil.NON_NLS), false, false)) { return; } if (!text.contains("\\")) { consumer.consumeToken(element, PlainTextSplitter.getInstance()); } else { processTextWithEscapeSequences(element, text, consumer); } }
private static void setupEditorForInjectedLanguage() { if (myEditor != null) { final Ref<EditorWindow> editorWindowRef = new Ref<EditorWindow>(); myEditor.getCaretModel().runForEachCaret(new CaretAction() { @Override public void perform(Caret caret) { Editor editor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(myEditor, myFile); if (caret == myEditor.getCaretModel().getPrimaryCaret() && editor instanceof EditorWindow) { editorWindowRef.set((EditorWindow)editor); } } }); if (!editorWindowRef.isNull()) { myEditor = editorWindowRef.get(); myFile = editorWindowRef.get().getInjectedFile(); } } }
void match(PsiElement element, final Language language) { final MatchingStrategy strategy = matchContext.getPattern().getStrategy(); final Language elementLanguage = element.getLanguage(); if (strategy.continueMatching(element) && elementLanguage.isKindOf(language)) { visitor.matchContext(new ArrayBackedNodeIterator(new PsiElement[] {element})); return; } for(PsiElement el=element.getFirstChild();el!=null;el=el.getNextSibling()) { match(el, language); } if (element instanceof PsiLanguageInjectionHost) { InjectedLanguageUtil.enumerate(element, new PsiLanguageInjectionHost.InjectedPsiVisitor() { @Override public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) { match(injectedPsi, language); } }); } }
private static boolean shouldSkipAutoPopup(Editor editor, PsiFile psiFile) { int offset = editor.getCaretModel().getOffset(); int psiOffset = Math.max(0, offset - 1); PsiElement elementAt = InjectedLanguageUtil.findInjectedElementNoCommit(psiFile, psiOffset); if (elementAt == null) { elementAt = psiFile.findElementAt(psiOffset); } if (elementAt == null) return true; Language language = PsiUtilCore.findLanguageFromElement(elementAt); for (CompletionConfidence confidence : CompletionConfidenceEP.forLanguage(language)) { final ThreeState result = confidence.shouldSkipAutopopup(elementAt, psiFile, offset); if (result != ThreeState.UNSURE) { LOG.debug(confidence + " has returned shouldSkipAutopopup=" + result); return result == ThreeState.YES; } } return false; }
private static CompletionContext createCompletionContext(PsiFile hostCopy, int hostStartOffset, OffsetMap hostMap, PsiFile originalFile) { CompletionAssertions.assertHostInfo(hostCopy, hostMap); InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(hostCopy.getProject()); CompletionContext context; PsiFile injected = InjectedLanguageUtil.findInjectedPsiNoCommit(hostCopy, hostStartOffset); if (injected != null) { if (injected instanceof PsiFileImpl) { ((PsiFileImpl)injected).setOriginalFile(originalFile); } DocumentWindow documentWindow = InjectedLanguageUtil.getDocumentWindow(injected); CompletionAssertions.assertInjectedOffsets(hostStartOffset, injectedLanguageManager, injected, documentWindow); context = new CompletionContext(injected, translateOffsetMapToInjected(hostMap, documentWindow)); } else { context = new CompletionContext(hostCopy, hostMap); } CompletionAssertions.assertFinalOffsets(originalFile, context, injected); return context; }
private static Runnable rememberDocumentState(final Editor _editor) { final Editor editor = InjectedLanguageUtil.getTopLevelEditor(_editor); final String documentText = editor.getDocument().getText(); final int caret = editor.getCaretModel().getOffset(); final int selStart = editor.getSelectionModel().getSelectionStart(); final int selEnd = editor.getSelectionModel().getSelectionEnd(); final int vOffset = editor.getScrollingModel().getVerticalScrollOffset(); final int hOffset = editor.getScrollingModel().getHorizontalScrollOffset(); return new Runnable() { @Override public void run() { DocumentEx document = (DocumentEx) editor.getDocument(); document.replaceString(0, document.getTextLength(), documentText); editor.getCaretModel().moveToOffset(caret); editor.getSelectionModel().setSelection(selStart, selEnd); editor.getScrollingModel().scrollHorizontally(hOffset); editor.getScrollingModel().scrollVertically(vOffset); } }; }
private static void iterateOverCarets(@NotNull final Project project, @NotNull final Editor hostEditor, @NotNull final MultiCaretCodeInsightActionHandler handler) { PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project); final PsiFile psiFile = documentManager.getCachedPsiFile(hostEditor.getDocument()); documentManager.commitAllDocuments(); hostEditor.getCaretModel().runForEachCaret(new CaretAction() { @Override public void perform(Caret caret) { Editor editor = hostEditor; if (psiFile != null) { Caret injectedCaret = InjectedLanguageUtil.getCaretForInjectedLanguageNoCommit(caret, psiFile); if (injectedCaret != null) { caret = injectedCaret; editor = caret.getEditor(); } } final PsiFile file = PsiUtilBase.getPsiFileInEditor(caret, project); if (file != null) { handler.invoke(project, editor, caret, file); } } }); }
@NotNull public static Editor injectedEditorIfCharTypedIsSignificant(final char charTyped, @NotNull Editor editor, @NotNull PsiFile oldFile) { int offset = editor.getCaretModel().getOffset(); // even for uncommitted document try to retrieve injected fragment that has been there recently // we are assuming here that when user is (even furiously) typing, injected language would not change // and thus we can use its lexer to insert closing braces etc for (DocumentWindow documentWindow : InjectedLanguageUtil.getCachedInjectedDocuments(oldFile)) { if (documentWindow.isValid() && documentWindow.containsRange(offset, offset)) { PsiFile injectedFile = PsiDocumentManager.getInstance(oldFile.getProject()).getPsiFile(documentWindow); final Editor injectedEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(editor, injectedFile); // IDEA-52375 fix: last quote sign should be handled by outer language quote handler final CharSequence charsSequence = editor.getDocument().getCharsSequence(); if (injectedEditor.getCaretModel().getOffset() == injectedEditor.getDocument().getTextLength() && offset < charsSequence.length() && charTyped == charsSequence.charAt(offset)) { return editor; } return injectedEditor; } } return editor; }
@NotNull public static PsiElement getContext(@NotNull PsiFile file, int offset, boolean searchInInjectedFragment) { PsiElement element = null; if (searchInInjectedFragment && !InjectedLanguageManager.getInstance(file.getProject()).isInjectedFragment(file)) { PsiDocumentManager documentManager = PsiDocumentManager.getInstance(file.getProject()); Document document = documentManager.getDocument(file); if (document != null && !documentManager.isCommitted(document)) { LOGGER.error("Trying to access to injected template context on uncommited document, offset = " + offset, AttachmentFactory.createAttachment(file.getVirtualFile())); } else { element = InjectedLanguageUtil.findInjectedElementNoCommit(file, offset); } } if (element == null) { element = PsiUtilCore.getElementAtOffset(file, offset); } return element; }
private void insertLookupString(LookupElement item, final int prefix) { final String lookupString = getCaseCorrectedLookupString(item); final Editor hostEditor = InjectedLanguageUtil.getTopLevelEditor(myEditor); hostEditor.getCaretModel().runForEachCaret(new CaretAction() { @Override public void perform(Caret caret) { EditorModificationUtil.deleteSelectedText(hostEditor); final int caretOffset = hostEditor.getCaretModel().getOffset(); int lookupStart = Math.min(caretOffset, Math.max(caretOffset - prefix, 0)); int len = hostEditor.getDocument().getTextLength(); LOG.assertTrue(lookupStart >= 0 && lookupStart <= len, "ls: " + lookupStart + " caret: " + caretOffset + " prefix:" + prefix + " doc: " + len); LOG.assertTrue(caretOffset >= 0 && caretOffset <= len, "co: " + caretOffset + " doc: " + len); hostEditor.getDocument().replaceString(lookupStart, caretOffset, lookupString); int offset = lookupStart + lookupString.length(); hostEditor.getCaretModel().moveToOffset(offset); hostEditor.getSelectionModel().removeSelection(); } }); myEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); }
@Override public boolean maySaveDocument(@NotNull Document document, boolean isSaveExplicit) { if (ApplicationManager.getApplication().isDisposed() || isSaveExplicit) { return true; } for (Project project : ProjectManager.getInstance().getOpenProjects()) { if (!project.isInitialized() || project.isDisposed()) { continue; } LookupEx lookup = LookupManager.getInstance(project).getActiveLookup(); if (lookup != null) { Editor editor = InjectedLanguageUtil.getTopLevelEditor(lookup.getEditor()); if (editor.getDocument() == document) { return false; } } } return true; }
@Nullable public static Pair<PsiFile,Editor> chooseBetweenHostAndInjected(@NotNull PsiFile hostFile, @NotNull Editor hostEditor, @NotNull PairProcessor<PsiFile, Editor> predicate) { Editor editorToApply = null; PsiFile fileToApply = null; int offset = hostEditor.getCaretModel().getOffset(); PsiFile injectedFile = InjectedLanguageUtil.findInjectedPsiNoCommit(hostFile, offset); if (injectedFile != null) { Editor injectedEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(hostEditor, injectedFile); if (predicate.process(injectedFile, injectedEditor)) { editorToApply = injectedEditor; fileToApply = injectedFile; } } if (editorToApply == null && predicate.process(hostFile, hostEditor)) { editorToApply = hostEditor; fileToApply = hostFile; } if (editorToApply == null) return null; return Pair.create(fileToApply, editorToApply); }
@Override public void caretPositionChanged(CaretEvent e) { if (!available() || myEditor.getSelectionModel().hasSelection()) return; final ViewerTreeStructure treeStructure = (ViewerTreeStructure)myPsiTreeBuilder.getTreeStructure(); final PsiElement rootPsiElement = treeStructure.getRootPsiElement(); if (rootPsiElement == null) return; final PsiElement rootElement = ((ViewerTreeStructure)myPsiTreeBuilder.getTreeStructure()).getRootPsiElement(); int baseOffset = rootPsiElement.getTextRange().getStartOffset(); final int offset = myEditor.getCaretModel().getOffset() + baseOffset; final PsiElement element = InjectedLanguageUtil.findElementAtNoCommit(rootElement.getContainingFile(), offset); if (element != null && myBlockTreeBuilder != null) { TextRange rangeInHostFile = InjectedLanguageManager.getInstance(myProject).injectedToHost(element, element.getTextRange()); selectBlockNode(findBlockNode(rangeInHostFile, true)); } myPsiTreeBuilder.select(element); }
@Override public void selectionChanged(SelectionEvent e) { if (!available() || !myEditor.getSelectionModel().hasSelection()) return; ViewerTreeStructure treeStructure = (ViewerTreeStructure)myPsiTreeBuilder.getTreeStructure(); if (treeStructure == null) return; final PsiElement rootElement = treeStructure.getRootPsiElement(); if (rootElement == null) return; final SelectionModel selection = myEditor.getSelectionModel(); final TextRange textRange = rootElement.getTextRange(); int baseOffset = textRange != null ? textRange.getStartOffset() : 0; final int start = selection.getSelectionStart()+baseOffset; final int end = selection.getSelectionEnd()+baseOffset - 1; final PsiElement element = findCommonParent(InjectedLanguageUtil.findElementAtNoCommit(rootElement.getContainingFile(), start), InjectedLanguageUtil.findElementAtNoCommit(rootElement.getContainingFile(), end)); if (element != null && myBlockTreeBuilder != null) { if (myEditor.getContentComponent().hasFocus()) { TextRange rangeInHostFile = InjectedLanguageManager.getInstance(myProject).injectedToHost(element, element.getTextRange()); selectBlockNode(findBlockNode(rangeInHostFile, true)); } } myPsiTreeBuilder.select(element); }
@Override public boolean containsWhiteSpaceSymbolsOnly(int startOffset, int endOffset) { WhiteSpaceFormattingStrategy strategy = myWhiteSpaceStrategy; if (strategy.check(myDocument.getCharsSequence(), startOffset, endOffset) >= endOffset) { return true; } PsiElement injectedElement = myFile != null ? InjectedLanguageUtil.findElementAtNoCommit(myFile, startOffset) : null; if (injectedElement != null) { Language injectedLanguage = injectedElement.getLanguage(); if (!injectedLanguage.equals(myFile.getLanguage())) { WhiteSpaceFormattingStrategy localStrategy = WhiteSpaceFormattingStrategyFactory.getStrategy(injectedLanguage); if (localStrategy != null) { return localStrategy.check(myDocument.getCharsSequence(), startOffset, endOffset) >= endOffset; } } } return false; }
@NotNull private static Pair<PsiElement, CharTable> doFindWhiteSpaceNode(@NotNull PsiFile file, int offset) { ASTNode astNode = SourceTreeToPsiMap.psiElementToTree(file); if (!(astNode instanceof FileElement)) { return new Pair<PsiElement, CharTable>(null, null); } PsiElement elementAt = InjectedLanguageUtil.findInjectedElementNoCommit(file, offset); final CharTable charTable = ((FileElement)astNode).getCharTable(); if (elementAt == null) { elementAt = findElementInTreeWithFormatterEnabled(file, offset); } if( elementAt == null) { return new Pair<PsiElement, CharTable>(null, charTable); } ASTNode node = elementAt.getNode(); if (node == null || node.getElementType() != TokenType.WHITE_SPACE) { return new Pair<PsiElement, CharTable>(null, charTable); } return Pair.create(elementAt, charTable); }
public static TodoItem[] findAllTodos(final PsiFile psiFile, final PsiTodoSearchHelper helper) { final List<TodoItem> todoItems = new ArrayList<TodoItem>(Arrays.asList(helper.findTodoItems(psiFile))); psiFile.accept(new PsiRecursiveElementWalkingVisitor() { @Override public void visitElement(PsiElement element) { if (element instanceof PsiLanguageInjectionHost) { InjectedLanguageUtil.enumerate(element, new PsiLanguageInjectionHost.InjectedPsiVisitor() { @Override public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) { if (places.size() == 1) { Document document = PsiDocumentManager.getInstance(injectedPsi.getProject()).getCachedDocument(injectedPsi); if (!(document instanceof DocumentWindow)) return; for (TodoItem item : helper.findTodoItems(injectedPsi)) { TextRange rangeInHost = ((DocumentWindow)document).injectedToHost(item.getTextRange()); todoItems.add(new TodoItemImpl(psiFile, rangeInHost.getStartOffset(), rangeInHost.getEndOffset(), item.getPattern())); } } } }); } super.visitElement(element); } }); return todoItems.toArray(new TodoItem[todoItems.size()]); }
@Override public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) { PsiElement element = getElement(dataContext); if (element == null) { element = BaseRefactoringAction.getElementAtCaret(editor, file); } if (ApplicationManager.getApplication().isUnitTestMode()) { final String newName = DEFAULT_NAME.getData(dataContext); if (newName != null) { rename(element, project, element, editor, newName); return; } } editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); final PsiElement nameSuggestionContext = InjectedLanguageUtil.findElementAtNoCommit(file, editor.getCaretModel().getOffset()); invoke(element, project, nameSuggestionContext, editor); }
@Override public void templateFinished(Template template, final boolean brokenOff) { boolean bind = false; try { super.templateFinished(template, brokenOff); if (!brokenOff) { bind = performRefactoring(); } else { performCleanup(); } moveOffsetAfter(!brokenOff); } finally { if (!bind) { try { ((EditorImpl)InjectedLanguageUtil.getTopLevelEditor(myEditor)).stopDumbLater(); } finally { FinishMarkAction.finish(myProject, myEditor, myMarkAction); if (myBeforeRevert != null) { myBeforeRevert.dispose(); } } } } }
@Override public Result preprocessEnter(@NotNull PsiFile file, @NotNull Editor editor, @NotNull Ref<Integer> caretOffset, @NotNull Ref<Integer> caretAdvance, @NotNull DataContext dataContext, EditorActionHandler originalHandler) { int offset = caretOffset.get(); if (editor instanceof EditorWindow) { file = InjectedLanguageManager.getInstance(file.getProject()).getTopLevelFile(file); editor = InjectedLanguageUtil.getTopLevelEditor(editor); offset = editor.getCaretModel().getOffset(); } if (!(file instanceof PyFile)) { return Result.Continue; } // honor dedent (PY-3009) if (BackspaceHandler.isWhitespaceBeforeCaret(editor)) { return Result.DefaultSkipIndent; } return Result.Continue; }
private static boolean isMatchingText(@NotNull PsiFile regexpFile, @NotNull String sampleText) { final String regExp = regexpFile.getText(); PsiLanguageInjectionHost host = InjectedLanguageUtil.findInjectionHost(regexpFile); int flags = 0; if (host != null) { for (RegExpModifierProvider provider : RegExpModifierProvider.EP.allForLanguage(host.getLanguage())) { flags = provider.getFlags(host, regexpFile); if (flags > 0) break; } } try { return Pattern.compile(regExp, flags).matcher(sampleText).matches(); } catch (Exception ignore) {} return false; }
@Override public void invoke(@NotNull Project project, @NotNull PsiFile file, @NotNull PsiElement startElement, @NotNull PsiElement endElement) { final PsiFile psiFile = startElement.getContainingFile(); if (!FileModificationService.getInstance().prepareFileForWrite(psiFile)) return; final TextRange range = startElement.getTextRange(); OpenFileDescriptor descriptor = new OpenFileDescriptor( project, psiFile.getVirtualFile(), range.getStartOffset() + startInElement ); final Editor editor = FileEditorManager.getInstance(project).openTextEditor(descriptor, true); if (editor == null) return; final String xmlCharacter = getXmlCharacter(); String replacement = xmlCharacter.equals("&") ? AMP_ENTITY_REFERENCE : LT_ENTITY_REFERENCE; replacement = startElement.getText().replace(xmlCharacter,replacement); InjectedLanguageUtil.getTopLevelEditor(editor).getDocument().replaceString( range.getStartOffset(), range.getEndOffset(), replacement ); }
@Nullable private static PsiElement getPsiElement(DataContext dataContext, Project project, Editor editor) { PsiElement psiElement = null; if (editor == null) { psiElement = CommonDataKeys.PSI_ELEMENT.getData(dataContext); } else { final PsiFile file = PsiUtilBase.getPsiFileInEditor(editor, project); final Editor injectedEditor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(editor, file); if (injectedEditor != null) { PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(injectedEditor, project); psiElement = psiFile != null ? psiFile.findElementAt(injectedEditor.getCaretModel().getOffset()) : null; } if (file != null && psiElement == null) { psiElement = file.findElementAt(editor.getCaretModel().getOffset()); } } return psiElement; }
private static void invokeImpl(Project project, Editor editor, PsiFile file) { final PsiFile psiFile = InjectedLanguageUtil.findInjectedPsiNoCommit(file, editor.getCaretModel().getOffset()); if (psiFile == null) return; final PsiLanguageInjectionHost host = InjectedLanguageManager.getInstance(project).getInjectionHost(psiFile); if (host == null) return; final LanguageInjectionSupport support = psiFile.getUserData(LanguageInjectionSupport.SETTINGS_EDITOR); if (support == null) return; try { if (!support.editInjectionInPlace(host)) { ShowSettingsUtil.getInstance().editConfigurable(project, new InjectionsSettingsUI(project, Configuration.getProjectInstance(project))); } } finally { FileContentUtil.reparseFiles(project, Collections.<VirtualFile>emptyList(), true); } }
@NotNull public static PsiFile[] getFiles(XmlAttribute attribute) { final XmlAttributeValue value = attribute.getValueElement(); if (value != null) { final List<PsiFile> files = new SmartList<PsiFile>(); InjectedLanguageUtil.enumerate(value, new PsiLanguageInjectionHost.InjectedPsiVisitor() { public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) { if (injectedPsi instanceof XPathFile) { files.add(injectedPsi); } } }); return files.isEmpty() ? PsiFile.EMPTY_ARRAY : PsiUtilCore.toPsiFileArray(files); } return PsiFile.EMPTY_ARRAY; }
public ShaderLabCGCompletionContributor() { extend(CompletionType.BASIC, StandardPatterns.psiElement().withLanguage(CGLanguage.INSTANCE), new CompletionProvider() { @RequiredReadAction @Override public void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @NotNull final CompletionResultSet result) { Place shreds = InjectedLanguageUtil.getShreds(parameters.getOriginalFile()); for(PsiLanguageInjectionHost.Shred shred : shreds) { PsiLanguageInjectionHost host = shred.getHost(); if(host instanceof ShaderCGScript) { ShaderLabFile containingFile = (ShaderLabFile) host.getContainingFile(); ShaderReference.consumeProperties(containingFile, result::addElement); } } } }); }
@Override public Object getData(String dataId) { if (PlatformDataKeys.EDITOR.is(dataId)) { return myEditor; } if (dataId.equals(AnActionEvent.injectedId(PlatformDataKeys.EDITOR.getName()))) { return InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(getEditor(), getFile()); } if (LangDataKeys.PSI_FILE.is(dataId)) { return myFile; } if (dataId.equals(AnActionEvent.injectedId(LangDataKeys.PSI_FILE.getName()))) { Editor editor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(getEditor(), getFile()); return editor instanceof EditorWindow ? ((EditorWindow)editor).getInjectedFile() : getFile(); } return super.getData(dataId); }
private static boolean shouldSkipAutoPopup(Editor editor, PsiFile psiFile) { int offset = editor.getCaretModel().getOffset(); int psiOffset = Math.max(0, offset - 1); PsiElement elementAt = InjectedLanguageUtil.findInjectedElementNoCommit(psiFile, psiOffset); if (elementAt == null) { elementAt = psiFile.findElementAt(psiOffset); } if (elementAt == null) return true; Language language = PsiUtilBase.findLanguageFromElement(elementAt); for (CompletionConfidence confidence : CompletionConfidenceEP.forLanguage(language)) { final ThreeState result = confidence.shouldSkipAutopopup(elementAt, psiFile, offset); if (result != ThreeState.UNSURE) { LOG.debug(confidence + " has returned shouldSkipAutopopup=" + result); return result == ThreeState.YES; } } return false; }
private static CompletionContext createCompletionContext(PsiFile hostCopy, int hostStartOffset, OffsetMap hostMap, PsiFile originalFile) { CompletionAssertions.assertHostInfo(hostCopy, hostMap); InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(hostCopy.getProject()); CompletionContext context; PsiFile injected = InjectedLanguageUtil.findInjectedPsiNoCommit(hostCopy, hostStartOffset); if (injected != null) { if (injected instanceof PsiFileImpl && injectedLanguageManager.isInjectedFragment(originalFile)) { ((PsiFileImpl)injected).setOriginalFile(originalFile); } DocumentWindow documentWindow = InjectedLanguageUtil.getDocumentWindow(injected); CompletionAssertions.assertInjectedOffsets(hostStartOffset, injectedLanguageManager, injected, documentWindow); context = new CompletionContext(injected, translateOffsetMapToInjected(hostMap, documentWindow)); } else { context = new CompletionContext(hostCopy, hostMap); } CompletionAssertions.assertFinalOffsets(originalFile, context, injected); return context; }
@NotNull private static PsiFile getInjectedFileIfAny(@NotNull final Editor editor, @NotNull final Project project, int offset, @NotNull PsiFile psiFile, @NotNull final Alarm alarm) { Document document = editor.getDocument(); // when document is committed, try to highlight braces in injected lang - it's fast if (!PsiDocumentManager.getInstance(project).isUncommited(document)) { final PsiElement injectedElement = InjectedLanguageUtil.findInjectedElementNoCommit(psiFile, offset); if (injectedElement != null /*&& !(injectedElement instanceof PsiWhiteSpace)*/) { final PsiFile injected = injectedElement.getContainingFile(); if (injected != null) { return injected; } } } else { PsiDocumentManager.getInstance(project).performForCommittedDocument(document, new Runnable() { @Override public void run() { if (!project.isDisposed() && !editor.isDisposed()) { BraceHighlighter.updateBraces(editor, alarm); } } }); } return psiFile; }
@NotNull static Editor injectedEditorIfCharTypedIsSignificant(final char charTyped, Editor editor, PsiFile oldFile) { int offset = editor.getCaretModel().getOffset(); // even for uncommitted document try to retrieve injected fragment that has been there recently // we are assuming here that when user is (even furiously) typing, injected language would not change // and thus we can use its lexer to insert closing braces etc for (DocumentWindow documentWindow : InjectedLanguageUtil.getCachedInjectedDocuments(oldFile)) { if (documentWindow.isValid() && documentWindow.containsRange(offset, offset)) { PsiFile injectedFile = PsiDocumentManager.getInstance(oldFile.getProject()).getPsiFile(documentWindow); final Editor injectedEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(editor, injectedFile); // IDEA-52375 fix: last quote sign should be handled by outer language quote handler final CharSequence charsSequence = editor.getDocument().getCharsSequence(); if (injectedEditor.getCaretModel().getOffset() == injectedEditor.getDocument().getTextLength() && offset < charsSequence.length() && charTyped == charsSequence.charAt(offset)) { return editor; } return injectedEditor; } } return editor; }
@Nullable private static PsiElement getPsiElementAt(Point point, Editor editor) { if (editor.isDisposed()) { return null; } Project project = editor.getProject(); if (project == null || project.isDisposed()) { return null; } PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); if (psiFile == null || psiFile instanceof PsiCompiledElement || !psiFile.isValid()) { return null; } return InjectedLanguageUtil.findElementAtNoCommit(psiFile, editor.logicalPositionToOffset(editor.xyToLogicalPosition(point))); }
@Override public void selectionChanged(SelectionEvent e) { if (!available() || !myEditor.getSelectionModel().hasSelection()) return; ViewerTreeStructure treeStructure = (ViewerTreeStructure)myPsiTreeBuilder.getTreeStructure(); if (treeStructure == null) return; final PsiElement rootElement = treeStructure.getRootPsiElement(); if (rootElement == null) return; final SelectionModel selection = myEditor.getSelectionModel(); final TextRange textRange = rootElement.getTextRange(); int baseOffset = textRange != null ? textRange.getStartOffset() : 0; final int start = selection.getSelectionStart()+baseOffset; final int end = selection.getSelectionEnd()+baseOffset - 1; final PsiElement element = findCommonParent(InjectedLanguageUtil.findElementAtNoCommit(rootElement.getContainingFile(), start), InjectedLanguageUtil.findElementAtNoCommit(rootElement.getContainingFile(), end)); if (element != null && myBlockTreeBuilder != null) { if (myEditor.getContentComponent().hasFocus()) { TextRange rangeInHostFile = InjectedLanguageManager.getInstance(myProject).injectedToHost(element, element.getTextRange()); selectBlockNode(findBlockNode(rangeInHostFile, true)); updateIntersectHighlighter(myHighlighter.getStartOffset(), myHighlighter.getEndOffset()); } } myPsiTreeBuilder.select(element); }
@NotNull private static Pair<PsiElement, CharTable> doFindWhiteSpaceNode(@NotNull PsiFile file, int offset) { ASTNode astNode = SourceTreeToPsiMap.psiElementToTree(file); if (!(astNode instanceof FileElement)) { return new Pair<PsiElement, CharTable>(null, null); } PsiElement elementAt = InjectedLanguageUtil.findInjectedElementNoCommit(file, offset); final CharTable charTable = ((FileElement)astNode).getCharTable(); if (elementAt == null) { elementAt = findElementInTreeWithFormatterEnabled(file, offset); } if( elementAt == null) { return new Pair<PsiElement, CharTable>(null, charTable); } ASTNode node = elementAt.getNode(); if (node == null || node.getElementType() != TokenType.WHITE_SPACE) { return new Pair<PsiElement, CharTable>(null, charTable); } return new Pair<PsiElement, CharTable>(elementAt, charTable); }