Multiple Optional Parameters JSDoc - google-closure-compiler

I have a function in js with the following signature:
function foo(name, opt_callback, opt_dataStr);
And I'm trying to annotate this using JSDoc for Closure compiler like so:
/**
* #param {string} name
* #param {function(*)=} opt_callback
* #param {string=} opt_dataStr
*/
But the compiler generates a dozen of type warnings every time opt_callback is not passed in and opt_dataStr is, complaining that I'm passing a string where I should have a function.
I'm sure there is a simple solution as to how annotate this correctly, but I've tried
* #param {function(*)=|string=} opt_callback
and
* #param {(function(*)|string)=} opt_callback
and so on, with no avail. Can anyone point me in the right direction?

The last works, this compiles without warning:
/**
* #param {string} name
* #param {(function(*)|string)=} opt_callback
* #param {string=} opt_dataStr
*/
function fn(name, opt_callback, opt_dataStr) {}
fn('a','b');
Here is an example

Related

Strange Issue With Entity Relationship in Symfony 4

This is a very odd one, i'll try to explain with couple of sample entities.
class Property{
/**
* #var string
* #ORM\Column(type="string", length=10)
*/
private $postCode;
/**
* #var InstructionToSell
* #ORM\OneToOne(targetEntity="App\Entity\InstructionToSell")
* #ORM\JoinColumn(nullable=true)
*/
private $instructionToSell;
}
class InstructionToSell{
/**
* #var Property
* #ORM\OneToOne(targetEntity="App\Entity\Property")
* #ORM\JoinColumn(nullable=true)
*/
private $property;
}
So two sample entities, the property can have an instruction to sell entity and vice versa. I then have a very basic post code search method in the repo:
/**
* #param string $postCode
* #return array|null
*/
public function searchByPostcode(string $postCode) : ?array{
$builder = $this->createQueryBuilder('p');
$builder->where(
$builder->expr()->like('p.postCode',':postCode')
)->setParameter('postCode',str_replace(' ','','%'.$postCode.'%'));
return $builder->getQuery()->getResult();
}
It all works fine except for one very strange thing. If say a property had the Uk post code of "YO12 7YA" and we run a search for "YO127YA" then it's bringing back a result, but if we use "YO12 7YA" it's bringing back a result but the instructionToSell is null on the property, but it's not null if i remove the space from the search term.
I'm aware this search isn't the best as it stands, need to strip spaces out of the column as well, but the point i am making is, the same code runs for "YO12 7YA" and "YO127YA" which brings back the same property, but one of them has the relationship matched to the instruction to sell, the other it's null.
Why would this happen? It's exactly the same property it's bringing back.

icCube Reporting - Labels using Events: Formatting and Syntax

What is the correct syntax for using the event variable within the label boxes (e.g Header Title).
Having a defined event (e.g. Test), what are the possible use?
What is the meaning of the following expression?
#{Test:'Alternate Text'!} #{Test}
Are there other available functions?
Events in icCube are objects (base class is viz.event.Event) that implement mainly two methods :
caption() - return the caption/name of the event, e.g. Italy for a country MDX member
asMdx() - return the mdx unique name (caption if there is none), e.g. [Country].[Italy]
So when you define an event listener #{eventName} it's going to be changed by it's caption() value, unless you are in an MDX expression where it's changed by the asMdx() value.
You can decorate your event in three ways
#{eventName!emptyValue} -> if the event is empty, returns the string 'emptyValue' (without single quotes)
#{eventName:eventFunction} -> calls eventObject.eventFunction , e.g. #{event:asMdx}
#{eventName:'valueIfNotEmpty'} -> if the event exists, return the string 'valueIfNotEmpty' (without single quotes)
More information on the doc.
As it's javascript you're free to add you own methods to the object of the class (e.g. using On Send Event hook in a widget - the JS icon)
The interface that all events implement is :
export interface IEvent {
/**
* Return true if the event is empty.
* #returns {boolean}
*/
isEmptyEvent():boolean;
/**
* Returns the caption of the event.
* #returns {string}
*/
caption():string;
/**
* Returns the value of the event.
* #returns {string}
*/
value():any;
/**
* Returns the event value as MDX expression.
* #returns {string}
*/
asMdx():string;
/**
* Return the event value key
* #return {string}
*/
asKey():string;
/**
* Return the string representation of member key with quotes. If multiple keys present it returns: 'key1', 'key2', 'key3'
* #return {string}
*/
asQuotedKey():string;
/**
* Return the string representation of member captions with quotes. If multiple keys present it returns: 'name1, 'name2', 'name3'
* #return {string}
*/
asQuotedCaption():string;
/**
* Return the array of event keys
* #return {Array}
*/
asKeyArray():string[];
/**
* Returns the event value es MDX set expression.
* #returns {string}
*/
asSet():string;
/**
* Returns the event value as filter initial selection.
* #returns {any}
*/
asFilterInitialSelection():any;
/**
* Return true if the event is selection event. Used for type check.
* #returns {boolean}
*/
isSelectionEvent():boolean;
/**
* Returns the event value as an array.
* #returns {any[]}
*/
getSelectedItems():any[];
/**
* Returns a serialized event object.
* #returns {EventGuts}
*/
asReportParam():EventGuts;
}

