📄 nrefactoryresolver.cs
字号:
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Andrea Paatz" email="andrea@icsharpcode.net"/>
// <version>$Revision: 1379 $</version>
// </file>
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.NRefactory.Parser.AST;
using ICSharpCode.NRefactory.Parser;
namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
{
public class NRefactoryResolver : IResolver
{
ICompilationUnit cu;
IClass callingClass;
IMember callingMember;
ICSharpCode.NRefactory.Parser.LookupTableVisitor lookupTableVisitor;
IProjectContent projectContent = null;
SupportedLanguage language;
int caretLine;
int caretColumn;
public SupportedLanguage Language {
get {
return language;
}
}
public IProjectContent ProjectContent {
get {
return projectContent;
}
set {
projectContent = value;
}
}
public ICompilationUnit CompilationUnit {
get {
return cu;
}
}
public IClass CallingClass {
get {
return callingClass;
}
}
public IMember CallingMember {
get {
return callingMember;
}
}
public int CaretLine {
get {
return caretLine;
}
}
public int CaretColumn {
get {
return caretColumn;
}
}
LanguageProperties languageProperties;
public LanguageProperties LanguageProperties {
get {
return languageProperties;
}
}
public NRefactoryResolver(SupportedLanguage language)
{
this.language = language;
this.projectContent = ParserService.CurrentProjectContent;
switch (language) {
case SupportedLanguage.CSharp:
languageProperties = LanguageProperties.CSharp;
break;
case SupportedLanguage.VBNet:
languageProperties = LanguageProperties.VBNet;
break;
default:
throw new NotSupportedException("The language " + language + " is not supported in the resolver");
}
}
Expression ParseExpression(string expression)
{
Expression expr = SpecialConstructs(expression);
if (expr == null) {
using (ICSharpCode.NRefactory.Parser.IParser p = ParserFactory.CreateParser(language, new System.IO.StringReader(expression))) {
expr = p.ParseExpression();
}
}
return expr;
}
string GetFixedExpression(ExpressionResult expressionResult)
{
string expression = expressionResult.Expression;
if (expression == null) {
expression = "";
}
expression = expression.TrimStart();
return expression;
}
public static ResolveResult GetResultFromDeclarationLine(IClass callingClass, IMethodOrProperty callingMember, int caretLine, int caretColumn, string expression)
{
if (callingClass == null) return null;
int pos = expression.IndexOf('(');
if (pos >= 0) {
expression = expression.Substring(0, pos);
}
expression = expression.Trim();
if (!callingClass.BodyRegion.IsInside(caretLine, caretColumn)
&& callingClass.ProjectContent.Language.NameComparer.Equals(expression, callingClass.Name))
{
return new TypeResolveResult(callingClass, callingMember, callingClass);
}
if (callingMember != null
&& !callingMember.BodyRegion.IsInside(caretLine, caretColumn)
&& callingClass.ProjectContent.Language.NameComparer.Equals(expression, callingMember.Name))
{
return new MemberResolveResult(callingClass, callingMember, callingMember);
}
return null;
}
public ResolveResult Resolve(ExpressionResult expressionResult,
int caretLineNumber,
int caretColumn,
string fileName,
string fileContent)
{
string expression = GetFixedExpression(expressionResult);
this.caretLine = caretLineNumber;
this.caretColumn = caretColumn;
ParseInformation parseInfo = ParserService.GetParseInformation(fileName);
if (parseInfo == null) {
return null;
}
cu = parseInfo.MostRecentCompilationUnit;
if (cu != null) {
callingClass = cu.GetInnermostClass(caretLine, caretColumn);
}
Expression expr = null;
if (language == SupportedLanguage.VBNet) {
if (expression.Length == 0 || expression[0] == '.') {
return WithResolve(expression, fileContent);
} else if ("global".Equals(expression, StringComparison.InvariantCultureIgnoreCase)) {
return new NamespaceResolveResult(null, null, "");
}
}
if (expr == null) {
expr = ParseExpression(expression);
if (expr == null) {
return null;
}
if (expressionResult.Context.IsObjectCreation) {
Expression tmp = expr;
while (tmp != null) {
if (tmp is IdentifierExpression)
return ResolveInternal(expr, ExpressionContext.Type);
if (tmp is FieldReferenceExpression)
tmp = (tmp as FieldReferenceExpression).TargetObject;
else
break;
}
expr = ParseExpression("new " + expression);
if (expr == null) {
return null;
}
}
}
if (expressionResult.Context == ExpressionContext.Attribute) {
return ResolveAttribute(expr);
}
RunLookupTableVisitor(fileContent);
ResolveResult rr = GetResultFromDeclarationLine(callingClass, callingMember as IMethodOrProperty, caretLine, caretColumn, expression);
if (rr != null) return rr;
return ResolveInternal(expr, expressionResult.Context);
}
ResolveResult WithResolve(string expression, string fileContent)
{
RunLookupTableVisitor(fileContent);
WithStatement innermost = null;
if (lookupTableVisitor.WithStatements != null) {
foreach (WithStatement with in lookupTableVisitor.WithStatements) {
if (IsInside(new Point(caretColumn, caretLine), with.StartLocation, with.EndLocation)) {
innermost = with;
}
}
}
if (innermost != null) {
if (expression.Length > 1) {
Expression expr = ParseExpression(DummyFindVisitor.dummyName + expression);
if (expr == null) return null;
DummyFindVisitor v = new DummyFindVisitor();
expr.AcceptVisitor(v, null);
if (v.result == null) return null;
v.result.TargetObject = innermost.Expression;
return ResolveInternal(expr, ExpressionContext.Default);
} else {
return ResolveInternal(innermost.Expression, ExpressionContext.Default);
}
} else {
return null;
}
}
private class DummyFindVisitor : AbstractAstVisitor {
internal const string dummyName = "___withStatementExpressionDummy";
internal FieldReferenceExpression result;
public override object Visit(FieldReferenceExpression fieldReferenceExpression, object data)
{
IdentifierExpression ie = fieldReferenceExpression.TargetObject as IdentifierExpression;
if (ie != null && ie.Identifier == dummyName)
result = fieldReferenceExpression;
return base.Visit(fieldReferenceExpression, data);
}
}
void RunLookupTableVisitor(string fileContent)
{
lookupTableVisitor = new LookupTableVisitor(languageProperties.NameComparer);
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);
}
}
}
string GetAttributeName(Expression expr)
{
if (expr is IdentifierExpression) {
return (expr as IdentifierExpression).Identifier;
} else if (expr is FieldReferenceExpression) {
TypeVisitor typeVisitor = new TypeVisitor(this);
FieldReferenceExpression fieldReferenceExpression = (FieldReferenceExpression)expr;
IReturnType type = fieldReferenceExpression.TargetObject.AcceptVisitor(typeVisitor, null) as IReturnType;
if (type is TypeVisitor.NamespaceReturnType) {
return type.FullyQualifiedName + "." + fieldReferenceExpression.FieldName;
}
}
return null;
}
IClass GetAttribute(string name)
{
if (name == null)
return null;
IClass c = SearchClass(name);
if (c != null) {
if (c.IsTypeInInheritanceTree(ProjectContentRegistry.Mscorlib.GetClass("System.Attribute")))
return c;
}
return SearchClass(name + "Attribute");
}
ResolveResult ResolveAttribute(Expression expr)
{
string attributeName = GetAttributeName(expr);
IClass c = GetAttribute(attributeName);
if (c != null) {
return new TypeResolveResult(callingClass, callingMember, c);
} else if (expr is InvocationExpression) {
InvocationExpression ie = (InvocationExpression)expr;
attributeName = GetAttributeName(ie.TargetObject);
c = GetAttribute(attributeName);
if (c != null) {
List<IMethod> ctors = new List<IMethod>();
foreach (IMethod m in c.Methods) {
if (m.IsConstructor && !m.IsStatic)
ctors.Add(m);
}
TypeVisitor typeVisitor = new TypeVisitor(this);
return CreateMemberResolveResult(typeVisitor.FindOverload(ctors, null, ie.Arguments, null));
}
}
return null;
}
ResolveResult ResolveInternal(Expression expr, ExpressionContext context)
{
TypeVisitor typeVisitor = new TypeVisitor(this);
IReturnType type;
if (expr is PrimitiveExpression) {
if (((PrimitiveExpression)expr).Value is int)
return new IntegerLiteralResolveResult(callingClass, callingMember);
} else if (expr is InvocationExpression) {
IMethodOrProperty method = typeVisitor.GetMethod(expr as InvocationExpression);
if (method != null) {
return CreateMemberResolveResult(method);
} else {
// InvocationExpression can also be a delegate/event call
ResolveResult invocationTarget = ResolveInternal((expr as InvocationExpression).TargetObject, ExpressionContext.Default);
if (invocationTarget == null)
return null;
type = invocationTarget.ResolvedType;
if (type == null)
return null;
IClass c = type.GetUnderlyingClass();
if (c == null || c.ClassType != ClassType.Delegate)
return null;
// We don't want to show "System.EventHandler.Invoke" in the tooltip
// of "EventCall(this, EventArgs.Empty)", we just show the event/delegate for now
// but for DelegateCall(params).* completion, we use the delegate's
// return type instead of the delegate type itself
method = c.Methods.Find(delegate(IMethod innerMethod) { return innerMethod.Name == "Invoke"; });
if (method != null)
invocationTarget.ResolvedType = method.ReturnType;
return invocationTarget;
}
} else if (expr is IndexerExpression) {
return CreateMemberResolveResult(typeVisitor.GetIndexer(expr as IndexerExpression));
} else if (expr is FieldReferenceExpression) {
FieldReferenceExpression fieldReferenceExpression = (FieldReferenceExpression)expr;
if (fieldReferenceExpression.FieldName == null || fieldReferenceExpression.FieldName.Length == 0) {
// NRefactory creates this "dummy" fieldReferenceExpression when it should
// parse a primitive type name (int, short; Integer, Decimal)
if (fieldReferenceExpression.TargetObject is TypeReferenceExpression) {
type = TypeVisitor.CreateReturnType(((TypeReferenceExpression)fieldReferenceExpression.TargetObject).TypeReference, this);
if (type != null) {
return new TypeResolveResult(callingClass, callingMember, type);
}
}
}
type = fieldReferenceExpression.TargetObject.AcceptVisitor(typeVisitor, null) as IReturnType;
if (type != null) {
ResolveResult result = ResolveMemberReferenceExpression(type, fieldReferenceExpression);
if (result != null)
return result;
}
} else if (expr is IdentifierExpression) {
ResolveResult result = ResolveIdentifier(((IdentifierExpression)expr).Identifier, context);
if (result != null)
return result;
} else if (expr is TypeReferenceExpression) {
type = TypeVisitor.CreateReturnType(((TypeReferenceExpression)expr).TypeReference, this);
if (type != null) {
if (type is TypeVisitor.NamespaceReturnType)
return new NamespaceResolveResult(callingClass, callingMember, type.FullyQualifiedName);
IClass c = type.GetUnderlyingClass();
if (c != null)
return new TypeResolveResult(callingClass, callingMember, type, c);
}
return null;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -