Browse Source

Fixed code completion for generic methods.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@158 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 20 years ago
parent
commit
4c05bc6cdd
  1. 4
      src/Libraries/NRefactory/NRefactory.sln
  2. 3
      src/Libraries/NRefactory/Project/Src/Output/CodeDOM/CodeDOMOutputVisitor.cs
  3. 1
      src/Libraries/NRefactory/Test/NRefactoryTests.csproj
  4. 48
      src/Libraries/NRefactory/Test/Output/CodeDOM/InvocationExpressionTest.cs
  5. 13
      src/Main/Base/Project/Src/Dom/Implementations/SpecificReturnType.cs
  6. 19
      src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryASTConvertVisitor.cs
  7. 48
      src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs
  8. 50
      src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs
  9. 15
      src/Main/Base/Test/GenericResolverTests.cs
  10. 5
      src/Main/Base/Test/NRefactoryResolverTests.cs

4
src/Libraries/NRefactory/NRefactory.sln

@ -1,8 +1,8 @@ @@ -1,8 +1,8 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# SharpDevelop 2.0.0.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.Tests", "Test\NRefactoryTests.csproj", "{870115dd-960a-4406-a6b9-600bcdc36a03}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory", "Project\NRefactory.csproj", "{3a9ae6aa-bc07-4a2f-972c-581e3ae2f195}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.Tests", "Test\NRefactoryTests.csproj", "{870115dd-960a-4406-a6b9-600bcdc36a03}"
EndProject
Global
EndGlobal

3
src/Libraries/NRefactory/Project/Src/Output/CodeDOM/CodeDOMOutputVisitor.cs

@ -648,6 +648,9 @@ namespace ICSharpCode.NRefactory.Parser @@ -648,6 +648,9 @@ namespace ICSharpCode.NRefactory.Parser
if (methodName == "ChrW") {
return new CodeCastExpression("System.Char", GetExpressionList(invocationExpression.Parameters)[0]);
}
} else if (target is IdentifierExpression) {
targetExpr = new CodeThisReferenceExpression();
methodName = ((IdentifierExpression)target).Identifier;
} else {
targetExpr = (CodeExpression)target.AcceptVisitor(this, data);
}

1
src/Libraries/NRefactory/Test/NRefactoryTests.csproj

@ -124,6 +124,7 @@ @@ -124,6 +124,7 @@
<Compile Include="Lexer\VBNet\LiteralsTests.cs" />
<Compile Include="Parser\SkipMethodBodiesTest.cs" />
<Compile Include="Parser\Expressions\AnonymousMethodTests.cs" />
<Compile Include="Output\CodeDOM\InvocationExpressionTest.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="General\" />

