Browse Source

Merge remote-tracking branch 'upstream/master' into mansheng

newNRvisualizers
Mansheng Yang 14 years ago
parent
commit
ad46ffdd49
  1. 17
      ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs
  2. 13
      ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs
  3. 12
      ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs
  4. 2
      ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs
  5. 5
      ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs
  6. 7
      ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-tokenizer.cs
  7. 1
      ICSharpCode.NRefactory.CSharp/Parser/mcs/driver.cs
  8. 8
      ICSharpCode.NRefactory.CSharp/Parser/mcs/namespace.cs
  9. 63
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ImplementAbstractMembersAction.cs
  10. 156
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ImplementInterfaceAction.cs
  11. 4
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpConversions.cs
  12. 8
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs
  13. 19
      ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs
  14. 1
      ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs
  15. 10
      ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ImplementAbstractMembersTest.cs
  16. 8
      ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ImplementInterfaceTests.cs
  17. 2
      ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs
  18. 22
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs
  19. 117
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs
  20. 24
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs
  21. 2
      ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs
  22. 61
      ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs
  23. 6
      ICSharpCode.NRefactory/TypeSystem/IAssembly.cs
  24. 5
      ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs
  25. 25
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedMethod.cs
  26. 11
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs
  27. 3
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs

17
ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs

@ -62,12 +62,29 @@ namespace ICSharpCode.NRefactory.CSharp
get { return GetChildrenByRole(MemberRole); } get { return GetChildrenByRole(MemberRole); }
} }
string[] conditionals = null;
List<Error> errors = new List<Error> (); List<Error> errors = new List<Error> ();
public List<Error> Errors { public List<Error> Errors {
get { return errors; } get { return errors; }
} }
/// <summary>
/// Gets the conditional symbols used to parse the source file. Note that this list contains
/// the conditional symbols at the start of the first token in the file - including the ones defined
/// in the source file.
/// </summary>
public string[] Conditionals {
get {
return conditionals ?? new string[0];
}
internal set {
conditionals = value;
}
}
/// <summary> /// <summary>
/// Gets the expression that was on top of the parse stack. /// Gets the expression that was on top of the parse stack.
/// This is the only way to get an expression that isn't part of a statment. /// This is the only way to get an expression that isn't part of a statment.

13
ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs

@ -31,6 +31,7 @@ namespace ICSharpCode.NRefactory.CSharp
public class CSharpProjectContent : IProjectContent public class CSharpProjectContent : IProjectContent
{ {
string assemblyName; string assemblyName;
string location;
Dictionary<string, IParsedFile> parsedFiles; Dictionary<string, IParsedFile> parsedFiles;
List<IAssemblyReference> assemblyReferences; List<IAssemblyReference> assemblyReferences;
CompilerSettings compilerSettings; CompilerSettings compilerSettings;
@ -47,6 +48,7 @@ namespace ICSharpCode.NRefactory.CSharp
protected CSharpProjectContent(CSharpProjectContent pc) protected CSharpProjectContent(CSharpProjectContent pc)
{ {
this.assemblyName = pc.assemblyName; this.assemblyName = pc.assemblyName;
this.location = pc.location;
this.parsedFiles = new Dictionary<string, IParsedFile>(pc.parsedFiles, Platform.FileNameComparer); this.parsedFiles = new Dictionary<string, IParsedFile>(pc.parsedFiles, Platform.FileNameComparer);
this.assemblyReferences = new List<IAssemblyReference>(pc.assemblyReferences); this.assemblyReferences = new List<IAssemblyReference>(pc.assemblyReferences);
this.compilerSettings = pc.compilerSettings; this.compilerSettings = pc.compilerSettings;
@ -64,6 +66,10 @@ namespace ICSharpCode.NRefactory.CSharp
get { return assemblyName; } get { return assemblyName; }
} }
public string Location {
get { return location; }
}
public CompilerSettings CompilerSettings { public CompilerSettings CompilerSettings {
get { return compilerSettings; } get { return compilerSettings; }
} }
@ -124,6 +130,13 @@ namespace ICSharpCode.NRefactory.CSharp
return pc; return pc;
} }
public IProjectContent SetLocation(string location)
{
CSharpProjectContent pc = Clone();
pc.location = location;
return pc;
}
public IProjectContent SetCompilerSettings(object compilerSettings) public IProjectContent SetCompilerSettings(object compilerSettings)
{ {
if (!(compilerSettings is CompilerSettings)) if (!(compilerSettings is CompilerSettings))

12
ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs

@ -767,7 +767,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
} }
idx++; idx++;
foreach (var list in mgr.GetExtensionMethods ()) { foreach (var list in mgr.GetEligibleExtensionMethods (true)) {
foreach (var method in list) { foreach (var method in list) {
if (idx < method.Parameters.Count && method.Parameters [idx].Type.Kind == TypeKind.Delegate) { if (idx < method.Parameters.Count && method.Parameters [idx].Type.Kind == TypeKind.Delegate) {
AutoSelect = false; AutoSelect = false;
@ -2323,11 +2323,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
continue; continue;
result.AddMember(field); result.AddMember(field);
} }
foreach (var m in type.GetMethods ()) {
if (m.IsStatic && m.IsPublic) {
result.AddMember(m);
}
}
return result.Result; return result.Result;
} }
@ -2351,11 +2346,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
foreach (var field in trr.Type.GetFields ()) { foreach (var field in trr.Type.GetFields ()) {
result.AddMember(field); result.AddMember(field);
} }
foreach (var m in trr.Type.GetMethods ()) {
if (m.Name == "TryParse" && m.IsStatic) {
result.AddMember(m);
}
}
return result.Result; return result.Result;
} }
} }

2
ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs

@ -121,7 +121,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
yield return method; yield return method;
} }
foreach (var extMethods in resolveResult.GetExtensionMethods ()) { foreach (var extMethods in resolveResult.GetEligibleExtensionMethods (true)) {
foreach (var method in extMethods) { foreach (var method in extMethods) {
yield return method; yield return method;
} }

5
ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs

@ -3669,7 +3669,9 @@ namespace ICSharpCode.NRefactory.CSharp
if (top.LastYYValue is Mono.CSharp.Expression) { if (top.LastYYValue is Mono.CSharp.Expression) {
conversionVisitor.Unit.TopExpression = ((Mono.CSharp.Expression)top.LastYYValue).Accept(conversionVisitor) as AstNode; conversionVisitor.Unit.TopExpression = ((Mono.CSharp.Expression)top.LastYYValue).Accept(conversionVisitor) as AstNode;
} }
conversionVisitor.Unit.FileName = fileName; conversionVisitor.Unit.FileName = fileName;
conversionVisitor.Unit.Conditionals = top.Conditionals.ToArray ();
return conversionVisitor.Unit; return conversionVisitor.Unit;
} }
@ -3714,7 +3716,8 @@ namespace ICSharpCode.NRefactory.CSharp
var top = new CompilerCompilationUnit () { var top = new CompilerCompilationUnit () {
ModuleCompiled = module, ModuleCompiled = module,
LocationsBag = parser.LocationsBag, LocationsBag = parser.LocationsBag,
SpecialsBag = parser.Lexer.sbag SpecialsBag = parser.Lexer.sbag,
Conditionals = parser.Lexer.SourceFile.Conditionals
}; };
var unit = Parse (top, fileName, lineModifier); var unit = Parse (top, fileName, lineModifier);
unit.Errors.AddRange (errorReportPrinter.Errors); unit.Errors.AddRange (errorReportPrinter.Errors);

7
ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-tokenizer.cs

@ -174,6 +174,13 @@ namespace Mono.CSharp
readonly SeekableStreamReader reader; readonly SeekableStreamReader reader;
readonly CompilationSourceFile source_file; readonly CompilationSourceFile source_file;
public CompilationSourceFile SourceFile {
get {
return source_file;
}
}
readonly CompilerContext context; readonly CompilerContext context;
SourceFile current_source; SourceFile current_source;

1
ICSharpCode.NRefactory.CSharp/Parser/mcs/driver.cs

@ -369,6 +369,7 @@ namespace Mono.CSharp
public ModuleContainer ModuleCompiled { get; set; } public ModuleContainer ModuleCompiled { get; set; }
public LocationsBag LocationsBag { get; set; } public LocationsBag LocationsBag { get; set; }
public SpecialsBag SpecialsBag { get; set; } public SpecialsBag SpecialsBag { get; set; }
public IEnumerable<string> Conditionals { get; set; }
public object LastYYValue { get; set; } public object LastYYValue { get; set; }
} }

8
ICSharpCode.NRefactory.CSharp/Parser/mcs/namespace.cs

