2016-10-07 8 views
4

Я пытаюсь проанализировать скрипт Pester и извлечь значения из параметра -Tag. Кто-нибудь знает, как это сделать, используя [System.Management.Automation.PSParser]?. Я думал, что мне придется перебирать токены, возвращаемые с [System.Management.Automation.PSParser]::Tokenize(), но это кажется довольно клонистым и учитывая, что значения для -Tag могут быть предоставлены в разных форматах, не очень практичны.Анализ синтаксического сценария PowerShell с AST

В конце дня я надеюсь вернуть коллекцию с именем блока Describe и списком тегов (если они есть) для этого блока.

Name  Tags   
----  ----   
Section1 {tag1, tag2} 
Section2 {foo, bar} 
Section3 {asdf}  
Section4 {}  

Вот примеры тестов Pester, с которыми я работаю.

describe 'Section1' -Tag @('tag1', 'tag2') { 
    it 'blah1' { 
     $true | should be $true 
    } 
} 
describe 'Section2' -Tag 'foo', 'bar' { 
    it 'blah2' { 
     $true | should be $true 
    }  
} 
describe 'Section3' -Tag 'asdf'{ 
    it 'blah3' { 
     $true | should be $true 
    } 
} 
describe 'Section4' { 
    it 'blah4' { 
     $true | should be $true 
    } 
} 

У кого-нибудь есть идеи, как это решить? Есть [System.Management.Automation.PSParser] правильный путь, или есть лучший способ?

Приветствия

ответ

4

Использование PS3.0 + Language namespace АСТ парсер:

$text = Get-Content 'pester-script.ps1' -Raw # text is a multiline string, not an array! 

$tokens = $null 
$errors = $null 
[Management.Automation.Language.Parser]::ParseInput($text, [ref]$tokens, [ref]$errors). 
    FindAll([Func[Management.Automation.Language.Ast,bool]]{ 
     param ($ast) 
     $ast.CommandElements -and 
     $ast.CommandElements[0].Value -eq 'describe' 
    }, $true) | 
    ForEach { 
     $CE = $_.CommandElements 
     $secondString = ($CE | Where { $_.StaticType.name -eq 'string' })[1] 
     $tagIdx = $CE.IndexOf(($CE | Where ParameterName -eq 'Tag')) + 1 
     $tags = if ($tagIdx -and $tagIdx -lt $CE.Count) { 
      $CE[$tagIdx].Extent 
     } 
     New-Object PSCustomObject -Property @{ 
      Name = $secondString 
      Tags = $tags 
     } 
    } 
Name  Tags    
----  ----    
'Section1' @('tag1', 'tag2') 
'Section2' 'foo', 'bar'  
'Section3' 'asdf'   
'Section4' 

код не интерпретирует теги в виде списка строк, а просто использует исходный текст extent.
Используйте отладчик в PowerShell ISE/Visual Studio/VSCode для проверки различных типов данных.

+0

Спасибо @ w0xx0m. С небольшим изменением мне удалось вытащить теги как [string] или [string []]. – devblackops