~ubuntu-branches/ubuntu/hardy/codeblocks/hardy-backports

« back to all changes in this revision

Viewing changes to src/plugins/contrib/codestat/codestatexec.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Casadevall
  • Date: 2008-07-17 04:39:23 UTC
  • Revision ID: james.westby@ubuntu.com-20080717043923-gmsy5cwkdjswghkm
Tags: upstream-8.02
ImportĀ upstreamĀ versionĀ 8.02

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************
 
2
 * Name:      codestatexec.cpp
 
3
 * Purpose:   Code::Blocks CodeStat plugin: main window
 
4
 * Author:    Zlika
 
5
 * Created:   11/09/2005
 
6
 * Copyright: (c) Zlika
 
7
 * License:   GPL
 
8
 **************************************************************/
 
9
#include "sdk.h"
 
10
#ifndef CB_PRECOMP
 
11
#include <wx/intl.h>
 
12
#include <wx/stattext.h>
 
13
#include <wx/string.h>
 
14
#include <wx/xrc/xmlres.h>
 
15
#include "cbproject.h"
 
16
#include "configmanager.h"
 
17
#include "editormanager.h"
 
18
#include "globals.h"
 
19
#include "manager.h"
 
20
#include "logmanager.h"
 
21
#include "projectfile.h"
 
22
#include "projectmanager.h"
 
23
#endif
 
24
#include <wx/gauge.h>
 
25
#include <wx/progdlg.h>
 
26
#include <wx/textfile.h>
 
27
#include "codestatexec.h"
 
28
 
 
29
/** Count the lines on all project's files and display the results.
 
30
 *  @param languages Languages definitions
 
31
 *  @param nb_languages Number of languages defined in the 'languages' array
 
32
 */
 
33
int CodeStatExecDlg::Execute(LanguageDef languages[NB_FILETYPES_MAX], int nb_languages)
 
34
{
 
35
   cbProject* project = Manager::Get()->GetProjectManager()->GetActiveProject();
 
36
   long nb_files = project->GetFilesCount();
 
37
   //wxMessageBox(wxString::Format(_T("Nb files: %ld"), nb_files), _("Error"), wxOK);
 
38
 
 
39
   // Check if all files have been saved
 
40
   bool all_files_saved = true;
 
41
   for (int i=0; i<nb_files; ++i)
 
42
      if (project->GetFile(i)->GetFileState() == fvsModified)
 
43
         all_files_saved = false;
 
44
   // If not, ask user if we can save them
 
45
   if (!all_files_saved)
 
46
   {
 
47
       if (cbMessageBox(_T("Some files are not saved.\nDo you want to save them before running the plugin?"), _("Warning"), wxICON_EXCLAMATION | wxYES_NO, Manager::Get()->GetAppWindow()) == wxID_YES)
 
48
       {
 
49
           for (int i=0; i<nb_files; ++i)
 
50
           {
 
51
              if (project->GetFile(i)->GetFileState() == fvsModified)
 
52
                 Manager::Get()->GetEditorManager()->Save(project->GetFile(i)->file.GetFullPath());
 
53
           }
 
54
       }
 
55
   }
 
56
 
 
57
        // Count code statistics on each file
 
58
        long nb_files_not_found = 0;
 
59
        long nb_skipped_files = 0;
 
60
        long total_lines = 0;
 
61
        long code_lines = 0;
 
62
        long empty_lines = 0;
 
63
        long comment_lines = 0;
 
64
        long codecomments_lines = 0;
 
65
 
 
66
        wxProgressDialog progress(_("Code Statistics plugin"),_("Parsing project files. Please wait..."));
 
67
        for (int i=0; i<nb_files; ++i)
 
68
        {
 
69
                ProjectFile* pf = project->GetFile(i);
 
70
                wxFileName filename(pf->file.GetFullPath(), wxPATH_DOS);
 
71
                if (!filename.FileExists())
 
72
                {
 
73
                        ++nb_files_not_found;
 
74
                        //Manager::Get()->GetLogManager()->DebugLog(_T("Code Statistics: Ignoring file '%s' (file not found)"), filename.GetName());
 
75
                }
 
76
                else
 
77
                {
 
78
                        // Find the language associated to the file extension
 
79
                        int num_language = -1;
 
80
                        for (int l = 0; l<nb_languages; ++l)
 
81
                        {
 
82
                                for (int j = 0; j<(int)languages[l].ext.Count(); ++j)
 
83
                                {
 
84
                                  if (filename.GetExt() == languages[l].ext[j])
 
85
                                         num_language = l;
 
86
                                }
 
87
                        }
 
88
 
 
89
                        // If the language is found, analyse the source file
 
90
                        if (num_language > -1)
 
91
                          CountLines(filename, languages[num_language], code_lines, codecomments_lines, comment_lines, empty_lines, total_lines);
 
92
                        else ++nb_skipped_files;
 
93
                }
 
94
                if (nb_files > 1)
 
95
                        progress.Update((100*i)/(nb_files-1));
 
96
   }
 
97
   progress.Update(100);
 
98
 
 
99
   // Setting-up the statistics dialog box
 
100
   wxXmlResource::Get()->LoadDialog(this, parent, _T("dlgCodeStatExec"));
 
101
 
 
102
   wxStaticText* txt_num_files = XRCCTRL(*this, "txt_num_files", wxStaticText);
 
103
   txt_num_files->SetLabel(wxString::Format(_("%ld"), nb_files));
 
104
   wxStaticText* txt_skipped_files = XRCCTRL(*this, "txt_skipped_files", wxStaticText);
 
105
   txt_skipped_files->SetLabel(wxString::Format(_("%ld"), nb_skipped_files));
 
106
   wxStaticText* txt_files_not_found = XRCCTRL(*this, "txt_files_not_found", wxStaticText);
 
107
   txt_files_not_found->SetLabel(wxString::Format(_("%ld"), nb_files_not_found));
 
108
 
 
109
   wxStaticText* txt_Code = XRCCTRL(*this, "txt_Code", wxStaticText);
 
110
   txt_Code->SetLabel(wxString::Format(_("%ld"), code_lines));
 
111
   wxStaticText* txt_Empty = XRCCTRL(*this, "txt_Empty", wxStaticText);
 
112
   txt_Empty->SetLabel(wxString::Format(_("%ld"), empty_lines));
 
113
   wxStaticText* txt_Comments = XRCCTRL(*this, "txt_Comments", wxStaticText);
 
114
   txt_Comments->SetLabel(wxString::Format(_("%ld"), comment_lines));
 
115
   wxStaticText* txt_Code_Comments = XRCCTRL(*this, "txt_Code_Comments", wxStaticText);
 
116
   txt_Code_Comments->SetLabel(wxString::Format(_("%ld"), codecomments_lines));
 
117
   wxStaticText* txt_Total = XRCCTRL(*this, "txt_Total", wxStaticText);
 
118
   txt_Total->SetLabel(wxString::Format(_("%ld"), total_lines));
 
119
 
 
120
   // If the project is not empty, display the main dialog box
 
121
   if(total_lines) // avoid division by zero on empty document
 
122
   {
 
123
                int icode = static_cast<int>(round(static_cast<double>(100 * code_lines) / static_cast<double>(total_lines)));
 
124
                wxGauge* Gauge_Code = XRCCTRL(*this, "Gauge_Code", wxGauge);
 
125
                Gauge_Code->SetValue(icode);
 
126
                wxStaticText* txt_Gauge_Code = XRCCTRL(*this, "txt_Gauge_Code", wxStaticText);
 
127
                txt_Gauge_Code->SetLabel(wxString::Format(_("%3d%% Code only"), icode));
 
128
 
 
129
                int icode_comments = static_cast<int>(round(static_cast<double>(100 * codecomments_lines) / static_cast<double>(total_lines)));
 
130
                wxGauge* Gauge_Code_Comments = XRCCTRL(*this, "Gauge_Code_Comments", wxGauge);
 
131
                Gauge_Code_Comments->SetValue(icode_comments);
 
132
                wxStaticText* txt_Gauge_Code_Comments = XRCCTRL(*this, "txt_Gauge_Code_Comments", wxStaticText);
 
133
                txt_Gauge_Code_Comments->SetLabel(wxString::Format(_("%3d%% Code + Comment"), icode_comments));
 
134
 
 
135
                int icomments = static_cast<int>(round(static_cast<double>(100 * comment_lines) / static_cast<double>(total_lines)));
 
136
                wxGauge* Gauge_Comments = XRCCTRL(*this, "Gauge_Comments", wxGauge);
 
137
                Gauge_Comments->SetValue(icomments);
 
138
                wxStaticText* txt_Gauge_Comments = XRCCTRL(*this, "txt_Gauge_Comments", wxStaticText);
 
139
                txt_Gauge_Comments->SetLabel(wxString::Format(_("%3d%% Comments"), icomments));
 
140
 
 
141
                int iempty = static_cast<int>(round(static_cast<double>(100 * empty_lines) / static_cast<double>(total_lines)));
 
142
                wxGauge* Gauge_Empty = XRCCTRL(*this, "Gauge_Empty", wxGauge);
 
143
                Gauge_Empty->SetValue(iempty);
 
144
                wxStaticText* txt_Gauge_Empty = XRCCTRL(*this, "txt_Gauge_Empty", wxStaticText);
 
145
                txt_Gauge_Empty->SetLabel(wxString::Format(_("%3d%% Empty"), iempty));
 
146
 
 
147
        ShowModal();
 
148
   }
 
149
   else cbMessageBox(_("The project is empty!"), _("Warning"), wxICON_EXCLAMATION | wxOK, Manager::Get()->GetAppWindow());
 
150
 
 
151
   return 0;
 
152
}
 
153
 
 
154
void CodeStatExecDlg::EndModal(int retCode)
 
155
{
 
156
    wxDialog::EndModal(retCode);
 
157
}
 
158
 
 
159
/** This function analyses a given source file and count the lines of code, comments etc...
 
160
 */
 
161
void CodeStatExecDlg::CountLines(wxFileName filename, LanguageDef &language,
 
162
                                 long int &code_lines, long int &codecomments_lines,
 
163
                                 long int &comment_lines, long int &empty_lines, long int &total_lines)
 
164
{
 
165
        wxTextFile file;
 
166
        if (file.Open(filename.GetFullPath(),wxConvFile))
 
167
        {
 
168
                bool multi_line_comment = false;
 
169
                total_lines += file.GetLineCount();
 
170
                for (unsigned int i=0; i<file.GetLineCount(); ++i)
 
171
                {
 
172
                   wxString line(file[i]);
 
173
                   line = line.Trim(true);
 
174
           line = line.Trim(false);
 
175
                   bool comment = false;
 
176
                   bool code = false;
 
177
                   if (line.IsEmpty())
 
178
                 ++empty_lines;
 
179
                   else
 
180
                   {
 
181
                          AnalyseLine(language, line, comment, code, multi_line_comment);
 
182
                      if (comment&&code) ++codecomments_lines;
 
183
                      else if (comment) ++comment_lines;
 
184
                      else if (code) ++code_lines;
 
185
                   }
 
186
                }
 
187
        }
 
188
}
 
189
 
 
190
/** This function determines the caracteristics of a given line (code line, comment line etc...).
 
191
 *  It is called by the "CountLines" function.
 
192
 *  @see CountLines
 
193
 */
 
194
void CodeStatExecDlg::AnalyseLine(LanguageDef &language, wxString line, bool &comment, bool &code, bool &multi_line_comment)
 
195
{
 
196
   int first_single_line_comment, first_multi_line_comment_begin, first_multi_line_comment_end;
 
197
 
 
198
   // Delete first and trailing spaces
 
199
   line = line.Trim(true);
 
200
   line = line.Trim(false);
 
201
 
 
202
        if (line.IsEmpty())
 
203
           return;
 
204
 
 
205
        // Searching for single and multi-lines comment signs
 
206
        if (language.single_line_comment.Length() > 0)
 
207
      first_single_line_comment = line.Find(language.single_line_comment);
 
208
   else first_single_line_comment = -1;
 
209
   if (language.multiple_line_comment[0].Length() > 0)
 
210
      first_multi_line_comment_begin = line.Find(language.multiple_line_comment[0]);
 
211
   else first_multi_line_comment_begin = -1;
 
212
   if (language.multiple_line_comment[1].Length() > 0)
 
213
      first_multi_line_comment_end = line.Find(language.multiple_line_comment[1]);
 
214
   else first_multi_line_comment_end = -1;
 
215
 
 
216
   // We are in a multiple line comment => finding the "end of multiple line comment" sign
 
217
   if (multi_line_comment)
 
218
   {
 
219
      comment = true;
 
220
        if (first_multi_line_comment_end > -1)
 
221
        {
 
222
                multi_line_comment = false;
 
223
                if (first_multi_line_comment_end+language.multiple_line_comment[1].Length() < line.Length())
 
224
                   AnalyseLine(language, line.Mid(first_multi_line_comment_end+language.multiple_line_comment[1].Length()), comment, code, multi_line_comment);
 
225
        }
 
226
   }
 
227
   // We are not in a multiple line comment
 
228
   else if (!multi_line_comment)
 
229
   {
 
230
        // First comment sign found is a single line comment sign
 
231
      if ( (first_single_line_comment>-1)
 
232
         &&((first_multi_line_comment_begin==-1)||((first_multi_line_comment_begin>-1)&&(first_single_line_comment<first_multi_line_comment_begin))) )
 
233
      {
 
234
        comment = true;
 
235
         if (first_single_line_comment > 0)
 
236
            code = true;
 
237
      }
 
238
      // First comment sign found is a multi-line comment begin sign
 
239
      else if (first_multi_line_comment_begin>-1)
 
240
      {
 
241
         multi_line_comment = true;
 
242
         comment = true;
 
243
         if (first_multi_line_comment_begin > 0)
 
244
            code = true;
 
245
         if (first_multi_line_comment_begin+language.multiple_line_comment[0].Length() < line.Length())
 
246
                   AnalyseLine(language, line.Mid(first_multi_line_comment_begin+language.multiple_line_comment[0].Length()), comment, code, multi_line_comment);
 
247
      }
 
248
      else
 
249
      {
 
250
        code = true;
 
251
      }
 
252
   }
 
253
}
 
254
 
 
255
CodeStatExecDlg::~CodeStatExecDlg()
 
256
{
 
257
}