How to use JSDoc to document an ES6 class property - jsdoc

I'm using the documentation package, but cannot figure out how to get it to document class properties (that aren't defined via getters and setters).
As the following just generates class documentation for SomeClass, but omits the someProperty documentation.
/**
* SomeClass is an example class for my question.
* #class
* #constructor
* #public
*/
class SomeClass {
constructor () {
this.someProperty = true // how do I document this?
}
/**
* someProperty is an example property that is set to `true`
* #property {boolean} someProperty
* #public
*/
}
An aside: the #constructor on the class jsdoc is a documentation thing.

Move the JSDoc for someProperty into the constructor where it is first defined:
/**
* SomeClass is an example class for my question.
* #class
* #constructor
* #public
*/
class SomeClass {
constructor () {
/**
* someProperty is an example property that is set to `true`
* #type {boolean}
* #public
*/
this.someProperty = true
}
}
I'm unsure if there is a way of accomplishing it with the documentation package using an approach that doesn't involve inlining the JSDocs into the constructor.

Another way is to declare them in class documentation as follows:
/**
* Class definition
* #property {type} propName - propriety description
* ...
*/
class ClassName {
constructor () {...}
...
}

You can declare properties in a class, and use #type to declare a type for them. Worked in VSCode 1.70.2 with in a plain ECMAScript Module.
class Foo {
/**
* Some bary data
* #type { BarClass }
*/
bar;
}
let f = new Foo();
f.bar; // Intellisense can tell you type and purpose

Related

Laravel Backpack basic request validation

I'm having an issue that I thought would be VERY simple to accomplish. I can not get this very basic request validation to work. I can enter "Bob" on the create form and the edit form and get no error messages. It simply inserts into the database.
Here's my code. I feel I'm doing/not doing something stupid.
UserCrudController.php
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Requests\UserRequest;
use Backpack\CRUD\app\Http\Controllers\CrudController;
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
/**
* Class UserCrudController
* #package App\Http\Controllers\Admin
* #property-read \Backpack\CRUD\app\Library\CrudPanel\CrudPanel $crud
*/
class UserCrudController extends CrudController
{
use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
/**
* Configure the CrudPanel object. Apply settings to all operations.
*
* #return void
*/
public function setup()
{
CRUD::setModel(\App\Models\User::class);
CRUD::setRoute(config('backpack.base.route_prefix') . '/user');
CRUD::setEntityNameStrings('user', 'users');
}
/**
* Define what happens when the List operation is loaded.
*
* #see https://backpackforlaravel.com/docs/crud-operation-list-entries
* #return void
*/
protected function setupListOperation()
{
CRUD::column('name');
CRUD::column('email');
//CRUD::column('password');
/**
* Columns can be defined using the fluent syntax or array syntax:
* - CRUD::column('price')->type('number');
* - CRUD::addColumn(['name' => 'price', 'type' => 'number']);
*/
}
/**
* Define what happens when the Create operation is loaded.
*
* #see https://backpackforlaravel.com/docs/crud-operation-create
* #return void
*/
protected function setupCreateOperation()
{
CRUD::setValidation(UserRequest::class);
CRUD::field('name');
CRUD::field('email');
//CRUD::field('password');
/**
* Fields can be defined using the fluent syntax or array syntax:
* - CRUD::field('price')->type('number');
* - CRUD::addField(['name' => 'price', 'type' => 'number']));
*/
}
/**
* Define what happens when the Update operation is loaded.
*
* #see https://backpackforlaravel.com/docs/crud-operation-update
* #return void
*/
protected function setupUpdateOperation()
{
$this->setupCreateOperation();
}
}
UserRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UserRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
// only allow updates if the user is logged in
return backpack_auth()->check();
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => ['required','min:5','max:255'],
];
}
/**
* Get the validation attributes that apply to the request.
*
* #return array
*/
public function attributes()
{
return [
//
];
}
/**
* Get the validation messages that apply to the request.
*
* #return array
*/
public function messages()
{
return [
//
];
}
}
I think what is happening is that you are not loading that controller.
If you have installed PermissionManager and now want to configure the UserCrudController you need to either manually register the routes yourself and point to your new controller, or alternativelly (and probably recommended) bind your new controller to the package one so your controller gets "served" instead of the package controller.
// In AppServiceProvider.php or any other provider of your choice:
$this->app->bind(
\Backpack\PermissionManager\app\Http\Controllers\UserCrudController::class,
\App\Http\Controllers\Admin\UserCrudController::class
);
If you don't need to change everything in the Controller you can directly extend the package UserCrudController and only change the things you need.
<?php
namespace App\Http\Controllers\Admin;
class UserCrudController extends \Backpack\PermissionManager\app\Http\Controllers\UserCrudController
{
}
The package controller already extends the CrudController.
The validation is added on setupCreateOperation() that you can override to fit your needs.
Cheers

vscode JavaScript - Reference types across files

