Skip to content
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

Add-Type -AssemblyName not taken into account by the completion #637

Open
nanoant opened this issue Mar 21, 2018 · 8 comments
Open

Add-Type -AssemblyName not taken into account by the completion #637

nanoant opened this issue Mar 21, 2018 · 8 comments
Labels
Area-IntelliSense Issue-Enhancement A feature request (enhancement).

Comments

@nanoant
Copy link

nanoant commented Mar 21, 2018

I tried to look for the solution in existing tickets, but found no ticket mentioning Add-Type support.

I am using now PSES in Sublime Text with PR and recipe at: #629 (comment) and I found that it is not completing .NET types loaded by Add-Type e.g.:

Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.

completes only to types present in System.IO.Compression but not System.IO.Compression.FileSystem, like ZipFile.

psesaddtypecomplete

Also trying to complete [System.IO.Compression.ZipFile]:: returns nothing. I tried adding explicit path, no effect.

Do I need to explicitly specify additional modules somewhere when starting PSES or it should pick up the Add-Type from my script?

@SeeminglyScience
Copy link
Collaborator

So the intellisense provided by PSES is powered by the same API that powers tab completion in the PowerShell engine. For a lot of things, that API relies on session state. Until the engine can provide purely static completion for things like this the only way is to alter the session state of the runspace PSES is running in.

Ideally this would be done via an integrated console, but the easiest way to provide a way to do this for new implementations is to implement the equivalent of VSCode's F8 or PowerShell.RunSelection. To do this you need a hotkey/command/something that sends selected text (or current line) to PSES via the evaluate request.

Here's some relevant bits from VSCode:

EvaluateRequest definition

PowerShell.RunSelection definition

And from PSES

EvaluateRequest definition

HandleEvaluateRequest definition

As a sort of work around, you can also add bits of code for completion to your profile. Make sure to edit the one for the editor host (HostProfileId_profile.ps1 where HostProfileId is the value specified for that parameter in Start-EditorServicesHost)

@nanoant
Copy link
Author

nanoant commented Mar 21, 2018

Okay the workaround with HostProfileId_profile.ps1 worked, many thanks 👍, I had only a trouble because this functionality has to be explicitly enabled with:

			"settings": {
				"powershell": {
					"enableProfileLoading": true,
				}
			}

Anyway I think there might be at least some basic support for Add-Type handling without state considered. At least for the cases where it is explicit condition-less statement.

@SeeminglyScience
Copy link
Collaborator

Anyway I think there might be at least some basic support for Add-Type handling without state considered. At least for the cases where it is explicit condition-less statement.

Unfortunately there isn't, there's been discussions on how to implement it (mostly around using assembly x statements) but nothing has been added yet. Remember that debugging a script or running something in the integrated console will run against the same runspace used for completion, so that makes it difficult to tell what requires state and what doesn't (until you use an editor that can't easily modify it of course)

When in doubt, you can check by loading up PowerShell with no profile and running something like this

$script = '
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.'

TabExpansion2 -inputScript $script -cursorColumn $script.Length

If that doesn't give you the completion you expect, PSES won't either. Because of the dynamic nature of PowerShell, a lot of completion is based on what's loaded in the runspace. There's a bunch of completion improvements in core, but it's still kind of hard to get great intellisense without a way to invoke scripts in the runspace directly.

@TylerLeonhardt
Copy link
Member

Yeah @rjmholt, @joeyaiello and I were talking about this the other day. using assembly x is what we want people to do but there's currently not an incredible experience with that.

Same thing goes for Import-Module vs using.

We want folks to use using since it's a parse-time construct vs a runtime construct like Import-Module and Add-Type.

A plan isn't shelled out just yet, but expect more in this space in the near future.

@rjmholt
Copy link
Contributor

rjmholt commented Mar 25, 2018

Yeah, the problem with getting completions on Add-Type and Import-Module is that they are dynamic executions, just like Invoke-Expression. You can use arbitrary PowerShell in their arguments, anything from variables to calling Invoke-WebRequest. That means that trying to work out what they load is tantamount to just running PowerShell in your script. But as a static analysis and completion provider, that's exactly what we're trying to avoid.

We've been discussing this a bit in relation to the VS Code extension and for PSSA, and I think we're hoping to implement some support for using statements at some point. At which point we'll be able to recommend to everyone that:

If you can use a using statement, you should, because it requires a static description of the
resource that a static analyser is much more likely to succeed with.

To be clear, the way PowerShell works (depending on the module path, etc.), even using statements are not really static constructs (since what they load in depends on what's available when the script executes, not when you write it). And it's still tricky, since finding completions for a script loaded with using means going and finding that script in the filesystem and parsing it, and loading an assembly would mean having to parse the metadata (since we don't want to run it or load it in without being told explicitly to do that), and assemblies can depend on other assemblies through references, so in the worst case we would be jumping all over the file system trying to parse DLLs — which is why it's recommended that you write a module manifest when you can. BUT, to my mind a lot of it is possible, and in fact I've written metadata reading logic before to get completions out of a DLL, so it's something I'd like to see work on in the future.

@rkeithhill
Copy link
Contributor

In the meantime, if Sublime supports F8 style execution, try executing the Add-Type line(s). That works in VSCode.

@TylerLeonhardt
Copy link
Member

Might need to do some work on a Sublime extension to get F8 to work. Here's what we do in VSCode:

We have F8 bound to this command:
https://github.com/PowerShell/vscode-powershell/blob/945b12623406d8c7204ea8d36151d89e171109ff/src/features/Console.ts#L205-L229

which sends the "evaluate" message to the language server.

@arpan3t
Copy link

arpan3t commented Dec 14, 2024

Is this still the recommendation for this issue? I'm working on setting up PSES as the LSP for Neovim, and this issue is the only relevant search result I've found. It's a pretty old issue so I want to make sure I'm following best practices when setting up PSES.

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