I am developing some JavaScript to be used in a CMS I'm working on.
I have encapsulated my code like this:
(function(){
var libraryName = {};
...code...
window.libraryName = libraryName;
}())
Now when I add a subnamespace and try using it outside my declaration, the NetBeans (8.0.2) autocomplete function doesn't work. Like this:
(function(){
var libraryName = {};
libraryName.subSet = {
showSomething: function(){}
};
window.libraryName = libraryName;
}())
libraryName.subSet.showSomething(); // This works
libraryName.subSet. // No current autocomplete even when pressing CTRL+space
I would like to know if there is some way to tell NetBeans how to autocomplete instead of it guessing.
Thanks
You can use Ctrl+K, the "hippie" code completion. It directly completes some matching result and if the completed item is not what you wanted, you can keep pressing Ctrl+K to get another autocompleted item (will replace the previously inserted one). Another thing, you can press Ctrl+Space 2 times to get "full" code completion (meaning pretty much everything from other objects/variables)
Update: There is another way using JSDoc, but it works only in Dev build of NetBeans and will be part of the next 8.1 release (you can download Dev builds from here):
/**
* #typedef libraryName
* #property {Function} showSomething description
* #property {someProp} foo description
*/
/**
* #typedef someProp
* #property {Date} day description
* #property {Number} num description
*/
/**
* #typedef libraryName.someProp2
* #property {Date} day description
* #property {Number} num description
*/
This way you'd have to create this "documentation" for your library and have it somewhere in JS file in your project (perhaps non-minified JS file of your library). With this #typedef feature, you can learn code completion pretty much anything even if it is not even in your code). Of course there are some issues yet to be fixed (it is a Dev build)...
I tried another approach which worked for me.
I copied my JavaScript file and removed the encapsulation. So I now have two files, the "real" one with the encapsulation and another "working" one that doesn't have the encapsulation. Now when I try using the autocomplete it works.
The downside for this is that you create noise since there is a file that isn't meant for the web app and you have to update it every time you update the original file. But it makes coding easier with the magic of autocomplete. When you load html you just don't reference the "working" file.
So, this would be my main.js file (in /js/main.js for instance)
(function(){
var libraryName = {};
libraryName.subSet = {
showSomething: function(){}
};
window.libraryName = libraryName;
}())
And a main.tmp.js file would be like this (in /tmp/main.tmp.js for instance)
var libraryName = {};
libraryName.subSet = {
showSomething: function(){}
};
Now, when I do libraryName.subSet. it shows me the correct autocomplete with showSomething.
Related
Here in my code in my ASP.NET Core project I have that's causing the issue:
As Text:
<script>
/**
* Get a setting value.
* #param {string} name
* #param defaultValue
* #returns {*}
*/
getSetting(name, defaultValue) {
return name in this.settings ? this.settings[name] : defaultValue;
}
</script>
The error that I'm getting for every documentation code, which is red lined is https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/cs0103
which gets clearly identified as C# code, even though I'm writing this code in a .cshtml file <script> tag...
How do I fix this? It prevents me from compiling and executing...
I am using Visual Studio 2022 Preview 4.1 if that matters
.cshtml files are interpreted as Razor templates where # is used to mark C# code in the template.
You can either escape with a second # i.e. ##param etc or move the JS to a separate file.
I wanted to take some time to "clean" a personal app, to remove most of the warnings, etc.
As stated in the title I use the PhpStorm IDE and I have some warnings "Unresolved variable slug" when I use series.slug. The variable series comes from either a JSON from a PHP Class or after an Ajax call.
Is there a way to indicate an object's properties or to link a js variable to a PHP class (like in Twig)?
P.S. In my "Settings > Languages > JS > Code Quality Tools", I have nothing enabled, I just have the "basic" PhpStorm inspection.
If you use some object with keys only known in runtime (generated, received through the ajax call, etc.) in your code, there is no way for the IDE to resolve them using static code analysis.
But you can let the IDE know what your runtime data looks like. Possible solution using JSDoc annotations:
/**
* #typedef {Object} series
* #property {string} slug
* ... other series props here....
*/
...
/**
* function that uses series data
* #param {series} data
*/
function foo (data){...}
See also https://youtrack.jetbrains.com/issue/WEB-17419#comment=27-1058451, https://intellij-support.jetbrains.com/hc/en-us/community/posts/206349469-disable-unresolved-variable-on-json-object-received-by-ajax-call for other possible workarounds
I would think that all members / objects / etc. documented by JSDoc should be their own click-able links; e.g., if I have levelOne --> levelTwo --> levelThree --> levelFour, then I should see levelOne on the first page and be able to click my way through to levelFour...but that doesn't seem to be the case.
Here is my code:
/**
Contains various tools and extensions.
#namespace App
*/
var app = app || {};
/**
Contains App plugins.
#namespace App.Plugins
*/
app.Plugins = app.Plugins || {};
/**
Contains methods and classes usable within unit-testing.
#memberof App
#type {object}
#namespace App.UnitTesting
*/
app.UnitTesting = app.UnitTesting || {
/**
Test methods for the App library.
#memberof App.UnitTesting
#type {object}
#property {object} test1 Property definition.
*/
PluginTests: {
/**
Test for this or that
#memberof App.UnitTesting.PluginTests
#type {object}
#property {method} innertest1 Property definition for "innertest1"
*/
test1: {
/**
Run another nested test
#memberof App.UnitTesting.PluginTests.test1
#method innertest1
#returns {object}
*/
innertest1: function () { }
}
}
};
The "namespace" objects are easily clickable, and are accessible from the home page, but PluginTests IS NOT CLICKABLE (IT ISN'T A LINK!!), and therefore test1 and innertest1 are not accessible. Am I grossly misunderstanding how JSDoc works?
PS: Before anyone starts tearing apart my code with hurtful comments, please note that I learned of JSDoc's existence about 3 hours ago and am very new to this.
As far as I know, JSDoc doesn't generate pages for all or an arbitrary property. You might expect JSDoc to generate pages for deeply nested object properties automatically, but that isn't the case. For example, there is an open issue on Github on making it easier to link to object properties.
The JSDoc output for the UnitTesting namespace in the code you provided looks as following (using the default template):
I assume that you expected the property test1 to be clickable and that it would lead you to a page providing information on test1 (eg. the fact that it has a method innertest1). Unfortunately, that isn't the case.
The way code is documented is slightly related to its architecture (eg. JSDoc provides support for classes, modules, mixins, namespaces, and so on). In my experience, good architecture helps writing neat documentation. The JSDoc template you use might influence how your perceive hierarchy. For example: some templates create a tree of namespaces.
Anyway, in this particular example/architecture, your options are:
Adding another #namespace for PluginTests.
Adding a #property entry for innertest1 in the PluginTests doclet.
Examples coming up.
1: Add a #namespace
Adding a #namespace to PluginTests would result in another namespace page, specifically for PluginTests, and would include the information you need:
The change to the code you provided is obvious, yet I'll just include the part that changed for the sake of completeness:
/**
* Test methods for the App library.
* #namespace App.UnitTesting.PluginTests
* #memberof App.UnitTesting
* #type {object}
* #property {object} test1 Property definition.
*/
PluginTests: {}
2: Add #property for innertest1
Instead of creating another namespace, you could document the property test1.innertest1 in the PluginTests doclet:
/**
* Test methods for the App library.
* #memberof App.UnitTesting
* #type {object}
* #property {object} test1 Property definition.
* #property {method} test1.innertest1 A method.
*/
PluginTests: {}
This would result in an extra property table inside the description of test1:
Side note
You might like using the Baseline template to format your documentation. It's still under active development (by Googlers) and subject to change. One of the reasons I occasionally use it: it's easier to navigate. From the docs:
An expandable table of contents helps users find what they're looking for. Also, a summary at the top of each page shows users what's documented on that page.
One downside is that Baseline doesn't support the second option yet.
I open a project with file => new => static web project. Name it MyProject and web content folder name is WebContent.
Right click the WebContent directory and add a js directory. Right click the js directory and choose new => other => JavaScript source file and call it DomStuff.js with the following content:
var MyApp={};
MyApp.DomStuff={};
MyApp.DomStuff.someFunction=function(){
return true;
}
MyApp.do<== here it auto completes to DomStuff
Right click the js directory again and choose new => other => JavaScript source file and call it WorkFlow.js
When I type MyApp. then press control + space I get a box saying No Default Proposals. It's like auto complete only works when all the code is in one file.
Right click JavaScript Resources under the Source tab MyProject/WebContent is listed as included all and excluded none.
This is in Eclipse Version: 4.2.1 with Eclipse Web Developer Tools 3.4.1 and JavaScript Development Tools 1.4.1.
For as long as I remember I never got the auto complete to work on code outside the file I am currently working on. Is this normal or am I missing some setting here?
Standard JSDT can seem non deterministic when it come to completions across files. That is because even if the project is configured correctly then the most expensive type of it's source code analysis only occurs on files that are open. Do you get the same result if both files are open?
By the way, there is a fork of JSDT that is a candidate for merging to official JSDT called JSDT+NJSDoc that handles such cross file analysis extremely efficiently (and adds other features): https://bitbucket.org/nexj/webtools.jsdt.core
[update]
Basically Eclipse with JSDT can't do the job. Tried to define all my namespaces with constructor functions but it's all too much trouble.
Trying netbeans now and it'll assist most of the closure library and all of my code. Some things like goog.array won't complete because goog.array is never defined. When adding goog.array=new Object() to the array.js it'll complete goog.array and goog.array.ArrayLike. These modded js file go in your js/libs directory of your project.
If you want the troublesome way to get it to work in Eclipse then keep reading.
It seems that Eclipse has problems with objects declared as object literals. Declaring my complex types with a constructor function seems to do the trick. An instance of the root object has to be created on Window (capital W).
// this would be the way I would define
// a complex property that doesn't need
// more than one instance and is not complex
// enough to put in a separate file
myapp.workflow.objectLiteral={
thisDoesNotCodeAssist:function(){},
neitherDoesThis:22
};
/** if you define the complex property as
* a constructor it will auto complete
* in other files and closure compiler will
* recognize it's type
*/
/** #constructor organizes flow
* used for Eclipse code assist */
var WorkFlow=function(){};
ProwpWithSubs=function(){};
PropWithSubs.prototype.subProp=22;
PropWithSubs.prototype.subFunction=function(){
this.subsub=44;
};
WorkFlow.prototype.propwithsubs=new PropWithSubs();
if(ALLWAYSFALSE){
/**needed for Eclipse code assist
* #constructor
*/
var MyApp=function(){};
MyApp.prototype.workflow=new WorkFlow();
MyApp.prototype.dom=new DOM();
Window.prototype.myapp=new MyApp();
}else{
myapp.workflow=new WorkFlow();
}
[update]
Here are 3 files I use to split up the definition and the implementation a little so it's easier with google closure.
Setting up the main types in types.js
// source: js/mmyapp/types.js
goog.provide("myapp.types");
/** #constructor */
var gooblediegoog=function(){};
/** #constructor */
gooblediegoog.prototype.WorkFlow=function(){};
/** #constructor */
gooblediegoog.prototype.Dom=function(){};
myapp.types=new gooblediegoog();
A file that isn't used at all in my code but tells Eclipse how to auto complete:
// source: js/myapp/forCodeAssist.js
/** #const {boolean} */
var ALLWAYSFALSE=false;
if(ALLWAYSFALSE){
/**needed for Eclipse autocomplete
* #constructor
*/
var MyApp=function(){};
MyApp.prototype.types=new gooblediegoog();
Window.prototype.myapp=new MyApp();
MyApp.prototype.workflow=new myapp.types.WorkFlow();
MyApp.prototype.dom=new myapp.types.Dom();
}
An implementation of workflow:
// source: js/myapp/workflow.js
goog.provide("myapp.workflow");
goog.require("myapp.types");
goog.require("myapp.dom");
/** #returns number|undefined */
myapp.types.WorkFlow.prototype.createOrder=function(){
return myapp.dom.getArticleAmout();
};
myapp.workflow=new myapp.types.WorkFlow();
window['console'].log(myapp.workflow.createOrder());
This can be converted to a myapp.workflow.createOrder=... syntax by replacing myapp.types.WorkFlow.prototype with myapp.workflow, removing myapp.workflow=new myapp.types.WorkFlow() and removing the goog.require("myapp.types"). Maybe this can be automated in the build/compile process if needed.
I am not sure if creating a single object with the help from a constructor function is much more expensive than just having goog.require create myapp.workflow and adding properties to it as I used to do (and as it's done in closure library).
Example:
There are several .js files with couple functions like:
/**
* TestFunction - doing something.
* #param {String} strTest Test string.
* #return {Boolean} bRes Returned value.
*/
function TestFunction(strTest) {
//code ...
return bRes;
}
After JsDuck.exe created help file - no parameters of function in function description is present, only return value bRes with description.
Version: SDuck 5.0.0.beta2 also tried on earlier version and same result.
Does anyone used JSduck for functional frameworks and got success. or are there any workaround to get this work properly?
Same .js files work correctly with JSDoc toolkit and all data is shown, but JSDuck is still preferable to make it work.
Thanks in advance for reply.
Answered your question in bug-tracker: https://github.com/senchalabs/jsduck/issues/358