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; }
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { final int offset = editor.getCaretModel().getOffset(); final PsiFile psiFile = InjectedLanguageUtil.findInjectedPsiNoCommit(file, offset); if (psiFile == null) return false; final LanguageInjectionSupport support = psiFile.getUserData(LanguageInjectionSupport.INJECTOR_SUPPORT); return support != null; }
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.INJECTOR_SUPPORT); if (support == null) return; try { if (!support.removeInjectionInPlace(host)) { defaultFunctionalityWorked(host); } } finally { FileContentUtil.reparseFiles(project, Collections.<VirtualFile>emptyList(), true); } }
@Nullable public static Pair<PsiFile, Editor> chooseBetweenHostAndInjected( PsiFile hostFile, Editor hostEditor, 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); }
private static TextRange preprocess(@NotNull final ASTNode node, @NotNull TextRange range) { TextRange result = range; PsiElement psi = node.getPsi(); if (!psi.isValid()) { for (PreFormatProcessor processor : Extensions.getExtensions(PreFormatProcessor.EP_NAME)) { result = processor.process(node, result); } return result; } PsiFile file = psi.getContainingFile(); // We use a set here because we encountered a situation when more than one PSI leaf points to // the same injected fragment // (at least for sql injected into sql). final LinkedHashSet<TextRange> injectedFileRangesSet = ContainerUtilRt.newLinkedHashSet(); if (!psi.getProject().isDefault()) { List<DocumentWindow> injectedDocuments = InjectedLanguageUtil.getCachedInjectedDocuments(file); if (!injectedDocuments.isEmpty()) { for (DocumentWindow injectedDocument : injectedDocuments) { injectedFileRangesSet.add( TextRange.from(injectedDocument.injectedToHost(0), injectedDocument.getTextLength())); } } else { Collection<PsiLanguageInjectionHost> injectionHosts = collectInjectionHosts(file, range); PsiLanguageInjectionHost.InjectedPsiVisitor visitor = new PsiLanguageInjectionHost.InjectedPsiVisitor() { @Override public void visit( @NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) { for (PsiLanguageInjectionHost.Shred place : places) { Segment rangeMarker = place.getHostRangeMarker(); injectedFileRangesSet.add( TextRange.create(rangeMarker.getStartOffset(), rangeMarker.getEndOffset())); } } }; for (PsiLanguageInjectionHost host : injectionHosts) { InjectedLanguageUtil.enumerate(host, visitor); } } } if (!injectedFileRangesSet.isEmpty()) { List<TextRange> ranges = ContainerUtilRt.newArrayList(injectedFileRangesSet); Collections.reverse(ranges); for (TextRange injectedFileRange : ranges) { int startHostOffset = injectedFileRange.getStartOffset(); int endHostOffset = injectedFileRange.getEndOffset(); if (startHostOffset >= range.getStartOffset() && endHostOffset <= range.getEndOffset()) { PsiFile injected = InjectedLanguageUtil.findInjectedPsiNoCommit(file, startHostOffset); if (injected != null) { int startInjectedOffset = range.getStartOffset() > startHostOffset ? startHostOffset - range.getStartOffset() : 0; int endInjectedOffset = injected.getTextLength(); if (range.getEndOffset() < endHostOffset) { endInjectedOffset -= endHostOffset - range.getEndOffset(); } final TextRange initialInjectedRange = TextRange.create(startInjectedOffset, endInjectedOffset); TextRange injectedRange = initialInjectedRange; for (PreFormatProcessor processor : Extensions.getExtensions(PreFormatProcessor.EP_NAME)) { injectedRange = processor.process(injected.getNode(), injectedRange); } // Allow only range expansion (not reduction) for injected context. if ((initialInjectedRange.getStartOffset() > injectedRange.getStartOffset() && initialInjectedRange.getStartOffset() > 0) || (initialInjectedRange.getEndOffset() < injectedRange.getEndOffset() && initialInjectedRange.getEndOffset() < injected.getTextLength())) { range = TextRange.create( range.getStartOffset() + injectedRange.getStartOffset() - initialInjectedRange.getStartOffset(), range.getEndOffset() + initialInjectedRange.getEndOffset() - injectedRange.getEndOffset()); } } } } } for (PreFormatProcessor processor : Extensions.getExtensions(PreFormatProcessor.EP_NAME)) { result = processor.process(node, result); } return result; }