Пример #1
0
    @NotNull
    private MutableClassDescriptor createClassDescriptorForClass(
        @NotNull JetClass klass, @NotNull DeclarationDescriptor containingDeclaration) {
      ClassKind kind = getClassKind(klass);
      // Kind check is needed in order to not consider enums as inner in any case
      // (otherwise it would be impossible to create a class object in the enum)
      boolean isInner = kind == ClassKind.CLASS && klass.isInner();
      MutableClassDescriptor mutableClassDescriptor =
          new MutableClassDescriptor(
              containingDeclaration,
              outerScope,
              kind,
              isInner,
              JetPsiUtil.safeName(klass.getName()));
      c.getClasses().put(klass, mutableClassDescriptor);
      trace.record(
          FQNAME_TO_CLASS_DESCRIPTOR, JetPsiUtil.getUnsafeFQName(klass), mutableClassDescriptor);

      createClassObjectForEnumClass(mutableClassDescriptor);

      JetScope classScope = mutableClassDescriptor.getScopeForMemberDeclarationResolution();

      prepareForDeferredCall(classScope, mutableClassDescriptor, klass);

      return mutableClassDescriptor;
    }
Пример #2
0
  public static boolean doNeedImport(
      @NotNull ImportPath importPath, @Nullable String aliasName, @NotNull JetFile file) {
    if (QualifiedNamesUtil.getFirstSegment(importPath.fqnPart().getFqName())
        .equals(JavaDescriptorResolver.JAVA_ROOT.getName())) {
      FqName withoutJavaRoot = QualifiedNamesUtil.withoutFirstSegment(importPath.fqnPart());
      importPath = new ImportPath(withoutJavaRoot, importPath.isAllUnder());
    }

    if (isImportedByDefault(importPath, null, JetPsiUtil.getFQName(file))) {
      return false;
    }

    List<JetImportDirective> importDirectives = file.getImportDirectives();

    if (!importDirectives.isEmpty()) {
      // Check if import is already present
      for (JetImportDirective directive : importDirectives) {
        ImportPath existentImportPath = JetPsiUtil.getImportPath(directive);
        if (directive.getAliasName() == null && aliasName == null) {
          if (existentImportPath != null
              && QualifiedNamesUtil.isImported(existentImportPath, importPath)) {
            return false;
          }
        }
      }
    }

    return true;
  }
Пример #3
0
  protected static PsiElement adjustSibling(
      @NotNull Editor editor,
      @NotNull LineRange sourceRange,
      @NotNull MoveInfo info,
      boolean down) {
    PsiElement element = down ? sourceRange.lastElement : sourceRange.firstElement;
    PsiElement sibling = down ? element.getNextSibling() : element.getPrevSibling();

    PsiElement whiteSpaceTestSubject = sibling;
    if (sibling == null) {
      PsiElement parent = element.getParent();
      if (parent != null && isBracelessBlock(parent)) {
        whiteSpaceTestSubject = down ? parent.getNextSibling() : parent.getPrevSibling();
      }
    }

    if (whiteSpaceTestSubject instanceof PsiWhiteSpace) {
      if (getElementLineCount(whiteSpaceTestSubject, editor) > 1) {
        int nearLine = down ? sourceRange.endLine : sourceRange.startLine - 1;

        info.toMove = sourceRange;
        info.toMove2 = new LineRange(nearLine, nearLine + 1);
        info.indentTarget = false;

        return null;
      }

      if (sibling != null) {
        sibling = firstNonWhiteElement(sibling, down);
      }
    }

    if (sibling == null) {
      JetCallExpression callExpression =
          PsiTreeUtil.getParentOfType(element, JetCallExpression.class);
      if (callExpression != null) {
        JetBlockExpression dslBlock = getDSLLambdaBlock(callExpression, down);
        if (PsiTreeUtil.isAncestor(dslBlock, element, false)) {
          //noinspection ConstantConditions
          PsiElement blockParent = dslBlock.getParent();
          return down
              ? JetPsiUtil.findChildByType(blockParent, JetTokens.RBRACE)
              : JetPsiUtil.findChildByType(blockParent, JetTokens.LBRACE);
        }
      }

      info.toMove2 = null;
      return null;
    }

    return sibling;
  }
Пример #4
0
 @Nullable
 public static BinaryCall getRangeAsBinaryCall(@NotNull JetForExpression forExpression) {
   // We are looking for rangeTo() calls
   // Other binary operations will succeed too, but will be filtered out later (by examining a
   // resolvedCall)
   JetExpression rangeExpression = forExpression.getLoopRange();
   assert rangeExpression != null;
   JetExpression loopRange = JetPsiUtil.deparenthesizeWithNoTypeResolution(rangeExpression);
   if (loopRange instanceof JetQualifiedExpression) {
     // a.rangeTo(b)
     JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) loopRange;
     JetExpression selector = qualifiedExpression.getSelectorExpression();
     if (selector instanceof JetCallExpression) {
       JetCallExpression callExpression = (JetCallExpression) selector;
       List<? extends ValueArgument> arguments = callExpression.getValueArguments();
       if (arguments.size() == 1) {
         return new BinaryCall(
             qualifiedExpression.getReceiverExpression(),
             callExpression.getCalleeExpression(),
             arguments.get(0).getArgumentExpression());
       }
     }
   } else if (loopRange instanceof JetBinaryExpression) {
     // a rangeTo b
     // a .. b
     JetBinaryExpression binaryExpression = (JetBinaryExpression) loopRange;
     return new BinaryCall(
         binaryExpression.getLeft(),
         binaryExpression.getOperationReference(),
         binaryExpression.getRight());
   }
   return null;
 }
Пример #5
0
  /** Check that import is useless. */
  private static boolean isImportedByDefault(
      @NotNull ImportPath importPath, @NotNull JetFile jetFile) {
    if (importPath.fqnPart().isRoot()) {
      return true;
    }

    if (!importPath.isAllUnder() && !importPath.hasAlias()) {
      // Single element import without .* and alias is useless
      if (QualifiedNamesUtil.isOneSegmentFQN(importPath.fqnPart())) {
        return true;
      }

      // There's no need to import a declaration from the package of current file
      if (JetPsiUtil.getFQName(jetFile).equals(importPath.fqnPart().parent())) {
        return true;
      }
    }

    if (isImportedWithKotlinDefault(importPath)) return true;

    if (KotlinFrameworkDetector.isJsKotlinModule(jetFile)) {
      return isImportedWithJsDefault(importPath);
    } else {
      return isImportedWithJavaDefault(importPath);
    }
  }
Пример #6
0
  @Nullable
  private static JetBlockExpression findClosestBlock(
      @NotNull PsiElement anchor, boolean down, boolean strict) {
    PsiElement current = PsiTreeUtil.getParentOfType(anchor, JetBlockExpression.class, strict);
    while (current != null) {
      PsiElement parent = current.getParent();
      if (parent instanceof JetClassBody
          || parent instanceof JetClassInitializer
          || parent instanceof JetNamedFunction
          || (parent instanceof JetProperty && !((JetProperty) parent).isLocal())) {
        return null;
      }

      if (parent instanceof JetBlockExpression) return (JetBlockExpression) parent;

      PsiElement sibling = down ? current.getNextSibling() : current.getPrevSibling();
      if (sibling != null) {
        //noinspection unchecked
        JetBlockExpression block =
            (JetBlockExpression)
                JetPsiUtil.getOutermostDescendantElement(sibling, down, CHECK_BLOCK);
        if (block != null) return block;

        current = sibling;
      } else {
        current = parent;
      }
    }

    return null;
  }
Пример #7
0
  // TODO: Make it work for properties
  public Collection<DeclarationDescriptor> getJetCallableExtensions(
      @NotNull Condition<String> acceptedNameCondition,
      @NotNull JetSimpleNameExpression expression,
      @NotNull ResolveSession resolveSession,
      @NotNull GlobalSearchScope searchScope) {
    Collection<DeclarationDescriptor> resultDescriptors = new ArrayList<DeclarationDescriptor>();

    BindingContext context = ResolveSessionUtils.resolveToExpression(resolveSession, expression);
    JetExpression receiverExpression = expression.getReceiverExpression();

    if (receiverExpression != null) {
      JetType expressionType = context.get(BindingContext.EXPRESSION_TYPE, receiverExpression);
      JetScope scope = context.get(BindingContext.RESOLUTION_SCOPE, receiverExpression);

      if (expressionType != null && scope != null) {
        Collection<String> extensionFunctionsNames = getAllJetExtensionFunctionsNames(searchScope);

        Set<FqName> functionFQNs = new java.util.HashSet<FqName>();

        // Collect all possible extension function qualified names
        for (String name : extensionFunctionsNames) {
          if (acceptedNameCondition.value(name)) {
            Collection<PsiElement> extensionFunctions =
                getJetExtensionFunctionsByName(name, searchScope);

            for (PsiElement extensionFunction : extensionFunctions) {
              if (extensionFunction instanceof JetNamedFunction) {
                functionFQNs.add(JetPsiUtil.getFQName((JetNamedFunction) extensionFunction));
              } else if (extensionFunction instanceof PsiMethod) {
                FqName functionFQN =
                    JetFromJavaDescriptorHelper.getJetTopLevelDeclarationFQN(
                        (PsiMethod) extensionFunction);
                if (functionFQN != null) {
                  functionFQNs.add(functionFQN);
                }
              }
            }
          }
        }

        // Iterate through the function with attempt to resolve found functions
        for (FqName functionFQN : functionFQNs) {
          for (CallableDescriptor functionDescriptor :
              ExpressionTypingUtils.canFindSuitableCall(
                  functionFQN,
                  project,
                  receiverExpression,
                  expressionType,
                  scope,
                  resolveSession.getModuleConfiguration())) {

            resultDescriptors.add(functionDescriptor);
          }
        }
      }
    }

    return resultDescriptors;
  }
Пример #8
0
    @Override
    public void visitObjectDeclaration(@NotNull JetObjectDeclaration declaration) {
      if (declaration.isObjectLiteral()) {
        createClassDescriptorForSingleton(
            declaration, SpecialNames.NO_NAME_PROVIDED, ClassKind.CLASS);
        return;
      }

      MutableClassDescriptor descriptor =
          createClassDescriptorForSingleton(
              declaration, JetPsiUtil.safeName(declaration.getName()), ClassKind.OBJECT);

      owner.addClassifierDescriptor(descriptor);
      trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetPsiUtil.getUnsafeFQName(declaration), descriptor);

      descriptor.getBuilder().setClassObjectDescriptor(createSyntheticClassObject(descriptor));
    }
Пример #9
0
    @Override
    public void visitEnumEntry(@NotNull JetEnumEntry declaration) {
      MutableClassDescriptor descriptor =
          createClassDescriptorForSingleton(
              declaration, JetPsiUtil.safeName(declaration.getName()), ClassKind.ENUM_ENTRY);

      owner.addClassifierDescriptor(descriptor);

      descriptor.getBuilder().setClassObjectDescriptor(createSyntheticClassObject(descriptor));
    }
Пример #10
0
  private static boolean checkFoldableIfExpressionWithAsymmetricReturns(
      JetIfExpression ifExpression) {
    if (getFoldableBranchedReturn(ifExpression.getThen()) == null
        || ifExpression.getElse() != null) {
      return false;
    }

    PsiElement nextElement = JetPsiUtil.skipTrailingWhitespacesAndComments(ifExpression);
    return (nextElement instanceof JetExpression)
        && getFoldableBranchedReturn((JetExpression) nextElement) != null;
  }
Пример #11
0
  /** Return class names form jet sources in given scope which should be visible as Java classes. */
  @NotNull
  @Override
  public PsiClass[] getClassesByName(
      @NotNull @NonNls String name, @NotNull GlobalSearchScope scope) {
    List<PsiClass> result = new ArrayList<PsiClass>();

    IDELightClassGenerationSupport lightClassGenerationSupport =
        IDELightClassGenerationSupport.getInstanceForIDE(project);
    MultiMap<String, FqName> packageClasses =
        lightClassGenerationSupport.getAllPackageClasses(scope);

    // .namespace classes can not be indexed, since they have no explicit declarations
    Collection<FqName> fqNames = packageClasses.get(name);
    if (!fqNames.isEmpty()) {
      for (FqName fqName : fqNames) {
        PsiClass psiClass =
            JavaElementFinder.getInstance(project).findClass(fqName.getFqName(), scope);
        if (psiClass != null) {
          result.add(psiClass);
        }
      }
    }

    // Quick check for classes from getAllClassNames()
    Collection<JetClassOrObject> classOrObjects =
        JetShortClassNameIndex.getInstance().get(name, project, scope);
    if (classOrObjects.isEmpty()) {
      return result.toArray(new PsiClass[result.size()]);
    }

    for (JetClassOrObject classOrObject : classOrObjects) {
      FqName fqName = JetPsiUtil.getFQName(classOrObject);
      if (fqName != null) {
        assert fqName.shortName().getName().equals(name)
            : "A declaration obtained from index has non-matching name:\n"
                + "in index: "
                + name
                + "\n"
                + "declared: "
                + fqName.shortName()
                + "("
                + fqName
                + ")";
        PsiClass psiClass =
            JavaElementFinder.getInstance(project).findClass(fqName.getFqName(), scope);
        if (psiClass != null) {
          result.add(psiClass);
        }
      }
    }

    return result.toArray(new PsiClass[result.size()]);
  }
Пример #12
0
        @Override
        public boolean apply(@Nullable JetElement input) {
          if (input == null || !JetPsiUtil.isAssignment(input)) {
            return false;
          }

          JetBinaryExpression assignment = (JetBinaryExpression) input;

          if (assignment.getRight() == null
              || !(assignment.getLeft() instanceof JetSimpleNameExpression)) {
            return false;
          }

          if (assignment.getParent() instanceof JetBlockExpression) {
            //noinspection ConstantConditions
            return !JetPsiUtil.checkVariableDeclarationInBlock(
                (JetBlockExpression) assignment.getParent(), assignment.getLeft().getText());
          }

          return true;
        }
Пример #13
0
  @Nullable
  private static JetBlockExpression getDSLLambdaBlock(@NotNull PsiElement element, boolean down) {
    JetCallExpression callExpression =
        (JetCallExpression)
            JetPsiUtil.getOutermostDescendantElement(element, down, IS_CALL_EXPRESSION);
    if (callExpression == null) return null;

    List<JetExpression> functionLiterals = callExpression.getFunctionLiteralArguments();
    if (functionLiterals.isEmpty()) return null;

    return ((JetFunctionLiteralExpression) functionLiterals.get(0)).getBodyExpression();
  }
Пример #14
0
  public static @NotNull BindingContext resolveToExpression(
      @NotNull final ResolveSession resolveSession, @NotNull JetExpression expression) {
    final DelegatingBindingTrace trace =
        new DelegatingBindingTrace(
            resolveSession.getBindingContext(), "trace to resolve expression", expression);
    JetFile file = (JetFile) expression.getContainingFile();

    @SuppressWarnings("unchecked")
    PsiElement topmostCandidateForAdditionalResolve =
        JetPsiUtil.getTopmostParentOfTypes(
            expression,
            JetNamedFunction.class,
            JetClassInitializer.class,
            JetProperty.class,
            JetDelegationSpecifierList.class);

    if (topmostCandidateForAdditionalResolve != null) {
      if (topmostCandidateForAdditionalResolve instanceof JetNamedFunction) {
        functionAdditionalResolve(
            resolveSession, (JetNamedFunction) topmostCandidateForAdditionalResolve, trace, file);
      } else if (topmostCandidateForAdditionalResolve instanceof JetClassInitializer) {
        initializerAdditionalResolve(
            resolveSession,
            (JetClassInitializer) topmostCandidateForAdditionalResolve,
            trace,
            file);
      } else if (topmostCandidateForAdditionalResolve instanceof JetProperty) {
        propertyAdditionalResolve(
            resolveSession, (JetProperty) topmostCandidateForAdditionalResolve, trace, file);
      } else if (topmostCandidateForAdditionalResolve instanceof JetDelegationSpecifierList) {
        delegationSpecifierAdditionalResolve(
            resolveSession,
            (JetDelegationSpecifierList) topmostCandidateForAdditionalResolve,
            trace,
            file);
      } else {
        assert false : "Invalid type of the topmost parent";
      }

      return trace.getBindingContext();
    }

    // Setup resolution scope explicitly
    if (trace.getBindingContext().get(BindingContext.RESOLUTION_SCOPE, expression) == null) {
      JetScope scope = getExpressionMemberScope(resolveSession, expression);
      if (scope != null) {
        trace.record(BindingContext.RESOLUTION_SCOPE, expression, scope);
      }
    }

    return trace.getBindingContext();
  }
