Pertanyaan Script untuk memasukkan login ke setiap fungsi dalam sebuah proyek?


Saya telah mewarisi basis kode yang cukup besar, 90% C ++, dan saya harus segera mempercepatnya. Ada ratusan file .cc dalam struktur pohon direktori lebar.

Ini cukup rumit, dan tidak ada penebangan. Untuk mencari tahu bagaimana beberapa subsistem utama berfungsi, saya ingin memasukkan pemanggilan fungsi ke setiap fungsi.

Misalnya, diberi file .cc penuh dengan hal-hal seperti ini:

void A::foo(int a, int b) {
    // ...
}

void A::bar() {
    // ...
}

void B::bleh(const string& in) {
    // ...
}

Saya ingin mendapatkan ini:

void A::foo(int a, int b) {
    LOG(debug) << "A::foo() called.";
    // ...
}

void A::bar() {
    LOG(debug) << "A::bar() called.";
    // ...
}

void B::bleh(const string& in) {
    LOG(debug) << "B::bleh() called.";
    // ...
}

Ini dapat dilakukan melalui skrip python, skrip CMD, skrip daya, dll. Jika ada cara untuk membuat VS melakukannya, bagus. Apapun yang berhasil. Tidak harus cantik, aku tidak memeriksa semua ini.

Juga, tidak perlu mendapatkan semuanya. Misalnya. kelas bertingkat, implementasi dalam file header, dll.


5
2017-09-18 03:18


asal


Jawaban:


Memiliki sesuatu yang mirip untuk menambahkan kode pembuatan menggunakan Macro di VS, inilah kodenya (ini juga mengelompokkan semua di bawah satu perintah "undo" dan mencantumkan semua perubahan di jendela outputnya sendiri)

Imports System
Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics

Public Module Module1

    Function GetOutputWindowPane(ByVal Name As String, Optional ByVal show As Boolean = True) As OutputWindowPane
        Dim window As Window
        Dim outputWindow As OutputWindow
        Dim outputWindowPane As OutputWindowPane

        window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput)
        If show Then window.Visible = True
        outputWindow = window.Object
        Try
            outputWindowPane = outputWindow.OutputWindowPanes.Item(Name)
        Catch e As System.Exception
            outputWindowPane = outputWindow.OutputWindowPanes.Add(Name)
        End Try
        outputWindowPane.Activate()
        Return outputWindowPane
    End Function

    Const ToInsert As String = "/* Inserted text :D */"

    Sub AddProfilingToFunction(ByVal func As CodeFunction2)
        Dim editPoint As EditPoint2 = func.StartPoint.CreateEditPoint()
        While editPoint.GetText(1) <> "{"
            editPoint.CharRight()
        End While

        editPoint.CharRight()
        editPoint.InsertNewLine(1)

        Dim insertStartLine As Integer = editPoint.Line
        Dim insertStartChar As Integer = editPoint.LineCharOffset
        editPoint.Insert(ToInsert)

        GetOutputWindowPane("Macro Inserted Code").OutputString( _
            editPoint.Parent.Parent.FullName & _
            "(" & insertStartLine & "," & insertStartChar & _
            ") : Inserted Code """ & ToInsert & """" & vbCrLf)
    End Sub

    Sub AddProfilingToProject(ByVal proj As Project)
        If Not proj.CodeModel() Is Nothing Then
            Dim EventTitle As String = "Add Profiling to project '" & proj.Name & "'"
            GetOutputWindowPane("Macro Inserted Code").OutputString("Add Profiling to project '" & proj.Name & "'" & vbCrLf)
            DTE.UndoContext.Open(EventTitle)
            Try
                Dim allNames As String = ""
                For i As Integer = 1 To proj.CodeModel().CodeElements.Count()
                    If proj.CodeModel().CodeElements.Item(i).Kind = vsCMElement.vsCMElementFunction Then
                        AddProfilingToFunction(proj.CodeModel().CodeElements.Item(i))
                    End If
                Next
            Finally
                DTE.UndoContext.Close()
            End Try
            GetOutputWindowPane("Macro Inserted Code").OutputString(vbCrLf)
        End If
    End Sub

    Sub AddProfilingToSolution()
        GetOutputWindowPane("Macro Inserted Code").Clear()
        If Not DTE.Solution Is Nothing And DTE.Solution.IsOpen() Then
            For i As Integer = 1 To DTE.Solution.Projects.Count()
                AddProfilingToProject(DTE.Solution.Projects.Item(i))
            Next
        End If
    End Sub

End Module

P.S Ingatlah untuk mengubah "Const ToInsert Sebagai String = ..." ke kode yang sebenarnya ingin Anda sisipkan


4
2017-09-18 05:41



Karena Anda menggunakan Visual C ++, dan tampaknya Anda hanya perlu nama fungsi yang disebut, mungkin untuk mengotomatisasi ini lebih lanjut menggunakan switch baris perintah berikut untuk cl.exe:

  • /Gh: Aktifkan _penter panggilan fungsi
  • /GH: Aktifkan _pexit panggilan fungsi

Pada dasarnya, menyediakan switch ini berarti kompiler akan secara otomatis menyuntikkan panggilan ke fungsi bernama _penter() dan _pexit() kapan pun fungsi apa pun dimulai atau berakhir. Anda kemudian dapat menyediakan modul yang dikompilasi secara terpisah yang mengimplementasikan dua fungsi ini, yang (a) memanggil beberapa perpustakaan pembantu seperti DbgHelp untuk menentukan nama fungsi yang dipanggil, atau (b) ambil saja alamat pengirim dari tumpukan dan cetak verbatim - setelah itu, tulis skrip untuk mengubah alamat ini menjadi nama fungsi dengan melihat misalnya file peta tautan dihasilkan jika Anda lulus /link /MAP:mymapfile.txt untuk cl.exe.

Tentu saja, Anda harus meletakkannya _penter() dan _pexit() dalam modul terpisah dengan /Gh dan /GH dimatikan untuk menghindari rekursi tak terbatas! :)


4
2017-09-18 04:22



Saya melakukannya beberapa tahun yang lalu di VS.
Regex akan membantu Anda.
BTW, tidak nesasary untuk memasukkan string yang berbeda. Anda dapat menambahkan string yang sama seperti:


LOG(debug) << __FUNCTION__ << " called.";

EDIT

sesuatu seperti regexp ini (berlaku untuk VS saja):


(void|char|int):b+:i\:\::i\([^(]*\):b*\{

Anda harus memperpanjang regexp tergantung kebutuhan Anda.


2
2017-09-18 03:38



Seorang profiler run-time akan memberikan Anda informasi itu: ia akan memberi tahu apa yang disebut subrutin dari setiap rutinitas, dan berapa kali (tetapi tidak, dalam urutan apa).


1
2017-09-18 03:23



Sudahkah Anda mempertimbangkan untuk menjalankan kode dalam debugger, dan cukup melangkah melalui seluruh aplikasi (atau jika tidak mengatur breakpoint pada kode yang Anda minati dan hanya melangkah melalui itu)? Saya menemukan bahwa kadang-kadang menjadi teknik yang berguna ketika berhadapan dengan basis kode warisan besar yang tidak saya tulis.

Atau, jika Anda menyusun di dunia VS, pertimbangkan untuk melihat pada /Ghdan   /GH beralih ke cl.exe. Mereka tampaknya memungkinkan Anda untuk menghubungkan fungsi masuk / keluar dan memanggil beberapa rutin lainnya. Saya belum pernah menggunakan ini sebelumnya, tetapi tampaknya langsung menjawab kebutuhan Anda.


1
2017-09-18 03:40