//===--- Analyzer.cpp - Analysis for indexing information -------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Analyzer interface.
//
//===----------------------------------------------------------------------===//

#include "clang/Index/Analyzer.h"
#include "clang/Index/Entity.h"
#include "clang/Index/TranslationUnit.h"
#include "clang/Index/Handlers.h"
#include "clang/Index/ASTLocation.h"
#include "clang/Index/GlobalSelector.h"
#include "clang/Index/DeclReferenceMap.h"
#include "clang/Index/SelectorMap.h"
#include "clang/Index/IndexProvider.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprObjC.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/Support/Compiler.h"
using namespace clang;
using namespace idx;

namespace  {

//===----------------------------------------------------------------------===//
// DeclEntityAnalyzer Implementation
//===----------------------------------------------------------------------===//

class VISIBILITY_HIDDEN DeclEntityAnalyzer : public TranslationUnitHandler {
  Entity Ent;
  TULocationHandler &TULocHandler;

public:
  DeclEntityAnalyzer(Entity ent, TULocationHandler &handler)
    : Ent(ent), TULocHandler(handler) { }

  virtual void Handle(TranslationUnit *TU) {
    assert(TU && "Passed null translation unit");

    Decl *D = Ent.getDecl(TU->getASTContext());
    assert(D && "Couldn't resolve Entity");

    for (Decl::redecl_iterator I = D->redecls_begin(),
                               E = D->redecls_end(); I != E; ++I)
      TULocHandler.Handle(TULocation(TU, ASTLocation(*I)));
  }
};

//===----------------------------------------------------------------------===//
// RefEntityAnalyzer Implementation
//===----------------------------------------------------------------------===//

class VISIBILITY_HIDDEN RefEntityAnalyzer : public TranslationUnitHandler {
  Entity Ent;
  TULocationHandler &TULocHandler;

public:
  RefEntityAnalyzer(Entity ent, TULocationHandler &handler)
    : Ent(ent), TULocHandler(handler) { }

  virtual void Handle(TranslationUnit *TU) {
    assert(TU && "Passed null translation unit");

    Decl *D = Ent.getDecl(TU->getASTContext());
    assert(D && "Couldn't resolve Entity");
    NamedDecl *ND = dyn_cast<NamedDecl>(D);
    if (!ND)
      return;

    DeclReferenceMap &RefMap = TU->getDeclReferenceMap();
    for (DeclReferenceMap::astlocation_iterator
           I = RefMap.refs_begin(ND), E = RefMap.refs_end(ND); I != E; ++I)
      TULocHandler.Handle(TULocation(TU, *I));
  }
};

//===----------------------------------------------------------------------===//
// RefSelectorAnalyzer Implementation
//===----------------------------------------------------------------------===//

/// \brief Accepts an ObjC method and finds all message expressions that this
/// method may respond to.
class VISIBILITY_HIDDEN RefSelectorAnalyzer : public TranslationUnitHandler {
  Program &Prog;
  TULocationHandler &TULocHandler;

  // The original ObjCInterface associated with the method.
  Entity IFaceEnt;
  GlobalSelector GlobSel;
  bool IsInstanceMethod;

  /// \brief Super classes of the ObjCInterface.
  typedef llvm::SmallSet<Entity, 16> EntitiesSetTy;
  EntitiesSetTy HierarchyEntities;

public:
  RefSelectorAnalyzer(ObjCMethodDecl *MD,
                      Program &prog, TULocationHandler &handler)
    : Prog(prog), TULocHandler(handler) {
    assert(MD);

    // FIXME: Protocol methods.
    assert(!isa<ObjCProtocolDecl>(MD->getDeclContext()) &&
           "Protocol methods not supported yet");

    ObjCInterfaceDecl *IFD = MD->getClassInterface();
    assert(IFD);
    IFaceEnt = Entity::get(IFD, Prog);
    GlobSel = GlobalSelector::get(MD->getSelector(), Prog);
    IsInstanceMethod = MD->isInstanceMethod();

    for (ObjCInterfaceDecl *Cls = IFD->getSuperClass();
           Cls; Cls = Cls->getSuperClass())
      HierarchyEntities.insert(Entity::get(Cls, Prog));
  }

  virtual void Handle(TranslationUnit *TU) {
    assert(TU && "Passed null translation unit");

    ASTContext &Ctx = TU->getASTContext();
    // Null means it doesn't exist in this translation unit.
    ObjCInterfaceDecl *IFace =
        cast_or_null<ObjCInterfaceDecl>(IFaceEnt.getDecl(Ctx));
    Selector Sel = GlobSel.getSelector(Ctx);

    SelectorMap &SelMap = TU->getSelectorMap();
    for (SelectorMap::astlocation_iterator
           I = SelMap.refs_begin(Sel), E = SelMap.refs_end(Sel); I != E; ++I) {
      if (ValidReference(*I, IFace))
        TULocHandler.Handle(TULocation(TU, *I));
    }
  }

  /// \brief Determines whether the given message expression is likely to end
  /// up at the given interface decl.
  ///
  /// It returns true "eagerly", meaning it will return false only if it can
  /// "prove" statically that the interface cannot accept this message.
  bool ValidReference(ASTLocation ASTLoc, ObjCInterfaceDecl *IFace) {
    assert(ASTLoc.isStmt());

    // FIXME: Finding @selector references should be through another Analyzer
    // method, like FindSelectors.
    if (isa<ObjCSelectorExpr>(ASTLoc.AsStmt()))
      return false;

    ObjCInterfaceDecl *MsgD = 0;
    ObjCMessageExpr *Msg = cast<ObjCMessageExpr>(ASTLoc.AsStmt());

    if (Msg->getReceiver()) {
      const ObjCObjectPointerType *OPT =
          Msg->getReceiver()->getType()->getAsObjCInterfacePointerType();

      // Can be anything! Accept it as a possibility..
      if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType())
        return true;

      // Expecting class method.
      if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType())
        return !IsInstanceMethod;

      MsgD = OPT->getInterfaceDecl();
      assert(MsgD);

      // Should be an instance method.
      if (!IsInstanceMethod)
        return false;

    } else {
      // Expecting class method.
      if (IsInstanceMethod)
        return false;

      MsgD = Msg->getClassInfo().first;
      // FIXME: Case when we only have an identifier.
      assert(MsgD && "Identifier only");
    }

    assert(MsgD);

    // Same interface ? We have a winner!
    if (MsgD == IFace)
      return true;

    // If the message interface is a superclass of the original interface,
    // accept this message as a possibility.
    if (HierarchyEntities.count(Entity::get(MsgD, Prog)))
      return true;

    // If the message interface is a subclass of the original interface, accept
    // the message unless there is a subclass in the hierarchy that will
    // "steal" the message (thus the message "will go" to the subclass and not
    /// the original interface).
    if (IFace) {
      Selector Sel = Msg->getSelector();
      for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
        if (Cls == IFace)
          return true;
        if (Cls->getMethod(Sel, IsInstanceMethod))
          return false;
      }
    }

    // The interfaces are unrelated, don't accept the message.
    return false;
  }
};

//===----------------------------------------------------------------------===//
// MessageAnalyzer Implementation
//===----------------------------------------------------------------------===//

/// \brief Accepts an ObjC message expression and finds all methods that may
/// respond to it.
class VISIBILITY_HIDDEN MessageAnalyzer : public TranslationUnitHandler {
  Program &Prog;
  TULocationHandler &TULocHandler;

  // The ObjCInterface associated with the message. Can be null/invalid.
  Entity MsgIFaceEnt;
  GlobalSelector GlobSel;
  bool CanBeInstanceMethod;
  bool CanBeClassMethod;

  /// \brief Super classes of the ObjCInterface.
  typedef llvm::SmallSet<Entity, 16> EntitiesSetTy;
  EntitiesSetTy HierarchyEntities;

  /// \brief The interface in the message interface hierarchy that "intercepts"
  /// the selector.
  Entity ReceiverIFaceEnt;

public:
  MessageAnalyzer(ObjCMessageExpr *Msg,
                  Program &prog, TULocationHandler &handler)
    : Prog(prog), TULocHandler(handler),
      CanBeInstanceMethod(false),
      CanBeClassMethod(false) {

    assert(Msg);

    ObjCInterfaceDecl *MsgD = 0;

    while (true) {
      if (Msg->getReceiver() == 0) {
        CanBeClassMethod = true;
        MsgD = Msg->getClassInfo().first;
        // FIXME: Case when we only have an identifier.
        assert(MsgD && "Identifier only");
        break;
      }

      const ObjCObjectPointerType *OPT =
          Msg->getReceiver()->getType()->getAsObjCInterfacePointerType();

      if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()) {
        CanBeInstanceMethod = CanBeClassMethod = true;
        break;
      }

      if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) {
        CanBeClassMethod = true;
        break;
      }

      MsgD = OPT->getInterfaceDecl();
      assert(MsgD);
      CanBeInstanceMethod = true;
      break;
    }

    assert(CanBeInstanceMethod || CanBeClassMethod);

    Selector sel = Msg->getSelector();
    assert(!sel.isNull());

    MsgIFaceEnt = Entity::get(MsgD, Prog);
    GlobSel = GlobalSelector::get(sel, Prog);

    if (MsgD) {
      for (ObjCInterfaceDecl *Cls = MsgD->getSuperClass();
             Cls; Cls = Cls->getSuperClass())
        HierarchyEntities.insert(Entity::get(Cls, Prog));

      // Find the interface in the hierarchy that "receives" the message.
      for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
        bool isReceiver = false;

        ObjCInterfaceDecl::lookup_const_iterator Meth, MethEnd;
        for (llvm::tie(Meth, MethEnd) = Cls->lookup(sel);
               Meth != MethEnd; ++Meth) {
          if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth))
            if ((MD->isInstanceMethod() && CanBeInstanceMethod) ||
                (MD->isClassMethod()    && CanBeClassMethod)) {
              isReceiver = true;
              break;
            }
        }

        if (isReceiver) {
          ReceiverIFaceEnt = Entity::get(Cls, Prog);
          break;
        }
      }
    }
  }

  virtual void Handle(TranslationUnit *TU) {
    assert(TU && "Passed null translation unit");
    ASTContext &Ctx = TU->getASTContext();

    // Null means it doesn't exist in this translation unit or there was no
    // interface that was determined to receive the original message.
    ObjCInterfaceDecl *ReceiverIFace =
        cast_or_null<ObjCInterfaceDecl>(ReceiverIFaceEnt.getDecl(Ctx));

    // No subclass for the original receiver interface, so it remains the
    // receiver.
    if (ReceiverIFaceEnt.isValid() && ReceiverIFace == 0)
      return;

    // Null means it doesn't exist in this translation unit or there was no
    // interface associated with the message in the first place.
    ObjCInterfaceDecl *MsgIFace =
        cast_or_null<ObjCInterfaceDecl>(MsgIFaceEnt.getDecl(Ctx));

    Selector Sel = GlobSel.getSelector(Ctx);
    SelectorMap &SelMap = TU->getSelectorMap();
    for (SelectorMap::method_iterator
           I = SelMap.methods_begin(Sel), E = SelMap.methods_end(Sel);
           I != E; ++I) {
      ObjCMethodDecl *D = *I;
      if (ValidMethod(D, MsgIFace, ReceiverIFace)) {
        for (ObjCMethodDecl::redecl_iterator
               RI = D->redecls_begin(), RE = D->redecls_end(); RI != RE; ++RI)
          TULocHandler.Handle(TULocation(TU, ASTLocation(*RI)));
      }
    }
  }

  /// \brief Determines whether the given method is likely to accept the
  /// original message.
  ///
  /// It returns true "eagerly", meaning it will return false only if it can
  /// "prove" statically that the method cannot accept the original message.
  bool ValidMethod(ObjCMethodDecl *D, ObjCInterfaceDecl *MsgIFace,
                   ObjCInterfaceDecl *ReceiverIFace) {
    assert(D);

    // FIXME: Protocol methods ?
    if (isa<ObjCProtocolDecl>(D->getDeclContext()))
      return false;

    // No specific interface associated with the message. Can be anything.
    if (MsgIFaceEnt.isInvalid())
      return true;

    if ((!CanBeInstanceMethod && D->isInstanceMethod()) ||
        (!CanBeClassMethod    && D->isClassMethod()))
      return false;

    ObjCInterfaceDecl *IFace = D->getClassInterface();
    assert(IFace);

    // If the original message interface is the same or a superclass of the
    // given interface, accept the method as a possibility.
    if (MsgIFace && MsgIFace->isSuperClassOf(IFace))
      return true;

    if (ReceiverIFace) {
      // The given interface, "overrides" the receiver.
      if (ReceiverIFace->isSuperClassOf(IFace))
        return true;
    } else {
      // No receiver was found for the original message.
      assert(ReceiverIFaceEnt.isInvalid());

      // If the original message interface is a subclass of the given interface,
      // accept the message.
      if (HierarchyEntities.count(Entity::get(IFace, Prog)))
        return true;
    }

    // The interfaces are unrelated, or the receiver interface wasn't
    // "overriden".
    return false;
  }
};

} // end anonymous namespace

//===----------------------------------------------------------------------===//
// Analyzer Implementation
//===----------------------------------------------------------------------===//

void Analyzer::FindDeclarations(Decl *D, TULocationHandler &Handler) {
  assert(D && "Passed null declaration");
  Entity Ent = Entity::get(D, Prog);
  if (Ent.isInvalid())
    return;

  DeclEntityAnalyzer DEA(Ent, Handler);
  Idxer.GetTranslationUnitsFor(Ent, DEA);
}

void Analyzer::FindReferences(Decl *D, TULocationHandler &Handler) {
  assert(D && "Passed null declaration");
  if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
    RefSelectorAnalyzer RSA(MD, Prog, Handler);
    GlobalSelector Sel = GlobalSelector::get(MD->getSelector(), Prog);
    Idxer.GetTranslationUnitsFor(Sel, RSA);
    return;
  }

  Entity Ent = Entity::get(D, Prog);
  if (Ent.isInvalid())
    return;

  RefEntityAnalyzer REA(Ent, Handler);
  Idxer.GetTranslationUnitsFor(Ent, REA);
}

/// \brief Find methods that may respond to the given message and pass them
/// to Handler.
void Analyzer::FindObjCMethods(ObjCMessageExpr *Msg,
                               TULocationHandler &Handler) {
  assert(Msg);
  MessageAnalyzer MsgAnalyz(Msg, Prog, Handler);
  GlobalSelector GlobSel = GlobalSelector::get(Msg->getSelector(), Prog);
  Idxer.GetTranslationUnitsFor(GlobSel, MsgAnalyz);
}
