Closed kzrnm closed 4 years ago
$csprojPath = "$PSScriptRoot/AtCoderLibrary/AtCoderLibrary.csproj"
$buildType = "Debug"
if ($UseRelease) { $buildType = "Release" }
$target = @(([xml](Get-Content $csprojPath)).GetElementsByTagName('TargetFramework'))[0].InnerText
$atcoderlibPath = "$PSScriptRoot/AtCoderLibrary/bin/$buildType/$target/AtCoderLibrary.dll"
if (-not (Test-Path $atcoderlibPath) ) {
Get-Command dotnet -ErrorAction SilentlyContinue | Out-Null
if ($?) {
dotnet build "$csprojPath" -c "$buildType"
}
else {
Write-Error "You need dotnet command."
exit
}
}
AtCoderLibrary.dll
(デフォルトでは"$PSScriptRoot/AtCoderLibrary/bin/Debug/netcoreapp3.1/AtCoderLibrary.dll"
)があるか確認。dotnet build
でビルドする。dotnet
コマンドが見つからない場合はしょうがないので終了する。文字通りHashtable
をマージする。
SyntaxTree
からSemanticModel
を取得する。ここでAtCoderLibrary.dll
が必要。
メソッド呼び出しを取得する。
ソースコード文字列をusingディレクティブと残りに分割する
ロジックの本体
$aclpath = Merge-Hashtable (
Get-ChildItem "$PSScriptRoot/aclpath.*.json" | ForEach-Object {
Get-Content $_ | ConvertFrom-Json -AsHashtable
})
aclpath.*.json
ファイルからクラス名とファイルの対応関係を取得する。aclpath.*.json
が複数あるならマージしておく。
if ($aclpath.ContainsKey($className)) {
$updated = $true
foreach ($file in $aclpath[$className]) {
if ($addedFiles.Add($file)) {
Write-Debug $file
$headUsing, $bodies = (Split-Code @(Get-Content $file))
$code = ($headUsing -join $lineBreak) + $lineBreak + $code + $lineBreak + ($bodies -join $lineBreak)
}
}
$aclpath.Remove($className)
}
expand部分。aclpath.*.json
を元に必要なファイルを持ってくる。usingディレクティブは本体より前、残りは後ろにつける。
$aclpath.ContainsKey($className)
が$true
であるかぎり、ソース解析→追加→……とループすることで必要なファイルを再帰的に追加する。
$lines = $code.Split($lineBreak)
$headUsing, $bodies = (Split-Code $lines)
$headUsing = [System.Collections.Generic.List[string]]$headUsing
$headUsing.Sort([System.Comparison[string]] { param($a, $b); [System.StringComparer]::Ordinal.Compare($a.Trim(';'), $b.Trim(';')) })
$headUsing = $headUsing | Get-Unique
usingディレクティブは重複しても問題ないが見た目が長くなってしまうので重複するものは削除する。
PowerShell標準のソートだと大文字小文字区別するソートができないのでList<T>
のソートを使う。
実装ありがとうございます!
別途 powershell
が必須なことに関して、技術選定をもう少しした上で確定する必要があると感じています。自分で実装するつもりでいたため、仕様等をあまり議論していなかったのがとても申し訳ないです。
また、依存関係を記した json
ファイルを追加するのは保守コストの観点からも慎重になりたいという気持ちはあります。
現段階では一旦確認は保留とさせて頂き、 #21 でもう少し議論を重ねたいです。本当に申し訳ありません。
保留中ですが機能改修です。
aclpath.default.json
を不要にした
21 について、Expanderを実装してみました。
PowerShell CoreがRoslynを標準搭載しているのでPythonより適しているかと思います。 WindowsとMacのPowerShell Core 7.0.3で動作確認しました。
AtCoderProgram
コンテスト時にコードを書くのを想定したプロジェクトです。
C# 8.0、
unsafe
許可、System.Runtime.CompilerServices.Unsafe
(4.7.0)などはAtCoderの環境にあわせています。このPull requestではProgram.csを含めていますが、実際には含めない方が良いかもしれません。
オプションについて
公式の
expander.py
に合わせて、ファイルではなく標準出力へ書き出すオプションもつけています。また、AtCoderLibraryの参照が必須なのでDebugかReleaseのどちらかを選ぶようにしています。どちらでも動くのであまり意味はないです。