Symfony Validation dependent on another property

Trying to validate if one field is not empty (length > 0) then the length of the field being validated must be a certain length (2 characters). It seems like an "Assert\Expression" might work in this situation but I am having trouble trying to find the length of the properties. It seems like you cannot call php functions within the Expression. The expression documentation mentions functions but maybe I do not understand it... Do I need to register my own function that simply return a strlen(). If so how do you register your own functions? Can someone explain if there is a way to do this, or maybe there is a better way than using Expression that I am overlooking...
/**
* #var string
*
* #ORM\Column(name="plate", type="string", length=10)
*/
private $plate;
/**
* #var string
*
* #ORM\Column(name="state", type="string", length=2)
* #Assert\Expression(
* "strlen(this.getPlate()) == 0 or (strlen(this.getPlate()) > 0 and strlen(value) == 2)",
* message="Must be 2 characters"
* )
*/
private $state;
In the above case I get an error The function "strlen" does not exist around position 1
Looks like you will need to register your own function. Have a look at the docs: https://symfony.com/doc/current/components/expression_language/extending.html#registering-functions
There is an example on lowercase, strlen should be very similar.
EDIT:
You can also use a callback validator.
/**
* #Assert\Callback()
*/
public function validateState(ExecutionContextInterface $context)
{
if (!empty($this->plate) && mb_strlen($this->state) !== 2) {
$context->buildViolation('State must be 2 characters long')
->atPath('state')
->addViolation();
}
}
But if you are planning to using this kind of validation in multiple places, you can write and register your own validator.

Symfony2 route in annotations with optional parameters

i created a route with optional parameter in controller like this:
/**
* League action
*
* #Route("/association/{assoc}/{league}", name="league", requirements={"league" = "\d+"}, defaults={"game" = null})
* #Route("/association/{assoc}/{league}/{game}")
* #Template()
*
* #param $assoc
* #param $league
* #param $game
* #return array
*/
public function leagueAction($assoc, $league, $game)
but if i try to create a link with this named route, the optional parameter is ommitted:
{{ path('league', {'assoc': association.short, 'league': league.id, 'game': g.id}) }}
resulting link is
/association/BVNR/7
What am i missing?
In the following definitions,
* #Route("/association/{assoc}/{league}", name="league", requirements={"league" = "\d+"}, defaults={"game" = null})
* #Route("/association/{assoc}/{league}/{game}")
two routes are related to your action, the first one (named "league" which doesn't have any default parameter and a second unnamed one (as you didn't add name attribute) which also doesn't have any default parameter.
How to fix ...
Add a name to your second route and call it as it contains "game" parameter.
Move the default value of "game" parameter to your second route (As it the only one to have a game parameter.
(You don't really need to define two routes, take a look at the "How to improve ..." part of my answer).
Try this ...
* #Route("/association/{assoc}/{league}/{game}", name="league_game", requirements={"league" = "\d+"}, defaults={"game" = null})
While you should call "league_game" instead of "league",
{{ path('league_game', {'assoc': association.short, 'league': league.id, 'game': g.id}) }}
How to improve ...
Make sure you really need to define two routes, because I would suggest keeping only one route.
As there's a default value for "game"in the following definition,
#Route("/association/{assoc}/{league}/{game}", name="league", requirements={"league" = "\d+"}, defaults={"game" = null}
It then covers both versions, with and without "game".

Doxygen and #ORM annotated entities in Symfony2

I have implemented entities within the Symfony2 framework that are annotated to be used by Doctrine. For example:
/*
* class description
*
* #ORM\Entity(repositoryClass="Website\ContentBundle\Repository\ContentRepository")
* #ORM\HasLifecycleCallbacks()
* #ORM\InheritanceType("SINGLE_TABLE")
* #ORM\DiscriminatorColumn(name="type", type="string")
* #ORM\DiscriminatorMap({"article" = "Article"})
* #ORM\Table(name="content",indexes={#ORM\index(name="id_UNIQUE",columns={"id"})})
*/
class Content {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
...
}
When I run Doxygen on my source code, the documentation is not very readable. I have tried to define aliases for each #ORM* symbol; for example "ORM=ORM", "Entity=Entity", and so on. But this does not work. For the above mentioned class Doxygen returns
...
ORMEntity(repositoryClass="Website\ContentBundle\Repository\ContentRepository") ORM() ORM("SINGLE_TABLE") ORM(name="type", type="string") ORM({"article" = "Article", "picture_series" = "PictureSeries", "event" = "Event", "invitation" = "Invitation"}) ORMTable(name="content",indexes={ORM(name="id_UNIQUE",columns={"id"})})
With respect to method
/**
* sets the given id
*
* #param number $id
* #return \Website\ContentBundle\Entity\Content
*/
public function setId($id) {
$this->id = $id;
return $this; // fluent interface
}
Doxygen creates
setId ($ id)
sets the given id
Parameters:
number $id
Returns:
Why does it not show the \Website\ContentBundle\Entity\Content after "Returns:"?
Maybe someone can give me a hint or a link on how to configure Doxygen such that it can handle the #ORM annotations appropriately.
THX in advance!
With respect to the question
Why does it not show the \Website\ContentBundle\Entity\Content after Returns:?
This is probably because doxygen commands start with a \, do doxygen thinks you are calling some commands which it does not recognise, and so presumably strips from the documentation and does nothing with.
You were on the right line with attempting to use the ALIASES configuration file option. However, instead of defining ORM=ORM try using ORM=\#ORM. I got your example source code to be documented by doxygen without any warnings by defining the following aliases:
ALIASES = "ORM=\#ORM"
ALIASES += "Entity=\\Entity"
ALIASES += "InheritanceType=\\InheritanceType"
ALIASES += "DiscriminatorColumn=\\DiscriminatorColumn"
ALIASES += "DiscriminatorMap=\\DiscriminatorMap"
ALIASES += "Table=\\Table"
ALIASES += "Id=\\Id"
ALIASES += "Column=\\Column"
ALIASES += "GeneratedValue=\\GeneratedValue"
ALIASES += "index=\\index"
ALIASES += "HasLifecycleCallbacks=\\HasLifecycleCallbacks"
ALIASES += "Repository=\\Repository"
ALIASES += "ContentRepository=\\ContentRepository"
ALIASES += "ContentBundle=\\ContentBundle"
ALIASES += "Website=\\Website"
ALIASES += "Content=\\Content"
Here \\, \# are actually doxygen commands for printing the backslash \ and # characters respectively.
Note, however, that the #ORM... directives will all appear on the same line. I'm not sure how to avoid this (update: see my edit below). Does anyone else have any ideas?
Finally, as a side note, your documentation for $id should be
* #param $id number
note the order of $id and number. See the documentation for \param.
Edit: An alternative way of doing this would be to wrap the Doctrine relavent parts in \verbatim and \endverbatim tags. This will preserve the line breaks in your class description which will be more readable.

Resources