How can I reference a type that is not exported (like MyClass) from another file in VSCode using JavaScript and CommonJS?
I have tried to use #module as dictated by JSDoc but it does not work. Is this not supported by VSCode?
Let's say I have two files:
myFactory.js:
/**
* #module MyModule
*/
class MyClass {}
const myFactory = {
create() {
return new MyClass();
}
}
module.exports = myFactory;
doSomething.js:
const myFactory = require('./myFactory');
/**
* #param {MyClass} item
*/
function doSomething1(item) {}
/**
* #param {MyModule.MyClass} item
*/
function doSomething2(item) {}
/**
* #param {module:MyModule.MyClass} item
*/
function doSomething3(item) {}
In doSomething.js, VSCode's Intellisence is not aware of MyClass so all 3 function signatures looks like this:
(local function) doSomethingX(item: any): void
Instead of
(local function) doSomethingX(item: MyClass): void
Here is my jsconfig.json:
{
"compilerOptions": {
"target": "es2017"
}
}
Try to move MyClass into separate file and set same #namespace for all files:
MyClass.js:
/** #namespace MyNamespace */
/** This is my class */
class MyClass {}
myFactory.js:
/** #namespace MyNamespace */
const myFactory = require('./MyClass');
const myFactory = {
create() {
return new MyClass();
}
}
module.exports = myFactory
doSomething.js:
/** #namespace MyNamespace */
const myFactory = require('./myFactory');
/** #param {MyClass} item */
function doSomething1(item) {}

How to singularize route path part using FOSRestBundle

I have this controller (a snippet here)
/**
* Class UserController
* #package Belka\AuthBundle\Controller
*/
class UserController extends FOSRestController implements ClassResourceInterface
{
/**
* #View()
*
* #Route(requirements={"user"="\w+"})
* #ParamConverter("user", converter="fos_rest.request_body")
*/
public function postGlobaltokenAction(User $user)
{
...
}
that automatically generates the route:
post_user_globaltoken POST ANY ANY /api/users/{user}/globaltokens.{_format}
which is OK, except for the fact I would like "globaltoken" singularized. Is that possible? I cannot find any annotation to tweak this. Should I hardcode the route in my route.yml?
I've found two ways:
Using a personal Inflector
as Symfony's documentation suggests, you can register a personal Inflector which returns "globaltoken" always as singular, whereas all the other resources will be pluralized:
use Doctrine\Common\Util\Inflector;
use FOS\RestBundle\Util\Inflector\DoctrineInflector;
use FOS\RestBundle\Util\Inflector\InflectorInterface;
/**
* Inflector class
*
*/
class NoopInflector extends DoctrineInflector implements InflectorInterface
{
public function pluralize($word)
{
if($word == "globaltoken")
return $word;
return parent::pluralize($word);
}
}
services.yml:
services:
belka.auth_bundle.util.inflector:
class: Belka\AuthBundle\Util\NoopInflector
but I found this way a bit dirty, as I could need the plural form in the future.
Overriding the FOSRestBundle auto-generated routes
It's that simple! Just add the #Route annotation on the right methos and you're done!
/**
* #View()
*
* #Route("/users/{user}/globaltoken", defaults={"_format" = "json"}, requirements={"user"="\w+"})
*
* #ParamConverter("user", converter="fos_rest.request_body")
*/
public function postAction(User $user)
{
}
Now if I call php app/console debug:route I get what I want:
post_user_globaltoken POST ANY ANY /api/users/{user}/globaltoken.{_format}

Extend function with Doctrine ORM Annotation

I've got the following situation: a (Doctrine Entity) ContentCategory that is extending the DataObject class. The DataObject class has the following function, onPrePersist:
/**
* #ORM\HasLifecycleCallbacks
*/
class DataObject implements InputFilterAwareInterface
{
...
/** #ORM\PrePersist */
public function onPrePersist()
{
//using Doctrine DateTime here
$this->creation_date = new \DateTime('now');
}
The ContentCategory class needs this function aswell. When I put this function in the ContentCategory class it works just fine. Is there a way whereby, the ContentCategory class can use the same function, onPrePersist() without defining it in the class itsself?
* #ORM\HasLifecycleCallbacks()
*/
class ContentCategory extends DataObject implements InputFilterAwareInterface
{
...
}
The reason to give objects the onPrePersist function, is to set a DateTime when this object is created or any other object / entity that is extending the DataObject class.
--< Edited >--
I've currently added a construct method to the ContentCategory like this:
public function __construct() {
parent::onPrePersist();
}
In this way Doctrine executes the function onPersist when a new Entity is created. The other case is when an enttiy is being updated, with Doctrine. I'll like to set a Modified_date. In that case there will be a function like this, in the DataObject class.
/**
* #ORM\HasLifecycleCallbacks
*/
class DataObject implements InputFilterAwareInterface
{
...
/**
* #ORM\PreUpdate
*/
public function onUpdate()
{
$this->last_modified_date = new \DateTime('now');
}
The Doctrine ORM Annotation (PreUpdate) that have been added, will make sure that the function (above) will be excuted on an update statement for an object. The problem is, how to call those functions in an object which extends the DataObject
/**
* #ORM\MappedSuperclass
* #ORM\HasLifecycleCallbacks
*/
class TestimonialSuperclass
{
/**
* #ORM\PreFlush
*/
public function onPreFlush ()
{
echo 123;
}
}
/**
* #ORM\Entity
* #ORM\Table(name="testimonials")
* #ORM\HasLifecycleCallbacks
*/
class Testimonial extends TestimonialSuperclass
{
...
}

phpdoc suggesting type for $this->someField

In Netbeans and phpStorm,
this works as expected:
public function someMethod() {
$objectA = uberEnterprisyFactory('someclassA');
/* #var $objectA TheClassA */
// $objectA-> (autocomplete for TheClassA is displayed, good)
This does not:
public function someMethod() {
$this->objectA = uberEnterprisyFactory('somemodelA');
/* #var $this->objectA TheClassA */
// $this->objectA-> (no autocomplete here, not good, $this->objectA is inferred to be null)
How can I sugest type of $this->someThing to Netbeans and/or phpStorm?
Use the following PHPDoc annotation:
class MyClass {
/**
* #var MyPropertyClass
*/
private $myProperty
}