@ -591,6 +591,14 @@ namespace Mono.CSharp {
} }
} }
public IEnumerable<string> Conditionals {
get {
if (conditionals == null)
return Enumerable.Empty<string> ();
return conditionals.Where (kv => kv.Value).Select (kv => kv.Key);
}
}
public string FileName { public string FileName {
get { get {
return file.Name; return file.Name;

63
ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ImplementAbstractMembersAction.cs

@ -31,7 +31,7 @@ using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring namespace ICSharpCode.NRefactory.CSharp.Refactoring
{ {
// [ContextAction("Implement abstract members", Description = "Implements abstract members from an abstract class.")] [ContextAction("Implement abstract members", Description = "Implements abstract members from an abstract class.")]
public class ImplementAbstractMembersAction : ICodeActionProvider public class ImplementAbstractMembersAction : ICodeActionProvider
{ {
public IEnumerable<CodeAction> GetActions(RefactoringContext context) public IEnumerable<CodeAction> GetActions(RefactoringContext context)
@ -47,15 +47,70 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (resolveResult.Type.Kind != TypeKind.Class || resolveResult.Type.GetDefinition() == null || !resolveResult.Type.GetDefinition().IsAbstract) if (resolveResult.Type.Kind != TypeKind.Class || resolveResult.Type.GetDefinition() == null || !resolveResult.Type.GetDefinition().IsAbstract)
yield break; yield break;
var toImplement = CollectMembersToImplement(state.CurrentTypeDefinition, resolveResult.Type);
if (toImplement.Count == 0)
yield break; yield break;
/*
yield return new CodeAction(context.TranslateString("Implement abstract members"), script => { yield return new CodeAction(context.TranslateString("Implement abstract members"), script => {
script.InsertWithCursor( script.InsertWithCursor(
context.TranslateString("Implement abstract members"), context.TranslateString("Implement abstract members"),
state.CurrentTypeDefinition, state.CurrentTypeDefinition,
ImplementInterfaceAction.GenerateImplementation (context, toImplement) ImplementInterfaceAction.GenerateImplementation (context, toImplement.Select (m => Tuple.Create (m, false))).Select (entity => {
var decl = entity as EntityDeclaration;
if (decl != null)
decl.Modifiers |= Modifiers.Override;
return entity;
})
);
});
}
public static List<IMember> CollectMembersToImplement(ITypeDefinition implementingType, IType abstractType)
{
var def = abstractType.GetDefinition();
var toImplement = new List<IMember>();
bool alreadyImplemented;
// Stub out non-implemented events defined by @iface
foreach (var ev in abstractType.GetEvents (e => !e.IsSynthetic && e.IsAbstract)) {
alreadyImplemented = implementingType.GetAllBaseTypeDefinitions().Any(
x => x.Kind != TypeKind.Interface && x.Events.Any (y => y.Name == ev.Name)
); );
});*/
if (!alreadyImplemented)
toImplement.Add(ev);
}
// Stub out non-implemented methods defined by @iface
foreach (var method in abstractType.GetMethods (d => !d.IsSynthetic && d.IsAbstract)) {
alreadyImplemented = false;
foreach (var cmet in implementingType.GetMethods ()) {
if (!cmet.IsAbstract && ImplementInterfaceAction.CompareMethods(method, cmet)) {
alreadyImplemented = true;
} }
} }
if (!alreadyImplemented)
toImplement.Add(method);
}
// Stub out non-implemented properties defined by @iface
foreach (var prop in abstractType.GetProperties (p => !p.IsSynthetic && p.IsAbstract)) {
alreadyImplemented = false;
foreach (var t in implementingType.GetAllBaseTypeDefinitions ()) {
if (t.Kind == TypeKind.Interface)
continue;
foreach (IProperty cprop in t.Properties) {
if (!cprop.IsAbstract && cprop.Name == prop.Name) {
alreadyImplemented = true;
}
}
}
if (!alreadyImplemented)
toImplement.Add(prop);
}
return toImplement;
}
}
} }

156
ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ImplementInterfaceAction.cs

@ -23,7 +23,6 @@
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
using System; using System;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using System.Threading; using System.Threading;
@ -55,9 +54,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
yield return new CodeAction(context.TranslateString("Implement interface"), script => { yield return new CodeAction(context.TranslateString("Implement interface"), script => {
script.InsertWithCursor( script.InsertWithCursor(
context.TranslateString ("Implement Interface"), context.TranslateString("Implement Interface"),
state.CurrentTypeDefinition, state.CurrentTypeDefinition,
GenerateImplementation (context, toImplement) GenerateImplementation(context, toImplement)
); );
}); });
} }
@ -73,9 +72,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
} }
foreach (var kv in nodes) { foreach (var kv in nodes) {
if (kv.Key.Kind == TypeKind.Interface) {
yield return new PreProcessorDirective( yield return new PreProcessorDirective(
PreProcessorDirectiveType.Region, PreProcessorDirectiveType.Region,
string.Format("{0} implementation", kv.Key.Name)); string.Format("{0} implementation", kv.Key.Name));
} else {
yield return new PreProcessorDirective(
PreProcessorDirectiveType.Region,
string.Format("implemented abstract members of {0}", kv.Key.Name));
}
foreach (var member in kv.Value) foreach (var member in kv.Value)
yield return member; yield return member;
yield return new PreProcessorDirective( yield return new PreProcessorDirective(
@ -88,11 +93,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{ {
switch (member.Item1.EntityType) { switch (member.Item1.EntityType) {
case EntityType.Property: case EntityType.Property:
return null; return GenerateProperty(context, (IProperty)member.Item1, member.Item2);
case EntityType.Indexer: case EntityType.Indexer:
return null; return GenerateIndexer(context, (IProperty)member.Item1, member.Item2);
case EntityType.Event: case EntityType.Event:
return null; return GenerateEvent(context, (IEvent)member.Item1, member.Item2);
case EntityType.Method: case EntityType.Method:
return GenerateMethod(context, (IMethod)member.Item1, member.Item2); return GenerateMethod(context, (IMethod)member.Item1, member.Item2);
default: default:
@ -100,6 +105,114 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
} }
} }
static AstNode GenerateEvent(RefactoringContext context, IEvent evt, bool explicitImplementation)
{
if (!explicitImplementation) {
return new EventDeclaration() {
Modifiers = Modifiers.Public,
Name = evt.Name,
ReturnType = context.CreateShortType (evt.ReturnType)
};
}
return new CustomEventDeclaration() {
Name = evt.Name,
ReturnType = context.CreateShortType (evt.ReturnType),
PrivateImplementationType = context.CreateShortType(evt.DeclaringType),
AddAccessor = new Accessor {
Body = new BlockStatement() {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
}
},
RemoveAccessor = new Accessor {
Body = new BlockStatement() {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
}
}
};
}
static AstNode GenerateProperty(RefactoringContext context, IProperty property, bool explicitImplementation)
{
var result = new PropertyDeclaration() {
Name = property.Name,
ReturnType = context.CreateShortType (property.ReturnType)
};
if (!explicitImplementation) {
result.Modifiers = Modifiers.Public;
} else {
result.PrivateImplementationType = context.CreateShortType(property.DeclaringType);
}
if (property.CanGet) {
if (property.DeclaringType.Kind != TypeKind.Interface) {
result.Getter = new Accessor() {
Body = new BlockStatement () {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
}
};
} else {
result.Getter = new Accessor();
}
}
if (property.CanSet) {
if (property.DeclaringType.Kind != TypeKind.Interface) {
result.Setter = new Accessor() {
Body = new BlockStatement () {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
}
};
} else {
result.Setter = new Accessor();
}
}
return result;
}
static AstNode GenerateIndexer(RefactoringContext context, IProperty indexer, bool explicitImplementation)
{
var result = new IndexerDeclaration() {
ReturnType = context.CreateShortType (indexer.ReturnType)
};
if (!explicitImplementation) {
result.Modifiers = Modifiers.Public;
} else {
result.PrivateImplementationType = context.CreateShortType(indexer.DeclaringType);
}
foreach (var p in indexer.Parameters) {
ParameterModifier modifier;
if (p.IsOut) {
modifier = ParameterModifier.Out;
} else if (p.IsRef) {
modifier = ParameterModifier.Ref;
} else if (p.IsParams) {
modifier = ParameterModifier.Params;
} else {
modifier = ParameterModifier.None;
}
result.Parameters.Add(new ParameterDeclaration(context.CreateShortType(p.Type), p.Name, modifier));
}
if (indexer.CanGet) {
result.Getter = new Accessor() {
Body = new BlockStatement () {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
}
};
}
if (indexer.CanSet) {
result.Setter = new Accessor() {
Body = new BlockStatement () {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
}
};
}
return result;
}
static AstNode GenerateMethod(RefactoringContext context, IMethod method, bool explicitImplementation) static AstNode GenerateMethod(RefactoringContext context, IMethod method, bool explicitImplementation)
{ {
var result = new MethodDeclaration() { var result = new MethodDeclaration() {
@ -124,11 +237,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
}; };
if (typeParam.HasDefaultConstructorConstraint) { if (typeParam.HasDefaultConstructorConstraint) {
constraint.BaseTypes.Add (new PrimitiveType("new")); constraint.BaseTypes.Add(new PrimitiveType("new"));
} else if (typeParam.HasReferenceTypeConstraint) { } else if (typeParam.HasReferenceTypeConstraint) {
constraint.BaseTypes.Add (new PrimitiveType("class")); constraint.BaseTypes.Add(new PrimitiveType("class"));
} else if (typeParam.HasValueTypeConstraint) { } else if (typeParam.HasValueTypeConstraint) {
constraint.BaseTypes.Add (new PrimitiveType("struct")); constraint.BaseTypes.Add(new PrimitiveType("struct"));
} }
foreach (var type in typeParam.DirectBaseTypes) { foreach (var type in typeParam.DirectBaseTypes) {
@ -136,11 +249,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
continue; continue;
if (type.FullName == "System.ValueType") if (type.FullName == "System.ValueType")
continue; continue;
constraint.BaseTypes.Add (context.CreateShortType (type)); constraint.BaseTypes.Add(context.CreateShortType(type));
} }
if (constraint.BaseTypes.Count == 0) if (constraint.BaseTypes.Count == 0)
continue; continue;
result.Constraints.Add (constraint); result.Constraints.Add(constraint);
} }
foreach (var p in method.Parameters) { foreach (var p in method.Parameters) {
@ -160,7 +273,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return result; return result;
} }
public static List<Tuple<IMember, bool>> CollectMembersToImplement(ITypeDefinition implementingType, IType interfaceType, bool explicitly) public static List<Tuple<IMember, bool>> CollectMembersToImplement(ITypeDefinition implementingType, IType interfaceType, bool explicitly)
{ {
var def = interfaceType.GetDefinition(); var def = interfaceType.GetDefinition();
@ -168,10 +280,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
bool alreadyImplemented; bool alreadyImplemented;
// Stub out non-implemented events defined by @iface // Stub out non-implemented events defined by @iface
foreach (var ev in interfaceType.GetEvents (e => !e.IsSynthetic && e.DeclaringTypeDefinition.ReflectionName == def.ReflectionName).Reverse ()) { foreach (var evGroup in interfaceType.GetEvents (e => !e.IsSynthetic && e.DeclaringTypeDefinition.ReflectionName == def.ReflectionName).GroupBy (m => m.DeclaringType).Reverse ())
foreach (var ev in evGroup) {
bool needsExplicitly = explicitly; bool needsExplicitly = explicitly;
alreadyImplemented = implementingType.GetAllBaseTypeDefinitions().Any( alreadyImplemented = implementingType.GetAllBaseTypeDefinitions().Any(
x => x.Kind != TypeKind.Interface && x.Events.Any (y => y.Name == ev.Name) x => x.Kind != TypeKind.Interface && x.Events.Any(y => y.Name == ev.Name)
); );
if (!alreadyImplemented) if (!alreadyImplemented)
@ -179,7 +292,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
} }
// Stub out non-implemented methods defined by @iface // Stub out non-implemented methods defined by @iface
foreach (var method in interfaceType.GetMethods (d => !d.IsSynthetic /* && d.DeclaringTypeDefinition.ReflectionName == def.ReflectionName*/).Reverse ()) { foreach (var methodGroup in interfaceType.GetMethods (d => !d.IsSynthetic).GroupBy (m => m.DeclaringType).Reverse ())
foreach (var method in methodGroup) {
bool needsExplicitly = explicitly; bool needsExplicitly = explicitly;
alreadyImplemented = false; alreadyImplemented = false;
@ -191,14 +306,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
alreadyImplemented |= !needsExplicitly /*|| cmet.InterfaceImplementations.Any (impl => impl.InterfaceType.Equals (interfaceType))*/; alreadyImplemented |= !needsExplicitly /*|| cmet.InterfaceImplementations.Any (impl => impl.InterfaceType.Equals (interfaceType))*/;
} }
} }
if (toImplement.Where (t => t.Item1 is IMethod).Any (t => CompareMethods (method, (IMethod)t.Item1))) if (toImplement.Where(t => t.Item1 is IMethod).Any(t => CompareMethods(method, (IMethod)t.Item1)))
needsExplicitly = true; needsExplicitly = true;
if (!alreadyImplemented) if (!alreadyImplemented)
toImplement.Add(new Tuple<IMember, bool>(method, needsExplicitly)); toImplement.Add(new Tuple<IMember, bool>(method, needsExplicitly));
} }
// Stub out non-implemented properties defined by @iface // Stub out non-implemented properties defined by @iface
foreach (var prop in interfaceType.GetProperties (p => !p.IsSynthetic && p.DeclaringTypeDefinition.ReflectionName == def.ReflectionName).Reverse ()) { foreach (var propGroup in interfaceType.GetProperties (p => !p.IsSynthetic && p.DeclaringTypeDefinition.ReflectionName == def.ReflectionName).GroupBy (m => m.DeclaringType).Reverse ())
foreach (var prop in propGroup) {
bool needsExplicitly = explicitly; bool needsExplicitly = explicitly;
alreadyImplemented = false; alreadyImplemented = false;
foreach (var t in implementingType.GetAllBaseTypeDefinitions ()) { foreach (var t in implementingType.GetAllBaseTypeDefinitions ()) {
@ -219,11 +335,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return toImplement; return toImplement;
} }
static bool CompareMethods (IMethod interfaceMethod, IMethod typeMethod) internal static bool CompareMethods(IMethod interfaceMethod, IMethod typeMethod)
{ {
if (typeMethod.IsExplicitInterfaceImplementation) if (typeMethod.IsExplicitInterfaceImplementation)
return typeMethod.ImplementedInterfaceMembers.Any (m => m.Equals (interfaceMethod)); return typeMethod.ImplementedInterfaceMembers.Any(m => m.Equals(interfaceMethod));
return SignatureComparer.Ordinal.Equals (interfaceMethod, typeMethod); return SignatureComparer.Ordinal.Equals(interfaceMethod, typeMethod);
} }
} }
} }

4
ICSharpCode.NRefactory.CSharp/Resolver/CSharpConversions.cs

@ -112,6 +112,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
c = ImplicitConversion(resolveResult.Type, toType); c = ImplicitConversion(resolveResult.Type, toType);
if (c.IsValid) return c; if (c.IsValid) return c;
if (resolveResult.Type.Kind == TypeKind.Dynamic)
return Conversion.ImplicitDynamicConversion;
c = AnonymousFunctionConversion(resolveResult, toType); c = AnonymousFunctionConversion(resolveResult, toType);
if (c.IsValid) return c; if (c.IsValid) return c;
c = MethodGroupConversion(resolveResult, toType); c = MethodGroupConversion(resolveResult, toType);
@ -159,8 +161,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return Conversion.ImplicitReferenceConversion; return Conversion.ImplicitReferenceConversion;
if (IsBoxingConversion(fromType, toType)) if (IsBoxingConversion(fromType, toType))
return Conversion.BoxingConversion; return Conversion.BoxingConversion;
if (fromType.Kind == TypeKind.Dynamic)
return Conversion.ImplicitDynamicConversion;
if (ImplicitTypeParameterConversion(fromType, toType)) { if (ImplicitTypeParameterConversion(fromType, toType)) {
// Implicit type parameter conversions that aren't also // Implicit type parameter conversions that aren't also
// reference conversions are considered to be boxing conversions // reference conversions are considered to be boxing conversions

8
ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs

@ -1618,7 +1618,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
throw new NotSupportedException("Invalid value for NameLookupMode"); throw new NotSupportedException("Invalid value for NameLookupMode");
} }
if (result is UnknownMemberResolveResult) { if (result is UnknownMemberResolveResult) {
var extensionMethods = GetExtensionMethods(target.Type, identifier, typeArguments, true); // We intentionally use all extension methods here, not just the eligible ones.
// Proper eligibility checking is only possible for the full invocation
// (after we know the remaining arguments).
// The eligibility check in GetExtensionMethods is only intended for code completion.
var extensionMethods = GetExtensionMethods(identifier, typeArguments);
if (extensionMethods.Count > 0) { if (extensionMethods.Count > 0) {
return new MethodGroupResolveResult(target, identifier, EmptyList<MethodListWithDeclaringType>.Instance, typeArguments) { return new MethodGroupResolveResult(target, identifier, EmptyList<MethodListWithDeclaringType>.Instance, typeArguments) {
extensionMethods = extensionMethods extensionMethods = extensionMethods
@ -1755,7 +1759,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (method.TypeParameters.Count != typeArguments.Count) if (method.TypeParameters.Count != typeArguments.Count)
continue; continue;
SpecializedMethod sm = new SpecializedMethod(method, new TypeParameterSubstitution(null, typeArguments)); SpecializedMethod sm = new SpecializedMethod(method, new TypeParameterSubstitution(null, typeArguments));
if (IsEligibleExtensionMethod(compilation, conversions, targetType, method, false, out inferredTypes)) if (IsEligibleExtensionMethod(compilation, conversions, targetType, sm, false, out inferredTypes))
outputGroup.Add(sm); outputGroup.Add(sm);
} else { } else {
if (IsEligibleExtensionMethod(compilation, conversions, targetType, method, true, out inferredTypes)) { if (IsEligibleExtensionMethod(compilation, conversions, targetType, method, true, out inferredTypes)) {

19
ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs

@ -132,6 +132,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// Gets all candidate extension methods. /// Gets all candidate extension methods.
/// Note: this includes candidates that are not eligible due to an inapplicable /// Note: this includes candidates that are not eligible due to an inapplicable
/// this argument. /// this argument.
/// The candidates will only be specialized if the type arguments were provided explicitly.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// The results are stored in nested lists because they are grouped by using scope. /// The results are stored in nested lists because they are grouped by using scope.
@ -155,6 +156,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return extensionMethods ?? Enumerable.Empty<IEnumerable<IMethod>>(); return extensionMethods ?? Enumerable.Empty<IEnumerable<IMethod>>();
} }
/// <summary>
/// Gets the eligible extension methods.
/// </summary>
/// <param name="substituteInferredTypes">
/// Specifies whether to produce a <see cref="SpecializedMethod"/>
/// when type arguments could be inferred from <see cref="TargetType"/>.
/// This setting is only used for inferred types and has no effect if the type parameters are
/// specified explicitly.
/// </param>
/// <remarks>
/// The results are stored in nested lists because they are grouped by using scope.
/// That is, for "using SomeExtensions; namespace X { using MoreExtensions; ... }",
/// the return value will be
/// new List {
/// new List { all extensions from MoreExtensions },
/// new List { all extensions from SomeExtensions }
/// }
/// </remarks>
public IEnumerable<IEnumerable<IMethod>> GetEligibleExtensionMethods(bool substituteInferredTypes) public IEnumerable<IEnumerable<IMethod>> GetEligibleExtensionMethods(bool substituteInferredTypes)
{ {
var result = new List<List<IMethod>>(); var result = new List<List<IMethod>>();

1
ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs

@ -510,7 +510,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
var or = mgrr.PerformOverloadResolution(compilation, var or = mgrr.PerformOverloadResolution(compilation,
args, args,
allowExtensionMethods: false,
allowExpandingParams: false); allowExpandingParams: false);
if (or.FoundApplicableCandidate && or.BestCandidateAmbiguousWith == null) { if (or.FoundApplicableCandidate && or.BestCandidateAmbiguousWith == null) {
IType returnType = or.GetBestCandidateWithSubstitutedTypeArguments().ReturnType; IType returnType = or.GetBestCandidateWithSubstitutedTypeArguments().ReturnType;

10
ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ImplementAbstractMembersTest.cs

@ -29,12 +29,11 @@ using ICSharpCode.NRefactory.CSharp.Refactoring;
namespace ICSharpCode.NRefactory.CSharp.CodeActions namespace ICSharpCode.NRefactory.CSharp.CodeActions
{ {
[Ignore("TODO")]
[TestFixture] [TestFixture]
public class ImplementAbstractMembersTest : ContextActionTestBase public class ImplementAbstractMembersTest : ContextActionTestBase
{ {
[Test()] [Test()]
public void TestSimpleInterface() public void TestSimpleBaseType()
{ {
Test<ImplementAbstractMembersAction>(@"abstract class Simple { Test<ImplementAbstractMembersAction>(@"abstract class Simple {
public abstract void FooBar (string foo, int bar); public abstract void FooBar (string foo, int bar);
@ -50,12 +49,13 @@ class Foo : $Simple
class Foo : Simple class Foo : Simple
{ {
#region implemented abstract members of Simple #region implemented abstract members of Simple
public override void FooBar(string foo, int bar) public override void FooBar (string foo, int bar)
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException ();
} }
#endregion #endregion
}"); }
");
} }
} }

8
ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ImplementInterfaceTests.cs

@ -236,14 +236,14 @@ public interface ITest : IA, IEnumerable
class Foo : ITest class Foo : ITest
{ {
#region IA implementation #region IEnumerable implementation
public bool GetEnumerator () public IEnumerator GetEnumerator ()
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }
#endregion #endregion
#region IEnumerable implementation #region IA implementation
IEnumerator IEnumerable.GetEnumerator () bool IA.GetEnumerator ()
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }

2
ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs

@ -4572,7 +4572,7 @@ class Test
} }
} }
"); ");
Assert.AreEqual (4, provider.Count); // 2xTryParse + 2 fields Assert.AreEqual (2, provider.Count); // 2 fields
Assert.IsNotNull (provider.Find ("Value1"), "field 'Value1' not found."); Assert.IsNotNull (provider.Find ("Value1"), "field 'Value1' not found.");
Assert.IsNotNull (provider.Find ("Value2"), "field 'Value2' not found."); Assert.IsNotNull (provider.Find ("Value2"), "field 'Value2' not found.");
} }

22
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs

@ -73,8 +73,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
[Test] [Test]
public void DynamicIdentityConversions() public void DynamicIdentityConversions()
{ {
Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(object), typeof(ReflectionHelper.Dynamic))); Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(object), typeof(dynamic)));
Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(ReflectionHelper.Dynamic), typeof(object))); Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(dynamic), typeof(object)));
} }
[Test] [Test]
@ -155,12 +155,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
[Test] [Test]
public void SimpleDynamicConversions() public void ConversionToDynamic()
{ {
Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(string), typeof(dynamic))); Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(string), typeof(dynamic)));
Assert.AreEqual(C.ImplicitDynamicConversion, ImplicitConversion(typeof(dynamic), typeof(string)));
Assert.AreEqual(C.BoxingConversion, ImplicitConversion(typeof(int), typeof(dynamic))); Assert.AreEqual(C.BoxingConversion, ImplicitConversion(typeof(int), typeof(dynamic)));
Assert.AreEqual(C.ImplicitDynamicConversion, ImplicitConversion(typeof(dynamic), typeof(int))); }
[Test]
public void ConversionFromDynamic()
{
// There is no conversion from the type 'dynamic' to other types (except object).
// Such conversions only exists from dynamic expression.
// This is an important distinction for type inference (see TypeInferenceTests.IEnumerableCovarianceWithDynamic)
Assert.AreEqual(C.None, ImplicitConversion(typeof(dynamic), typeof(string)));
Assert.AreEqual(C.None, ImplicitConversion(typeof(dynamic), typeof(int)));
var dynamicRR = new ResolveResult(SpecialType.Dynamic);
Assert.AreEqual(C.ImplicitDynamicConversion, conversions.ImplicitConversion(dynamicRR, compilation.FindType(typeof(string))));
Assert.AreEqual(C.ImplicitDynamicConversion, conversions.ImplicitConversion(dynamicRR, compilation.FindType(typeof(int))));
} }
[Test] [Test]

117
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs

@ -17,8 +17,10 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Linq;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using NUnit.Framework; using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Resolver namespace ICSharpCode.NRefactory.CSharp.Resolver
@ -118,5 +120,120 @@ public static class XC {
Assert.AreEqual(1, inferredTypes.Length); Assert.AreEqual(1, inferredTypes.Length);
Assert.AreEqual("System.String", inferredTypes[0].ReflectionName); Assert.AreEqual("System.String", inferredTypes[0].ReflectionName);
} }
[Test]
public void InferTypeFromOverwrittenMethodArguments()
{
string program = @"using System.Collections.Generic;
using System.Linq;
public class A { }
public class B : A { }
class Program
{
static void Main(string[] args)
{
IEnumerable<B> list = new List<B>();
var arr = $list.ToArray<A>()$;
}
}
";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.AreEqual("A[]", rr.Type.ReflectionName);
Assert.AreEqual("System.Linq.Enumerable.ToArray", rr.Member.FullName);
Assert.AreEqual("A", ((SpecializedMethod)rr.Member).TypeArguments.Single().ReflectionName);
}
[Test]
public void TypeInferenceBasedOnTargetTypeAndArgumentType()
{
string program = @"using System.Collections.Generic;
using System.Linq;
public class A { }
public class B : A { }
static class Program
{
static void Main(A a, B b)
{
var x = $b.Choose(a)$;
}
public static T Choose<T>(this T a, T b) { }
}
";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.AreEqual("A", rr.Type.ReflectionName);
}
[Test]
public void PartiallySpecializedMethod()
{
string program = @"using System.Collections.Generic;
using System.Linq;
public class A { }
public class B : A { }
static class Program
{
static void Main(A a, B b)
{
var x = $b.Choose$(a);
}
public static T Choose<T>(this T a, T b) { }
}
";
var rr = Resolve<MethodGroupResolveResult>(program);
Assert.IsFalse(rr.Methods.Any());
// We deliberately do not specialize the method unless partial specialization is requested explicitly.
// This is because the actual type (when considering the whole invocation, not just the method group)
// is actually A.
Assert.AreEqual("``0", rr.GetExtensionMethods().Single().Single().ReturnType.ReflectionName);
Assert.AreEqual("``0", rr.GetEligibleExtensionMethods(false).Single().Single().ReturnType.ReflectionName);
Assert.AreEqual("B", rr.GetEligibleExtensionMethods(true).Single().Single().ReturnType.ReflectionName);
}
[Test]
public void CreateDelegateFromExtensionMethod()
{
string program = @"using System;
static class Program
{
static void Main() {
Func<string> f = $"""".id$;
}
static string id(this string x) { return x; }
}
";
Conversion c = GetConversion(program);
Assert.IsTrue(c.IsValid);
Assert.IsTrue(c.IsMethodGroupConversion);
Assert.AreEqual("Program.id", c.Method.FullName);
}
[Test]
public void InferDelegateTypeFromExtensionMethod()
{
string program = @"using System;
static class Program
{
static void Main() {
$call("""".id)$;
}
static string id(this string x) { return x; }
static T call<T>(Func<T> f) { }
}
";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.IsFalse(rr.IsError);
Assert.AreEqual("System.String", rr.Type.FullName);
}
} }
} }

24
ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs

@ -148,6 +148,30 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
out success)); out success));
Assert.IsTrue(success); Assert.IsTrue(success);
} }
[Test]
public void IEnumerableCovarianceWithDynamic()
{
ITypeParameter tp = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T");
var ienumerableOfT = new ParameterizedType(compilation.FindType(typeof(IEnumerable<>)).GetDefinition(), new[] { tp });
var ienumerableOfString = compilation.FindType(typeof(IEnumerable<string>));
var ienumerableOfDynamic = compilation.FindType(typeof(IEnumerable<ReflectionHelper.Dynamic>));
// static T M<T>(IEnumerable<T> x, IEnumerable<T> y) {}
// M(IEnumerable<dynamic>, IEnumerable<string>); -> should infer T=dynamic, no ambiguity
// See http://blogs.msdn.com/b/cburrows/archive/2010/04/01/errata-dynamic-conversions-and-overload-resolution.aspx
// for details.
bool success;
Assert.AreEqual(
new [] { SpecialType.Dynamic },
ti.InferTypeArguments(
new [] { tp },
new [] { new ResolveResult(ienumerableOfDynamic), new ResolveResult(ienumerableOfString) },
new [] { ienumerableOfT, ienumerableOfT },
out success));
Assert.IsTrue(success);
}
#endregion #endregion
#region Inference with Method Groups #region Inference with Method Groups

