@NotNull
  private Collection<PsiElement> getDeclarationsByDescriptor(
      @NotNull DeclarationDescriptor declarationDescriptor) {
    Collection<PsiElement> declarations;
    if (declarationDescriptor instanceof PackageViewDescriptor) {
      final PackageViewDescriptor aPackage = (PackageViewDescriptor) declarationDescriptor;
      Collection<JetFile> files = trace.get(BindingContext.PACKAGE_TO_FILES, aPackage.getFqName());

      if (files == null) {
        return Collections
            .emptyList(); // package can be defined out of Kotlin sources, e. g. in library or Java
        // code
      }

      declarations =
          Collections2.transform(
              files,
              new Function<JetFile, PsiElement>() {
                @Override
                public PsiElement apply(@Nullable JetFile file) {
                  assert file != null : "File is null for aPackage " + aPackage;
                  return file.getPackageDirective().getNameIdentifier();
                }
              });
    } else {
      declarations =
          Collections.singletonList(
              BindingContextUtils.descriptorToDeclaration(
                  trace.getBindingContext(), declarationDescriptor));
    }
    return declarations;
  }
    @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);
    }
  private static Map<DeclarationDescriptor, List<String>> getExpectedLoadErrors(
      @NotNull PackageViewDescriptor packageFromJava) {
    final Map<DeclarationDescriptor, List<String>> map =
        new HashMap<DeclarationDescriptor, List<String>>();

    packageFromJava.acceptVoid(
        new DeclarationDescriptorVisitorEmptyBodies<Void, Void>() {
          @Override
          public Void visitPackageViewDescriptor(PackageViewDescriptor descriptor, Void data) {
            return visitDeclarationRecursively(descriptor, descriptor.getMemberScope());
          }

          @Override
          public Void visitClassDescriptor(ClassDescriptor descriptor, Void data) {
            return visitDeclarationRecursively(
                descriptor, descriptor.getDefaultType().getMemberScope());
          }

          @Override
          public Void visitFunctionDescriptor(FunctionDescriptor descriptor, Void data) {
            return visitDeclaration(descriptor);
          }

          @Override
          public Void visitPropertyDescriptor(PropertyDescriptor descriptor, Void data) {
            return visitDeclaration(descriptor);
          }

          private Void visitDeclaration(@NotNull DeclarationDescriptor descriptor) {
            AnnotationDescriptor annotation =
                descriptor.getAnnotations().findAnnotation(new FqName(ANNOTATION_CLASS_NAME));
            if (annotation == null) return null;

            // we expect exactly one annotation argument
            CompileTimeConstant<?> argument =
                annotation.getAllValueArguments().values().iterator().next();

            String error = (String) argument.getValue();
            //noinspection ConstantConditions
            List<String> errors = Arrays.asList(error.split("\\|"));

            map.put(descriptor, errors);

            return null;
          }

          private Void visitDeclarationRecursively(
              @NotNull DeclarationDescriptor descriptor, @NotNull JetScope memberScope) {
            for (DeclarationDescriptor member : memberScope.getAllDescriptors()) {
              member.acceptVoid(this);
            }

            return visitDeclaration(descriptor);
          }
        });

    return map;
  }
  private void checkRedeclarationsInPackages(@NotNull TopDownAnalysisContext c) {
    for (MutablePackageFragmentDescriptor packageFragment :
        Sets.newHashSet(c.getPackageFragments().values())) {
      PackageViewDescriptor packageView =
          packageFragment.getContainingDeclaration().getPackage(packageFragment.getFqName());
      JetScope packageViewScope = packageView.getMemberScope();
      Multimap<Name, DeclarationDescriptor> simpleNameDescriptors =
          packageFragment.getMemberScope().getDeclaredDescriptorsAccessibleBySimpleName();
      for (Name name : simpleNameDescriptors.keySet()) {
        // Keep only properties with no receiver
        Collection<DeclarationDescriptor> descriptors =
            Collections2.filter(
                simpleNameDescriptors.get(name),
                new Predicate<DeclarationDescriptor>() {
                  @Override
                  public boolean apply(@Nullable DeclarationDescriptor descriptor) {
                    if (descriptor instanceof PropertyDescriptor) {
                      PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
                      return propertyDescriptor.getReceiverParameter() == null;
                    }
                    return true;
                  }
                });
        ContainerUtil.addIfNotNull(descriptors, packageViewScope.getPackage(name));

        if (descriptors.size() > 1) {
          for (DeclarationDescriptor declarationDescriptor : descriptors) {
            for (PsiElement declaration : getDeclarationsByDescriptor(declarationDescriptor)) {
              assert declaration != null
                  : "Null declaration for descriptor: "
                      + declarationDescriptor
                      + " "
                      + (declarationDescriptor != null
                          ? DescriptorRenderer.FQ_NAMES_IN_TYPES.render(declarationDescriptor)
                          : "");
              trace.report(
                  REDECLARATION.on(declaration, declarationDescriptor.getName().asString()));
            }
          }
        }
      }
    }
  }