diff options
author | Karsten Heimrich <karsten.heimrich@qt.io> | 2017-01-06 16:34:06 +0100 |
---|---|---|
committer | Karsten Heimrich <karsten.heimrich@qt.io> | 2017-01-09 11:08:38 +0000 |
commit | dd04f89de803f10201c2f5870ffff95d8452ee1c (patch) | |
tree | afa752dfbf2f8c17cb2c3ac832f9ec8118c54f64 | |
parent | d2e1d457013845e10e818de75e2826ba69efa574 (diff) |
Some better performance while parsing C++ files
Load the file as a whole and perform an initial search on the file
before parsing line by line, e.g. to find Q_OBJECT, Q_GADGET macro.
Change-Id: Ied69749be6ce5c2e92a31da211df087f580db5d2
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
-rw-r--r-- | src/qtprojectlib/CxxStreamReader.cs | 30 | ||||
-rw-r--r-- | src/qtprojectlib/HelperFunctions.cs | 58 | ||||
-rw-r--r-- | src/qtvstools/DteEventsHandler.cs | 2 |
3 files changed, 63 insertions, 27 deletions
diff --git a/src/qtprojectlib/CxxStreamReader.cs b/src/qtprojectlib/CxxStreamReader.cs index 4689da21..224896bb 100644 --- a/src/qtprojectlib/CxxStreamReader.cs +++ b/src/qtprojectlib/CxxStreamReader.cs @@ -46,6 +46,14 @@ namespace QtProjectLib private string partialLine; bool disposed; + int _lineNum; + string[] _lines; + + public CxxStreamReader(string[] lines) + { + _lines = lines; + } + public CxxStreamReader(string fileName) { sr = new StreamReader(fileName); @@ -72,7 +80,7 @@ namespace QtProjectLib if (disposed) return; - if (disposing) + if (disposing && sr != null) sr.Dispose(); disposed = true; @@ -86,12 +94,20 @@ namespace QtProjectLib public string ReadLine(bool removeStrings) { var line = string.Empty; - do { - line = sr.ReadLine(); - if (line == null) - return null; - line = ProcessString(line, removeStrings); - } while (line.Length == 0); + if (sr != null) { + do { + line = sr.ReadLine(); + if (line == null) + return null; + line = ProcessString(line, removeStrings); + } while (line.Length == 0); + } else { + do { + if (_lineNum >= _lines.Length) + return null; + line = ProcessString(_lines[_lineNum++], removeStrings); + } while (line.Length == 0); + } return line; } diff --git a/src/qtprojectlib/HelperFunctions.cs b/src/qtprojectlib/HelperFunctions.cs index 092fc652..f8fb9a91 100644 --- a/src/qtprojectlib/HelperFunctions.cs +++ b/src/qtprojectlib/HelperFunctions.cs @@ -32,6 +32,7 @@ using System; using System.Collections.Generic; using System.Drawing; using System.IO; +using System.Linq; using System.Reflection; using System.Text.RegularExpressions; using System.Windows.Forms; @@ -837,40 +838,59 @@ namespace QtProjectLib public static bool HasQObjectDeclaration(VCFile file) { - return CxxFileContainsNotCommented(file, new[] { "Q_OBJECT", "Q_GADGET" }, true, true); + return CxxFileContainsNotCommented(file, new[] { "Q_OBJECT", "Q_GADGET" }, + StringComparison.Ordinal, true); } - public static bool CxxFileContainsNotCommented(VCFile file, string str, bool caseSensitive, bool suppressStrings) + public static bool CxxFileContainsNotCommented(VCFile file, string str, + StringComparison comparisonType, bool suppressStrings) { - return CxxFileContainsNotCommented(file, new[] { str }, caseSensitive, suppressStrings); + return CxxFileContainsNotCommented(file, new[] { str }, comparisonType, suppressStrings); } - public static bool CxxFileContainsNotCommented(VCFile file, string[] searchStrings, bool caseSensitive, bool suppressStrings) + public static bool CxxFileContainsNotCommented(VCFile file, string[] searchStrings, + StringComparison comparisonType, bool suppressStrings) { - if (!caseSensitive) { - for (var i = 0; i < searchStrings.Length; ++i) - searchStrings[i] = searchStrings[i].ToLower(); - } + // Small optimization, we first read the whole content as a string and look for the + // search strings. Once we found at least one, ... + bool found = false; + var content = string.Empty; + try { + using (StreamReader sr = new StreamReader(file.FullPath)) + content = sr.ReadToEnd(); - CxxStreamReader sr = null; - var found = false; + foreach (var key in searchStrings) { + if (content.IndexOf(key, comparisonType) >= 0) { + found = true; + break; + } + } + } catch { } + + if (!found) + return false; + + // ... we will start parsing the file again to see if the actual string is commented + // or not. The combination of string.IndexOf(...) and string.Split(...) seems to be + // way faster then reading the file line by line. + found = false; + CxxStreamReader cxxSr = null; try { - var strLine = string.Empty; - sr = new CxxStreamReader(file.FullPath); - while (!found && (strLine = sr.ReadLine(suppressStrings)) != null) { - if (!caseSensitive) - strLine = strLine.ToLower(); + cxxSr = new CxxStreamReader(content.Split(new[] { "\n", "\r\n" }, + StringSplitOptions.RemoveEmptyEntries)); + string strLine; + while (!found && (strLine = cxxSr.ReadLine(suppressStrings)) != null) { foreach (var str in searchStrings) { - if (strLine.IndexOf(str, StringComparison.Ordinal) != -1) { + if (strLine.IndexOf(str, comparisonType) != -1) { found = true; break; } } } - sr.Close(); + cxxSr.Close(); } catch (Exception) { - if (sr != null) - sr.Close(); + if (cxxSr != null) + cxxSr.Close(); } return found; } diff --git a/src/qtvstools/DteEventsHandler.cs b/src/qtvstools/DteEventsHandler.cs index 0088e0f5..b27f6735 100644 --- a/src/qtvstools/DteEventsHandler.cs +++ b/src/qtvstools/DteEventsHandler.cs @@ -380,7 +380,7 @@ namespace QtVsTools if (pcHeaderThrough != null) { var pcHeaderCreator = pcHeaderThrough.Remove(pcHeaderThrough.LastIndexOf('.')) + ".cpp"; if (vcFile.Name.EndsWith(pcHeaderCreator, StringComparison.OrdinalIgnoreCase) - && HelperFunctions.CxxFileContainsNotCommented(vcFile, "#include \"" + pcHeaderThrough + "\"", false, false)) { + && HelperFunctions.CxxFileContainsNotCommented(vcFile, "#include \"" + pcHeaderThrough + "\"", StringComparison.OrdinalIgnoreCase, false)) { //File is used to create precompiled headers QtProject.SetPCHOption(vcFile, pchOption.pchCreateUsingSpecific); return; |