Browse Source

Improved performance of parser run after opening a solution (really big improvement!!).

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@140 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 20 years ago
parent
commit
8ec53afcbd
  1. 1
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs
  2. 12
      src/Libraries/NRefactory/Project/Src/Lexer/AbstractLexer.cs
  3. 21
      src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Lexer.cs
  4. 5
      src/Libraries/NRefactory/Project/Src/Lexer/ILexer.cs
  5. 11
      src/Libraries/NRefactory/Project/Src/Parser/AbstractParser.cs
  6. 955
      src/Libraries/NRefactory/Project/Src/Parser/CSharp/Parser.cs
  7. 4
      src/Libraries/NRefactory/Project/Src/Parser/CSharp/cs.ATG
  8. 26
      src/Libraries/NRefactory/Test/Lexer/CSharp/LexerTest.cs
  9. 13
      src/Main/Base/Project/Src/Project/AbstractProject.cs
  10. 22
      src/Main/Core/Project/Src/Services/FileUtility/FileUtility.cs

1
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs

@ -95,6 +95,7 @@ namespace CSharpBinding.Parser
ICompilationUnit Parse(ICSharpCode.NRefactory.Parser.IParser p, string fileName, IProjectContent projectContent) ICompilationUnit Parse(ICSharpCode.NRefactory.Parser.IParser p, string fileName, IProjectContent projectContent)
{ {
p.Lexer.SpecialCommentTags = lexerTags; p.Lexer.SpecialCommentTags = lexerTags;
((ICSharpCode.NRefactory.Parser.AbstractParser)p).ParseMethodContents = false;
p.Parse(); p.Parse();
NRefactoryASTConvertVisitor visitor = new NRefactoryASTConvertVisitor(projectContent); NRefactoryASTConvertVisitor visitor = new NRefactoryASTConvertVisitor(projectContent);

12
src/Libraries/NRefactory/Project/Src/Lexer/AbstractLexer.cs

@ -3,7 +3,7 @@
* User: Omnibrain * User: Omnibrain
* Date: 08.09.2004 * Date: 08.09.2004
* Time: 23:13 * Time: 23:13
* *
* To change this template use Tools | Options | Coding | Edit Standard Headers. * To change this template use Tools | Options | Coding | Edit Standard Headers.
*/ */
@ -169,6 +169,14 @@ namespace ICSharpCode.NRefactory.Parser
protected abstract Token Next(); protected abstract Token Next();
/// <summary>
/// Skips to the end of the current code block.
/// </summary>
public virtual void SkipCurrentBlock()
{
throw new NotSupportedException();
}
protected bool IsIdentifierPart(char ch) protected bool IsIdentifierPart(char ch)
{ {
return Char.IsLetterOrDigit(ch) || ch == '_'; return Char.IsLetterOrDigit(ch) || ch == '_';
@ -224,7 +232,7 @@ namespace ICSharpCode.NRefactory.Parser
int nextChar; int nextChar;
while ((nextChar = reader.Read()) != -1) { while ((nextChar = reader.Read()) != -1) {
char ch = (char)nextChar; char ch = (char)nextChar;
// Return read string, if EOL is reached // Return read string, if EOL is reached
if (HandleLineEnd(ch)) { if (HandleLineEnd(ch)) {
return sb.ToString();; return sb.ToString();;

21
src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Lexer.cs

@ -16,7 +16,7 @@ using ICSharpCode.NRefactory.Parser;
namespace ICSharpCode.NRefactory.Parser.CSharp namespace ICSharpCode.NRefactory.Parser.CSharp
{ {
internal class Lexer : AbstractLexer internal sealed class Lexer : AbstractLexer
{ {
public Lexer(TextReader reader) : base(reader) public Lexer(TextReader reader) : base(reader)
{ {
@ -802,5 +802,24 @@ namespace ICSharpCode.NRefactory.Parser.CSharp
// Reached EOF before end of multiline comment. // Reached EOF before end of multiline comment.
errors.Error(line, col, String.Format("Reached EOF before the end of a multiline comment")); errors.Error(line, col, String.Format("Reached EOF before the end of a multiline comment"));
} }
/// <summary>
/// Skips to the end of the current code block.
/// </summary>
public override void SkipCurrentBlock()
{
int braceCount = 0;
Token t;
StartPeek();
while ((t = Peek()).kind != Tokens.EOF) {
if (t.kind == Tokens.OpenCurlyBrace) {
++braceCount;
} else if (t.kind == Tokens.CloseCurlyBrace) {
if (--braceCount < 0)
return;
}
NextToken();
}
}
} }
} }

5
src/Libraries/NRefactory/Project/Src/Lexer/ILexer.cs

@ -67,5 +67,10 @@ namespace ICSharpCode.NRefactory.Parser
/// </summary> /// </summary>
/// <returns>An <see cref="Token"/> object.</returns> /// <returns>An <see cref="Token"/> object.</returns>
Token NextToken(); Token NextToken();
/// <summary>
/// Skips to the end of the current code block.
/// </summary>
void SkipCurrentBlock();
} }
} }

11
src/Libraries/NRefactory/Project/Src/Parser/AbstractParser.cs

@ -27,6 +27,17 @@ namespace ICSharpCode.NRefactory.Parser
protected CompilationUnit compilationUnit; protected CompilationUnit compilationUnit;
protected bool parseMethodContents = true;
public bool ParseMethodContents {
get {
return parseMethodContents;
}
set {
parseMethodContents = value;
}
}
public ILexer Lexer { public ILexer Lexer {
get { get {
return lexer; return lexer;

955
src/Libraries/NRefactory/Project/Src/Parser/CSharp/Parser.cs

File diff suppressed because it is too large Load Diff

4
src/Libraries/NRefactory/Project/Src/Parser/CSharp/cs.ATG

@ -1415,9 +1415,11 @@ Block<out Statement stmt> /* not BlockStatement because of EmbeddedStatement */
"{" (. BlockStatement blockStmt = new BlockStatement(); "{" (. BlockStatement blockStmt = new BlockStatement();
blockStmt.StartLocation = t.EndLocation; blockStmt.StartLocation = t.EndLocation;
compilationUnit.BlockStart(blockStmt); compilationUnit.BlockStart(blockStmt);
if (!parseMethodContents) lexer.SkipCurrentBlock();
.) .)
{ Statement } { Statement }
"}" (. stmt = blockStmt; "}" (.
stmt = blockStmt;
blockStmt.EndLocation = t.EndLocation; blockStmt.EndLocation = t.EndLocation;
compilationUnit.BlockEnd(); compilationUnit.BlockEnd();
.) .)

26
src/Libraries/NRefactory/Test/Lexer/CSharp/LexerTest.cs

@ -112,6 +112,32 @@ namespace ICSharpCode.NRefactory.Tests.Lexer.CSharp
ILexer lexer = GenerateLexer(new StringReader("}")); ILexer lexer = GenerateLexer(new StringReader("}"));
Assert.AreEqual(Tokens.CloseCurlyBrace, lexer.NextToken().kind); Assert.AreEqual(Tokens.CloseCurlyBrace, lexer.NextToken().kind);
} }
[Test]
public void TestEmptyBlock()
{
ILexer lexer = GenerateLexer(new StringReader("{}"));
Assert.AreEqual(Tokens.OpenCurlyBrace, lexer.NextToken().kind);
Assert.AreEqual(Tokens.CloseCurlyBrace, lexer.NextToken().kind);
}
[Test]
public void TestSkippedEmptyBlock()
{
ILexer lexer = GenerateLexer(new StringReader("{}"));
Assert.AreEqual(Tokens.OpenCurlyBrace, lexer.NextToken().kind);
lexer.SkipCurrentBlock();
Assert.AreEqual(Tokens.CloseCurlyBrace, lexer.NextToken().kind);
}
[Test]
public void TestSkippedNonEmptyBlock()
{
ILexer lexer = GenerateLexer(new StringReader("{ TestMethod('}'); /* }}} */ break; }"));
Assert.AreEqual(Tokens.OpenCurlyBrace, lexer.NextToken().kind);
lexer.SkipCurrentBlock();
Assert.AreEqual(Tokens.CloseCurlyBrace, lexer.NextToken().kind);
}
[Test] [Test]
public void TestOpenSquareBracket() public void TestOpenSquareBracket()

13
src/Main/Base/Project/Src/Project/AbstractProject.cs

@ -101,13 +101,18 @@ namespace ICSharpCode.SharpDevelop.Project
} }
} }
string directoryName;
[Browsable(false)] [Browsable(false)]
public string Directory { public string Directory {
get { get {
if (fileName == null) { if (directoryName == null) {
return String.Empty; if (fileName == null) {
return String.Empty;
}
directoryName = Path.GetFullPath(Path.GetDirectoryName(fileName));
} }
return Path.GetFullPath(Path.GetDirectoryName(fileName)); return directoryName;
} }
} }
@ -337,7 +342,7 @@ namespace ICSharpCode.SharpDevelop.Project
} }
#endregion #endregion
public virtual CompilerResults Build() public virtual CompilerResults Build()
{ {
return null; return null;

22
src/Main/Core/Project/Src/Services/FileUtility/FileUtility.cs

@ -41,6 +41,9 @@ namespace ICSharpCode.Core
/// </summary> /// </summary>
public sealed class FileUtility public sealed class FileUtility
{ {
// TODO: GetFullPath is a **very** expensive method (performance-wise)!
// Call it only when necessary. (see IsEqualFile)
readonly static char[] separators = { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar, Path.VolumeSeparatorChar }; readonly static char[] separators = { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar, Path.VolumeSeparatorChar };
static string sharpDevelopRootPath; static string sharpDevelopRootPath;
const string fileNameRegEx = @"^(([a-zA-Z]:)|.)[^:]*$"; const string fileNameRegEx = @"^(([a-zA-Z]:)|.)[^:]*$";
@ -155,11 +158,28 @@ namespace ICSharpCode.Core
public static bool IsEqualFile(string fileName1, string fileName2) public static bool IsEqualFile(string fileName1, string fileName2)
{ {
// Optimized for performance:
//return Path.GetFullPath(fileName1.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)).ToLower() == Path.GetFullPath(fileName2.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)).ToLower();
if (fileName1.Length == 0 || fileName2.Length == 0) return false;
char lastChar;
lastChar = fileName1[fileName1.Length - 1];
if (lastChar == Path.DirectorySeparatorChar || lastChar == Path.AltDirectorySeparatorChar)
fileName1 = fileName1.Substring(0, fileName1.Length - 1);
lastChar = fileName2[fileName2.Length - 1];
if (lastChar == Path.DirectorySeparatorChar || lastChar == Path.AltDirectorySeparatorChar)
fileName2 = fileName2.Substring(0, fileName2.Length - 1);
try { try {
return Path.GetFullPath(fileName1.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)).ToLower() == Path.GetFullPath(fileName2.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)).ToLower(); if (fileName1.Length < 2 || fileName1[1] != ':')
fileName1 = Path.GetFullPath(fileName1);
if (fileName2.Length < 2 || fileName2[1] != ':')
fileName2 = Path.GetFullPath(fileName2);
} catch (Exception) { } catch (Exception) {
return false; return false;
} }
return string.Equals(fileName1, fileName2, StringComparison.OrdinalIgnoreCase);
} }
public static bool IsBaseDirectory(string baseDirectory, string testDirectory) public static bool IsBaseDirectory(string baseDirectory, string testDirectory)

Loading…
Cancel
Save