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

Function transformStatement

src/utils/powershell/parser.ts:1002–1103  ·  view source on GitHub ↗
(raw: RawStatement)

Source from the content-addressed store, hash-verified

1000/** Transform a raw statement into ParsedStatement */
1001// exported for testing
1002export function transformStatement(raw: RawStatement): ParsedStatement {
1003 const statementType = mapStatementType(raw.type)
1004 const commands: ParsedCommandElement[] = []
1005 const redirections: ParsedRedirection[] = []
1006
1007 if (raw.elements) {
1008 // PipelineAst: walk pipeline elements
1009 for (const elem of ensureArray(raw.elements)) {
1010 if (elem.type === 'CommandAst') {
1011 commands.push(transformCommandAst(elem))
1012 for (const redir of ensureArray(elem.redirections)) {
1013 redirections.push(transformRedirection(redir))
1014 }
1015 } else {
1016 commands.push(transformExpressionElement(elem))
1017 // SECURITY: CommandExpressionAst also carries .Redirections (inherited
1018 // from CommandBaseAst). `1 > /tmp/evil.txt` is a CommandExpressionAst
1019 // with a FileRedirectionAst. Must extract here or getFileRedirections()
1020 // misses it and compound commands like `Get-ChildItem; 1 > /tmp/x`
1021 // auto-allow at step 5 (only Get-ChildItem is checked).
1022 for (const redir of ensureArray(elem.redirections)) {
1023 redirections.push(transformRedirection(redir))
1024 }
1025 }
1026 }
1027 // SECURITY: The PS1 PipelineAst branch does a deep FindAll for
1028 // FileRedirectionAst to catch redirections hidden inside:
1029 // - colon-bound ParenExpressionAst args: -Name:('payload' > file)
1030 // - hashtable value statements: @{k='payload' > ~/.bashrc}
1031 // Both are invisible at the element level — the redirection's parent
1032 // is a child of CommandParameterAst / CommandExpressionAst, not a
1033 // separate pipeline element. Merge into statement-level redirections.
1034 //
1035 // The FindAll ALSO re-discovers direct-element redirections already
1036 // captured in the per-element loop above. Dedupe by (operator, target)
1037 // so tests and consumers see the real count.
1038 const seen = new Set(redirections.map(r => `${r.operator}\0${r.target}`))
1039 for (const redir of ensureArray(raw.redirections)) {
1040 const r = transformRedirection(redir)
1041 const key = `${r.operator}\0${r.target}`
1042 if (!seen.has(key)) {
1043 seen.add(key)
1044 redirections.push(r)
1045 }
1046 }
1047 } else {
1048 // Non-pipeline statement: add synthetic command entry with full text
1049 commands.push({
1050 name: raw.text,
1051 nameType: 'unknown',
1052 elementType: 'CommandExpressionAst',
1053 args: [],
1054 text: raw.text,
1055 })
1056 // SECURITY: The PS1 else-branch does a direct recursive FindAll on
1057 // FileRedirectionAst to catch expression redirections inside control flow
1058 // (if/for/foreach/while/switch/try/trap/&& and ||). The CommandAst FindAll
1059 // above CANNOT see these: in if ($x) { 1 > /tmp/evil }, the literal 1 with

Callers

nothing calls this directly

Calls 8

mapStatementTypeFunction · 0.85
ensureArrayFunction · 0.85
transformCommandAstFunction · 0.85
transformRedirectionFunction · 0.85
pushMethod · 0.45
hasMethod · 0.45
addMethod · 0.45

Tested by

no test coverage detected