Почему в этом скрипте PowerShell так много StringConstantExpressionAst? - PullRequest
0 голосов
/ 20 октября 2019

Я делаю канонизацию некоторого набора данных PowerShell, и один шаг обработки состоит в замене всех переменных на X и всех строковых литералов на Y, чтобы я мог обнаруживать и удалять почти дубликаты.

Однако я заметил, что для многих сценариев после канонизации весь сценарий сводится к большому количеству Y и некоторым X с едва ли любым другим кодом. Это не то, что я ожидал, так как в сценариях есть только несколько переменных и строковых литералов.

Чтобы найти все строковые литералы, я использовал команду:

$Strings = $AST.FindAll({$args[0] -is System.Management.Automation.Language.StringConstantExpressionAst]}, $true)

Для устранения этой проблемы яиспользовал ShowPSAst (инструмент визуализации PowerShell AST) для визуализации одного примера сценария, в котором вышеупомянутая проблема была заметна.

Исходный сценарий выглядит следующим образом:

 Describe "Files" -Tag OSX,Linux {
    It "is utf-8 encoded" {
        $true | Should Be $false
    }
    It "uses Unix-style line endings" {
        $true | Should Be $false
    }
    It "has a shebang" {
        $true | Should Be $false
    }
}
Describe "Placeholder for Nano tests" -Tag Nano {
}

После канонизации я получаю следующее:

Y Y -Tag Y,Y {
    Y Y {
        X | Y Y X
    }
    Y Y {
        X | Y Y X
    }
    Y Y {
        X | Y Y X
    }
}
Y Y -Tag Y {
}

Отрывок визуализации AST для вышеуказанного сценария:

Part of the AST visualization of the above script

Обратите внимание, что выделенная часть на правой панели изображения соответствует узлу AST CommandAST на левой панели, который затем имеет множество StringConstantExpressionAst узлов в качестве дочерних элементов. ,Глядя на эти узлы AST, становится понятно, почему в моей канонической версии так много Y. Однако меня смущает то, что почти все отдельные токены в выделенном коде рассматриваются как StringContantExpressionAst. Я ожидаю, что только "Placeholder for Nano tests" будет считаться строковым литералом.

Если быть точным, я бы ожидал, что

Describe "Placeholder for Nano tests" -Tag Nano

будет преобразован в

 Describe Y -Tag Nano

, а НЕ в

Y Y -Tag Y

Я нея действительно не использую PowerShell самостоятельно и не знаю его тонкостей, поэтому я прошу прощения, если мне не хватает чего-то базового, и заранее благодарен за любую помощь в понимании этого поведения PowerShell.

1 Ответ

1 голос
/ 22 октября 2019

PowerShell - это интерпретируемый язык, то есть он не придает значения некоторым частям вашего кода, пока вы его не запустите. В вашем случае он не знает, что слово «Describe» относится к функции «Describe» в модуле «Pester» (которая может даже не быть импортирована в ваш сеанс), и это может означать внешнюю программу под названием «Describe». exe ", например.

Все, что делает анализатор, запоминает имя команды как StringConstantExpressionAst, и логика времени выполнения должна искать что-то для запуска с таким именем.

Если вы внимательно посмотрите на свой AST, то увидите, что токен "Describe" имеет свойство StringConstantType, равное BareWord, тогда как строка "my tests" имеет значение DoubleQuoted. Если вы хотите выполнять обработку только «буквенных строк», вы можете использовать свойство StringConstantType в качестве фильтра.

$Strings = $AST.FindAll(
    {
        ( $args[0] -is [System.Management.Automation.Language.StringConstantExpressionAst] ) -and
        ( $args[0].StringConstantType -ne "BareWord" )
    },
    $true
)

Кроме , тогда вы можете пропустить строки без кавычек в таких вещах, как:

Describe Files -Tag OSX,Linux {

Таким образом, другой (лучше?) Вариант может состоять в том, чтобы просто игнорировать первый дочерний элемент в любых узлах CommandAst.

...