コード例 #1
0
void PHPDocVisitor::OnEntity(PHPEntityBase::Ptr_t entity)
{
    // Locate a comment for this entity
    entity->SetFilename(m_sourceFile.GetFilename());

    if(!entity->GetDocComment().IsEmpty()) {
        // PHPDoc was already assigned to this entity during the parsing phase
        if(entity->Is(kEntityTypeClass)) {
            // Process @property tags here
            PHPDocComment docComment(m_sourceFile, entity->GetDocComment());
            if(!docComment.GetProperties().empty()) {
                // Got some @properties
                std::for_each(docComment.GetProperties().begin(), docComment.GetProperties().end(),
                    [&](PHPDocComment::Property::Map_t::value_type& p) {
                        PHPEntityBase::Ptr_t child = entity->FindChild(p.second.name);
                        if(!child) {
                            // No child of this type, create a new property and add it
                            child.Reset(new PHPEntityVariable());
                            child->SetFilename(m_sourceFile.GetFilename());
                            child->SetLine(entity->GetLine());
                            child->Cast<PHPEntityVariable>()->SetTypeHint(p.second.type);
                            child->Cast<PHPEntityVariable>()->SetFlag(kVar_Member); // Member variable
                            child->Cast<PHPEntityVariable>()->SetFlag(kVar_Public); // Public access
                            child->SetShortName(p.second.name);
                            child->SetFullName(p.second.name);
                            entity->AddChild(child);
                        }
                    });
            } else if(!docComment.GetMethods().empty()) {
                std::for_each(docComment.GetMethods().begin(), docComment.GetMethods().end(),
                    [&](PHPEntityBase::Ptr_t method) { entity->AddChild(method); });
            }
        }
    } else {
        // search for the comment placed at the top of the variable
        // this is why we use here -1
        int lineNum = (entity->GetLine() - 1);

        // for debugging purposes
        wxString entityName = entity->GetShortName();
        wxUnusedVar(entityName);

        std::map<int, phpLexerToken>::iterator iter = m_comments.find(lineNum);
        if(iter == m_comments.end()) {
            // try to locate a comment on the same line
            ++lineNum;
            iter = m_comments.find(lineNum);
        }

        if(iter != m_comments.end()) {

            // we got a match
            entity->SetDocComment(iter->second.Text());
            m_comments.erase(iter);

            PHPDocComment docComment(m_sourceFile, entity->GetDocComment());
            if(entity->Is(kEntityTypeFunction) && !docComment.GetReturn().IsEmpty()) {
                entity->Cast<PHPEntityFunction>()->SetReturnValue(docComment.GetReturn());
            } else if(entity->Is(kEntityTypeVariable) && !entity->Cast<PHPEntityVariable>()->IsFunctionArg()) {
                // A global variable, const or a member
                entity->Cast<PHPEntityVariable>()->SetTypeHint(docComment.GetVar());
            }

        } else if(entity->Is(kEntityTypeVariable) && entity->Parent() && entity->Parent()->Is(kEntityTypeFunction) &&
            entity->Cast<PHPEntityVariable>()->IsFunctionArg()) {
            // A function argument
            PHPDocComment docComment(m_sourceFile, entity->Parent()->GetDocComment());
            wxString typeHint = docComment.GetParam(entity->GetFullName());
            if(!typeHint.IsEmpty()) {
                entity->Cast<PHPEntityVariable>()->SetTypeHint(typeHint);
            }
        }
    }
}
コード例 #2
0
ファイル: func.cpp プロジェクト: mediaprojects/hiphop-php
void Func::getFuncInfo(ClassInfo::MethodInfo* mi) const {
  ASSERT(mi);
  if (info() != NULL) {
    // Very large operator=() invocation.
    *mi = *info();
    // Deep copy the vectors of mi-owned pointers.
    cloneMembers(mi->parameters);
    cloneMembers(mi->staticVariables);
  } else {
    // hphpc and hphpi set the ClassInfo::VariableArguments attribute if the
    // method contains a call to func_get_arg, func_get_args, or func_num_args.
    // We don't do this in the VM currently and hopefully we never will need to.
    int attr = 0;
    if (m_attrs & AttrReference) attr |= ClassInfo::IsReference;
    if (m_attrs & AttrAbstract) attr |= ClassInfo::IsAbstract;
    if (m_attrs & AttrFinal) attr |= ClassInfo::IsFinal;
    if (m_attrs & AttrProtected) attr |= ClassInfo::IsProtected;
    if (m_attrs & AttrPrivate) attr |= ClassInfo::IsPrivate;
    if (m_attrs & AttrStatic) attr |= ClassInfo::IsStatic;
    if (!(attr & ClassInfo::IsProtected || attr & ClassInfo::IsPrivate)) {
      attr |= ClassInfo::IsPublic;
    }
    if (preClass() &&
        (!strcasecmp(m_name->data(), "__construct") ||
         (!(preClass()->attrs() & AttrTrait) &&
          !strcasecmp(m_name->data(), preClass()->name()->data()) &&
          !preClass()->hasMethod(String("__construct").get())))) {
      attr |= ClassInfo::IsConstructor;
    }
    if (attr == 0) attr = ClassInfo::IsNothing;
    mi->attribute = (ClassInfo::Attribute)attr;
    mi->name = m_name->data();
    mi->file = m_unit->filepath()->data();
    mi->line1 = line1();
    mi->line2 = line2();
    if (docComment() && !docComment()->empty()) {
      mi->docComment = docComment()->data();
    }
    // Get the parameter info
    for (unsigned i = 0; i < unsigned(m_numParams); ++i) {
      ClassInfo::ParameterInfo* pi = new ClassInfo::ParameterInfo;
      attr = 0;
      if (byRef(i)) {
        attr |= ClassInfo::IsReference;
      }
      if (attr == 0) {
        attr = ClassInfo::IsNothing;
      }
      const ParamInfoVec& params = shared()->m_params;
      const ParamInfo& fpi = params[i];
      pi->attribute = (ClassInfo::Attribute)attr;
      pi->name = shared()->m_localNames[i]->data();
      if (params.size() <= i || !fpi.hasDefaultValue()) {
        pi->value = NULL;
        pi->valueText = "";
      } else {
        if (fpi.hasScalarDefaultValue()) {
          // Most of the time the default value is scalar, so we can
          // avoid evaling in the common case
          pi->value = strdup(f_serialize(
            tvAsVariant((TypedValue*)&fpi.defaultValue())).get()->data());
        } else {
          // Eval PHP code to get default value, and serialize the result. Note
          // that access of undefined class constants can cause the eval() to
          // fatal. Zend lets such fatals propagate, so don't bother catching
          // exceptions here.
          CVarRef v = g_vmContext->getEvaledArg(fpi.phpCode());
          pi->value = strdup(f_serialize(v).get()->data());
        }
        // This is a raw char*, but its lifetime should be at least as long
        // as the the Func*. At this writing, it's a merged anon string
        // owned by ParamInfo.
        pi->valueText = fpi.phpCode()->data();
      }
      pi->type = fpi.typeConstraint().exists() ?
        fpi.typeConstraint().typeName()->data() : "";
      mi->parameters.push_back(pi);
    }
    // XXX ConstantInfo is abused to store static variable metadata, and
    // although ConstantInfo::callbacks provides a mechanism for registering
    // callbacks, it does not pass enough information through for the callback
    // functions to know the function context whence the callbacks came.
    // Furthermore, the callback mechanism isn't employed in a fashion that
    // would allow repeated introspection to reflect updated values.
    // Supporting introspection of static variable values will require
    // different plumbing than currently exists in ConstantInfo.
    const SVInfoVec& staticVars = shared()->m_staticVars;
    for (SVInfoVec::const_iterator it = staticVars.begin();
         it != staticVars.end(); ++it) {
      ClassInfo::ConstantInfo* ci = new ClassInfo::ConstantInfo;
      ci->name = *(String*)(&(*it).name);
      if ((*it).phpCode != NULL) {
        ci->valueLen = (*it).phpCode->size();
        ci->valueText = (*it).phpCode->data();
      } else {
        ci->valueLen = 0;
        ci->valueText = "";
      }

      mi->staticVariables.push_back(ci);
    }
  }
}