Browse Source

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

newNRvisualizers
Mansheng Yang 13 years ago
parent
commit
ad46ffdd49
  1. 21
      ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs
  2. 15
      ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs
  3. 12
      ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs
  4. 2
      ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs
  5. 7
      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. 65
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ImplementAbstractMembersAction.cs
  10. 270
      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. 6
      ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/EventDeclarationTests.cs
  19. 22
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs
  20. 117
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs
  21. 24
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs
  22. 2
      ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs
  23. 93
      ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs
  24. 8
      ICSharpCode.NRefactory/TypeSystem/IAssembly.cs
  25. 7
      ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs
  26. 25
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedMethod.cs
  27. 13
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs
  28. 3
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs

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

@ -61,13 +61,30 @@ namespace ICSharpCode.NRefactory.CSharp @@ -61,13 +61,30 @@ namespace ICSharpCode.NRefactory.CSharp
public AstNodeCollection<AstNode> Members {
get { return GetChildrenByRole(MemberRole); }
}
string[] conditionals = null;
List<Error> errors = new List<Error> ();
public List<Error> 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>
/// 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.

15
ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs

@ -31,6 +31,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -31,6 +31,7 @@ namespace ICSharpCode.NRefactory.CSharp
public class CSharpProjectContent : IProjectContent
{
string assemblyName;
string location;
Dictionary<string, IParsedFile> parsedFiles;
List<IAssemblyReference> assemblyReferences;
CompilerSettings compilerSettings;
@ -47,6 +48,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -47,6 +48,7 @@ namespace ICSharpCode.NRefactory.CSharp
protected CSharpProjectContent(CSharpProjectContent pc)
{
this.assemblyName = pc.assemblyName;
this.location = pc.location;
this.parsedFiles = new Dictionary<string, IParsedFile>(pc.parsedFiles, Platform.FileNameComparer);
this.assemblyReferences = new List<IAssemblyReference>(pc.assemblyReferences);
this.compilerSettings = pc.compilerSettings;
@ -63,7 +65,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -63,7 +65,11 @@ namespace ICSharpCode.NRefactory.CSharp
public string AssemblyName {
get { return assemblyName; }
}
public string Location {
get { return location; }
}
public CompilerSettings CompilerSettings {
get { return compilerSettings; }
}
@ -123,6 +129,13 @@ namespace ICSharpCode.NRefactory.CSharp @@ -123,6 +129,13 @@ namespace ICSharpCode.NRefactory.CSharp
pc.assemblyName = newAssemblyName;
return pc;
}
public IProjectContent SetLocation(string location)
{
CSharpProjectContent pc = Clone();
pc.location = location;
return pc;
}
public IProjectContent SetCompilerSettings(object compilerSettings)
{

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

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

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

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

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

@ -3669,7 +3669,9 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3669,7 +3669,9 @@ namespace ICSharpCode.NRefactory.CSharp
if (top.LastYYValue is Mono.CSharp.Expression) {
conversionVisitor.Unit.TopExpression = ((Mono.CSharp.Expression)top.LastYYValue).Accept(conversionVisitor) as AstNode;
}
conversionVisitor.Unit.FileName = fileName;
conversionVisitor.Unit.Conditionals = top.Conditionals.ToArray ();
return conversionVisitor.Unit;
}
@ -3710,11 +3712,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3710,11 +3712,12 @@ namespace ICSharpCode.NRefactory.CSharp
Location.Initialize (new List<SourceFile> (new [] { file }));
var module = new ModuleContainer (ctx);
var parser = Driver.Parse (reader, file, module, lineModifier);
var top = new CompilerCompilationUnit () {
ModuleCompiled = module,
LocationsBag = parser.LocationsBag,
SpecialsBag = parser.Lexer.sbag
SpecialsBag = parser.Lexer.sbag,
Conditionals = parser.Lexer.SourceFile.Conditionals
};
var unit = Parse (top, fileName, lineModifier);
unit.Errors.AddRange (errorReportPrinter.Errors);

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

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

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

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

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

@ -591,6 +591,14 @@ namespace Mono.CSharp { @@ -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 {
get {
return file.Name;

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

@ -31,7 +31,7 @@ using System.Linq; @@ -31,7 +31,7 @@ using System.Linq;
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 IEnumerable<CodeAction> GetActions(RefactoringContext context)
@ -47,15 +47,70 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -47,15 +47,70 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
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 return new CodeAction(context.TranslateString("Implement abstract members"), script => {
script.InsertWithCursor(
context.TranslateString("Implement abstract members"),
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;
}
}
}

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

@ -23,7 +23,6 @@ @@ -23,7 +23,6 @@
// 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
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem;
using System.Threading;
@ -40,42 +39,48 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -40,42 +39,48 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var type = context.GetNode<AstType>();
if (type == null || type.Role != Roles.BaseType)
yield break;
var state = context.GetResolverStateBefore(type);
if (state.CurrentTypeDefinition == null)
yield break;
var resolveResult = context.Resolve(type);
if (resolveResult.Type.Kind != TypeKind.Interface)
yield break;
var toImplement = CollectMembersToImplement(state.CurrentTypeDefinition, resolveResult.Type, false);
if (toImplement.Count == 0)
yield break;
yield return new CodeAction(context.TranslateString("Implement interface"), script => {
script.InsertWithCursor(
context.TranslateString ("Implement Interface"),
context.TranslateString("Implement Interface"),
state.CurrentTypeDefinition,
GenerateImplementation (context, toImplement)
GenerateImplementation(context, toImplement)
);
});
}
public static IEnumerable<AstNode> GenerateImplementation(RefactoringContext context, IEnumerable<Tuple<IMember, bool>> toImplement)
{
var nodes = new Dictionary<IType, List<AstNode>>();
foreach (var member in toImplement) {
if (!nodes.ContainsKey(member.Item1.DeclaringType))
nodes [member.Item1.DeclaringType] = new List<AstNode>();
nodes [member.Item1.DeclaringType].Add(GenerateMemberImplementation(context, member));
}
foreach (var kv in nodes) {
yield return new PreProcessorDirective(
PreProcessorDirectiveType.Region,
string.Format("{0} implementation", kv.Key.Name));
if (kv.Key.Kind == TypeKind.Interface) {
yield return new PreProcessorDirective(
PreProcessorDirectiveType.Region,
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)
yield return member;
yield return new PreProcessorDirective(
@ -83,23 +88,131 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -83,23 +88,131 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
);
}
}
static AstNode GenerateMemberImplementation(RefactoringContext context, Tuple<IMember, bool> member)
{
switch (member.Item1.EntityType) {
case EntityType.Property:
return null;
return GenerateProperty(context, (IProperty)member.Item1, member.Item2);
case EntityType.Indexer:
return null;
return GenerateIndexer(context, (IProperty)member.Item1, member.Item2);
case EntityType.Event:
return null;
return GenerateEvent(context, (IEvent)member.Item1, member.Item2);
case EntityType.Method:
return GenerateMethod(context, (IMethod)member.Item1, member.Item2);
default:
throw new ArgumentOutOfRangeException();
}
}
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)
{
var result = new MethodDeclaration() {
@ -109,40 +222,40 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -109,40 +222,40 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
}
};
if (!explicitImplementation) {
result.Modifiers = Modifiers.Public;
} else {
result.PrivateImplementationType = context.CreateShortType(method.DeclaringType);
}
foreach (var typeParam in method.TypeParameters) {
result.TypeParameters.Add(new TypeParameterDeclaration(typeParam.Name));
var constraint = new Constraint() {
TypeParameter = new SimpleType(typeParam.Name)
};
if (typeParam.HasDefaultConstructorConstraint) {
constraint.BaseTypes.Add (new PrimitiveType("new"));
constraint.BaseTypes.Add(new PrimitiveType("new"));
} else if (typeParam.HasReferenceTypeConstraint) {
constraint.BaseTypes.Add (new PrimitiveType("class"));
constraint.BaseTypes.Add(new PrimitiveType("class"));
} else if (typeParam.HasValueTypeConstraint) {
constraint.BaseTypes.Add (new PrimitiveType("struct"));
constraint.BaseTypes.Add(new PrimitiveType("struct"));
}
foreach (var type in typeParam.DirectBaseTypes) {
if (type.FullName == "System.Object")
continue;
if (type.FullName == "System.ValueType")
continue;
constraint.BaseTypes.Add (context.CreateShortType (type));
constraint.BaseTypes.Add(context.CreateShortType(type));
}
if (constraint.BaseTypes.Count == 0)
continue;
result.Constraints.Add (constraint);
result.Constraints.Add(constraint);
}
foreach (var p in method.Parameters) {
ParameterModifier modifier;
if (p.IsOut) {
@ -156,74 +269,77 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -156,74 +269,77 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
}
result.Parameters.Add(new ParameterDeclaration(context.CreateShortType(p.Type), p.Name, modifier));
}
return result;
}
public static List<Tuple<IMember, bool>> CollectMembersToImplement(ITypeDefinition implementingType, IType interfaceType, bool explicitly)
{
var def = interfaceType.GetDefinition();
List<Tuple<IMember, bool>> toImplement = new List<Tuple<IMember, bool>>();
bool alreadyImplemented;
// Stub out non-implemented events defined by @iface
foreach (var ev in interfaceType.GetEvents (e => !e.IsSynthetic && e.DeclaringTypeDefinition.ReflectionName == def.ReflectionName).Reverse ()) {
bool needsExplicitly = explicitly;
alreadyImplemented = implementingType.GetAllBaseTypeDefinitions().Any(
x => x.Kind != TypeKind.Interface && x.Events.Any (y => y.Name == ev.Name)
);
if (!alreadyImplemented)
toImplement.Add(new Tuple<IMember, bool>(ev, needsExplicitly));
}
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;
alreadyImplemented = implementingType.GetAllBaseTypeDefinitions().Any(
x => x.Kind != TypeKind.Interface && x.Events.Any(y => y.Name == ev.Name)
);
if (!alreadyImplemented)
toImplement.Add(new Tuple<IMember, bool>(ev, needsExplicitly));
}
// Stub out non-implemented methods defined by @iface
foreach (var method in interfaceType.GetMethods (d => !d.IsSynthetic /* && d.DeclaringTypeDefinition.ReflectionName == def.ReflectionName*/).Reverse ()) {
bool needsExplicitly = explicitly;
alreadyImplemented = false;
foreach (var methodGroup in interfaceType.GetMethods (d => !d.IsSynthetic).GroupBy (m => m.DeclaringType).Reverse ())
foreach (var method in methodGroup) {
foreach (var cmet in implementingType.GetMethods ()) {
if (CompareMethods(method, cmet)) {
if (!needsExplicitly && !cmet.ReturnType.Equals(method.ReturnType))
needsExplicitly = true;
else
alreadyImplemented |= !needsExplicitly /*|| cmet.InterfaceImplementations.Any (impl => impl.InterfaceType.Equals (interfaceType))*/;
bool needsExplicitly = explicitly;
alreadyImplemented = false;
foreach (var cmet in implementingType.GetMethods ()) {
if (CompareMethods(method, cmet)) {
if (!needsExplicitly && !cmet.ReturnType.Equals(method.ReturnType))
needsExplicitly = true;
else
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)))
needsExplicitly = true;
if (!alreadyImplemented)
toImplement.Add(new Tuple<IMember, bool>(method, needsExplicitly));
}
if (toImplement.Where (t => t.Item1 is IMethod).Any (t => CompareMethods (method, (IMethod)t.Item1)))
needsExplicitly = true;
if (!alreadyImplemented)
toImplement.Add(new Tuple<IMember, bool>(method, needsExplicitly));
}
// Stub out non-implemented properties defined by @iface
foreach (var prop in interfaceType.GetProperties (p => !p.IsSynthetic && p.DeclaringTypeDefinition.ReflectionName == def.ReflectionName).Reverse ()) {
bool needsExplicitly = explicitly;
alreadyImplemented = false;
foreach (var t in implementingType.GetAllBaseTypeDefinitions ()) {
if (t.Kind == TypeKind.Interface)
continue;
foreach (IProperty cprop in t.Properties) {
if (cprop.Name == prop.Name) {
if (!needsExplicitly && !cprop.ReturnType.Equals(prop.ReturnType))
needsExplicitly = true;
else
alreadyImplemented |= !needsExplicitly/* || cprop.InterfaceImplementations.Any (impl => impl.InterfaceType.Resolve (ctx).Equals (interfaceType))*/;
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;
alreadyImplemented = false;
foreach (var t in implementingType.GetAllBaseTypeDefinitions ()) {
if (t.Kind == TypeKind.Interface)
continue;
foreach (IProperty cprop in t.Properties) {
if (cprop.Name == prop.Name) {
if (!needsExplicitly && !cprop.ReturnType.Equals(prop.ReturnType))
needsExplicitly = true;
else
alreadyImplemented |= !needsExplicitly/* || cprop.InterfaceImplementations.Any (impl => impl.InterfaceType.Resolve (ctx).Equals (interfaceType))*/;
}
}
}
if (!alreadyImplemented)
toImplement.Add(new Tuple<IMember, bool>(prop, needsExplicitly));
}
if (!alreadyImplemented)
toImplement.Add(new Tuple<IMember, bool>(prop, needsExplicitly));
}
return toImplement;
}
static bool CompareMethods (IMethod interfaceMethod, IMethod typeMethod)
internal static bool CompareMethods(IMethod interfaceMethod, IMethod typeMethod)
{
if (typeMethod.IsExplicitInterfaceImplementation)
return typeMethod.ImplementedInterfaceMembers.Any (m => m.Equals (interfaceMethod));
return SignatureComparer.Ordinal.Equals (interfaceMethod, typeMethod);
return typeMethod.ImplementedInterfaceMembers.Any(m => m.Equals(interfaceMethod));
return SignatureComparer.Ordinal.Equals(interfaceMethod, typeMethod);
}
}
}

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

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

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

@ -1618,7 +1618,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1618,7 +1618,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
throw new NotSupportedException("Invalid value for NameLookupMode");
}
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) {
return new MethodGroupResolveResult(target, identifier, EmptyList<MethodListWithDeclaringType>.Instance, typeArguments) {
extensionMethods = extensionMethods
@ -1755,7 +1759,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1755,7 +1759,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (method.TypeParameters.Count != typeArguments.Count)
continue;
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);
} else {
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 @@ -132,6 +132,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// Gets all candidate extension methods.
/// Note: this includes candidates that are not eligible due to an inapplicable
/// this argument.
/// The candidates will only be specialized if the type arguments were provided explicitly.
/// </summary>
/// <remarks>
/// The results are stored in nested lists because they are grouped by using scope.
@ -155,6 +156,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -155,6 +156,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
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)
{
var result = new List<List<IMethod>>();

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

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

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

@ -29,12 +29,11 @@ using ICSharpCode.NRefactory.CSharp.Refactoring; @@ -29,12 +29,11 @@ using ICSharpCode.NRefactory.CSharp.Refactoring;
namespace ICSharpCode.NRefactory.CSharp.CodeActions
{
[Ignore("TODO")]
[TestFixture]
public class ImplementAbstractMembersTest : ContextActionTestBase
{
[Test()]
public void TestSimpleInterface()
public void TestSimpleBaseType()
{
Test<ImplementAbstractMembersAction>(@"abstract class Simple {
public abstract void FooBar (string foo, int bar);
@ -50,12 +49,13 @@ class Foo : $Simple @@ -50,12 +49,13 @@ class Foo : $Simple
class Foo : 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
}");
}
");
}
}

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

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

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

@ -4572,7 +4572,7 @@ class Test @@ -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 ("Value2"), "field 'Value2' not found.");
}

6
ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/EventDeclarationTests.cs

@ -70,9 +70,9 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers @@ -70,9 +70,9 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers
MemberName = "EventHandler"
},
Name = "MyEvent",
AddAccessor = new Accessor { Body = new BlockStatement() },
RemoveAccessor = new Accessor { Body = new BlockStatement() }
});
AddAccessor = new Accessor { Body = new BlockStatement() },
RemoveAccessor = new Accessor { Body = new BlockStatement() }
});
}
[Test]

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

@ -73,8 +73,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -73,8 +73,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
[Test]
public void DynamicIdentityConversions()
{
Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(object), typeof(ReflectionHelper.Dynamic)));
Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(ReflectionHelper.Dynamic), typeof(object)));
Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(object), typeof(dynamic)));
Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(dynamic), typeof(object)));
}
[Test]
@ -155,12 +155,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -155,12 +155,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
[Test]
public void SimpleDynamicConversions()
public void ConversionToDynamic()
{
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.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]

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

@ -17,8 +17,10 @@ @@ -17,8 +17,10 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Resolver
@ -118,5 +120,120 @@ public static class XC { @@ -118,5 +120,120 @@ public static class XC {
Assert.AreEqual(1, inferredTypes.Length);
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 @@ -148,6 +148,30 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
out 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
#region Inference with Method Groups

2
ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs

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

93
ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

@ -98,6 +98,21 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -98,6 +98,21 @@ namespace ICSharpCode.NRefactory.TypeSystem
// Enable interning by default.
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
/// <summary>
@ -124,6 +139,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -124,6 +139,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
}
this.currentAssembly = new CecilUnresolvedAssembly(assemblyDefinition.Name.Name, this.DocumentationProvider);
currentAssembly.Location = assemblyDefinition.MainModule.FullyQualifiedName;
currentAssembly.AssemblyAttributes.AddRange(assemblyAttributes);
currentAssembly.ModuleAttributes.AddRange(assemblyAttributes);
@ -133,13 +149,15 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -133,13 +149,15 @@ namespace ICSharpCode.NRefactory.TypeSystem
int typeParameterCount;
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount);
var typeRef = new GetClassTypeReference(GetAssemblyReference(type.Scope), type.Namespace, name, typeParameterCount);
typeRef = this.InterningProvider.Intern(typeRef);
if (this.InterningProvider != null)
typeRef = this.InterningProvider.Intern(typeRef);
var key = new FullNameAndTypeParameterCount(type.Namespace, name, typeParameterCount);
currentAssembly.AddTypeForwarder(key, typeRef);
}
}
// Create and register all types:
CecilLoader cecilLoaderCloneForLazyLoading = LazyLoad ? new CecilLoader(this) : null;
List<TypeDefinition> cecilTypeDefs = new List<TypeDefinition>();
List<DefaultUnresolvedTypeDefinition> typeDefs = new List<DefaultUnresolvedTypeDefinition>();
foreach (ModuleDefinition module in assemblyDefinition.Modules) {
@ -150,10 +168,14 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -150,10 +168,14 @@ namespace ICSharpCode.NRefactory.TypeSystem
if (name.Length == 0)
continue;
var t = CreateTopLevelTypeDefinition(td);
cecilTypeDefs.Add(td);
typeDefs.Add(t);
currentAssembly.AddTypeDefinition(t);
if (this.LazyLoad) {
currentAssembly.AddTypeDefinition(new LazyCecilTypeDefinition(cecilLoaderCloneForLazyLoading, td));
} else {
var t = CreateTopLevelTypeDefinition(td);
cecilTypeDefs.Add(td);
typeDefs.Add(t);
currentAssembly.AddTypeDefinition(t);
}
}
}
}
@ -162,8 +184,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -162,8 +184,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
InitTypeDefinition(cecilTypeDefs[i], typeDefs[i]);
}
if (HasCecilReferences)
typeSystemTranslationTable[this.currentAssembly] = assemblyDefinition;
RegisterCecilObject(this.currentAssembly, assemblyDefinition);
var result = this.currentAssembly;
this.currentAssembly = null;
@ -229,8 +250,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -229,8 +250,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
var param = new ReaderParameters { AssemblyResolver = new DummyAssemblyResolver() };
AssemblyDefinition asm = AssemblyDefinition.ReadAssembly(fileName, param);
var result = LoadAssembly(asm);
if (HasCecilReferences)
typeSystemTranslationTable[result] = asm;
RegisterCecilObject(result, asm);
return result;
}
@ -1177,14 +1197,14 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1177,14 +1197,14 @@ namespace ICSharpCode.NRefactory.TypeSystem
EntityType memberType;
var b = ReadByte();
switch (b) {
case 0x53:
memberType = EntityType.Field;
break;
case 0x54:
memberType = EntityType.Property;
break;
default:
throw new NotSupportedException(string.Format("Custom member type 0x{0:x} is not supported.", b));
case 0x53:
memberType = EntityType.Field;
break;
case 0x54:
memberType = EntityType.Property;
break;
default:
throw new NotSupportedException(string.Format("Custom member type 0x{0:x} is not supported.", b));
}
IType type = ReadCustomAttributeFieldOrPropType();
string name = ReadSerString();
@ -1500,12 +1520,11 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1500,12 +1520,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
td.AddDefaultConstructorIfRequired = (td.Kind == TypeKind.Struct || td.Kind == TypeKind.Enum);
InitMembers(typeDefinition, td, td.Members);
if (HasCecilReferences)
typeSystemTranslationTable[td] = typeDefinition;
if (this.InterningProvider != null) {
td.ApplyInterningProvider(this.InterningProvider);
}
td.Freeze();
RegisterCecilObject(td, typeDefinition);
}
void InitBaseTypes(TypeDefinition typeDefinition, IList<ITypeReference> baseTypes)
@ -1708,12 +1727,11 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1708,12 +1727,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
loader.AddAttributes(typeDefinition, this);
flags[FlagHasExtensionMethods] = HasExtensionAttribute(typeDefinition);
if (loader.HasCecilReferences)
loader.typeSystemTranslationTable[this] = typeDefinition;
if (loader.InterningProvider != null) {
this.ApplyInterningProvider(loader.InterningProvider);
}
this.Freeze();
loader.RegisterCecilObject(this, typeDefinition);
}
public override string Namespace {
@ -1721,6 +1739,15 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1721,6 +1739,15 @@ namespace ICSharpCode.NRefactory.TypeSystem
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 {
get { return kind; }
}
@ -2124,14 +2151,24 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -2124,14 +2151,24 @@ namespace ICSharpCode.NRefactory.TypeSystem
void FinishReadMember(AbstractUnresolvedMember member, object cecilDefinition)
{
member.ApplyInterningProvider(this.InterningProvider);
if (this.InterningProvider != null)
member.ApplyInterningProvider(this.InterningProvider);
member.Freeze();
if (HasCecilReferences)
typeSystemTranslationTable[member] = cecilDefinition;
RegisterCecilObject(member, cecilDefinition);
}
#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
{
@ -2140,8 +2177,10 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -2140,8 +2177,10 @@ namespace ICSharpCode.NRefactory.TypeSystem
if (!HasCecilReferences)
throw new NotSupportedException ("This instance contains no cecil references.");
object result;
if (!typeSystemTranslationTable.TryGetValue (typeSystemObject, out result))
return null;
lock (typeSystemTranslationTable) {
if (!typeSystemTranslationTable.TryGetValue (typeSystemObject, out result))
return null;
}
return result as T;
}

8
ICSharpCode.NRefactory/TypeSystem/IAssembly.cs

@ -30,7 +30,13 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -30,7 +30,13 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// Gets the assembly name (short name).
/// </summary>
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>
/// Gets the list of all assembly attributes in the project.
/// </summary>

7
ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs

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

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

@ -19,6 +19,8 @@ @@ -19,6 +19,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ICSharpCode.NRefactory.Semantics;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
@ -217,6 +219,29 @@ 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>
/// Gets a dummy constructor for the specified compilation.
/// </summary>

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

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

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

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

Loading…
Cancel
Save