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;
  }
 @Override
 @Nullable
 public List<Pair<PsiElement, TextRange>> getInjectedPsiFiles(@NotNull final PsiElement host) {
   if (!(host instanceof PsiLanguageInjectionHost)
       || !((PsiLanguageInjectionHost) host).isValidHost()) {
     return null;
   }
   final PsiElement inTree = InjectedLanguageUtil.loadTree(host, host.getContainingFile());
   final List<Pair<PsiElement, TextRange>> result = new SmartList<Pair<PsiElement, TextRange>>();
   InjectedLanguageUtil.enumerate(
       inTree,
       new PsiLanguageInjectionHost.InjectedPsiVisitor() {
         @Override
         public void visit(
             @NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
           for (PsiLanguageInjectionHost.Shred place : places) {
             if (place.getHost() == inTree) {
               result.add(
                   new Pair<PsiElement, TextRange>(injectedPsi, place.getRangeInsideHost()));
             }
           }
         }
       });
   return result.isEmpty() ? null : result;
 }
  @Nullable
  public static LookupEx getActiveLookup(@Nullable Editor editor) {
    if (editor == null) return null;

    final Project project = editor.getProject();
    if (project == null || project.isDisposed()) return null;

    final LookupEx lookup = getInstance(project).getActiveLookup();
    if (lookup == null) return null;

    return InjectedLanguageUtil.getTopLevelEditor(lookup.getEditor())
            == InjectedLanguageUtil.getTopLevelEditor(editor)
        ? lookup
        : null;
  }
  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 boolean isInContext(@NotNull final PsiFile file, final int offset) {
    PsiElement at = file.findElementAt(offset);
    if (at == null && offset == file.getTextLength()) {
      at = file.findElementAt(offset - 1);
    }
    Language language = at != null ? at.getParent().getLanguage() : null;

    if (language instanceof XMLLanguage) {
      final PsiLanguageInjectionHost host =
          PsiTreeUtil.getParentOfType(at, PsiLanguageInjectionHost.class, false);

      if (host != null) {
        final Ref<Boolean> hasJsInjection = new Ref<Boolean>(Boolean.FALSE);

        InjectedLanguageUtil.enumerate(
            host,
            new JSResolveUtil.JSInjectedFilesVisitor() {
              @Override
              protected void process(final JSFile file) {
                hasJsInjection.set(Boolean.TRUE);
              }
            });

        if (hasJsInjection.get()) {
          language = JavaScriptSupportLoader.JAVASCRIPT.getLanguage();
        }
      }
    }
    return language != null && language.isKindOf(JavaScriptSupportLoader.JAVASCRIPT.getLanguage());
  }
  protected void restoreState(@NotNull final V psiField) {
    if (!ReadonlyStatusHandler.ensureDocumentWritable(
        myProject, InjectedLanguageUtil.getTopLevelEditor(myEditor).getDocument())) return;
    ApplicationManager.getApplication()
        .runWriteAction(
            () -> {
              final PsiFile containingFile = psiField.getContainingFile();
              final RangeMarker exprMarker = getExprMarker();
              if (exprMarker != null) {
                myExpr = restoreExpression(containingFile, psiField, exprMarker, myExprText);
              }

              if (myLocalMarker != null) {
                final PsiElement refVariableElement =
                    containingFile.findElementAt(myLocalMarker.getStartOffset());
                if (refVariableElement != null) {
                  final PsiElement parent = refVariableElement.getParent();
                  if (parent instanceof PsiNamedElement) {
                    ((PsiNamedElement) parent).setName(myLocalName);
                  }
                }

                final V localVariable = getLocalVariable();
                if (localVariable != null && localVariable.isPhysical()) {
                  myLocalVariable = localVariable;
                  final PsiElement nameIdentifier = localVariable.getNameIdentifier();
                  if (nameIdentifier != null) {
                    myLocalMarker = createMarker(nameIdentifier);
                  }
                }
              }
              final List<RangeMarker> occurrenceMarkers = getOccurrenceMarkers();
              for (int i = 0, occurrenceMarkersSize = occurrenceMarkers.size();
                  i < occurrenceMarkersSize;
                  i++) {
                RangeMarker marker = occurrenceMarkers.get(i);
                if (getExprMarker() != null
                    && marker.getStartOffset() == getExprMarker().getStartOffset()
                    && myExpr != null) {
                  myOccurrences[i] = myExpr;
                  continue;
                }
                final E psiExpression =
                    restoreExpression(
                        containingFile,
                        psiField,
                        marker,
                        getLocalVariable() != null ? myLocalName : myExprText);
                if (psiExpression != null) {
                  myOccurrences[i] = psiExpression;
                }
              }

              if (myExpr != null && myExpr.isPhysical()) {
                myExprMarker = createMarker(myExpr);
              }
              myOccurrenceMarkers = null;
              deleteTemplateField(psiField);
            });
  }
 public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
   final PsiLanguageInjectionHost host = findInjectionHost(editor, file);
   if (host == null) return false;
   final List<Pair<PsiElement, TextRange>> injectedPsi =
       InjectedLanguageUtil.getInstance().getInjectedPsiFiles(host);
   return injectedPsi == null || injectedPsi.isEmpty();
 }
  private void altCommitToOriginal(@NotNull DocumentEvent e) {
    final PsiFile origPsiFile =
        PsiDocumentManager.getInstance(myProject).getPsiFile(myOrigDocument);
    String newText = myNewDocument.getText();
    // prepare guarded blocks
    LinkedHashMap<String, String> replacementMap = new LinkedHashMap<String, String>();
    int count = 0;
    for (RangeMarker o : ContainerUtil.reverse(((DocumentEx) myNewDocument).getGuardedBlocks())) {
      String replacement = o.getUserData(REPLACEMENT_KEY);
      String tempText = "REPLACE" + (count++) + Long.toHexString(StringHash.calc(replacement));
      newText =
          newText.substring(0, o.getStartOffset()) + tempText + newText.substring(o.getEndOffset());
      replacementMap.put(tempText, replacement);
    }
    // run preformat processors
    final int hostStartOffset = myAltFullRange.getStartOffset();
    myEditor.getCaretModel().moveToOffset(hostStartOffset);
    for (CopyPastePreProcessor preProcessor :
        Extensions.getExtensions(CopyPastePreProcessor.EP_NAME)) {
      newText = preProcessor.preprocessOnPaste(myProject, origPsiFile, myEditor, newText, null);
    }
    myOrigDocument.replaceString(hostStartOffset, myAltFullRange.getEndOffset(), newText);
    // replace temp strings for guarded blocks
    for (String tempText : replacementMap.keySet()) {
      int idx =
          CharArrayUtil.indexOf(
              myOrigDocument.getCharsSequence(),
              tempText,
              hostStartOffset,
              myAltFullRange.getEndOffset());
      myOrigDocument.replaceString(idx, idx + tempText.length(), replacementMap.get(tempText));
    }
    // JAVA: fix occasional char literal concatenation
    fixDocumentQuotes(myOrigDocument, hostStartOffset - 1);
    fixDocumentQuotes(myOrigDocument, myAltFullRange.getEndOffset());

    // reformat
    PsiDocumentManager.getInstance(myProject).commitDocument(myOrigDocument);
    Runnable task =
        () -> {
          try {
            CodeStyleManager.getInstance(myProject)
                .reformatRange(origPsiFile, hostStartOffset, myAltFullRange.getEndOffset(), true);
          } catch (IncorrectOperationException e1) {
            // LOG.error(e);
          }
        };
    DocumentUtil.executeInBulk(myOrigDocument, true, task);

    PsiElement newInjected =
        InjectedLanguageManager.getInstance(myProject)
            .findInjectedElementAt(origPsiFile, hostStartOffset);
    DocumentWindow documentWindow =
        newInjected == null ? null : InjectedLanguageUtil.getDocumentWindow(newInjected);
    if (documentWindow != null) {
      myEditor.getCaretModel().moveToOffset(documentWindow.injectedToHost(e.getOffset()));
      myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
    }
  }
 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;
 }
 @Override
 public void tokenize(@NotNull T element, TokenConsumer consumer) {
   if (element instanceof PsiLanguageInjectionHost
       && InjectedLanguageUtil.hasInjections((PsiLanguageInjectionHost) element)) {
     return;
   }
   consumer.consumeToken(element, mySplitter);
 }
 @Override
 public void enumerateEx(
     @NotNull PsiElement host,
     @NotNull PsiFile containingFile,
     boolean probeUp,
     @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) {
   InjectedLanguageUtil.enumerate(host, containingFile, probeUp, visitor);
 }
 @Override
 protected void revertStateOnFinish() {
   final Editor editor = InjectedLanguageUtil.getTopLevelEditor(myEditor);
   if (editor == FileEditorManager.getInstance(myProject).getSelectedTextEditor()) {
     ((EditorImpl) editor).startDumb();
   }
   revertState();
 }
  @Nullable
  protected PsiFile getContainingFile() {
    final PsiFile file = InjectedLanguageUtil.getTopLevelFile(myElement.getContainingFile());
    if (file == null) {
      LOG.error("Invalid element: " + myElement);
    }

    return file.getOriginalFile();
  }
  private void getInjectedPsiFiles(
      @NotNull final List<PsiElement> elements1,
      @NotNull final List<PsiElement> elements2,
      @NotNull final ProgressIndicator progress,
      @NotNull final Set<PsiFile> outInjected) {
    List<DocumentWindow> injected = InjectedLanguageUtil.getCachedInjectedDocuments(myFile);
    Collection<PsiElement> hosts =
        new THashSet<PsiElement>(elements1.size() + elements2.size() + injected.size());

    // rehighlight all injected PSI regardless the range,
    // since change in one place can lead to invalidation of injected PSI in (completely) other
    // place.
    for (DocumentWindow documentRange : injected) {
      progress.checkCanceled();
      if (!documentRange.isValid()) continue;
      PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(documentRange);
      if (file == null) continue;
      PsiElement context =
          InjectedLanguageManager.getInstance(file.getProject()).getInjectionHost(file);
      if (context != null
          && context.isValid()
          && !file.getProject().isDisposed()
          && (myUpdateAll
              || new ProperTextRange(myStartOffset, myEndOffset)
                  .intersects(context.getTextRange()))) {
        hosts.add(context);
      }
    }
    hosts.addAll(elements1);
    hosts.addAll(elements2);

    final PsiLanguageInjectionHost.InjectedPsiVisitor visitor =
        new PsiLanguageInjectionHost.InjectedPsiVisitor() {
          @Override
          public void visit(
              @NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
            synchronized (outInjected) {
              outInjected.add(injectedPsi);
            }
          }
        };
    if (!JobUtil.invokeConcurrentlyUnderProgress(
        new ArrayList<PsiElement>(hosts),
        progress,
        false,
        new Processor<PsiElement>() {
          @Override
          public boolean process(PsiElement element) {
            progress.checkCanceled();
            InjectedLanguageUtil.enumerate(element, myFile, false, visitor);
            return true;
          }
        })) throw new ProcessCanceledException();
  }
  public static void disposeInvalidEditors() {
    ApplicationManager.getApplication().assertWriteAccessAllowed();
    Iterator<EditorWindow> iterator = allEditors.iterator();
    while (iterator.hasNext()) {
      EditorWindow editorWindow = iterator.next();
      if (!editorWindow.isValid()) {
        editorWindow.dispose();

        InjectedLanguageUtil.clearCaches(editorWindow.myInjectedFile, editorWindow.getDocument());
        iterator.remove();
      }
    }
  }
 private static boolean defaultFunctionalityWorked(final PsiLanguageInjectionHost host) {
   final THashSet<String> languages = new THashSet<String>();
   final List<Pair<PsiElement, TextRange>> files = InjectedLanguageUtil.getInjectedPsiFiles(host);
   if (files == null) return false;
   for (Pair<PsiElement, TextRange> pair : files) {
     for (Language lang = pair.first.getLanguage(); lang != null; lang = lang.getBaseLanguage()) {
       languages.add(lang.getID());
     }
   }
   // todo there is a problem: host i.e. literal expression is confused with "target" i.e.
   // parameter
   // todo therefore this part doesn't work for java
   return Configuration.getInstance().setHostInjectionEnabled(host, languages, false);
 }
  @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);
  }
 /**
  * intersection may spread over several injected fragments
  *
  * @param rangeToEdit range in encoded(raw) PSI
  * @return list of ranges in encoded (raw) PSI
  */
 @Override
 @SuppressWarnings({"ConstantConditions", "unchecked"})
 @NotNull
 public List<TextRange> intersectWithAllEditableFragments(
     @NotNull PsiFile injectedPsi, @NotNull TextRange rangeToEdit) {
   Place shreds = InjectedLanguageUtil.getShreds(injectedPsi);
   if (shreds == null) return Collections.emptyList();
   Object result = null; // optimization: TextRange or ArrayList
   int count = 0;
   int offset = 0;
   for (PsiLanguageInjectionHost.Shred shred : shreds) {
     TextRange encodedRange =
         TextRange.from(
             offset + shred.getPrefix().length(), shred.getRangeInsideHost().getLength());
     TextRange intersection = encodedRange.intersection(rangeToEdit);
     if (intersection != null) {
       count++;
       if (count == 1) {
         result = intersection;
       } else if (count == 2) {
         TextRange range = (TextRange) result;
         if (range.isEmpty()) {
           result = intersection;
           count = 1;
         } else if (intersection.isEmpty()) {
           count = 1;
         } else {
           List<TextRange> list = new ArrayList<TextRange>();
           list.add(range);
           list.add(intersection);
           result = list;
         }
       } else if (intersection.isEmpty()) {
         count--;
       } else {
         ((List<TextRange>) result).add(intersection);
       }
     }
     offset +=
         shred.getPrefix().length()
             + shred.getRangeInsideHost().getLength()
             + shred.getSuffix().length();
   }
   return count == 0
       ? Collections.<TextRange>emptyList()
       : count == 1 ? Collections.singletonList((TextRange) result) : (List<TextRange>) result;
 }
Example #19
0
        @Override
        public void mouseMoved(final EditorMouseEvent e) {
          if (e.isConsumed() || !myProject.isInitialized() || myProject.isDisposed()) {
            return;
          }
          MouseEvent mouseEvent = e.getMouseEvent();

          if (isMouseOverTooltip(mouseEvent.getLocationOnScreen())
              || ScreenUtil.isMovementTowards(
                  myPrevMouseLocation, mouseEvent.getLocationOnScreen(), getHintBounds())) {
            myPrevMouseLocation = mouseEvent.getLocationOnScreen();
            return;
          }
          myPrevMouseLocation = mouseEvent.getLocationOnScreen();

          Editor editor = e.getEditor();
          if (editor.getProject() != null && editor.getProject() != myProject) return;
          PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
          PsiFile psiFile = documentManager.getPsiFile(editor.getDocument());
          Point point = new Point(mouseEvent.getPoint());
          if (documentManager.isCommitted(editor.getDocument())) {
            // when document is committed, try to check injected stuff - it's fast
            int offset = editor.logicalPositionToOffset(editor.xyToLogicalPosition(point));
            editor =
                InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(editor, psiFile, offset);
          }

          LogicalPosition pos = editor.xyToLogicalPosition(point);
          int offset = editor.logicalPositionToOffset(pos);
          int selStart = editor.getSelectionModel().getSelectionStart();
          int selEnd = editor.getSelectionModel().getSelectionEnd();

          myStoredModifiers = mouseEvent.getModifiers();
          BrowseMode browseMode = getBrowseMode(myStoredModifiers);

          cancelPreviousTooltip();

          if (browseMode == BrowseMode.None || offset >= selStart && offset < selEnd) {
            disposeHighlighter();
            return;
          }

          myTooltipProvider = new TooltipProvider(editor, pos);
          myTooltipProvider.execute(browseMode);
        }
 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);
   }
 }
 public int getLineNumber() {
   if (myLineNumber == -1) {
     PsiElement psiElement = getPsiElement();
     if (psiElement == null) return -1;
     if (!psiElement.isValid()) return -1;
     LOG.assertTrue(psiElement.isPhysical());
     PsiFile containingFile = InjectedLanguageUtil.getTopLevelFile(psiElement);
     Document document =
         PsiDocumentManager.getInstance(psiElement.getProject()).getDocument(containingFile);
     if (document == null) return -1;
     TextRange textRange = getTextRange();
     if (textRange == null) return -1;
     textRange =
         InjectedLanguageManager.getInstance(containingFile.getProject())
             .injectedToHost(psiElement, textRange);
     myLineNumber = document.getLineNumber(textRange.getStartOffset()) + 1;
   }
   return myLineNumber;
 }
        public void mouseMoved(final EditorMouseEvent e) {
          if (e.isConsumed() || !myProject.isInitialized()) {
            return;
          }
          MouseEvent mouseEvent = e.getMouseEvent();

          Editor editor = e.getEditor();
          if (editor.getProject() != null && editor.getProject() != myProject) return;
          PsiFile psiFile =
              PsiDocumentManager.getInstance(myProject).getPsiFile(editor.getDocument());
          Point point = new Point(mouseEvent.getPoint());
          if (!PsiDocumentManager.getInstance(myProject).isUncommited(editor.getDocument())) {
            // when document is committed, try to check injected stuff - it's fast
            editor =
                InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(
                    editor,
                    psiFile,
                    editor.logicalPositionToOffset(editor.xyToLogicalPosition(point)));
          }

          LogicalPosition pos = editor.xyToLogicalPosition(point);
          int offset = editor.logicalPositionToOffset(pos);
          int selStart = editor.getSelectionModel().getSelectionStart();
          int selEnd = editor.getSelectionModel().getSelectionEnd();

          myStoredModifiers = mouseEvent.getModifiers();
          BrowseMode browseMode = getBrowseMode(myStoredModifiers);

          if (myTooltipProvider != null) {
            myTooltipProvider.dispose();
          }

          if (browseMode == BrowseMode.None || offset >= selStart && offset < selEnd) {
            disposeHighlighter();
            myTooltipProvider = null;
            return;
          }

          myTooltipProvider = new TooltipProvider(editor, pos);
          myTooltipProvider.execute(browseMode);
        }
  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;
  }
 @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;
 }
  @Override
  protected void performRefactoringRename(final String newName, final StartMarkAction markAction) {
    try {
      final PsiNamedElement variable = getVariable();
      if (variable != null && !newName.equals(myOldName)) {
        if (isIdentifier(newName, variable.getLanguage())) {
          final PsiElement substituted = getSubstituted();
          if (substituted == null) {
            return;
          }

          final String commandName =
              RefactoringBundle.message(
                  "renaming.0.1.to.2",
                  UsageViewUtil.getType(variable),
                  UsageViewUtil.getDescriptiveName(variable),
                  newName);
          CommandProcessor.getInstance()
              .executeCommand(
                  myProject,
                  new Runnable() {
                    @Override
                    public void run() {
                      performRenameInner(substituted, newName);
                      PsiDocumentManager.getInstance(myProject).commitAllDocuments();
                    }
                  },
                  commandName,
                  null);
        }
      }
    } finally {
      try {
        ((EditorImpl) InjectedLanguageUtil.getTopLevelEditor(myEditor)).stopDumbLater();
      } finally {
        FinishMarkAction.finish(myProject, myEditor, markAction);
      }
    }
  }
  @NotNull
  @Override
  public PsiReference[] getReferencesByElement(
      @NotNull PsiElement element, @NotNull ProcessingContext context) {

    if (XmlSchemaTagsProcessor.PROCESSING_FLAG.get() != null || context.get(SUPPRESS) != null) {
      return PsiReference.EMPTY_ARRAY;
    }
    @SuppressWarnings("unchecked")
    PsiElement host = getHost((T) element);
    if (host instanceof PsiLanguageInjectionHost
        && InjectedLanguageUtil.hasInjections((PsiLanguageInjectionHost) host)) {
      return PsiReference.EMPTY_ARRAY;
    }
    String unquotedValue = ElementManipulators.getValueText(element);
    if (XmlHighlightVisitor.skipValidation(element)
        || !XmlUtil.isSimpleValue(unquotedValue, element)) {
      return PsiReference.EMPTY_ARRAY;
    }
    @SuppressWarnings("unchecked")
    final Object descriptor = getDescriptor((T) element);
    if (descriptor instanceof XmlEnumerationDescriptor) {
      XmlEnumerationDescriptor enumerationDescriptor = (XmlEnumerationDescriptor) descriptor;

      if (enumerationDescriptor.isFixed()
          || enumerationDescriptor.isEnumerated((XmlElement) element)) {
        //noinspection unchecked
        return enumerationDescriptor.getValueReferences((XmlElement) element, unquotedValue);
      } else if (unquotedValue.equals(
          enumerationDescriptor.getDefaultValue())) { // todo case insensitive
        return ContainerUtil.map2Array(
            enumerationDescriptor.getValueReferences((XmlElement) element, unquotedValue),
            PsiReference.class,
            reference -> PsiDelegateReference.createSoft(reference, true));
      }
    }
    return PsiReference.EMPTY_ARRAY;
  }
  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.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 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 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);
      }
    };
  }
  @Override
  public void addOccurrenceHighlights(
      @NotNull Editor editor,
      @NotNull PsiReference[] occurrences,
      @NotNull TextAttributes attributes,
      boolean hideByTextChange,
      Collection<RangeHighlighter> outHighlighters) {
    if (occurrences.length == 0) return;
    int flags = HIDE_BY_ESCAPE;
    if (hideByTextChange) {
      flags |= HIDE_BY_TEXT_CHANGE;
    }
    Color scrollmarkColor = getScrollMarkColor(attributes);

    int oldOffset = editor.getCaretModel().getOffset();
    int horizontalScrollOffset = editor.getScrollingModel().getHorizontalScrollOffset();
    int verticalScrollOffset = editor.getScrollingModel().getVerticalScrollOffset();
    for (PsiReference occurrence : occurrences) {
      PsiElement element = occurrence.getElement();
      int startOffset = element.getTextRange().getStartOffset();
      int start = startOffset + occurrence.getRangeInElement().getStartOffset();
      int end = startOffset + occurrence.getRangeInElement().getEndOffset();
      PsiFile containingFile = element.getContainingFile();
      Project project = element.getProject();
      // each reference can reside in its own injected editor
      Editor textEditor = InjectedLanguageUtil.openEditorFor(containingFile, project);
      if (textEditor != null) {
        addOccurrenceHighlight(
            textEditor, start, end, attributes, flags, outHighlighters, scrollmarkColor);
      }
    }
    editor.getCaretModel().moveToOffset(oldOffset);
    editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
    editor.getScrollingModel().scrollHorizontally(horizontalScrollOffset);
    editor.getScrollingModel().scrollVertically(verticalScrollOffset);
  }