How can I implementing method auto-completing?

Hi, 

I'm developing a plugin to support a JavaScript platform, this platform have the its own module system, with the grammar as below:

/**
* main.js
*/
define(["./a.js"], function(a){
a.<caret>
})

/**
* a.js
*/
define([], function(){
return {
"test" : 1,
"test2" : 2,
"ItsAFun": function(){ console.log(3)}
}
})

Now I  want to the place where "<caret>" placed will have the auto completion, showing a list of suggestions, just as what Nodejs plugin does. Now I have implemented resolve the jsLiteralElement "./a.js" to PsiFile("a.js"). 

I guess I should solve the parameter "a" to the PsiElement of the PsiElement after return, but in this way, when I command-click the parameter "a", it will just navigate to the file a.js, but not show the usage.

So could you tell me how to achieve the methods/fields auto completing?

 

18 comments
Comment actions Permalink

This should be handled in JSTypeEvaluator#addTypeFromAmdModuleReference, but it is written in such a way that custom file references are not supported. I've fixed it, so your code should work without additional tweaks in the next IDEA version.

0
Comment actions Permalink

hi, Konstantin.

The code written shows above is using its own module system, which is different from Amd Module. I have wrote path resolve code for its package. So it's ok to use JSTypeEvaluator#addTypeFromAmdModuleReference you mentioned? 

Now I wanna to reuse the code from ES6ImportSpecifierCompletionProvider, it's ok to use those code? Because JavaScriptLang isn't open source, I wonder whether my plugin will not pass your company's approval. 

0
Comment actions Permalink

Yep, I mean if you implement resolving of JSLiteralExpression to PsiFile, competion will just work. 

I have no legitimate answer about copying code from ES6ImportSpecifierCompletionProvider. Maybe it is possible to reuse it another way?

0
Comment actions Permalink

Could you please tell me whether `the next IDEA version` you mentioned is the same as EAP downloadable in the jetbrain website? If not, when will this version be published?

0
Comment actions Permalink
/**
* main.js
*/
define(["./a.js"], function(aaaa){
aaaa.<caret>
})

/**
* a.js
*/
define([], function(){
return {
"test" : 1,
"test2" : 2,
"ItsAFun": function(){ console.log(3)}
}
})


I tried resolve the parameter aaaa to the return value of function in file "a.js", in other words the psi element of
{
"test" : 1,
"test2" : 2,
"ItsAFun": function(){ console.log(3)}
}

but I can't get the right completions.

I just find it works well in es6's import/export or nodejs's require. 

Is there someway for me to implement this feature? 

 

0
Comment actions Permalink

No, the version I mentioned is not available now, it will be the next published EAP version, probably next week.

0
Comment actions Permalink

References shouldn't be resolved to expressions, but to variables, definitions etc. You shouldn't change resolving of 'aaaa' in this case. As I said, hopefully in the new IDEA version containing my yesterday's fix completion will just work.

0
Comment actions Permalink

Konstantin, thanks for you reply. Hope to see next version will work. 

One more question please.

As your said, I should resolve the reference to the variables or definitions.  I change the code, shows below.

/**
* main.js
*/
define(["./a.js"], function(aaaa){
aaaa.<caret>
})

/**
* a.js
*/
define([], function(){
var Avariable = {
"test" : 1,
"test2" : 2,
"ItsAFun": function(){ console.log(3)}
}
return a;
})



 

 

I could resolve the JSParameter `aaaa` to the JSElement `Avariable`, and when I command click JSParameter `aaaa`, it'll jump to the Avariable. But when I click the JSReferceExpression `aaaa`, it will just jump to JSParameter `aaaa`. This is different from ES6 import/export logic, where I command-click those two kinds of element, it will all go to Avariant. So I wander whether this is the problem why I can not get auto method completions works.  

And I also try to change the resolve element of JSReferceExpression `aaaa` to Avariant, just as what I do in resolving JSParameter, I think if I get JSReferceExpression `aaaa` resolve to the right things, then the mothod completions will get work. Can I do this?

0
Comment actions Permalink

We prefer not to resolve references to elements having different name, e.g. to keep rename working. I'd suggest to add GotoDeclarationHandler instead.

0
Comment actions Permalink

hi, Ulitin,

Whether the version mentioned above have released?

 

0
Comment actions Permalink

Hi Abnerzheng. Yes, it was, it's 2017.1.

0
Comment actions Permalink

Hi Ulitin, 

Sorry for reply so late.  These day I have too many task to do. 

I have tried 2017.1, but found it doesn't work. So would you please give me some more detail?

0
Comment actions Permalink

Hi Ulitin, 

I tried what you said again, and sadly found it didn't work. I wonder if I misunderstanding your idea, so I write down what I did and what I want to achieve.

 

This is my example code as posted above:

/**
* main.js
*/
define(["./a.js"], function(aaaa){
aaaa.<caret>
})

/**
* a.js
*/
define([], function(){
var Avariable = {
"test" : 1,
"test2" : 2,
"ItsAFun": function(){ console.log(3)}
}
return a;
})


 

Now I  want to the place where "<caret>" placed will have the auto completion, showing a list of suggestions, just as what Nodejs plugin does.  As you said above, when I have implemented resolving of JSLiteralExpression to PsiFile, completion will just work.  So I have resolve "./a.js" and "aaaa" both to the PsiFile "a.js". But nothing changed. 

Could you please give me some help?

0
Comment actions Permalink

Hi. You shouldn't change resolve of 'aaaa', only make "./a.js" resolved to PsiFile. Also, please note that in your example Avariable should be returned. Does this help?

0
Comment actions Permalink

Thanks for your answer. I trie your suggestion " You shouldn't change resolve of 'aaaa', only make "./a.js" resolved to PsiFile" . But found it doesn't work. 

I recorded a gif, you can click http://recordit.co/DRGUkayTJq .  Is there anything wrong?

0
Comment actions Permalink

By convention, elements having names starting with underscore are considered private (unless they have @public tag in JSDoc) and we don't show them in completion. Can you please check if it works for the example you posted with changed  'return a;' to 'return Avariable;'?

0
Comment actions Permalink

Yeah, it works!  

But there is still some problem.  The example I give above is:

define(["./a.js"], function(aaaa){
aaaa.<caret>
})

/**
* a.js
*/
define([], function(){
var Avariable = {
"test" : 1,
"test2" : 2,
"ItsAFun": function(){ console.log(3)}
}
return a;
})







But actually, in our project, we use NEJ.define, rather than define, and in this way,
method auto completion will not work. Is there any patch to this?



0
Comment actions Permalink

Unfortunately, there's no extension point for it now. It's checked in com.intellij.lang.javascript.frameworks.amd.JSAmdPsiUtil.isDefineCall.

0

Please sign in to leave a comment.