How to type hint class definition - visual-studio-code

Consider the following example of 3 javascript files:
/** myclass.js **/
import jQuery from 'jQuery';
class MyClass {
constructor() {
this.property = null;
jQuery('#test').data('myClass', this);
}
testMethod() {
return null;
}
}
export default MyClass;
/** file.js **/
import MyClass from './myclass.js';
new MyClass();
export default null;
/** index.js **/
import './file.js';
import jQuery from 'jQuery';
let myValue = jQuery('#test').data('myClass');
What I would like to achieve, is to get property and method auto suggestion from my IDE on the myValue variable. I know (I mean I presume) that automatically, there is no way for the IDE to know what I stored in the data variable of jQuery, but what kind of type hint should I provide before myValue to tell the IDE, that it should be an instance of MyClass?
If in index.js I also import myclass.js with the definition of the class, I was able to achieve my result, by type hinting before the variable with the following jsdoc comment:
/** #type {MyClass} */
But this line only works if I also imported the definition in the current scope. Is there any way to either:
achieve suggestions automatically, without manually type hinting?
or if that is not possible, type hint, without manually importing the definition beforehand?
I am using Visual Studio Code v1.46.1 and I have the ESLint v2.1.5 extension installed on it.
EDIT: After trying to create a jsconfig.json file in my root folder, with the following options:
{
"exclude": ["node_modules"]
}
and modifying my index.js by adding this jsdoc comment, I am still getting no autosuggestions by VSCode:
/** #type {MyClass} */
I've tried adding the above comment both above, and below the line, where I fetch the data from the jQuery element.
EDIT 2:
Okay, basically, it looks like that my IntelliSense "breaks" when I am trying to export something from a file. Could this be a VSCode issue?

Related

Flutter auto importing extension file is not working

I have a simple String-Extension which looks like this:
extension TranslationHelper on String {
String localized() {
return AppLocalizations(Locale('de', 'DE')).translate(this);
}
}
With this I am able to call .localized() on any String.
Problem: Flutter or VSCode is not auto-importing the file for me and also not suggesting it with a Quick-Fix. Importing the file manually is quite painful. Is this a bug or what am I missing here?
All other importing works perfectly fine...
This is a known issue, and is being tracked.
As a workaround, typing the name of the extension should let you auto import it.
For example, with the following extension, typing MyExtension should allow you to import it.
extension MyExtension on Object {
void doSomething() {}
}

PHP Intellisense in Visual Studio Code

I'm using Visual Studio Code to develop in PHP, and I've been having some trouble getting Code to provide the proper intellisense results. For example, this newly created Codeception unit test:
<?php
class MyTest extends \Codeception\Test\Unit
{
/**
* #var \UnitTester
*/
protected $tester;
protected function _before()
{
}
protected function _after()
{
}
// tests
public function testSomeFeature()
{
$this->assertFalse(false);
}
}
When I type $this-> I expect to see assertFalse, assertTrue, and all the other methods provided by \Codeception\Test\Unit. But what I get is basically whatever items exist within the current file and that's it.
What can I do to get all the methods from the Unit class to show up? I already have the PHP IntelliSense extension installed, v2.3.4.
Visual Studio Code core does not include advanced PHP features, just syntax highlighting, simple code completion and code linting provided by the PHP binary as long as you have it installed. In short, the features you can configure with these directives:
// Controls whether the built-in PHP language suggestions are enabled. The support suggests PHP globals and variables.
"php.suggest.basic": true,
// Enable/disable built-in PHP validation.
"php.validate.enable": true,
// Points to the PHP executable.
"php.validate.executablePath": null,
// Whether the linter is run on save or on type.
"php.validate.run": "onSave"
For anything else you need to install a third-party extension.
My personal choice is PHP Intelephense. In particular, it supports docblock annotations, including magic properties:
/**
* #property string $foo
*/
class Bar
{
}
... and inline types:
/** #var \Database $db */
$db->connect();

Call to private PHPExcel_IOFactory::__construct() from context - TYPO3

Hi have to create an excel export using phpexcel library. So I copy the library in my class then write the following code in my controller
require_once PATH_site . 'typo3conf/ext/extension_name/Classes/Library/PHPExcel/IOFactory.php';
public function excelTest()
{
$objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\ObjectManager');
$objReader = $objectManager->get('PHPExcel_IOFactory');
}
But it return an error
Fatal error: Call to private PHPExcel_IOFactory::__construct() from
context 'TYPO3\CMS\Core\Utility\GeneralUtility' in
/opt/lampp_repository/lampp-5.6/htdocs/typo3_src-7.6.6/typo3/sysext/core/Classes/Utility/GeneralUtility.php
on line 4533
Don't include the library yourself, TYPO3 has dependency injection for that. All the php files in your Extension directory will be indexed, and all Classes inside will automatically be available, you just have to make sure, that your class cache is fresh, if in doubt by manually deleting the typo3temp/Cache/Code/ClassLoader* file.
If you want to include en external class into your own namespace, you have to hint Extbase as to how to include it, with an ext_autoload.php file, because if multiple extensions load code into the same class namespace they will collide.
It also is good practice not to inject the class itself, but an Abstrct that extends upon it, so you can customize it in an isolated manner that doesn't modify the vendor files.
Heres my approach to it:
Put all files of PHPExcel into yourextension/Classes/Vendor/PHPExcel.
Create a new file yourextension/Classes/Vendor/PHPExcel.php:
<?php
namespace Vendorname\Extensionname\Classes;
/*
* PhpExcel
*/
class PhpExcel implements \TYPO3\CMS\Core\SingletonInterface extends \PHPExcel {
// Differences from the original implementation, e.g. a writer that generates
// a filename and puts the Excel file into typo3temp
}
You should then be able to just inject the class #inject-Annotation in your ActionController:
/**
* PhpExcel
*
* #var \Vendorname\Extensionname\Classes\PhpExcel
* #inject
*/
protected $phpExcel;
Further reading:
https://wiki.typo3.org/Dependency_Injection
https://docs.typo3.org/typo3cms/CoreApiReference/ApiOverview/Autoloading/Index.html

VSCode : It is not showing java script functions in intellisense e.g. .toLowerCase

VS Code is an amazing text editor but I am facing some issues.
ISSUE
VS Code not showing IntelliSense for basic javascript functions like myVariable.toLowerCase();
Please let me know if there is any solution for this.
Thanks VS Code team for making development beautiful!
I'm on the VSCode team.
We cannot infer the types of JavaScript variables like categoryName in many cases, so we cannot know that toLowerCase is a valid method on categoryName. There are a few ways to fix this:
Use jsdoc to specify the argument type:
/**
* #param {string} categoryName
*/
function foo(categoryName){
// `string` member completions avalible here
}
Add a guard to the function:
function foo(categoryName){
if (typeof categoryName !== 'string')
return
// `string` member completions available here
}
Use TypeScript or Flow types
function foo(categoryName: string){
// `string` member completions available here
}
Hope that helps.

Difference between ES2015 `import * as` vs just plain `import`

I just fixed a bug by changing import * as CodeMirror to just plain import CodeMirror.
I copied this code. (Porting it from TypeScript)
import * as CodeMirror worked until an addon was imported for its side effects: the expected new fold property was undefined.
Questions: (I am trying to understand what happened better)
What is going on? How did this change fix the bug?
Who is adding the default property to CodeMirror? (Or more likely: wrapping the module inside another object that looks very similar) The most likely suspects:
JavaScript modules (ES2015)
Babel
Webpack
CoffeeScript
CodeMirror
Is there a better way to accomplish what I was trying to achieve?
More details:
This code doesn't work as expected:
import * as CodeMirror from 'codemirror'
import 'codemirror/addon/fold/indent-fold.js' # should add `fold` object to `CodeMirror`
console.log typeof CodeMirror ## 'object'
console.log typeof CodeMirror.fold ## 'undefined'
console.log typeof CodeMirror.default ## 'function'
## Work-around:
console.log typeof CodeMirror.default.fold ## 'object'
This code works as expected:
import CodeMirror from 'codemirror'
import 'codemirror/addon/fold/indent-fold.js' # should add `fold` object to `CodeMirror`
console.log typeof CodeMirror ## 'function'
console.log typeof CodeMirror.fold ## 'object'
console.log typeof CodeMirror.default ## 'undefined'
I have already studied these resources, but they have not helped me fully understand what happened:
JS import reference
JS export reference
CoffeeScript modules
Let's assume you have a very simple module named 'test-module', in it you have:
var test = 'test';
export default test;
export function helloWorld () { ... };
When you do:
import something from 'test-module';
you are only importing the default export of 'some-module'. In this case, it is the string test. The default export can be anything, object, function, etc.
When you do:
import {helloWorld} from 'test-module';
You are specifically importing a member of 'test-module' named 'helloWorld' and not the default export. In this case, it is the function 'helloWorld'.
If you had done:
import {something} from 'test-module';
The 'something' would be 'undefined' since there is no export for with that name.
import * as something from 'test-module';
is asking for an object with all of the named exports of 'test-module'.
Then you can access any of the exports in 'test-module' as something.name. In this case they will be something.default and something.helloWorld.
import * as CodeMirror from 'codemirror' imports all the named exports and namespaces them into an object called CodeMirror.
import CodeMirror from 'codemirror' imports the default export.