예제 #1
0
    @Override
    public void visitJetFile(@NotNull JetFile file) {
      MutablePackageFragmentDescriptor packageFragment = getOrCreatePackageFragmentForFile(file);
      c.getPackageFragments().put(file, packageFragment);
      c.addFile(file);

      PackageViewDescriptor packageView =
          packageFragment.getContainingDeclaration().getPackage(packageFragment.getFqName());
      ChainedScope rootPlusPackageScope =
          new ChainedScope(
              packageView, "Root scope for " + file, packageView.getMemberScope(), outerScope);
      WriteThroughScope packageScope =
          new WriteThroughScope(
              rootPlusPackageScope,
              packageFragment.getMemberScope(),
              new TraceBasedRedeclarationHandler(trace),
              "package in file " + file.getName());
      packageScope.changeLockLevel(WritableScope.LockLevel.BOTH);
      c.getFileScopes().put(file, packageScope);

      if (file.isScript()) {
        scriptHeaderResolver.processScriptHierarchy(c, file.getScript(), packageScope);
      }

      prepareForDeferredCall(packageScope, packageFragment, file);
    }
예제 #2
0
  private void resolveFunctionAndPropertyHeaders(@NotNull TopDownAnalysisContext c) {
    for (Map.Entry<JetFile, WritableScope> entry : c.getFileScopes().entrySet()) {
      JetFile file = entry.getKey();
      WritableScope fileScope = entry.getValue();
      PackageLikeBuilder packageBuilder = c.getPackageFragments().get(file).getBuilder();

      resolveFunctionAndPropertyHeaders(
          c, file.getDeclarations(), fileScope, fileScope, fileScope, packageBuilder);
    }
    for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry :
        c.getDeclaredClasses().entrySet()) {
      JetClassOrObject classOrObject = entry.getKey();
      MutableClassDescriptor classDescriptor = (MutableClassDescriptor) entry.getValue();

      resolveFunctionAndPropertyHeaders(
          c,
          classOrObject.getDeclarations(),
          classDescriptor.getScopeForMemberDeclarationResolution(),
          classDescriptor.getScopeForInitializerResolution(),
          classDescriptor.getScopeForMemberDeclarationResolution(),
          classDescriptor.getBuilder());
    }

    // TODO : Extensions
  }
예제 #3
0
 public static void deleteClass(@NotNull JetClassOrObject clazz) {
   CheckUtil.checkWritable(clazz);
   JetFile file = (JetFile) clazz.getContainingFile();
   List<JetDeclaration> declarations = file.getDeclarations();
   if (declarations.size() == 1) {
     file.delete();
   } else {
     PsiElement parent = clazz.getParent();
     CodeEditUtil.removeChild(parent.getNode(), clazz.getNode());
   }
 }
 @Nullable
 private static PsiClass getLightClassForDecompiledPackage(
     @NotNull FqName packageFqName, @NotNull List<JetFile> filesWithCallables) {
   JetFile firstFile = filesWithCallables.iterator().next();
   if (firstFile.isCompiled()) {
     if (filesWithCallables.size() > 1) {
       LOG.error("Several files with callables for package: " + packageFqName);
     }
     return createLightClassForDecompiledKotlinFile(firstFile);
   }
   return null;
 }
  @NotNull
  @Override
  public LightClassConstructionContext getContextForPackage(@NotNull Collection<JetFile> files) {
    assert !files.isEmpty() : "No files in package";

    List<JetFile> sortedFiles = new ArrayList<JetFile>(files);
    Collections.sort(sortedFiles, scopeFileComparator);

    JetFile file = sortedFiles.get(0);
    ResolveSessionForBodies session =
        KotlinCacheService.getInstance(file.getProject()).getLazyResolveSession(file);
    forceResolvePackageDeclarations(files, session);
    return new LightClassConstructionContext(
        session.getBindingContext(), session.getModuleDescriptor());
  }
  @Nullable
  private static PsiClass getLightClassForDecompiledClassOrObject(
      @NotNull JetClassOrObject decompiledClassOrObject) {
    if (decompiledClassOrObject instanceof JetEnumEntry) {
      return null;
    }
    JetFile containingJetFile = decompiledClassOrObject.getContainingJetFile();
    if (!containingJetFile.isCompiled()) {
      return null;
    }
    PsiClass rootLightClassForDecompiledFile =
        createLightClassForDecompiledKotlinFile(containingJetFile);
    if (rootLightClassForDecompiledFile == null) return null;

    return findCorrespondingLightClass(decompiledClassOrObject, rootLightClassForDecompiledFile);
  }
예제 #7
0
    @NotNull
    private MutablePackageFragmentDescriptor getOrCreatePackageFragmentForFile(
        @NotNull JetFile file) {
      JetPackageDirective packageDirective = file.getPackageDirective();
      assert packageDirective != null : "scripts are not supported";

      MutablePackageFragmentDescriptor fragment =
          packageFragmentProvider.getOrCreateFragment(packageDirective.getFqName());

      ModuleDescriptor module = packageFragmentProvider.getModule();
      DescriptorResolver.resolvePackageHeader(
          packageDirective, module, TypeHierarchyResolver.this.trace);

      trace.record(BindingContext.FILE_TO_PACKAGE_FRAGMENT, file, fragment);

      // Register files corresponding to this package
      // The trace currently does not support bi-di multimaps that would handle this task nicer
      FqName fqName = fragment.getFqName();
      Collection<JetFile> files = trace.get(PACKAGE_TO_FILES, fqName);
      if (files == null) {
        files = Sets.newIdentityHashSet();
      }
      files.add(file);
      trace.record(BindingContext.PACKAGE_TO_FILES, fqName, files);
      return fragment;
    }
  @Nullable
  private static KotlinLightClassForDecompiledDeclaration createLightClassForDecompiledKotlinFile(
      @NotNull JetFile file) {
    VirtualFile virtualFile = file.getVirtualFile();
    if (virtualFile == null) {
      return null;
    }

    JetClassOrObject classOrObject =
        singleOrNull(filterIsInstance(file.getDeclarations(), JetClassOrObject.class));

    ClsClassImpl javaClsClass = createClsJavaClassFromVirtualFile(file, virtualFile, classOrObject);
    if (javaClsClass == null) {
      return null;
    }
    return new KotlinLightClassForDecompiledDeclaration(javaClsClass, classOrObject);
  }
  private static void forceResolvePackageDeclarations(
      @NotNull Collection<JetFile> files, @NotNull KotlinCodeAnalyzer session) {
    for (JetFile file : files) {
      // SCRIPT: not supported
      if (file.isScript()) continue;

      FqName packageFqName = file.getPackageFqName();

      // make sure we create a package descriptor
      PackageViewDescriptor packageDescriptor =
          session.getModuleDescriptor().getPackage(packageFqName);
      if (packageDescriptor.isEmpty()) {
        LOG.warn(
            "No descriptor found for package "
                + packageFqName
                + " in file "
                + file.getName()
                + "\n"
                + file.getText());
        session.forceResolveAll();
        continue;
      }

      for (JetDeclaration declaration : file.getDeclarations()) {
        if (declaration instanceof JetFunction) {
          JetFunction jetFunction = (JetFunction) declaration;
          Name name = jetFunction.getNameAsSafeName();
          Collection<FunctionDescriptor> functions =
              packageDescriptor.getMemberScope().getFunctions(name, LookupLocation.NO_LOCATION);
          for (FunctionDescriptor descriptor : functions) {
            ForceResolveUtil.forceResolveAllContents(descriptor);
          }
        } else if (declaration instanceof JetProperty) {
          JetProperty jetProperty = (JetProperty) declaration;
          Name name = jetProperty.getNameAsSafeName();
          Collection<VariableDescriptor> properties =
              packageDescriptor.getMemberScope().getProperties(name, LookupLocation.NO_LOCATION);
          for (VariableDescriptor descriptor : properties) {
            ForceResolveUtil.forceResolveAllContents(descriptor);
          }
        } else if (declaration instanceof JetClassOrObject) {
          // Do nothing: we are not interested in classes
        } else {
          LOG.error(
              "Unsupported declaration kind: "
                  + declaration
                  + " in file "
                  + file.getName()
                  + "\n"
                  + file.getText());
        }
      }
    }
  }
예제 #10
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;
  }
예제 #11
0
  public static NavigatablePsiElement getPackageReference(@NotNull JetFile file, int partIndex) {
    JetNamespaceHeader header = file.getNamespaceHeader();
    if (header == null) {
      throw new IllegalArgumentException("Should be called only for files with namespace: " + file);
    }

    List<JetSimpleNameExpression> names = header.getNamespaceNames();
    if (!(0 <= partIndex && partIndex < names.size())) {
      throw new IndexOutOfBoundsException(
          String.format(
              "%s index for file with header %s is out of range", partIndex, header.getText()));
    }

    return names.get(partIndex);
  }
예제 #12
0
 private static BodyResolver createBodyResolver(
     DelegatingBindingTrace trace,
     JetFile file,
     BodyResolveContextForLazy bodyResolveContext,
     ModuleConfiguration moduleConfiguration) {
   TopDownAnalysisParameters parameters =
       new TopDownAnalysisParameters(
           Predicates.<PsiFile>alwaysTrue(),
           false,
           true,
           Collections.<AnalyzerScriptParameter>emptyList());
   InjectorForBodyResolve bodyResolve =
       new InjectorForBodyResolve(
           file.getProject(), parameters, trace, bodyResolveContext, moduleConfiguration);
   return bodyResolve.getBodyResolver();
 }
예제 #13
0
  private void checkModifiersAndAnnotationsInPackageDirective(JetFile file) {
    JetPackageDirective packageDirective = file.getPackageDirective();
    if (packageDirective == null) return;

    JetModifierList modifierList = packageDirective.getModifierList();
    if (modifierList == null) return;

    for (JetAnnotationEntry annotationEntry : modifierList.getAnnotationEntries()) {
      JetConstructorCalleeExpression calleeExpression = annotationEntry.getCalleeExpression();
      if (calleeExpression != null) {
        JetReferenceExpression reference = calleeExpression.getConstructorReferenceExpression();
        if (reference != null) {
          trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
        }
      }
    }
    AnnotationTargetChecker.INSTANCE$.check(packageDirective, trace);

    ModifiersChecker.reportIllegalModifiers(
        modifierList, Arrays.asList(JetTokens.MODIFIER_KEYWORDS_ARRAY), trace);
  }
  @Nullable
  private static ClsClassImpl createClsJavaClassFromVirtualFile(
      @NotNull final JetFile decompiledKotlinFile,
      @NotNull VirtualFile virtualFile,
      @Nullable final JetClassOrObject decompiledClassOrObject) {
    final PsiJavaFileStubImpl javaFileStub = getOrCreateJavaFileStub(virtualFile);
    if (javaFileStub == null) {
      return null;
    }
    PsiManager manager = PsiManager.getInstance(decompiledKotlinFile.getProject());
    ClsFileImpl fakeFile =
        new ClsFileImpl((PsiManagerImpl) manager, new ClassFileViewProvider(manager, virtualFile)) {
          @NotNull
          @Override
          public PsiElement getNavigationElement() {
            if (decompiledClassOrObject != null) {
              return decompiledClassOrObject.getNavigationElement().getContainingFile();
            }
            return super.getNavigationElement();
          }

          @NotNull
          @Override
          public PsiClassHolderFileStub getStub() {
            return javaFileStub;
          }

          @Override
          public PsiElement getMirror() {
            return decompiledKotlinFile;
          }
        };
    fakeFile.setPhysical(false);
    javaFileStub.setPsi(fakeFile);
    return (ClsClassImpl) single(fakeFile.getClasses());
  }
예제 #15
0
 public static void initTrace(BindingTrace bindingTrace, Collection<JetFile> files) {
   CodegenAnnotatingVisitor visitor = new CodegenAnnotatingVisitor(bindingTrace);
   for (JetFile file : allFilesInNamespaces(bindingTrace.getBindingContext(), files)) {
     file.accept(visitor);
   }
 }
예제 #16
0
 @NotNull
 public static FqName getFQName(@NotNull JetFile file) {
   JetNamespaceHeader header = file.getNamespaceHeader();
   return header != null ? header.getFqName() : FqName.ROOT;
 }
예제 #17
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;
  }