_Recreating https://github.com/PowerShell/PSScriptAnalyzer/issues/1617 here for visibility, as I'm not sure whether this feature request relates to the analyzer, the extension, or both._
In the programming world, developers are encouraged to follow a "one type per file" rule. I am trying to apply this rule to classes in PowerShell. Unfortunately, I can't find a way to allow my editor (VS Code in my case) to "see" types in other files. Consider this trivial case where I have a module consisting of two classes:
Class1.ps1class Class1 {
[void]Method() {
}
}
Class2.ps1using module .\Class1.ps1
class Class2 {
Class2() {
$c = [Class1]::new() # Class1 is visible to the analyzer
$c. # Method() is not visible
}
}
I experimented with using module .\Class1.ps1 to fake out the editor into thinking the script file was a module. This works, but only the type becomes visible; its members do not.

If I inline the class, its members become visible, as one would expect:

Is there a way around this problem?
I'm not sure what can be done to improve the developer experience, but as it stands now this is preventing me from using classes to their full extent in my more complex PowerShell modules. I know I could always create a full-blown C# project, but that introduces build pipeline and CI dependencies I'm trying to avoid. It also means developers who work on my module need to be more aware of .NET tools like Visual Studio than they otherwise would need to be.
Some kind of special comment used by the extension and/or analyzer to temporarily import other files for the purposes of parsing, perhaps?
#analyze Class1.ps1
This has the following benefits:
#region in that it's an editor-specific feature#include from C or other similar languages2020.6.0
It seems that renaming the type scripts to .psm1 causes the type to be correctly imported:

However, this still has the same drawbacks mentioned above.
I am noticing my more complex usages of the using module workaround are not working as in the above screenshot. I'm not sure why.
Hi @nathan-alden-hp, I'm actually a maintainer of vscode-PowerShell, PSScriptAnalyzer and PowerShell, so I've got some visibility of this issue, the PSScriptAnalyzer issue and related discussions.
What you're describing is more or less a language-level feature, rather than something that's editor- or analyser-specific.
The #analyze pragma you're suggesting makes sense, but is effectively equivalent to the using module statement.
There are some discussions in issues in the PowerShell repo about classes, modules and discovery, but the fundamental issue is that PowerShell classes were originally not designed to be dot-sourced. Instead they were intended to be used like modules and shared with using module statements.
Completions in PowerShell come from the PowerShell engine rather than the editor (the language server just hooks into the engine to provide them to the editor). Similarly, when PSScriptAnalyzer looks at a script and shows TypeNotFound errors, it's because PowerShell's own parser is generating them, not the analyser.
The completion logic and the parser errors arise because the language isn't intended to support the way classes are often used, and if invoked as they are in the static state, these scripts won't run -- the errors are legitimate.
Naturally this puts the editor and analyser in a tricky spot, because:
For us to try and work around and reimplement completions would be a large undertaking, and one that would be secondary to other work items we're prioritising in the medium term.
Instead, I think the discussion has to come back to PowerShell itself, where PowerShell must solve the impedance mismatch between how the language implements classes in modules and how users actually want to use them. For the editor or analyser to try to take responsibility for taping over the seams in that experience is probably only going to suppress deeper issues that PowerShell itself needs to address.
Given that, I'm going to mark this issue as resolved and recommend that you open an issue on the PowerShell repo.
Some related issues:
Most helpful comment
Hi @nathan-alden-hp, I'm actually a maintainer of vscode-PowerShell, PSScriptAnalyzer and PowerShell, so I've got some visibility of this issue, the PSScriptAnalyzer issue and related discussions.
What you're describing is more or less a language-level feature, rather than something that's editor- or analyser-specific.
The
#analyzepragma you're suggesting makes sense, but is effectively equivalent to theusing modulestatement.There are some discussions in issues in the PowerShell repo about classes, modules and discovery, but the fundamental issue is that PowerShell classes were originally not designed to be dot-sourced. Instead they were intended to be used like modules and shared with
using modulestatements.Completions in PowerShell come from the PowerShell engine rather than the editor (the language server just hooks into the engine to provide them to the editor). Similarly, when PSScriptAnalyzer looks at a script and shows TypeNotFound errors, it's because PowerShell's own parser is generating them, not the analyser.
The completion logic and the parser errors arise because the language isn't intended to support the way classes are often used, and if invoked as they are in the static state, these scripts won't run -- the errors are legitimate.
Naturally this puts the editor and analyser in a tricky spot, because:
For us to try and work around and reimplement completions would be a large undertaking, and one that would be secondary to other work items we're prioritising in the medium term.
Instead, I think the discussion has to come back to PowerShell itself, where PowerShell must solve the impedance mismatch between how the language implements classes in modules and how users actually want to use them. For the editor or analyser to try to take responsibility for taping over the seams in that experience is probably only going to suppress deeper issues that PowerShell itself needs to address.
Given that, I'm going to mark this issue as resolved and recommend that you open an issue on the PowerShell repo.
Some related issues: