ultimatepp/uppsrc/ide/Errors.cpp
cxl e1bbcb4ece ide: error handling improvements...
git-svn-id: svn://ultimatepp.org/upp/trunk@7453 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2014-06-17 10:41:00 +00:00

297 lines
7 KiB
C++

#include "ide.h"
bool Ide::FindLineError(const String& ln, FindLineErrorCache& cache, ErrorInfo& f)
{
VectorMap<String, String> bm = GetMethodVars(method);
bool is_java = (bm.Get("BUILDER", Null) == "JDK");
const char *s = ln;
while(*s == ' ' || *s == '\t')
s++;
for(; s < ln.End(); s++) {
if(*s != '\"' && (byte)*s >= 32 && *s != '(' && (f.file.GetLength() < 3 || *s != ':'))
f.file.Cat(*s);
else {
if(*s == '\"') {
f.file = Null;
s++;
while(*s && *s != '\"')
f.file.Cat(*s++);
if(*s)
s++;
}
int e = f.file.GetLength();
while(e > 0 && f.file[e - 1] == ' ')
e--;
f.file.Trim(e);
f.file = TrimLeft(f.file);
String upp = GetUppDir();
#ifdef PLATFORM_WIN32
if(f.file[0] == '\\' || f.file[0] == '/')
f.file = String(upp[0], 1) + ':' + f.file;
#endif
if(!IsFullPath(f.file) && *f.file != '\\' && *f.file != '/') {
if(cache.wspc_paths.IsEmpty()) {
::Workspace wspc;
wspc.Scan(main);
for(int i = 0; i < wspc.GetCount(); i++)
cache.wspc_paths.Add(GetFileDirectory(PackagePath(wspc[i])));
}
for(int i = 0; i < cache.wspc_paths.GetCount(); i++) {
String path = AppendFileName(cache.wspc_paths[i], f.file);
int q = cache.ff.Find(path);
if(q >= 0) {
if(cache.ff[q]) {
f.file = path;
break;
}
}
else {
bool b = false;
String ext = ToLower(GetFileExt(path));
if(findarg(ext, ".obj", ".lib", ".o", ".so", ".a", ".", "") < 0) {
FindFile ff;
b = ff.Search(path) && ff.IsFile();
}
cache.ff.Add(path, b);
if(b) {
f.file = path;
break;
}
}
}
}
f.file = FollowCygwinSymlink(f.file);
if(IsFullPath(f.file) && FileExists(f.file) && IsTextFile(f.file)) {
while(*s && !IsDigit(*s))
s++;
f.lineno = f.linepos = 0;
CParser p(s);
if(p.IsInt())
f.lineno = p.ReadInt();
if(p.Char(':') && p.IsInt())
f.linepos = p.ReadInt();
const char *ms = p.GetPtr();
int pos = ms - ~ln;
f.kind = ln.Find("error", pos) > 0 ? 1 :
ln.Find("warning", pos) > 0 ? 2 :
ln.Find("note", pos) > 0 ? 3 : 4;
const char *hs = ms;
while(!IsLetter(*hs) && *hs)
hs++;
f.message = *hs ? hs : ms;
Vector<String> conf = SplitFlags(mainconfigparam, true);
String uppout = GetVar("OUTPUT");
int upplen = uppout.GetLength();
if(is_java && f.file.GetLength() > upplen
&& !MemICmp(f.file, uppout, upplen) && f.file[upplen] == DIR_SEP) { // check for preprocessed file
FileIn fi(f.file);
if(fi.IsOpen())
{
String fake_file = f.file;
int fake_line = 1;
int file_line = 1;
while(!fi.IsEof())
{
String line = fi.GetLine();
const char *p = line;
if(p[0] == '/' && p[1] == '/' && p[2] == '#')
{
p += 3;
if(p[0] == 'l' && p[1] == 'i' && p[2] == 'n' && p[3] == 'e')
p += 4;
while(*p == ' ' || *p == '\t')
p++;
if(IsDigit(*p))
{
fake_line = stou(p, &p);
while(*p == ' ' || *p == '\t')
p++;
if(*p == '\"')
p++;
fake_file.Clear();
while(*p && *p != '\"')
if(*p == '/')
{
fake_file.Cat('/');
if(p[1] == '/')
p++;
p++;
}
else
fake_file.Cat(*p++);
}
file_line++;
continue;
}
if(f.lineno <= file_line) {
f.file = fake_file;
f.lineno = fake_line;
f.linepos = 0;
break;
}
file_line++;
fake_line++;
}
}
}
if(f.lineno > 0)
return true;
}
f.file.Clear();
}
}
return false;
}
void Ide::FindError()
{
FindLineError(GetConsole().GetLine(GetConsole().GetCursor()));
}
void Ide::FindNextError()
{
if(findarg(btabs.GetCursor(), BCONSOLE, BFINDINFILES) < 0) {
int c = error.GetCursor();
if(c >= 0 && c < error.GetCount() - 1)
error.SetCursor(c + 1);
else
error.GoBegin();
}
else {
int ln = GetConsole().GetLine(GetConsole().GetCursor());
int l = ln;
for(l = ln; l < GetConsole().GetLineCount(); l++)
if(FindLineError(l)) return;
for(l = 0; l < ln; l++)
if(FindLineError(l)) return;
}
}
void Ide::FindPrevError() {
if(findarg(btabs.GetCursor(), BCONSOLE, BFINDINFILES) < 0) {
int c = error.GetCursor();
if(c > 0)
error.SetCursor(c - 1);
else
error.GoEnd();
}
else {
int ln = GetConsole().GetLine(GetConsole().GetCursor());
int l = ln;
One<Host> host = CreateHost(false);
for(l = ln - 2; l >= 0; l--)
if(FindLineError(l)) return;
for(l = GetConsole().GetLineCount() - 1; l > ln; l--)
if(FindLineError(l)) return;
}
}
void Ide::ClearErrorEditor()
{
if(!mark_lines)
return;
for(int i = 0; i < filedata.GetCount(); i++) {
ClearErrorEditor(filedata.GetKey(i));
}
SetErrorFiles(Vector<String>());
}
void Ide::ClearErrorEditor(String file)
{
if(!mark_lines)
return;
if(file == editfile)
editor.ClearErrors();
else {
FileData& fd = Filedata(file);
ClearErrors(fd.lineinfo);
}
}
void Ide::SetErrorEditor()
{
if(error.GetCount()) {
SetBottom(BERRORS);
if(!error.IsCursor())
error.GoBegin();
}
if(!mark_lines)
return;
bool refresh = false;
String hfile;
EditorBar hbar;
Vector<String> errorfiles;
FindLineErrorCache cache;
for(int i = 0; i < console.GetLineCount(); i++) {
ErrorInfo f;
if(FindLineError(console.GetUtf8Line(i), cache, f)) {
String file = NormalizePath(f.file);
#ifdef PLATFORM_WIN32
errorfiles.Add(ToLower(file));
#else
errorfiles.Add(file);
#endif
if(editfile == file) {
editor.SetError(f.lineno - 1, f.kind);
refresh = true;
}
else {
if(hfile != file) {
if(hfile.GetCount())
Filedata(hfile).lineinfo = hbar.GetLineInfo();
hbar.SetLineInfo(Filedata(file).lineinfo, -1);
hfile = file;
}
hbar.SetError(f.lineno - 1, f.kind);
}
}
}
if(hfile.GetCount())
Filedata(hfile).lineinfo = hbar.GetLineInfo();
if(refresh)
editor.RefreshFrame();
SetErrorFiles(errorfiles);
}
void Ide::ConsoleLine(const String& line)
{
ErrorInfo f;
if(FindLineError(line, error_cache, f)) {
int cnt = error.GetCount();
Value rf = RawToValue(f);
if(findarg(f.kind, 1, 2) >= 0 || cnt == 0)
error.Add(GetFileName(f.file), f.lineno,
AttrText(f.message)
.NormalPaper(HighlightSetup::GetHlStyle(f.kind == 1 ? HighlightSetup::PAPER_ERROR
: HighlightSetup::PAPER_WARNING).color),
rf);
else {
ValueArray n = error.Get(cnt - 1, "NOTES");
n.Add(rf);
error.Set(cnt - 1, "NOTES", n);
}
}
}
void Ide::ShowNote()
{
if(notes.IsCursor())
GoToError(ValueTo<ErrorInfo>(notes.Get("INFO")));
}
void Ide::ShowError()
{
notes.Clear();
if(error.IsCursor()) {
ValueArray n = error.Get("NOTES");
for(int i = 0; i < n.GetCount(); i++) {
const ErrorInfo& f = ValueTo<ErrorInfo>(n[i]);
notes.Add(GetFileName(f.file), f.lineno, f.message, n[i]);
}
GoToError(ValueTo<ErrorInfo>(error.Get("INFO")));
}
}