Browse Source

Improved BooBinding:

Allow for code completion on ArrayReturnType and ConstructedReturnType even if they are encapsulated by an InferredReturnType.
Fixed code completion on arrays created through array literals or the "array" builtin.
Recognize variables created by "for" statements if their type is inferred from the element type of the enumerable object.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@610 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 20 years ago
parent
commit
e2d20525d9
  1. 1
      src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.csproj
  2. 17
      src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooAmbience.cs
  3. 16
      src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooResolver.cs
  4. 2
      src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs
  5. 64
      src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ElementReturnType.cs
  6. 66
      src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ResolveVisitor.cs
  7. 76
      src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/VariableLookupVisitor.cs
  8. 16
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpAmbience.cs
  9. 16
      src/AddIns/BackendBindings/VBNetBinding/Project/Src/VBNetAmbience.cs
  10. 2
      src/AddIns/Misc/NAntAddIn/Test/NAntAddIn.Tests.csproj
  11. 14
      src/Libraries/ICSharpCode.TextEditor/Test/ICSharpCode.TextEditor.Test.csproj.user
  12. 24
      src/Main/Base/Project/Src/Dom/IReturnType.cs
  13. 18
      src/Main/Base/Project/Src/Dom/Implementations/AbstractReturnType.cs
  14. 17
      src/Main/Base/Project/Src/Dom/Implementations/ArrayReturnType.cs
  15. 32
      src/Main/Base/Project/Src/Dom/Implementations/CombinedReturnType.cs
  16. 42
      src/Main/Base/Project/Src/Dom/Implementations/ConstructedReturnType.cs
  17. 21
      src/Main/Base/Project/Src/Dom/Implementations/ProxyReturnType.cs
  18. 76
      src/Main/Base/Project/Src/Dom/MemberLookupHelper.cs
  19. 27
      src/Main/Base/Project/Src/Dom/ReflectionLayer/DomPersistence.cs
  20. 12
      src/Main/Base/Project/Src/Services/RefactoringService/CodeGenerator.cs
  21. 1
      src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj
  22. 44
      src/Main/Base/Test/MemberLookupHelperTests.cs

1
src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.csproj

@ -83,6 +83,7 @@ @@ -83,6 +83,7 @@
<Compile Include="Src\Designer\FormDesignerBinding.cs" />
<Compile Include="Src\Designer\CodeDomVisitor.cs" />
<Compile Include="Src\BooCodeGenerator.cs" />
<Compile Include="Src\CodeCompletion\ElementReturnType.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="BooBinding.addin">

17
src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooAmbience.cs

