📄 nrefactoryresolver.cs
字号:
}
type = expr.AcceptVisitor(typeVisitor, null) as IReturnType;
if (type == null || type.FullyQualifiedName == "") {
return null;
}
if (expr is ObjectCreateExpression) {
List<IMethod> constructors = new List<IMethod>();
foreach (IMethod m in type.GetMethods()) {
if (m.IsConstructor && !m.IsStatic)
constructors.Add(m);
}
if (constructors.Count == 0) {
// Class has no constructors -> create default constructor
IClass c = type.GetUnderlyingClass();
if (c != null) {
return CreateMemberResolveResult(Constructor.CreateDefault(c));
}
}
IReturnType[] typeParameters = null;
if (type.TypeArguments != null) {
typeParameters = new IReturnType[type.TypeArguments.Count];
type.TypeArguments.CopyTo(typeParameters, 0);
}
ResolveResult rr = CreateMemberResolveResult(typeVisitor.FindOverload(constructors, typeParameters, ((ObjectCreateExpression)expr).Parameters, null));
if (rr != null) {
rr.ResolvedType = type;
}
return rr;
}
return new ResolveResult(callingClass, callingMember, type);
}
ResolveResult ResolveMemberReferenceExpression(IReturnType type, FieldReferenceExpression fieldReferenceExpression)
{
IClass c;
IMember member;
if (type is TypeVisitor.NamespaceReturnType) {
string combinedName;
if (type.FullyQualifiedName == "")
combinedName = fieldReferenceExpression.FieldName;
else
combinedName = type.FullyQualifiedName + "." + fieldReferenceExpression.FieldName;
if (projectContent.NamespaceExists(combinedName)) {
return new NamespaceResolveResult(callingClass, callingMember, combinedName);
}
c = GetClass(combinedName);
if (c != null) {
return new TypeResolveResult(callingClass, callingMember, c);
}
if (languageProperties.ImportModules) {
// go through the members of the modules
foreach (object o in projectContent.GetNamespaceContents(type.FullyQualifiedName)) {
member = o as IMember;
if (member != null && IsSameName(member.Name, fieldReferenceExpression.FieldName)) {
return CreateMemberResolveResult(member);
}
}
}
return null;
}
member = GetMember(type, fieldReferenceExpression.FieldName);
if (member != null)
return CreateMemberResolveResult(member);
c = type.GetUnderlyingClass();
if (c != null) {
foreach (IClass baseClass in c.ClassInheritanceTree) {
List<IClass> innerClasses = baseClass.InnerClasses;
if (innerClasses != null) {
foreach (IClass innerClass in innerClasses) {
if (IsSameName(innerClass.Name, fieldReferenceExpression.FieldName)) {
return new TypeResolveResult(callingClass, callingMember, innerClass);
}
}
}
}
}
return ResolveMethod(type, fieldReferenceExpression.FieldName);
}
/// <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)
{
// 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.IsEmpty) return null;
int startLine = member.Region.BeginLine;
if (startLine < 1) return null;
DomRegion bodyRegion;
if (member is IMethodOrProperty) {
bodyRegion = ((IMethodOrProperty)member).BodyRegion;
} else if (member is IEvent) {
bodyRegion = ((IEvent)member).BodyRegion;
} else {
return null;
}
if (bodyRegion.IsEmpty) return null;
int endLine = bodyRegion.EndLine;
// Fix for SD2-511 (Code completion in inserted line)
if (language == SupportedLanguage.CSharp) {
// Do not do this for VB: the parser does not correct create the
// ForEachStatement when the method in truncated in the middle
// VB does not have the "inserted line looks like variable declaration"-problem
// anyways.
if (caretLine > startLine && caretLine < endLine)
endLine = caretLine;
}
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;
}
int length = offset - startOffset;
string classDecl, endClassDecl;
if (language == SupportedLanguage.VBNet) {
classDecl = "Class A";
endClassDecl = "End Class\n";
} else {
classDecl = "class A {";
endClassDecl = "}\n";
}
System.Text.StringBuilder b = new System.Text.StringBuilder(classDecl, length + classDecl.Length + endClassDecl.Length + startLine - 1);
b.Append('\n', startLine - 1);
b.Append(fileContent, startOffset, length);
b.Append(endClassDecl);
return new System.IO.StringReader(b.ToString());
}
#region Resolve Identifier
ResolveResult ResolveIdentifier(string identifier, ExpressionContext context)
{
ResolveResult result = ResolveIdentifierInternal(identifier);
if (result is TypeResolveResult)
return result;
ResolveResult result2 = null;
IReturnType t = SearchType(identifier);
if (t != null) {
result2 = new TypeResolveResult(callingClass, callingMember, t);
} else {
if (callingClass != null) {
if (callingMember is IMethod) {
foreach (ITypeParameter typeParameter in (callingMember as IMethod).TypeParameters) {
if (IsSameName(identifier, typeParameter.Name)) {
return new TypeResolveResult(callingClass, callingMember, new GenericReturnType(typeParameter));
}
}
}
foreach (ITypeParameter typeParameter in callingClass.TypeParameters) {
if (IsSameName(identifier, typeParameter.Name)) {
return new TypeResolveResult(callingClass, callingMember, new GenericReturnType(typeParameter));
}
}
}
}
if (result == null) return result2;
if (result2 == null) return result;
if (context == ExpressionContext.Type)
return result2;
return new MixedResolveResult(result, result2);
}
IField CreateLocalVariableField(LocalLookupVariable var, string identifier)
{
IReturnType type = GetVariableType(var);
IField f = new DefaultField.LocalVariableField(type, identifier, new DomRegion(var.StartPos, var.EndPos), callingClass);
if (var.IsConst) {
f.Modifiers |= ModifierEnum.Const;
}
return f;
}
ResolveResult ResolveIdentifierInternal(string identifier)
{
if (callingMember != null) { // LocalResolveResult requires callingMember to be set
LocalLookupVariable var = SearchVariable(identifier);
if (var != null) {
return new LocalResolveResult(callingMember, CreateLocalVariableField(var, identifier));
}
IParameter para = SearchMethodParameter(identifier);
if (para != null) {
IField field = new DefaultField.ParameterField(para.ReturnType, para.Name, para.Region, callingClass);
return new LocalResolveResult(callingMember, field);
}
if (IsSameName(identifier, "value")) {
IProperty property = callingMember as IProperty;
if (property != null && property.SetterRegion.IsInside(caretLine, caretColumn)) {
IField field = new DefaultField.ParameterField(property.ReturnType, "value", property.Region, callingClass);
return new LocalResolveResult(callingMember, field);
}
}
}
if (callingClass != null) {
IMember member = GetMember(callingClass.DefaultReturnType, identifier);
if (member != null) {
return CreateMemberResolveResult(member);
}
ResolveResult result = ResolveMethod(callingClass.DefaultReturnType, identifier);
if (result != null)
return result;
}
// try if there exists a static member in outer classes named typeName
List<IClass> classes = cu.GetOuterClasses(caretLine, caretColumn);
foreach (IClass c in classes) {
IMember member = GetMember(c.DefaultReturnType, identifier);
if (member != null && member.IsStatic) {
return new MemberResolveResult(callingClass, callingMember, member);
}
}
string namespaceName = SearchNamespace(identifier);
if (namespaceName != null && namespaceName.Length > 0) {
return new NamespaceResolveResult(callingClass, callingMember, namespaceName);
}
if (languageProperties.CanImportClasses) {
foreach (IUsing @using in cu.Usings) {
foreach (string import in @using.Usings) {
IClass c = GetClass(import);
if (c != null) {
IMember member = GetMember(c.DefaultReturnType, identifier);
if (member != null) {
return CreateMemberResolveResult(member);
}
ResolveResult result = ResolveMethod(c.DefaultReturnType, identifier);
if (result != null)
return result;
}
}
}
}
if (languageProperties.ImportModules) {
ArrayList list = new ArrayList();
AddImportedNamespaceContents(list, cu, callingClass);
foreach (object o in list) {
IClass c = o as IClass;
if (c != null && IsSameName(identifier, c.Name)) {
return new TypeResolveResult(callingClass, callingMember, c);
}
IMember member = o as IMember;
if (member != null && IsSameName(identifier, member.Name)) {
if (member is IMethod) {
return new MethodResolveResult(callingClass, callingMember, member.DeclaringType.DefaultReturnType, member.Name);
} else {
return CreateMemberResolveResult(member);
}
}
}
}
return null;
}
#endregion
private ResolveResult CreateMemberResolveResult(IMember member)
{
if (member == null) return null;
return new MemberResolveResult(callingClass, callingMember, member);
}
#region ResolveMethod
ResolveResult ResolveMethod(IReturnType type, string identifier)
{
if (type == null)
return null;
foreach (IMethod method in type.GetMethods()) {
if (IsSameName(identifier, method.Name))
return new MethodResolveResult(callingClass, callingMember, type, identifier);
}
if (languageProperties.SupportsExtensionMethods && callingClass != null) {
ArrayList list = new ArrayList();
ResolveResult.AddExtensions(languageProperties, list, callingClass, type);
foreach (IMethodOrProperty mp in list) {
if (mp is IMethod && IsSameName(mp.Name, identifier)) {
return new MethodResolveResult(callingClass, callingMember, type, identifier);
}
}
}
return null;
}
#endregion
Expression SpecialConstructs(string expression)
{
if (language == SupportedLanguage.VBNet) {
// MyBase and MyClass are no expressions, only MyBase.Identifier and MyClass.Identifier
if ("mybase".Equals(expression, StringComparison.InvariantCultureIgnoreCase)) {
return new BaseReferenceExpression();
} else if ("myclass".Equals(expression, StringComparison.InvariantCultureIgnoreCase)) {
return new ClassReferenceExpression();
} // Global is handled in Resolve() because we don't need an expression for that
} else if (language == SupportedLanguage.CSharp) {
// generic type names are no expressions, only property access on them is an expression
if (expression.EndsWith(">")) {
FieldReferenceExpression expr = ParseExpression(expression + ".Prop") as FieldReferenceExpression;
if (expr != null) {
return expr.TargetObject;
}
}
return null;
}
return null;
}
public bool IsSameName(string name1, string name2)
{
return languageProperties.NameComparer.Equals(name1, name2);
}
bool IsInside(Point between, Point start, Point end)
{
if (between.Y < start.Y || between.Y > end.Y) {
return false;
}
if (between.Y > start.Y) {
if (between.Y < end.Y) {
return true;
}
// between.Y == end.Y
return between.X <= end.X;
}
// between.Y == start.Y
if (between.X < start.X) {
return false;
}
// start is OK and between.Y <= end.Y
return between.Y < end.Y || between.X <= end.X;
}
IMember GetCurrentMember()
{
if (callingClass == null)
return null;
foreach (IMethod method in callingClass.Methods) {
if (method.Region.IsInside(caretLine, caretColumn) || method.BodyRegion.IsInside(caretLine, caretColumn)) {
return method;
}
}
foreach (IProperty property in callingClass.Properties) {
if (property.Region.IsInside(caretLine, caretColumn) || property.BodyRegion.IsInside(caretLine, caretColumn)) {
return property;
}
}
return null;
}
/// <remarks>
/// use the usings to find the correct name of a namespace
/// </remarks>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -