⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nativeparser.cpp

📁 非常好用的可移植的多平台C/C++源代码编辑器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*
* 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 + -