@ -486,21 +486,20 @@ namespace Grunwald.BooBinding @@ -486,21 +486,20 @@ namespace Grunwald.BooBinding
void UnpackNestedType(StringBuilder builder, IReturnType returnType)
{
ArrayReturnType art = returnType as ArrayReturnType;
if (art != null) {
if (returnType.ArrayDimensions > 0) {
builder.Append('(');
UnpackNestedType(builder, art.ElementType);
for (int i = 1; i < art.ArrayDimensions; ++i) {
UnpackNestedType(builder, returnType.ArrayElementType);
if (returnType.ArrayDimensions > 1) {
builder.Append(',');
builder.Append(returnType.ArrayDimensions);
}
builder.Append(')');
} else if (returnType is ConstructedReturnType) {
ConstructedReturnType rt = (ConstructedReturnType)returnType;
UnpackNestedType(builder, rt.BaseType);
} else if (returnType.TypeArguments != null) {
UnpackNestedType(builder, returnType.UnboundType);
builder.Append("[of ");
for (int i = 0; i < rt.TypeArguments.Count; ++i) {
for (int i = 0; i < returnType.TypeArguments.Count; ++i) {
if (i > 0) builder.Append(", ");
builder.Append(Convert(rt.TypeArguments[i]));
builder.Append(Convert(returnType.TypeArguments[i]));
}
builder.Append(']');
} else {

16
src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooResolver.cs

@ -206,6 +206,10 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -206,6 +206,10 @@ namespace Grunwald.BooBinding.CodeCompletion
if (c != null)
return new TypeResolveResult(callingClass, callingMember, c);
}
string namespaceName = pc.SearchNamespace(name, callingClass, cu, caretLine, caretColumn);
if (namespaceName != null) {
return new NamespaceResolveResult(callingClass, callingMember, namespaceName);
}
return null;
} else {
if (expr.NodeType == AST.NodeType.ReferenceExpression) {
@ -285,21 +289,17 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -285,21 +289,17 @@ namespace Grunwald.BooBinding.CodeCompletion
NRResolver.AddContentsFromCalling(result, callingClass, callingMember);
ArrayList knownVariableNames = new ArrayList();
List<string> knownVariableNames = new List<string>();
foreach (object o in result) {
IMember m = o as IMember;
if (m != null) {
knownVariableNames.Add(m.Name);
}
}
VariableListLookupVisitor vllv = new VariableListLookupVisitor(knownVariableNames);
VariableListLookupVisitor vllv = new VariableListLookupVisitor(knownVariableNames, this);
vllv.Visit(GetCurrentBooMethod());
foreach (DictionaryEntry entry in vllv.Results) {
IReturnType type;
if (entry.Value is AST.TypeReference) {
type = ConvertType((AST.TypeReference)entry.Value);
result.Add(new DefaultField.LocalVariableField(type, (string)entry.Key, DomRegion.Empty, callingClass));
}
foreach (KeyValuePair<string, IReturnType> entry in vllv.Results) {
result.Add(new DefaultField.LocalVariableField(entry.Value, entry.Key, DomRegion.Empty, callingClass));
}
return result;

2
src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs

@ -203,7 +203,7 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -203,7 +203,7 @@ namespace Grunwald.BooBinding.CodeCompletion
AST.ArrayTypeReference arr = (AST.ArrayTypeReference)reference;
return new ArrayReturnType(CreateReturnType(arr.ElementType, callingClass, callingMember,
caretLine, caretColumn, projectContent, useLazyReturnType),
(int)arr.Rank.Value);
(arr.Rank != null) ? (int)arr.Rank.Value : 1);
} else if (reference is AST.SimpleTypeReference) {
string name = ((AST.SimpleTypeReference)reference).Name;
if (BooAmbience.ReverseTypeConversionTable.ContainsKey(name))

64
src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ElementReturnType.cs

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
/*
* Created by SharpDevelop.
* User: Daniel Grunwald
* Date: 22.10.2005
* Time: 19:19
*/
using System;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Dom;
namespace Grunwald.BooBinding.CodeCompletion
{
/// <summary>
/// The return type that is the element of an enumerable.
/// Used to infer the type in "for x in enumerableVariable" loops.
/// </summary>
public class ElementReturnType : ProxyReturnType
{
IReturnType listType;
public ElementReturnType(IReturnType listType)
{
// listType is probably an InferredReturnType
this.listType = listType;
}
public override IReturnType BaseType {
get {
// get element type from listType
if (listType.ArrayDimensions > 0)
return listType.ArrayElementType;
IClass c = listType.GetUnderlyingClass();
if (c == null)
return null;
IClass genumerable = ProjectContentRegistry.Mscorlib.GetClass("System.Collections.Generic.IEnumerable", 1);
if (c.IsTypeInInheritanceTree(genumerable)) {
return MemberLookupHelper.GetTypeParameterPassedToBaseClass(listType, genumerable, 0);
}
IClass enumerable = ProjectContentRegistry.Mscorlib.GetClass("System.Collections.IEnumerable", 0);
if (c.IsTypeInInheritanceTree(enumerable)) {
// We can't use the EnumeratorItemType attribute because SharpDevelop
// does not store attribute argument values in the cache.
// HACK: Hacked in support for range(), take out when RangeEnumerator implements IEnumerable<int>
if (c.FullyQualifiedName == "Boo.Lang.Builtins.RangeEnumerator") {
return ReflectionReturnType.Int;
}
return ReflectionReturnType.Object;
}
return null;
}
}
public override bool IsDefaultReturnType {
get {
IReturnType baseType = BaseType;
return (baseType != null) ? baseType.IsDefaultReturnType : false;
}
}
}
}

66
src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ResolveVisitor.cs

@ -293,24 +293,17 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -293,24 +293,17 @@ namespace Grunwald.BooBinding.CodeCompletion
string methodName = ((MethodResolveResult)resolveResult).Name;
IReturnType containingType = ((MethodResolveResult)resolveResult).ContainingType;
List<IMethod> methods = new List<IMethod>();
bool isClassInInheritanceTree = false;
if (callingClass != null)
isClassInInheritanceTree = callingClass.IsTypeInInheritanceTree(containingType.GetUnderlyingClass());
foreach (IMethod m in containingType.GetMethods()) {
if (IsSameName(m.Name, methodName)
&& m.IsAccessible(callingClass, isClassInInheritanceTree)
) {
methods.Add(m);
}
}
ResolveInvocation(methods, node.Arguments);
ResolveMethodInType(containingType, methodName, node.Arguments);
} else if (resolveResult is TypeResolveResult || resolveResult is MixedResolveResult) {
TypeResolveResult trr = resolveResult as TypeResolveResult;
if (trr == null)
trr = (resolveResult as MixedResolveResult).TypeResult;
if (trr != null && trr.ResolvedClass != null) {
if (trr.ResolvedClass.FullyQualifiedName == "array") {
ResolveArrayCreation(node.Arguments);
return;
}
List<IMethod> methods = new List<IMethod>();
bool isClassInInheritanceTree = false;
if (callingClass != null)
@ -353,6 +346,38 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -353,6 +346,38 @@ namespace Grunwald.BooBinding.CodeCompletion
}
}
void ResolveArrayCreation(ExpressionCollection arguments)
{
if (arguments.Count == 2) {
ClearResult();
arguments[0].Accept(this);
TypeResolveResult trr = resolveResult as TypeResolveResult;
if (trr != null) {
MakeResult(new ArrayReturnType(trr.ResolvedType, 1));
}
} else {
ResolveMethodInType(new GetClassReturnType(projectContent, "Boo.Lang.Builtins", 0),
"array", arguments);
}
}
void ResolveMethodInType(IReturnType containingType, string methodName, ExpressionCollection arguments)
{
List<IMethod> methods = new List<IMethod>();
bool isClassInInheritanceTree = false;
if (callingClass != null)
isClassInInheritanceTree = callingClass.IsTypeInInheritanceTree(containingType.GetUnderlyingClass());
foreach (IMethod m in containingType.GetMethods()) {
if (IsSameName(m.Name, methodName)
&& m.IsAccessible(callingClass, isClassInInheritanceTree)
) {
methods.Add(m);
}
}
ResolveInvocation(methods, arguments);
}
void ResolveInvocation(List<IMethod> methods, ExpressionCollection arguments)
{
ClearResult();
@ -471,8 +496,19 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -471,8 +496,19 @@ namespace Grunwald.BooBinding.CodeCompletion
public override void OnArrayLiteralExpression(ArrayLiteralExpression node)
{
// TODO: get real array type
MakeLiteralResult("System.Array");
IReturnType elementType = null;
foreach (Expression expr in node.Items) {
ClearResult();
node.Items[0].Accept(this);
IReturnType thisType = (resolveResult != null) ? resolveResult.ResolvedType : null;
if (elementType == null)
elementType = thisType;
else if (thisType != null)
elementType = MemberLookupHelper.GetCommonType(elementType, thisType);
}
if (elementType == null)
elementType = ReflectionReturnType.Object;
MakeResult(new ArrayReturnType(elementType, 1));
}
public override void OnAsExpression(AsExpression node)

76
src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/VariableLookupVisitor.cs

@ -6,7 +6,8 @@ @@ -6,7 +6,8 @@
// </file>
using System;
using System.Collections;
using System.Collections.Generic;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Dom;
using Boo.Lang.Compiler.Ast;
@ -36,13 +37,16 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -36,13 +37,16 @@ namespace Grunwald.BooBinding.CodeCompletion
}
}
private void InferResult(Expression expr, string name, LexicalInfo lexicalInfo)
private void InferResult(Expression expr, string name, LexicalInfo lexicalInfo, bool useElementType)
{
if (expr == null)
return;
if (result != null)
return;
result = new DefaultField.LocalVariableField(new InferredReturnType(expr), name,
IReturnType returnType = new InferredReturnType(expr);
if (useElementType)
returnType = new ElementReturnType(returnType);
result = new DefaultField.LocalVariableField(returnType, name,
new DomRegion(lexicalInfo.Line, lexicalInfo.Column),
resolver.CallingClass);
}
@ -65,10 +69,15 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -65,10 +69,15 @@ namespace Grunwald.BooBinding.CodeCompletion
{
if (node.Declaration.Name == lookFor) {
Visit(node.Declaration);
InferResult(node.Initializer, node.Declaration.Name, node.LexicalInfo);
InferResult(node.Initializer, node.Declaration.Name, node.LexicalInfo, false);
}
}
protected override void OnError(Node node, Exception error)
{
MessageService.ShowError(error, "VariableLookupVisitor: error processing " + node);
}
public override void OnBinaryExpression(BinaryExpression node)
{
if (acceptImplicit) {
@ -76,13 +85,29 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -76,13 +85,29 @@ namespace Grunwald.BooBinding.CodeCompletion
if (node.Operator == BinaryOperatorType.Assign && reference != null) {
if (!(reference is MemberReferenceExpression)) {
if (reference.Name == lookFor) {
InferResult(node.Right, reference.Name, reference.LexicalInfo);
InferResult(node.Right, reference.Name, reference.LexicalInfo, false);
}
}
}
}
base.OnBinaryExpression(node);
}
public override void OnForStatement(ForStatement node)
{
if (node.LexicalInfo.Line > resolver.CaretLine || node.Block.EndSourceLocation.Line < resolver.CaretLine)
return;
if (node.Declarations.Count != 1) {
// TODO: support unpacking
base.OnForStatement(node);
return;
}
if (node.Declarations[0].Name == lookFor) {
Visit(node.Declarations[0]);
InferResult(node.Iterator, node.Declarations[0].Name, node.LexicalInfo, true);
}
}
}
/// <summary>
@ -91,28 +116,33 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -91,28 +116,33 @@ namespace Grunwald.BooBinding.CodeCompletion
/// </summary>
public class VariableListLookupVisitor : DepthFirstVisitor
{
ArrayList knownVariableNames;
List<string> knownVariableNames;
BooResolver resolver;
public VariableListLookupVisitor(ArrayList knownVariableNames)
public VariableListLookupVisitor(List<string> knownVariableNames, BooResolver resolver)
{
this.knownVariableNames = knownVariableNames;
this.resolver = resolver;
}
Hashtable results = new Hashtable();
Dictionary<string, IReturnType> results = new Dictionary<string, IReturnType>();
public Hashtable Results {
public Dictionary<string, IReturnType> Results {
get {
return results;
}
}
private void Add(string name, Expression expr)
private void Add(string name, Expression expr, bool elementReturnType)
{
if (name == null || expr == null)
return;
if (results.ContainsKey(name))
return;
results.Add(name, expr);
if (elementReturnType)
results.Add(name, new ElementReturnType(new InferredReturnType(expr)));
else
results.Add(name, new InferredReturnType(expr));
}
private void Add(string name, TypeReference reference)
@ -121,7 +151,7 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -121,7 +151,7 @@ namespace Grunwald.BooBinding.CodeCompletion
return;
if (results.ContainsKey(name))
return;
results.Add(name, reference);
results.Add(name, resolver.ConvertType(reference));
}
public override void OnDeclaration(Declaration node)
@ -132,7 +162,12 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -132,7 +162,12 @@ namespace Grunwald.BooBinding.CodeCompletion
public override void OnDeclarationStatement(DeclarationStatement node)
{
Visit(node.Declaration);
Add(node.Declaration.Name, node.Initializer);
Add(node.Declaration.Name, node.Initializer, false);
}
protected override void OnError(Node node, Exception error)
{
MessageService.ShowError(error, "VariableListLookupVisitor: error processing " + node);
}
public override void OnBinaryExpression(BinaryExpression node)
@ -142,12 +177,25 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -142,12 +177,25 @@ namespace Grunwald.BooBinding.CodeCompletion
if (node.Operator == BinaryOperatorType.Assign && reference != null) {
if (!(reference is MemberReferenceExpression)) {
if (!knownVariableNames.Contains(reference.Name)) {
Add(reference.Name, node.Right);
Add(reference.Name, node.Right, false);
}
}
}
}
base.OnBinaryExpression(node);
}
public override void OnForStatement(ForStatement node)
{
if (node.LexicalInfo.Line > resolver.CaretLine || node.Block.EndSourceLocation.Line < resolver.CaretLine)
return;
if (node.Declarations.Count != 1) {
// TODO: support unpacking
base.OnForStatement(node);
return;
}
Add(node.Declarations[0].Name, node.Iterator, true);
}
}
}

16
src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpAmbience.cs

@ -491,21 +491,19 @@ namespace ICSharpCode.Core @@ -491,21 +491,19 @@ namespace ICSharpCode.Core
void UnpackNestedType(StringBuilder builder, IReturnType returnType)
{
ArrayReturnType art = returnType as ArrayReturnType;
if (art != null) {
if (returnType.ArrayDimensions > 0) {
builder.Append('[');
for (int i = 1; i < art.ArrayDimensions; ++i) {
for (int i = 1; i < returnType.ArrayDimensions; ++i) {
builder.Append(',');
}
builder.Append(']');
UnpackNestedType(builder, art.ElementType);
} else if (returnType is ConstructedReturnType) {
ConstructedReturnType rt = (ConstructedReturnType)returnType;
UnpackNestedType(builder, rt.BaseType);
UnpackNestedType(builder, returnType.ArrayElementType);
} else if (returnType.TypeArguments != null) {
UnpackNestedType(builder, returnType.UnboundType);
builder.Append('<');
for (int i = 0; i < rt.TypeArguments.Count; ++i) {
for (int i = 0; i < returnType.TypeArguments.Count; ++i) {
if (i > 0) builder.Append(", ");
builder.Append(Convert(rt.TypeArguments[i]));
builder.Append(Convert(returnType.TypeArguments[i]));
}
builder.Append('>');
}

16
src/AddIns/BackendBindings/VBNetBinding/Project/Src/VBNetAmbience.cs

@ -493,21 +493,19 @@ namespace VBNetBinding @@ -493,21 +493,19 @@ namespace VBNetBinding
void UnpackNestedType(StringBuilder builder, IReturnType returnType)
{
ArrayReturnType art = returnType as ArrayReturnType;
if (art != null) {
if (returnType.ArrayDimensions > 0) {
builder.Append('(');
for (int i = 1; i < art.ArrayDimensions; ++i) {
for (int i = 1; i < returnType.ArrayDimensions; ++i) {
builder.Append(',');
}
builder.Append(')');
UnpackNestedType(builder, art.ElementType);
} else if (returnType is ConstructedReturnType) {
ConstructedReturnType rt = (ConstructedReturnType)returnType;
UnpackNestedType(builder, rt.BaseType);
UnpackNestedType(builder, returnType.ArrayElementType);
} else if (returnType.TypeArguments != null) {
UnpackNestedType(builder, returnType.UnboundType);
builder.Append("(Of ");
for (int i = 0; i < rt.TypeArguments.Count; ++i) {
for (int i = 0; i < returnType.TypeArguments.Count; ++i) {
if (i > 0) builder.Append(", ");
builder.Append(Convert(rt.TypeArguments[i]));
builder.Append(Convert(returnType.TypeArguments[i]));
}
builder.Append(')');
}

2
src/AddIns/Misc/NAntAddIn/Test/NAntAddIn.Tests.csproj

@ -39,7 +39,7 @@ @@ -39,7 +39,7 @@
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="nunit.framework, Version=2.2.0.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77" />
<Reference Include="nunit.framework" />
<Reference Include="ICSharpCode.SharpDevelop">
<HintPath>..\..\..\..\..\bin\ICSharpCode.SharpDevelop.dll</HintPath>
<SpecificVersion>False</SpecificVersion>

14
src/Libraries/ICSharpCode.TextEditor/Test/ICSharpCode.TextEditor.Test.csproj.user

@ -1,16 +1,4 @@ @@ -1,16 +1,4 @@
<Project DefaultTargets="Build" xmlns:Conversion="urn:Conversion" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<StartProgram>
</StartProgram>
<StartArguments>
</StartArguments>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<StartProgram>
</StartProgram>
<StartArguments>
</StartArguments>
</PropertyGroup>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<LastOpenVersion>8.0.41115</LastOpenVersion>
<ProjectView>ProjectFiles</ProjectView>

24
src/Main/Base/Project/Src/Dom/IReturnType.cs

@ -70,6 +70,14 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -70,6 +70,14 @@ namespace ICSharpCode.SharpDevelop.Dom
get;
}
/// <summary>
/// Gets the element type of the array.
/// When the return type is not an array, a NotSupportedException is thrown.
/// </summary>
IReturnType ArrayElementType {
get;
}
/// <summary>
/// Gets the count of type parameters the target class should have.
/// </summary>
@ -88,6 +96,22 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -88,6 +96,22 @@ namespace ICSharpCode.SharpDevelop.Dom
get;
}
/// <summary>
/// Gets the type arguments used if this is a ConstructedReturnType.
/// Otherwise, null is returned.
/// </summary>
IList<IReturnType> TypeArguments {
get;
}
/// <summary>
/// Gets the unbound type if this is a ConstructedReturnType.
/// Otherwise, a NotSupportedException is thrown.
/// </summary>
IReturnType UnboundType {
get;
}
/// <summary>
/// Gets the underlying class of this return type.
/// </summary>

18
src/Main/Base/Project/Src/Dom/Implementations/AbstractReturnType.cs

@ -91,5 +91,23 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -91,5 +91,23 @@ namespace ICSharpCode.SharpDevelop.Dom
return true;
}
}
public IReturnType ArrayElementType {
get {
throw new NotSupportedException();
}
}
public IReturnType UnboundType {
get {
throw new NotSupportedException();
}
}
public IList<IReturnType> TypeArguments {
get {
return null;
}
}
}
}

17
src/Main/Base/Project/Src/Dom/Implementations/ArrayReturnType.cs

@ -33,7 +33,22 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -33,7 +33,22 @@ namespace ICSharpCode.SharpDevelop.Dom
this.dimensions = dimensions;
}
public IReturnType ElementType {
public override bool Equals(object o)
{
IReturnType rt = o as IReturnType;
if (rt == null) return false;
if (rt.ArrayDimensions != dimensions) return false;
return elementType.Equals(rt.ArrayElementType);
}
public override int GetHashCode()
{
unchecked {
return 2 * elementType.GetHashCode() + 27 * dimensions;
}
}
public override IReturnType ArrayElementType {
get {
return elementType;
}

32
src/Main/Base/Project/Src/Dom/Implementations/CombinedReturnType.cs

@ -12,9 +12,9 @@ using ICSharpCode.Core; @@ -12,9 +12,9 @@ using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop.Dom
{
/// <summary>
/// Combines multiple return types.
/// Combines multiple return types for use in contraints.
/// </summary>
public sealed class CombinedReturnType : IReturnType
public sealed class CombinedReturnType : AbstractReturnType
{
IList<IReturnType> baseTypes;
@ -93,69 +93,63 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -93,69 +93,63 @@ namespace ICSharpCode.SharpDevelop.Dom
return list;
}
public List<IMethod> GetMethods()
public override List<IMethod> GetMethods()
{
return Combine<IMethod>(delegate(IReturnType type) { return type.GetMethods(); });
}
public List<IProperty> GetProperties()
public override List<IProperty> GetProperties()
{
return Combine<IProperty>(delegate(IReturnType type) { return type.GetProperties(); });
}
public List<IField> GetFields()
public override List<IField> GetFields()
{
return Combine<IField>(delegate(IReturnType type) { return type.GetFields(); });
}
public List<IEvent> GetEvents()
public override List<IEvent> GetEvents()
{
return Combine<IEvent>(delegate(IReturnType type) { return type.GetEvents(); });
}
public string FullyQualifiedName {
public override string FullyQualifiedName {
get {
return fullName;
}
}
public string Name {
public override string Name {
get {
return name;
}
}
public string Namespace {
public override string Namespace {
get {
return @namespace;
}
}
public string DotNetName {
public override string DotNetName {
get {
return dotnetName;
}
}
public int ArrayDimensions {
get {
return 0;
}
}
public bool IsDefaultReturnType {
public override bool IsDefaultReturnType {
get {
return false;
}
}
public int TypeParameterCount {
public override int TypeParameterCount {
get {
return 0;
}
}
public IClass GetUnderlyingClass()
public override IClass GetUnderlyingClass()
{
return null;
}

42
src/Main/Base/Project/Src/Dom/Implementations/ConstructedReturnType.cs

@ -27,7 +27,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -27,7 +27,7 @@ namespace ICSharpCode.SharpDevelop.Dom
IList<IReturnType> typeParameters;
IReturnType baseType;
public IList<IReturnType> TypeArguments {
public override IList<IReturnType> TypeArguments {
get {
return typeParameters;
}
@ -45,14 +45,9 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -45,14 +45,9 @@ namespace ICSharpCode.SharpDevelop.Dom
public override bool Equals(object o)
{
ConstructedReturnType rt = o as ConstructedReturnType;
IReturnType rt = o as IReturnType;
if (rt == null) return false;
if (!baseType.Equals(rt.baseType)) return false;
if (typeParameters.Count != rt.typeParameters.Count) return false;
for (int i = 0; i < typeParameters.Count; ++i) {
if (!object.Equals(typeParameters[i], rt.typeParameters[i])) return false;
}
return true;
return this.DotNetName == rt.DotNetName;
}
public override int GetHashCode()
@ -70,15 +65,21 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -70,15 +65,21 @@ namespace ICSharpCode.SharpDevelop.Dom
}
}
public override IReturnType UnboundType {
get {
return baseType;
}
}
bool CheckReturnType(IReturnType t)
{
if (t is GenericReturnType) {
GenericReturnType rt = (GenericReturnType)t;
return rt.TypeParameter.Method == null;
} else if (t is ArrayReturnType) {
return CheckReturnType(((ArrayReturnType)t).ElementType);
} else if (t is ConstructedReturnType) {
foreach (IReturnType para in ((ConstructedReturnType)t).TypeArguments) {
} else if (t.ArrayDimensions > 0) {
return CheckReturnType(t.ArrayElementType);
} else if (t.TypeArguments != null) {
foreach (IReturnType para in t.TypeArguments) {
if (CheckReturnType(para)) return true;
}
return false;
@ -129,18 +130,17 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -129,18 +130,17 @@ namespace ICSharpCode.SharpDevelop.Dom
}
}
}
} else if (input is ArrayReturnType) {
IReturnType e = ((ArrayReturnType)input).ElementType;
} else if (input.ArrayDimensions > 0) {
IReturnType e = input.ArrayElementType;
IReturnType t = TranslateType(e, typeParameters, convertForMethod);
if (e != t && t != null)
return new ArrayReturnType(t, input.ArrayDimensions);
} else if (input is ConstructedReturnType) {
ConstructedReturnType r = (ConstructedReturnType)input;
List<IReturnType> para = new List<IReturnType>(r.TypeArguments.Count);
for (int i = 0; i < r.TypeArguments.Count; ++i) {
para.Add(TranslateType(r.TypeArguments[i], typeParameters, convertForMethod));
} else if (input.TypeArguments != null) {
List<IReturnType> para = new List<IReturnType>(input.TypeArguments.Count);
foreach (IReturnType argument in input.TypeArguments) {
para.Add(TranslateType(argument, typeParameters, convertForMethod));
}
return new ConstructedReturnType(r.baseType, para);
return new ConstructedReturnType(input.UnboundType, para);
}
return input;
}
@ -212,7 +212,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -212,7 +212,7 @@ namespace ICSharpCode.SharpDevelop.Dom
public override string ToString()
{
string r = "[SpecificReturnType: ";
string r = "[ConstructedReturnType: ";
r += baseType;
r += "<";
for (int i = 0; i < typeParameters.Count; i++) {

21
src/Main/Base/Project/Src/Dom/Implementations/ProxyReturnType.cs

@ -66,6 +66,27 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -66,6 +66,27 @@ namespace ICSharpCode.SharpDevelop.Dom
}
}
public virtual IReturnType ArrayElementType {
get {
IReturnType baseType = BaseType;
return (baseType != null) ? baseType.ArrayElementType : null;
}
}
public virtual IReturnType UnboundType {
get {
IReturnType baseType = BaseType;
return (baseType != null) ? baseType.UnboundType : null;
}
}
public virtual IList<IReturnType> TypeArguments {
get {
IReturnType baseType = BaseType;
return (baseType != null) ? baseType.TypeArguments : null;
}
}
/// <summary>
/// Gets the underlying class of this return type.
/// </summary>

76
src/Main/Base/Project/Src/Dom/MemberLookupHelper.cs

@ -241,8 +241,8 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -241,8 +241,8 @@ namespace ICSharpCode.SharpDevelop.Dom
if (j < parameters.Count) {
IParameter parameter = parameters[j];
if (parameter.IsParams && needToExpand[i]) {
if (parameter.ReturnType is ArrayReturnType) {
paramsType = ((ArrayReturnType)parameter.ReturnType).ElementType;
if (parameter.ReturnType.ArrayDimensions > 0) {
paramsType = parameter.ReturnType.ArrayElementType;
paramsType = ConstructedReturnType.TranslateType(paramsType, typeParameters, true);
}
expandedParameters[i][j] = paramsType;
@ -347,14 +347,17 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -347,14 +347,17 @@ namespace ICSharpCode.SharpDevelop.Dom
static int GetMoreSpecific(IReturnType r, IReturnType s)
{
if (r == null && s == null) return 0;
if (r == null) return 2;
if (s == null) return 1;
if (r is GenericReturnType && !(s is GenericReturnType))
return 2;
if (s is GenericReturnType && !(r is GenericReturnType))
return 1;
if (r is ArrayReturnType && s is ArrayReturnType)
return GetMoreSpecific(((ArrayReturnType)r).ElementType, ((ArrayReturnType)s).ElementType);
if (r is ConstructedReturnType && s is ConstructedReturnType)
return GetMoreSpecific(((ConstructedReturnType)r).TypeArguments, ((ConstructedReturnType)s).TypeArguments);
if (r.ArrayDimensions > 0 && s.ArrayDimensions > 0)
return GetMoreSpecific(r.ArrayElementType, s.ArrayElementType);
if (r.TypeArguments != null && s.TypeArguments != null)
return GetMoreSpecific(r.TypeArguments, s.TypeArguments);
return 0;
}
#endregion
@ -372,11 +375,8 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -372,11 +375,8 @@ namespace ICSharpCode.SharpDevelop.Dom
break;
if (!InferTypeArgument(parameters[i].ReturnType, arguments[i], result)) {
// inferring failed: maybe this is a params parameter that must be expanded?
if (parameters[i].IsParams) {
ArrayReturnType art = parameters[i].ReturnType as ArrayReturnType;
if (art != null) {
InferTypeArgument(art.ElementType, arguments[i], result);
}
if (parameters[i].IsParams && parameters[i].ReturnType.ArrayDimensions == 1) {
InferTypeArgument(parameters[i].ReturnType.ArrayElementType, arguments[i], result);
}
}
}
@ -392,16 +392,15 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -392,16 +392,15 @@ namespace ICSharpCode.SharpDevelop.Dom
static bool InferTypeArgument(IReturnType expectedArgument, IReturnType passedArgument, IReturnType[] outputArray)
{
if (passedArgument == null) return true; // TODO: NullTypeReference
ArrayReturnType ea = expectedArgument as ArrayReturnType;
if (ea != null) {
if (passedArgument is ArrayReturnType && ea.ArrayDimensions == passedArgument.ArrayDimensions) {
return InferTypeArgument(ea.ElementType, ((ArrayReturnType)passedArgument).ElementType, outputArray);
} else if (passedArgument is ConstructedReturnType) {
if (expectedArgument != null && expectedArgument.ArrayDimensions > 0) {
if (expectedArgument.ArrayDimensions == passedArgument.ArrayDimensions) {
return InferTypeArgument(expectedArgument.ArrayElementType, passedArgument.ArrayElementType, outputArray);
} else if (passedArgument.TypeArguments != null) {
switch (passedArgument.FullyQualifiedName) {
case "System.Collections.Generic.IList":
case "System.Collections.Generic.ICollection":
case "System.Collections.Generic.IEnumerable":
return InferTypeArgument(ea.ElementType, ((ConstructedReturnType)passedArgument).TypeArguments[0], outputArray);
return InferTypeArgument(expectedArgument.ArrayElementType, passedArgument.TypeArguments[0], outputArray);
}
}
// If P is an array type, and A is not an array type of the same rank,
@ -416,15 +415,13 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -416,15 +415,13 @@ namespace ICSharpCode.SharpDevelop.Dom
}
return true;
}
ConstructedReturnType constructed = expectedArgument as ConstructedReturnType;
if (constructed != null) {
if (expectedArgument.TypeArguments != null) {
// The spec for this case is quite complex.
// For our purposes, we can simplify enourmously:
ConstructedReturnType passed = passedArgument as ConstructedReturnType;
if (passed == null) return false;
int count = Math.Min(constructed.TypeArguments.Count, passed.TypeArguments.Count);
if (passedArgument.TypeArguments == null) return false;
int count = Math.Min(expectedArgument.TypeArguments.Count, passedArgument.TypeArguments.Count);
for (int i = 0; i < count; i++) {
InferTypeArgument(constructed.TypeArguments[i], passed.TypeArguments[i], outputArray);
InferTypeArgument(expectedArgument.TypeArguments[i], passedArgument.TypeArguments[i], outputArray);
}
}
return true;
@ -476,12 +473,12 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -476,12 +473,12 @@ namespace ICSharpCode.SharpDevelop.Dom
score++;
// - all additional parameters must be applicable to the unpacked array
ArrayReturnType rt = parameters[lastParameter].ReturnType as ArrayReturnType;
if (rt == null) {
IReturnType rt = parameters[lastParameter].ReturnType;
if (rt == null || rt.ArrayDimensions == 0) {
return false;
}
for (int i = lastParameter; i < arguments.Length; i++) {
if (IsApplicable(arguments[i], rt.ElementType)) {
if (IsApplicable(arguments[i], rt.ArrayElementType)) {
score++;
} else {
ok = false;
@ -558,9 +555,9 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -558,9 +555,9 @@ namespace ICSharpCode.SharpDevelop.Dom
return true;
}
}
if (from is ArrayReturnType && to is ArrayReturnType && from.ArrayDimensions == to.ArrayDimensions) {
if (from.ArrayDimensions > 0 && from.ArrayDimensions == to.ArrayDimensions) {
// from array to other array type
return ConversionExists((from as ArrayReturnType).ElementType, (to as ArrayReturnType).ElementType);
return ConversionExists(from.ArrayElementType, to.ArrayElementType);
}
return false;
}
@ -685,5 +682,28 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -685,5 +682,28 @@ namespace ICSharpCode.SharpDevelop.Dom
return a;
return ReflectionReturnType.Object;
}
/// <summary>
/// Gets the type parameter that was passed to a certain base class.
/// For example, when <paramref name="returnType"/> is Dictionary(of string, int)
/// this method will return KeyValuePair(of string, int)
/// </summary>
public static IReturnType GetTypeParameterPassedToBaseClass(IReturnType returnType, IClass baseClass, int baseClassTypeParameterIndex)
{
IClass c = returnType.GetUnderlyingClass();
if (c == null) return null;
foreach (IReturnType baseType in c.BaseTypes) {
if (baseClass.CompareTo(baseType.GetUnderlyingClass()) == 0) {
if (baseType.TypeArguments == null || baseClassTypeParameterIndex >= baseType.TypeArguments.Count)
return null;
IReturnType result = baseType.TypeArguments[baseClassTypeParameterIndex];
if (returnType.TypeArguments != null) {
result = ConstructedReturnType.TranslateType(result, returnType.TypeArguments, false);
}
return result;
}
}
return null;
}
}
}

27
src/Main/Base/Project/Src/Dom/ReflectionLayer/DomPersistence.cs

@ -526,12 +526,11 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -526,12 +526,11 @@ namespace ICSharpCode.SharpDevelop.Dom
classIndices.Add(pair, externalTypes.Count + classCount);
externalTypes.Add(pair);
}
} else if (rt is ArrayReturnType) {
AddExternalType(((ArrayReturnType)rt).ElementType, externalTypes, classCount);
} else if (rt is ConstructedReturnType) {
ConstructedReturnType crt = (ConstructedReturnType)rt;
AddExternalType(crt.BaseType, externalTypes, classCount);
foreach (IReturnType typeArgument in crt.TypeArguments) {
} else if (rt.ArrayDimensions > 0) {
AddExternalType(rt.ArrayElementType, externalTypes, classCount);
} else if (rt.TypeArguments != null) {
AddExternalType(rt.UnboundType, externalTypes, classCount);
foreach (IReturnType typeArgument in rt.TypeArguments) {
AddExternalType(typeArgument, externalTypes, classCount);
}
} else if (rt is GenericReturnType) {
@ -561,17 +560,15 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -561,17 +560,15 @@ namespace ICSharpCode.SharpDevelop.Dom
} else {
writer.Write(classIndices[new ClassNameTypeCountPair(rt)]);
}
} else if (rt is ArrayReturnType) {
ArrayReturnType art = (ArrayReturnType)rt;
} else if (rt.ArrayDimensions > 0) {
writer.Write(ArrayRTCode);
writer.Write(art.ArrayDimensions);
WriteType(art.ElementType);
} else if (rt is ConstructedReturnType) {
ConstructedReturnType crt = (ConstructedReturnType)rt;
writer.Write(rt.ArrayDimensions);
WriteType(rt.ArrayElementType);
} else if (rt.TypeArguments != null) {
writer.Write(ConstructedRTCode);
WriteType(crt.BaseType);
writer.Write((byte)crt.TypeArguments.Count);
foreach (IReturnType typeArgument in crt.TypeArguments) {
WriteType(rt.UnboundType);
writer.Write((byte)rt.TypeArguments.Count);
foreach (IReturnType typeArgument in rt.TypeArguments) {
WriteType(typeArgument);
}
} else if (rt is GenericReturnType) {

12
src/Main/Base/Project/Src/Services/RefactoringService/CodeGenerator.cs

@ -24,17 +24,15 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -24,17 +24,15 @@ namespace ICSharpCode.SharpDevelop.Refactoring
if (returnType is NullReturnType) return TypeReference.Null;
TypeReference typeRef = new TypeReference(returnType.FullyQualifiedName);
while (returnType is ArrayReturnType) {
ArrayReturnType art = (ArrayReturnType)returnType;
while (returnType.ArrayDimensions > 0) {
int[] rank = typeRef.RankSpecifier ?? new int[0];
Array.Resize(ref rank, rank.Length + 1);
rank[rank.Length - 1] = art.ArrayDimensions;
rank[rank.Length - 1] = returnType.ArrayDimensions;
typeRef.RankSpecifier = rank;
returnType = art.ElementType;
returnType = returnType.ArrayElementType;
}
if (returnType is ConstructedReturnType) {
ConstructedReturnType rt = (ConstructedReturnType)returnType;
foreach (IReturnType typeArgument in rt.TypeArguments) {
if (returnType.TypeArguments != null) {
foreach (IReturnType typeArgument in returnType.TypeArguments) {
typeRef.GenericTypes.Add(ConvertType(typeArgument));
}
}

1
src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj

@ -51,6 +51,7 @@ @@ -51,6 +51,7 @@
<Compile Include="SearchClassTests.cs" />
<Compile Include="OverloadFinding.cs" />
<Compile Include="SearchGenericClassTests.cs" />
<Compile Include="MemberLookupHelperTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Project\ICSharpCode.SharpDevelop.csproj">

44
src/Main/Base/Test/MemberLookupHelperTests.cs

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
// <file>
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
// <license see="prj:///doc/license.txt">GNU General Public License</license>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using NUnit.Framework;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Dom;
namespace ICSharpCode.SharpDevelop.Tests
{
[TestFixture]
public class MemberLookupHelperTests
{
IProjectContent msc = ProjectContentRegistry.Mscorlib;
public IReturnType DictionaryRT {
get {
return new GetClassReturnType(msc, "System.Collections.Generic.Dictionary", 2);
}
}
public IClass EnumerableClass {
get {
return msc.GetClass("System.Collections.Generic.IEnumerable", 1);
}
}
[Test]
public void TypeParameterPassedToBaseClassTest()
{
IReturnType[] stringInt = { ReflectionReturnType.String, ReflectionReturnType.Int };
IReturnType rrt = new ConstructedReturnType(DictionaryRT, stringInt);
IReturnType res = MemberLookupHelper.GetTypeParameterPassedToBaseClass(rrt, EnumerableClass, 0);
Assert.AreEqual("System.Collections.Generic.KeyValuePair", res.FullyQualifiedName);
Assert.AreEqual("System.String", res.TypeArguments[0].FullyQualifiedName);
Assert.AreEqual("System.Int32", res.TypeArguments[1].FullyQualifiedName);
}
}
}
Loading…
Cancel
Save