2
ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs

@ -28,7 +28,7 @@ namespace ICSharpCode.NRefactory.Semantics
/// <summary> /// <summary>
/// Represents the result of a member invocation. /// Represents the result of a member invocation.
/// Used for field/property/event access. /// Used for field/property/event access.
/// Also, <see cref="InvocationResultResult"/> derives from MemberResolveResult. /// Also, <see cref="InvocationResolveResult"/> derives from MemberResolveResult.
/// </summary> /// </summary>
public class MemberResolveResult : ResolveResult public class MemberResolveResult : ResolveResult
{ {

61
ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

@ -99,6 +99,21 @@ namespace ICSharpCode.NRefactory.TypeSystem
this.InterningProvider = new SimpleInterningProvider(); this.InterningProvider = new SimpleInterningProvider();
} }
/// <summary>
/// Creates a nested CecilLoader for lazy-loading.
/// </summary>
private CecilLoader(CecilLoader loader)
{
// use a shared typeSystemTranslationTable
this.typeSystemTranslationTable = loader.typeSystemTranslationTable;
this.IncludeInternalMembers = loader.IncludeInternalMembers;
this.LazyLoad = loader.LazyLoad;
this.currentModule = loader.currentModule;
this.currentAssembly = loader.currentAssembly;
// don't use interning - the interning provider is most likely not thread-safe
// don't use cancellation for delay-loaded members
}
#region Load From AssemblyDefinition #region Load From AssemblyDefinition
/// <summary> /// <summary>
/// Loads the assembly definition into a project content. /// Loads the assembly definition into a project content.
@ -124,6 +139,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
} }
this.currentAssembly = new CecilUnresolvedAssembly(assemblyDefinition.Name.Name, this.DocumentationProvider); this.currentAssembly = new CecilUnresolvedAssembly(assemblyDefinition.Name.Name, this.DocumentationProvider);
currentAssembly.Location = assemblyDefinition.MainModule.FullyQualifiedName;
currentAssembly.AssemblyAttributes.AddRange(assemblyAttributes); currentAssembly.AssemblyAttributes.AddRange(assemblyAttributes);
currentAssembly.ModuleAttributes.AddRange(assemblyAttributes); currentAssembly.ModuleAttributes.AddRange(assemblyAttributes);
@ -133,6 +149,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
int typeParameterCount; int typeParameterCount;
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount);
var typeRef = new GetClassTypeReference(GetAssemblyReference(type.Scope), type.Namespace, name, typeParameterCount); var typeRef = new GetClassTypeReference(GetAssemblyReference(type.Scope), type.Namespace, name, typeParameterCount);
if (this.InterningProvider != null)
typeRef = this.InterningProvider.Intern(typeRef); typeRef = this.InterningProvider.Intern(typeRef);
var key = new FullNameAndTypeParameterCount(type.Namespace, name, typeParameterCount); var key = new FullNameAndTypeParameterCount(type.Namespace, name, typeParameterCount);
currentAssembly.AddTypeForwarder(key, typeRef); currentAssembly.AddTypeForwarder(key, typeRef);
@ -140,6 +157,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
} }
// Create and register all types: // Create and register all types:
CecilLoader cecilLoaderCloneForLazyLoading = LazyLoad ? new CecilLoader(this) : null;
List<TypeDefinition> cecilTypeDefs = new List<TypeDefinition>(); List<TypeDefinition> cecilTypeDefs = new List<TypeDefinition>();
List<DefaultUnresolvedTypeDefinition> typeDefs = new List<DefaultUnresolvedTypeDefinition>(); List<DefaultUnresolvedTypeDefinition> typeDefs = new List<DefaultUnresolvedTypeDefinition>();
foreach (ModuleDefinition module in assemblyDefinition.Modules) { foreach (ModuleDefinition module in assemblyDefinition.Modules) {
@ -150,6 +168,9 @@ namespace ICSharpCode.NRefactory.TypeSystem
if (name.Length == 0) if (name.Length == 0)
continue; continue;
if (this.LazyLoad) {
currentAssembly.AddTypeDefinition(new LazyCecilTypeDefinition(cecilLoaderCloneForLazyLoading, td));
} else {
var t = CreateTopLevelTypeDefinition(td); var t = CreateTopLevelTypeDefinition(td);
cecilTypeDefs.Add(td); cecilTypeDefs.Add(td);
typeDefs.Add(t); typeDefs.Add(t);
@ -157,13 +178,13 @@ namespace ICSharpCode.NRefactory.TypeSystem
} }
} }
} }
}
// Initialize the type's members: // Initialize the type's members:
for (int i = 0; i < typeDefs.Count; i++) { for (int i = 0; i < typeDefs.Count; i++) {
InitTypeDefinition(cecilTypeDefs[i], typeDefs[i]); InitTypeDefinition(cecilTypeDefs[i], typeDefs[i]);
} }
if (HasCecilReferences) RegisterCecilObject(this.currentAssembly, assemblyDefinition);
typeSystemTranslationTable[this.currentAssembly] = assemblyDefinition;
var result = this.currentAssembly; var result = this.currentAssembly;
this.currentAssembly = null; this.currentAssembly = null;
@ -229,8 +250,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
var param = new ReaderParameters { AssemblyResolver = new DummyAssemblyResolver() }; var param = new ReaderParameters { AssemblyResolver = new DummyAssemblyResolver() };
AssemblyDefinition asm = AssemblyDefinition.ReadAssembly(fileName, param); AssemblyDefinition asm = AssemblyDefinition.ReadAssembly(fileName, param);
var result = LoadAssembly(asm); var result = LoadAssembly(asm);
if (HasCecilReferences) RegisterCecilObject(result, asm);
typeSystemTranslationTable[result] = asm;
return result; return result;
} }
@ -1500,12 +1520,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
td.AddDefaultConstructorIfRequired = (td.Kind == TypeKind.Struct || td.Kind == TypeKind.Enum); td.AddDefaultConstructorIfRequired = (td.Kind == TypeKind.Struct || td.Kind == TypeKind.Enum);
InitMembers(typeDefinition, td, td.Members); InitMembers(typeDefinition, td, td.Members);
if (HasCecilReferences)
typeSystemTranslationTable[td] = typeDefinition;
if (this.InterningProvider != null) { if (this.InterningProvider != null) {
td.ApplyInterningProvider(this.InterningProvider); td.ApplyInterningProvider(this.InterningProvider);
} }
td.Freeze(); td.Freeze();
RegisterCecilObject(td, typeDefinition);
} }
void InitBaseTypes(TypeDefinition typeDefinition, IList<ITypeReference> baseTypes) void InitBaseTypes(TypeDefinition typeDefinition, IList<ITypeReference> baseTypes)
@ -1708,12 +1727,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
loader.AddAttributes(typeDefinition, this); loader.AddAttributes(typeDefinition, this);
flags[FlagHasExtensionMethods] = HasExtensionAttribute(typeDefinition); flags[FlagHasExtensionMethods] = HasExtensionAttribute(typeDefinition);
if (loader.HasCecilReferences)
loader.typeSystemTranslationTable[this] = typeDefinition;
if (loader.InterningProvider != null) { if (loader.InterningProvider != null) {
this.ApplyInterningProvider(loader.InterningProvider); this.ApplyInterningProvider(loader.InterningProvider);
} }
this.Freeze(); this.Freeze();
loader.RegisterCecilObject(this, typeDefinition);
} }
public override string Namespace { public override string Namespace {
@ -1721,6 +1739,15 @@ namespace ICSharpCode.NRefactory.TypeSystem
set { throw new NotSupportedException(); } set { throw new NotSupportedException(); }
} }
public override string FullName {
// This works because LazyCecilTypeDefinition is only used for top-level types
get { return cecilTypeDef.FullName; }
}
public override string ReflectionName {
get { return cecilTypeDef.FullName; }
}
public TypeKind Kind { public TypeKind Kind {
get { return kind; } get { return kind; }
} }
@ -2124,14 +2151,24 @@ namespace ICSharpCode.NRefactory.TypeSystem
void FinishReadMember(AbstractUnresolvedMember member, object cecilDefinition) void FinishReadMember(AbstractUnresolvedMember member, object cecilDefinition)
{ {
if (this.InterningProvider != null)
member.ApplyInterningProvider(this.InterningProvider); member.ApplyInterningProvider(this.InterningProvider);
member.Freeze(); member.Freeze();
if (HasCecilReferences) RegisterCecilObject(member, cecilDefinition);
typeSystemTranslationTable[member] = cecilDefinition;
} }
#region Type system translation table #region Type system translation table
Dictionary<object, object> typeSystemTranslationTable; readonly Dictionary<object, object> typeSystemTranslationTable;
void RegisterCecilObject(object typeSystemObject, object cecilObject)
{
if (typeSystemTranslationTable != null) {
// When lazy-loading, the dictionary might be shared between multiple cecil-loaders that are used concurrently
lock (typeSystemTranslationTable) {
typeSystemTranslationTable[typeSystemObject] = cecilObject;
}
}
}
T InternalGetCecilObject<T> (object typeSystemObject) where T : class T InternalGetCecilObject<T> (object typeSystemObject) where T : class
{ {
@ -2140,8 +2177,10 @@ namespace ICSharpCode.NRefactory.TypeSystem
if (!HasCecilReferences) if (!HasCecilReferences)
throw new NotSupportedException ("This instance contains no cecil references."); throw new NotSupportedException ("This instance contains no cecil references.");
object result; object result;
lock (typeSystemTranslationTable) {
if (!typeSystemTranslationTable.TryGetValue (typeSystemObject, out result)) if (!typeSystemTranslationTable.TryGetValue (typeSystemObject, out result))
return null; return null;
}
return result as T; return result as T;
} }

