Skip to content

Intellisense does not show module-private functions #104

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
leoniDEV opened this issue Feb 28, 2016 · 17 comments
Open

Intellisense does not show module-private functions #104

leoniDEV opened this issue Feb 28, 2016 · 17 comments
Assignees
Labels
Area-IntelliSense Issue-Enhancement A feature request (enhancement).

Comments

@leoniDEV
Copy link

Inside of my script modules I don't use the naming convention "verb-noun" for the functions which are private and are used only inside the modules and therefore I don't expose. Tipically I put these functions in a nested module.

Intellisense is unable to suggest these functions if I try to call them from the parent module or others nested modules, also Peek Definition and Find All Reference don't give me any results.
Instead Peek Definition and Fin All Reference work properly if I'm in the module where the function is defined, while Intellisens works partially, it suggest me the funtion but don't show the extendend information.

If the functions follow the "verb-noun" naming convention Intellisense, Peek Definition and Find All Reference work fine, no matter where they are defined and where I try to call them

@daviwil daviwil added the Issue-Enhancement A feature request (enhancement). label Feb 29, 2016
@daviwil daviwil added this to the Backlog milestone Feb 29, 2016
@daviwil
Copy link
Contributor

daviwil commented Feb 29, 2016

Hey @leoniDEV,

Not sure why "verb-noun" functions are working, I was under the impression that functions from nested modules weren't working at this point. I'd definitely like to make this work, though!

Could you do me a favor and try this in the PowerShell ISE and see if it works for you? Also, would you mind giving me a simple example that I can use to reproduce this on my side? You can either paste some simple code files here into the issue or use https://gist.github.com/ and create a Gist with multiple files (use the Add File) button on that page.

Thanks!

@leoniDEV
Copy link
Author

leoniDEV commented Mar 1, 2016

In the ISE all work fine.
I've made a very simple module with some comments to explain how you can reproduce what i'm describing:
https://gist.github.com/leoniDEV/cbcc87ba7c374ad7c4e1

After some more investigation i've found that the problem could be in the FunctionsToExport property of the module manifest, usually I assign to that property the string "-" so the module export only the functions with a dash in the name which are the ones that follow the naming convention.

If I export all the functions (using "*" instead of "-") and restart VSCode (exiting and reopening the module in VSCode) it seems that everything works properly also for the functions that haven't a dash in the name (except for the syntax highlighting which still doens't works).

@daviwil
Copy link
Contributor

daviwil commented Mar 1, 2016

Thanks for the example, that is helpful! The FunctionsToExport property may be part of the puzzle. I'll look into this and see if I can figure out what's going on.

@daviwil daviwil self-assigned this Mar 1, 2016
@KirkMunro
Copy link

@leoniDEV This issue aside, as a best practice you should explicitly list your function names in your manifest, and avoid wildcard in FunctionsToExport, AliasesToExport, CmdletsToExport, etc. attributes. Explicitly identifying command names in a module manifest is more reliable and it improves performance by eliminating unnecessary inspection work that PowerShell needs to do when wildcards are used in the "ToExport" attributes.

@leoniDEV
Copy link
Author

leoniDEV commented Mar 2, 2016

Good to know but sometimes, when there are many functions to export it is more practical to use wildcards, or when the module isn't complete and the functions and their names may vary often

@KirkMunro
Copy link

Maybe when you're developing the module, but even then a relatively simple script could easily pull out the names of the functions you want to export and automatically update your psd1 file so that it has explicitly defined exports before you publish it. Even without that in place, it is so little effort to maintain as you develop the module (add/rename/remove a function you want exported, modify the manifest), that even when there are many functions, that there really isn't any good excuse for not doing it imho. You just need to be diciplined enough to get it done.

@daviwil
Copy link
Contributor

daviwil commented Mar 2, 2016

Hmmm, seems like some nice editor should have an "Export function from module" command which can automatically detect which psd1 file to which the function under the cursor should be added and then add it ;) I definitely want to add some module creation utilities to Editor Services.

@leoniDEV
Copy link
Author

leoniDEV commented Mar 4, 2016

@KirkMunro I always try to follow the best practice in a very strict way (sometimes too strict) when I do something, and if I need to use my module in a real production environment or I want to make public my modules I definitely would try to apply all the best practices (at least the ones I know).
But I want to point out that I'm not an IT PRO or a developer, I'm only a "nerd" passonate to informatic so I'm not aware of many things.
I made some modules for fun or for manage my personal staff or for my little office (with 5 client and a file server+domain controller which require a very very little effort to manage) so I never made my modules public or used in a real production environment.
So every time I made or update a module I try to learn something new and try to do my staff in a little more professional ways, so thanks for the suggestion.