Пример #15
0
  private static boolean checkFoldableWhenExpressionWithReturns(JetWhenExpression whenExpression) {
    if (!JetPsiUtil.checkWhenExpressionHasSingleElse(whenExpression)) return false;

    List<JetWhenEntry> entries = whenExpression.getEntries();

    if (entries.isEmpty()) return false;

    for (JetWhenEntry entry : entries) {
      if (getFoldableBranchedReturn(entry.getExpression()) == null) return false;
    }

    return true;
  }
  @NotNull
  public Collection<? extends DeclarationDescriptor> lookupDescriptorsForQualifiedExpression(
      @NotNull JetQualifiedExpression importedReference,
      @NotNull JetScope outerScope,
      @NotNull JetScope scopeToCheckVisibility,
      @NotNull BindingTrace trace,
      @NotNull LookupMode lookupMode,
      boolean storeResult) {

    JetExpression receiverExpression = importedReference.getReceiverExpression();
    Collection<? extends DeclarationDescriptor> declarationDescriptors;
    if (receiverExpression instanceof JetQualifiedExpression) {
      declarationDescriptors =
          lookupDescriptorsForQualifiedExpression(
              (JetQualifiedExpression) receiverExpression,
              outerScope,
              scopeToCheckVisibility,
              trace,
              lookupMode,
              storeResult);
    } else {
      assert receiverExpression instanceof JetSimpleNameExpression;
      declarationDescriptors =
          lookupDescriptorsForSimpleNameReference(
              (JetSimpleNameExpression) receiverExpression,
              outerScope,
              scopeToCheckVisibility,
              trace,
              lookupMode,
              true,
              storeResult);
    }

    JetExpression selectorExpression = importedReference.getSelectorExpression();
    if (!(selectorExpression instanceof JetSimpleNameExpression)) {
      return Collections.emptyList();
    }

    JetSimpleNameExpression selector = (JetSimpleNameExpression) selectorExpression;
    JetSimpleNameExpression lastReference = JetPsiUtil.getLastReference(receiverExpression);
    if (lastReference == null
        || !canImportMembersFrom(declarationDescriptors, lastReference, trace, lookupMode)) {
      return Collections.emptyList();
    }

    return lookupSelectorDescriptors(
        selector, declarationDescriptors, trace, scopeToCheckVisibility, lookupMode, storeResult);
  }
Пример #17
0
  private static BraceStatus checkForMovableUpClosingBrace(
      @NotNull PsiElement closingBrace,
      PsiElement block,
      @NotNull Editor editor,
      @NotNull MoveInfo info) {
    //noinspection unchecked
    PsiElement prev = JetPsiUtil.getLastChildByType(block, JetExpression.class);
    if (prev == null) return BraceStatus.NOT_MOVABLE;

    Document doc = editor.getDocument();

    info.toMove = new LineRange(closingBrace, closingBrace, doc);
    info.toMove2 = new LineRange(prev, prev, doc);
    info.indentSource = true;

    return BraceStatus.MOVABLE;
  }
Пример #18
0
 @Override
 public void visitJetFile(JetFile file) {
   if (file.isScript()) {
     //noinspection ConstantConditions
     final ClassDescriptor classDescriptor =
         bindingContext.get(CLASS_FOR_FUNCTION, bindingContext.get(SCRIPT, file.getScript()));
     classStack.push(classDescriptor);
     //noinspection ConstantConditions
     nameStack.push(classNameForScriptPsi(bindingContext, file.getScript()).getInternalName());
   } else {
     nameStack.push(JetPsiUtil.getFQName(file).getFqName().replace('.', '/'));
   }
   file.acceptChildren(this);
   nameStack.pop();
   if (file.isScript()) {
     classStack.pop();
   }
 }
Пример #19
0
  @NotNull
  public static Collection<JetFile> allFilesInNamespaces(
      BindingContext bindingContext, Collection<JetFile> files) {
    // todo: we use Set and add given files but ignoring other scripts because something non-clear
    // kept in binding
    // for scripts especially in case of REPL

    HashSet<FqName> names = new HashSet<FqName>();
    for (JetFile file : files) {
      if (!file.isScript()) {
        names.add(JetPsiUtil.getFQName(file));
      }
    }

    HashSet<JetFile> answer = new HashSet<JetFile>();
    answer.addAll(files);

    for (FqName name : names) {
      NamespaceDescriptor namespaceDescriptor =
          bindingContext.get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, name);
      Collection<JetFile> jetFiles = bindingContext.get(NAMESPACE_TO_FILES, namespaceDescriptor);
      if (jetFiles != null) answer.addAll(jetFiles);
    }

    List<JetFile> sortedAnswer = new ArrayList<JetFile>(answer);
    Collections.sort(
        sortedAnswer,
        new Comparator<JetFile>() {
          @NotNull
          private String path(JetFile file) {
            VirtualFile virtualFile = file.getVirtualFile();
            assert virtualFile != null : "VirtualFile is null for JetFile: " + file.getName();
            return virtualFile.getPath();
          }

          @Override
          public int compare(JetFile first, JetFile second) {
            return path(first).compareTo(path(second));
          }
        });

    return sortedAnswer;
  }
Пример #20
0
  public static void foldIfExpressionWithAsymmetricReturns(JetIfExpression ifExpression) {
    Project project = ifExpression.getProject();

    JetExpression condition = ifExpression.getCondition();
    JetExpression thenRoot = ifExpression.getThen();
    JetExpression elseRoot =
        (JetExpression) JetPsiUtil.skipTrailingWhitespacesAndComments(ifExpression);

    assertNotNull(condition);
    assertNotNull(thenRoot);
    assertNotNull(elseRoot);

    //noinspection ConstantConditions
    JetIfExpression newIfExpression =
        JetPsiFactory.createIf(project, condition, thenRoot, elseRoot);
    JetReturnExpression newReturnExpression = JetPsiFactory.createReturn(project, newIfExpression);

    newIfExpression = (JetIfExpression) newReturnExpression.getReturnedExpression();

    assertNotNull(newIfExpression);

    //noinspection ConstantConditions
    JetReturnExpression thenReturn = getFoldableBranchedReturn(newIfExpression.getThen());
    JetReturnExpression elseReturn = getFoldableBranchedReturn(newIfExpression.getElse());

    assertNotNull(thenReturn);
    assertNotNull(elseReturn);

    JetExpression thenExpr = thenReturn.getReturnedExpression();
    JetExpression elseExpr = elseReturn.getReturnedExpression();

    assertNotNull(thenExpr);
    assertNotNull(elseExpr);

    //noinspection ConstantConditions
    thenReturn.replace(thenExpr);
    //noinspection ConstantConditions
    elseReturn.replace(elseExpr);

    elseRoot.delete();
    ifExpression.replace(newReturnExpression);
  }
  private static boolean compileBunchOfSources(
      K2JVMCompileEnvironmentConfiguration configuration,
      String jar,
      String outputDir,
      boolean includeRuntime) {
    FqName mainClass = null;
    for (JetFile file : configuration.getEnvironment().getSourceFiles()) {
      if (JetMainDetector.hasMain(file.getDeclarations())) {
        FqName fqName = JetPsiUtil.getFQName(file);
        mainClass = fqName.child(JvmAbi.PACKAGE_CLASS);
        break;
      }
    }

    GenerationState generationState = analyzeAndGenerate(configuration);
    if (generationState == null) {
      return false;
    }

    try {
      ClassFileFactory factory = generationState.getFactory();
      if (jar != null) {
        try {
          CompileEnvironmentUtil.writeToJar(
              factory, new FileOutputStream(jar), mainClass, includeRuntime);
        } catch (FileNotFoundException e) {
          throw new CompileEnvironmentException("Invalid jar path " + jar, e);
        }
      } else if (outputDir != null) {
        CompileEnvironmentUtil.writeToOutputDirectory(factory, outputDir);
      } else {
        throw new CompileEnvironmentException(
            "Output directory or jar file is not specified - no files will be saved to the disk");
      }
      return true;
    } finally {
      generationState.destroy();
    }
  }