48
src/Libraries/NRefactory/Test/Output/CodeDOM/InvocationExpressionTest.cs

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
/*
* Created by SharpDevelop.
* User: Daniel Grunwald
* Date: 23.05.2005
* Time: 19:06
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using System.Collections;
using System.CodeDom;
using NUnit.Framework;
using ICSharpCode.NRefactory.Parser;
using ICSharpCode.NRefactory.Parser.AST;
namespace ICSharpCode.NRefactory.Tests.Output.CodeDom.Tests
{
[TestFixture]
public class InvocationExpressionsTests
{
[Test]
public void IdentifierOnlyInvocation()
{
// InitializeComponents();
IdentifierExpression identifier = new IdentifierExpression("InitializeComponents");
InvocationExpression invocation = new InvocationExpression(identifier, new ArrayList());
object output = invocation.AcceptVisitor(new CodeDOMVisitor(), null);
Assert.IsTrue(output is CodeMethodInvokeExpression);
CodeMethodInvokeExpression mie = (CodeMethodInvokeExpression)output;
Assert.AreEqual("InitializeComponents", mie.Method.MethodName);
Assert.IsTrue(mie.Method.TargetObject is CodeThisReferenceExpression);
}
[Test]
public void MethodOnThisReferenceInvocation()
{
// InitializeComponents();
FieldReferenceExpression field = new FieldReferenceExpression(new ThisReferenceExpression(), "InitializeComponents");
InvocationExpression invocation = new InvocationExpression(field, new ArrayList());
object output = invocation.AcceptVisitor(new CodeDOMVisitor(), null);
Assert.IsTrue(output is CodeMethodInvokeExpression);
CodeMethodInvokeExpression mie = (CodeMethodInvokeExpression)output;
Assert.AreEqual("InitializeComponents", mie.Method.MethodName);
Assert.IsTrue(mie.Method.TargetObject is CodeThisReferenceExpression);
}
}
}

13
src/Main/Base/Project/Src/Dom/Implementations/SpecificReturnType.cs

@ -114,31 +114,36 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -114,31 +114,36 @@ namespace ICSharpCode.SharpDevelop.Dom
}
}
IReturnType TranslateType(IReturnType input)
public static IReturnType TranslateType(IReturnType input, List<IReturnType> typeParameters, bool convertForMethod)
{
if (input is GenericReturnType) {
GenericReturnType rt = (GenericReturnType)input;
if (rt.TypeParameter.Method == null) {
if (convertForMethod ? (rt.TypeParameter.Method != null) : (rt.TypeParameter.Method == null)) {
if (rt.TypeParameter.Index < typeParameters.Count) {
return typeParameters[rt.TypeParameter.Index];
}
}
} else if (input is ArrayReturnType) {
IReturnType e = ((ArrayReturnType)input).ElementType;
IReturnType t = TranslateType(e);
IReturnType t = TranslateType(e, typeParameters, convertForMethod);
if (e != t && t != null)
return new ArrayReturnType(t, input.ArrayDimensions);
} else if (input is SpecificReturnType) {
SpecificReturnType r = (SpecificReturnType)input;
List<IReturnType> para = new List<IReturnType>(r.TypeParameters.Count);
for (int i = 0; i < r.TypeParameters.Count; ++i) {
para.Add(TranslateType(r.TypeParameters[i]));
para.Add(TranslateType(r.TypeParameters[i], typeParameters, convertForMethod));
}
return new SpecificReturnType(r.baseType, para);
}
return input;
}
IReturnType TranslateType(IReturnType input)
{
return TranslateType(input, typeParameters, false);
}
public override List<IMethod> GetMethods()
{
List<IMethod> l = baseType.GetMethods();

19
src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryASTConvertVisitor.cs

@ -267,19 +267,19 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -267,19 +267,19 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
{
DefaultRegion region = GetRegion(methodDeclaration.StartLocation, methodDeclaration.EndLocation);
DefaultRegion bodyRegion = GetRegion(methodDeclaration.EndLocation, methodDeclaration.Body != null ? methodDeclaration.Body.EndLocation : new Point(-1, -1));
IReturnType type = CreateReturnType(methodDeclaration.TypeReference);
DefaultClass c = GetCurrentClass();
DefaultMethod method = new DefaultMethod(methodDeclaration.Name, type, ConvertModifier(methodDeclaration.Modifier), region, bodyRegion, GetCurrentClass());
DefaultMethod method = new DefaultMethod(methodDeclaration.Name, null, ConvertModifier(methodDeclaration.Modifier), region, bodyRegion, GetCurrentClass());
ConvertTemplates(methodDeclaration.Templates, method);
method.ReturnType = CreateReturnType(methodDeclaration.TypeReference, method);
method.Attributes.AddRange(VisitAttributes(methodDeclaration.Attributes));
if (methodDeclaration.Parameters != null) {
foreach (AST.ParameterDeclarationExpression par in methodDeclaration.Parameters) {
IReturnType parType = CreateReturnType(par.TypeReference);
IReturnType parType = CreateReturnType(par.TypeReference, method);
DefaultParameter p = new DefaultParameter(par.ParameterName, parType, new DefaultRegion(par.StartLocation, methodDeclaration.Body.EndLocation));
method.Parameters.Add(p);
}
}
ConvertTemplates(methodDeclaration.Templates, method);
c.Methods.Add(method);
return null;
}
@ -397,6 +397,17 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -397,6 +397,17 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
return null;
}
IReturnType CreateReturnType(AST.TypeReference reference, IMethod method)
{
if (method.TypeParameters != null) {
foreach (ITypeParameter tp in method.TypeParameters) {
if (tp.Name.Equals(reference.SystemType, StringComparison.InvariantCultureIgnoreCase))
return new GenericReturnType(tp);
}
}
return CreateReturnType(reference);
}
IReturnType CreateReturnType(AST.TypeReference reference)
{
IClass c = GetCurrentClass();

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

@ -93,6 +93,13 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -93,6 +93,13 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
}
}
Expression ParseExpression(string expression)
{
using (ICSharpCode.NRefactory.Parser.IParser p = ParserFactory.CreateParser(language, new System.IO.StringReader(expression))) {
return p.ParseExpression();
}
}
public ResolveResult Resolve(string expression,
int caretLineNumber,
int caretColumn,
@ -120,8 +127,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -120,8 +127,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
if (expr == null) {
expr = SpecialConstructs(expression);
if (expr == null) {
ICSharpCode.NRefactory.Parser.IParser p = ParserFactory.CreateParser(language, new System.IO.StringReader(expression));
expr = p.ParseExpression();
expr = ParseExpression(expression);
if (expr == null) {
return null;
}
@ -147,6 +153,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -147,6 +153,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
}
TypeVisitor typeVisitor = new TypeVisitor(this);
IReturnType type;
if (expr is PrimitiveExpression) {
if (((PrimitiveExpression)expr).Value is int)
@ -157,20 +164,19 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -157,20 +164,19 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
return CreateMemberResolveResult(method);
} else if (expr is FieldReferenceExpression) {
FieldReferenceExpression fieldReferenceExpression = (FieldReferenceExpression)expr;
IReturnType returnType;
if (fieldReferenceExpression.FieldName == null || fieldReferenceExpression.FieldName == "") {
if (fieldReferenceExpression.TargetObject is TypeReferenceExpression) {
returnType = TypeVisitor.CreateReturnType(((TypeReferenceExpression)fieldReferenceExpression.TargetObject).TypeReference, this);
if (returnType != null) {
IClass c = projectContent.GetClass(returnType.FullyQualifiedName);
type = TypeVisitor.CreateReturnType(((TypeReferenceExpression)fieldReferenceExpression.TargetObject).TypeReference, this);
if (type != null) {
IClass c = projectContent.GetClass(type.FullyQualifiedName);
if (c != null)
return new TypeResolveResult(callingClass, callingMember, returnType, c);
return new TypeResolveResult(callingClass, callingMember, type, c);
}
}
}
returnType = fieldReferenceExpression.TargetObject.AcceptVisitor(typeVisitor, null) as IReturnType;
if (returnType != null) {
string name = SearchNamespace(returnType.FullyQualifiedName, this.CompilationUnit);
type = fieldReferenceExpression.TargetObject.AcceptVisitor(typeVisitor, null) as IReturnType;
if (type != null) {
string name = SearchNamespace(type.FullyQualifiedName, this.CompilationUnit);
if (name != null) {
name += "." + fieldReferenceExpression.FieldName;
string n = SearchNamespace(name, null);
@ -183,10 +189,10 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -183,10 +189,10 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
}
return null;
}
IMember member = GetMember(returnType, fieldReferenceExpression.FieldName);
IMember member = GetMember(type, fieldReferenceExpression.FieldName);
if (member != null)
return CreateMemberResolveResult(member);
ResolveResult result = ResolveMethod(returnType, fieldReferenceExpression.FieldName);
ResolveResult result = ResolveMethod(type, fieldReferenceExpression.FieldName);
if (result != null)
return result;
}
@ -194,8 +200,15 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -194,8 +200,15 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
ResolveResult result = ResolveIdentifier(((IdentifierExpression)expr).Identifier);
if (result != null)
return result;
} else if (expr is TypeReferenceExpression) {
type = TypeVisitor.CreateReturnType(((TypeReferenceExpression)expr).TypeReference, this);
if (type != null) {
IClass c = projectContent.GetClass(type.FullyQualifiedName);
if (c != null)
return new TypeResolveResult(callingClass, callingMember, type, c);
}
}
IReturnType type = expr.AcceptVisitor(typeVisitor, null) as IReturnType;
type = expr.AcceptVisitor(typeVisitor, null) as IReturnType;
if (type == null || type.FullyQualifiedName == "") {
return null;
@ -375,6 +388,15 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -375,6 +388,15 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
} else if (expression == "myclass") {
return new ClassReferenceExpression();
}
} else if (language == SupportedLanguages.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;
}

50
src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs

@ -81,6 +81,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -81,6 +81,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
int ScoreOverload(IMethod method, IReturnType[] types)
{
if (method == null) return -1;
if (method.Parameters.Count == types.Length) {
int points = types.Length;
for (int i = 0; i < types.Length; ++i) {
@ -102,6 +103,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -102,6 +103,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
FieldReferenceExpression field = (FieldReferenceExpression)invocationExpression.TargetObject;
IReturnType type = field.TargetObject.AcceptVisitor(this, data) as IReturnType;
ArrayList methods = resolver.SearchMethod(type, field.FieldName);
InjectMethodTypeParameters(methods, invocationExpression);
return FindOverload(methods, invocationExpression.Parameters, data);
} else if (invocationExpression.TargetObject is IdentifierExpression) {
string id = ((IdentifierExpression)invocationExpression.TargetObject).Identifier;
@ -109,6 +111,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -109,6 +111,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
return null;
}
ArrayList methods = resolver.SearchMethod(resolver.CallingClass.DefaultReturnType, id);
InjectMethodTypeParameters(methods, invocationExpression);
return FindOverload(methods, invocationExpression.Parameters, data);
}
// invocationExpression is delegate call
@ -124,6 +127,26 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -124,6 +127,26 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
return null;
}
void InjectMethodTypeParameters(ArrayList methods, InvocationExpression invocationExpression)
{
if (invocationExpression.TypeParameters == null) return;
if (invocationExpression.TypeParameters.Count == 0) return;
List<IReturnType> typeParameters = CreateReturnType(invocationExpression.TypeParameters);
for (int i = 0; i < methods.Count; ++i) {
IMethod m = (IMethod)methods[i];
if (m.TypeParameters.Count == 0) {
m = null; // this is not the correct overload, ignore this method
} else {
m = (IMethod)m.Clone();
m.ReturnType = SpecificReturnType.TranslateType(m.ReturnType, typeParameters, true);
for (int j = 0; j < m.Parameters.Count; ++j) {
m.Parameters[j].ReturnType = SpecificReturnType.TranslateType(m.Parameters[j].ReturnType, typeParameters, true);
}
}
methods[i] = m;
}
}
public override object Visit(FieldReferenceExpression fieldReferenceExpression, object data)
{
if (fieldReferenceExpression == null) {
@ -177,7 +200,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -177,7 +200,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
return null;
}
string name = resolver.SearchNamespace(identifierExpression.Identifier, resolver.CompilationUnit);
if (name != null && name != "") {
if (name != null && name.Length > 0) {
return new NamespaceReturnType(name);
}
IClass c = resolver.SearchType(identifierExpression.Identifier, resolver.CallingClass, resolver.CompilationUnit);
@ -337,6 +360,11 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -337,6 +360,11 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
return null;
}
List<IReturnType> CreateReturnType(List<TypeReference> references)
{
return references.ConvertAll<IReturnType>(new Converter<TypeReference, IReturnType>(CreateReturnType));
}
IReturnType CreateReturnType(TypeReference reference)
{
return CreateReturnType(reference, resolver);
@ -345,9 +373,16 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -345,9 +373,16 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
public static IReturnType CreateReturnType(TypeReference reference, NRefactoryResolver resolver)
{
if (reference.IsNull) return null;
IClass c = resolver.SearchType(reference.SystemType, resolver.CallingClass);
IClass callingClass = resolver.CallingClass;
IClass c = resolver.SearchType(reference.SystemType, callingClass);
if (c == null) return null;
IReturnType t = c.DefaultReturnType;
foreach (ITypeParameter tp in callingClass.TypeParameters) {
if (resolver.LanguageProperties.NameComparer.Equals(reference.SystemType, tp.Name)) {
t = new GenericReturnType(tp);
break;
}
}
if (reference.GenericTypes.Count > 0) {
List<IReturnType> para = new List<IReturnType>(reference.GenericTypes.Count);
for (int i = 0; i < reference.GenericTypes.Count; ++i) {
@ -361,7 +396,16 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -361,7 +396,16 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
public static IReturnType CreateReturnType(TypeReference reference, IClass callingClass, int caretLine, int caretColumn)
{
if (reference.IsNull) return null;
IReturnType t = new SearchClassReturnType(callingClass, caretLine, caretColumn, reference.SystemType);
IReturnType t = null;
foreach (ITypeParameter tp in callingClass.TypeParameters) {
if (tp.Name.Equals(reference.SystemType, StringComparison.InvariantCultureIgnoreCase)) {
t = new GenericReturnType(tp);
break;
}
}
if (t == null) {
t = new SearchClassReturnType(callingClass, caretLine, caretColumn, reference.SystemType);
}
if (reference.GenericTypes.Count > 0) {
List<IReturnType> para = new List<IReturnType>(reference.GenericTypes.Count);
for (int i = 0; i < reference.GenericTypes.Count; ++i) {

15
src/Main/Base/Test/GenericResolverTests.cs

@ -33,9 +33,11 @@ class TestClass { @@ -33,9 +33,11 @@ class TestClass {
}
T CloneIt<T>(T source) where T : ICloneable {
if (source == null) return new TestClass();
return source.Clone();
}
public int PublicField;
}
";
@ -95,5 +97,16 @@ class TestClass { @@ -95,5 +97,16 @@ class TestClass {
MemberResolveResult mrr = (MemberResolveResult) result;
Assert.AreEqual("TestClass.CloneIt", mrr.ResolvedMember.FullyQualifiedName);
}
[Test]
public void FieldReferenceOnGenericMethodTest()
{
ResolveResult result = Resolve(listProgram, "CloneIt<TestClass>(null).PublicField", 5);
Assert.IsNotNull(result);
Assert.IsTrue(result is MemberResolveResult);
Assert.AreEqual("System.Int32", result.ResolvedType.FullyQualifiedName);
MemberResolveResult mrr = (MemberResolveResult) result;
Assert.AreEqual("TestClass.PublicField", mrr.ResolvedMember.FullyQualifiedName);
}
}
}

5
src/Main/Base/Test/NRefactoryResolverTests.cs

@ -367,14 +367,15 @@ interface IInterface2 { @@ -367,14 +367,15 @@ interface IInterface2 {
[Test]
public void AnonymousMethodParameters()
{
string program = @"class A {
string program = @"using System;
class A {
void Method() {
SomeEvent += delegate(object sender, EventArgs e) {
};
} }
";
ResolveResult result = Resolve(program, "e", 4);
ResolveResult result = Resolve(program, "e", 5);
Assert.IsNotNull(result);
Assert.IsTrue(result is LocalResolveResult);
Assert.AreEqual("System.EventArgs", result.ResolvedType.FullyQualifiedName);

Loading…
Cancel
Save