📄 nativeparser.cpp
字号:
/*
* This file is part of Code::Blocks Studio, an open-source cross-platform IDE
* Copyright (C) 2003 Yiannis An. Mandravellos
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact e-mail: Yiannis An. Mandravellos <mandrav@codeblocks.org>
* Program URL : http://www.codeblocks.org
*
* $Id: nativeparser.cpp,v 1.30.2.1 2005/10/25 07:59:01 mandrav Exp $
* $Date: 2005/10/25 07:59:01 $
*/
#include <sdk.h>
#include "nativeparser.h"
#include <manager.h>
#include <configmanager.h>
#include <projectmanager.h>
#include <pluginmanager.h>
#include <messagemanager.h>
#include <editormanager.h>
#include <macrosmanager.h>
#include <customvars.h>
#include <cbeditor.h>
#include <cbproject.h>
#include <cbexception.h>
#include "classbrowser.h"
#include "parser/parser.h"
#include <compilerfactory.h>
#include <cctype>
BEGIN_EVENT_TABLE(NativeParser, wxEvtHandler)
// EVT_MENU(THREAD_START, NativeParser::OnThreadStart)
// EVT_MENU(THREAD_END, NativeParser::OnThreadEnd)
EVT_MENU(PARSER_END, NativeParser::OnParserEnd)
END_EVENT_TABLE()
NativeParser::NativeParser()
: m_Parsers(1)
{
//ctor
m_pClassBrowser = 0L;
}
NativeParser::~NativeParser()
{
RemoveClassBrowser();
ClearParsers();
}
void NativeParser::CreateClassBrowser()
{
if (!m_pClassBrowser)
m_pClassBrowser = new ClassBrowser(Manager::Get()->GetNotebook(), this);
}
void NativeParser::RemoveClassBrowser(bool appShutDown)
{
if (!appShutDown && m_pClassBrowser)
{
delete m_pClassBrowser;
}
m_pClassBrowser = 0L;
}
void NativeParser::RereadParserOptions()
{
bool needsReparsing = false;
for (ParsersMap::iterator it = m_Parsers.begin(); it != m_Parsers.end(); ++it)
{
Parser* parser = it->second;
if (parser)
{
ParserOptions opts = parser->Options();
parser->ReadOptions();
if (opts.followLocalIncludes != parser->Options().followLocalIncludes ||
opts.followGlobalIncludes != parser->Options().followGlobalIncludes ||
opts.wantPreprocessor != parser->Options().wantPreprocessor)
{
// important options changed... flag for reparsing
needsReparsing = true;
}
}
}
if (needsReparsing)
{
if (wxMessageBox(_("You changed some class parser options. Do you want to "
"reparse your projects now, using the new options?"),
_("Reparse?"),
wxYES | wxNO | wxICON_QUESTION) == wxYES)
{
cbProject* proj = Manager::Get()->GetProjectManager()->GetActiveProject();
ClearParsers();
ProjectsArray* projects = Manager::Get()->GetProjectManager()->GetProjects();
for (unsigned int i = 0; i < projects->GetCount(); ++i)
{
AddParser(projects->Item(i));
}
if (m_pClassBrowser)
m_pClassBrowser->SetParser(m_Parsers[proj]);
}
}
if (m_pClassBrowser)
m_pClassBrowser->Update();
}
void NativeParser::SetClassBrowserProject(cbProject* project)
{
if (m_pClassBrowser)
m_pClassBrowser->SetParser(m_Parsers[project]);
}
void NativeParser::SetCBViewMode(const BrowserViewMode& mode)
{
for (ParsersMap::iterator it = m_Parsers.begin(); it != m_Parsers.end(); ++it)
{
Parser* parser = it->second;
if (parser)
{
parser->ClassBrowserOptions().showInheritance = mode == bvmInheritance;
}
}
if (m_pClassBrowser)
m_pClassBrowser->Update();
}
void NativeParser::ClearParsers()
{
if (m_pClassBrowser)
m_pClassBrowser->SetParser(0L);
for (ParsersMap::iterator it = m_Parsers.begin(); it != m_Parsers.end(); ++it)
{
Parser* parser = it->second;
if (parser)
{
delete parser;
}
}
m_Parsers.clear();
}
void NativeParser::AddCompilerDirs(Parser* parser, cbProject* project)
{
if (!parser)
return;
parser->IncludeDirs().Clear();
wxString base = project->GetBasePath();
parser->IncludeDirs().Add(base); // add project's base path
Compiler* compiler = 0;
// apply compiler global vars
if (CompilerFactory::Compilers.GetCount() > 0 && CompilerFactory::CompilerIndexOK(project->GetCompilerIndex()))
{
compiler = CompilerFactory::Compilers[project->GetCompilerIndex()];
compiler->GetCustomVars().ApplyVarsToEnvironment();
}
// apply project vars
project->GetCustomVars().ApplyVarsToEnvironment();
// get project include dirs
for (unsigned int i = 0; i < project->GetIncludeDirs().GetCount(); ++i)
{
wxString out = project->GetIncludeDirs()[i];
Manager::Get()->GetMacrosManager()->ReplaceEnvVars(out);
wxFileName dir(out);
wxLogNull ln; // hide the error log about "too many ..", if the relative path is invalid
if (!dir.IsAbsolute())
dir.Normalize(wxPATH_NORM_ALL & ~wxPATH_NORM_CASE, base);
if (dir.IsOk() && parser->IncludeDirs().Index(dir.GetFullPath()) == wxNOT_FOUND)
{
parser->IncludeDirs().Add(dir.GetFullPath());
// Manager::Get()->GetMessageManager()->DebugLog("Parser prj dir: " + dir.GetFullPath());
}
}
// get targets include dirs
for (int i = 0; i < project->GetBuildTargetsCount(); ++i)
{
ProjectBuildTarget* target = project->GetBuildTarget(i);
if (target)
{
// apply target vars
target->GetCustomVars().ApplyVarsToEnvironment();
for (unsigned int ti = 0; ti < target->GetIncludeDirs().GetCount(); ++ti)
{
wxString out = target->GetIncludeDirs()[ti];
Manager::Get()->GetMacrosManager()->ReplaceEnvVars(out);
wxFileName dir(out);
wxLogNull ln; // hide the error log about "too many ..", if the relative path is invalid
if (!dir.IsAbsolute())
dir.Normalize(wxPATH_NORM_ALL & ~wxPATH_NORM_CASE, base);
if (dir.IsOk() && parser->IncludeDirs().Index(dir.GetFullPath()) == wxNOT_FOUND)
{
parser->IncludeDirs().Add(dir.GetFullPath());
// Manager::Get()->GetMessageManager()->DebugLog("Parser tgt dir: " + dir.GetFullPath());
}
}
}
}
// add compiler include dirs
if (compiler)
{
const wxArrayString& dirs = compiler->GetIncludeDirs();
for (unsigned int i = 0; i < dirs.GetCount(); ++i)
{
//Manager::Get()->GetMessageManager()->Log(mltDevDebug, "Adding %s", dirs[i].c_str());
wxString out = dirs[i];
Manager::Get()->GetMacrosManager()->ReplaceEnvVars(out);
wxFileName dir(out);
wxLogNull ln; // hide the error log about "too many ..", if the relative path is invalid
if (!dir.IsAbsolute())
dir.Normalize(wxPATH_NORM_ALL & ~wxPATH_NORM_CASE, base);
if (dir.IsOk() && parser->IncludeDirs().Index(dir.GetFullPath()) == wxNOT_FOUND)
{
parser->IncludeDirs().Add(dir.GetFullPath());
// Manager::Get()->GetMessageManager()->DebugLog("Parser cmp dir: " + dir.GetFullPath());
}
}
}
else
Manager::Get()->GetMessageManager()->DebugLog(_("No compilers found!"));
}
void NativeParser::AddParser(cbProject* project, bool useCache)
{
if (!project)
return;
// check if we already have a parser for this project
if (m_Parsers[project])
return;
Manager::Get()->GetMessageManager()->DebugLog(_("Start parsing project %s"), project->GetTitle().c_str());
Parser* parser = new Parser(this);
m_Parsers[project] = parser;
m_ParsersFilenames[project] = project->GetFilename();
AddCompilerDirs(parser, project);
parser->StartTimer();
if (useCache && ConfigManager::Get()->Read(_T("/code_completion/use_cache"), 0L) != 0)
{
if (LoadCachedData(parser, project))
return;
}
wxArrayString files;
// parse header files first
for (int i = 0; i < project->GetFilesCount(); ++i)
{
ProjectFile* pf = project->GetFile(i);
FileType ft = FileTypeOf(pf->relativeFilename);
if (ft == ftHeader) // only parse header files
{
files.Add(pf->file.GetFullPath());
}
}
// next, parse source files
for (int i = 0; i < project->GetFilesCount(); ++i)
{
ProjectFile* pf = project->GetFile(i);
FileType ft = FileTypeOf(pf->relativeFilename);
if (ft == ftSource) // only parse source files
{
files.Add(pf->file.GetFullPath());
}
}
if (files.IsEmpty())
Manager::Get()->GetMessageManager()->DebugLog(_("End parsing project %s (no files found?)"), project->GetTitle().c_str());
else
{
parser->BatchParse(files);
}
}
void NativeParser::RemoveParser(cbProject* project, bool useCache)
{
// check if we already have a parser for this project
Parser* parser = m_Parsers[project];
if (!parser)
return;
if (useCache && ConfigManager::Get()->Read(_T("/code_completion/use_cache"), 0L) != 0)
{
if (ConfigManager::Get()->Read(_T("/code_completion/update_cache_always"), 0L) != 0 ||
parser->CacheNeedsUpdate())
{
SaveCachedData(parser, m_ParsersFilenames[project]);
}
}
m_Parsers.erase(project);
m_ParsersFilenames.erase(project);
if (parser)
delete parser;
if (m_pClassBrowser)
m_pClassBrowser->SetParser(0L);
Manager::Get()->GetMessageManager()->DebugLog(_("C++ Parser freed"));
}
void NativeParser::AddFileToParser(cbProject* project, const wxString& filename)
{
Parser* parser = m_Parsers[project];
if (!parser)
return;
parser->Parse(filename, true);
}
void NativeParser::RemoveFileFromParser(cbProject* project, const wxString& filename)
{
Parser* parser = m_Parsers[project];
if (!parser)
return;
parser->RemoveFile(filename);
}
void NativeParser::ForceReparseActiveProject()
{
cbProject* prj = Manager::Get()->GetProjectManager()->GetActiveProject();
if (prj)
{
RemoveParser(prj, false);
AddParser(prj, false);
}
}
cbProject* NativeParser::FindProjectFromParser(Parser* parser)
{
for (ParsersMap::iterator it = m_Parsers.begin(); it != m_Parsers.end(); ++it)
{
if (parser == it->second)
return it->first;
}
return 0L;
}
cbProject* NativeParser::FindProjectFromEditor(cbEditor* editor)
{
Parser* parser = FindParserFromEditor(editor);
return FindProjectFromParser(parser);
}
cbProject* NativeParser::FindProjectFromActiveEditor()
{
EditorManager* edMan = Manager::Get()->GetEditorManager();
if (!edMan)
return 0L;
cbEditor* ed = edMan->GetBuiltinActiveEditor();
return FindProjectFromEditor(ed);
}
Parser* NativeParser::FindParserFromEditor(cbEditor* editor)
{
if (!editor)
return 0L;
ProjectFile* pf = editor->GetProjectFile();
if (!pf)
return 0L;
cbProject* project = pf->project;
return m_Parsers[project];
}
Parser* NativeParser::FindParserFromActiveEditor()
{
EditorManager* edMan = Manager::Get()->GetEditorManager();
if (!edMan)
return 0L;
cbEditor* ed = edMan->GetBuiltinActiveEditor();
return FindParserFromEditor(ed);
}
Parser* NativeParser::FindParserFromActiveProject()
{
return FindParserFromProject(Manager::Get()->GetProjectManager()->GetActiveProject());
}
Parser* NativeParser::FindParserFromProject(cbProject* project)
{
if (!project)
return 0L;
return m_Parsers[project];
}
bool NativeParser::LoadCachedData(Parser* parser, cbProject* project)
{
if (!parser || !project)
return false;
wxFileName projectCache = project->GetFilename();
projectCache.SetExt(_T("cbCache"));
wxLogNull ln;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -