MCPcopy Index your code
hub / github.com/codeaashu/claude-code / extractPrefixFromElement

Function extractPrefixFromElement

src/utils/powershell/staticPrefix.ts:30–156  ·  view source on GitHub ↗

* Extract a static prefix from a single parsed command element. * Returns null for commands we won't suggest (shells, eval cmdlets, path-like * invocations) or can't extract a meaningful prefix from.

(
  cmd: ParsedCommandElement,
)

Source from the content-addressed store, hash-verified

28 * invocations) or can't extract a meaningful prefix from.
29 */
30async function extractPrefixFromElement(
31 cmd: ParsedCommandElement,
32): Promise<string | null> {
33 // nameType === 'application' means the raw name had path chars (./x, x\y,
34 // x.exe) — PowerShell will run a file, not a named cmdlet. Don't suggest.
35 // Same reasoning as the permission engine's nameType gate (PR #20096).
36 if (cmd.nameType === 'application') {
37 return null
38 }
39
40 const name = cmd.name
41 if (!name) {
42 return null
43 }
44
45 if (NEVER_SUGGEST.has(name.toLowerCase())) {
46 return null
47 }
48
49 // Cmdlets (Verb-Noun): the name alone is the right prefix granularity.
50 // Get-Process -Name pwsh → Get-Process. There's no subcommand concept.
51 if (cmd.nameType === 'cmdlet') {
52 return name
53 }
54
55 // External command. Guard the argv before feeding it to buildPrefix.
56 //
57 // elementTypes[0] (command name) must be a literal. `& $cmd status` has
58 // elementTypes[0]='Variable', name='$cmd' — classifies as 'unknown' (no path
59 // chars), passes NEVER_SUGGEST, getCommandSpec('$cmd')=null → returns bare
60 // '$cmd' → dead rule. Cheap to gate here.
61 //
62 // elementTypes[1..] (args) must all be StringConstant or Parameter. Anything
63 // dynamic (Variable/SubExpression/ScriptBlock/ExpandableString) would embed
64 // `$foo`/`$(...)` in the prefix → dead rule.
65 if (cmd.elementTypes?.[0] !== 'StringConstant') {
66 return null
67 }
68 for (let i = 0; i < cmd.args.length; i++) {
69 const t = cmd.elementTypes[i + 1]
70 if (t !== 'StringConstant' && t !== 'Parameter') {
71 return null
72 }
73 }
74
75 // Consult the fig spec — same oracle bash uses. If git's spec says -C takes
76 // a value, buildPrefix skips -C /repo and finds `status` as a subcommand.
77 // Lowercase for lookup: fig specs are filesystem paths (git.js), case-
78 // sensitive on Linux. PowerShell is case-insensitive (Git === git) so `Git`
79 // must resolve to the git spec. macOS hides this bug (case-insensitive fs).
80 // Call buildPrefix unconditionally — calculateDepth consults DEPTH_RULES
81 // before its own `if (!spec) return 2` fallback, so gcloud/aws/kubectl/az
82 // get depth-aware prefixes even without a loaded spec. The old
83 // `if (!spec) return name` short-circuit produced bare `gcloud:*` which
84 // auto-allows every gcloud subcommand.
85 const nameLower = name.toLowerCase()
86 const spec = await getCommandSpec(nameLower)
87 const prefix = await buildPrefix(name, cmd.args, spec)

Callers 2

getCommandPrefixStaticFunction · 0.85

Calls 2

buildPrefixFunction · 0.85
hasMethod · 0.45

Tested by

no test coverage detected