JSDoc and objects

Voted.

Actually I was looking yesterday again at Douglas Crockford’s presentation on “The JavaScript Programming Language” : http://dai.ly/c4TcPG (there are 4 parts of this, names “tjpl” 1 to 4)
Douglas Crockford is the guy who wrote “JavaScript: The good parts” - probably the best book ever written on the language).

And he explains in detail how and Object in JavaScript is basically a Hashtable (and is implemented as such), and what are the big advantages of having such a dynamic implementation… something now totally lost in Servoy because of these JSDocs… so are we now condemned to only have “JavaScript: the bad parts” in Servoy?

I certainly hope not. Please vote on the issue.

david:
[cut]

Instead of trying to put javascript in a box where it doesn’t belong, in my world I would remove most of the new cruft, keep the rhino javascript engine up-to-date and look at adding support for other languages such as groovy and jython.

+1 and totally agreed. I’m starting to reappraise javascript exactly for the freedom (and inherent power) it leaves to the developer, much like C/C++ w.r.t Java and other higher-level languages.
However sometimes I just have to close and restart Servoy developer to make it work decently again. Definitely not pleasant for a developer.

P.S.: I’d love to see groovy supported. As a side note, what’s the reason behind js as a server side language choice?

studiomiazzo:
As a side note, what’s the reason behind js as a server side language choice?

Apart from that it’s an awesome Object Oriented, loosely typed, open standards based, easy to learn (also because already used in other environments) language and that Rhino can compile it into actual Java code?
Just the preference of the Servoy team I guess ;)

ROCLASI:

studiomiazzo:
As a side note, what’s the reason behind js as a server side language choice?

Apart from that it’s an awesome Object Oriented, loosely typed, open standards based, easy to learn (also because already used in other environments) language and that Rhino can compile it into actual Java code?
Just the preference of the Servoy team I guess ;)

Eheheh, ok I asked for that :mrgreen:
Besides, I’ve just discovered first-class continuations, cool :D

I mention a few other languages that compile to java byte code (and can also script straight up java code) because maybe a few options might make Servoy more palatable for enterprise customers who won’t touch javascript. You could even include java itself as a “scripting” language option.

Better than blending JSDoc into javascript to come up with some hybrid pseudo typed language that makes javascript unrecognizable to the legion of javascript coders coming down the pike.

Hi David,

david:
…because maybe a few options might make Servoy more palatable for enterprise customers who won’t touch javascript.

I am not sure where this notion comes from.
You say Enterprise customers don’t use DHTML (HTML5 is full of this) or Ajax in their Enterprise websolutions? All of which uses/requires JavaScript.
Or look at tools like Appcellerator Titanium that uses JavaScript as it’s language as well and so far I can see is used a lot by enterprises (NBC for instance).

Why would you say that Enterprise will not touch JavaScript?

None of which I disagree with. I am talking about the perception that javascript is not a great tool for the enterprise because of various assumed weaknesses—many of which stem from the html5/javascript development chaos going on right now. (And which using a tool like Servoy already addresses in areas such as an IDE with refactoring, debugging and code organization.) Weak typing combined with lack of compile time error checking is one of those bad perceptions of javascript to many developers. One of the reasons I can think of for foisting this JSDoc thing on us.

Hi David,

So I guess it’s more a perception problem then a technical issue then.

Anyway, we are muddling the actual topic of this thread, or at least the one Patrick started.

Patrick also pointed to some (very good!) videos from Douglas Crockford that in fact point out why the strict JSDoc’ing is wrong. Douglas also points out that you can still have the develop/compile time checking of your code that one expects from a strongly typed language like Java/C/etc. and also have the power of JavaScript. He actually wrote a tool for that named JSLint. Something that also found it’s way into Eclipse so Servoy can use this (perhaps already does under the surface, I dunno).

I guess Servoy’s reasoning for using the strict JSDoc is to allow for some very strong refactoring support but by doing so has such a huge impact on the actual language I think it’s just a bridge too far.
So apart from all the side effects like performance, the perception of the language or even the volume of warnings I think this is the core issue and what Patrick’s feature request tries to address.

i am reading this thread and i think what are you guys talking about
everything is optional, don’t like the warnings? turn of the warnings, you can disable pretty much all warnings in the preferences one by one.

Turning of the complete parser is not possible, and we need it for our selfs also, so it will always be parsed.

Also the speed problems are always looked at there are currently one or 2 known issues that are already fixed in the next release of 6

The parser of 5 doesn’t have anything to do with the one in 6, they are not even remotely the same

The only thing you really need to type is parameters, if you do that then it works for most of the stuff already

Yes stuff like this: databasemanager.getFoundset(“datasourcestring”) can never be smarter because that ‘datasourcestring’ is dynamic or just a string in code.
thats impossible to make better in this current setup. The only way to make that kind of things better is to do:

var fs = datasources.db.server.table.getFoundset();
var fs = datasources.mem.name.getFoundset();

so that directly in code, then it will work because everything are properties directly in code.

And also you are talking about if we make it strict if we change javascript itself, that is completely not true, it is just a helper tool so that in code everything knows what it can and can’t do.
And again, if you don’t like it Turn it of, set all the preferences to “ignore”. Done.

By the way, the parser is also used for stuff like references finding and so on (F3 on a function call). Or all other things like Call hierarchy, Search by references/declarations, mark occurrences and code completion

What you’re saying is perfectly fine, though I’m wondering whether JSDoc is the only or the best way of achieving this. But I’m not a servoy engineer so I could very well be utterly wrong. As a side note, the next version of servoy you’re talking about is the 6.1?

jcompagner:
i am reading this thread and i think what are you guys talking about
everything is optional, don’t like the warnings? turn of the warnings, you can disable pretty much all warnings in the preferences one by one.

Yes, one by one. What if I want to disable them temporarily, then later have them back as-is? A global on/off preference would help here.

Also, I think that by default for a new Servoy installation this should be off by default.
Because newbie with JavaScript background coming to the platform will not understand that and will run away.

jcompagner:
The only thing you really need to type is parameters, if you do that then it works for most of the stuff already

The “most of the stuff” is what hurts currently.
You cannot rely on a warning system that works “for the most part”.

jcompagner:
Yes stuff like this: databasemanager.getFoundset(“datasourcestring”) can never be smarter because that ‘datasourcestring’ is dynamic or just a string in code.
thats impossible to make better in this current setup.

Then it should be ignored by default: if you cannot make the parser smarter for now, don’t force that it be declared.

jcompagner:
And also you are talking about if we make it strict if we change javascript itself, that is completely not true, it is just a helper tool so that in code everything knows what it can and can’t do.

When I want completion and refactoring on some fixed structure this is fine to have these warnings and JSDocs enforced, but when I want to use JavaScript’s loose objects and pass them around (with no pre-defined structure) right now there’s 2 only options: I get warnings that are confusing, or I turn everything off and then I don’t have any warnings anymore, even for really wrong usage.
This is also wrong for object that I could retrieve from JSON as someone pointed out. The power of JSON and JavaScript objects is that I don’t need to know the properties of an object in advance, I can also augment them on the fly, the way I would do with a Map. I should be able to tell the parser that this is my intent.

Thus the need of a /** @nontype */ tag, that would tag that object as unstructured once and for all and tell the pasrser that it shouldn’t be further considered for warnings.
This would mark an object decorated with it as a non-descript JavaScript Object that the parser shouldn’t create warnings markers from, ever.
I see lots of advantages in that.

Patrick again we dont FORCE you to define an extra type info for JSFoundSet
only if you want to really use the dataproviders directly in code and you have the warning “undefined java property” set to something else the “ignore”
If you set that specific warning on ignore then all java related objects like JSFoundSet and JSRecord and so on are just ignored.

Also you are talking also about a “nonetype” we already have that for parameters:

/**

  • @param event
    */
    function test(event) {
    event.xx;
    event.yy();
    }

nothing is reported if you do it like that, If you don’t specify any type info then we ignore it completely.

So tell me, you have the possibility to turn it all off, and you can just 'not type" a parameter so that it is ignored.

Patrick, i am also getting confused, what do you want, do you want that people are warned that if they do:

var record = xxx;
record.typoindataprovder = 10;

that that is or isn’t reported?

Because i one sentence you say “and then I don’t have any warnings anymore, even for really wrong usage.” and in another “Then it should be ignored by default: if you cannot make the parser smarter for now, don’t force that it be declared.”

huh???
thats a contradiction …
So what do you want??? Do you want full loose ? or a bit more stricter so that people don’t type the wrong dataprovider and so on?? What are “really wrong usage” things???
I my point of few “record.typoindataprovder = 10;” that is wrong usage…

Also if you do want that record to be reported but you do want to have javascript way more loose
then just disable that specific warning: “Undefined javascript property access” set that to “ignore”
If you only disable that, then all your pure javascript objects property access are just ignored and are completely dynamic…

jcompagner:
Patrick again we dont FORCE you to define an extra type info for JSFoundSet
only if you want to really use the dataproviders directly in code and you have the warning “undefined java property” set to something else the “ignore”
If you set that specific warning on ignore then all java related objects like JSFoundSet and JSRecord and so on are just ignored.

Also you are talking also about a “nonetype” we already have that for parameters:

/**

  • @param event
    */
    function test(event) {
    event.xx;
    event.yy();
    }

nothing is reported if you do it like that, If you don’t specify any type info then we ignore it completely.

So tell me, you have the possibility to turn it all off, and you can just 'not type" a parameter so that it is ignored.

Didn’t know about that option in the parameters. Is this documented anywhere?
First time I heard of it and I bet I’m not the only one!

jcompagner:
Patrick, i am also getting confused, what do you want, do you want that people are warned that if they do:

var record = xxx;
record.typoindataprovder = 10;

that that is or isn’t reported?

Because i one sentence you say “and then I don’t have any warnings anymore, even for really wrong usage.” and in another “Then it should be ignored by default: if you cannot make the parser smarter for now, don’t force that it be declared.”

huh???
thats a contradiction …
So what do you want??? Do you want full loose ? or a bit more stricter so that people don’t type the wrong dataprovider and so on?? What are “really wrong usage” things???
I my point of few “record.typoindataprovder = 10;” that is wrong usage…

Also if you do want that record to be reported but you do want to have javascript way more loose
then just disable that specific warning: “Undefined javascript property access” set that to “ignore”
If you only disable that, then all your pure javascript objects property access are just ignored and are completely dynamic…

The whole current behaviour of the parser and warnings is confusing, which might explain why I’m confused ;)

The previous post you revealed some undocumented feature that I guess would fit the bill for loose JS Object in the cases I’m talking about.
I’m sure there are others, except that it’s hard sometimes to discover what’s going to work (which is why there are numerous threads on this forum about JSDocs).

I’ve discussed with people lately who told me they just abandonned the idea of fixing all the warnings and are now shipping their solutions with them: I think this is wrong.
So I’m trying to think of options, better ways to avoid that.

I guess what I fail to understand is why for Servoy generated objects (JSFoundSet/JSDataSet/JSRecord), the parser cannot be strict while for custom objects it would allow for loose (as intended by the language).
An “all or nothing” option as you point to is currently not the best answer to every cases.

jcompagner:
Also you are talking also about a “nonetype” we already have that for parameters:

/**

  • @param event
    */
    function test(event) {
    event.xx;
    event.yy();
    }

nothing is reported if you do it like that, If you don’t specify any type info then we ignore it completely.

This works, I like it.

Annoyances to fix before I’m comfortable:

  • speed (looking forward to next release)
  • warning markers are above breakpoints (causes lots of fumbling around when debugging)
  • one command to turn off all warnings
  • update jsdoc automatically when adding a param to a current method (you do this already for new methods)
  • “open in script editor” and “open in form editor” shortcut keys for mac back to servoy 5 shortcuts (use the command key instead of cntrl key)

One thing we find extremely useful with the new editor is that we can setup an API via a global variable and inline jsdocs as follows and it gives the user/coder code completion. Just start typing “globals.CMS.” and all options are available right there. No going and looking up our API global methods like you had to in Servoy 5.

This approach also gives us the flexibility to deprecate or significantly change functions over time. The API function call remains the same but depending on what version of the CMS they are on, could call a specific global method. Wrapping global methods in this fashion instead of calling them directly is pretty powerful for code maintenance.

/**
 * The Sutra CMS api variable contains calls to commonly used functions.
 * Everything you need to call should be available below.
 * 
 * @properties={typeid:35,uuid:"669F47AD-6BF9-4038-A808-1A8530337316",variableType:-4}
 */
var CMS = {
		cookie : new Object(),
		//see forms.WEB_0__controller.CONTROLLER_setup() for how this data point is constructed
		data : new Object(),
		markup : {
				getAsset : function(/**String*/ assetInstanceID) {
						return globals.WEBc_markup_link_asset(assetInstanceID, globals.CMS.data, null, null, globals.CMS.data)
					},
				getErrorPage : function(/**JSRecord<db:/sutra_cms/web_site>*/ siteRec) {
						return globals.WEBc_markup_link_error(siteRec)
					},
				getHomePage : function(/**JSRecord<db:/sutra_cms/web_site>*/ siteRec) {
						return globals.WEBc_markup_link_home(siteRec)
					},
				getPagesAttribute : function(/**String*/ att) {
						return globals.WEBc_markup_pages_attribute(globals.CMS.data, att)
					},
				getPagesDown : function(/**JSRecord<db:/sutra_cms/web_page>*/pageRec, /**JSRecord<db:/sutra_cms/web_path>*/ pathRec) {
						return globals.WEBc_markup_pages_down(null, pageRec, pathRec)
					},
				getPagesUp : function(/**JSRecord<db:/sutra_cms/web_page>*/pageRec, /**JSRecord<db:/sutra_cms/web_path>*/ pathRec, /**String*/ order) {
						return globals.WEBc_markup_pages_up(null, order, pageRec, pathRec)
					},
				getSiteDirectory : function(/**String*/ pageID) {
						//check if globals.CMS.data is defined to get language
						if (globals.CMS.data && globals.CMS.data.language && globals.CMS.data.language.record && utils.hasRecords(globals.CMS.data.language.record,'web_language_to_site_language')) {
							var siteLanguageRec = globals.CMS.data.language.record.web_language_to_site_language.getSelectedRecord()
						}
						
						//check if page specified; pass in object if not
						if (!pageID) {
							pageID = globals.CMS.data
						}
						
						//both the base and resource url methods will return with "sutraCMS/"; need to remove from one so no doubling
						return utils.stringReplace(globals.WEBc_markup_link_base(pageID,null,siteLanguageRec),'sutraCMS/','') + globals.WEBc_markup_link_resources(pageID)
					}
			},
		session : {
				clearData : function(/**String*/ sessionID, /**String*/ dataKey) {
						return globals.WEBc_session_deleteData(sessionID,dataKey)
					},
				getData : function(/**String*/ sessionID, /**String*/ dataKey) {
						return globals.WEBc_session_getData(sessionID,dataKey)
					},
				getSession : function(/**String*/ sessionID) {
						return globals.WEBc_session_getSession(sessionID)
					},
				setData : function(/**String*/ sessionID, /**String*/ dataKey, /**Object*/ dataValue) {
						return globals.WEBc_session_setData(sessionID, dataKey, dataValue)
					}
			},
		token : {
				getFile : function(/**JSRecord|String|UUID*/ input) {
						return {
							link : globals.WEBc_markup_token(input, 'file'),
							name : globals.WEBc_markup_token(input, 'fileName')
						}
					},
				getImage : function(/**JSRecord|String|UUID*/ input) {
						return {
							link : globals.WEBc_markup_token(input, 'image'),
							name : globals.WEBc_markup_token(input, 'imageName')
						}
					},
				getPage : function(/**JSRecord|String|UUID*/ input) {
						return {
							link : globals.WEBc_markup_token(input, 'page'),
							name : globals.WEBc_markup_token(input, 'pageName')
						}
					}
			},
		ui : {
				getData : function(/**JSForm*/ formName) {
						return globals.WEBc_block_getData(formName)
					},
				setData : function(/**JSEvent*/ event, /**String*/ key, /**String*/ value, /**JSForm*/ formName) {
						return globals.WEBc_block_setData(event,key,value,formName)
					},
				getConfig : function(/**JSForm*/ formName) {
						return globals.WEBc_block_getConfig(formName)
					},
				setConfig : function(/**JSEvent*/ event, /**String*/ key, /**String*/ value, /**JSForm*/ formName) {
						return globals.WEBc_block_setConfig(event,key,value,formName)
					},
				getResponse : function(/**JSForm*/ formName) {
						return globals.WEBc_block_getResponse(formName)
					},
				setResponse : function() {
						return globals.WEBc_markup_block_saveResponse(globals.CMS.data)
					},
				getDisplay : function(/**JSForm*/ formName) {
						return globals.WEBc_block_getDisplay(formName)
					},
				getEdit : function() {
						return globals.WEBc_block_getEdit()
					}
			},
		"utils" : {
				stripHTML : function(/**String*/ str) {
						return WEBc_data_strip_html(str)
					},
				stripCommonWords : function(/**String*/ str) {
						return WEBc_data_strip_common_words(str)
					},
				stripPunctuation : function(/**String*/ str) {
						return WEBc_data_strip_punctuation(str)
					},
				getCMSVersion : function() {
						return globals.CMS.data.cmsVersion
					}
			}
	};

