Browse Source

Resolver is now using ExtractMethod to parse only the current method to get local variables.

This removes the need to save the NRefactory-CompilationUnit in the Tag property of the AST-CompilationUnit.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@138 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 20 years ago
parent
commit
daee009454
  1. 46
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs
  2. 38
      src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/Parser.cs
  3. 11
      src/Main/Base/Project/Src/Dom/IResolver.cs
  4. 106
      src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs
  5. 2
      src/Main/Base/Project/Src/Services/ParserService/ParserService.cs

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

@ -19,7 +19,7 @@ namespace CSharpBinding.Parser @@ -19,7 +19,7 @@ namespace CSharpBinding.Parser
{
public class TParser : IParser
{
///<summary>IParser Interface</summary>
///<summary>IParser Interface</summary>
string[] lexerTags;
public string[] LexerTags {
@ -53,7 +53,7 @@ namespace CSharpBinding.Parser @@ -53,7 +53,7 @@ namespace CSharpBinding.Parser
ICSharpCode.NRefactory.Parser.PreProcessingDirective directive = tracker.CurrentSpecials[i] as ICSharpCode.NRefactory.Parser.PreProcessingDirective;
if (directive != null) {
if (directive.Cmd == "#region") {
int deep = 1;
int deep = 1;
for (int j = i + 1; j < tracker.CurrentSpecials.Count; ++j) {
ICSharpCode.NRefactory.Parser.PreProcessingDirective nextDirective = tracker.CurrentSpecials[j] as ICSharpCode.NRefactory.Parser.PreProcessingDirective;
if (nextDirective != null) {
@ -81,37 +81,31 @@ namespace CSharpBinding.Parser @@ -81,37 +81,31 @@ namespace CSharpBinding.Parser
{
Properties textEditorProperties = ((Properties)PropertyService.Get("ICSharpCode.TextEditor.Document.Document.DefaultDocumentAggregatorProperties", new Properties()));
using (ICSharpCode.NRefactory.Parser.IParser p = ICSharpCode.NRefactory.Parser.ParserFactory.CreateParser(fileName, Encoding.GetEncoding(textEditorProperties.Get("Encoding", 1252)))) {
p.Lexer.SpecialCommentTags = lexerTags;
p.Parse();
NRefactoryASTConvertVisitor visitor = new NRefactoryASTConvertVisitor(projectContent);
visitor.Visit(p.CompilationUnit, null);
visitor.Cu.FileName = fileName;
visitor.Cu.ErrorsDuringCompile = p.Errors.count > 0;
RetrieveRegions(visitor.Cu, p.Lexer.SpecialTracker);
AddCommentTags(visitor.Cu, p.Lexer.TagComments);
return visitor.Cu;
return Parse(p, fileName, projectContent);
}
}
public ICompilationUnit Parse(IProjectContent projectContent, string fileName, string fileContent)
{
{
using (ICSharpCode.NRefactory.Parser.IParser p = ICSharpCode.NRefactory.Parser.ParserFactory.CreateParser(ICSharpCode.NRefactory.Parser.SupportedLanguages.CSharp, new StringReader(fileContent))) {
p.Lexer.SpecialCommentTags = lexerTags;
p.Parse();
NRefactoryASTConvertVisitor visitor = new NRefactoryASTConvertVisitor(projectContent);
visitor.Visit(p.CompilationUnit, null);
visitor.Cu.FileName = fileName;
visitor.Cu.ErrorsDuringCompile = p.Errors.count > 0;
visitor.Cu.Tag = p.CompilationUnit;
RetrieveRegions(visitor.Cu, p.Lexer.SpecialTracker);
AddCommentTags(visitor.Cu, p.Lexer.TagComments);
return visitor.Cu;
return Parse(p, fileName, projectContent);
}
}
ICompilationUnit Parse(ICSharpCode.NRefactory.Parser.IParser p, string fileName, IProjectContent projectContent)
{
p.Lexer.SpecialCommentTags = lexerTags;
p.Parse();
NRefactoryASTConvertVisitor visitor = new NRefactoryASTConvertVisitor(projectContent);
visitor.Visit(p.CompilationUnit, null);
visitor.Cu.FileName = fileName;
visitor.Cu.ErrorsDuringCompile = p.Errors.count > 0;
RetrieveRegions(visitor.Cu, p.Lexer.SpecialTracker);
AddCommentTags(visitor.Cu, p.Lexer.TagComments);
return visitor.Cu;
}
void AddCommentTags(ICompilationUnit cu, ArrayList tagComments)
{
foreach (ICSharpCode.NRefactory.Parser.TagComment tagComment in tagComments) {
@ -124,7 +118,7 @@ namespace CSharpBinding.Parser @@ -124,7 +118,7 @@ namespace CSharpBinding.Parser
public IResolver CreateResolver()
{
return new ICSharpCode.SharpDevelop.Dom.NRefactoryResolver.NRefactoryResolver(ICSharpCode.NRefactory.Parser.SupportedLanguages.CSharp);
return new ICSharpCode.SharpDevelop.Dom.NRefactoryResolver.NRefactoryResolver(ICSharpCode.NRefactory.Parser.SupportedLanguages.CSharp);
}
///////// IParser Interface END
}

38
src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/Parser.cs

@ -94,36 +94,30 @@ namespace VBNetBinding.Parser @@ -94,36 +94,30 @@ namespace VBNetBinding.Parser
{
Properties textEditorProperties = ((Properties)PropertyService.Get("ICSharpCode.TextEditor.Document.Document.DefaultDocumentAggregatorProperties", new Properties()));
using (ICSharpCode.NRefactory.Parser.IParser p = ICSharpCode.NRefactory.Parser.ParserFactory.CreateParser(fileName, Encoding.GetEncoding(textEditorProperties.Get("Encoding", 1252)))) {
p.Lexer.SpecialCommentTags = lexerTags;
p.Parse();
NRefactoryASTConvertVisitor visitor = new NRefactoryASTConvertVisitor(projectContent);
visitor.Visit(p.CompilationUnit, null);
visitor.Cu.FileName = fileName;
visitor.Cu.ErrorsDuringCompile = p.Errors.count > 0;
RetrieveRegions(visitor.Cu, p.Lexer.SpecialTracker);
AddCommentTags(visitor.Cu, p.Lexer.TagComments);
return visitor.Cu;
return Parse(p, fileName, projectContent);
}
}
public ICompilationUnit Parse(IProjectContent projectContent, string fileName, string fileContent)
{
using (ICSharpCode.NRefactory.Parser.IParser p = ICSharpCode.NRefactory.Parser.ParserFactory.CreateParser(ICSharpCode.NRefactory.Parser.SupportedLanguages.VBNet, new StringReader(fileContent))) {
p.Lexer.SpecialCommentTags = lexerTags;
p.Parse();
NRefactoryASTConvertVisitor visitor = new NRefactoryASTConvertVisitor(projectContent);
visitor.Visit(p.CompilationUnit, null);
visitor.Cu.FileName = fileName;
visitor.Cu.ErrorsDuringCompile = p.Errors.count > 0;
visitor.Cu.Tag = p.CompilationUnit;
RetrieveRegions(visitor.Cu, p.Lexer.SpecialTracker);
AddCommentTags(visitor.Cu, p.Lexer.TagComments);
return visitor.Cu;
return Parse(p, fileName, projectContent);
}
}
ICompilationUnit Parse(ICSharpCode.NRefactory.Parser.IParser p, string fileName, IProjectContent projectContent)
{
p.Lexer.SpecialCommentTags = lexerTags;
p.Parse();
NRefactoryASTConvertVisitor visitor = new NRefactoryASTConvertVisitor(projectContent);
visitor.Visit(p.CompilationUnit, null);
visitor.Cu.FileName = fileName;
visitor.Cu.ErrorsDuringCompile = p.Errors.count > 0;
RetrieveRegions(visitor.Cu, p.Lexer.SpecialTracker);
AddCommentTags(visitor.Cu, p.Lexer.TagComments);
return visitor.Cu;
}
void AddCommentTags(ICompilationUnit cu, ArrayList tagComments)
{

11
src/Main/Base/Project/Src/Dom/IResolver.cs

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
* User: Omnibrain
* Date: 30.11.2004
* Time: 23:23
*
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
@ -24,10 +24,11 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -24,10 +24,11 @@ namespace ICSharpCode.SharpDevelop.Dom
/// Resolves an expression.
/// The caretLineNumber and caretColumn is 1 based.
/// </summary>
ResolveResult Resolve(string expression,
int caretLineNumber,
int caretColumn,
string fileName);
ResolveResult Resolve(string expression,
int caretLineNumber,
int caretColumn,
string fileName,
string fileContent);
ArrayList CtrlSpace(int caretLine, int caretColumn, string fileName);
}

106
src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs

@ -96,7 +96,8 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -96,7 +96,8 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
public ResolveResult Resolve(string expression,
int caretLineNumber,
int caretColumn,
string fileName)
string fileName,
string fileContent)
{
if (expression == null) {
expression = "";
@ -110,12 +111,6 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -110,12 +111,6 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
if (parseInfo == null) {
return null;
}
ICSharpCode.NRefactory.Parser.AST.CompilationUnit fileCompilationUnit = parseInfo.MostRecentCompilationUnit.Tag as ICSharpCode.NRefactory.Parser.AST.CompilationUnit;
if (fileCompilationUnit == null) {
// ICSharpCode.NRefactory.Parser.Parser fileParser = new ICSharpCode.NRefactory.Parser.Parser();
// fileParser.Parse(new Lexer(new StringReader(fileContent)));
return null;
}
Expression expr = null;
if (expression == "") {
if ((expr = WithResolve()) == null) {
@ -125,7 +120,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -125,7 +120,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
if (expr == null) {
expr = SpecialConstructs(expression);
if (expr == null) {
ICSharpCode.NRefactory.Parser.IParser p = ICSharpCode.NRefactory.Parser.ParserFactory.CreateParser(language, new System.IO.StringReader(expression));
ICSharpCode.NRefactory.Parser.IParser p = ParserFactory.CreateParser(language, new System.IO.StringReader(expression));
expr = p.ParseExpression();
if (expr == null) {
return null;
@ -133,17 +128,23 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -133,17 +128,23 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
}
}
lookupTableVisitor = new LookupTableVisitor(languageProperties.NameComparer);
lookupTableVisitor.Visit(fileCompilationUnit, null);
NRefactoryASTConvertVisitor cSharpVisitor = new NRefactoryASTConvertVisitor(parseInfo.MostRecentCompilationUnit != null ? parseInfo.MostRecentCompilationUnit.ProjectContent : null);
cu = (ICompilationUnit)cSharpVisitor.Visit(fileCompilationUnit, null);
//NRefactoryASTConvertVisitor cSharpVisitor = new NRefactoryASTConvertVisitor(parseInfo.MostRecentCompilationUnit != null ? parseInfo.MostRecentCompilationUnit.ProjectContent : null);
cu = parseInfo.MostRecentCompilationUnit; //(ICompilationUnit)cSharpVisitor.Visit(fileCompilationUnit, null);
if (cu != null) {
callingClass = cu.GetInnermostClass(caretLine, caretColumn);
cu.FileName = fileName;
}
callingMember = GetCurrentMember();
if (callingMember != null) {
System.IO.TextReader content = ExtractMethod(fileContent, callingMember);
if (content != null) {
ICSharpCode.NRefactory.Parser.IParser p = ParserFactory.CreateParser(language, content);
p.Parse();
lookupTableVisitor.Visit(p.CompilationUnit, null);
}
}
TypeVisitor typeVisitor = new TypeVisitor(this);
@ -206,12 +207,71 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -206,12 +207,71 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
}
return null;
}
return new ResolveResult(callingClass, callingMember, FixType(type));
return new ResolveResult(callingClass, callingMember, type);
}
IReturnType FixType(IReturnType type)
/// <summary>
/// Creates a new class containing only the specified member.
/// This is useful because we only want to parse current method for local variables,
/// as all fields etc. are already prepared in the AST.
/// </summary>
System.IO.TextReader ExtractMethod(string fileContent, IMember member)
{
return type;
// As the parse information is always some seconds old, the end line could be wrong
// if the user just inserted a line in the method.
// We can ignore that case because it is sufficient for the parser when the first part of the
// method body is ok.
// Since we are operating directly on the edited buffer, the parser might not be
// able to resolve invalid declarations.
// We can ignore even that because the 'invalid line' is the line the user is currently
// editing, and the declarations he is using are always above that line.
// The ExtractMethod-approach has the advantage that the method contents do not have
// do be parsed and stored in memory before they are needed.
// Previous SharpDevelop versions always stored the SharpRefactory[VB] parse tree as 'Tag'
// to the AST CompilationUnit.
// This approach doesn't need that, so one could even go and implement a special parser
// mode that does not parse the method bodies for the normal run (in the ParserUpdateThread or
// SolutionLoadThread). That could improve the parser's speed dramatically.
if (member.Region == null) return null;
int startLine = member.Region.BeginLine;
if (startLine < 1) return null;
IRegion bodyRegion;
if (member is IMethod) {
bodyRegion = ((IMethod)member).BodyRegion;
} else if (member is IProperty) {
bodyRegion = ((IProperty)member).BodyRegion;
} else if (member is IIndexer) {
bodyRegion = ((IIndexer)member).BodyRegion;
} else if (member is IEvent) {
bodyRegion = ((IEvent)member).BodyRegion;
} else {
return null;
}
if (bodyRegion == null) return null;
int endLine = bodyRegion.EndLine;
int offset = 0;
for (int i = 0; i < startLine - 1; ++i) { // -1 because the startLine must be included
offset = fileContent.IndexOf('\n', offset) + 1;
if (offset <= 0) return null;
}
int startOffset = offset;
for (int i = startLine - 1; i < endLine; ++i) {
int newOffset = fileContent.IndexOf('\n', offset) + 1;
if (newOffset <= 0) break;
offset = newOffset;
}
// Console.WriteLine("<source from={0} to={1}>", startLine, endLine);
// Console.Write(fileContent.Substring(startOffset, offset - startOffset));
// Console.WriteLine("</source>");
int length = offset - startOffset;
System.Text.StringBuilder b = new System.Text.StringBuilder("class A {", length + 10 + startLine);
b.Append('\n', startLine - 1);
b.Append(fileContent, startOffset, length);
b.Append("}\n");
return new System.IO.StringReader(b.ToString());
}
#region Resolve Identifier
@ -225,12 +285,12 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -225,12 +285,12 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
LocalLookupVariable var = SearchVariable(identifier);
if (var != null) {
IReturnType type = GetVariableType(var);
IField field = new DefaultField(FixType(type), identifier, ModifierEnum.None, new DefaultRegion(var.StartPos, var.EndPos), callingClass);
IField field = new DefaultField(type, identifier, ModifierEnum.None, new DefaultRegion(var.StartPos, var.EndPos), callingClass);
return new LocalResolveResult(callingMember, field, false);
}
IParameter para = SearchMethodParameter(identifier);
if (para != null) {
IField field = new DefaultField(FixType(para.ReturnType), para.Name, ModifierEnum.None, para.Region, callingClass);
IField field = new DefaultField(para.ReturnType, para.Name, ModifierEnum.None, para.Region, callingClass);
return new LocalResolveResult(callingMember, field, true);
}
}
@ -263,7 +323,6 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -263,7 +323,6 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
private ResolveResult CreateMemberResolveResult(IMember member)
{
member.ReturnType = FixType(member.ReturnType);
return new MemberResolveResult(callingClass, callingMember, member);
}
@ -339,14 +398,19 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -339,14 +398,19 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
{
if (callingClass == null)
return null;
foreach (IMethod method in callingClass.Methods) {
if (method.BodyRegion != null && method.BodyRegion.IsInside(caretLine, caretColumn)) {
return method;
}
}
foreach (IProperty property in callingClass.Properties) {
if (property.BodyRegion != null && property.BodyRegion.IsInside(caretLine, caretColumn)) {
return property;
}
}
foreach (IMethod method in callingClass.Methods) {
if (method.BodyRegion != null && method.BodyRegion.IsInside(caretLine, caretColumn)) {
return method;
foreach (IIndexer indexer in callingClass.Indexer) {
if (indexer.BodyRegion != null && indexer.BodyRegion.IsInside(caretLine, caretColumn)) {
return indexer;
}
}
return null;

2
src/Main/Base/Project/Src/Services/ParserService/ParserService.cs

@ -401,7 +401,7 @@ namespace ICSharpCode.Core @@ -401,7 +401,7 @@ namespace ICSharpCode.Core
//try {
IParser parser = GetParser(fileName);
if (parser != null) {
return parser.CreateResolver().Resolve(expression, caretLineNumber, caretColumn, fileName);
return parser.CreateResolver().Resolve(expression, caretLineNumber, caretColumn, fileName, fileContent);
}
return null;
//} catch {

Loading…
Cancel
Save