@daviwil Every utilities which can help the development are well accepted

Anyways even if it is OT, I want to take the opportunity to ask what is the best channel to report a bug about Powershell, connect.microsoft.com, UserVoice, Githhub or what? Because I have an issue with Powershell (which is not related with the issue reported here) and I like to know if it is a bug or is the intended behavior or it can be addressed in some way.

@KirkMunro
Copy link

UserVoice is the go to place for PowerShell bugs/suggestions now. Here's a link:
https://windowsserver.uservoice.com/forums/301869-powershell

@daviwil
Copy link
Contributor

daviwil commented Mar 4, 2016

Yep, Kirk's right, UserVoice is the place to file feedback now.

@leoniDEV
Copy link
Author

leoniDEV commented Mar 4, 2016

Well, many thanks

@TylerLeonhardt
Copy link
Member

Reading over the comments here, I don't think I quite understand the issue. Can I have a little bit more context?

@SeeminglyScience
Copy link
Collaborator

@tylerl0706 functions that are private (not exported, think internal classes) don't show up in intellisense. They don't show up because command completion runs from the top level session state. Those private functions aren't in the top level session state, they are only discoverable from within the modules session state.

All of the solutions I can think of require

  1. The module to be actually imported into the session

  2. Us having some way of automatically detecting which module in the workspace they are working on. (Assuming there even is one)

Possible solutions:

  1. Force export private functions. This is what I usually do when I'm working on a private function heavy module. Something like this
$module = Get-Module MyModule
. $module { Export-ModuleMember -Function * }
$module | Import-Module -Force
  1. Something I've thought about but not actually tested, maybe we could run TabExpansion2 from within the module. Something like
$module = Get-Module MyModule
& $module { TabExpansion2 -inputScript 'example script' -cursorPosition 1 }

But that would require that TabExpansion2 doesn't have a session state, which I haven't checked. If it does we'd have to strip it first:

& $module { & ($function:TabExpansion2.Ast.GetScriptBlock()) -inputScript 'example script' -cursorPosition 1 }

@TylerLeonhardt TylerLeonhardt modified the milestone: Future May 24, 2018
@rjmholt rjmholt changed the title Intellisense don't recognize functions that doesn't match the naming convention of Powarshell Intellisense don't recognize functions that doesn't match the naming convention of PowerShell Oct 10, 2018
@rjmholt rjmholt changed the title Intellisense don't recognize functions that doesn't match the naming convention of PowerShell Intellisense does not show module-private functions Oct 10, 2018
@rjmholt
Copy link
Contributor

rjmholt commented Oct 10, 2018

Reading over this just now, is this not by-design? Is there a reason we would want intellisense to show non-exported functions? That would be like giving completions for out-of-scope variables, no?

@SeeminglyScience
Copy link
Collaborator

@rjmholt Think of it like showing internal members for the project you're working on. The idea is to show intellisense for non-exported functions if the file/function you are editing would typically be in that scope.

Also in 2.0, support for $Host.EnterNestedPrompt() buys us this:

& (gmo MyModule) { $Host.EnterNestedPrompt() }

While in that nested prompt all intellisense will be from within the module's SessionState.

That's a decent workaround for now, but ideally it wouldn't require importing the module at all.

@rjmholt
Copy link
Contributor

rjmholt commented Oct 11, 2018

Oh right! To summarise the problem:

I want to edit a module, but to interact with it, PSES imports it, meaning it doesn't see/expose module-private members.

I'm thinking PSES should dot-source it instead?

@SeeminglyScience
Copy link
Collaborator

SeeminglyScience commented Oct 11, 2018

That's right!

I'm thinking PSES should dot-source it instead?

Nah, can't do that. Trying to dot source a psm1 or psd1 is the same as Invoke-Item (typically open in default text editor)

You could:

  1. Use the above enter nested prompt trick
  2. Import the module and then do
    $m = Get-Module Name
    . $m Export-ModuleMember -Function *
    $m | Import-Module -Force
  3. Hook into completion and generate completion results based on the workspace (preferably without even loading the module).

The last one would be ideal obviously, but significantly more work involved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-IntelliSense Issue-Enhancement A feature request (enhancement).
Projects
None yet
Development

No branches or pull requests

7 participants