ui/logic/data: show parse errors in CodeView
This change saves the errors while parsing in the Storage and displays them in the CodeView. The error messages can be read in the tooltip on hovering. The error count is visible in the status bar.
This commit is contained in:
@@ -9,6 +9,19 @@ ParseLocation::ParseLocation()
|
||||
{
|
||||
}
|
||||
|
||||
ParseLocation::ParseLocation(
|
||||
const std::string& filePath,
|
||||
uint lineNumber,
|
||||
uint columnNumber
|
||||
)
|
||||
: filePath(filePath)
|
||||
, startLineNumber(lineNumber)
|
||||
, startColumnNumber(columnNumber)
|
||||
, endLineNumber(lineNumber)
|
||||
, endColumnNumber(columnNumber)
|
||||
{
|
||||
}
|
||||
|
||||
ParseLocation::ParseLocation(
|
||||
const std::string& filePath,
|
||||
uint startLineNumber, uint startColumnNumber,
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
struct ParseLocation
|
||||
{
|
||||
ParseLocation();
|
||||
ParseLocation(
|
||||
const std::string& filePath,
|
||||
uint lineNumber,
|
||||
uint columnNumber
|
||||
);
|
||||
ParseLocation(
|
||||
const std::string& filePath,
|
||||
uint startLineNumber, uint startColumnNumber,
|
||||
|
||||
@@ -49,6 +49,8 @@ public:
|
||||
ParserClient();
|
||||
virtual ~ParserClient();
|
||||
|
||||
virtual void onError(const ParseLocation& location, const std::string& message) = 0;
|
||||
|
||||
virtual Id onTypedefParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& nameHierarchy,
|
||||
const ParseTypeUsage& underlyingType, AccessType access) = 0;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "data/parser/cxx/ASTConsumer.h"
|
||||
|
||||
#include "data/parser/ParserClient.h"
|
||||
|
||||
ASTConsumer::ASTConsumer(clang::ASTContext* context, ParserClient* client)
|
||||
: m_visitor(context, client)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
#include "data/parser/cxx/CxxDiagnosticConsumer.h"
|
||||
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
|
||||
#include "data/parser/ParseLocation.h"
|
||||
#include "data/parser/ParserClient.h"
|
||||
|
||||
CxxDiagnosticConsumer::CxxDiagnosticConsumer(
|
||||
clang::raw_ostream &os,
|
||||
clang::DiagnosticOptions *diags,
|
||||
ParserClient* client,
|
||||
bool useLogging
|
||||
)
|
||||
: clang::TextDiagnosticPrinter(os, diags)
|
||||
, m_client(client)
|
||||
, m_isParsingFile(false)
|
||||
, m_useLogging(useLogging)
|
||||
{
|
||||
}
|
||||
|
||||
void CxxDiagnosticConsumer::BeginSourceFile(const clang::LangOptions& langOptions, const clang::Preprocessor* preProcessor)
|
||||
{
|
||||
if (m_useLogging)
|
||||
{
|
||||
clang::TextDiagnosticPrinter::BeginSourceFile(langOptions, preProcessor);
|
||||
}
|
||||
|
||||
m_isParsingFile = true;
|
||||
}
|
||||
|
||||
void CxxDiagnosticConsumer::EndSourceFile()
|
||||
{
|
||||
if (m_useLogging)
|
||||
{
|
||||
clang::TextDiagnosticPrinter::EndSourceFile();
|
||||
}
|
||||
|
||||
m_isParsingFile = false;
|
||||
}
|
||||
|
||||
void CxxDiagnosticConsumer::HandleDiagnostic(clang::DiagnosticsEngine::Level level, const clang::Diagnostic& info)
|
||||
{
|
||||
if (m_useLogging)
|
||||
{
|
||||
clang::TextDiagnosticPrinter::HandleDiagnostic(level, info);
|
||||
}
|
||||
|
||||
if (!m_isParsingFile)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (level == clang::DiagnosticsEngine::Error || level == clang::DiagnosticsEngine::Fatal)
|
||||
{
|
||||
llvm::SmallString<100> messageStr;
|
||||
info.FormatDiagnostic(messageStr);
|
||||
std::string message = messageStr.str();
|
||||
|
||||
std::string filePath;
|
||||
uint line = 0;
|
||||
uint column = 0;
|
||||
|
||||
if (info.getLocation().isValid() && info.hasSourceManager())
|
||||
{
|
||||
const clang::SourceManager& sourceManager = info.getSourceManager();
|
||||
clang::PresumedLoc presumedLocation = sourceManager.getPresumedLoc(info.getLocation());
|
||||
|
||||
filePath = presumedLocation.getFilename();
|
||||
line = presumedLocation.getLine();
|
||||
column = presumedLocation.getColumn();
|
||||
}
|
||||
|
||||
m_client->onError(ParseLocation(filePath, line, column), message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef CXX_DIAGNOSTIC_CONSUMER
|
||||
#define CXX_DIAGNOSTIC_CONSUMER
|
||||
|
||||
#include "clang/Frontend/TextDiagnosticPrinter.h"
|
||||
|
||||
class ParserClient;
|
||||
|
||||
class CxxDiagnosticConsumer
|
||||
: public clang::TextDiagnosticPrinter
|
||||
{
|
||||
public:
|
||||
CxxDiagnosticConsumer(clang::raw_ostream &os, clang::DiagnosticOptions *diags, ParserClient* client, bool useLogging = true);
|
||||
|
||||
void BeginSourceFile(const clang::LangOptions& langOptions, const clang::Preprocessor* preProcessor);
|
||||
void EndSourceFile();
|
||||
|
||||
void HandleDiagnostic(clang::DiagnosticsEngine::Level level, const clang::Diagnostic& info);
|
||||
|
||||
private:
|
||||
ParserClient* m_client;
|
||||
bool m_isParsingFile;
|
||||
bool m_useLogging;
|
||||
};
|
||||
|
||||
#endif // CXX_DIAGNOSTIC_CONSUMER
|
||||
@@ -1,9 +1,54 @@
|
||||
#include "data/parser/cxx/CxxParser.h"
|
||||
|
||||
#include "data/parser/cxx/ASTActionFactory.h"
|
||||
#include "utility/logging/logging.h"
|
||||
#include "utility/text/TextAccess.h"
|
||||
|
||||
#include "data/parser/cxx/ASTActionFactory.h"
|
||||
#include "data/parser/cxx/CxxDiagnosticConsumer.h"
|
||||
|
||||
namespace {
|
||||
|
||||
static std::vector<std::string> getSyntaxOnlyToolArgs(const std::vector<std::string> &ExtraArgs, llvm::StringRef FileName)
|
||||
{
|
||||
std::vector<std::string> Args;
|
||||
Args.push_back("clang-tool");
|
||||
Args.push_back("-fsyntax-only");
|
||||
Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());
|
||||
Args.push_back(FileName.str());
|
||||
return Args;
|
||||
}
|
||||
|
||||
// custom implementation of clang::runToolOnCodeWithArgs which also sets our custon DiagnosticConsumer
|
||||
static bool runToolOnCodeWithArgs(
|
||||
clang::DiagnosticConsumer* DiagConsumer,
|
||||
clang::FrontendAction *ToolAction,
|
||||
const llvm::Twine &Code,
|
||||
const std::vector<std::string> &Args,
|
||||
const llvm::Twine &FileName = "input.cc",
|
||||
const clang::tooling::FileContentMappings &VirtualMappedFiles = clang::tooling::FileContentMappings()
|
||||
){
|
||||
llvm::SmallString<16> FileNameStorage;
|
||||
llvm::StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
|
||||
llvm::IntrusiveRefCntPtr<clang::FileManager> Files(new clang::FileManager(clang::FileSystemOptions()));
|
||||
clang::tooling::ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), ToolAction, Files.get());
|
||||
|
||||
llvm::SmallString<1024> CodeStorage;
|
||||
Invocation.mapVirtualFile(FileNameRef,
|
||||
Code.toNullTerminatedStringRef(CodeStorage));
|
||||
|
||||
for (auto &FilenameWithContent : VirtualMappedFiles)
|
||||
{
|
||||
Invocation.mapVirtualFile(FilenameWithContent.first,
|
||||
FilenameWithContent.second);
|
||||
}
|
||||
|
||||
Invocation.setDiagnosticConsumer(DiagConsumer);
|
||||
|
||||
return Invocation.run();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CxxParser::CxxParser(ParserClient* client)
|
||||
: Parser(client)
|
||||
{
|
||||
@@ -68,15 +113,22 @@ void CxxParser::parseFiles(
|
||||
|
||||
clang::tooling::ClangTool tool(*compilationDatabase, filePaths);
|
||||
|
||||
ASTActionFactory actionFactory(m_client);
|
||||
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> options = new clang::DiagnosticOptions();
|
||||
CxxDiagnosticConsumer reporter(llvm::errs(), &*options, m_client);
|
||||
tool.setDiagnosticConsumer(&reporter);
|
||||
|
||||
ASTActionFactory actionFactory(m_client);
|
||||
tool.run(&actionFactory);
|
||||
}
|
||||
|
||||
void CxxParser::parseFile(std::shared_ptr<TextAccess> textAccess)
|
||||
{
|
||||
ASTActionFactory actionFactory(m_client);
|
||||
std::vector<std::string> args;
|
||||
args.push_back("-fno-delayed-template-parsing");
|
||||
clang::tooling::runToolOnCodeWithArgs(actionFactory.create(), textAccess->getText(), args);
|
||||
|
||||
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> options = new clang::DiagnosticOptions();
|
||||
CxxDiagnosticConsumer reporter(llvm::errs(), &*options, m_client, false);
|
||||
|
||||
ASTActionFactory actionFactory(m_client);
|
||||
runToolOnCodeWithArgs(&reporter, actionFactory.create(), textAccess->getText(), args);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user