예제 #1
0
 @NotNull
 private Dimension expandIfNecessary(@NotNull Dimension base) {
   if (base.width >= myMinWidth && base.height >= myMinHeight) {
     return base;
   }
   return new Dimension(Math.max(myMinWidth, base.width), Math.max(myMinHeight, base.height));
 }
    private Pair<MutableTextRange, StringBuffer> getFragmentByRange(int start, final int length) {
      final StringBuffer fragmentBuffer = new StringBuffer();
      int end = start + length;

      // restoring buffer and remove all subfragments from the list
      int documentOffset = 0;
      int effectiveOffset = 0;

      Iterator<Pair<MutableTextRange, StringBuffer>> iterator = myAffectedFragments.iterator();
      while (iterator.hasNext() && effectiveOffset <= end) {
        final Pair<MutableTextRange, StringBuffer> pair = iterator.next();
        final MutableTextRange range = pair.getFirst();
        final StringBuffer buffer = pair.getSecond();
        int effectiveFragmentEnd = range.getStartOffset() + buffer.length();

        if (range.getStartOffset() <= start && effectiveFragmentEnd >= end) return pair;

        if (effectiveFragmentEnd >= start) {
          final int effectiveStart = Math.max(effectiveOffset, start);
          if (range.getStartOffset() > start) {
            fragmentBuffer.append(
                myDocument.getCharsSequence(),
                effectiveStart - effectiveOffset + documentOffset,
                Math.min(range.getStartOffset(), end) - effectiveOffset + documentOffset);
          }
          if (end >= range.getStartOffset()) {
            fragmentBuffer.append(buffer);
            end =
                end > effectiveFragmentEnd
                    ? end - (buffer.length() - range.getLength())
                    : range.getEndOffset();
            effectiveFragmentEnd = range.getEndOffset();
            start = Math.min(start, range.getStartOffset());
            iterator.remove();
          }
        }

        documentOffset += range.getEndOffset() - effectiveOffset;
        effectiveOffset = effectiveFragmentEnd;
      }

      if (effectiveOffset < end) {
        final int effectiveStart = Math.max(effectiveOffset, start);
        fragmentBuffer.append(
            myDocument.getCharsSequence(),
            effectiveStart - effectiveOffset + documentOffset,
            end - effectiveOffset + documentOffset);
      }

      MutableTextRange newRange = new MutableTextRange(start, end);
      final Pair<MutableTextRange, StringBuffer> pair =
          new Pair<MutableTextRange, StringBuffer>(newRange, fragmentBuffer);
      for (Pair<MutableTextRange, StringBuffer> affectedFragment : myAffectedFragments) {
        MutableTextRange range = affectedFragment.getFirst();
        assert end <= range.getStartOffset() || range.getEndOffset() <= start
            : "Range :" + range + "; Added: " + newRange;
      }
      myAffectedFragments.add(pair);
      return pair;
    }
예제 #3
0
  /**
   * Returns the original comment info of the specified element or null
   *
   * @param element the specified element
   * @return text chunk
   */
  @Nullable
  private static String getOrigCommentInfo(PsiDocCommentOwner element) {
    StringBuilder sb = new StringBuilder();
    PsiElement e = element.getFirstChild();
    if (!(e instanceof PsiComment)) {
      // no comments for this element
      return null;
    } else {
      boolean first = true;
      while (true) {
        if (e instanceof PsiDocComment) {
          PsiComment cm = (PsiComment) e;
          String text = cm.getText();
          if (text.startsWith("//")) {
            if (!first) sb.append('\n');
            sb.append(text.substring(2).trim());
          } else if (text.startsWith("/*")) {
            if (text.charAt(2) == '*') {
              text = text.substring(3, Math.max(3, text.length() - 2));
            } else {
              text = text.substring(2, Math.max(2, text.length() - 2));
            }
            sb.append(text);
          }
        } else if (!(e instanceof PsiWhiteSpace) && !(e instanceof PsiComment)) {
          break;
        }
        first = false;
        e = e.getNextSibling();
      }

      return sb.toString();
    }
  }
예제 #4
0
 public static boolean filterEquals(ClassFilter[] filters1, ClassFilter[] filters2) {
   if (filters1.length != filters2.length) {
     return false;
   }
   final Set<ClassFilter> f1 =
       new HashSet<ClassFilter>(Math.max((int) (filters1.length / .75f) + 1, 16));
   final Set<ClassFilter> f2 =
       new HashSet<ClassFilter>(Math.max((int) (filters2.length / .75f) + 1, 16));
   Collections.addAll(f1, filters1);
   Collections.addAll(f2, filters2);
   return f2.equals(f1);
 }
  public static void initOffsets(final PsiFile file, final OffsetMap offsetMap) {
    int offset =
        Math.max(
            offsetMap.getOffset(CompletionInitializationContext.SELECTION_END_OFFSET),
            offsetMap.getOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET));

    PsiElement element = file.findElementAt(offset);
    if (element instanceof PsiWhiteSpace
        && (!element.textContains('\n')
            || CodeStyleSettingsManager.getSettings(file.getProject())
                .getCommonSettings(JavaLanguage.INSTANCE)
                .METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE)) {
      element = file.findElementAt(element.getTextRange().getEndOffset());
    }
    if (element == null) return;

    if (LEFT_PAREN.accepts(element)) {
      offsetMap.addOffset(LPAREN_OFFSET, element.getTextRange().getStartOffset());
      PsiElement list = element.getParent();
      PsiElement last = list.getLastChild();
      if (last instanceof PsiJavaToken
          && ((PsiJavaToken) last).getTokenType() == JavaTokenType.RPARENTH) {
        offsetMap.addOffset(RPAREN_OFFSET, last.getTextRange().getStartOffset());
      }

      offsetMap.addOffset(ARG_LIST_END_OFFSET, list.getTextRange().getEndOffset());
    }
  }
 private void enterScope(PsiElement element) {
   scopeEntered.add(element);
   m_currentDepth++;
   if ((m_maximumDepth = Math.max(m_maximumDepth, m_currentDepth)) > myLimit) {
     stopWalking();
   }
 }
 public static boolean filterEquals(ClassFilter[] filters1, ClassFilter[] filters2) {
   if (filters1.length != filters2.length) {
     return false;
   }
   final Set<ClassFilter> f1 =
       new HashSet<ClassFilter>(Math.max((int) (filters1.length / .75f) + 1, 16));
   final Set<ClassFilter> f2 =
       new HashSet<ClassFilter>(Math.max((int) (filters2.length / .75f) + 1, 16));
   for (ClassFilter filter : filters1) {
     f1.add(filter);
   }
   for (ClassFilter aFilters2 : filters2) {
     f2.add(aFilters2);
   }
   return f2.equals(f1);
 }
  @Override
  @NotNull
  public String getPlainText() {
    int startOffset = getNavigationOffset();
    final PsiElement element = getElement();
    if (element != null && startOffset != -1) {
      final Document document = getDocument();
      if (document != null) {
        int lineNumber = document.getLineNumber(startOffset);
        int lineStart = document.getLineStartOffset(lineNumber);
        int lineEnd = document.getLineEndOffset(lineNumber);
        String prefixSuffix = null;

        if (lineEnd - lineStart > ChunkExtractor.MAX_LINE_LENGTH_TO_SHOW) {
          prefixSuffix = "...";
          lineStart =
              Math.max(
                  startOffset - ChunkExtractor.OFFSET_BEFORE_TO_SHOW_WHEN_LONG_LINE, lineStart);
          lineEnd =
              Math.min(startOffset + ChunkExtractor.OFFSET_AFTER_TO_SHOW_WHEN_LONG_LINE, lineEnd);
        }
        String s = document.getCharsSequence().subSequence(lineStart, lineEnd).toString();
        if (prefixSuffix != null) s = prefixSuffix + s + prefixSuffix;
        return s;
      }
    }
    return UsageViewBundle.message("node.invalid");
  }
  private static int getQuickFixType(PsiVariable variable) {
    PsiElement outerCodeBlock = PsiUtil.getVariableCodeBlock(variable, null);
    if (outerCodeBlock == null) return -1;
    List<PsiReferenceExpression> outerReferences = new ArrayList<PsiReferenceExpression>();
    collectReferences(outerCodeBlock, variable, outerReferences);

    int type = MAKE_FINAL;
    for (PsiReferenceExpression expression : outerReferences) {
      // if it happens that variable referenced from another inner class, make sure it can be make
      // final from there
      PsiClass innerClass =
          HighlightControlFlowUtil.getInnerClassVariableReferencedFrom(variable, expression);

      if (innerClass != null) {
        int thisType = MAKE_FINAL;
        if (writtenInside(variable, innerClass)) {
          // cannot make parameter array
          if (variable instanceof PsiParameter) return -1;
          thisType = MAKE_ARRAY;
        }
        if (thisType == MAKE_FINAL && !canBeFinal(variable, outerReferences)) {
          thisType = COPY_TO_FINAL;
        }
        type = Math.max(type, thisType);
      }
    }
    return type;
  }
예제 #10
0
 private static LineRange expandLineRangeToCoverPsiElements(
     final LineRange range, Editor editor, final PsiFile file) {
   Pair<PsiElement, PsiElement> psiRange = getElementRange(editor, file, range);
   if (psiRange == null) return null;
   final PsiElement parent =
       PsiTreeUtil.findCommonParent(psiRange.getFirst(), psiRange.getSecond());
   Pair<PsiElement, PsiElement> elementRange =
       getElementRange(parent, psiRange.getFirst(), psiRange.getSecond());
   if (elementRange == null) return null;
   int endOffset = elementRange.getSecond().getTextRange().getEndOffset();
   Document document = editor.getDocument();
   if (endOffset > document.getTextLength()) {
     LOG.assertTrue(!PsiDocumentManager.getInstance(file.getProject()).isUncommited(document));
     LOG.assertTrue(PsiDocumentManagerImpl.checkConsistency(file, document));
   }
   int endLine;
   if (endOffset == document.getTextLength()) {
     endLine = document.getLineCount();
   } else {
     endLine = editor.offsetToLogicalPosition(endOffset).line + 1;
     endLine = Math.min(endLine, document.getLineCount());
   }
   int startLine =
       Math.min(
           range.startLine,
           editor.offsetToLogicalPosition(elementRange.getFirst().getTextOffset()).line);
   endLine = Math.max(endLine, range.endLine);
   return new LineRange(startLine, endLine);
 }
 private int getTypesMaxLength() {
   int len = 0;
   for (ParameterTableModelItemBase<ParameterInfoImpl> item : myParametersTableModel.getItems()) {
     final String text = item.typeCodeFragment == null ? null : item.typeCodeFragment.getText();
     len = Math.max(len, text == null ? 0 : text.length());
   }
   return len;
 }
 private int getNamesMaxLength() {
   int len = 0;
   for (ParameterTableModelItemBase<ParameterInfoImpl> item : myParametersTableModel.getItems()) {
     final String text = item.parameter.getName();
     len = Math.max(len, text == null ? 0 : text.length());
   }
   return len;
 }
예제 #13
0
    QuickDocInfoPane(
        @NotNull PsiElement documentationAnchor,
        @NotNull PsiElement elementUnderMouse,
        @NotNull JComponent baseDocControl) {
      myBaseDocControl = baseDocControl;

      PresentationFactory presentationFactory = new PresentationFactory();
      for (AbstractDocumentationTooltipAction action : ourTooltipActions) {
        Icon icon = action.getTemplatePresentation().getIcon();
        Dimension minSize = new Dimension(icon.getIconWidth(), icon.getIconHeight());
        myButtons.add(
            new ActionButton(
                action,
                presentationFactory.getPresentation(action),
                IdeTooltipManager.IDE_TOOLTIP_PLACE,
                minSize));
        action.setDocInfo(documentationAnchor, elementUnderMouse);
      }
      Collections.reverse(myButtons);

      setPreferredSize(baseDocControl.getPreferredSize());
      setMaximumSize(baseDocControl.getMaximumSize());
      setMinimumSize(baseDocControl.getMinimumSize());
      setBackground(baseDocControl.getBackground());

      add(baseDocControl, Integer.valueOf(0));
      int minWidth = 0;
      int minHeight = 0;
      int buttonWidth = 0;
      for (JComponent button : myButtons) {
        button.setBorder(null);
        button.setBackground(baseDocControl.getBackground());
        add(button, Integer.valueOf(1));
        button.setVisible(false);
        Dimension preferredSize = button.getPreferredSize();
        minWidth += preferredSize.width;
        minHeight = Math.max(minHeight, preferredSize.height);
        buttonWidth = Math.max(buttonWidth, preferredSize.width);
      }
      myButtonWidth = buttonWidth;

      int margin = 2;
      myMinWidth = minWidth + margin * 2 + (myButtons.size() - 1) * BUTTON_HGAP;
      myMinHeight = minHeight + margin * 2;
    }
    private String getText(final int start, final int end) {
      int currentOldDocumentOffset = 0;
      int currentNewDocumentOffset = 0;
      StringBuilder text = new StringBuilder();
      Iterator<Pair<MutableTextRange, StringBuffer>> iterator = myAffectedFragments.iterator();
      while (iterator.hasNext() && currentNewDocumentOffset < end) {
        final Pair<MutableTextRange, StringBuffer> pair = iterator.next();
        final MutableTextRange range = pair.getFirst();
        final StringBuffer buffer = pair.getSecond();
        final int fragmentEndInNewDocument = range.getStartOffset() + buffer.length();

        if (range.getStartOffset() <= start && fragmentEndInNewDocument >= end) {
          return buffer.substring(start - range.getStartOffset(), end - range.getStartOffset());
        }

        if (range.getStartOffset() >= start) {
          final int effectiveStart = Math.max(currentNewDocumentOffset, start);
          text.append(
              myDocument.getCharsSequence(),
              effectiveStart - currentNewDocumentOffset + currentOldDocumentOffset,
              Math.min(range.getStartOffset(), end)
                  - currentNewDocumentOffset
                  + currentOldDocumentOffset);
          if (end > range.getStartOffset()) {
            text.append(
                buffer.substring(0, Math.min(end - range.getStartOffset(), buffer.length())));
          }
        }

        currentOldDocumentOffset += range.getEndOffset() - currentNewDocumentOffset;
        currentNewDocumentOffset = fragmentEndInNewDocument;
      }

      if (currentNewDocumentOffset < end) {
        final int effectiveStart = Math.max(currentNewDocumentOffset, start);
        text.append(
            myDocument.getCharsSequence(),
            effectiveStart - currentNewDocumentOffset + currentOldDocumentOffset,
            end - currentNewDocumentOffset + currentOldDocumentOffset);
      }

      return text.toString();
    }
 int getNavigationOffset() {
   Document document = getDocument();
   if (document == null) return -1;
   int offset = getUsageInfo().getNavigationOffset();
   if (offset == -1) offset = myOffset;
   if (offset >= document.getTextLength()) {
     int line = Math.max(0, Math.min(myLineNumber, document.getLineCount() - 1));
     offset = document.getLineStartOffset(line);
   }
   return offset;
 }
 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);
   }
 }
예제 #17
0
 private void updatedMovedIntoEnd(
     final Document document, @NotNull final MoveInfo info, final int offset) {
   if (offset + 1 < document.getTextLength()) {
     final int line = document.getLineNumber(offset + 1);
     final LineRange toMove2 = info.toMove2;
     if (toMove2 == null) return;
     info.toMove2 =
         new LineRange(
             toMove2.startLine,
             Math.min(Math.max(line, toMove2.endLine), document.getLineCount() - 1));
   }
 }
 private boolean isWhiteSpaceOrComment(@NotNull PsiElement element, @NotNull TextRange range) {
   final TextRange textRange = element.getTextRange();
   TextRange intersection = range.intersection(textRange);
   if (intersection == null) {
     return false;
   }
   intersection =
       TextRange.create(
           Math.max(intersection.getStartOffset() - textRange.getStartOffset(), 0),
           Math.min(
               intersection.getEndOffset() - textRange.getStartOffset(), textRange.getLength()));
   return isWhiteSpaceOrComment(element)
       || intersection.substring(element.getText()).trim().length() == 0;
 }