6
ICSharpCode.NRefactory/TypeSystem/IAssembly.cs

@ -31,6 +31,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// </summary> /// </summary>
string AssemblyName { get; } string AssemblyName { get; }
/// <summary>
/// Gets the path to the assembly location.
/// For projects it is the same as the output path.
/// </summary>
string Location { get; }
/// <summary> /// <summary>
/// Gets the list of all assembly attributes in the project. /// Gets the list of all assembly attributes in the project.
/// </summary> /// </summary>

5
ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs

@ -70,6 +70,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// </summary> /// </summary>
IProjectContent SetAssemblyName(string newAssemblyName); IProjectContent SetAssemblyName(string newAssemblyName);
/// <summary>
/// Changes the location of this project content.
/// </summary>
IProjectContent SetLocation(string newLocation);
/// <summary> /// <summary>
/// Add assembly references to this project content. /// Add assembly references to this project content.
/// </summary> /// </summary>

25
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedMethod.cs

@ -19,6 +19,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation namespace ICSharpCode.NRefactory.TypeSystem.Implementation
@ -217,6 +219,29 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
} }
} }
public override string ToString()
{
StringBuilder b = new StringBuilder("[");
b.Append(this.EntityType);
b.Append(' ');
b.Append(this.DeclaringType.ReflectionName);
b.Append('.');
b.Append(this.Name);
if (this.TypeParameters.Count > 0) {
b.Append("``");
b.Append(this.TypeParameters.Count);
}
b.Append('(');
for (int i = 0; i < this.Parameters.Count; i++) {
if (i > 0) b.Append(", ");
b.Append(this.Parameters[i].ToString());
}
b.Append("):");
b.Append(this.ReturnType.ReflectionName);
b.Append(']');
return b.ToString();
}
/// <summary> /// <summary>
/// Gets a dummy constructor for the specified compilation. /// Gets a dummy constructor for the specified compilation.
/// </summary> /// </summary>

11
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs

@ -70,6 +70,17 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
} }
} }
string location;
public string Location {
get {
return location;
}
set {
FreezableHelper.ThrowIfFrozen(this);
location = value;
}
}
public IList<IUnresolvedAttribute> AssemblyAttributes { public IList<IUnresolvedAttribute> AssemblyAttributes {
get { return assemblyAttributes; } get { return assemblyAttributes; }
} }

3
ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs

@ -195,6 +195,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
b.Append(this.TypeArguments[i].ReflectionName); b.Append(this.TypeArguments[i].ReflectionName);
} }
b.Append(']'); b.Append(']');
} else if (this.TypeParameters.Count > 0) {
b.Append("``");
b.Append(this.TypeParameters.Count);
} }
b.Append('('); b.Append('(');
for (int i = 0; i < this.Parameters.Count; i++) { for (int i = 0; i < this.Parameters.Count; i++) {

Loading…
Cancel
Save