@NotNull
 /*package*/ MemberScope getMemberScopeDeclaredIn(
     @NotNull KtDeclaration declaration, @NotNull LookupLocation location) {
   KtDeclaration parentDeclaration = KtStubbedPsiUtil.getContainingDeclaration(declaration);
   boolean isTopLevel = parentDeclaration == null;
   if (isTopLevel) { // for top level declarations we search directly in package because of
     // possible conflicts with imports
     FqName fqName = ((KtFile) declaration.getContainingFile()).getPackageFqName();
     LazyPackageDescriptor packageDescriptor =
         topLevelDescriptorProvider.getPackageFragment(fqName);
     assert packageDescriptor != null;
     return packageDescriptor.getMemberScope();
   } else {
     if (parentDeclaration instanceof KtClassOrObject) {
       return getClassDescriptor((KtClassOrObject) parentDeclaration, location)
           .getUnsubstitutedMemberScope();
     } else if (parentDeclaration instanceof KtScript) {
       return getScriptDescriptor((KtScript) parentDeclaration, location)
           .getUnsubstitutedMemberScope();
     } else {
       throw new IllegalStateException(
           "Don't call this method for local declarations: "
               + declaration
               + "\n"
               + PsiUtilsKt.getElementTextWithContext(declaration));
     }
   }
 }
  @NotNull
  private DeclarationDescriptor resolveToDescriptor(
      @NotNull KtDeclaration declaration, final boolean track) {
    DeclarationDescriptor result =
        declaration.accept(
            new KtVisitor<DeclarationDescriptor, Void>() {
              @NotNull
              private LookupLocation lookupLocationFor(
                  @NotNull KtDeclaration declaration, boolean isTopLevel) {
                return isTopLevel && track
                    ? new KotlinLookupLocation(declaration)
                    : NoLookupLocation.WHEN_RESOLVE_DECLARATION;
              }

              @Override
              public DeclarationDescriptor visitClass(@NotNull KtClass klass, Void data) {
                return getClassDescriptor(klass, lookupLocationFor(klass, klass.isTopLevel()));
              }

              @Override
              public DeclarationDescriptor visitObjectDeclaration(
                  @NotNull KtObjectDeclaration declaration, Void data) {
                return getClassDescriptor(
                    declaration, lookupLocationFor(declaration, declaration.isTopLevel()));
              }

              @Override
              public DeclarationDescriptor visitTypeParameter(
                  @NotNull KtTypeParameter parameter, Void data) {
                KtTypeParameterListOwner ownerElement =
                    PsiTreeUtil.getParentOfType(parameter, KtTypeParameterListOwner.class);
                assert ownerElement != null
                    : "Owner not found for type parameter: " + parameter.getText();
                DeclarationDescriptor ownerDescriptor =
                    resolveToDescriptor(ownerElement, /*track =*/ false);

                List<TypeParameterDescriptor> typeParameters;
                if (ownerDescriptor instanceof CallableDescriptor) {
                  CallableDescriptor callableDescriptor = (CallableDescriptor) ownerDescriptor;
                  typeParameters = callableDescriptor.getTypeParameters();
                } else if (ownerDescriptor instanceof ClassDescriptor) {
                  ClassDescriptor classDescriptor = (ClassDescriptor) ownerDescriptor;
                  typeParameters = classDescriptor.getTypeConstructor().getParameters();
                } else {
                  throw new IllegalStateException(
                      "Unknown owner kind for a type parameter: " + ownerDescriptor);
                }

                Name name = parameter.getNameAsSafeName();
                for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
                  if (typeParameterDescriptor.getName().equals(name)) {
                    return typeParameterDescriptor;
                  }
                }

                throw new IllegalStateException(
                    "Type parameter " + name + " not found for " + ownerDescriptor);
              }

              @Override
              public DeclarationDescriptor visitNamedFunction(
                  @NotNull KtNamedFunction function, Void data) {
                LookupLocation location = lookupLocationFor(function, function.isTopLevel());
                MemberScope scopeForDeclaration = getMemberScopeDeclaredIn(function, location);
                scopeForDeclaration.getContributedFunctions(function.getNameAsSafeName(), location);
                return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, function);
              }

              @Override
              public DeclarationDescriptor visitParameter(
                  @NotNull KtParameter parameter, Void data) {
                PsiElement grandFather = parameter.getParent().getParent();
                if (grandFather instanceof KtPrimaryConstructor) {
                  KtClassOrObject jetClass =
                      ((KtPrimaryConstructor) grandFather).getContainingClassOrObject();
                  // This is a primary constructor parameter
                  ClassDescriptor classDescriptor =
                      getClassDescriptor(jetClass, lookupLocationFor(jetClass, false));
                  if (parameter.hasValOrVar()) {
                    classDescriptor
                        .getDefaultType()
                        .getMemberScope()
                        .getContributedVariables(
                            parameter.getNameAsSafeName(), lookupLocationFor(parameter, false));
                    return getBindingContext()
                        .get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
                  } else {
                    ConstructorDescriptor constructor =
                        classDescriptor.getUnsubstitutedPrimaryConstructor();
                    assert constructor != null
                        : "There are constructor parameters found, so a constructor should also exist";
                    constructor.getValueParameters();
                    return getBindingContext().get(BindingContext.VALUE_PARAMETER, parameter);
                  }
                } else if (grandFather instanceof KtNamedFunction) {
                  FunctionDescriptor function =
                      (FunctionDescriptor) visitNamedFunction((KtNamedFunction) grandFather, data);
                  function.getValueParameters();
                  return getBindingContext().get(BindingContext.VALUE_PARAMETER, parameter);
                } else if (grandFather instanceof KtSecondaryConstructor) {
                  ConstructorDescriptor constructorDescriptor =
                      (ConstructorDescriptor)
                          visitSecondaryConstructor((KtSecondaryConstructor) grandFather, data);
                  constructorDescriptor.getValueParameters();
                  return getBindingContext().get(BindingContext.VALUE_PARAMETER, parameter);
                } else {
                  // TODO: support parameters in accessors and other places(?)
                  return super.visitParameter(parameter, data);
                }
              }

              @Override
              public DeclarationDescriptor visitSecondaryConstructor(
                  @NotNull KtSecondaryConstructor constructor, Void data) {
                getClassDescriptor(
                        (KtClassOrObject) constructor.getParent().getParent(),
                        lookupLocationFor(constructor, false))
                    .getConstructors();
                return getBindingContext().get(BindingContext.CONSTRUCTOR, constructor);
              }

              @Override
              public DeclarationDescriptor visitPrimaryConstructor(
                  @NotNull KtPrimaryConstructor constructor, Void data) {
                getClassDescriptor(
                        constructor.getContainingClassOrObject(),
                        lookupLocationFor(constructor, false))
                    .getConstructors();
                return getBindingContext().get(BindingContext.CONSTRUCTOR, constructor);
              }

              @Override
              public DeclarationDescriptor visitProperty(@NotNull KtProperty property, Void data) {
                LookupLocation location = lookupLocationFor(property, property.isTopLevel());
                MemberScope scopeForDeclaration = getMemberScopeDeclaredIn(property, location);
                scopeForDeclaration.getContributedVariables(property.getNameAsSafeName(), location);
                return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, property);
              }

              @Override
              public DeclarationDescriptor visitScript(@NotNull KtScript script, Void data) {
                return getScriptDescriptor(script, lookupLocationFor(script, true));
              }

              @Override
              public DeclarationDescriptor visitKtElement(@NotNull KtElement element, Void data) {
                throw new IllegalArgumentException(
                    "Unsupported declaration type: "
                        + element
                        + " "
                        + PsiUtilsKt.getElementTextWithContext(element));
              }
            },
            null);
    if (result == null) {
      throw new NoDescriptorForDeclarationException(declaration);
    }
    return result;
  }