didn’t you read my replies?

You can configure anything you want…

if you want strict mode for JSFoundset or databaseManager (which are really java objects…) and loose mode for javascript (custom) objects
Then that is perfectly possible…
Go to the preferences and set the “Undefined java property access” to “warning” or 'error"
and set the “Undefined javascript property access” to “ignore”

(and you could also do that with undefined function but i guess it is better to let that be a warning or error but thats up to the developer)

the JSDoc notation for param is:

@param {Type} name

but {Type} is not mandatory… You don’t have to specify type. We even don’t generate that on certain places for example if you have a media dataprovider and you generate there a onDataChange method on
we don’t generate the type because we have no idea what the real type is…

david:
[function(/*String/ assetInstanceID)

This looks like yet another undocumented syntax…
Is this all thread a big misunderstanding because of undocumented features?

Will this thread be the only place where people will learn that {Type} is not mandatory?
Seems like an essential piece of information missing from the docs…

My conclusion is that the exact syntax and behavior of JSDocs should be thoroughly documented in the Wiki (in a page of its own and not only buried in the “New in this release” page for Servoy 6).

david:

  • speed (looking forward to next release)

if you still have a problem with some problems with the 6.0.6 release which will be released shortly then please
open a case with if possible the file or completely workspace that is slow. Then i can debug it.

david:

  • warning markers are above breakpoints (causes lots of fumbling around when debugging)

Welcome to the club, this is something in eclipse, i have the same in the java editors :(
(yes really annoying)

david:

  • one command to turn off all warnings

make a feature request, but i don’t know if you really should do this, but i guess a button could be made to toggle between ignore and warning for everything…

david:

  • update jsdoc automatically when adding a param to a current method (you do this already for new methods)

We should just do that when saving? or should it just be a quick fix so that developers know what happens?

david:

  • “open in script editor” and “open in form editor” shortcut keys for mac back to servoy 5 shortcuts (use the command key instead of cntrl key)

this is one i don’t get, it is configured like: M1+M2+A in the plugin
And M1 stands for Command on the mac or Ctrl on windows…
So it should be Command-Shift-A for you on the mac…

You can always change the keybindings the way you want, just open the preferences and filter on “keys”.