aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarsten Heimrich <karsten.heimrich@qt.io>2017-01-06 16:34:06 +0100
committerKarsten Heimrich <karsten.heimrich@qt.io>2017-01-09 11:08:38 +0000
commitdd04f89de803f10201c2f5870ffff95d8452ee1c (patch)
treeafa752dfbf2f8c17cb2c3ac832f9ec8118c54f64
parentd2e1d457013845e10e818de75e2826ba69efa574 (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.cs30
-rw-r--r--src/qtprojectlib/HelperFunctions.cs58
-rw-r--r--src/qtvstools/DteEventsHandler.cs2
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;