Пример #22
0
  @NotNull
  public Collection<ClassDescriptor> getTopLevelObjectsByName(
      @NotNull String name,
      @NotNull JetSimpleNameExpression expression,
      @NotNull ResolveSession resolveSession,
      @NotNull GlobalSearchScope scope) {
    BindingContext context = ResolveSessionUtils.resolveToExpression(resolveSession, expression);
    JetScope jetScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);

    if (jetScope == null) {
      return Collections.emptyList();
    }

    Set<ClassDescriptor> result = Sets.newHashSet();

    Collection<JetObjectDeclaration> topObjects =
        JetTopLevelShortObjectNameIndex.getInstance().get(name, project, scope);
    for (JetObjectDeclaration objectDeclaration : topObjects) {
      FqName fqName = JetPsiUtil.getFQName(objectDeclaration);
      assert fqName != null
          : "Local object declaration in JetTopLevelShortObjectNameIndex:"
              + objectDeclaration.getText();
      result.addAll(
          ResolveSessionUtils.getClassOrObjectDescriptorsByFqName(resolveSession, fqName, true));
    }

    for (PsiClass psiClass :
        JetFromJavaDescriptorHelper.getCompiledClassesForTopLevelObjects(
            project, GlobalSearchScope.allScope(project))) {
      String qualifiedName = psiClass.getQualifiedName();
      if (qualifiedName != null) {
        FqName fqName = new FqName(qualifiedName);
        result.addAll(
            ResolveSessionUtils.getClassOrObjectDescriptorsByFqName(resolveSession, fqName, true));
      }
    }

    return result;
  }
Пример #23
0
  private static boolean checkFoldableWhenExpressionWithAssignments(
      JetWhenExpression whenExpression) {
    if (!JetPsiUtil.checkWhenExpressionHasSingleElse(whenExpression)) return false;

    List<JetWhenEntry> entries = whenExpression.getEntries();

    if (entries.isEmpty()) return false;

    List<JetBinaryExpression> assignments = new ArrayList<JetBinaryExpression>();
    for (JetWhenEntry entry : entries) {
      JetBinaryExpression assignment = getFoldableBranchedAssignment(entry.getExpression());
      if (assignment == null) return false;
      assignments.add(assignment);
    }

    assert !assignments.isEmpty();

    JetBinaryExpression firstAssignment = assignments.get(0);
    for (JetBinaryExpression assignment : assignments) {
      if (!checkAssignmentsMatch(assignment, firstAssignment)) return false;
    }

    return true;
  }
Пример #24
0
  @Nullable
  private static LineRange getExpressionTargetRange(
      @NotNull Editor editor, @NotNull PsiElement sibling, boolean down) {
    if (sibling instanceof JetIfExpression && !down) {
      JetExpression elseBranch = ((JetIfExpression) sibling).getElse();
      if (elseBranch instanceof JetBlockExpression) {
        sibling = elseBranch;
      }
    }

    PsiElement start = sibling;
    PsiElement end = sibling;

    // moving out of code block
    if (sibling.getNode().getElementType() == (down ? JetTokens.RBRACE : JetTokens.LBRACE)) {
      PsiElement parent = sibling.getParent();
      if (!(parent instanceof JetBlockExpression || parent instanceof JetFunctionLiteral))
        return null;

      JetBlockExpression newBlock;
      if (parent instanceof JetFunctionLiteral) {
        //noinspection ConstantConditions
        newBlock = findClosestBlock(((JetFunctionLiteral) parent).getBodyExpression(), down, false);

        if (!down) {
          ASTNode arrow = ((JetFunctionLiteral) parent).getArrowNode();
          if (arrow != null) {
            end = arrow.getPsi();
          }
        }
      } else {
        newBlock = findClosestBlock(sibling, down, true);
      }

      if (newBlock == null) return null;

      if (PsiTreeUtil.isAncestor(newBlock, parent, true)) {
        PsiElement outermostParent = JetPsiUtil.getOutermostParent(parent, newBlock, true);

        if (down) {
          end = outermostParent;
        } else {
          start = outermostParent;
        }
      } else {
        if (down) {
          end = newBlock.getLBrace();
        } else {
          start = newBlock.getRBrace();
        }
      }
    }
    // moving into code block
    else {
      PsiElement blockLikeElement;

      JetBlockExpression dslBlock = getDSLLambdaBlock(sibling, down);
      if (dslBlock != null) {
        // Use JetFunctionLiteral (since it contains braces)
        blockLikeElement = dslBlock.getParent();
      } else {
        // JetBlockExpression and other block-like elements
        blockLikeElement =
            JetPsiUtil.getOutermostDescendantElement(sibling, down, CHECK_BLOCK_LIKE_ELEMENT);
      }

      if (blockLikeElement != null) {
        if (down) {
          end = JetPsiUtil.findChildByType(blockLikeElement, JetTokens.LBRACE);
          if (blockLikeElement instanceof JetFunctionLiteral) {
            ASTNode arrow = ((JetFunctionLiteral) blockLikeElement).getArrowNode();
            if (arrow != null) {
              end = arrow.getPsi();
            }
          }
        } else {
          start = JetPsiUtil.findChildByType(blockLikeElement, JetTokens.RBRACE);
        }
      }
    }

    return start != null && end != null ? new LineRange(start, end, editor.getDocument()) : null;
  }
Пример #25
0
  private PsiJavaFileStub calcStub() {
    final PsiJavaFileStubImpl answer = new PsiJavaFileStubImpl(JetPsiUtil.getFQName(file), true);
    final Project project = getProject();

    final Stack<StubElement> stubStack = new Stack<StubElement>();

    final ClassBuilderFactory builderFactory =
        new ClassBuilderFactory() {
          @Override
          public ClassBuilder newClassBuilder() {
            return new StubClassBuilder(stubStack);
          }

          @Override
          public String asText(ClassBuilder builder) {
            throw new UnsupportedOperationException("asText is not implemented"); // TODO
          }

          @Override
          public byte[] asBytes(ClassBuilder builder) {
            throw new UnsupportedOperationException("asBytes is not implemented"); // TODO
          }
        };

    final GenerationState state =
        new GenerationState(project, builderFactory) {
          @Override
          protected void generateNamespace(JetFile namespace) {
            PsiManager manager = PsiManager.getInstance(project);
            stubStack.push(answer);

            answer.setPsiFactory(new ClsWrapperStubPsiFactory());
            final ClsFileImpl fakeFile =
                new ClsFileImpl(
                    (PsiManagerImpl) manager,
                    new ClassFileViewProvider(manager, file.getVirtualFile())) {
                  @NotNull
                  @Override
                  public PsiClassHolderFileStub getStub() {
                    return answer;
                  }
                };

            fakeFile.setPhysical(false);
            answer.setPsi(fakeFile);

            try {
              super.generateNamespace(namespace);
            } finally {
              final StubElement pop = stubStack.pop();
              if (pop != answer) {
                LOG.error("Unbalanced stack operations: " + pop);
              }
            }
          }
        };

    List<JetFile> files = Collections.singletonList(file);
    final BindingContext context = AnalyzerFacade.shallowAnalyzeFiles(files);
    state.compileCorrectFiles(context, files);
    state.getFactory().files();

    return answer;
  }
  @Override
  public final boolean update() {
    CompositeAppearance oldText = myHighlightedText;
    Icon oldIcon = getIcon();

    int flags = Iconable.ICON_FLAG_VISIBILITY;
    if (isMarkReadOnly()) {
      flags |= Iconable.ICON_FLAG_READ_STATUS;
    }

    boolean changes = super.update();

    PsiElement targetElement = getTargetElement();
    String elementText = renderElement(targetElement);

    if (elementText == null) {
      String invalidPrefix = IdeBundle.message("node.hierarchy.invalid");
      if (!myHighlightedText.getText().startsWith(invalidPrefix)) {
        myHighlightedText
            .getBeginning()
            .addText(invalidPrefix, HierarchyNodeDescriptor.getInvalidPrefixAttributes());
      }
      return true;
    }

    Icon newIcon = targetElement.getIcon(flags);
    if (changes && myIsBase) {
      LayeredIcon icon = new LayeredIcon(2);
      icon.setIcon(newIcon, 0);
      icon.setIcon(AllIcons.Hierarchy.Base, 1, -AllIcons.Hierarchy.Base.getIconWidth() / 2, 0);
      newIcon = icon;
    }
    setIcon(newIcon);

    myHighlightedText = new CompositeAppearance();
    TextAttributes mainTextAttributes = null;
    if (myColor != null) {
      mainTextAttributes = new TextAttributes(myColor, null, null, null, Font.PLAIN);
    }

    String packageName = null;
    if (targetElement instanceof JetElement) {
      packageName = JetPsiUtil.getPackageName((JetElement) targetElement);
    } else {
      PsiClass enclosingClass = PsiTreeUtil.getParentOfType(targetElement, PsiClass.class, false);
      if (enclosingClass != null) {
        packageName = JavaHierarchyUtil.getPackageName(enclosingClass);
      }
    }

    myHighlightedText.getEnding().addText(elementText, mainTextAttributes);

    if (usageCount > 1) {
      myHighlightedText
          .getEnding()
          .addText(
              IdeBundle.message("node.call.hierarchy.N.usages", usageCount),
              HierarchyNodeDescriptor.getUsageCountPrefixAttributes());
    }

    if (packageName == null) {
      packageName = "";
    }
    myHighlightedText
        .getEnding()
        .addText("  (" + packageName + ")", HierarchyNodeDescriptor.getPackageNameAttributes());

    myName = myHighlightedText.getText();

    if (!(Comparing.equal(myHighlightedText, oldText) && Comparing.equal(getIcon(), oldIcon))) {
      changes = true;
    }
    return changes;
  }
Пример #27
0
  public static Icon getBaseIcon(PsiElement psiElement) {
    if (psiElement instanceof JetNamespaceHeader) {
      return PlatformIcons.PACKAGE_ICON;
    }

    if (psiElement instanceof KotlinLightClassForPackage) {
      return JetIcons.FILE;
    }

    if (psiElement instanceof KotlinLightClassForExplicitDeclaration) {
      psiElement = psiElement.getNavigationElement();
    }

    if (psiElement instanceof JetNamedFunction) {
      if (((JetFunction) psiElement).getReceiverTypeRef() != null) {
        return JetIcons.EXTENSION_FUNCTION;
      }

      if (PsiTreeUtil.getParentOfType(psiElement, JetNamedDeclaration.class) instanceof JetClass) {
        if (JetPsiUtil.isAbstract((JetFunction) psiElement)) {
          return PlatformIcons.ABSTRACT_METHOD_ICON;
        } else {
          return PlatformIcons.METHOD_ICON;
        }
      } else {
        return JetIcons.FUNCTION;
      }
    }
    if (psiElement instanceof JetClass) {
      JetClass jetClass = (JetClass) psiElement;
      if (jetClass.isTrait()) {
        return JetIcons.TRAIT;
      }

      Icon icon = jetClass.isEnum() ? PlatformIcons.ENUM_ICON : JetIcons.CLASS;
      if (jetClass instanceof JetEnumEntry) {
        JetEnumEntry enumEntry = (JetEnumEntry) jetClass;
        if (enumEntry.getPrimaryConstructorParameterList() == null) {
          icon = PlatformIcons.ENUM_ICON;
        }
      }
      return icon;
    }
    if (psiElement instanceof JetObjectDeclaration || psiElement instanceof JetClassObject) {
      return JetIcons.OBJECT;
    }
    if (psiElement instanceof JetParameter) {
      JetParameter parameter = (JetParameter) psiElement;
      if (parameter.getValOrVarNode() != null) {
        JetParameterList parameterList =
            PsiTreeUtil.getParentOfType(psiElement, JetParameterList.class);
        if (parameterList != null && parameterList.getParent() instanceof JetClass) {
          return parameter.isMutable() ? JetIcons.FIELD_VAR : JetIcons.FIELD_VAL;
        }
      }
      return JetIcons.PARAMETER;
    }
    if (psiElement instanceof JetProperty) {
      JetProperty property = (JetProperty) psiElement;
      return property.isVar() ? JetIcons.FIELD_VAR : JetIcons.FIELD_VAL;
    }

    return null;
  }
  @NotNull
  protected JetTypeInfo visitAssignmentOperation(
      JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
    // There is a temporary binding trace for an opportunity to resolve set method for array if
    // needed (the initial trace should be used there)
    TemporaryBindingTrace temporaryBindingTrace =
        TemporaryBindingTrace.create(
            contextWithExpectedType.trace,
            "trace to resolve array set method for binary expression",
            expression);
    ExpressionTypingContext context =
        contextWithExpectedType
            .replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE)
            .replaceBindingTrace(temporaryBindingTrace);

    JetSimpleNameExpression operationSign = expression.getOperationReference();
    IElementType operationType = operationSign.getReferencedNameElementType();
    JetTypeInfo leftInfo = facade.getTypeInfo(expression.getLeft(), context);
    JetType leftType = leftInfo.getType();
    DataFlowInfo dataFlowInfo = leftInfo.getDataFlowInfo();

    JetExpression right = expression.getRight();
    JetExpression left = JetPsiUtil.deparenthesizeWithNoTypeResolution(expression.getLeft());
    if (right == null || left == null) {
      temporaryBindingTrace.commit();
      return JetTypeInfo.create(null, dataFlowInfo);
    }

    if (leftType == null) {
      dataFlowInfo =
          facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
      context.trace.report(UNRESOLVED_REFERENCE.on(operationSign));
      temporaryBindingTrace.commit();
      return JetTypeInfo.create(null, dataFlowInfo);
    }
    ExpressionReceiver receiver = new ExpressionReceiver(left, leftType);

    // We check that defined only one of '+=' and '+' operations, and call it (in the case '+' we
    // then also assign)
    // Check for '+='
    Name name = OperatorConventions.ASSIGNMENT_OPERATIONS.get(operationType);
    TemporaryBindingTrace assignmentOperationTrace =
        TemporaryBindingTrace.create(
            context.trace, "trace to check assignment operation like '+=' for", expression);
    OverloadResolutionResults<FunctionDescriptor> assignmentOperationDescriptors =
        basic.getResolutionResultsForBinaryCall(
            scope,
            name,
            context.replaceBindingTrace(assignmentOperationTrace),
            expression,
            receiver);
    JetType assignmentOperationType =
        OverloadResolutionResultsUtil.getResultType(assignmentOperationDescriptors);

    // Check for '+'
    Name counterpartName =
        OperatorConventions.BINARY_OPERATION_NAMES.get(
            OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(operationType));
    TemporaryBindingTrace binaryOperationTrace =
        TemporaryBindingTrace.create(
            context.trace, "trace to check binary operation like '+' for", expression);
    OverloadResolutionResults<FunctionDescriptor> binaryOperationDescriptors =
        basic.getResolutionResultsForBinaryCall(
            scope,
            counterpartName,
            context.replaceBindingTrace(binaryOperationTrace),
            expression,
            receiver);
    JetType binaryOperationType =
        OverloadResolutionResultsUtil.getResultType(binaryOperationDescriptors);

    JetType type = assignmentOperationType != null ? assignmentOperationType : binaryOperationType;
    if (assignmentOperationType != null && binaryOperationType != null) {
      OverloadResolutionResults<FunctionDescriptor> ambiguityResolutionResults =
          OverloadResolutionResultsUtil.ambiguity(
              assignmentOperationDescriptors, binaryOperationDescriptors);
      context.trace.report(
          ASSIGN_OPERATOR_AMBIGUITY.on(
              operationSign, ambiguityResolutionResults.getResultingCalls()));
      Collection<DeclarationDescriptor> descriptors = Sets.newHashSet();
      for (ResolvedCall<? extends FunctionDescriptor> call :
          ambiguityResolutionResults.getResultingCalls()) {
        descriptors.add(call.getResultingDescriptor());
      }
      dataFlowInfo =
          facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
      context.trace.record(AMBIGUOUS_REFERENCE_TARGET, operationSign, descriptors);
    } else if (assignmentOperationType != null) {
      assignmentOperationTrace.commit();
      if (!KotlinBuiltIns.getInstance().isUnit(assignmentOperationType)) {
        context.trace.report(
            ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT.on(
                operationSign,
                assignmentOperationDescriptors.getResultingDescriptor(),
                operationSign));
      }
    } else {
      binaryOperationTrace.commit();
      context.trace.record(VARIABLE_REASSIGNMENT, expression);
      if (left instanceof JetArrayAccessExpression) {
        ExpressionTypingContext contextForResolve =
            context
                .replaceScope(scope)
                .replaceBindingTrace(
                    TemporaryBindingTrace.create(
                        contextWithExpectedType.trace,
                        "trace to resolve array set method for assignment",
                        expression));
        basic.resolveArrayAccessSetMethod(
            (JetArrayAccessExpression) left, right, contextForResolve, context.trace);
      }
      dataFlowInfo =
          facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
    }
    basic.checkLValue(context.trace, expression.getLeft());
    temporaryBindingTrace.commit();
    return JetTypeInfo.create(
        checkAssignmentType(type, expression, contextWithExpectedType), dataFlowInfo);
  }
Пример #29
0
  @NotNull
  public Collection<FunctionDescriptor> getTopLevelFunctionDescriptorsByName(
      @NotNull String name,
      @NotNull JetSimpleNameExpression expression,
      @NotNull ResolveSession resolveSession,
      @NotNull GlobalSearchScope scope) {
    // name parameter can differ from expression.getReferenceName() when expression contains
    // completion suffix
    Name referenceName =
        expression.getIdentifier() == null
            ? JetPsiUtil.getConventionName(expression)
            : Name.identifier(name);
    if (referenceName == null || referenceName.toString().isEmpty()) {
      return Collections.emptyList();
    }

    BindingContext context = ResolveSessionUtils.resolveToExpression(resolveSession, expression);
    JetScope jetScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);

    if (jetScope == null) {
      return Collections.emptyList();
    }

    Set<FunctionDescriptor> result = Sets.newHashSet();

    Collection<PsiMethod> topLevelFunctionPrototypes =
        JetFromJavaDescriptorHelper.getTopLevelFunctionPrototypesByName(
            referenceName.getName(), project, scope);
    for (PsiMethod method : topLevelFunctionPrototypes) {
      FqName functionFQN = JetFromJavaDescriptorHelper.getJetTopLevelDeclarationFQN(method);
      if (functionFQN != null) {
        JetImportDirective importDirective =
            JetPsiFactory.createImportDirective(project, new ImportPath(functionFQN, false));
        Collection<? extends DeclarationDescriptor> declarationDescriptors =
            new QualifiedExpressionResolver()
                .analyseImportReference(
                    importDirective,
                    jetScope,
                    new BindingTraceContext(),
                    resolveSession.getModuleConfiguration());
        for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) {
          if (declarationDescriptor instanceof FunctionDescriptor) {
            result.add((FunctionDescriptor) declarationDescriptor);
          }
        }
      }
    }

    Set<FqName> affectedPackages = Sets.newHashSet();
    Collection<JetNamedFunction> jetNamedFunctions =
        JetShortFunctionNameIndex.getInstance().get(referenceName.getName(), project, scope);
    for (JetNamedFunction jetNamedFunction : jetNamedFunctions) {
      PsiFile containingFile = jetNamedFunction.getContainingFile();
      if (containingFile instanceof JetFile) {
        JetFile jetFile = (JetFile) containingFile;
        String packageName = jetFile.getPackageName();
        if (packageName != null) {
          affectedPackages.add(new FqName(packageName));
        }
      }
    }

    for (FqName affectedPackage : affectedPackages) {
      NamespaceDescriptor packageDescriptor =
          resolveSession.getPackageDescriptorByFqName(affectedPackage);
      assert packageDescriptor != null
          : "There's a function in stub index with invalid package: " + affectedPackage;
      JetScope memberScope = packageDescriptor.getMemberScope();
      result.addAll(memberScope.getFunctions(referenceName));
    }

    return result;
  }
  @NotNull
  public Collection<? extends DeclarationDescriptor> processImportReference(
      @NotNull JetImportDirective importDirective,
      @NotNull JetScope scope,
      @NotNull JetScope scopeToCheckVisibility,
      @NotNull Importer importer,
      @NotNull BindingTrace trace,
      @NotNull ModuleConfiguration moduleConfiguration,
      @NotNull LookupMode lookupMode) {
    if (importDirective.isAbsoluteInRootNamespace()) {
      trace.report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO
      return Collections.emptyList();
    }
    JetExpression importedReference = importDirective.getImportedReference();
    if (importedReference == null) {
      return Collections.emptyList();
    }

    Collection<? extends DeclarationDescriptor> descriptors;
    if (importedReference instanceof JetQualifiedExpression) {
      // store result only when we find all descriptors, not only classes on the second phase
      descriptors =
          lookupDescriptorsForQualifiedExpression(
              (JetQualifiedExpression) importedReference,
              scope,
              scopeToCheckVisibility,
              trace,
              lookupMode,
              lookupMode == LookupMode.EVERYTHING);
    } else {
      assert importedReference instanceof JetSimpleNameExpression;
      descriptors =
          lookupDescriptorsForSimpleNameReference(
              (JetSimpleNameExpression) importedReference,
              scope,
              scopeToCheckVisibility,
              trace,
              lookupMode,
              true,
              lookupMode == LookupMode.EVERYTHING);
    }

    JetSimpleNameExpression referenceExpression = JetPsiUtil.getLastReference(importedReference);
    if (importDirective.isAllUnder()) {
      if (referenceExpression == null
          || !canImportMembersFrom(descriptors, referenceExpression, trace, lookupMode)) {
        return Collections.emptyList();
      }

      for (DeclarationDescriptor descriptor : descriptors) {
        importer.addAllUnderImport(descriptor, moduleConfiguration.getPlatformToKotlinClassMap());
      }
      return Collections.emptyList();
    }

    Name aliasName = JetPsiUtil.getAliasName(importDirective);
    if (aliasName == null) {
      return Collections.emptyList();
    }

    for (DeclarationDescriptor descriptor : descriptors) {
      importer.addAliasImport(descriptor, aliasName);
    }

    return descriptors;
  }