예제 #1
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;
  }
예제 #2
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);
    }
  }
예제 #3
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;
  }
예제 #4
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()]);
  }
예제 #5
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();
   }
 }
  @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;
  }
  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();
    }
  }
예제 #8
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;
  }
예제 #9
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;
  }