Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Added PSUseFullyQualifiedCmdletNames rule with fix capabilities#2122

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
genXdev wants to merge9 commits intoPowerShell:main
base:main
Choose a base branch
Loading
fromgenXdev:main

Conversation

@genXdev
Copy link

PR Summary

Add new diagnostic rulePSUseFullyQualifiedCmdletNames to replace aliases and unqualified cmdlet names with fully qualified versions (e.g.,ModuleName\CmdletName).

This rule addresses a common pain point in PowerShell scripting where cmdlet names without module prefixes can lead to ambiguity, especially in environments with multiple modules exporting similarly named cmdlets. By enforcing fully qualified names, the rule provides the following benefits:

  • Automatic module loading: PowerShell will auto-load the specified module if it's not already loaded when the qualified cmdlet is invoked.
  • Enhanced safety: Prevents accidental execution of the wrong cmdlet due to name conflicts across modules, reducing runtime errors.
  • Improved readability and maintainability: Explicit module references make the code's intent clearer, aiding in code reviews and long-term upkeep.
  • Better portability: Scripts become more reliable across different PowerShell environments or versions where module availability might vary.
  • Reduced ambiguity: Helps avoid issues with alias resolution or unqualified names that might resolve differently based on session state.
  • Facilitates advanced editor features: Supports better IntelliSense, auto-completion, and static analysis in tools like VS Code.

This change directly relates toPowerShell/PSScriptAnalyzer#2123, where the PowerShell extension for VS Code has been reported to unexpectedly remove module prefixes (e.g., convertingMicrosoftTeams\Get-CsLisCivicAddress toGet-CsLisCivicAddress) during code formatting, potentially introducing ambiguities and runtime issues in scripts. This new rule enables users to automatically add or restore fully qualified cmdlet names during analysis or formatting, helping to repair the damage caused by such removals and promoting safer, more explicit scripting practices.

Implemented inRules/UseFullyQualifiedCmdletNames.cs, with accompanying tests in the test suite to verify replacement logic for aliases (e.g.,lsMicrosoft.PowerShell.Management\Get-ChildItem) and unqualified cmdlets.

PR Checklist

CopilotAI review requested due to automatic review settingsAugust 19, 2025 04:07
Copy link
Contributor

CopilotAI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Pull Request Overview

This PR introduces a new PowerShell Script Analyzer rulePSUseFullQualifiedCmdletNames that enforces the use of fully qualified cmdlet names (e.g.,ModuleName\CmdletName) instead of aliases or unqualified names to improve script reliability and prevent ambiguity.

  • Implements diagnostic rule with automatic fix capabilities for replacing aliases and unqualified cmdlets
  • Adds caching mechanism for command resolution to improve performance
  • Provides localized error messages and correction descriptions

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

FileDescription
Rules/UseFullyQualifiedCmdletNames.csCore implementation of the new diagnostic rule with command resolution and fix suggestions
Rules/Strings.resxLocalized string resources for error messages and rule descriptions

Tip: Customize your code reviews with copilot-instructions.md.Create the file orlearn how to get started.


var extent = commandAst.CommandElements[0].Extent;

bool isAlias = commandName != fullyQualifiedName.Split('\\')[1];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

The logic for determining if a command is an alias is incorrect. This will incorrectly identify unqualified cmdlets as aliases when the command name matches the actual cmdlet name. Consider checking the resolved command type instead:bool isAlias = resolvedCommand.CommandType == CommandTypes.Alias;

Suggested change
bool isAlias = commandName != fullyQualifiedName.Split('\\')[1];

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Not following..


var extent = commandAst.CommandElements[0].Extent;

bool isAlias = commandName != fullyQualifiedName.Split('\\')[1];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

TheSplit('\\')[1] operation is performed for every command analysis. Since the actual cmdlet name is already available from the resolution logic above (line 99), consider storing it in a variable to avoid redundant string operations.

Suggested change
boolisAlias=commandName!=fullyQualifiedName.Split('\\')[1];
else
{
// Extract actualCmdletName from the cached fullyQualifiedName
intidx=fullyQualifiedName.IndexOf('\\');
actualCmdletName=(idx>=0&&idx<fullyQualifiedName.Length-1)
?fullyQualifiedName.Substring(idx+1)
:fullyQualifiedName;
}
varextent=commandAst.CommandElements[0].Extent;
boolisAlias=commandName!=actualCmdletName;

Copilot uses AI. Check for mistakes.
genXdevand others added3 commitsAugust 19, 2025 06:20
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@genXdev
Copy link
Author

@microsoft-github-policy-service agree

I have sole ownership of intellectual property rights to my Submissions and I am not making Submissions in the course of work for my employer.

@microsoft-github-policy-service agree company="Microsoft"

@genXdev
Copy link
Author

@genXdev please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.

@microsoft-github-policy-service agree [company="{your company}"]

Options:

  • (default - no company specified) I have sole ownership of intellectual property rights to my Submissions and I am not making Submissions in the course of work for my employer.
@microsoft-github-policy-service agree
  • (when company given) I am making Submissions in the course of work for my employer (or my employer has intellectual property rights in my Submissions by contract or applicable law). I have permission from my employer to make Submissions and enter into this Agreement on behalf of my employer. By signing below, the defined term “You” includes me and my employer.