예제 #19
0
  private static void addNamesFromStatistics(
      Set<String> names,
      VariableKind variableKind,
      @Nullable String propertyName,
      @Nullable PsiType type) {
    String[] allNames =
        JavaStatisticsManager.getAllVariableNamesUsed(variableKind, propertyName, type);

    int maxFrequency = 0;
    for (String name : allNames) {
      int count =
          JavaStatisticsManager.getVariableNameUseCount(name, variableKind, propertyName, type);
      maxFrequency = Math.max(maxFrequency, count);
    }

    int frequencyLimit = Math.max(5, maxFrequency / 2);

    for (String name : allNames) {
      if (names.contains(name)) {
        continue;
      }
      int count =
          JavaStatisticsManager.getVariableNameUseCount(name, variableKind, propertyName, type);
      if (LOG.isDebugEnabled()) {
        LOG.debug("new name:" + name + " count:" + count);
        LOG.debug("frequencyLimit:" + frequencyLimit);
      }
      if (count >= frequencyLimit) {
        names.add(name);
      }
    }

    if (propertyName != null && type != null) {
      addNamesFromStatistics(names, variableKind, propertyName, null);
      addNamesFromStatistics(names, variableKind, null, type);
    }
  }
예제 #20
0
  private static int calcMatch(final String expectedName, final List<String> words, int max) {
    if (expectedName == null) return max;

    String[] expectedWords = NameUtil.nameToWords(expectedName);
    int limit = Math.min(words.size(), expectedWords.length);
    for (int i = 0; i < limit; i++) {
      String word = words.get(words.size() - i - 1);
      String expectedWord = expectedWords[expectedWords.length - i - 1];
      if (word.equalsIgnoreCase(expectedWord)) {
        max = Math.max(max, i + 1);
      } else {
        break;
      }
    }
    return max;
  }
 private static void adjustIndentationInRange(
     final PsiFile file,
     final Document document,
     final TextRange[] indents,
     final int indentAdjustment) {
   final CharSequence charsSequence = document.getCharsSequence();
   for (final TextRange indent : indents) {
     final String oldIndentStr =
         charsSequence.subSequence(indent.getStartOffset() + 1, indent.getEndOffset()).toString();
     final int oldIndent =
         IndentHelperImpl.getIndent(file.getProject(), file.getFileType(), oldIndentStr, true);
     final String newIndentStr =
         IndentHelperImpl.fillIndent(
             file.getProject(), file.getFileType(), Math.max(oldIndent + indentAdjustment, 0));
     document.replaceString(indent.getStartOffset() + 1, indent.getEndOffset(), newIndentStr);
   }
 }
예제 #22
0
    @Override
    public void exchangeRows(int row, int targetRow) {
      if (row < 0 || row >= getVariableData().length) return;
      if (targetRow < 0 || targetRow >= getVariableData().length) return;

      final VariableData currentItem = getVariableData()[row];
      getVariableData()[row] = getVariableData()[targetRow];
      getVariableData()[targetRow] = currentItem;

      TypeSelector currentSelector = myParameterTypeSelectors[row];
      myParameterTypeSelectors[row] = myParameterTypeSelectors[targetRow];
      myParameterTypeSelectors[targetRow] = currentSelector;

      myTypeRendererCombo.setModel(new DefaultComboBoxModel(getVariableData()));

      myTableModel.fireTableRowsUpdated(Math.min(targetRow, row), Math.max(targetRow, row));
      myTable.getSelectionModel().setSelectionInterval(targetRow, targetRow);
      updateSignature();
    }
예제 #23
0
  /**
   * It's possible that we need to expand quick doc control's width in order to provide better
   * visual representation (see http://youtrack.jetbrains.com/issue/IDEA-101425). This method
   * calculates that width expand.
   *
   * @param buttonWidth icon button's width
   * @param updatedText text which will be should at the quick doc control
   * @return width increase to apply to the target quick doc control (zero if no additional width
   *     increase is required)
   */
  private static int calculateWidthIncrease(int buttonWidth, String updatedText) {
    int maxLineWidth = 0;
    TIntArrayList lineWidths = new TIntArrayList();
    for (String lineText : StringUtil.split(updatedText, "<br/>")) {
      String html = HintUtil.prepareHintText(lineText, HintUtil.getInformationHint());
      int width = new JLabel(html).getPreferredSize().width;
      maxLineWidth = Math.max(maxLineWidth, width);
      lineWidths.add(width);
    }

    if (!lineWidths.isEmpty()) {
      int firstLineAvailableTrailingWidth = maxLineWidth - lineWidths.get(0);
      if (firstLineAvailableTrailingWidth >= buttonWidth) {
        return 0;
      } else {
        return buttonWidth - firstLineAvailableTrailingWidth;
      }
    }
    return 0;
  }
예제 #24
0
  private int updateMovedRegionEnd(
      final Document document,
      int movedLineStart,
      final int valueStart,
      @NotNull final MoveInfo info,
      final boolean down) {
    final int line = document.getLineNumber(valueStart);
    final LineRange toMove = info.toMove;
    int delta = line - toMove.endLine;
    info.toMove = new LineRange(toMove.startLine, Math.max(line, toMove.endLine));

    // update moved range
    if (delta > 0 && down) {
      final LineRange toMove2 = info.toMove2;
      info.toMove2 =
          new LineRange(
              toMove2.startLine + delta,
              Math.min(toMove2.endLine + delta, document.getLineCount() - 1));
      movedLineStart = document.getLineStartOffset(toMove.startLine);
    }
    return movedLineStart;
  }
  protected static void checkAccessStaticLevels(
      @NotNull List<CandidateInfo> conflicts, boolean checkAccessible) {
    int conflictsCount = conflicts.size();

    int maxCheckLevel = -1;
    int[] checkLevels = new int[conflictsCount];
    int index = 0;
    for (final CandidateInfo conflict : conflicts) {
      ProgressManager.checkCanceled();
      final MethodCandidateInfo method = (MethodCandidateInfo) conflict;
      final int level = checkAccessible ? getCheckAccessLevel(method) : getCheckStaticLevel(method);
      checkLevels[index++] = level;
      maxCheckLevel = Math.max(maxCheckLevel, level);
    }

    for (int i = conflictsCount - 1; i >= 0; i--) {
      // check for level
      if (checkLevels[i] < maxCheckLevel) {
        conflicts.remove(i);
      }
    }
  }
예제 #26
0
    @NotNull
    @Override
    public Comparable weigh(@NotNull LookupElement element) {
      final Object object = element.getObject();

      final String name = getLookupObjectName(object);
      if (name != null) {
        int max = 0;
        final List<String> wordsNoDigits = NameUtil.nameToWordsLowerCase(truncDigits(name));
        for (ExpectedTypeInfo myExpectedInfo : myExpectedTypes) {
          String expectedName = ((ExpectedTypeInfoImpl) myExpectedInfo).getExpectedName().compute();
          if (expectedName != null) {
            final THashSet<String> set =
                new THashSet<String>(NameUtil.nameToWordsLowerCase(truncDigits(expectedName)));
            set.retainAll(wordsNoDigits);
            max = Math.max(max, set.size());
          }
        }
        return -max;
      }
      return 0;
    }
예제 #27
0
 public int getEmptyLinesBetween(
     @NotNull PsiImportStatementBase statement1, @NotNull PsiImportStatementBase statement2) {
   int index1 = findEntryIndex(statement1);
   int index2 = findEntryIndex(statement2);
   if (index1 == index2) return 0;
   if (index1 > index2) {
     int t = index1;
     index1 = index2;
     index2 = t;
   }
   Entry[] entries = mySettings.IMPORT_LAYOUT_TABLE.getEntries();
   int maxSpace = 0;
   for (int i = index1 + 1; i < index2; i++) {
     if (entries[i] instanceof EmptyLineEntry) {
       int space = 0;
       do {
         space++;
       } while (entries[++i] instanceof EmptyLineEntry);
       maxSpace = Math.max(maxSpace, space);
     }
   }
   return maxSpace;
 }
예제 #28
0
 /**
  * Returns number of different parameters in i18n message. For example, for string <i>Class {0}
  * info: Class {0} extends class {1} and implements interface {2}</i> number of parameters is 3.
  *
  * @param expression i18n literal
  * @return number of parameters
  */
 public static int getPropertyValueParamsMaxCount(final PsiLiteralExpression expression) {
   int maxCount = -1;
   for (PsiReference reference : expression.getReferences()) {
     if (reference instanceof PsiPolyVariantReference) {
       for (ResolveResult result : ((PsiPolyVariantReference) reference).multiResolve(false)) {
         if (result.isValidResult() && result.getElement() instanceof IProperty) {
           String value = ((IProperty) result.getElement()).getValue();
           MessageFormat format;
           try {
             format = new MessageFormat(value);
           } catch (Exception e) {
             continue; // ignore syntax error
           }
           try {
             int count = format.getFormatsByArgumentIndex().length;
             maxCount = Math.max(maxCount, count);
           } catch (IllegalArgumentException ignored) {
           }
         }
       }
     }
   }
   return maxCount;
 }
  /**
   * This method searches ast node that could be reparsed incrementally and returns pair of target
   * reparseable node and new replacement node. Returns null if there is no any chance to make
   * incremental parsing.
   */
  @Nullable
  public Couple<ASTNode> findReparseableRoots(
      @NotNull PsiFileImpl file,
      @NotNull TextRange changedPsiRange,
      @NotNull CharSequence newFileText) {
    Project project = file.getProject();
    final FileElement fileElement = file.getTreeElement();
    final CharTable charTable = fileElement.getCharTable();
    int lengthShift = newFileText.length() - fileElement.getTextLength();

    if (fileElement.getElementType() instanceof ITemplateDataElementType || isTooDeep(file)) {
      // unable to perform incremental reparse for template data in JSP, or in exceptionally deep
      // trees
      return null;
    }

    final ASTNode leafAtStart =
        fileElement.findLeafElementAt(Math.max(0, changedPsiRange.getStartOffset() - 1));
    final ASTNode leafAtEnd =
        fileElement.findLeafElementAt(
            Math.min(changedPsiRange.getEndOffset(), fileElement.getTextLength() - 1));
    ASTNode node =
        leafAtStart != null && leafAtEnd != null
            ? TreeUtil.findCommonParent(leafAtStart, leafAtEnd)
            : fileElement;
    Language baseLanguage = file.getViewProvider().getBaseLanguage();

    while (node != null && !(node instanceof FileElement)) {
      IElementType elementType = node.getElementType();
      if (elementType instanceof IReparseableElementType) {
        final TextRange textRange = node.getTextRange();
        final IReparseableElementType reparseable = (IReparseableElementType) elementType;

        if (baseLanguage.isKindOf(reparseable.getLanguage())
            && textRange.getLength() + lengthShift > 0) {
          final int start = textRange.getStartOffset();
          final int end = start + textRange.getLength() + lengthShift;
          if (end > newFileText.length()) {
            reportInconsistentLength(file, newFileText, node, start, end);
            break;
          }

          CharSequence newTextStr = newFileText.subSequence(start, end);

          if (reparseable.isParsable(node.getTreeParent(), newTextStr, baseLanguage, project)) {
            ASTNode chameleon = reparseable.createNode(newTextStr);
            if (chameleon != null) {
              DummyHolder holder =
                  DummyHolderFactory.createHolder(
                      file.getManager(), null, node.getPsi(), charTable);
              holder.getTreeElement().rawAddChildren((TreeElement) chameleon);

              if (holder.getTextLength() != newTextStr.length()) {
                String details =
                    ApplicationManager.getApplication().isInternal()
                        ? "text=" + newTextStr + "; treeText=" + holder.getText() + ";"
                        : "";
                LOG.error("Inconsistent reparse: " + details + " type=" + elementType);
              }

              return Couple.of(node, chameleon);
            }
          }
        }
      }
      node = node.getTreeParent();
    }
    return null;
  }
  private List<PostponedAction> normalizeAndReorderPostponedActions(
      final TreeSet<PostprocessFormattingTask> rangesToProcess, Document document) {
    final List<PostprocessFormattingTask> freeFormatingActions =
        new ArrayList<PostprocessFormattingTask>();
    final List<ReindentTask> indentActions = new ArrayList<ReindentTask>();

    PostprocessFormattingTask accumulatedTask = null;
    Iterator<PostprocessFormattingTask> iterator = rangesToProcess.iterator();
    while (iterator.hasNext()) {
      final PostprocessFormattingTask currentTask = iterator.next();
      if (accumulatedTask == null) {
        accumulatedTask = currentTask;
        iterator.remove();
      } else if (accumulatedTask.getStartOffset() > currentTask.getEndOffset()
          || accumulatedTask.getStartOffset() == currentTask.getEndOffset()
              && !canStickActionsTogether(accumulatedTask, currentTask)) {
        // action can be pushed
        if (accumulatedTask instanceof ReindentTask) {
          indentActions.add((ReindentTask) accumulatedTask);
        } else {
          freeFormatingActions.add(accumulatedTask);
        }

        accumulatedTask = currentTask;
        iterator.remove();
      } else if (accumulatedTask instanceof ReformatTask && currentTask instanceof ReindentTask) {
        // split accumulated reformat range into two
        if (accumulatedTask.getStartOffset() < currentTask.getStartOffset()) {
          final RangeMarker endOfRange =
              document.createRangeMarker(
                  accumulatedTask.getStartOffset(), currentTask.getStartOffset());
          // add heading reformat part
          rangesToProcess.add(new ReformatTask(endOfRange));
          // and manage heading whitespace because formatter does not edit it in previous action
          iterator = rangesToProcess.iterator();
          //noinspection StatementWithEmptyBody
          while (iterator.next().getRange() != currentTask.getRange()) ;
        }
        final RangeMarker rangeToProcess =
            document.createRangeMarker(currentTask.getEndOffset(), accumulatedTask.getEndOffset());
        freeFormatingActions.add(new ReformatWithHeadingWhitespaceTask(rangeToProcess));
        accumulatedTask = currentTask;
        iterator.remove();
      } else {
        if (!(accumulatedTask instanceof ReindentTask)) {
          iterator.remove();

          boolean withLeadingWhitespace =
              accumulatedTask instanceof ReformatWithHeadingWhitespaceTask;
          if (accumulatedTask instanceof ReformatTask
              && currentTask instanceof ReformatWithHeadingWhitespaceTask
              && accumulatedTask.getStartOffset() == currentTask.getStartOffset()) {
            withLeadingWhitespace = true;
          } else if (accumulatedTask instanceof ReformatWithHeadingWhitespaceTask
              && currentTask instanceof ReformatTask
              && accumulatedTask.getStartOffset() < currentTask.getStartOffset()) {
            withLeadingWhitespace = false;
          }
          int newStart = Math.min(accumulatedTask.getStartOffset(), currentTask.getStartOffset());
          int newEnd = Math.max(accumulatedTask.getEndOffset(), currentTask.getEndOffset());
          RangeMarker rangeMarker;

          if (accumulatedTask.getStartOffset() == newStart
              && accumulatedTask.getEndOffset() == newEnd) {
            rangeMarker = accumulatedTask.getRange();
          } else if (currentTask.getStartOffset() == newStart
              && currentTask.getEndOffset() == newEnd) {
            rangeMarker = currentTask.getRange();
          } else {
            rangeMarker = document.createRangeMarker(newStart, newEnd);
          }

          if (withLeadingWhitespace) {
            accumulatedTask = new ReformatWithHeadingWhitespaceTask(rangeMarker);
          } else {
            accumulatedTask = new ReformatTask(rangeMarker);
          }
        } else if (currentTask instanceof ReindentTask) {
          iterator.remove();
        } // TODO[ik]: need to be fixed to correctly process indent inside indent
      }
    }
    if (accumulatedTask != null) {
      if (accumulatedTask instanceof ReindentTask) {
        indentActions.add((ReindentTask) accumulatedTask);
      } else {
        freeFormatingActions.add(accumulatedTask);
      }
    }

    final List<PostponedAction> result = new ArrayList<PostponedAction>();
    Collections.reverse(freeFormatingActions);
    Collections.reverse(indentActions);

    if (!freeFormatingActions.isEmpty()) {
      FormatTextRanges ranges = new FormatTextRanges();
      for (PostprocessFormattingTask action : freeFormatingActions) {
        TextRange range = TextRange.create(action);
        ranges.add(range, action instanceof ReformatWithHeadingWhitespaceTask);
      }
      result.add(new ReformatRangesAction(ranges));
    }

    if (!indentActions.isEmpty()) {
      ReindentRangesAction reindentRangesAction = new ReindentRangesAction();
      for (ReindentTask action : indentActions) {
        reindentRangesAction.add(action.getRange(), action.getOldIndent());
      }
      result.add(reindentRangesAction);
    }

    return result;
  }