//===--- 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"
using namespace clang;
using namespace idx;

namespace  {

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

class 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 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 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 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);
}
