private void highlightInjectedSyntax( @NotNull PsiFile injectedPsi, @NotNull HighlightInfoHolder holder) { List<Trinity<IElementType, SmartPsiElementPointer<PsiLanguageInjectionHost>, TextRange>> tokens = InjectedLanguageUtil.getHighlightTokens(injectedPsi); if (tokens == null) return; final Language injectedLanguage = injectedPsi.getLanguage(); Project project = injectedPsi.getProject(); SyntaxHighlighter syntaxHighlighter = SyntaxHighlighterFactory.getSyntaxHighlighter( injectedLanguage, project, injectedPsi.getVirtualFile()); final TextAttributes defaultAttrs = myGlobalScheme.getAttributes(HighlighterColors.TEXT); for (Trinity<IElementType, SmartPsiElementPointer<PsiLanguageInjectionHost>, TextRange> token : tokens) { ProgressManager.checkCanceled(); IElementType tokenType = token.getFirst(); PsiLanguageInjectionHost injectionHost = token.getSecond().getElement(); if (injectionHost == null) continue; TextRange textRange = token.getThird(); TextAttributesKey[] keys = syntaxHighlighter.getTokenHighlights(tokenType); if (textRange.getLength() == 0) continue; TextRange annRange = textRange.shiftRight(injectionHost.getTextRange().getStartOffset()); // force attribute colors to override host' ones TextAttributes attributes = null; for (TextAttributesKey key : keys) { TextAttributes attrs2 = myGlobalScheme.getAttributes(key); if (attrs2 != null) { attributes = attributes == null ? attrs2 : TextAttributes.merge(attributes, attrs2); } } TextAttributes forcedAttributes; if (attributes == null || attributes.isEmpty() || attributes.equals(defaultAttrs)) { forcedAttributes = TextAttributes.ERASE_MARKER; } else { HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.INJECTED_LANGUAGE_FRAGMENT) .range(annRange) .textAttributes(TextAttributes.ERASE_MARKER) .createUnconditionally(); holder.add(info); forcedAttributes = new TextAttributes( attributes.getForegroundColor(), attributes.getBackgroundColor(), attributes.getEffectColor(), attributes.getEffectType(), attributes.getFontType()); } HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.INJECTED_LANGUAGE_FRAGMENT) .range(annRange) .textAttributes(forcedAttributes) .createUnconditionally(); holder.add(info); } }
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); }
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 static boolean hasInjections(@NotNull PsiLanguageInjectionHost host) { if (!host.isPhysical()) return false; final Ref<Boolean> result = Ref.create(false); enumerate( host, new PsiLanguageInjectionHost.InjectedPsiVisitor() { @Override public void visit( @NotNull final PsiFile injectedPsi, @NotNull final List<PsiLanguageInjectionHost.Shred> places) { result.set(true); } }); return result.get().booleanValue(); }
private boolean addInjectedPsiHighlights( @NotNull PsiFile injectedPsi, TextAttributes injectedAttributes, @NotNull Collection<HighlightInfo> outInfos, @NotNull ProgressIndicator progress, @NotNull InjectedLanguageManager injectedLanguageManager) { DocumentWindow documentWindow = (DocumentWindow) PsiDocumentManager.getInstance(myProject).getCachedDocument(injectedPsi); if (documentWindow == null) return true; Place places = InjectedLanguageUtil.getShreds(injectedPsi); for (PsiLanguageInjectionHost.Shred place : places) { PsiLanguageInjectionHost host = place.getHost(); if (host == null) continue; TextRange textRange = place.getRangeInsideHost().shiftRight(host.getTextRange().getStartOffset()); if (textRange.isEmpty()) continue; String desc = injectedPsi.getLanguage().getDisplayName() + ": " + injectedPsi.getText(); HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(HighlightInfoType.INJECTED_LANGUAGE_BACKGROUND) .range(textRange); if (injectedAttributes != null && InjectedLanguageUtil.isHighlightInjectionBackground(host)) { builder.textAttributes(injectedAttributes); } builder.unescapedToolTip(desc); HighlightInfo info = builder.createUnconditionally(); info.setFromInjection(true); outInfos.add(info); } HighlightInfoHolder holder = createInfoHolder(injectedPsi); runHighlightVisitorsForInjected(injectedPsi, holder, progress); for (int i = 0; i < holder.size(); i++) { HighlightInfo info = holder.get(i); final int startOffset = documentWindow.injectedToHost(info.startOffset); final TextRange fixedTextRange = getFixedTextRange(documentWindow, startOffset); addPatchedInfos( info, injectedPsi, documentWindow, injectedLanguageManager, fixedTextRange, outInfos); } int injectedStart = holder.size(); highlightInjectedSyntax(injectedPsi, holder); for (int i = injectedStart; i < holder.size(); i++) { HighlightInfo info = holder.get(i); final int startOffset = info.startOffset; final TextRange fixedTextRange = getFixedTextRange(documentWindow, startOffset); if (fixedTextRange == null) { info.setFromInjection(true); outInfos.add(info); } else { HighlightInfo patched = new HighlightInfo( info.forcedTextAttributes, info.forcedTextAttributesKey, info.type, fixedTextRange.getStartOffset(), fixedTextRange.getEndOffset(), info.getDescription(), info.getToolTip(), info.type.getSeverity(null), info.isAfterEndOfLine(), null, false, 0, info.getProblemGroup(), info.getGutterIconRenderer()); patched.setFromInjection(true); outInfos.add(patched); } } if (!isDumbMode()) { List<HighlightInfo> todos = new ArrayList<HighlightInfo>(); highlightTodos( injectedPsi, injectedPsi.getText(), 0, injectedPsi.getTextLength(), progress, myPriorityRange, todos, todos); for (HighlightInfo info : todos) { addPatchedInfos(info, injectedPsi, documentWindow, injectedLanguageManager, null, outInfos); } } advanceProgress(1); return true; }