@microsoft-github-policy-service agree company="Microsoft"

Contributor License Agreement

@microsoft-github-policy-service agree

I have sole ownership of intellectual property rights to my Submissions and I am not making Submissions in the course of work for my employer.

@microsoft-github-policy-service agree company="Microsoft"

@liamjpeters
Copy link
Contributor

👋 Hey@genXdev, could you please add your tests and docs to the PR for your new rule? If you're still working on it, please title the PR as WIP and mark as draft.

My initial thoughts on this:

  • This shouldn't be a default rule. I would expect most people would find this behaviour undesirable - it makes even simple scripts incredibly verbose. My suggestion would be to make it a configurable rule, disabled by default. This allows those that want this behaviour to opt into it and still benefit from your hard work. See something likeUseSingularNouns as an example for making a rule configurable and offering settings.

  • If you made the rule configurable, you could add a setting for something likeIgnoredModules \IgnoredNamespaces. For commands in those modules (i.e.Microsoft.PowerShell.Management andMicrosoft.PowerShell.Utility) the rule would not expand them into their fully qualified names. This could help with some of the verbosity while still retaining the value you're after.

  • Looking through the context ofthe issue raised in the VSCode-PowerShell project, I'm not sure that this rule resolves that original issue (not that that's your stated goal). I think that, depending on order of rule execution/formatting, if your rule runs first to expand the command names to their fully qualified names - then the faulty rule runs to "correct" them - your hard work is undone. If it runs afterward it's simply masking that erroneous behaviour which will still be happening.

  • The rule name is inconsistent in the PR title (...FullQualified... vs...FullyQualified...).

@genXdev
Copy link
Author

👋 Hey@genXdev, could you please add your tests and docs to the PR for your new rule? If you're still working on it, please title the PR as WIP and mark as draft.

I have committed them;
971f02b

My initial thoughts on this:

  • This shouldn't be a default rule. I would expect most people would find this behaviour undesirable - it makes even simple scripts incredibly verbose. My suggestion would be to make it a configurable rule, disabled by default. This allows those that want this behaviour to opt into it and still benefit from your hard work. See something likeUseSingularNouns as an example for making a rule configurable and offering settings.

Whatever you think is best.

  • If you made the rule configurable, you could add a setting for something likeIgnoredModules \IgnoredNamespaces. For commands in those modules (i.e.Microsoft.PowerShell.Management andMicrosoft.PowerShell.Utility) the rule would not expand them into their fully qualified names. This could help with some of the verbosity while still retaining the value you're after.

If this still desirable, I'll add them, let me know.

  • Looking through the context ofthe issue raised in the VSCode-PowerShell project, I'm not sure that this rule resolves that original issue (not that that's your stated goal). I think that, depending on order of rule execution/formatting, if your rule runs first to expand the command names to their fully qualified names - then the faulty rule runs to "correct" them - your hard work is undone. If it runs afterward it's simply masking that erroneous behaviour which will still be happening.

Haven't tested that, for fixing damage, I only enabled my new rule with -Fix

Maybe not the place to mention it, but analyzing 100+ script files at once, I sometimes see 'Collection modified' concurrency exceptions.
I think it is because of SSADictionary, VariablesDictionary, VariableAnalysisDetails in .\Engine\VariableAnalysisBase.cs

@genXdevgenXdev changed the titleAdded PSUseFullQualifiedCmdletNames rule with fix capabilitiesAdded PSUseFullyQualifiedCmdletNames rule with fix capabilitiesAug 19, 2025
@genXdev
Copy link
Author

Also added 'IgnoredModules' parameter and updated tests and docs accordingly

@bergmeister
Copy link
Collaborator

Sorry it's taken so long. Agree to not enable it by default but otherwise happy to have it. I know some module owners do this for performance reasons and replace commands with the full version as part of their build process.@genXdev can you resolve the merge conflict please, I will then greenlight the running of the CI test suite

@genXdev
Copy link
Author

Sorry it's taken so long. Agree to not enable it by default but otherwise happy to have it. I know some module owners do this for performance reasons and replace commands with the full version as part of their build process.@genXdev can you resolve the merge conflict please, I will then greenlight the running of the CI test suite

Hi@bergmeister,

I've resolved the merge conflict. The conflict was in Strings.resx where my UseFullyQualifiedCmdletNames resource entries overlapped with the new AvoidReservedWordsAsFunctionNames entries from main. I kept both sets of changes.

Merge commit:f6d123d

The branch should now be ready for CI tests to run.

bergmeister reacted with thumbs up emoji

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

Copilot code reviewCopilotCopilot left review comments

@andyleejordanandyleejordanAwaiting requested review from andyleejordan

@bergmeisterbergmeisterAwaiting requested review from bergmeisterbergmeister is a code owner

@sdwheelersdwheelerAwaiting requested review from sdwheelersdwheeler is a code owner

@michaeltlombardimichaeltlombardiAwaiting requested review from michaeltlombardimichaeltlombardi is a code owner

At least 1 approving review is required to merge this pull request.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

3 participants

@genXdev@liamjpeters@bergmeister

[8]ページ先頭

©2009-2025 Movatter.jp