예제 #1
0
 @Nullable
 public static String getReferencePrefix(@NotNull PsiElement insertedElement, int offsetInFile) {
   final PsiReference ref = insertedElement.getContainingFile().findReferenceAt(offsetInFile);
   if (ref != null) {
     final PsiElement element = ref.getElement();
     final int endIndex = offsetInFile - element.getTextRange().getStartOffset();
     final int beginIndex = ref.getRangeInElement().getStartOffset();
     if (beginIndex > endIndex) {
       LOG.error(
           "Inconsistent reference (found at offset not included in its range): ref="
               + ref
               + " element="
               + element
               + " text="
               + element.getText());
     }
     if (beginIndex < 0) {
       LOG.error(
           "Inconsistent reference (begin < 0): ref="
               + ref
               + " element="
               + element
               + "; begin="
               + beginIndex
               + " text="
               + element.getText());
     }
     LOG.assertTrue(endIndex >= 0);
     return element.getText().substring(beginIndex, endIndex);
   }
   return null;
 }
  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;
      }
    };
  }
예제 #3
0
 @Override
 protected void previewRefactoring(@NotNull final UsageInfo[] usages) {
   MigrationPanel panel = new MigrationPanel(myRoot, myLabeler, myProject, isPreviewUsages());
   String name;
   if (myRoot.length == 1) {
     String fromType =
         assertNotNull(TypeMigrationLabeler.getElementType(myRoot[0])).getPresentableText();
     String toType = myRootTypes.fun(myRoot[0]).getPresentableText();
     String text;
     text = getPresentation(myRoot[0]);
     name = "Migrate Type of " + text + " from \'" + fromType + "\' to \'" + toType + "\'";
   } else {
     final int rootsInPresentationCount =
         myRoot.length > MAX_ROOT_IN_PREVIEW_PRESENTATION
             ? MAX_ROOT_IN_PREVIEW_PRESENTATION
             : myRoot.length;
     String[] rootsPresentation = new String[rootsInPresentationCount];
     for (int i = 0; i < rootsInPresentationCount; i++) {
       final PsiElement root = myRoot[i];
       rootsPresentation[i] =
           root instanceof PsiNamedElement ? ((PsiNamedElement) root).getName() : root.getText();
     }
     rootsPresentation = StringUtil.surround(rootsPresentation, "\'", "\'");
     name = "Migrate Type of " + StringUtil.join(rootsPresentation, ", ");
     if (myRoot.length > MAX_ROOT_IN_PREVIEW_PRESENTATION) {
       name += "...";
     }
   }
   Content content =
       UsageViewManager.getInstance(myProject).addContent(name, false, panel, true, true);
   panel.setContent(content);
   ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.FIND).activate(null);
 }
예제 #4
0
 public static boolean isStringPsiLiteral(PsiElement element) {
   if (element instanceof PsiLiteralExpression) {
     final String text = element.getText();
     return StringUtil.isQuotedString(text);
   }
   return false;
 }
예제 #5
0
  @NotNull
  public static String getElementTextWithContext(@NotNull JetElement element) {
    if (element instanceof JetFile) {
      return element.getContainingFile().getText();
    }

    // Find parent for element among file children
    PsiElement inFileParent =
        PsiTreeUtil.findFirstParent(
            element,
            new Condition<PsiElement>() {
              @Override
              public boolean value(PsiElement parentCandidate) {
                return parentCandidate != null && parentCandidate.getParent() instanceof JetFile;
              }
            });

    assert inFileParent != null
        : "For non-file element we should always be able to find parent in file children";

    int startContextOffset = inFileParent.getTextRange().getStartOffset();
    int elementContextOffset = element.getTextRange().getStartOffset();

    int inFileParentOffset = elementContextOffset - startContextOffset;

    return new StringBuilder(inFileParent.getText())
        .insert(inFileParentOffset, "<caret>")
        .toString();
  }
  protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) {
    final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();

    checkExistingMethods(conflicts, true);
    checkExistingMethods(conflicts, false);
    final Collection<PsiClass> classes = ClassInheritorsSearch.search(myClass).findAll();
    for (FieldDescriptor fieldDescriptor : myFieldDescriptors) {
      final Set<PsiMethod> setters = new HashSet<PsiMethod>();
      final Set<PsiMethod> getters = new HashSet<PsiMethod>();

      for (PsiClass aClass : classes) {
        final PsiMethod getterOverrider =
            myDescriptor.isToEncapsulateGet()
                ? aClass.findMethodBySignature(fieldDescriptor.getGetterPrototype(), false)
                : null;
        if (getterOverrider != null) {
          getters.add(getterOverrider);
        }
        final PsiMethod setterOverrider =
            myDescriptor.isToEncapsulateSet()
                ? aClass.findMethodBySignature(fieldDescriptor.getSetterPrototype(), false)
                : null;
        if (setterOverrider != null) {
          setters.add(setterOverrider);
        }
      }
      if (!getters.isEmpty() || !setters.isEmpty()) {
        final PsiField field = fieldDescriptor.getField();
        for (PsiReference reference : ReferencesSearch.search(field)) {
          final PsiElement place = reference.getElement();
          if (place instanceof PsiReferenceExpression) {
            final PsiExpression qualifierExpression =
                ((PsiReferenceExpression) place).getQualifierExpression();
            final PsiClass ancestor;
            if (qualifierExpression == null) {
              ancestor = PsiTreeUtil.getParentOfType(place, PsiClass.class, false);
            } else {
              ancestor = PsiUtil.resolveClassInType(qualifierExpression.getType());
            }

            final boolean isGetter = !PsiUtil.isAccessedForWriting((PsiExpression) place);
            for (PsiMethod overridden : isGetter ? getters : setters) {
              if (InheritanceUtil.isInheritorOrSelf(myClass, ancestor, true)) {
                conflicts.putValue(
                    overridden,
                    "There is already a "
                        + RefactoringUIUtil.getDescription(overridden, true)
                        + " which would hide generated "
                        + (isGetter ? "getter" : "setter")
                        + " for "
                        + place.getText());
                break;
              }
            }
          }
        }
      }
    }
    return showConflicts(conflicts, refUsages.get());
  }
  public static String getPrevSiblingAsTextUntil(
      PsiElement psiElement, ElementPattern pattern, boolean includeMatching) {
    String prevText = "";

    for (PsiElement child = psiElement.getPrevSibling();
        child != null;
        child = child.getPrevSibling()) {
      if (pattern.accepts(child)) {
        if (includeMatching) {
          return child.getText() + prevText;
        }
        return prevText;
      } else {
        prevText = child.getText() + prevText;
      }
    }

    return prevText;
  }
  public PyType getType(@NotNull TypeEvalContext context, @NotNull TypeEvalContext.Key key) {
    if (!TypeEvalStack.mayEvaluate(this)) {
      return null;
    }
    try {
      final boolean qualified = isQualified();
      if (!qualified) {
        String name = getReferencedName();
        if (PyNames.NONE.equals(name)) {
          return PyNoneType.INSTANCE;
        }
      }
      PyType type = getTypeFromProviders(context);
      if (type != null) {
        return type;
      }
      if (qualified) {
        PyType maybe_type = PyUtil.getSpecialAttributeType(this, context);
        if (maybe_type != null) return maybe_type;
        Ref<PyType> typeOfProperty = getTypeOfProperty(context);
        if (typeOfProperty != null) {
          return typeOfProperty.get();
        }
      }
      final PsiPolyVariantReference reference =
          getReference(PyResolveContext.noImplicits().withTypeEvalContext(context));
      final List<PsiElement> targets = PyUtil.multiResolveTopPriority(reference);
      if (targets.isEmpty()) {
        return getQualifiedReferenceTypeByControlFlow(context);
      }

      final List<PyType> members = new ArrayList<PyType>();
      for (PsiElement target : targets) {
        if (target == this || target == null) {
          continue;
        }
        if (!target.isValid()) {
          LOG.error(
              "Reference "
                  + this
                  + " resolved to invalid element "
                  + target
                  + " (text="
                  + target.getText()
                  + ")");
          continue;
        }
        members.add(getTypeFromTarget(target, context, this));
      }

      return PyUnionType.union(members);
    } finally {
      TypeEvalStack.evaluated(this);
    }
  }
  private static void processParameterUsage(
      PsiReferenceExpression ref, String oldName, String newName)
      throws IncorrectOperationException {

    PsiElement last = ref.getReferenceNameElement();
    if (last instanceof PsiIdentifier && last.getText().equals(oldName)) {
      PsiElementFactory factory = JavaPsiFacade.getInstance(ref.getProject()).getElementFactory();
      PsiIdentifier newNameIdentifier = factory.createIdentifier(newName);
      last.replace(newNameIdentifier);
    }
  }
  /**
   * Try to visit possible class name for PsiElements with text like "Foo\|Bar", "Foo|\Bar",
   * "\Foo|\Bar" Cursor must have position in PsiElement
   *
   * @param psiElement the element context, cursor should be in it
   * @param cursorOffset current cursor editor eg from completion context
   * @param visitor callback on matching class
   */
  public static void visitNamespaceClassForCompletion(
      PsiElement psiElement, int cursorOffset, ClassForCompletionVisitor visitor) {

    int cursorOffsetClean = cursorOffset - psiElement.getTextOffset();
    if (cursorOffsetClean < 1) {
      return;
    }

    String content = psiElement.getText();
    int length = content.length();
    if (!(length >= cursorOffsetClean)) {
      return;
    }

    String beforeCursor = content.substring(0, cursorOffsetClean);
    boolean isValid;

    // espend\|Container, espend\Cont|ainer <- fallback to last full namespace
    // espend|\Container <- only on known namespace "espend"
    String namespace = beforeCursor;

    // if no backslash or its equal in first position, fallback on namespace completion
    int lastSlash = beforeCursor.lastIndexOf("\\");
    if (lastSlash <= 0) {
      isValid = PhpIndexUtil.hasNamespace(psiElement.getProject(), beforeCursor);
    } else {
      isValid = true;
      namespace = beforeCursor.substring(0, lastSlash);
    }

    if (!isValid) {
      return;
    }

    // format namespaces and add prefix for fluent completion
    String prefix = "";
    if (namespace.startsWith("\\")) {
      prefix = "\\";
    } else {
      namespace = "\\" + namespace;
    }

    // search classes in current namespace and child namespaces
    for (PhpClass phpClass :
        PhpIndexUtil.getPhpClassInsideNamespace(psiElement.getProject(), namespace)) {
      String presentableFQN = phpClass.getPresentableFQN();
      if (presentableFQN != null
          && fr.adrienbrault.idea.symfony2plugin.util.StringUtils.startWithEqualClassname(
              presentableFQN, beforeCursor)) {
        visitor.visit(phpClass, presentableFQN, prefix);
      }
    }
  }
  public FileReferenceSet(final @NotNull PsiElement element) {

    myElement = element;
    TextRange range = ElementManipulators.getValueTextRange(element);
    myStartInElement = range.getStartOffset();
    myPathStringNonTrimmed = range.substring(element.getText());
    myPathString = myPathStringNonTrimmed.trim();
    myEndingSlashNotAllowed = true;
    myCaseSensitive = false;

    reparse();
  }
  private static void processMethodUsage(
      PsiElement ref,
      JavaChangeInfo changeInfo,
      boolean toChangeArguments,
      boolean toCatchExceptions,
      PsiMethod callee,
      PsiSubstitutor subsitutor,
      final UsageInfo[] usages)
      throws IncorrectOperationException {
    if (changeInfo.isNameChanged()) {
      if (ref instanceof PsiJavaCodeReferenceElement) {
        PsiElement last = ((PsiJavaCodeReferenceElement) ref).getReferenceNameElement();
        if (last instanceof PsiIdentifier && last.getText().equals(changeInfo.getOldName())) {
          last.replace(changeInfo.getNewNameIdentifier());
        }
      }
    }

    final PsiMethod caller = RefactoringUtil.getEnclosingMethod(ref);
    if (toChangeArguments) {
      final PsiExpressionList list = RefactoringUtil.getArgumentListByMethodReference(ref);
      LOG.assertTrue(list != null);
      boolean toInsertDefaultValue = needDefaultValue(changeInfo, caller);
      if (toInsertDefaultValue && ref instanceof PsiReferenceExpression) {
        final PsiExpression qualifierExpression =
            ((PsiReferenceExpression) ref).getQualifierExpression();
        if (qualifierExpression instanceof PsiSuperExpression
            && callerSignatureIsAboutToChangeToo(caller, usages)) {
          toInsertDefaultValue = false;
        }
      }

      fixActualArgumentsList(list, changeInfo, toInsertDefaultValue, subsitutor);
    }

    if (toCatchExceptions) {
      if (!(ref instanceof PsiReferenceExpression
          && ((PsiReferenceExpression) ref).getQualifierExpression()
              instanceof PsiSuperExpression)) {
        if (needToCatchExceptions(changeInfo, caller)) {
          PsiClassType[] newExceptions =
              callee != null
                  ? getCalleeChangedExceptionInfo(callee)
                  : getPrimaryChangedExceptionInfo(changeInfo);
          fixExceptions(ref, newExceptions);
        }
      }
    }
  }
예제 #13
0
  protected static String findPrefixDefault(
      final PsiElement insertedElement, final int offset, @NotNull final ElementPattern trimStart) {
    String substr =
        insertedElement
            .getText()
            .substring(0, offset - insertedElement.getTextRange().getStartOffset());
    if (substr.length() == 0 || Character.isWhitespace(substr.charAt(substr.length() - 1)))
      return "";

    substr = substr.trim();

    int i = 0;
    while (substr.length() > i && trimStart.accepts(substr.charAt(i))) i++;
    return substr.substring(i).trim();
  }
예제 #14
0
 public static String getPresentation(PsiElement element) {
   String text;
   if (element instanceof PsiField) {
     text = "field \'" + ((PsiField) element).getName() + "\'";
   } else if (element instanceof PsiParameter) {
     text = "parameter \'" + ((PsiParameter) element).getName() + "\'";
   } else if (element instanceof PsiLocalVariable) {
     text = "variable \'" + ((PsiLocalVariable) element).getName() + "\'";
   } else if (element instanceof PsiMethod) {
     text = "method \'" + ((PsiMethod) element).getName() + "\' return";
   } else {
     text = element.getText();
   }
   return text;
 }
  @Override
  @Nullable
  public String getReferenceName() {
    PsiElement nameElement = getReferenceNameElement();
    if (nameElement != null) {
      IElementType nodeType = nameElement.getNode().getElementType();
      if (TokenSets.STRING_LITERAL_SET.contains(nodeType)) {
        final Object value = GrLiteralImpl.getLiteralValue(nameElement);
        if (value instanceof String) {
          return (String) value;
        }
      }

      return nameElement.getText();
    }
    return null;
  }
 @Nullable
 private static PsiMethod getOverridingConstructorOfSuperCall(final PsiElement element) {
   if (element instanceof PsiReferenceExpression && "super".equals(element.getText())) {
     PsiElement parent = element.getParent();
     if (parent instanceof PsiMethodCallExpression) {
       parent = parent.getParent();
       if (parent instanceof PsiExpressionStatement) {
         parent = parent.getParent();
         if (parent instanceof PsiCodeBlock) {
           parent = parent.getParent();
           if (parent instanceof PsiMethod && ((PsiMethod) parent).isConstructor()) {
             return (PsiMethod) parent;
           }
         }
       }
     }
   }
   return null;
 }
예제 #17
0
  private JavaResolveResult doAdvancedResolve() {
    final PsiElement psiElement = getElement();

    if (!psiElement.isValid()) return JavaResolveResult.EMPTY;

    final String elementText = psiElement.getText();

    final PsiElement context = getContext();
    if (context instanceof PsiClass) {
      if (isStaticClassReference(elementText, false)) {
        final PsiClass psiClass =
            ((PsiClass) context).findInnerClassByName(getCanonicalText(), false);
        if (psiClass != null)
          return new ClassCandidateInfo(psiClass, PsiSubstitutor.EMPTY, false, psiElement);
        PsiElement member = doResolveMember((PsiClass) context, myText);
        return member == null
            ? JavaResolveResult.EMPTY
            : new CandidateInfo(member, PsiSubstitutor.EMPTY, false, false, psiElement);
      } else if (!myInStaticImport && myJavaClassReferenceSet.isAllowDollarInNames()) {
        return JavaResolveResult.EMPTY;
      }
    }

    final int endOffset = getRangeInElement().getEndOffset();
    LOG.assertTrue(endOffset <= elementText.length(), elementText);
    final int startOffset =
        myJavaClassReferenceSet.getReference(0).getRangeInElement().getStartOffset();
    final String qName = elementText.substring(startOffset, endOffset);
    if (!qName.contains(".")) {
      final String defaultPackage =
          JavaClassReferenceProvider.DEFAULT_PACKAGE.getValue(getOptions());
      if (StringUtil.isNotEmpty(defaultPackage)) {
        final JavaResolveResult resolveResult =
            advancedResolveInner(psiElement, defaultPackage + "." + qName);
        if (resolveResult != JavaResolveResult.EMPTY) {
          return resolveResult;
        }
      }
    }
    return advancedResolveInner(psiElement, qName);
  }
예제 #18
0
  public void testGroupByValuesCorrectLeaves() throws Exception {
    SliceTreeStructure treeStructure = configureTree("DuplicateLeaves");
    SliceRootNode root = (SliceRootNode) treeStructure.getRootElement();
    Map<SliceNode, Collection<PsiElement>> map = SliceLeafAnalyzer.createMap();
    Collection<PsiElement> leaves = SliceLeafAnalyzer.calcLeafExpressions(root, treeStructure, map);
    assertNotNull(leaves);
    assertEquals(1, leaves.size());
    PsiElement leaf = leaves.iterator().next();
    assertTrue(leaf instanceof PsiLiteralExpression);
    assertEquals("\"oo\"", leaf.getText());

    SliceRootNode newRoot = SliceLeafAnalyzer.createTreeGroupedByValues(leaves, root, map);
    Collection<? extends AbstractTreeNode> children = newRoot.getChildren();
    assertEquals(1, children.size());
    SliceNode child = (SliceNode) children.iterator().next();
    assertTrue(child instanceof SliceLeafValueRootNode);

    children = child.getChildren();
    assertEquals(1, children.size());
    child = (SliceNode) children.iterator().next();
    assertTrue(child.getValue().getElement() instanceof PsiField);

    children = child.getChildren();
    assertEquals(1, children.size());
    child = (SliceNode) children.iterator().next();
    assertTrue(child.getValue().getElement() instanceof PsiReferenceExpression);

    children = child.getChildren();
    assertEquals(1, children.size());
    child = (SliceNode) children.iterator().next();
    assertTrue(child.getValue().getElement() instanceof PsiReferenceExpression);

    children = child.getChildren();
    assertEquals(1, children.size());
    child = (SliceNode) children.iterator().next();
    assertTrue(child.getValue().getElement() instanceof PsiLiteralExpression);
    assertEquals(child.getValue().getElement(), leaf);
  }
  /** "DateTime", DateTime::class */
  @Nullable
  public static PhpClass resolvePhpClassOnPsiElement(@NotNull PsiElement psiElement) {

    String dataClass = null;
    if (psiElement instanceof ClassConstantReference) {
      PsiElement lastChild = psiElement.getLastChild();
      // @TODO: FOO::class find PhpElementTyp: toString provides "class"
      if ("class".equals(lastChild.getText())) {
        PhpExpression classReference = ((ClassConstantReference) psiElement).getClassReference();
        if (classReference instanceof PhpReference) {
          dataClass = ((PhpReference) classReference).getFQN();
        }
      }
    } else {
      dataClass = getStringValue(psiElement);
    }

    if (dataClass == null) {
      return null;
    }

    return getClassInterface(psiElement.getProject(), dataClass);
  }
예제 #20
0
  private HashMap<PsiMethod, HashSet<PsiMethod>> buildConstructorsToSubConstructorsMap(
      final PsiMethod[] constructors) {
    final HashMap<PsiMethod, HashSet<PsiMethod>> constructorsToSubConstructors =
        new HashMap<PsiMethod, HashSet<PsiMethod>>();
    for (PsiMethod constructor : constructors) {
      final HashSet<PsiMethod> referencingSubConstructors = new HashSet<PsiMethod>();
      constructorsToSubConstructors.put(constructor, referencingSubConstructors);
      if (constructor != null) {
        // find references
        for (PsiReference reference :
            ReferencesSearch.search(constructor, new LocalSearchScope(mySourceClass), false)) {
          final PsiElement element = reference.getElement();
          if (element != null && "super".equals(element.getText())) {
            PsiMethod parentMethod = PsiTreeUtil.getParentOfType(element, PsiMethod.class);
            if (parentMethod != null && parentMethod.isConstructor()) {
              referencingSubConstructors.add(parentMethod);
            }
          }
        }
      }

      // check default constructor
      if (constructor == null || constructor.getParameterList().getParametersCount() == 0) {
        RefactoringUtil.visitImplicitSuperConstructorUsages(
            mySourceClass,
            new RefactoringUtil.ImplicitConstructorUsageVisitor() {
              public void visitConstructor(PsiMethod constructor, PsiMethod baseConstructor) {
                referencingSubConstructors.add(constructor);
              }

              public void visitClassWithoutConstructors(PsiClass aClass) {}
            },
            myTargetSuperClass);
      }
    }
    return constructorsToSubConstructors;
  }
예제 #21
0
 private static boolean hasExactImportStaticConflict(
     String qualifierClass, String memberName, PsiElement context) {
   final PsiFile file = context.getContainingFile();
   if (!(file instanceof PsiJavaFile)) {
     return false;
   }
   final PsiJavaFile javaFile = (PsiJavaFile) file;
   final PsiImportList importList = javaFile.getImportList();
   if (importList == null) {
     return false;
   }
   final PsiImportStaticStatement[] importStaticStatements =
       importList.getImportStaticStatements();
   for (PsiImportStaticStatement importStaticStatement : importStaticStatements) {
     if (importStaticStatement.isOnDemand()) {
       continue;
     }
     final String name = importStaticStatement.getReferenceName();
     if (!memberName.equals(name)) {
       continue;
     }
     final PsiJavaCodeReferenceElement importReference =
         importStaticStatement.getImportReference();
     if (importReference == null) {
       continue;
     }
     final PsiElement qualifier = importReference.getQualifier();
     if (qualifier == null) {
       continue;
     }
     final String qualifierText = qualifier.getText();
     if (!qualifierClass.equals(qualifierText)) {
       return true;
     }
   }
   return false;
 }
  public final RunnerResult analyzeMethod(
      @NotNull PsiElement psiBlock,
      InstructionVisitor visitor,
      boolean ignoreAssertions,
      @NotNull Collection<DfaMemoryState> initialStates) {
    try {
      prepareAnalysis(psiBlock, initialStates);

      final ControlFlow flow =
          createControlFlowAnalyzer().buildControlFlow(psiBlock, ignoreAssertions);
      if (flow == null) return RunnerResult.NOT_APPLICABLE;

      int endOffset = flow.getInstructionCount();
      myInstructions = flow.getInstructions();
      myFields = flow.getFields();
      myNestedClosures.clear();

      if (LOG.isDebugEnabled()) {
        LOG.debug("Analyzing code block: " + psiBlock.getText());
        for (int i = 0; i < myInstructions.length; i++) {
          Instruction instruction = myInstructions[i];
          LOG.debug(i + ": " + instruction.toString());
        }
      }

      Integer tooExpensiveHash = psiBlock.getUserData(TOO_EXPENSIVE_HASH);
      if (tooExpensiveHash != null && tooExpensiveHash == psiBlock.getText().hashCode()) {
        LOG.debug("Too complex because hasn't changed since being too complex already");
        return RunnerResult.TOO_COMPLEX;
      }

      final ArrayList<DfaInstructionState> queue = new ArrayList<DfaInstructionState>();
      for (final DfaMemoryState initialState : initialStates) {
        queue.add(new DfaInstructionState(myInstructions[0], initialState));
      }

      long timeLimit = ourTimeLimit;
      final boolean unitTestMode = ApplicationManager.getApplication().isUnitTestMode();
      WorkingTimeMeasurer measurer = new WorkingTimeMeasurer(timeLimit);
      int count = 0;
      while (!queue.isEmpty()) {
        if (count % 50 == 0 && !unitTestMode && measurer.isTimeOver()) {
          LOG.debug("Too complex because the analysis took too long");
          psiBlock.putUserData(TOO_EXPENSIVE_HASH, psiBlock.getText().hashCode());
          return RunnerResult.TOO_COMPLEX;
        }
        ProgressManager.checkCanceled();

        DfaInstructionState instructionState = queue.remove(0);
        if (LOG.isDebugEnabled()) {
          LOG.debug(instructionState.toString());
        }
        // System.out.println(instructionState.toString());

        Instruction instruction = instructionState.getInstruction();
        long distance = instructionState.getDistanceFromStart();

        if (instruction instanceof BranchingInstruction) {
          if (!instruction.setMemoryStateProcessed(
              instructionState.getMemoryState().createCopy())) {
            LOG.debug("Too complex because too many different possible states");
            return RunnerResult.TOO_COMPLEX; // Too complex :(
          }
        }

        DfaInstructionState[] after = acceptInstruction(visitor, instructionState);
        for (DfaInstructionState state : after) {
          Instruction nextInstruction = state.getInstruction();
          if ((!(nextInstruction instanceof BranchingInstruction)
                  || !nextInstruction.isMemoryStateProcessed(state.getMemoryState()))
              && instruction.getIndex() < endOffset) {
            state.setDistanceFromStart(distance + 1);
            queue.add(state);
          }
        }

        count++;
      }

      psiBlock.putUserData(TOO_EXPENSIVE_HASH, null);
      LOG.debug("Analysis ok");
      return RunnerResult.OK;
    } catch (ArrayIndexOutOfBoundsException e) {
      LOG.error(psiBlock.getText(), e); // TODO fix in better times
      return RunnerResult.ABORTED;
    } catch (EmptyStackException e) {
      if (LOG.isDebugEnabled()) {
        LOG.error(e); // TODO fix in better times
      }
      return RunnerResult.ABORTED;
    }
  }
예제 #23
0
  public static boolean areParenthesesNecessary(
      @NotNull JetExpression innerExpression,
      @NotNull JetExpression currentInner,
      @NotNull JetExpression parentExpression) {
    if (parentExpression instanceof JetParenthesizedExpression
        || innerExpression instanceof JetParenthesizedExpression) {
      return false;
    }

    if (parentExpression instanceof JetWhenExpression
        || innerExpression instanceof JetWhenExpression) {
      return false;
    }

    if (innerExpression instanceof JetIfExpression) {
      PsiElement current = parentExpression;

      while (!(current instanceof JetBlockExpression
          || current instanceof JetDeclaration
          || current instanceof JetStatementExpression)) {
        if (current.getTextRange().getEndOffset() != currentInner.getTextRange().getEndOffset()) {
          return current.getText().charAt(current.getTextLength() - 1)
              != ')'; // if current expression is "guarded" by parenthesis, no extra parenthesis is
                      // necessary
        }

        current = current.getParent();
      }
    }

    IElementType innerOperation = getOperation(innerExpression);
    IElementType parentOperation = getOperation(parentExpression);

    // 'return (@label{...})' case
    if (parentExpression instanceof JetReturnExpression
        && innerOperation == JetTokens.LABEL_IDENTIFIER) {
      return true;
    }

    // '(x: Int) < y' case
    if (innerExpression instanceof JetBinaryExpressionWithTypeRHS
        && parentOperation == JetTokens.LT) {
      return true;
    }

    int innerPriority = getPriority(innerExpression);
    int parentPriority = getPriority(parentExpression);

    if (innerPriority == parentPriority) {
      if (parentExpression instanceof JetBinaryExpression) {
        if (innerOperation == JetTokens.ANDAND || innerOperation == JetTokens.OROR) {
          return false;
        }
        return ((JetBinaryExpression) parentExpression).getRight() == currentInner;
      }

      // '-(-x)' case
      if (parentExpression instanceof JetPrefixExpression
          && innerExpression instanceof JetPrefixExpression) {
        return innerOperation == parentOperation
            && (innerOperation == JetTokens.PLUS || innerOperation == JetTokens.MINUS);
      }
      return false;
    }

    return innerPriority < parentPriority;
  }
예제 #24
0
 @NotNull
 public static String getText(@Nullable PsiElement element) {
   return element != null ? element.getText() : "";
 }
예제 #25
0
 @Nullable
 public static String getNullableText(@Nullable PsiElement element) {
   return element != null ? element.getText() : null;
 }
  @Override
  public void writeExternal(Element element) throws WriteExternalException {
    PsiDocumentManager.getInstance(myProject).commitAllDocuments();

    if (myPsiElements.isEmpty() && myRangeMarkers.isEmpty() && mySerializedElements.isEmpty()) {
      throw new WriteExternalException();
    }

    if (mySerializedElements.isEmpty()) {
      for (SmartPsiElementPointer<PsiElement> ptr : myPsiElements) {
        PsiElement psiElement = ptr.getElement();
        if (psiElement == null || !psiElement.isValid()) {
          continue;
        }
        FoldingInfo fi = psiElement.getUserData(FOLDING_INFO_KEY);
        boolean state = fi != null && fi.expanded;
        String signature = FoldingPolicy.getSignature(psiElement);
        if (signature == null) {
          continue;
        }

        PsiFile containingFile = psiElement.getContainingFile();
        PsiElement restoredElement = FoldingPolicy.restoreBySignature(containingFile, signature);
        if (!psiElement.equals(restoredElement)) {
          StringBuilder trace = new StringBuilder();
          PsiElement restoredAgain =
              FoldingPolicy.restoreBySignature(containingFile, signature, trace);
          LOG.error(
              "element: "
                  + psiElement
                  + "("
                  + psiElement.getText()
                  + "); restoredElement: "
                  + restoredElement
                  + "; signature: '"
                  + signature
                  + "'; file: "
                  + containingFile
                  + "; injected: "
                  + InjectedLanguageManager.getInstance(myProject)
                      .isInjectedFragment(containingFile)
                  + "; languages: "
                  + containingFile.getViewProvider().getLanguages()
                  + "; restored again: "
                  + restoredAgain
                  + "; restore produces same results: "
                  + (restoredAgain == restoredElement)
                  + "; trace:\n"
                  + trace);
        }

        Element e = new Element(ELEMENT_TAG);
        e.setAttribute(SIGNATURE_ATT, signature);
        e.setAttribute(EXPANDED_ATT, Boolean.toString(state));
        element.addContent(e);
      }
    } else {
      // get back postponed state (before folding initialization)
      for (SerializedPsiElement entry : mySerializedElements) {
        Element e = new Element(ELEMENT_TAG);
        e.setAttribute(SIGNATURE_ATT, entry.mySerializedElement);
        e.setAttribute(EXPANDED_ATT, Boolean.toString(entry.myFoldingInfo.getExpanded()));
        element.addContent(e);
      }
    }
    String date = null;
    for (RangeMarker marker : myRangeMarkers) {
      FoldingInfo fi = marker.getUserData(FOLDING_INFO_KEY);
      boolean state = fi != null && fi.expanded;

      Element e = new Element(MARKER_TAG);
      if (date == null) {
        date = getTimeStamp();
      }
      if (date.isEmpty()) {
        continue;
      }

      e.setAttribute(DATE_ATT, date);
      e.setAttribute(EXPANDED_ATT, Boolean.toString(state));
      String signature =
          Integer.valueOf(marker.getStartOffset()) + ":" + Integer.valueOf(marker.getEndOffset());
      e.setAttribute(SIGNATURE_ATT, signature);
      String placeHolderText = fi == null ? DEFAULT_PLACEHOLDER : fi.placeHolder;
      e.setAttribute(PLACEHOLDER_ATT, placeHolderText);
      element.addContent(e);
    }
  }
  public static boolean checkConsistency(PsiFile psiFile, Document document) {
    // todo hack
    if (psiFile.getVirtualFile() == null) return true;

    CharSequence editorText = document.getCharsSequence();
    int documentLength = document.getTextLength();
    if (psiFile.textMatches(editorText)) {
      LOG.assertTrue(psiFile.getTextLength() == documentLength);
      return true;
    }

    char[] fileText = psiFile.textToCharArray();
    @SuppressWarnings({"NonConstantStringShouldBeStringBuffer"})
    @NonNls
    String error =
        "File '"
            + psiFile.getName()
            + "' text mismatch after reparse. "
            + "File length="
            + fileText.length
            + "; Doc length="
            + documentLength
            + "\n";
    int i = 0;
    for (; i < documentLength; i++) {
      if (i >= fileText.length) {
        error += "editorText.length > psiText.length i=" + i + "\n";
        break;
      }
      if (i >= editorText.length()) {
        error += "editorText.length > psiText.length i=" + i + "\n";
        break;
      }
      if (editorText.charAt(i) != fileText[i]) {
        error += "first unequal char i=" + i + "\n";
        break;
      }
    }
    // error += "*********************************************" + "\n";
    // if (i <= 500){
    //  error += "Equal part:" + editorText.subSequence(0, i) + "\n";
    // }
    // else{
    //  error += "Equal part start:\n" + editorText.subSequence(0, 200) + "\n";
    //  error += "................................................" + "\n";
    //  error += "................................................" + "\n";
    //  error += "................................................" + "\n";
    //  error += "Equal part end:\n" + editorText.subSequence(i - 200, i) + "\n";
    // }
    error += "*********************************************" + "\n";
    error +=
        "Editor Text tail:("
            + (documentLength - i)
            + ")\n"; // + editorText.subSequence(i, Math.min(i + 300, documentLength)) + "\n";
    error += "*********************************************" + "\n";
    error += "Psi Text tail:(" + (fileText.length - i) + ")\n";
    error += "*********************************************" + "\n";

    if (document instanceof DocumentWindow) {
      error += "doc: '" + document.getText() + "'\n";
      error += "psi: '" + psiFile.getText() + "'\n";
      error += "ast: '" + psiFile.getNode().getText() + "'\n";
      error += psiFile.getLanguage() + "\n";
      PsiElement context =
          InjectedLanguageManager.getInstance(psiFile.getProject()).getInjectionHost(psiFile);
      if (context != null) {
        error += "context: " + context + "; text: '" + context.getText() + "'\n";
        error += "context file: " + context.getContainingFile() + "\n";
      }
      error +=
          "document window ranges: "
              + Arrays.asList(((DocumentWindow) document).getHostRanges())
              + "\n";
    }
    LOG.error(error);
    // document.replaceString(0, documentLength, psiFile.getText());
    return false;
  }
예제 #28
0
  @NotNull
  final RunnerResult analyzeMethod(
      @NotNull PsiElement psiBlock,
      @NotNull InstructionVisitor visitor,
      boolean ignoreAssertions,
      @NotNull Collection<DfaMemoryState> initialStates) {
    if (PsiTreeUtil.findChildOfType(psiBlock, OuterLanguageElement.class) != null)
      return RunnerResult.NOT_APPLICABLE;

    try {
      final ControlFlow flow =
          new ControlFlowAnalyzer(myValueFactory, psiBlock, ignoreAssertions).buildControlFlow();
      if (flow == null) return RunnerResult.NOT_APPLICABLE;
      int[] loopNumber = LoopAnalyzer.calcInLoop(flow);

      int endOffset = flow.getInstructionCount();
      myInstructions = flow.getInstructions();
      myNestedClosures.clear();

      Set<Instruction> joinInstructions = ContainerUtil.newHashSet();
      for (int index = 0; index < myInstructions.length; index++) {
        Instruction instruction = myInstructions[index];
        if (instruction instanceof GotoInstruction) {
          joinInstructions.add(myInstructions[((GotoInstruction) instruction).getOffset()]);
        } else if (instruction instanceof ConditionalGotoInstruction) {
          joinInstructions.add(
              myInstructions[((ConditionalGotoInstruction) instruction).getOffset()]);
        } else if (instruction instanceof MethodCallInstruction
            && !((MethodCallInstruction) instruction).getContracts().isEmpty()) {
          joinInstructions.add(myInstructions[index + 1]);
        }
      }

      if (LOG.isDebugEnabled()) {
        LOG.debug("Analyzing code block: " + psiBlock.getText());
        for (int i = 0; i < myInstructions.length; i++) {
          LOG.debug(i + ": " + myInstructions[i]);
        }
      }
      // for (int i = 0; i < myInstructions.length; i++) System.out.println(i + ": " +
      // myInstructions[i].toString());

      Integer tooExpensiveHash = psiBlock.getUserData(TOO_EXPENSIVE_HASH);
      if (tooExpensiveHash != null && tooExpensiveHash == psiBlock.getText().hashCode()) {
        LOG.debug("Too complex because hasn't changed since being too complex already");
        return RunnerResult.TOO_COMPLEX;
      }

      final StateQueue queue = new StateQueue();
      for (final DfaMemoryState initialState : initialStates) {
        queue.offer(new DfaInstructionState(myInstructions[0], initialState));
      }

      MultiMap<BranchingInstruction, DfaMemoryState> processedStates = MultiMap.createSet();
      MultiMap<BranchingInstruction, DfaMemoryState> incomingStates = MultiMap.createSet();

      long msLimit =
          shouldCheckTimeLimit()
              ? Registry.intValue("ide.dfa.time.limit.online")
              : Registry.intValue("ide.dfa.time.limit.offline");
      WorkingTimeMeasurer measurer = new WorkingTimeMeasurer(msLimit * 1000 * 1000);
      int count = 0;
      while (!queue.isEmpty()) {
        List<DfaInstructionState> states = queue.getNextInstructionStates(joinInstructions);
        for (DfaInstructionState instructionState : states) {
          if (count++ % 1024 == 0 && measurer.isTimeOver()) {
            LOG.debug("Too complex because the analysis took too long");
            psiBlock.putUserData(TOO_EXPENSIVE_HASH, psiBlock.getText().hashCode());
            return RunnerResult.TOO_COMPLEX;
          }
          ProgressManager.checkCanceled();

          if (LOG.isDebugEnabled()) {
            LOG.debug(instructionState.toString());
          }
          // System.out.println(instructionState.toString());

          Instruction instruction = instructionState.getInstruction();

          if (instruction instanceof BranchingInstruction) {
            BranchingInstruction branching = (BranchingInstruction) instruction;
            Collection<DfaMemoryState> processed = processedStates.get(branching);
            if (processed.contains(instructionState.getMemoryState())) {
              continue;
            }
            if (processed.size() > MAX_STATES_PER_BRANCH) {
              LOG.debug("Too complex because too many different possible states");
              return RunnerResult.TOO_COMPLEX; // Too complex :(
            }
            if (loopNumber[branching.getIndex()] != 0) {
              processedStates.putValue(branching, instructionState.getMemoryState().createCopy());
            }
          }

          DfaInstructionState[] after = acceptInstruction(visitor, instructionState);
          for (DfaInstructionState state : after) {
            Instruction nextInstruction = state.getInstruction();
            if (nextInstruction.getIndex() >= endOffset) {
              continue;
            }
            handleStepOutOfLoop(
                instruction,
                nextInstruction,
                loopNumber,
                processedStates,
                incomingStates,
                states,
                after,
                queue);
            if (nextInstruction instanceof BranchingInstruction) {
              BranchingInstruction branching = (BranchingInstruction) nextInstruction;
              if (processedStates.get(branching).contains(state.getMemoryState())
                  || incomingStates.get(branching).contains(state.getMemoryState())) {
                continue;
              }
              if (loopNumber[branching.getIndex()] != 0) {
                incomingStates.putValue(branching, state.getMemoryState().createCopy());
              }
            }
            queue.offer(state);
          }
        }
      }

      psiBlock.putUserData(TOO_EXPENSIVE_HASH, null);
      LOG.debug("Analysis ok");
      return RunnerResult.OK;
    } catch (ArrayIndexOutOfBoundsException e) {
      LOG.error(psiBlock.getText(), e);
      return RunnerResult.ABORTED;
    } catch (EmptyStackException e) {
      LOG.error(psiBlock.getText(), e);
      return RunnerResult.ABORTED;
    }
  }