VB.netでの質問です。
Visual Studio2017でのMacroを使用し特定のメソッド内の特定の部分だけを置換する方法はありますでしょうか。
文字を挿入することはできるのですが、特定のメソッド内のみを指定する方法がわかりません。
以下例文
VB.net
Private Sub Hoge1()
Dim hoge1 as integer
MsgBox("Hoge1")
End Sub
Private Sub Hoge2()
Dim hoge2 as integer
MsgBox("Hoge2")
End Sub
上記のHoge2()のメソッド内のみMsgBoxの内容を変えたといった場合どうすればよいでしょうか。 また方法についてはMacroでなくでも大丈夫です。 [追記] 申し訳ございません。情報が足りなさ過ぎました。 例として、ある作業フォルダに上記と同じコードが記述されたファイルが複数あるとして、 その作業フォルダ内にあるすべてのファイルのHoge2()内のMsgBoxの内容だけをを一括で置換したいということです。 Hoge1()内の内容は変えずにHoge2()の内容だけ変えたいです。 質問の仕方が下手で申し訳ございません。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2020/03/02 00:36
2020/03/02 11:54
2020/03/02 12:11
2020/03/02 12:21
2020/03/02 22:45
回答1件
0
ベストアンサー
「定数等に置き換えようにも数が多すぎて、手作業ではやっていられない」みたいな状況なんでしょうか?
マクロは使ったことない上、今はJavaScriptなんですかね??
全然わからないのでコンソールアプリで作ってみました。
NuGet
でMicrosoft.CodeAnalysis.VisualBasic
を入れること。
VBNET
1Imports System.IO 2Imports Microsoft.CodeAnalysis 3Imports Microsoft.CodeAnalysis.VisualBasic 4Imports Microsoft.CodeAnalysis.VisualBasic.Syntax 5 6Module Module1 7 Sub Main() 8 CreateDummyFiles() 9 10 Dim rewriter = New MethodBlockRewriter 11 For Each filePath In Directory.GetFiles("test", "*.vb") 12 Dim text = File.ReadAllText(filePath) 13 Dim tree = SyntaxFactory.ParseSyntaxTree(text) 14 text = rewriter.Visit(tree.GetRoot).ToFullString 15 File.WriteAllText(filePath, text) 16 Next 17 End Sub 18 19 Private Class MethodBlockRewriter 20 Inherits VisualBasicSyntaxRewriter 21 Public Overrides Function VisitMethodBlock(ByVal node As MethodBlockSyntax) As SyntaxNode 22 Dim mss = TryCast(node.BlockStatement, MethodStatementSyntax) 23 If mss Is Nothing Then 24 Return MyBase.VisitMethodBlock(node) 25 End If 26 ' メソッド名がHoge1でなければ何もしない 27 If mss.Identifier.ValueText <> "Hoge1" Then 28 Return MyBase.VisitMethodBlock(node) 29 End If 30 31 ' メソッドブロックを文字列に 32 Dim text = node.ToFullString 33 34 Dim name As String = "" 35 Dim tbs = TryCast(node.Parent, TypeBlockSyntax) 36 If tbs IsNot Nothing Then 37 ' クラス名orモジュール名取得 38 name = tbs.BlockStatement.Identifier.ValueText 39 End If 40 41 ' 置換 42 text = text.Replace("MsgBox(""Hoge1"")", $"MsgBox(""{name}.Hoge1"")") 43 44 45 ' 実際はそんな単純な置換ではないでしょうから 46 ' 他と絶対被らない目印を入れて 47 ' エディタ等の正規表現で一括置換したらいいんじゃないでしょうか 48 'text = text.Replace("MsgBox(", "'Replace Point!! MsgBox(") 49 50 51 ' textからMethodBlockSyntaxを作り直して返す(もっといい書き方がありそう 52 Return SyntaxFactory.ParseSyntaxTree(text).GetCompilationUnitRoot.Members(0) 53 End Function 54 End Class 55 56 Private Sub CreateDummyFiles() 57 Directory.CreateDirectory("test") 58 File.WriteAllText("test\Module1.vb", 59"Module Module1 60 Sub Hoge1() 61 Dim hoge1 As Integer 62 MsgBox(""Hoge1"") 63 End Sub 64 Sub Hoge2() 65 Dim hoge2 As Integer 66 MsgBox(""Hoge2"") 67 End Sub 68End Module 69") 70 71 File.WriteAllText("test\Class1.vb", 72"Class Class1 73 Function Hoge1() As Integer 74 MsgBox(""Hoge1"") 75 Return 0 76 End Function 77 Function Hoge2() As Integer 78 MsgBox(""Hoge2"") 79 Return 0 80 End Function 81End Class 82") 83 End Sub 84End Module
C#コードをそのままVBに移したつもりですが、あっているか自信がないのでC#コードも載せます^^;
cs
1using System.IO; 2using Microsoft.CodeAnalysis; 3using Microsoft.CodeAnalysis.VisualBasic; 4using Microsoft.CodeAnalysis.VisualBasic.Syntax; 5 6namespace Questions244513 7{ 8 internal class Program 9 { 10 private static void Main() 11 { 12 CreateDummyFiles(); 13 14 var rewriter = new MethodBlockRewriter(); 15 foreach(var filePath in Directory.GetFiles(@"test", "*.vb")) 16 { 17 var text = File.ReadAllText(filePath); 18 var tree = SyntaxFactory.ParseSyntaxTree(text); 19 text = rewriter.Visit(tree.GetRoot()).ToFullString(); 20 File.WriteAllText(filePath, text); 21 } 22 } 23 24 private class MethodBlockRewriter : VisualBasicSyntaxRewriter 25 { 26 public override SyntaxNode VisitMethodBlock(MethodBlockSyntax node) 27 { 28 var mss = node.BlockStatement as MethodStatementSyntax; 29 // メソッド名がHoge1でなければ何もしない 30 if(mss?.Identifier.ValueText != "Hoge1") return base.VisitMethodBlock(node); 31 32 // メソッドブロックを文字列に 33 var text = node.ToFullString(); 34 35 // クラス名orモジュール名取得 36 var name = (node.Parent as TypeBlockSyntax)?.BlockStatement.Identifier.ValueText; 37 // 置換 38 text = text.Replace("MsgBox(\"Hoge1\")", $"MsgBox(\"{name}.Hoge1\")"); 39 40 41 // 実際はそんな単純な置換ではないでしょうから 42 // 他と絶対被らない目印を入れて 43 // エディタ等の正規表現で一括置換したらいいんじゃないでしょうか 44 //text = text.Replace("MsgBox(", "'Replace Point!! MsgBox("); 45 46 47 // textからMethodBlockSyntaxを作り直して返す(もっといい書き方がありそう 48 return SyntaxFactory.ParseSyntaxTree(text).GetCompilationUnitRoot().Members[0]; 49 } 50 } 51 52 private static void CreateDummyFiles() 53 { 54 Directory.CreateDirectory("test"); 55 56 File.WriteAllText(@"test\Module1.vb", 57@"Module Module1 58 Sub Hoge1() 59 Dim hoge1 As Integer 60 MsgBox(""Hoge1"") 61 End Sub 62 Sub Hoge2() 63 Dim hoge2 As Integer 64 MsgBox(""Hoge2"") 65 End Sub 66End Module 67"); 68 69 File.WriteAllText(@"test\Class1.vb", 70@"Class Class1 71 Function Hoge1() As Integer 72 MsgBox(""Hoge1"") 73 Return 0 74 End Function 75 Function Hoge2() As Integer 76 MsgBox(""Hoge2"") 77 Return 0 78 End Function 79End Class 80"); 81 } 82 } 83}
注意 この単純な変換元コードでは想定通りに動きましたが、書き方によっては動かないかもしれません(VBもRoslynもよくわかっておりません)
投稿2020/03/03 09:13
編集2023/07/21 08:31総合スコア9862
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。