266
private void FillFileInformation (FileInformation fileInfo)
271
string confdir = PropertyService.ConfigPath;
272
string tagFileName = Path.GetFileName (fileInfo.FileName) + ".tag";
273
string tagdir = Path.Combine (confdir, "system-tags");
274
string tagFullFileName = Path.Combine (tagdir, tagFileName);
275
string ctags_kinds = "--C++-kinds=+px";
277
if (PropertyService.Get<bool> ("CBinding.ParseLocalVariables", true))
280
string ctags_options = ctags_kinds + " --fields=+aStisk-fz --language-force=C++ --excmd=number --line-directives=yes -f '" + tagFullFileName + "' '" + fileInfo.FileName + "'";
282
if (!Directory.Exists (tagdir))
283
Directory.CreateDirectory (tagdir);
285
if (!File.Exists (tagFullFileName) || File.GetLastWriteTimeUtc (tagFullFileName) < File.GetLastWriteTimeUtc (fileInfo.FileName)) {
286
ProcessWrapper p = null;
287
System.IO.StringWriter output = null;
289
output = new System.IO.StringWriter ();
291
p = Runtime.ProcessService.StartProcess ("ctags", ctags_options, null, null, output, null);
292
p.WaitForOutput (10000);
293
if (p.ExitCode != 0 || !File.Exists (tagFullFileName)) {
294
LoggingService.LogError ("Ctags did not successfully populate the tags database '{0}' within ten seconds.\nOutput: {1}", tagFullFileName, output.ToString ());
297
} catch (Exception ex) {
298
throw new IOException ("Could not create tags database (You must have exuberant ctags installed).", ex);
310
using (StreamReader reader = new StreamReader (tagFullFileName)) {
311
ctags_output = reader.ReadToEnd ();
314
using (StringReader reader = new StringReader (ctags_output)) {
315
while ((tagEntry = reader.ReadLine ()) != null) {
316
if (tagEntry.StartsWith ("!_")) continue;
318
Tag tag = ParseTag (tagEntry);
321
AddInfo (fileInfo, tag, ctags_output);
325
fileInfo.IsFilled = true;
328
275
private void ParsingThread ()
372
private void DoUpdateFileTags (Project project, string filename)
377
string[] headers = Headers (project, filename, false);
378
string[] system_headers = diff (Headers (project, filename, true), headers);
379
StringBuilder ctags_kinds = new StringBuilder ("--C++-kinds=+px");
381
if (PropertyService.Get<bool> ("CBinding.ParseLocalVariables", true))
382
ctags_kinds.Append ("+l");
384
// Maybe we should only ask for locals for 'local' files? (not external #includes?)
385
ctags_kinds.AppendFormat (" --fields=+aStisk-fz --language-force=C++ --excmd=number --line-directives=yes -f - '{0}'", filename);
386
foreach (string header in headers) {
387
ctags_kinds.AppendFormat (" '{0}'", header);
390
string ctags_output = string.Empty;
392
ProcessWrapper p = null;
393
System.IO.StringWriter output = null, error = null;
395
output = new System.IO.StringWriter ();
396
error = new System.IO.StringWriter ();
398
p = Runtime.ProcessService.StartProcess ("ctags", ctags_kinds.ToString (), project.BaseDirectory, output, error, null);
399
p.WaitForOutput (10000);
400
if (p.ExitCode != 0) {
401
LoggingService.LogError ("Ctags did not successfully populate the tags database from '{0}' within ten seconds.\nError output: {1}", filename, error.ToString ());
404
ctags_output = output.ToString ();
405
} catch (Exception ex) {
406
throw new IOException ("Could not create tags database (You must have exuberant ctags installed).", ex);
416
ProjectInformation info = ProjectInformationManager.Instance.Get (project);
419
info.RemoveFileInfo (filename);
422
using (StringReader reader = new StringReader (ctags_output)) {
423
while ((tagEntry = reader.ReadLine ()) != null) {
424
if (tagEntry.StartsWith ("!_")) continue;
426
Tag tag = ParseTag (tagEntry);
429
AddInfo (info, tag, ctags_output);
434
OnFileUpdated (new ClassPadEventArgs (project));
436
if (PropertyService.Get<bool> ("CBinding.ParseSystemTags", true))
437
UpdateSystemTags (project, filename, system_headers);
439
if (cache.Count > cache_size)
443
private void AddInfo (FileInformation info, Tag tag, string ctags_output)
448
Class c = new Class (tag, info.Project, ctags_output);
449
if (!info.Classes.Contains (c))
450
info.Classes.Add (c);
452
case TagKind.Enumeration:
453
Enumeration e = new Enumeration (tag, info.Project, ctags_output);
454
if (!info.Enumerations.Contains (e))
455
info.Enumerations.Add (e);
457
case TagKind.Enumerator:
458
Enumerator en= new Enumerator (tag, info.Project, ctags_output);
459
if (!info.Enumerators.Contains (en))
460
info.Enumerators.Add (en);
462
case TagKind.ExternalVariable:
464
case TagKind.Function:
465
Function f = new Function (tag, info.Project, ctags_output);
466
if (!info.Functions.Contains (f))
467
info.Functions.Add (f);
470
Local lo = new Local (tag, info.Project, ctags_output);
471
if(!info.Locals.Contains (lo))
472
info.Locals.Add (lo);
475
Macro m = new Macro (tag, info.Project);
476
if (!info.Macros.Contains (m))
480
Member me = new Member (tag, info.Project, ctags_output);
481
if (!info.Members.Contains (me))
482
info.Members.Add (me);
484
case TagKind.Namespace:
485
Namespace n = new Namespace (tag, info.Project, ctags_output);
486
if (!info.Namespaces.Contains (n))
487
info.Namespaces.Add (n);
489
case TagKind.Prototype:
490
Function fu = new Function (tag, info.Project, ctags_output);
491
if (!info.Functions.Contains (fu))
492
info.Functions.Add (fu);
494
case TagKind.Structure:
495
Structure s = new Structure (tag, info.Project, ctags_output);
496
if (!info.Structures.Contains (s))
497
info.Structures.Add (s);
499
case TagKind.Typedef:
500
Typedef t = new Typedef (tag, info.Project, ctags_output);
501
if (!info.Typedefs.Contains (t))
502
info.Typedefs.Add (t);
505
Union u = new Union (tag, info.Project, ctags_output);
506
if (!info.Unions.Contains (u))
509
case TagKind.Variable:
510
Variable v = new Variable (tag, info.Project);
511
if (!info.Variables.Contains (v))
512
info.Variables.Add (v);
519
private Tag ParseTag (string tagEntry)
526
AccessModifier access = AccessModifier.Public;
527
string _class = null;
528
string _namespace = null;
529
string _struct = null;
530
string _union = null;
532
string signature = null;
534
int i1 = tagEntry.IndexOf ('\t');
535
name = tagEntry.Substring (0, tagEntry.IndexOf ('\t'));
538
int i2 = tagEntry.IndexOf ('\t', i1);
539
file = tagEntry.Substring (i1, i2 - i1);
542
i2 = tagEntry.IndexOf (";\"", i1);
543
line = UInt64.Parse(tagEntry.Substring (i1, i2 - i1));
546
kind = (TagKind)tagEntry[i1];
549
tagField = (tagEntry.Length > i1? tagField = tagEntry.Substring(i1) : String.Empty);
551
string[] fields = tagField.Split ('\t');
554
foreach (string field in fields) {
555
index = field.IndexOf (':');
557
// TODO: Support friend modifier
559
string key = field.Substring (0, index);
560
string val = field.Substring (index + 1);
565
access = (AccessModifier)System.Enum.Parse (typeof(AccessModifier), val, true);
566
} catch (ArgumentException) {
591
return new Tag (name, file, line, kind, access, _class, _namespace, _struct, _union, _enum, signature);
594
323
Tag BinarySearch (string[] ctags_lines, TagKind kind, string name)