📄 resolvevisitor.cs
字号:
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision: 1417 $</version>
// </file>
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Dom;
using Boo.Lang.Compiler.Ast;
namespace Grunwald.BooBinding.CodeCompletion
{
public class ResolveVisitor : DepthFirstVisitor
{
#region Field + Constructor
BooResolver resolver;
ResolveResult resolveResult;
IClass callingClass;
IProjectContent projectContent;
ICompilationUnit cu;
public ResolveVisitor(BooResolver resolver)
{
this.resolver = resolver;
this.callingClass = resolver.CallingClass;
this.projectContent = resolver.ProjectContent;
this.cu = resolver.CompilationUnit;
}
public ResolveResult ResolveResult {
get {
return resolveResult;
}
}
#endregion
#region Make Result
void ClearResult()
{
resolveResult = null;
}
void MakeResult(IReturnType type)
{
if (type == null)
ClearResult();
else
resolveResult = new ResolveResult(callingClass, resolver.CallingMember, type);
}
void MakeLiteralResult(string fullTypeName)
{
resolveResult = new ResolveResult(callingClass, resolver.CallingMember,
new GetClassReturnType(projectContent, fullTypeName, 0));
}
void MakeResult(IMember member)
{
IField field = member as IField;
if (field != null && (field.IsLocalVariable || field.IsParameter)) {
resolveResult = new LocalResolveResult(resolver.CallingMember, field);
} else if (member != null) {
resolveResult = new MemberResolveResult(callingClass, resolver.CallingMember, member);
} else {
ClearResult();
}
}
void MakeTypeResult(IClass c)
{
resolveResult = new TypeResolveResult(callingClass, resolver.CallingMember, c);
}
void MakeTypeResult(IReturnType rt)
{
resolveResult = new TypeResolveResult(callingClass, resolver.CallingMember, rt);
}
void MakeMethodResult(IReturnType type, string methodName)
{
resolveResult = new MethodResolveResult(callingClass, resolver.CallingMember, type, methodName);
IMethod m = (resolveResult as MethodResolveResult).GetMethodIfSingleOverload();
if (m != null) {
AnonymousMethodReturnType amrt = new AnonymousMethodReturnType(cu);
amrt.MethodReturnType = m.ReturnType;
amrt.MethodParameters = m.Parameters;
resolveResult.ResolvedType = amrt;
}
}
void MakeNamespaceResult(string namespaceName)
{
resolveResult = new NamespaceResolveResult(callingClass, resolver.CallingMember, namespaceName);
}
static bool IsSameName(string name1, string name2)
{
// boo is currently always case sensitive
return name1 == name2;
}
#endregion
#region Resolve Identifier
public override void OnReferenceExpression(ReferenceExpression node)
{
string identifier = node.Name;
bool wasResolved = ResolveIdentifier(identifier);
if (wasResolved && resolveResult is TypeResolveResult) {
return;
}
// was not resolved or was resolved as local, member etc.
ResolveResult oldResult = resolveResult;
ClearResult();
// Try to resolve as type:
IReturnType t = projectContent.SearchType(identifier, 0, callingClass, cu, resolver.CaretLine, resolver.CaretColumn);
if (t != null) {
MakeTypeResult(t);
} else {
if (callingClass != null) {
if (resolver.CallingMember is IMethod) {
foreach (ITypeParameter typeParameter in (resolver.CallingMember as IMethod).TypeParameters) {
if (IsSameName(identifier, typeParameter.Name)) {
MakeTypeResult(new GenericReturnType(typeParameter));
return;
}
}
}
foreach (ITypeParameter typeParameter in callingClass.TypeParameters) {
if (IsSameName(identifier, typeParameter.Name)) {
MakeTypeResult(new GenericReturnType(typeParameter));
return;
}
}
}
}
if (!wasResolved)
return; // return type result, if existant
if (resolveResult == null) {
resolveResult = oldResult;
} else {
// TODO: return type or mixed dependant on context!
resolveResult = new MixedResolveResult(oldResult, resolveResult);
}
}
bool ResolveIdentifier(string identifier)
{
IField local;
ClearResult();
if (resolver.CallingMember != null) {
local = resolver.FindLocalVariable(identifier, false);
if (local != null) {
MakeResult(local);
return true;
}
IMethodOrProperty method = resolver.CallingMember;
if (method != null) {
foreach (IParameter p in method.Parameters) {
if (IsSameName(p.Name, identifier)) {
MakeResult(new DefaultField.ParameterField(p.ReturnType, p.Name, p.Region, callingClass));
return true;
}
}
if (method is IProperty && IsSameName(identifier, "value")) {
if (((IProperty)method).SetterRegion.IsInside(resolver.CaretLine, resolver.CaretColumn)) {
MakeResult(new DefaultField.ParameterField(method.ReturnType, "value", method.Region, callingClass));
return true;
}
}
}
}
{ // Find members of this class or enclosing classes
IClass tmp = callingClass;
while (tmp != null) {
if (ResolveMember(tmp.DefaultReturnType, identifier))
return true;
tmp = tmp.DeclaringType;
}
}
string namespaceName = projectContent.SearchNamespace(identifier, callingClass, cu, resolver.CaretLine, resolver.CaretColumn);
if (namespaceName != null && namespaceName.Length > 0) {
MakeNamespaceResult(namespaceName);
return true;
}
// Boo can import classes+modules:
foreach (object o in resolver.GetImportedNamespaceContents()) {
IClass c = o as IClass;
if (c != null && IsSameName(identifier, c.Name)) {
MakeTypeResult(c);
return true;
}
IMember member = o as IMember;
if (member != null && IsSameName(identifier, member.Name)) {
if (member is IMethod) {
MakeMethodResult(member.DeclaringType.DefaultReturnType, member.Name);
} else {
MakeResult(member);
}
return true;
}
}
local = resolver.FindLocalVariable(identifier, true);
if (local != null) {
MakeResult(local);
return true;
}
return false;
}
#endregion
#region OnGenericReferenceExpression
public override void OnGenericReferenceExpression(GenericReferenceExpression node)
{
MakeTypeResult(ConstructTypeFromGenericReferenceExpression(node));
}
public ConstructedReturnType ConstructTypeFromGenericReferenceExpression(GenericReferenceExpression node)
{
Stack<Expression> stack = new Stack<Expression>();
Expression expr = node;
while (expr != null) {
stack.Push(expr);
if (expr is MemberReferenceExpression) {
expr = ((MemberReferenceExpression)expr).Target;
} else if (expr is GenericReferenceExpression) {
expr = ((GenericReferenceExpression)expr).Target;
} else {
expr = null;
}
}
StringBuilder name = new StringBuilder();
List<IReturnType> typeArguments = new List<IReturnType>();
while (stack.Count > 0) {
expr = stack.Pop();
if (expr is MemberReferenceExpression) {
name.Append('.');
name.Append(((MemberReferenceExpression)expr).Name);
} else if (expr is GenericReferenceExpression) {
foreach (TypeReference tr in ((GenericReferenceExpression)expr).GenericArguments) {
typeArguments.Add(ConvertVisitor.CreateReturnType(tr, callingClass,
resolver.CallingMember,
resolver.CaretLine,
resolver.CaretColumn,
projectContent));
}
} else if (expr is ReferenceExpression) {
name.Append(((ReferenceExpression)expr).Name);
} else {
LoggingService.Warn("Unknown expression in GenericReferenceExpression: " + expr);
}
}
IReturnType rt = projectContent.SearchType(name.ToString(), typeArguments.Count, callingClass,
cu, resolver.CaretLine, resolver.CaretColumn);
return new ConstructedReturnType(rt, typeArguments);
}
#endregion
#region Resolve Member
public override void OnMemberReferenceExpression(MemberReferenceExpression node)
{
ClearResult();
node.Target.Accept(this);
if (resolveResult is NamespaceResolveResult) {
string namespaceName = (resolveResult as NamespaceResolveResult).Name;
string combinedName;
if (namespaceName.Length == 0)
combinedName = node.Name;
else
combinedName = namespaceName + "." + node.Name;
if (projectContent.NamespaceExists(combinedName)) {
MakeNamespaceResult(combinedName);
return;
}
IClass c = projectContent.GetClass(combinedName);
if (c != null) {
MakeTypeResult(c);
return;
}
ClearResult();
// go through the members of the modules in that namespace
foreach (object o in projectContent.GetNamespaceContents(namespaceName)) {
IMember member = o as IMember;
if (member != null && IsSameName(member.Name, node.Name)) {
if (member is IMethod) {
MakeMethodResult(member.DeclaringType.DefaultReturnType, member.Name);
} else {
MakeResult(member);
}
break;
}
}
} else {
if (resolveResult != null) {
if (resolveResult is TypeResolveResult) {
IClass rClass = (resolveResult as TypeResolveResult).ResolvedClass;
if (rClass != null) {
foreach (IClass baseClass in rClass.ClassInheritanceTree) {
foreach (IClass innerClass in baseClass.InnerClasses) {
if (IsSameName(innerClass.Name, node.Name)) {
MakeTypeResult(innerClass);
return;
}
}
}
}
}
ResolveMember(resolveResult.ResolvedType, node.Name);
}
}
}
bool ResolveMember(IReturnType type, string memberName)
{
ClearResult();
if (type == null)
return false;
bool isClassInInheritanceTree = false;
if (callingClass != null)
isClassInInheritanceTree = callingClass.IsTypeInInheritanceTree(type.GetUnderlyingClass());
foreach (IProperty p in type.GetProperties()) {
if (IsSameName(p.Name, memberName)) {
MakeResult(p);
return true;
}
}
foreach (IField f in type.GetFields()) {
if (IsSameName(f.Name, memberName)) {
MakeResult(f);
return true;
}
}
foreach (IEvent e in type.GetEvents()) {
if (IsSameName(e.Name, memberName)) {
MakeResult(e);
return true;
}
}
foreach (IMethod m in type.GetMethods()) {
if (IsSameName(m.Name, memberName)) {
MakeMethodResult(type, memberName);
return true;
}
}
if (callingClass != null) {
ArrayList list = new ArrayList();
ResolveResult.AddExtensions(callingClass.ProjectContent.Language, list, callingClass, type);
foreach (IMethodOrProperty mp in list) {
if (IsSameName(mp.Name, memberName)) {
if (mp is IMethod)
MakeMethodResult(type, memberName);
else
MakeResult(mp);
return true;
}
}
}
return false;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -