If I have a macro as such
#define FOO(x) void x()
That I would us as such
class Test {
public:
/*
* #brief My func1
*/
FOO(func1);
/*
* #brief My func2
*/
FOO(func2);
};
Is there a way to have Doxygen, when it expands to FOO macro, put each expanded function into a group?
For example, I would like the macro expansion + Doxygen to result in something equivalent to if I have written:
class Test {
public:
/**
* #name MyGroup
* #{
*/
/*
* #brief My func1
*/
void func1();
/** #} */
/**
* #name MyGroup
* #{
*/
/*
* #brief My func1
*/
void func2();
/** #} */
};
Thus, I would like some way to have Doxygen document that all the functions generated by the macro are grouped together while still maintaining the comments for each individual function.
Please let me know if this does not make sense.
Related
Here is the code:
namespace Test {
/// Base class
class Base
{
public:
/// Method foo
/// #param a ParamA
/// #param b ParamB
virtual void foo(char a, int b);
/// Method foo
/// #param a ParamA
/// #param b ParamB
/// #param c ParamC
virtual void foo(char a, int b, char c);
/// Method foo
/// #param m ParamM
template<typename T>
void foo(std::vector<T> m)
{
}
};
/// Derived class
class Derived : public Base
{
public:
using Base::foo;
/// Method foo
/// #param a ParamA
/// #param b ParamB
void foo(char a, int b) override;
};
}
If this code will be processed with Doxygen. We get the strange error:
Error: argument 'm' of command #param is not found in the argument list of Test::Derived::foo(typename T) (warning treated as error, aborting now)
If commenting line using Base::foo; the Doxygen correctly processing this file.
Looks like a bug in Doxygen, but is anybody know a workaround for that?
With the doxygen versions till doxygen 1.9.1 (inclusive) I was able to reproduce the problem.
The problem is gone with the versions 1.9.2 and higher.
The current doxygen version is 1.9.4 (5d15657a55555e6181a7830a5c723af75e7577e2)
The solution for this problem is to update your doxygen version to the current doxygen version.
// in some file
/**
* #typedef myspace
* #property {Object} models
* #property {Object} services
*/
// in other files
/** #typedef myspace.models.ModelA */
class ModelA { ... }
/** #typedef myspace.models.ModelB */
class ModelB { ... }
/** #typedef myspace.services.ServiceA */
class ServiceA { ... }
How to define classes with JSDoc if I want to make them as members of the namespaces myspace.models and myspace.services?
You need using #namespace and #memberOf, I believe
Can a class be put into a member group like a function? For example,
/** Some module.
*
* #defgroup Group
* #{
*/
/** #name Same utility
*
*/
/** #{*/
/** Class A.
*
*/
class A
{
};
/** Function.
*
*/
void f();
/** #}*/ // end Same utility
/** Class B.
*
*/
class B
{
};
/** #}*/ // end Group
The above code will put f() into a custom section called "Same utility", but the document for class A is still in the section "class" with class B. So is there a way to group the class A into a member group as well?
I'm trying create something using ZF2 and Doctrine 2. But I'm kind lost about what I want to achieve.
First I now that using $em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager'); inside controller it will work.
But what I want it's something more elaborated, like this:
class BaseModel extends Doctrine\ORM\EntityManager
{
public function save()
{
$em->persist($this);
$em->flush();
}
}
/**
* #ORM\Entity
*/
class Customer extends BaseModel
{
// getters setters
}
class IndexController
{
public function indexAction()
{
$customer = new Customer();
$customer->setName('asd');
$customer->save();
Customer::findAll();
}
}
I have started this:
namespace Ws\Model;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorAwareTrait;
class BaseModel implements ServiceLocatorAwareInterface
{
use ServiceLocatorAwareTrait;
public function write() {
$em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
return $em->getRepository(__CLASS__);
}
}
But without success.
I understand that this is more than one question, but is it possible help me here even passing some links that could help me in this journey?
Thank you.
Did you have a look at the Zend\ServiceManager\ServiceLocatorAwareTrait implemntation ? It just give you the getter and setter, but of course, if you never set it, you will never get it. So $this->getServiceLocator() will always return null.
You'd better use dependency injection (never inject service locator but the needed services) or maybe, as pointed by #Cerad, use Doctrine the way it was designed.
You're in luck. Just created that myself to use in my own vendor package.
You're code is messy though, I'm going to assume that the "Model" your refer to is the Entity and not a combination of Entity and Repository.
However, to the code!
Make special note of the namespaces and organize folder structure and file names accordingly!
File: repoName/src/Entity/AbstractEntity.php
<?php
namespace Company\Core;
use Doctrine\ORM\Mapping as ORM;
use Company\Core\Listener\ServiceLocatorAwareEntity;
/**
* Class AbstractEntity
* #package Company\Core\Entity
*
* #ORM\MappedSuperclass
* #ORM\HasLifecycleCallbacks
*/
abstract class AbstractEntity extends ServiceLocatorAwareEntity
{
/**
* #var int
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #param int $id
* #return AbstractEntity
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
}
File: repoName/src/Service/AbstractEntityService.php
<?php
namespace Company\Core\Service;
use Doctrine\ORM\EntityManager;
use Company\Core\Interfaces\EntityServiceInterface;
abstract class AbstractEntityService implements EntityServiceInterface
{
/**
* #var EntityManager
*/
protected $entityManager;
/**
* AbstractEntityService constructor.
* #param EntityManager $entityManager
*/
public function __construct(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
/**
* #return EntityManager
*/
public function getEntityManager()
{
return $this->entityManager;
}
/**
* #return \Doctrine\ORM\EntityRepository
*/
public function getEntityRepository()
{
return $this->getEntityManager()->getRepository(__CLASS__);
}
//Feel free to add more functions here that you want all of your Entities to have
}
File: repoName/src/Interfaces/EntityServiceInterface.php (note, plural "interfaces" folder, as "interface" is protected name in PHP)
<?php
namespace Company\Core\Interfaces;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Repository\RepositoryFactory;
interface EntityServiceInterface
{
/**
* #return EntityManager
*/
public function getEntityManager();
/**
* #return RepositoryFactory
*/
public function getEntityRepository();
//Feel free to add more functions here
}
File: repoName/src/Listener/ServiceLocatorAwareEntity.php
<?php
namespace Company\Core\Listener;
use Zend\Di\ServiceLocator;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class ServiceLocatorAwareEntity implements ServiceLocatorAwareInterface
{
protected $sm;
/**
* Set the service locator
*
* #param ServiceLocatorInterface $sm
*
* #return void
*/
public function setServiceLocator(ServiceLocatorInterface $sm)
{
$this->sm = $sm;
}
/**
* Get the service locator
*
* #return ServiceLocator ServiceLocator instance
*/
public function getServiceLocator()
{
return $this->sm;
}
}
In the Module.php file add following onBootstrap() function
public function onBootstrap(MvcEvent $e)
{
$sm = $e->getApplication()->getServiceManager();
/** #var EntityManager $em */
$em = $sm->get('doctrine.entitymanager.orm_default');
/** #var \Doctrine\Common\EventManager $dem */
$dem = $em->getEventManager();
/**
* Binds adding EventListener "ServiceManagerListener" to the Doctrine Event PostLoad
*/
$dem->addEventListener([Events::postLoad], new ServiceManagerListener($sm));
}
Because of this setup, make sure to had the #ORM\HasLifecycleCallbacks Doctrine Annotation to the Entity class. The above function triggers the adding of the ServiceManagerListener, which in turn triggers the remainder.
Now all that remains is using it in your own modules (repeat endlessly if needed :) ).
Here we go back to the application itself.
Make sure you do the below for each of your entities and controllers and you should be fine.
Create the following:
<?php
namespace Application\Service;
use Company\Core\Service\AbstractEntityService;
class IndexControllerService extends AbstractEntityService
{
//Yes really, this class is empty. Extends an Abstract class which may not be directly instantiated.
}
Create a factory for you IndexController
<?php
namespace Application\Factory;
use Application\Controller\IndexController;
use Application\Service\IndexControllerService;
use Doctrine\ORM\EntityManager;
use Zend\Mvc\Controller\ControllerManager;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\ServiceManager;
class IndexControllerFactory implements FactoryInterface
{
/**
* #param ServiceLocatorInterface|ControllerManager $serviceLocator
* #return IndexController
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
/** #var ServiceManager $serviceManager */
$serviceManager = $serviceLocator->getServiceLocator();
/** #var EntityManager $entityManager */
$entityManager = $serviceManager->get('doctrine.entitymanager.orm_default');
/** #var IndexControllerService $entityService */
$entityService = new IndexControllerService($entityManager);
/** #var IndexController $controller */
$controller = new IndexController($entityService);
return $controller;
}
}
Make sure that your IndexController extends the AbstractActionController
<?php
namespace Application\Controller;
use Company\Core\Controller\AbstractActionController;
class IndexController extends AbstractActionController
{
public function indexAction()
{
return [];
}
}
And make sure that you've registered this configuration in the config files using the following:
'controllers' => [
'factories' => [
IndexController::class => IndexControllerFactory::class,
],
],
'service_manager' => [
'invokables' => [
IndexControllerService::class => IndexControllerService::class,
],
],
There ya go, should be all set.
I have a class which has may functions and i want to hide a particular function. For example
class Test
{
/**
* About Function1
*
* #param[in] arg1 About arg1
* #param[in] arg2 About arg2
*/
public void Function1(int arg1,char arg2);
// Presume same documentation for this function also
public void Function2(int,char);
// Presume same documentation for this function also
public void Function3(int,char);
// Presume same documentation for this function also
public void Function4(int,char);
}
Suppose I want to hide say Function2 how would I do that.
Now in the current scenario it is displaying all the four functions
along with its documentations.
Now, I have the following attribute set in my .doxygen rule file:
EXTRACT_ALL = YES
Can you please suggest me something by which i can hide say Function2?
If you have EXTRACT_PRIVATE = NO in the config file, then you can mark any member as private to Doxygen and it will not generate documentation for that member:
/// #private
public void Function2(int, char);
Bonus question: if you wanted to use the same documentation for all four members you can do so using one of these approaches:
/// #{
/**
* About Function1,2,3,4...
*/
public void Function1(int arg1, char arg2);
public void Function2(int arg1, char arg2);
public void Function3(int arg1, char arg2);
public void Function4(int arg1, char arg2);
/// #}
/**
* About Function1,2,3,4...
*/
public void Function1(int arg1, char arg2);
/// #copydoc Function1
public void Function2(int arg1, char arg2);
/// #copydoc Function1
public void Function3(int arg1, char arg2);
/// #copydoc Function1
public void Function4(int arg1, char arg2);
The one using #{...#} requires the use of DISTRIBUTE_GROUP_DOC = YES in the config file.
Use cond or internal
/*! \cond PRIVATE */
//only documented if cond is enabled
// ...
/*! \endcond */
Do something like this:
#ifndef DOXYGEN_SHOULD_SKIP_THIS
/* code that must be skipped by Doxygen */
/* in your case a method/function */
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
And in the config file, put PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS
Make sure that ENABLE_PREPROCESSING is set to YES.
In short, you are just leveraging the preprocessor concept to work for you!
I think I once used the EXCLUDE_SYMBOLS to achieve something like this.
The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
(namespaces, classes, functions, etc.) that should be excluded from the
output. The symbol name can be a fully qualified name, a word, or if the
wildcard * is used, a substring. Examples: ANamespace, AClass,
AClass::ANamespace, ANamespace::*Test
Unfortunately I can't completely recall nor find the config entry.
EXCLUDE_SYMBOLS = Test::Function2*