Example #1
0
  public ControllerAction(PhpClass phpClass, int startOffset) {
    this.currentControllerName = phpClass.getName();
    Pattern pattern = Pattern.compile(".*?this->render\\((.*?)\\).*?");

    for (Method method : phpClass.getOwnMethods()) {
      TextRange textRange = method.getTextRange();
      final String methodName = method.getName();
      Matcher matcher = pattern.matcher(method.getText());
      List<String> renderViews =
          new ArrayList<String>() {
            {
              add(methodName);
            }
          };

      while (matcher.find()) {
        renderViews.add(matcher.group(1).replace("'", ""));
      }

      if (textRange.getStartOffset() <= startOffset && startOffset <= textRange.getEndOffset()) {
        this.currentActionName = methodName;
      }

      // Method name will be unique. Because PHP doesn't have [overroad] like java.
      actions.put(methodName, new Function(method.getName(), textRange, renderViews));
    }
  }
Example #2
0
  private HighlightersSet installHighlighterSet(Info info, Editor editor) {
    final JComponent internalComponent = editor.getContentComponent();
    internalComponent.addKeyListener(myEditorKeyListener);
    editor.getScrollingModel().addVisibleAreaListener(myVisibleAreaListener);
    final Cursor cursor = internalComponent.getCursor();
    internalComponent.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
    myFileEditorManager.addFileEditorManagerListener(myFileEditorManagerListener);

    List<RangeHighlighter> highlighters = new ArrayList<RangeHighlighter>();
    TextAttributes attributes =
        myEditorColorsManager
            .getGlobalScheme()
            .getAttributes(EditorColors.REFERENCE_HYPERLINK_COLOR);
    for (TextRange range : info.getRanges()) {
      TextAttributes attr = patchAttributesColor(attributes, range, editor);
      final RangeHighlighter highlighter =
          editor
              .getMarkupModel()
              .addRangeHighlighter(
                  range.getStartOffset(),
                  range.getEndOffset(),
                  HighlighterLayer.SELECTION + 1,
                  attr,
                  HighlighterTargetArea.EXACT_RANGE);
      highlighters.add(highlighter);
    }

    return new HighlightersSet(highlighters, editor, cursor, info);
  }
  public GrLiteralImpl handleContentChange(GrLiteral expr, TextRange range, String newContent)
      throws IncorrectOperationException {
    if (!(expr.getValue() instanceof String))
      throw new IncorrectOperationException("cannot handle content change");

    LOG.assertTrue(expr instanceof GrLiteralImpl);

    String oldText = expr.getText();
    final String quote = GrStringUtil.getStartQuote(oldText);

    if (quote.startsWith("'")) {
      newContent = GrStringUtil.escapeSymbolsForString(newContent, !quote.equals("'''"), false);
    } else if (quote.startsWith("\"")) {
      newContent = GrStringUtil.escapeSymbolsForGString(newContent, !quote.equals("\"\"\""), true);
    } else if ("/".equals(quote)) {
      newContent = GrStringUtil.escapeSymbolsForSlashyStrings(newContent);
    } else if ("$/".equals(quote)) {
      newContent = GrStringUtil.escapeSymbolsForDollarSlashyStrings(newContent);
    }

    String newText =
        oldText.substring(0, range.getStartOffset())
            + newContent
            + oldText.substring(range.getEndOffset());
    return ((GrLiteralImpl) expr).updateText(newText);
  }
  @Nullable
  private Navigatable getSelectedNavigatable(
      final CommonProblemDescriptor descriptor, final PsiElement psiElement) {
    if (descriptor instanceof ProblemDescriptorBase) {
      Navigatable navigatable = ((ProblemDescriptorBase) descriptor).getNavigatable();
      if (navigatable != null) {
        return navigatable;
      }
    }
    if (psiElement == null || !psiElement.isValid()) return null;
    PsiFile containingFile = psiElement.getContainingFile();
    VirtualFile virtualFile = containingFile == null ? null : containingFile.getVirtualFile();

    if (virtualFile != null) {
      int startOffset = psiElement.getTextOffset();
      if (descriptor instanceof ProblemDescriptorBase) {
        final TextRange textRange =
            ((ProblemDescriptorBase) descriptor).getTextRangeForNavigation();
        if (textRange != null) {
          if (virtualFile instanceof VirtualFileWindow) {
            virtualFile = ((VirtualFileWindow) virtualFile).getDelegate();
          }
          startOffset = textRange.getStartOffset();
        }
      }
      return new OpenFileDescriptor(myProject, virtualFile, startOffset);
    }
    return null;
  }
Example #5
0
 @NotNull
 private static List<DiagnosticDescriptor> getSortedDiagnosticDescriptors(
     @NotNull Collection<Diagnostic> diagnostics) {
   LinkedListMultimap<TextRange, Diagnostic> diagnosticsGroupedByRanges =
       LinkedListMultimap.create();
   for (Diagnostic diagnostic : diagnostics) {
     if (!diagnostic.isValid()) continue;
     for (TextRange textRange : diagnostic.getTextRanges()) {
       diagnosticsGroupedByRanges.put(textRange, diagnostic);
     }
   }
   List<DiagnosticDescriptor> diagnosticDescriptors = Lists.newArrayList();
   for (TextRange range : diagnosticsGroupedByRanges.keySet()) {
     diagnosticDescriptors.add(
         new DiagnosticDescriptor(
             range.getStartOffset(), range.getEndOffset(), diagnosticsGroupedByRanges.get(range)));
   }
   Collections.sort(
       diagnosticDescriptors,
       new Comparator<DiagnosticDescriptor>() {
         @Override
         public int compare(@NotNull DiagnosticDescriptor d1, @NotNull DiagnosticDescriptor d2) {
           // Start early -- go first; start at the same offset, the one who end later is the
           // outer, i.e. goes first
           return (d1.start != d2.start) ? d1.start - d2.start : d2.end - d1.end;
         }
       });
   return diagnosticDescriptors;
 }
  public static FileReferenceSet createSet(
      PsiElement element,
      final boolean soft,
      boolean endingSlashNotAllowed,
      final boolean urlEncoded) {

    String text;
    int offset;

    final ElementManipulator<PsiElement> manipulator = ElementManipulators.getManipulator(element);
    assert manipulator != null;
    final TextRange range = manipulator.getRangeInElement(element);
    offset = range.getStartOffset();
    text = range.substring(element.getText());
    for (final FileReferenceHelper helper : FileReferenceHelperRegistrar.getHelpers()) {
      text = helper.trimUrl(text);
    }

    return new FileReferenceSet(text, element, offset, null, true, endingSlashNotAllowed) {
      @Override
      protected boolean isUrlEncoded() {
        return urlEncoded;
      }

      @Override
      protected boolean isSoft() {
        return soft;
      }
    };
  }
 @Override
 @Deprecated
 @Nullable
 public TextRange intersectWithEditable(@NotNull TextRange rangeToEdit) {
   int startOffset = -1;
   int endOffset = -1;
   synchronized (myLock) {
     int offset = 0;
     for (PsiLanguageInjectionHost.Shred shred : myShreds) {
       Segment hostRange = shred.getHostRangeMarker();
       if (hostRange == null) continue;
       offset += shred.getPrefix().length();
       int length = hostRange.getEndOffset() - hostRange.getStartOffset();
       TextRange intersection =
           new ProperTextRange(offset, offset + length).intersection(rangeToEdit);
       if (intersection != null) {
         if (startOffset == -1) {
           startOffset = intersection.getStartOffset();
         }
         endOffset = intersection.getEndOffset();
       }
       offset += length;
       offset += shred.getSuffix().length();
     }
   }
   if (startOffset == -1) return null;
   return new ProperTextRange(startOffset, endOffset);
 }
  @Override
  public void addOccurrenceHighlights(
      @NotNull Editor editor,
      @NotNull PsiElement[] elements,
      @NotNull TextAttributes attributes,
      boolean hideByTextChange,
      Collection<RangeHighlighter> outHighlighters) {
    if (elements.length == 0) return;
    int flags = HIDE_BY_ESCAPE;
    if (hideByTextChange) {
      flags |= HIDE_BY_TEXT_CHANGE;
    }

    Color scrollmarkColor = getScrollMarkColor(attributes);
    if (editor instanceof EditorWindow) {
      editor = ((EditorWindow) editor).getDelegate();
    }

    for (PsiElement element : elements) {
      TextRange range = element.getTextRange();
      range = InjectedLanguageManager.getInstance(myProject).injectedToHost(element, range);
      addOccurrenceHighlight(
          editor,
          trimOffsetToDocumentSize(editor, range.getStartOffset()),
          trimOffsetToDocumentSize(editor, range.getEndOffset()),
          attributes,
          flags,
          outHighlighters,
          scrollmarkColor);
    }
  }
 /**
  * @deprecated To be removed in idea 13. Use {@link
  *     HighlightInfo#newHighlightInfo(HighlightInfoType)} instead.
  */
 @Deprecated
 @Nullable
 public static HighlightInfo createHighlightInfo(
     @NotNull HighlightInfoType type, @NotNull TextRange textRange, @Nullable String description) {
   return createHighlightInfo(
       type, textRange.getStartOffset(), textRange.getEndOffset(), description);
 }
 /** Patches attributes to be visible under debugger active line */
 @SuppressWarnings("UseJBColor")
 public static TextAttributes patchAttributesColor(
     TextAttributes attributes, @NotNull TextRange range, @NotNull Editor editor) {
   if (attributes.getForegroundColor() == null && attributes.getEffectColor() == null)
     return attributes;
   MarkupModel model =
       DocumentMarkupModel.forDocument(editor.getDocument(), editor.getProject(), false);
   if (model != null) {
     if (!((MarkupModelEx) model)
         .processRangeHighlightersOverlappingWith(
             range.getStartOffset(),
             range.getEndOffset(),
             highlighter -> {
               if (highlighter.isValid()
                   && highlighter.getTargetArea() == HighlighterTargetArea.LINES_IN_RANGE) {
                 TextAttributes textAttributes = highlighter.getTextAttributes();
                 if (textAttributes != null) {
                   Color color = textAttributes.getBackgroundColor();
                   return !(color != null
                       && color.getBlue() > 128
                       && color.getRed() < 128
                       && color.getGreen() < 128);
                 }
               }
               return true;
             })) {
       TextAttributes clone = attributes.clone();
       clone.setForegroundColor(Color.orange);
       clone.setEffectColor(Color.orange);
       return clone;
     }
   }
   return attributes;
 }
 public TextRange surroundExpression(
     final Project project, final Editor editor, PsiExpression expr)
     throws IncorrectOperationException {
   assert expr.isValid();
   PsiType[] types = GuessManager.getInstance(project).guessTypeToCast(expr);
   final boolean parenthesesNeeded =
       expr instanceof PsiPolyadicExpression
           || expr instanceof PsiConditionalExpression
           || expr instanceof PsiAssignmentExpression;
   String exprText = parenthesesNeeded ? "(" + expr.getText() + ")" : expr.getText();
   final Template template = generateTemplate(project, exprText, types);
   TextRange range;
   if (expr.isPhysical()) {
     range = expr.getTextRange();
   } else {
     final RangeMarker rangeMarker = expr.getUserData(ElementToWorkOn.TEXT_RANGE);
     if (rangeMarker == null) return null;
     range = new TextRange(rangeMarker.getStartOffset(), rangeMarker.getEndOffset());
   }
   editor.getDocument().deleteString(range.getStartOffset(), range.getEndOffset());
   editor.getCaretModel().moveToOffset(range.getStartOffset());
   editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
   TemplateManager.getInstance(project).startTemplate(editor, template);
   return null;
 }
  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);
  }
Example #13
0
  public static TextRange textRangeToInject(PsiLanguageInjectionHost host) {
    ASTNode[] children = ((ASTNode) host).getChildren(null);
    TextRange insideQuotes = new ProperTextRange(0, host.getTextLength());

    if (children.length > 1
        && children[0].getElementType() == XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER) {
      insideQuotes =
          new ProperTextRange(
              children[1].getTextRange().getStartOffset() - host.getTextRange().getStartOffset(),
              insideQuotes.getEndOffset());
    }
    if (children.length > 1
        && children[children.length - 1].getElementType()
            == XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER) {
      insideQuotes =
          new ProperTextRange(
              insideQuotes.getStartOffset(),
              children[children.length - 2].getTextRange().getEndOffset()
                  - host.getTextRange().getStartOffset());
    }
    if (host instanceof PsiLiteralExpression) {
      insideQuotes = new ProperTextRange(1, host.getTextLength() - 1);
    }
    return insideQuotes;
  }
 @Nullable
 private PyType getImplicitlyResolvedType(
     @NotNull List<Token<PyElementType>> tokens,
     @NotNull TypeEvalContext context,
     @NotNull Map<TextRange, PyType> types,
     @NotNull Map<PyType, TextRange> fullRanges,
     TextRange firstRange) {
   PyType type = null;
   QualifiedName qName = null;
   while (!tokens.isEmpty()) {
     final Token<PyElementType> token = tokens.get(0);
     final String name = token.getText().toString();
     qName = qName != null ? qName.append(name) : QualifiedName.fromComponents(name);
     PsiElement module =
         new QualifiedNameResolverImpl(qName).fromElement(myAnchor).firstResult();
     if (module == null) {
       break;
     }
     if (module instanceof PsiDirectory) {
       module = PyUtil.getPackageElement((PsiDirectory) module, myAnchor);
     }
     if (module instanceof PyTypedElement) {
       final PyType moduleType = context.getType((PyTypedElement) module);
       if (moduleType != null) {
         type = moduleType;
         types.put(token.getRange(), type);
         fullRanges.put(
             type,
             TextRange.create(firstRange.getStartOffset(), token.getRange().getEndOffset()));
       }
     }
     tokens.remove(0);
   }
   return type;
 }
 @Override
 public int compare(TextRange range1, TextRange range2) {
   int startOffsetDiff = range1.getStartOffset() - range2.getStartOffset();
   return startOffsetDiff != 0
       ? startOffsetDiff
       : range1.getEndOffset() - range2.getEndOffset();
 }
  private static Condition<PsiElement> findFieldUsages(
      final PsiField psiField,
      final List<UsageInfo> usages,
      final PsiElement[] allElementsToDelete) {
    final Condition<PsiElement> isInsideDeleted = getUsageInsideDeletedFilter(allElementsToDelete);
    ReferencesSearch.search(psiField)
        .forEach(
            reference -> {
              if (!isInsideDeleted.value(reference.getElement())) {
                final PsiElement element = reference.getElement();
                final PsiElement parent = element.getParent();
                if (parent instanceof PsiAssignmentExpression
                    && element == ((PsiAssignmentExpression) parent).getLExpression()) {
                  usages.add(
                      new SafeDeleteFieldWriteReference(
                          (PsiAssignmentExpression) parent, psiField));
                } else {
                  TextRange range = reference.getRangeInElement();
                  usages.add(
                      new SafeDeleteReferenceJavaDeleteUsageInfo(
                          reference.getElement(),
                          psiField,
                          range.getStartOffset(),
                          range.getEndOffset(),
                          false,
                          PsiTreeUtil.getParentOfType(element, PsiImportStaticStatement.class)
                              != null));
                }
              }

              return true;
            });

    return isInsideDeleted;
  }
  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);
  }
  @Override
  public void checkFile(
      @NotNull PsiFile originalFile,
      @NotNull final InspectionManager manager,
      @NotNull ProblemsHolder problemsHolder,
      @NotNull final GlobalInspectionContext globalContext,
      @NotNull final ProblemDescriptionsProcessor problemDescriptionsProcessor) {
    for (Pair<PsiFile, HighlightInfo> pair :
        runGeneralHighlighting(originalFile, highlightErrorElements, runAnnotators)) {
      PsiFile file = pair.first;
      HighlightInfo info = pair.second;
      TextRange range = new TextRange(info.startOffset, info.endOffset);
      PsiElement element = file.findElementAt(info.startOffset);

      while (element != null && !element.getTextRange().contains(range)) {
        element = element.getParent();
      }

      if (element == null) {
        element = file;
      }

      GlobalInspectionUtil.createProblem(
          element,
          info,
          range.shiftRight(-element.getNode().getStartOffset()),
          info.getProblemGroup(),
          manager,
          problemDescriptionsProcessor,
          globalContext);
    }
  }
  @Nullable
  private static PsiElement findParent(
      int syncStartOffset, int syncEndOffset, @NotNull AnchorTypeInfo type, PsiElement anchor) {
    TextRange range = anchor.getTextRange();

    if (range.getStartOffset() != syncStartOffset) return null;
    while (range.getEndOffset() < syncEndOffset) {
      anchor = anchor.getParent();
      if (anchor == null || anchor.getTextRange() == null) {
        return null;
      }
      range = anchor.getTextRange();
    }

    while (range.getEndOffset() == syncEndOffset) {
      if (type.isAcceptable(anchor)) {
        return anchor;
      }
      anchor = anchor.getParent();
      if (anchor == null || anchor.getTextRange() == null) break;
      range = anchor.getTextRange();
    }

    return null;
  }
Example #20
0
  public TextRange getRangeInElement() {
    if (isSingleWord()) {
      return TextRange.from(0, getReferencedName().length());
    }

    return TextRange.from(1, getReferencedName().length()); // fixme make sure it has the end } ?
  }
  protected void invokeImpl(final PsiClass targetClass) {
    final Project project = myConstructorCall.getProject();
    PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory();

    try {
      PsiMethod constructor = (PsiMethod) targetClass.add(elementFactory.createConstructor());

      final PsiFile file = targetClass.getContainingFile();
      TemplateBuilderImpl templateBuilder = new TemplateBuilderImpl(constructor);
      CreateFromUsageUtils.setupMethodParameters(
          constructor,
          templateBuilder,
          myConstructorCall.getArgumentList(),
          getTargetSubstitutor(myConstructorCall));
      final PsiMethod superConstructor =
          CreateClassFromNewFix.setupSuperCall(targetClass, constructor, templateBuilder);

      constructor = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(constructor);
      Template template = templateBuilder.buildTemplate();
      if (targetClass == null) return;
      final Editor editor = positionCursor(project, targetClass.getContainingFile(), targetClass);
      final TextRange textRange = constructor.getTextRange();
      editor.getDocument().deleteString(textRange.getStartOffset(), textRange.getEndOffset());
      editor.getCaretModel().moveToOffset(textRange.getStartOffset());

      startTemplate(
          editor,
          template,
          project,
          new TemplateEditingAdapter() {
            public void templateFinished(Template template, boolean brokenOff) {
              ApplicationManager.getApplication()
                  .runWriteAction(
                      new Runnable() {
                        public void run() {
                          try {
                            PsiDocumentManager.getInstance(project)
                                .commitDocument(editor.getDocument());
                            final int offset = editor.getCaretModel().getOffset();
                            PsiMethod constructor =
                                PsiTreeUtil.findElementOfClassAtOffset(
                                    file, offset, PsiMethod.class, false);
                            if (superConstructor == null) {
                              CreateFromUsageUtils.setupMethodBody(constructor);
                            } else {
                              OverrideImplementUtil.setupMethodBody(
                                  constructor, superConstructor, targetClass);
                            }
                            CreateFromUsageUtils.setupEditor(constructor, editor);
                          } catch (IncorrectOperationException e) {
                            LOG.error(e);
                          }
                        }
                      });
            }
          });
    } catch (IncorrectOperationException e) {
      LOG.error(e);
    }
  }
Example #22
0
  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);
    }
  }
 @NotNull
 private static Collection<PsiLanguageInjectionHost> collectInjectionHosts(
     @NotNull PsiFile file, @NotNull TextRange range) {
   Stack<PsiElement> toProcess = new Stack<PsiElement>();
   for (PsiElement e = file.findElementAt(range.getStartOffset());
       e != null;
       e = e.getNextSibling()) {
     if (e.getTextRange().getStartOffset() >= range.getEndOffset()) {
       break;
     }
     toProcess.push(e);
   }
   if (toProcess.isEmpty()) {
     return Collections.emptySet();
   }
   Set<PsiLanguageInjectionHost> result = null;
   while (!toProcess.isEmpty()) {
     PsiElement e = toProcess.pop();
     if (e instanceof PsiLanguageInjectionHost) {
       if (result == null) {
         result = ContainerUtilRt.newHashSet();
       }
       result.add((PsiLanguageInjectionHost) e);
     } else {
       for (PsiElement child = e.getFirstChild(); child != null; child = child.getNextSibling()) {
         if (e.getTextRange().getStartOffset() >= range.getEndOffset()) {
           break;
         }
         toProcess.push(child);
       }
     }
   }
   return result == null ? Collections.<PsiLanguageInjectionHost>emptySet() : result;
 }
  @NotNull
  public static HighlightInfo fromAnnotation(
      @NotNull Annotation annotation, @Nullable TextRange fixedRange, boolean batchMode) {
    final TextAttributes forcedAttributes = annotation.getEnforcedTextAttributes();
    final TextAttributesKey forcedAttributesKey =
        forcedAttributes == null ? annotation.getTextAttributes() : null;

    HighlightInfo info =
        new HighlightInfo(
            forcedAttributes,
            forcedAttributesKey,
            convertType(annotation),
            fixedRange != null ? fixedRange.getStartOffset() : annotation.getStartOffset(),
            fixedRange != null ? fixedRange.getEndOffset() : annotation.getEndOffset(),
            annotation.getMessage(),
            annotation.getTooltip(),
            annotation.getSeverity(),
            annotation.isAfterEndOfLine(),
            annotation.needsUpdateOnTyping(),
            annotation.isFileLevelAnnotation(),
            0,
            annotation.getProblemGroup(),
            annotation.getGutterIconRenderer());
    appendFixes(
        fixedRange, info, batchMode ? annotation.getBatchFixes() : annotation.getQuickFixes());
    return info;
  }
  @Override
  public void visitField(PsiField field) {
    // There is a possible case that more than one field is declared for the same type like 'int i,
    // j;'. We want to process only
    // the first one then.
    PsiElement fieldPrev = getPreviousNonWsComment(field.getPrevSibling(), 0);
    if (fieldPrev instanceof PsiJavaToken
        && ((PsiJavaToken) fieldPrev).getTokenType() == JavaTokenType.COMMA) {
      return;
    }

    // There is a possible case that fields which share the same type declaration are located on
    // different document lines, e.g.:
    //    int i1,
    //        i2;
    // We want to consider only the first declaration then but need to expand its range to all
    // affected lines (up to semicolon).
    TextRange range = field.getTextRange();
    PsiElement child = field.getLastChild();
    boolean needSpecialProcessing = true;
    if (isSemicolon(child)) {
      needSpecialProcessing = false;
    } else if (child instanceof PsiComment) {
      // There is a possible field definition like below:
      //   int f; // my comment.
      // The comment goes into field PSI here, that's why we need to handle it properly.
      PsiElement prev = getPreviousNonWsComment(child, range.getStartOffset());
      needSpecialProcessing = prev != null && !isSemicolon(prev);
    }

    if (needSpecialProcessing) {
      for (PsiElement e = field.getNextSibling(); e != null; e = e.getNextSibling()) {
        if (e instanceof PsiWhiteSpace || e instanceof PsiComment) { // Skip white space and comment
          continue;
        } else if (e instanceof PsiJavaToken) {
          if (((PsiJavaToken) e).getTokenType() == JavaTokenType.COMMA) { // Skip comma
            continue;
          } else {
            break;
          }
        } else if (e instanceof PsiField) {
          PsiElement c = e.getLastChild();
          if (c != null) {
            c = getPreviousNonWsComment(c, range.getStartOffset());
          }
          // Stop if current field ends by a semicolon.
          if (c instanceof PsiErrorElement // Incomplete field without trailing semicolon
              || (c instanceof PsiJavaToken
                  && ((PsiJavaToken) c).getTokenType() == JavaTokenType.SEMICOLON)) {
            range = TextRange.create(range.getStartOffset(), c.getTextRange().getEndOffset());
          } else {
            continue;
          }
        }
        break;
      }
    }
    JavaElementArrangementEntry entry = createNewEntry(field, range, FIELD, field.getName(), true);
    processEntry(entry, field, field.getInitializer());
  }
  @Override
  @Nullable
  public PsiElement restoreElement() {
    long typeAndId = myStubElementTypeAndId;
    int stubId = (int) typeAndId;
    if (stubId != -1) {
      PsiFile file = restoreFile();
      if (!(file instanceof PsiFileWithStubSupport)) return null;
      short index = (short) (typeAndId >> 32);
      IStubElementType stubElementType = (IStubElementType) IElementType.find(index);
      return PsiAnchor.restoreFromStubIndex(
          (PsiFileWithStubSupport) file, stubId, stubElementType, false);
    }

    Segment psiRange = getPsiRange();
    if (psiRange == null) return null;

    PsiFile file = restoreFile();
    if (file == null) return null;
    PsiElement anchor = file.findElementAt(psiRange.getStartOffset());
    if (anchor == null) return null;

    TextRange range = anchor.getTextRange();
    if (range.getStartOffset() != psiRange.getStartOffset()
        || range.getEndOffset() != psiRange.getEndOffset()) return null;

    for (SmartPointerAnchorProvider provider : SmartPointerAnchorProvider.EP_NAME.getExtensions()) {
      final PsiElement element = provider.restoreElement(anchor);
      if (element != null) return element;
    }
    return null;
  }
  private static void highlightTodos(
      @NotNull PsiFile file,
      @NotNull CharSequence text,
      int startOffset,
      int endOffset,
      @NotNull ProgressIndicator progress,
      @NotNull ProperTextRange priorityRange,
      @NotNull Collection<HighlightInfo> result,
      @NotNull Collection<HighlightInfo> outsideResult) {
    PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(file.getProject());
    TodoItem[] todoItems = helper.findTodoItems(file, startOffset, endOffset);
    if (todoItems.length == 0) return;

    for (TodoItem todoItem : todoItems) {
      progress.checkCanceled();
      TextRange range = todoItem.getTextRange();
      String description =
          text.subSequence(range.getStartOffset(), range.getEndOffset()).toString();
      TextAttributes attributes = todoItem.getPattern().getAttributes().getTextAttributes();
      HighlightInfo info =
          HighlightInfo.createHighlightInfo(
              HighlightInfoType.TODO, range, description, description, attributes);
      assert info != null;
      if (priorityRange.containsRange(info.getStartOffset(), info.getEndOffset())) {
        result.add(info);
      } else {
        outsideResult.add(info);
      }
    }
  }
 private static void duplicateHighlighters(
     MarkupModel to, MarkupModel from, int offset, TextRange textRange) {
   for (RangeHighlighter rangeHighlighter : from.getAllHighlighters()) {
     if (!rangeHighlighter.isValid()) continue;
     Object tooltip = rangeHighlighter.getErrorStripeTooltip();
     HighlightInfo highlightInfo =
         tooltip instanceof HighlightInfo ? (HighlightInfo) tooltip : null;
     if (highlightInfo != null) {
       if (highlightInfo.getSeverity() != HighlightSeverity.INFORMATION) continue;
       if (highlightInfo.type.getAttributesKey() == EditorColors.IDENTIFIER_UNDER_CARET_ATTRIBUTES)
         continue;
     }
     final int localOffset = textRange.getStartOffset();
     final int start = Math.max(rangeHighlighter.getStartOffset(), localOffset) - localOffset;
     final int end =
         Math.min(rangeHighlighter.getEndOffset(), textRange.getEndOffset()) - localOffset;
     if (start > end) continue;
     final RangeHighlighter h =
         to.addRangeHighlighter(
             start + offset,
             end + offset,
             rangeHighlighter.getLayer(),
             rangeHighlighter.getTextAttributes(),
             rangeHighlighter.getTargetArea());
     ((RangeHighlighterEx) h)
         .setAfterEndOfLine(((RangeHighlighterEx) rangeHighlighter).isAfterEndOfLine());
   }
 }
  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);
    }
  }
 @Override
 public void visitPyStringLiteralExpression(PyStringLiteralExpression node) {
   final Pair<PsiElement, TextRange> data =
       node.getUserData(PyReplaceExpressionUtil.SELECTION_BREAKS_AST_NODE);
   if (data != null) {
     final PsiElement parent = data.getFirst();
     final String text = parent.getText();
     final Pair<String, String> detectedQuotes = PythonStringUtil.getQuotes(text);
     final Pair<String, String> quotes =
         detectedQuotes != null ? detectedQuotes : Pair.create("'", "'");
     final TextRange range = data.getSecond();
     final String substring = range.substring(text);
     myResult.append(quotes.getFirst() + substring + quotes.getSecond());
   } else {
     ASTNode child = node.getNode().getFirstChildNode();
     while (child != null) {
       String text = child.getText();
       if (child.getElementType() == TokenType.WHITE_SPACE) {
         if (text.contains("\n")) {
           if (!text.contains("\\")) {
             myResult.append("\\");
           }
           myResult.append(text);
         }
       } else {
         myResult.append(text);
       }
       child = child.getTreeNext();
     }
   }
 }