diff --git a/ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs b/ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs index 36e63d8188..e16fee1909 100644 --- a/ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs +++ b/ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs @@ -159,16 +159,14 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis Dictionary labels; List gotoStatements; - public IList BuildControlFlowGraph(Statement statement, ITypeResolveContext context) + public IList BuildControlFlowGraph(Statement statement) { - return BuildControlFlowGraph(statement, context, CancellationToken.None); + return BuildControlFlowGraph(statement, CancellationToken.None); } - public IList BuildControlFlowGraph(Statement statement, ITypeResolveContext context, CancellationToken cancellationToken) + public IList BuildControlFlowGraph(Statement statement, CancellationToken cancellationToken) { - return BuildControlFlowGraph(statement, new ResolveVisitor( - new CSharpResolver(context, cancellationToken), - null)); + throw new NotImplementedException(); } public IList BuildControlFlowGraph(Statement statement, ResolveVisitor resolveVisitor) @@ -308,9 +306,10 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis { if (c1 == null || c2 == null) return false; - CSharpResolver r = new CSharpResolver(resolveVisitor.TypeResolveContext, resolveVisitor.CancellationToken); + throw new NotImplementedException(); + /*CSharpResolver r = new CSharpResolver(resolveVisitor.TypeResolveContext, resolveVisitor.CancellationToken); ResolveResult c = r.ResolveBinaryOperator(BinaryOperatorType.Equality, c1, c2); - return c.IsCompileTimeConstant && (c.ConstantValue as bool?) == true; + return c.IsCompileTimeConstant && (c.ConstantValue as bool?) == true;*/ } #endregion diff --git a/ICSharpCode.NRefactory.CSharp/Analysis/DefiniteAssignmentAnalysis.cs b/ICSharpCode.NRefactory.CSharp/Analysis/DefiniteAssignmentAnalysis.cs index a4c18e496c..834ed1f166 100644 --- a/ICSharpCode.NRefactory.CSharp/Analysis/DefiniteAssignmentAnalysis.cs +++ b/ICSharpCode.NRefactory.CSharp/Analysis/DefiniteAssignmentAnalysis.cs @@ -98,26 +98,22 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis Queue nodesWithModifiedInput = new Queue(); public DefiniteAssignmentAnalysis(Statement rootStatement) - : this(rootStatement, null, CancellationToken.None) + : this(rootStatement, CancellationToken.None) { } - public DefiniteAssignmentAnalysis(Statement rootStatement, CancellationToken cancellationToken) - : this(rootStatement, null, cancellationToken) - { - } - public DefiniteAssignmentAnalysis(Statement rootStatement, ITypeResolveContext context) - : this(rootStatement, context, CancellationToken.None) + [ObsoleteAttribute] + public DefiniteAssignmentAnalysis(params object[] args) { + throw new NotImplementedException(); } - - public DefiniteAssignmentAnalysis(Statement rootStatement, ITypeResolveContext context, CancellationToken cancellationToken) - : this(rootStatement, new ResolveVisitor(new CSharpResolver(context ?? MinimalResolveContext.Instance, cancellationToken), - null)) + public DefiniteAssignmentAnalysis(Statement rootStatement, CancellationToken cancellationToken) { + throw new NotImplementedException(); } + /* public DefiniteAssignmentAnalysis(Statement rootStatement, ResolveVisitor resolveVisitor) { if (rootStatement == null) @@ -157,7 +153,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis this.analyzedRangeStart = 0; this.analyzedRangeEnd = allNodes.Count - 1; - } + }*/ void InsertAnonymousMethods(int insertPos, AstNode node) { @@ -416,10 +412,6 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis /// The constant value of the expression; or null if the expression is not a constant. ConstantResolveResult EvaluateConstant(Expression expr) { - if (resolveVisitor.TypeResolveContext is MinimalResolveContext) { - if (!(expr is PrimitiveExpression || expr is NullReferenceExpression)) - return null; - } return resolveVisitor.Resolve(expr) as ConstantResolveResult; } diff --git a/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs b/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs index fbc3eccf21..12925b60ba 100644 --- a/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using ICSharpCode.NRefactory.TypeSystem; namespace ICSharpCode.NRefactory.CSharp { diff --git a/ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs b/ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs index f90f7cf011..92a0df4cd6 100644 --- a/ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System; using System.Collections.Generic; +using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.TypeSystem; namespace ICSharpCode.NRefactory.CSharp @@ -87,6 +88,14 @@ namespace ICSharpCode.NRefactory.CSharp { return visitor.VisitCompilationUnit (this, data); } + + /// + /// Converts this compilation unit into a parsed file that can be stored in the type system. + /// + public CSharpParsedFile ToTypeSystem(string fileName) + { + return new TypeSystemConvertVisitor(fileName).Convert(this); + } } } diff --git a/ICSharpCode.NRefactory.CSharp/Ast/NodeType.cs b/ICSharpCode.NRefactory.CSharp/Ast/NodeType.cs index 2240130b88..cf96a60c8d 100644 --- a/ICSharpCode.NRefactory.CSharp/Ast/NodeType.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/NodeType.cs @@ -32,7 +32,7 @@ namespace ICSharpCode.NRefactory.CSharp { Unknown, /// - /// DomType + /// AstType /// TypeReference, /// diff --git a/ICSharpCode.NRefactory.CSharp/Ast/Statements/BlockStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/BlockStatement.cs index e42f13b6cc..066d381380 100644 --- a/ICSharpCode.NRefactory.CSharp/Ast/Statements/BlockStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/BlockStatement.cs @@ -116,7 +116,6 @@ namespace ICSharpCode.NRefactory.CSharp return o != null && !o.IsNull && this.Statements.DoMatch(o.Statements, match); } - #region Builder methods public void Add(Statement statement) { AddChild(statement, StatementRole); @@ -124,26 +123,9 @@ namespace ICSharpCode.NRefactory.CSharp public void Add(Expression expression) { - AddChild(new ExpressionStatement { Expression = expression }, StatementRole); + AddChild(new ExpressionStatement(expression), StatementRole); } - public void AddRange(IEnumerable statements) - { - foreach (Statement st in statements) - AddChild(st, StatementRole); - } - - public void AddAssignment(Expression left, Expression right) - { - Add(new AssignmentExpression { Left = left, Operator = AssignmentOperatorType.Assign, Right = right }); - } - - public void AddReturnStatement(Expression expression) - { - Add(new ReturnStatement { Expression = expression }); - } - #endregion - IEnumerator IEnumerable.GetEnumerator() { return this.Statements.GetEnumerator(); diff --git a/ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs b/ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs new file mode 100644 index 0000000000..bed1a47e2b --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs @@ -0,0 +1,82 @@ +/* + * Created by SharpDevelop. + * User: Daniel + * Date: 10/30/2011 + * Time: 01:02 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class CSharpProjectContent : IProjectContent + { + public IEnumerable Files { + get { + throw new NotImplementedException(); + } + } + + public IEnumerable AssemblyReferences { + get { + throw new NotImplementedException(); + } + } + + public string AssemblyName { + get { + throw new NotImplementedException(); + } + } + + public IList AssemblyAttributes { + get { + throw new NotImplementedException(); + } + } + + public IList ModuleAttributes { + get { + throw new NotImplementedException(); + } + } + + public IParsedFile GetFile(string fileName) + { + throw new NotImplementedException(); + } + + public ICompilation CreateCompilation() + { + throw new NotImplementedException(); + } + + public IProjectContent AddAssemblyReferences(IEnumerable references) + { + throw new NotImplementedException(); + } + + public IProjectContent RemoveAssemblyReferences(IEnumerable references) + { + throw new NotImplementedException(); + } + + public IProjectContent UpdateProjectContent(IParsedFile oldFile, IParsedFile newFile) + { + throw new NotImplementedException(); + } + + public IProjectContent UpdateProjectContent(IEnumerable oldFiles, IEnumerable newFiles) + { + throw new NotImplementedException(); + } + + public IAssembly Resolve(ICompilation compilation) + { + throw new NotImplementedException(); + } + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs index ca2291fcb5..0263c315fe 100644 --- a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs +++ b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs @@ -1,4 +1,4 @@ -// +// // CSharpCompletionEngine.cs // // Author: @@ -317,14 +317,14 @@ namespace ICSharpCode.NRefactory.CSharp.Completion var evt = mrr.Member as IEvent; if (evt == null) return null; - var delegateType = evt.ReturnType.Resolve (ctx); - if (!delegateType.IsDelegate ()) + var delegateType = evt.ReturnType; + if (delegateType.Kind != TypeKind.Delegate) return null; var wrapper = new CompletionDataWrapper (this); if (currentType != null) { // bool includeProtected = DomType.IncludeProtected (dom, typeFromDatabase, resolver.CallingType); - foreach (var method in currentType.GetMethods (ctx)) { + foreach (var method in currentType.GetMethods ()) { if (MatchDelegate (delegateType, method) /*&& method.IsAccessibleFrom (dom, resolver.CallingType, resolver.CallingMember, includeProtected) &&*/) { wrapper.AddMember (method); // data.SetText (data.CompletionText + ";"); @@ -380,7 +380,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion var contextList = new CompletionDataWrapper (this); if (n != null/* && !(identifierStart.Item2 is TypeDeclaration)*/) { - csResolver = new CSharpResolver (ctx, System.Threading.CancellationToken.None); + csResolver = new CSharpResolver (compilation); var nodes = new List (); nodes.Add (n); if (n.Parent is ICSharpCode.NRefactory.CSharp.Attribute) @@ -393,10 +393,10 @@ namespace ICSharpCode.NRefactory.CSharp.Completion if (n.Parent is ICSharpCode.NRefactory.CSharp.Attribute) { var resolved = visitor.GetResolveResult (n.Parent); if (resolved != null && resolved.Type != null) { - foreach (var property in resolved.Type.GetProperties (ctx).Where (p => p.Accessibility == Accessibility.Public)) { + foreach (var property in resolved.Type.GetProperties (p => p.Accessibility == Accessibility.Public)) { contextList.AddMember (property); } - foreach (var field in resolved.Type.GetFields (ctx).Where (p => p.Accessibility == Accessibility.Public)) { + foreach (var field in resolved.Type.GetFields (p => p.Accessibility == Accessibility.Public)) { contextList.AddMember (field); } } @@ -556,7 +556,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion } } - foreach (var member in currentType.Resolve (ctx).GetMembers (ctx)) { + foreach (var member in currentType.GetMembers ()) { if (memberPred == null || memberPred (member)) wrapper.AddMember (member); } @@ -572,22 +572,24 @@ namespace ICSharpCode.NRefactory.CSharp.Completion } foreach (var u in n.Usings) { - var ns = u.ResolveNamespace (ctx); - if (ns == null) + var importedNamespace = u.ResolveNamespace (compilation); + if (importedNamespace == null) continue; - foreach (var type in ctx.GetTypes (ns.NamespaceName, StringComparer.Ordinal)) { + foreach (var type in importedNamespace.Types) { if (typePred == null || typePred (type)) wrapper.AddType (type, type.Name); } } - foreach (var type in ctx.GetTypes (n.NamespaceName, StringComparer.Ordinal)) { + INamespace ns = null /* compilation.GetNamespace(n.NamespaceName) */; throw new NotImplementedException(); + + foreach (var type in ns.Types) { if (typePred == null || typePred (type)) wrapper.AddType (type, type.Name); } - foreach (var curNs in ctx.GetNamespaces ().Where (sn => sn.StartsWith (n.NamespaceName) && sn != n.NamespaceName)) { - wrapper.AddNamespace (n.NamespaceName, curNs); + foreach (var curNs in ns.ChildNamespaces) { + wrapper.AddNamespace (n.NamespaceName, curNs.FullName); } } } @@ -683,7 +685,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion } var isAsWrapper = new CompletionDataWrapper (this); - AddTypesAndNamespaces (isAsWrapper, GetState (), t => isAsType == null || t.IsDerivedFrom (isAsType.GetDefinition (), ctx)); + AddTypesAndNamespaces (isAsWrapper, GetState (), t => isAsType == null || t.IsDerivedFrom (isAsType.GetDefinition ())); return isAsWrapper.Result; // { // CompletionDataList completionList = new ProjectDomCompletionDataList (); @@ -904,7 +906,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion var wrapper = new CompletionDataWrapper (this); var state = GetState (); Predicate pred = null; - if (hintType != null && !hintType.Equals (SharedTypes.UnknownType)) { + if (hintType != null && !hintType.Equals (SpecialType.UnknownType)) { var lookup = new MemberLookup (ctx, currentType, ProjectContent); pred = t => { // check if type is in inheritance tree. @@ -1032,8 +1034,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion if (delegateMethod == null || delegateMethod.Parameters.Count != method.Parameters.Count) return false; + // TODO: add support for covariant/contravariant method group conversions for (int i = 0; i < delegateMethod.Parameters.Count; i++) { - if (!delegateMethod.Parameters [i].Type.Resolve (ctx).Equals (method.Parameters [i].Type.Resolve (ctx))) + if (!delegateMethod.Parameters [i].Type.Equals (method.Parameters [i].Type)) return false; } return true; diff --git a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs index 62f4938634..3fb2518eee 100644 --- a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs +++ b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs @@ -1,4 +1,4 @@ -// +// // CSharpCompletionEngineBase.cs // // Author: @@ -45,11 +45,12 @@ namespace ICSharpCode.NRefactory.CSharp.Completion protected int offset; protected TextLocation location; + protected ICompilation compilation; protected ITypeDefinition currentType; protected IMember currentMember; #region Input properties - public ITypeResolveContext ctx { get; set; } + //public ITypeResolveContext ctx { get; set; } public CompilationUnit Unit { get; set; } public CSharpParsedFile CSharpParsedFile { get; set; } public IProjectContent ProjectContent { get; set; } @@ -60,8 +61,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion this.offset = offset; this.location = document.GetLocation (offset); - this.currentType = CSharpParsedFile.GetInnermostTypeDefinition (location); - this.currentMember = CSharpParsedFile.GetMember (location); + throw new NotImplementedException(); + //this.currentType = CSharpParsedFile.GetInnermostTypeDefinition (location); + //this.currentMember = CSharpParsedFile.GetMember (location); } #region Context helper methods diff --git a/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj b/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj index 5b78ae6c85..793cc64e00 100644 --- a/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj +++ b/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj @@ -1,4 +1,4 @@ - + {53DCA265-3C3C-42F9-B647-F72BA678122B} @@ -165,6 +165,7 @@ + @@ -234,8 +235,6 @@ - - @@ -271,26 +270,20 @@ - - - + - - - - @@ -298,15 +291,21 @@ - - - - - - + + + + + + + + + + + + @@ -317,5 +316,6 @@ + \ No newline at end of file diff --git a/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpAmbience.cs b/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpAmbience.cs index cf4dea3afc..16fbccba11 100644 --- a/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpAmbience.cs +++ b/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpAmbience.cs @@ -32,24 +32,22 @@ namespace ICSharpCode.NRefactory.CSharp public ConversionFlags ConversionFlags { get; set; } #region ConvertEntity - public string ConvertEntity(IEntity e, ITypeResolveContext context) + public string ConvertEntity(IEntity e) { - using (var ctx = context.Synchronize()) { - StringWriter writer = new StringWriter(); - - if (e.EntityType == EntityType.TypeDefinition) { - ConvertTypeDeclaration((ITypeDefinition)e, ctx, writer); - } else { - ConvertMember((IMember)e, ctx, writer); - } - - return writer.ToString().TrimEnd(); + StringWriter writer = new StringWriter(); + + if (e.EntityType == EntityType.TypeDefinition) { + ConvertTypeDeclaration((ITypeDefinition)e, writer); + } else { + ConvertMember((IMember)e, writer); } + + return writer.ToString().TrimEnd(); } - void ConvertMember(IMember member, ISynchronizedTypeResolveContext ctx, StringWriter writer) + void ConvertMember(IMember member, StringWriter writer) { - TypeSystemAstBuilder astBuilder = CreateAstBuilder(ctx); + TypeSystemAstBuilder astBuilder = CreateAstBuilder(); astBuilder.ShowParameterNames = (ConversionFlags & ConversionFlags.ShowParameterNames) == ConversionFlags.ShowParameterNames; AttributedNode node = (AttributedNode)astBuilder.ConvertEntity(member); @@ -63,7 +61,7 @@ namespace ICSharpCode.NRefactory.CSharp } } - WriteMemberDeclarationName(member, ctx, writer); + WriteMemberDeclarationName(member, writer); if ((ConversionFlags & ConversionFlags.ShowParameterList) == ConversionFlags.ShowParameterList && member is IParameterizedMember && member.EntityType != EntityType.Property) { @@ -80,18 +78,18 @@ namespace ICSharpCode.NRefactory.CSharp } } - TypeSystemAstBuilder CreateAstBuilder(ITypeResolveContext ctx) + TypeSystemAstBuilder CreateAstBuilder() { - TypeSystemAstBuilder astBuilder = new TypeSystemAstBuilder(ctx); + TypeSystemAstBuilder astBuilder = new TypeSystemAstBuilder(); astBuilder.ShowModifiers = (ConversionFlags & ConversionFlags.ShowModifiers) == ConversionFlags.ShowModifiers; astBuilder.ShowAccessibility = (ConversionFlags & ConversionFlags.ShowAccessibility) == ConversionFlags.ShowAccessibility; astBuilder.AlwaysUseShortTypeNames = (ConversionFlags & ConversionFlags.UseFullyQualifiedTypeNames) != ConversionFlags.UseFullyQualifiedTypeNames; return astBuilder; } - void ConvertTypeDeclaration(ITypeDefinition typeDef, ITypeResolveContext ctx, StringWriter writer) + void ConvertTypeDeclaration(ITypeDefinition typeDef, StringWriter writer) { - TypeSystemAstBuilder astBuilder = CreateAstBuilder(ctx); + TypeSystemAstBuilder astBuilder = CreateAstBuilder(); TypeDeclaration typeDeclaration = (TypeDeclaration)astBuilder.ConvertEntity(typeDef); PrintModifiers(typeDeclaration.Modifiers, writer); if ((ConversionFlags & ConversionFlags.ShowDefinitionKeyWord) == ConversionFlags.ShowDefinitionKeyWord) { @@ -113,14 +111,14 @@ namespace ICSharpCode.NRefactory.CSharp } writer.Write(' '); } - WriteTypeDeclarationName(typeDef, ctx, writer); + WriteTypeDeclarationName(typeDef, writer); } - void WriteTypeDeclarationName(ITypeDefinition typeDef, ITypeResolveContext ctx, StringWriter writer) + void WriteTypeDeclarationName(ITypeDefinition typeDef, StringWriter writer) { - TypeSystemAstBuilder astBuilder = CreateAstBuilder(ctx); + TypeSystemAstBuilder astBuilder = CreateAstBuilder(); if (typeDef.DeclaringTypeDefinition != null) { - WriteTypeDeclarationName(typeDef.DeclaringTypeDefinition, ctx, writer); + WriteTypeDeclarationName(typeDef.DeclaringTypeDefinition, writer); writer.Write('.'); } else if ((ConversionFlags & ConversionFlags.UseFullyQualifiedMemberNames) == ConversionFlags.UseFullyQualifiedMemberNames) { writer.Write(typeDef.Namespace); @@ -132,9 +130,9 @@ namespace ICSharpCode.NRefactory.CSharp } } - void WriteMemberDeclarationName(IMember member, ITypeResolveContext ctx, StringWriter writer) + void WriteMemberDeclarationName(IMember member, StringWriter writer) { - TypeSystemAstBuilder astBuilder = CreateAstBuilder(ctx); + TypeSystemAstBuilder astBuilder = CreateAstBuilder(); if ((ConversionFlags & ConversionFlags.UseFullyQualifiedMemberNames) == ConversionFlags.UseFullyQualifiedMemberNames) { writer.Write(ConvertType(member.DeclaringType)); writer.Write('.'); @@ -154,11 +152,11 @@ namespace ICSharpCode.NRefactory.CSharp switch (member.Name) { case "op_Implicit": writer.Write("implicit operator "); - writer.Write(ConvertType(member.ReturnType, ctx)); + writer.Write(ConvertType(member.ReturnType)); break; case "op_Explicit": writer.Write("explicit operator "); - writer.Write(ConvertType(member.ReturnType, ctx)); + writer.Write(ConvertType(member.ReturnType)); break; default: writer.Write("operator "); @@ -195,21 +193,19 @@ namespace ICSharpCode.NRefactory.CSharp } #endregion - public string ConvertVariable(IVariable v, ITypeResolveContext context) + public string ConvertVariable(IVariable v) { - using (var ctx = context.Synchronize()) { - TypeSystemAstBuilder astBuilder = CreateAstBuilder(ctx); - AstNode astNode = astBuilder.ConvertVariable(v); - CSharpFormattingOptions formatting = new CSharpFormattingOptions(); - StringWriter writer = new StringWriter(); - astNode.AcceptVisitor(new CSharpOutputVisitor(writer, formatting), null); - return writer.ToString().TrimEnd(';', '\r', '\n'); - } + TypeSystemAstBuilder astBuilder = CreateAstBuilder(); + AstNode astNode = astBuilder.ConvertVariable(v); + CSharpFormattingOptions formatting = new CSharpFormattingOptions(); + StringWriter writer = new StringWriter(); + astNode.AcceptVisitor(new CSharpOutputVisitor(writer, formatting), null); + return writer.ToString().TrimEnd(';', '\r', '\n'); } public string ConvertType(IType type) { - TypeSystemAstBuilder astBuilder = CreateAstBuilder(MinimalResolveContext.Instance); + TypeSystemAstBuilder astBuilder = CreateAstBuilder(); AstType astType = astBuilder.ConvertType(type); CSharpFormattingOptions formatting = new CSharpFormattingOptions(); StringWriter writer = new StringWriter(); @@ -217,18 +213,6 @@ namespace ICSharpCode.NRefactory.CSharp return writer.ToString(); } - public string ConvertType(ITypeReference type, ITypeResolveContext context) - { - using (var ctx = context.Synchronize()) { - TypeSystemAstBuilder astBuilder = CreateAstBuilder(ctx); - AstType astType = astBuilder.ConvertTypeReference(type); - CSharpFormattingOptions formatting = new CSharpFormattingOptions(); - StringWriter writer = new StringWriter(); - astType.AcceptVisitor(new CSharpOutputVisitor(writer, formatting), null); - return writer.ToString(); - } - } - public string WrapAttribute(string attribute) { return "[" + attribute + "]"; diff --git a/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs b/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs index c27691ba40..040d02608d 100644 --- a/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs @@ -21,8 +21,8 @@ using System.CodeDom; using System.Collections.Generic; using System.IO; using System.Linq; - using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.PatternMatching; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; @@ -38,7 +38,7 @@ namespace ICSharpCode.NRefactory.CSharp /// public class CodeDomConvertVisitor : IAstVisitor { - ITypeResolveContext context = MinimalResolveContext.Instance; + //ICompilation compilation = MinimalResolveContext.Instance; ResolveVisitor resolveVisitor; bool useFullyQualifiedTypeNames; @@ -60,21 +60,23 @@ namespace ICSharpCode.NRefactory.CSharp /// /// This conversion process requires a resolver because it needs to distinguish field/property/event references etc. /// - public CodeCompileUnit Convert(CompilationUnit compilationUnit, ITypeResolveContext context, CSharpParsedFile parsedFile) + public CodeCompileUnit Convert(CompilationUnit compilationUnit, ICompilation compilation) { if (compilationUnit == null) throw new ArgumentNullException("compilationUnit"); - if (context == null) - throw new ArgumentNullException("context"); - if (parsedFile == null) - throw new ArgumentNullException("parsedFile"); + if (compilation == null) + throw new ArgumentNullException("compilation"); + + throw new NotImplementedException(); + /* using (var ctx = context.Synchronize()) { ResolveVisitor resolveVisitor = new ResolveVisitor(new CSharpResolver(ctx), parsedFile); resolveVisitor.Scan(compilationUnit); return (CodeCompileUnit)Convert(compilationUnit, resolveVisitor); - } + }*/ } + /* /// /// Converts a C# AST node to CodeDom. /// @@ -100,6 +102,7 @@ namespace ICSharpCode.NRefactory.CSharp this.context = MinimalResolveContext.Instance; } } + */ ResolveResult Resolve(AstNode node) { @@ -298,7 +301,7 @@ namespace ICSharpCode.NRefactory.CSharp case BinaryOperatorType.Equality: case BinaryOperatorType.InEquality: OperatorResolveResult rr = Resolve(binaryOperatorExpression) as OperatorResolveResult; - if (rr != null && rr.GetChildResults().Any(cr => cr.Type.IsReferenceType(context) == true)) { + if (rr != null && rr.GetChildResults().Any(cr => cr.Type.IsReferenceType == true)) { if (binaryOperatorExpression.Operator == BinaryOperatorType.Equality) op = CodeBinaryOperatorType.IdentityEquality; else @@ -1240,11 +1243,12 @@ namespace ICSharpCode.NRefactory.CSharp CodeObject IAstVisitor.VisitPrimitiveType(PrimitiveType primitiveType, object data) { string keyword = primitiveType.Keyword; - for (TypeCode c = TypeCode.Empty; c <= TypeCode.String; c++) { - if (ReflectionHelper.GetCSharpNameByTypeCode(c) == keyword) - return new CodeTypeReference("System." + ReflectionHelper.GetShortNameByTypeCode(c)); + KnownTypeCode typeCode = TypeSystemConvertVisitor.GetTypeCodeForPrimitiveType(keyword); + if (typeCode != KnownTypeCode.None) { + KnownTypeReference ktr = KnownTypeReference.Get(typeCode); + return new CodeTypeReference(ktr.Namespace + "." + ktr.Name); } - return new CodeTypeReference(primitiveType.Keyword); + return new CodeTypeReference(keyword); } CodeObject IAstVisitor.VisitComment(Comment comment, object data) diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateEventInvocator.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateEventInvocator.cs index e8473bdd9b..0fa5fa5650 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateEventInvocator.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateEventInvocator.cs @@ -1,4 +1,4 @@ -// +// // CreateEventInvocator.cs // // Author: @@ -84,7 +84,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring }; foreach (var par in pars) { - var typeName = context.CreateShortType (par.Type.Resolve (context.TypeResolveContext)); + var typeName = context.CreateShortType (par.Type); var decl = new ParameterDeclaration (typeName, par.Name); methodDeclaration.Parameters.Add (decl); } diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateLocalVariable.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateLocalVariable.cs index f5927a2d89..a6b091127b 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateLocalVariable.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateLocalVariable.cs @@ -1,4 +1,4 @@ -// +// // CreateLocalVariable.cs // // Author: @@ -120,7 +120,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring } if (result.Parameters.Count < i) return null; - return context.CreateShortType (result.Parameters[i].Type.Resolve (context.TypeResolveContext)); + return context.CreateShortType (result.Parameters[i].Type); } return null; } diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/GenerateSwitchLabels.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/GenerateSwitchLabels.cs index 04c98c5b43..316b9a3db0 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/GenerateSwitchLabels.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/GenerateSwitchLabels.cs @@ -49,8 +49,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring var type = result.Type; var newSwitch = (SwitchStatement)switchStatement.Clone (); - var target = new TypeReferenceExpression (context.CreateShortType (result.Type.Resolve (context.TypeResolveContext))); - foreach (var field in type.GetFields (context.TypeResolveContext)) { + var target = new TypeReferenceExpression (context.CreateShortType (result.Type)); + foreach (var field in type.GetFields ()) { if (field.IsSynthetic || !field.IsConst) continue; newSwitch.SwitchSections.Add (new SwitchSection () { diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/UseExplicitType.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/UseExplicitType.cs index b31bf78cb3..508867d20a 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/UseExplicitType.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/UseExplicitType.cs @@ -1,4 +1,4 @@ -// +// // UseExplicitType.cs // // Author: @@ -39,7 +39,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring if (varDecl == null) return false; var type = context.Resolve (varDecl.Variables.First ().Initializer).Type; - return !type.Equals (SharedTypes.Null) && !type.Equals (SharedTypes.UnknownType); + return !type.Equals (SpecialType.NullType) && !type.Equals (SpecialType.UnknownType); } public void Run (RefactoringContext context) diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs index 420b585f80..9d4d9e42ed 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs @@ -39,12 +39,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring protected set; } - public virtual ITypeResolveContext TypeResolveContext { - get { - return null; - } - } - public TextLocation Location { get; protected set; @@ -62,12 +56,14 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring public AstType CreateShortType (string ns, string typeName) { - return CreateShortType (TypeResolveContext.GetTypeDefinition (ns, typeName, 0, StringComparer.Ordinal)); + throw new NotImplementedException(); + //return CreateShortType (TypeResolveContext.GetTypeDefinition (ns, typeName, 0, StringComparer.Ordinal)); } public virtual AstType CreateShortType (AstType fullType) { - return CreateShortType (Resolve (fullType).Type.Resolve (TypeResolveContext)); + throw new NotImplementedException(); + //return CreateShortType (Resolve (fullType).Type.Resolve (TypeResolveContext)); } // public abstract IType GetDefinition (AstType resolvedType); @@ -133,7 +129,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring #region ConvertTypes public static ICSharpCode.NRefactory.CSharp.AstType ConvertToAstType (this IType type) { - var builder = new TypeSystemAstBuilder (MinimalResolveContext.Instance); + var builder = new TypeSystemAstBuilder (); return builder.ConvertType (type); } #endregion diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs index bd097604a3..4934647526 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs @@ -5,8 +5,8 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; - using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; @@ -20,7 +20,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring public class TypeSystemAstBuilder { readonly CSharpResolver resolver; - readonly ITypeResolveContext context; #region Constructor /// @@ -34,7 +33,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring if (resolver == null) throw new ArgumentNullException("resolver"); this.resolver = resolver; - this.context = resolver.Context; InitProperties(); } @@ -44,11 +42,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring /// /// Context used for resolving types. /// - public TypeSystemAstBuilder(ITypeResolveContext context) + public TypeSystemAstBuilder() { - if (context == null) - throw new ArgumentNullException("context"); - this.context = context; InitProperties(); } #endregion @@ -136,7 +131,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring // Unbound type IType[] typeArguments = new IType[typeDef.TypeParameterCount]; for (int i = 0; i < typeArguments.Length; i++) { - typeArguments[i] = SharedTypes.UnboundTypeArgument; + typeArguments[i] = SpecialType.UnboundTypeArgument; } return ConvertTypeHelper(typeDef, typeArguments); } else { @@ -146,62 +141,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring return new SimpleType(type.Name); } - public AstType ConvertTypeReference(ITypeReference typeRef) - { - ArrayTypeReference array = typeRef as ArrayTypeReference; - if (array != null) { - return ConvertTypeReference(array.ElementType).MakeArrayType(array.Dimensions); - } - PointerTypeReference pointer = typeRef as PointerTypeReference; - if (pointer != null) { - return ConvertTypeReference(pointer.ElementType).MakePointerType(); - } - ByReferenceType brt = typeRef as ByReferenceType; - if (brt != null) { - return ConvertTypeReference(brt.ElementType); - } - - IType type = typeRef.Resolve(context); - if (type.Kind != TypeKind.Unknown) - return ConvertType(type); - // Unknown type, let's try if we can find an appropriate type - // (anything is better than displaying a question mark) - KnownTypeReference knownType = typeRef as KnownTypeReference; - if (knownType != null) { - string keyword = ReflectionHelper.GetCSharpNameByTypeCode(knownType.TypeCode); - if (keyword != null) - return new PrimitiveType(keyword); - } - SimpleTypeOrNamespaceReference str = typeRef as SimpleTypeOrNamespaceReference; - if (str != null) { - return new SimpleType(str.Identifier, str.TypeArguments.Select(ConvertTypeReference)); - } - MemberTypeOrNamespaceReference mtr = typeRef as MemberTypeOrNamespaceReference; - if (mtr != null) { - return new MemberType(ConvertTypeReference(mtr.Target), mtr.Identifier, mtr.TypeArguments.Select(ConvertTypeReference)) { - IsDoubleColon = mtr.Target is AliasNamespaceReference - }; - } - AliasNamespaceReference alias = typeRef as AliasNamespaceReference; - if (alias != null) { - return new SimpleType(alias.Identifier); - } - // Unknown type reference that couldn't be resolved - return new SimpleType("?"); - } - AstType ConvertTypeHelper(ITypeDefinition typeDef, IList typeArguments) { Debug.Assert(typeArguments.Count >= typeDef.TypeParameterCount); - TypeCode typeCode = ReflectionHelper.GetTypeCode(typeDef); - if (typeCode != TypeCode.Empty) { - string keyword = ReflectionHelper.GetCSharpNameByTypeCode(typeCode); - if (keyword != null) - return new PrimitiveType(keyword); - } - // There is no type code for System.Void - if (typeDef.Kind == TypeKind.Void) - return new PrimitiveType("void"); + + string keyword = KnownTypeReference.GetCSharpNameByTypeCode(typeDef.KnownTypeCode); + if (keyword != null) + return new PrimitiveType(keyword); // The number of type parameters belonging to outer classes int outerTypeParameterCount; @@ -214,7 +160,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring // Look if there's an alias to the target type for (UsingScope usingScope = resolver.CurrentUsingScope; usingScope != null; usingScope = usingScope.Parent) { foreach (var pair in usingScope.UsingAliases) { - IType type = pair.Value.Resolve(resolver.Context); + IType type = pair.Value.ResolveType(resolver); if (TypeMatches(type, typeDef, typeArguments)) return new SimpleType(pair.Key); } @@ -306,8 +252,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring for (UsingScope usingScope = resolver.CurrentUsingScope; usingScope != null; usingScope = usingScope.Parent) { foreach (var pair in usingScope.UsingAliases) { // maybe add some caching? we're resolving all aliases N times when converting a namespace name with N parts - NamespaceResolveResult nrr = pair.Value.ResolveNamespace(resolver.Context); - if (nrr != null && nrr.NamespaceName == ns) + INamespace nrr = pair.Value.ResolveNamespace(resolver); + if (nrr != null && nrr.FullName == ns) return new SimpleType(pair.Key); } } @@ -344,15 +290,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring #endregion #region Convert Constant Value - public Expression ConvertConstantValue(IConstantValue constantValue) - { - if (constantValue == null) - throw new ArgumentNullException("constantValue"); - return ConvertConstantValue(constantValue.Resolve(context)); - } - - Expression ConvertConstantValue(ResolveResult rr) + public Expression ConvertConstantValue(ResolveResult rr) { + if (rr == null) + throw new ArgumentNullException("rr"); if (rr is TypeOfResolveResult) { return new TypeOfExpression(ConvertType(((TypeOfResolveResult)rr).Type)); } else if (rr is ArrayCreateResolveResult) { @@ -360,21 +301,27 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring AstType type = ConvertType(acrr.Type); throw new NotImplementedException(); } else if (rr.IsCompileTimeConstant) { - object val = rr.ConstantValue; - if (val == null) { - if (rr.Type.IsReferenceType(context) == true) - return new NullReferenceExpression(); - else - return new DefaultValueExpression(ConvertType(rr.Type)); - } else if (rr.Type.Kind == TypeKind.Enum) { - throw new NotImplementedException(); - } else { - return new PrimitiveExpression(val); - } + return ConvertConstantValue(rr.Type, rr.ConstantValue); } else { return new EmptyExpression(); } } + + public Expression ConvertConstantValue(IType type, object constantValue) + { + if (type == null) + throw new ArgumentNullException("type"); + if (constantValue == null) { + if (type.IsReferenceType == true) + return new NullReferenceExpression(); + else + return new DefaultValueExpression(ConvertType(type)); + } else if (type.Kind == TypeKind.Enum) { + throw new NotImplementedException(); + } else { + return new PrimitiveExpression(constantValue); + } + } #endregion #region Convert Parameter @@ -390,12 +337,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring } else if (parameter.IsParams) { decl.ParameterModifier = ParameterModifier.Params; } - decl.Type = ConvertTypeReference(parameter.Type); + decl.Type = ConvertType(parameter.Type); if (this.ShowParameterNames) { decl.Name = parameter.Name; } if (parameter.IsOptional && this.ShowConstantValues) { - decl.DefaultExpression = ConvertConstantValue(parameter.DefaultValue); + decl.DefaultExpression = ConvertConstantValue(parameter.Type, parameter.ConstantValue); } return decl; } @@ -482,8 +429,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring } if (this.ShowBaseTypes) { - foreach (ITypeReference baseType in typeDefinition.BaseTypes) { - decl.BaseTypes.Add(ConvertTypeReference(baseType)); + foreach (IType baseType in typeDefinition.DirectBaseTypes) { + decl.BaseTypes.Add(ConvertType(baseType)); } } @@ -503,7 +450,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring DelegateDeclaration decl = new DelegateDeclaration(); decl.Modifiers = modifiers; - decl.ReturnType = ConvertTypeReference(invokeMethod.ReturnType); + decl.ReturnType = ConvertType(invokeMethod.ReturnType); decl.Name = d.Name; if (this.ShowTypeParameters) { @@ -541,10 +488,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring } decl.Modifiers = m; } - decl.ReturnType = ConvertTypeReference(field.ReturnType); + decl.ReturnType = ConvertType(field.ReturnType); Expression initializer = null; if (field.IsConst && this.ShowConstantValues) - initializer = ConvertConstantValue(field.ConstantValue); + initializer = ConvertConstantValue(field.Type, field.ConstantValue); decl.Variables.Add(new VariableInitializer(field.Name, initializer)); return decl; } @@ -562,7 +509,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring { PropertyDeclaration decl = new PropertyDeclaration(); decl.Modifiers = GetMemberModifiers(property); - decl.ReturnType = ConvertTypeReference(property.ReturnType); + decl.ReturnType = ConvertType(property.ReturnType); decl.Name = property.Name; decl.Getter = ConvertAccessor(property.Getter); decl.Setter = ConvertAccessor(property.Setter); @@ -573,7 +520,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring { IndexerDeclaration decl = new IndexerDeclaration(); decl.Modifiers = GetMemberModifiers(indexer); - decl.ReturnType = ConvertTypeReference(indexer.ReturnType); + decl.ReturnType = ConvertType(indexer.ReturnType); foreach (IParameter p in indexer.Parameters) { decl.Parameters.Add(ConvertParameter(p)); } @@ -586,7 +533,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring { EventDeclaration decl = new EventDeclaration(); decl.Modifiers = GetMemberModifiers(ev); - decl.ReturnType = ConvertTypeReference(ev.ReturnType); + decl.ReturnType = ConvertType(ev.ReturnType); decl.Variables.Add(new VariableInitializer(ev.Name)); return decl; } @@ -595,7 +542,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring { MethodDeclaration decl = new MethodDeclaration(); decl.Modifiers = GetMemberModifiers(method); - decl.ReturnType = ConvertTypeReference(method.ReturnType); + decl.ReturnType = ConvertType(method.ReturnType); decl.Name = method.Name; if (this.ShowTypeParameters) { @@ -608,7 +555,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring decl.Parameters.Add(ConvertParameter(p)); } - if (this.ShowTypeParameters && this.ShowTypeParameterConstraints && !method.IsOverride) { + if (this.ShowTypeParameters && this.ShowTypeParameterConstraints && !method.IsOverride && !method.IsExplicitInterfaceImplementation) { foreach (ITypeParameter tp in method.TypeParameters) { var constraint = ConvertTypeParameterConstraint(tp); if (constraint != null) @@ -627,7 +574,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring OperatorDeclaration decl = new OperatorDeclaration(); decl.Modifiers = GetMemberModifiers(op); decl.OperatorType = opType.Value; - decl.ReturnType = ConvertTypeReference(op.ReturnType); + decl.ReturnType = ConvertType(op.ReturnType); foreach (IParameter p in op.Parameters) { decl.Parameters.Add(ConvertParameter(p)); } @@ -709,25 +656,30 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring Constraint ConvertTypeParameterConstraint(ITypeParameter tp) { - ITypeParameterConstraints constraints = tp.GetConstraints(context); - if (constraints.Count == 0 && !constraints.HasDefaultConstructorConstraint && !constraints.HasReferenceTypeConstraint && !constraints.HasValueTypeConstraint) { + if (!tp.HasDefaultConstructorConstraint && !tp.HasReferenceTypeConstraint && !tp.HasValueTypeConstraint && tp.DirectBaseTypes.All(IsObjectOrValueType)) { return null; } Constraint c = new Constraint(); c.TypeParameter = tp.Name; - if (constraints.HasReferenceTypeConstraint) { + if (tp.HasReferenceTypeConstraint) { c.BaseTypes.Add(new PrimitiveType("class")); - } else if (constraints.HasValueTypeConstraint) { + } else if (tp.HasValueTypeConstraint) { c.BaseTypes.Add(new PrimitiveType("struct")); } - foreach (IType t in constraints) { - c.BaseTypes.Add(ConvertType(t)); + foreach (IType t in tp.DirectBaseTypes) { + if (!IsObjectOrValueType(t)) + c.BaseTypes.Add(ConvertType(t)); } - if (constraints.HasDefaultConstructorConstraint) { + if (tp.HasDefaultConstructorConstraint) { c.BaseTypes.Add(new PrimitiveType("new")); } return c; } + + static bool IsObjectOrValueType(IType type) + { + return type.Namespace == "System" && type.TypeParameterCount == 0 && (type.Name == "Object" || type.Name == "ValueType"); + } #endregion #region Convert Variable @@ -735,10 +687,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring { VariableDeclarationStatement decl = new VariableDeclarationStatement(); decl.Modifiers = v.IsConst ? Modifiers.Const : Modifiers.None; - decl.Type = ConvertTypeReference(v.Type); + decl.Type = ConvertType(v.Type); Expression initializer = null; if (v.IsConst) - initializer = ConvertConstantValue(v.ConstantValue); + initializer = ConvertConstantValue(v.Type, v.ConstantValue); decl.Variables.Add(new VariableInitializer(v.Name, initializer)); return decl; } diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpInvocationResolveResult.cs b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpInvocationResolveResult.cs index 5e5bd21579..47e06f6ea4 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpInvocationResolveResult.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpInvocationResolveResult.cs @@ -53,7 +53,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver readonly IList argumentToParameterMap; public CSharpInvocationResolveResult( - ResolveResult targetResult, IParameterizedMember member, IType returnType, + ResolveResult targetResult, IParameterizedMember member, IList arguments, OverloadResolutionErrors overloadResolutionErrors = OverloadResolutionErrors.None, bool isExtensionMethodInvocation = false, @@ -61,7 +61,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver bool isLiftedOperatorInvocation = false, bool isDelegateInvocation = false, IList argumentToParameterMap = null) - : base(targetResult, member, returnType, arguments) + : base(targetResult, member, arguments) { this.OverloadResolutionErrors = overloadResolutionErrors; this.IsExtensionMethodInvocation = isExtensionMethodInvocation; diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpOperators.cs b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpOperators.cs new file mode 100644 index 0000000000..c0f0169013 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpOperators.cs @@ -0,0 +1,1011 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; +using System.Linq; +using System.Text; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + sealed class CSharpOperators + { + readonly ICompilation compilation; + + private CSharpOperators(ICompilation compilation) + { + this.compilation = compilation; + InitParameterArrays(); + } + + /// + /// Gets the CSharpOperators instance for the specified . + /// This will make use of the context's cache manager (if available) to reuse the CSharpOperators instance. + /// + public static CSharpOperators Get(ICompilation compilation) + { + CacheManager cache = compilation.CacheManager; + CSharpOperators operators = (CSharpOperators)cache.GetShared(typeof(CSharpOperators)); + if (operators == null) { + operators = (CSharpOperators)cache.GetOrAddShared(typeof(Conversions), new CSharpOperators(compilation)); + } + return operators; + } + + #region class OperatorMethod + OperatorMethod[] Lift(params OperatorMethod[] methods) + { + List result = new List(methods); + foreach (OperatorMethod method in methods) { + OperatorMethod lifted = method.Lift(this); + if (lifted != null) + result.Add(lifted); + } + return result.ToArray(); + } + + IParameter[] normalParameters = new IParameter[(int)(TypeCode.String + 1 - TypeCode.Object)]; + IParameter[] nullableParameters = new IParameter[(int)(TypeCode.Decimal + 1 - TypeCode.Boolean)]; + + void InitParameterArrays() + { + for (TypeCode i = TypeCode.Object; i <= TypeCode.String; i++) { + normalParameters[i - TypeCode.Object] = new DefaultParameter(compilation.FindType(i), string.Empty); + } + for (TypeCode i = TypeCode.Boolean; i <= TypeCode.Decimal; i++) { + IType type = NullableType.Create(compilation, compilation.FindType(i)); + nullableParameters[i - TypeCode.Boolean] = new DefaultParameter(type, string.Empty); + } + } + + IParameter MakeParameter(TypeCode code) + { + return normalParameters[code - TypeCode.Object]; + } + + IParameter MakeNullableParameter(IParameter normalParameter) + { + for (TypeCode i = TypeCode.Boolean; i <= TypeCode.Decimal; i++) { + if (normalParameter == normalParameters[i - TypeCode.Object]) + return nullableParameters[i - TypeCode.Boolean]; + } + throw new ArgumentException(); + } + + internal class OperatorMethod : IParameterizedMember + { + readonly ICompilation compilation; + readonly IList parameters = new List(); + + protected OperatorMethod(ICompilation compilation) + { + this.compilation = compilation; + } + + public IList Parameters { + get { return parameters; } + } + + public IType ReturnType { get; internal set; } + + public ICompilation Compilation { + get { return compilation; } + } + + public virtual OperatorMethod Lift(CSharpOperators operators) + { + return null; + } + + ITypeDefinition IEntity.DeclaringTypeDefinition { + get { return null; } + } + + IType IEntity.DeclaringType { + get { return SpecialType.UnknownType; } + } + + IMember IMember.MemberDefinition { + get { return this; } + } + + IList IMember.InterfaceImplementations { + get { return EmptyList.Instance; } + } + + bool IMember.IsVirtual { + get { return false; } + } + + bool IMember.IsOverride { + get { return false; } + } + + bool IMember.IsOverridable { + get { return false; } + } + + EntityType IEntity.EntityType { + get { return EntityType.Operator; } + } + + DomRegion IEntity.Region { + get { return DomRegion.Empty; } + } + + DomRegion IEntity.BodyRegion { + get { return DomRegion.Empty; } + } + + IList IEntity.Attributes { + get { return EmptyList.Instance; } + } + + string IEntity.Documentation { + get { return null; } + } + + Accessibility IHasAccessibility.Accessibility { + get { return Accessibility.Public; } + } + + bool IEntity.IsStatic { + get { return true; } + } + + bool IEntity.IsAbstract { + get { return false; } + } + + bool IEntity.IsSealed { + get { return false; } + } + + bool IEntity.IsShadowing { + get { return false; } + } + + bool IEntity.IsSynthetic { + get { return true; } + } + + bool IHasAccessibility.IsPrivate { + get { return false; } + } + + bool IHasAccessibility.IsPublic { + get { return true; } + } + + bool IHasAccessibility.IsProtected { + get { return false; } + } + + bool IHasAccessibility.IsInternal { + get { return false; } + } + + bool IHasAccessibility.IsProtectedOrInternal { + get { return false; } + } + + bool IHasAccessibility.IsProtectedAndInternal { + get { return false; } + } + + bool IMember.IsExplicitInterfaceImplementation { + get { return false; } + } + + IUnresolvedEntity IEntity.UnresolvedEntity { + get { return null; } + } + + IAssembly IEntity.ParentAssembly { + get { throw new NotImplementedException(); } + } + + IMemberReference IMember.ToMemberReference() + { + throw new NotSupportedException(); + } + + string INamedElement.FullName { + get { return "operator"; } + } + + string INamedElement.Name { + get { return "operator"; } + } + + string INamedElement.Namespace { + get { return string.Empty; } + } + + string INamedElement.ReflectionName { + get { return "operator"; } + } + + public override string ToString() + { + StringBuilder b = new StringBuilder(); + b.Append(ReturnType + " operator("); + for (int i = 0; i < parameters.Count; i++) { + if (i > 0) + b.Append(", "); + b.Append(parameters[i].Type); + } + b.Append(')'); + return b.ToString(); + } + } + #endregion + + #region Unary operator class definitions + internal class UnaryOperatorMethod : OperatorMethod + { + public virtual bool CanEvaluateAtCompileTime { get { return false; } } + + public virtual object Invoke(CSharpResolver resolver, object input) + { + throw new NotSupportedException(); + } + + public UnaryOperatorMethod(ICompilation compilaton) : base(compilaton) + { + } + } + + sealed class LambdaUnaryOperatorMethod : UnaryOperatorMethod + { + readonly Func func; + + public LambdaUnaryOperatorMethod(CSharpOperators operators, Func func) + : base(operators.compilation) + { + TypeCode typeCode = Type.GetTypeCode(typeof(T)); + this.ReturnType = operators.compilation.FindType(typeCode); + this.Parameters.Add(operators.MakeParameter(typeCode)); + this.func = func; + } + + public override bool CanEvaluateAtCompileTime { + get { return true; } + } + + public override object Invoke(CSharpResolver resolver, object input) + { + return func((T)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T)), input)); + } + + public override OperatorMethod Lift(CSharpOperators operators) + { + return new LiftedUnaryOperatorMethod(operators, this); + } + } + + sealed class LiftedUnaryOperatorMethod : UnaryOperatorMethod, OverloadResolution.ILiftedOperator + { + UnaryOperatorMethod baseMethod; + + public LiftedUnaryOperatorMethod(CSharpOperators operators, UnaryOperatorMethod baseMethod) : base(operators.compilation) + { + this.baseMethod = baseMethod; + this.ReturnType = NullableType.Create(baseMethod.Compilation, baseMethod.ReturnType); + this.Parameters.Add(operators.MakeNullableParameter(baseMethod.Parameters[0])); + } + + public IList NonLiftedParameters { + get { return baseMethod.Parameters; } + } + } + #endregion + + #region Unary operator definitions + // C# 4.0 spec: §7.7.1 Unary plus operator + OperatorMethod[] unaryPlusOperators; + + public OperatorMethod[] UnaryPlusOperators { + get { + OperatorMethod[] ops = unaryPlusOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref unaryPlusOperators, Lift( + new LambdaUnaryOperatorMethod (this, i => +i), + new LambdaUnaryOperatorMethod (this, i => +i), + new LambdaUnaryOperatorMethod (this, i => +i), + new LambdaUnaryOperatorMethod (this, i => +i), + new LambdaUnaryOperatorMethod (this, i => +i), + new LambdaUnaryOperatorMethod (this, i => +i), + new LambdaUnaryOperatorMethod(this, i => +i) + )); + } + } + } + + // C# 4.0 spec: §7.7.2 Unary minus operator + OperatorMethod[] uncheckedUnaryMinusOperators; + + public OperatorMethod[] UncheckedUnaryMinusOperators { + get { + OperatorMethod[] ops = uncheckedUnaryMinusOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref uncheckedUnaryMinusOperators, Lift( + new LambdaUnaryOperatorMethod (this, i => unchecked(-i)), + new LambdaUnaryOperatorMethod (this, i => unchecked(-i)), + new LambdaUnaryOperatorMethod (this, i => unchecked(-i)), + new LambdaUnaryOperatorMethod (this, i => unchecked(-i)), + new LambdaUnaryOperatorMethod(this, i => unchecked(-i)) + )); + } + } + } + + OperatorMethod[] checkedUnaryMinusOperators; + + public OperatorMethod[] CheckedUnaryMinusOperators { + get { + OperatorMethod[] ops = checkedUnaryMinusOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref checkedUnaryMinusOperators, Lift( + new LambdaUnaryOperatorMethod (this, i => checked(-i)), + new LambdaUnaryOperatorMethod (this, i => checked(-i)), + new LambdaUnaryOperatorMethod (this, i => checked(-i)), + new LambdaUnaryOperatorMethod (this, i => checked(-i)), + new LambdaUnaryOperatorMethod(this, i => checked(-i)) + )); + } + } + } + + // C# 4.0 spec: §7.7.3 Logical negation operator + OperatorMethod[] logicalNegationOperators; + + public OperatorMethod[] LogicalNegationOperators { + get { + OperatorMethod[] ops = logicalNegationOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref logicalNegationOperators, Lift( + new LambdaUnaryOperatorMethod(this, b => !b) + )); + } + } + } + + // C# 4.0 spec: §7.7.4 Bitwise complement operator + OperatorMethod[] bitwiseComplementOperators; + + public OperatorMethod[] BitwiseComplementOperators { + get { + OperatorMethod[] ops = bitwiseComplementOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref bitwiseComplementOperators, Lift( + new LambdaUnaryOperatorMethod (this, i => ~i), + new LambdaUnaryOperatorMethod (this, i => ~i), + new LambdaUnaryOperatorMethod (this, i => ~i), + new LambdaUnaryOperatorMethod(this, i => ~i) + )); + } + } + } + #endregion + + #region Binary operator class definitions + internal class BinaryOperatorMethod : OperatorMethod + { + public virtual bool CanEvaluateAtCompileTime { get { return false; } } + public virtual object Invoke(CSharpResolver resolver, object lhs, object rhs) { + throw new NotSupportedException(); + } + + public BinaryOperatorMethod(ICompilation compilation) : base(compilation) {} + } + + sealed class LambdaBinaryOperatorMethod : BinaryOperatorMethod + { + readonly Func checkedFunc; + readonly Func uncheckedFunc; + + public LambdaBinaryOperatorMethod(CSharpOperators operators, Func func) + : this(operators, func, func) + { + } + + public LambdaBinaryOperatorMethod(CSharpOperators operators, Func checkedFunc, Func uncheckedFunc) + : base(operators.compilation) + { + TypeCode t1 = Type.GetTypeCode(typeof(T1)); + this.ReturnType = operators.compilation.FindType(t1); + this.Parameters.Add(operators.MakeParameter(t1)); + this.Parameters.Add(operators.MakeParameter(Type.GetTypeCode(typeof(T2)))); + this.checkedFunc = checkedFunc; + this.uncheckedFunc = uncheckedFunc; + } + + public override bool CanEvaluateAtCompileTime { + get { return true; } + } + + public override object Invoke(CSharpResolver resolver, object lhs, object rhs) + { + Func func = resolver.CheckForOverflow ? checkedFunc : uncheckedFunc; + return func((T1)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T1)), lhs), + (T2)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T2)), rhs)); + } + + public override OperatorMethod Lift(CSharpOperators operators) + { + return new LiftedBinaryOperatorMethod(operators, this); + } + } + + sealed class LiftedBinaryOperatorMethod : BinaryOperatorMethod, OverloadResolution.ILiftedOperator + { + readonly BinaryOperatorMethod baseMethod; + + public LiftedBinaryOperatorMethod(CSharpOperators operators, BinaryOperatorMethod baseMethod) + : base(operators.compilation) + { + this.baseMethod = baseMethod; + this.ReturnType = NullableType.Create(operators.compilation, baseMethod.ReturnType); + this.Parameters.Add(operators.MakeNullableParameter(baseMethod.Parameters[0])); + this.Parameters.Add(operators.MakeNullableParameter(baseMethod.Parameters[1])); + } + + public IList NonLiftedParameters { + get { return baseMethod.Parameters; } + } + } + #endregion + + #region Arithmetic operators + // C# 4.0 spec: §7.8.1 Multiplication operator + + OperatorMethod[] multiplicationOperators; + + public OperatorMethod[] MultiplicationOperators { + get { + OperatorMethod[] ops = multiplicationOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref multiplicationOperators, Lift( + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)) + )); + } + } + } + + // C# 4.0 spec: §7.8.2 Division operator + OperatorMethod[] divisionOperators; + + public OperatorMethod[] DivisionOperators { + get { + OperatorMethod[] ops = divisionOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref divisionOperators, Lift( + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)) + )); + } + } + } + + // C# 4.0 spec: §7.8.3 Remainder operator + OperatorMethod[] remainderOperators; + + public OperatorMethod[] RemainderOperators { + get { + OperatorMethod[] ops = remainderOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref remainderOperators, Lift( + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)) + )); + } + } + } + + // C# 4.0 spec: §7.8.3 Addition operator + OperatorMethod[] additionOperators; + + public OperatorMethod[] AdditionOperators { + get { + OperatorMethod[] ops = additionOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref additionOperators, Lift( + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), + new StringConcatenation(this, TypeCode.String, TypeCode.String), + new StringConcatenation(this, TypeCode.String, TypeCode.Object), + new StringConcatenation(this, TypeCode.Object, TypeCode.String) + )); + } + } + } + + // not in this list, but handled manually: enum addition, delegate combination + sealed class StringConcatenation : BinaryOperatorMethod + { + bool canEvaluateAtCompileTime; + + public StringConcatenation(CSharpOperators operators, TypeCode p1, TypeCode p2) + : base(operators.compilation) + { + this.canEvaluateAtCompileTime = p1 == TypeCode.String && p2 == TypeCode.String; + this.ReturnType = KnownTypeReference.String.Resolve(operators.compilation.TypeResolveContext); + this.Parameters.Add(operators.MakeParameter(p1)); + this.Parameters.Add(operators.MakeParameter(p2)); + } + + public override bool CanEvaluateAtCompileTime { + get { return canEvaluateAtCompileTime; } + } + + public override object Invoke(CSharpResolver resolver, object lhs, object rhs) + { + return string.Concat(lhs, rhs); + } + } + + // C# 4.0 spec: §7.8.4 Subtraction operator + OperatorMethod[] subtractionOperators; + + public OperatorMethod[] SubtractionOperators { + get { + OperatorMethod[] ops = subtractionOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref subtractionOperators, Lift( + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)), + new LambdaBinaryOperatorMethod (this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)) + )); + } + } + } + + // C# 4.0 spec: §7.8.5 Shift operators + OperatorMethod[] shiftLeftOperators; + + public OperatorMethod[] ShiftLeftOperators { + get { + OperatorMethod[] ops = shiftLeftOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref shiftLeftOperators, Lift( + new LambdaBinaryOperatorMethod(this, (a, b) => a << b), + new LambdaBinaryOperatorMethod(this, (a, b) => a << b), + new LambdaBinaryOperatorMethod(this, (a, b) => a << b), + new LambdaBinaryOperatorMethod(this, (a, b) => a << b) + )); + } + } + } + + OperatorMethod[] shiftRightOperators; + + public OperatorMethod[] ShiftRightOperators { + get { + OperatorMethod[] ops = shiftRightOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref shiftRightOperators, Lift( + new LambdaBinaryOperatorMethod(this, (a, b) => a >> b), + new LambdaBinaryOperatorMethod(this, (a, b) => a >> b), + new LambdaBinaryOperatorMethod(this, (a, b) => a >> b), + new LambdaBinaryOperatorMethod(this, (a, b) => a >> b) + )); + } + } + } + #endregion + + #region Equality operators + sealed class EqualityOperatorMethod : BinaryOperatorMethod + { + public readonly TypeCode Type; + public readonly bool Negate; + + public EqualityOperatorMethod(CSharpOperators operators, TypeCode type, bool negate) + : base(operators.compilation) + { + this.Negate = negate; + this.Type = type; + this.ReturnType = operators.compilation.FindType(KnownTypeCode.Boolean); + this.Parameters.Add(operators.MakeParameter(type)); + this.Parameters.Add(operators.MakeParameter(type)); + } + + public override bool CanEvaluateAtCompileTime { + get { return Type != TypeCode.Object; } + } + + public override object Invoke(CSharpResolver resolver, object lhs, object rhs) + { + lhs = resolver.CSharpPrimitiveCast(Type, lhs); + rhs = resolver.CSharpPrimitiveCast(Type, rhs); + bool equal; + if (Type == TypeCode.Single) { + equal = (float)lhs == (float)rhs; + } else if (Type == TypeCode.Double) { + equal = (double)lhs == (double)rhs; + } else { + equal = object.Equals(lhs, rhs); + } + return equal ^ Negate; + } + + public override OperatorMethod Lift(CSharpOperators operators) + { + if (Type == TypeCode.Object || Type == TypeCode.String) + return null; + else + return new LiftedEqualityOperatorMethod(operators, this); + } + } + + sealed class LiftedEqualityOperatorMethod : BinaryOperatorMethod, OverloadResolution.ILiftedOperator + { + readonly EqualityOperatorMethod baseMethod; + + public LiftedEqualityOperatorMethod(CSharpOperators operators, EqualityOperatorMethod baseMethod) + : base(operators.compilation) + { + this.baseMethod = baseMethod; + this.ReturnType = baseMethod.ReturnType; + IParameter p = operators.MakeNullableParameter(baseMethod.Parameters[0]); + this.Parameters.Add(p); + this.Parameters.Add(p); + } + + public override bool CanEvaluateAtCompileTime { + get { return baseMethod.CanEvaluateAtCompileTime; } + } + + public override object Invoke(CSharpResolver resolver, object lhs, object rhs) + { + if (lhs == null && rhs == null) + return !baseMethod.Negate; // ==: true; !=: false + if (lhs == null || rhs == null) + return baseMethod.Negate; // ==: false; !=: true + return baseMethod.Invoke(resolver, lhs, rhs); + } + + public IList NonLiftedParameters { + get { return baseMethod.Parameters; } + } + } + + // C# 4.0 spec: §7.10 Relational and type-testing operators + static readonly TypeCode[] equalityOperatorsFor = { + TypeCode.Int32, TypeCode.UInt32, + TypeCode.Int64, TypeCode.UInt64, + TypeCode.Single, TypeCode.Double, + TypeCode.Decimal, + TypeCode.Boolean, + TypeCode.String, TypeCode.Object + }; + + OperatorMethod[] equalityOperators; + + public OperatorMethod[] EqualityOperators { + get { + OperatorMethod[] ops = equalityOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref equalityOperators, Lift( + equalityOperatorsFor.Select(c => new EqualityOperatorMethod(this, c, true)).ToArray() + )); + } + } + } + + OperatorMethod[] inequalityOperators; + + public OperatorMethod[] InequalityOperators { + get { + OperatorMethod[] ops = inequalityOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref inequalityOperators, Lift( + equalityOperatorsFor.Select(c => new EqualityOperatorMethod(this, c, false)).ToArray() + )); + } + } + } + #endregion + + #region Relational Operators + sealed class RelationalOperatorMethod : BinaryOperatorMethod + { + readonly Func func; + + public RelationalOperatorMethod(CSharpOperators operators, Func func) + : base(operators.compilation) + { + this.ReturnType = operators.compilation.FindType(KnownTypeCode.Boolean); + this.Parameters.Add(operators.MakeParameter(Type.GetTypeCode(typeof(T1)))); + this.Parameters.Add(operators.MakeParameter(Type.GetTypeCode(typeof(T2)))); + this.func = func; + } + + public override object Invoke(CSharpResolver resolver, object lhs, object rhs) + { + return func((T1)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T1)), lhs), + (T2)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T2)), rhs)); + } + + public override OperatorMethod Lift(CSharpOperators operators) + { + return new LiftedBinaryOperatorMethod(operators, this); + } + } + + OperatorMethod[] lessThanOperators; + + public OperatorMethod[] LessThanOperators { + get { + OperatorMethod[] ops = lessThanOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref lessThanOperators, Lift( + new RelationalOperatorMethod (this, (a, b) => a < b), + new RelationalOperatorMethod (this, (a, b) => a < b), + new RelationalOperatorMethod (this, (a, b) => a < b), + new RelationalOperatorMethod (this, (a, b) => a < b), + new RelationalOperatorMethod (this, (a, b) => a < b), + new RelationalOperatorMethod (this, (a, b) => a < b), + new RelationalOperatorMethod(this, (a, b) => a < b) + )); + } + } + } + + OperatorMethod[] lessThanOrEqualOperators; + + public OperatorMethod[] LessThanOrEqualOperators { + get { + OperatorMethod[] ops = lessThanOrEqualOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref lessThanOrEqualOperators, Lift( + new RelationalOperatorMethod (this, (a, b) => a <= b), + new RelationalOperatorMethod (this, (a, b) => a <= b), + new RelationalOperatorMethod (this, (a, b) => a <= b), + new RelationalOperatorMethod (this, (a, b) => a <= b), + new RelationalOperatorMethod (this, (a, b) => a <= b), + new RelationalOperatorMethod (this, (a, b) => a <= b), + new RelationalOperatorMethod(this, (a, b) => a <= b) + )); + } + } + } + + OperatorMethod[] greaterThanOperators; + + public OperatorMethod[] GreaterThanOperators { + get { + OperatorMethod[] ops = greaterThanOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref greaterThanOperators, Lift( + new RelationalOperatorMethod (this, (a, b) => a > b), + new RelationalOperatorMethod (this, (a, b) => a > b), + new RelationalOperatorMethod (this, (a, b) => a > b), + new RelationalOperatorMethod (this, (a, b) => a > b), + new RelationalOperatorMethod (this, (a, b) => a > b), + new RelationalOperatorMethod (this, (a, b) => a > b), + new RelationalOperatorMethod(this, (a, b) => a > b) + )); + } + } + } + + OperatorMethod[] greaterThanOrEqualOperators; + + public OperatorMethod[] GreaterThanOrEqualOperators { + get { + OperatorMethod[] ops = greaterThanOrEqualOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref greaterThanOrEqualOperators, Lift( + new RelationalOperatorMethod (this, (a, b) => a >= b), + new RelationalOperatorMethod (this, (a, b) => a >= b), + new RelationalOperatorMethod (this, (a, b) => a >= b), + new RelationalOperatorMethod (this, (a, b) => a >= b), + new RelationalOperatorMethod (this, (a, b) => a >= b), + new RelationalOperatorMethod (this, (a, b) => a >= b), + new RelationalOperatorMethod(this, (a, b) => a >= b) + )); + } + } + } + #endregion + + #region Bitwise operators + OperatorMethod[] logicalAndOperators; + + public OperatorMethod[] LogicalAndOperators { + get { + OperatorMethod[] ops = logicalAndOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref logicalAndOperators, new OperatorMethod[] { + new LambdaBinaryOperatorMethod(this, (a, b) => a & b) + }); + } + } + } + + + OperatorMethod[] bitwiseAndOperators; + + public OperatorMethod[] BitwiseAndOperators { + get { + OperatorMethod[] ops = bitwiseAndOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref bitwiseAndOperators, Lift( + new LambdaBinaryOperatorMethod (this, (a, b) => a & b), + new LambdaBinaryOperatorMethod (this, (a, b) => a & b), + new LambdaBinaryOperatorMethod (this, (a, b) => a & b), + new LambdaBinaryOperatorMethod(this, (a, b) => a & b), + this.LogicalAndOperators[0] + )); + } + } + } + + + OperatorMethod[] logicalOrOperators; + + public OperatorMethod[] LogicalOrOperators { + get { + OperatorMethod[] ops = logicalOrOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref logicalOrOperators, new OperatorMethod[] { + new LambdaBinaryOperatorMethod(this, (a, b) => a | b) + }); + } + } + } + + OperatorMethod[] bitwiseOrOperators; + + public OperatorMethod[] BitwiseOrOperators { + get { + OperatorMethod[] ops = bitwiseOrOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref bitwiseOrOperators, Lift( + new LambdaBinaryOperatorMethod (this, (a, b) => a | b), + new LambdaBinaryOperatorMethod (this, (a, b) => a | b), + new LambdaBinaryOperatorMethod (this, (a, b) => a | b), + new LambdaBinaryOperatorMethod(this, (a, b) => a | b), + this.LogicalOrOperators[0] + )); + } + } + } + + // Note: the logic for the lifted bool? bitwise operators is wrong; + // we produce "true | null" = "null" when it should be true. However, this is irrelevant + // because bool? cannot be a compile-time type. + + OperatorMethod[] bitwiseXorOperators; + + public OperatorMethod[] BitwiseXorOperators { + get { + OperatorMethod[] ops = bitwiseXorOperators; + if (ops != null) { + LazyInit.ReadBarrier(); + return ops; + } else { + return LazyInit.GetOrSet(ref bitwiseXorOperators, Lift( + new LambdaBinaryOperatorMethod (this, (a, b) => a ^ b), + new LambdaBinaryOperatorMethod (this, (a, b) => a ^ b), + new LambdaBinaryOperatorMethod (this, (a, b) => a ^ b), + new LambdaBinaryOperatorMethod(this, (a, b) => a ^ b), + new LambdaBinaryOperatorMethod (this, (a, b) => a ^ b) + )); + } + } + } + #endregion + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs index 4b8b067770..21b207d6cd 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs @@ -24,7 +24,7 @@ using System.Globalization; using System.Linq; using System.Text; using System.Threading; - +using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; @@ -38,34 +38,49 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public class CSharpResolver { static readonly ResolveResult ErrorResult = ErrorResolveResult.UnknownError; - static readonly ResolveResult DynamicResult = new ResolveResult(SharedTypes.Dynamic); - static readonly ResolveResult NullResult = new ResolveResult(SharedTypes.Null); + static readonly ResolveResult DynamicResult = new ResolveResult(SpecialType.Dynamic); + static readonly ResolveResult NullResult = new ResolveResult(SpecialType.NullType); - readonly ITypeResolveContext context; + readonly ICompilation compilation; internal readonly Conversions conversions; - internal readonly CancellationToken cancellationToken; #region Constructor - public CSharpResolver(ITypeResolveContext context) : this (context, CancellationToken.None) + public CSharpResolver(ICompilation compilation) { + if (compilation == null) + throw new ArgumentNullException("compilation"); + this.compilation = compilation; + this.conversions = Conversions.Get(compilation); } - public CSharpResolver(ITypeResolveContext context, CancellationToken cancellationToken) + public CSharpResolver(ITypeResolveContext context) { if (context == null) throw new ArgumentNullException("context"); - this.context = context; - this.cancellationToken = cancellationToken; - this.conversions = Conversions.Get(context); + this.compilation = context.Compilation; + this.conversions = Conversions.Get(compilation); + this.CurrentMember = context.CurrentEntity as IMember; + if (this.CurrentMember != null) { + this.CurrentTypeDefinition = this.CurrentMember.DeclaringTypeDefinition; + } else { + this.CurrentTypeDefinition = context.CurrentEntity as ITypeDefinition; + } } #endregion #region Properties /// - /// Gets the type resolve context used by the resolver. + /// Gets the compilation used by the resolver. + /// + public ICompilation Compilation { + get { return compilation; } + } + + /// + /// Gets the current type resolve context. /// - public ITypeResolveContext Context { - get { return context; } + public ITypeResolveContext CurrentTypeResolveContext { + get { throw new NotImplementedException(); } } /// @@ -80,19 +95,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// Don't forget to also set CurrentTypeDefinition when setting CurrentMember; /// setting one of the properties does not automatically set the other. public IMember CurrentMember { get; set; } - - /// - /// Gets the current project content. - /// Returns CurrentUsingScope.ProjectContent. - /// - public IProjectContent ProjectContent { - get { - if (currentUsingScope != null) - return currentUsingScope.UsingScope.ProjectContent; - else - return null; - } - } #endregion #region Per-CurrentTypeDefinition Cache @@ -166,119 +168,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver #endregion #region Local Variable Management - class LocalVariable : IVariable - { - // We store the local variable in a linked list - // and provide a stack-like API. - // The beginning of a stack frame is marked by a dummy local variable - // with type==null and name==null. - - // This data structure is used to allow efficient cloning of the resolver with its local variable context. - - internal readonly LocalVariable prev; - internal readonly ITypeReference type; - internal readonly DomRegion region; - internal readonly string name; - internal readonly IConstantValue constantValue; - - public LocalVariable(LocalVariable prev, ITypeReference type, DomRegion region, string name, IConstantValue constantValue) - { - this.prev = prev; - this.region = region; - this.type = type; - this.name = name; - this.constantValue = constantValue; - } - - string IVariable.Name { - get { return name; } - } - - DomRegion IVariable.Region { - get { return region; } - } - - ITypeReference IVariable.Type { - get { return type; } - } - bool IVariable.IsConst { - get { return constantValue != null; } - } - IConstantValue IVariable.ConstantValue { - get { return constantValue; } - } - - public override string ToString() - { - if (name == null) - return ""; - else - return name + ":" + type; - } - } - sealed class LambdaParameter : LocalVariable, IParameter - { - readonly bool isRef; - readonly bool isOut; - - public LambdaParameter(LocalVariable prev, ITypeReference type, DomRegion region, string name, bool isRef, bool isOut) - : base(prev, type, region, name, null) - { - this.isRef = isRef; - this.isOut = isOut; - } - - IList IParameter.Attributes { - get { return EmptyList.Instance; } - } - - IConstantValue IParameter.DefaultValue { - get { return null; } - } - - bool IParameter.IsRef { - get { return isRef; } - } - - bool IParameter.IsOut { - get { return isOut; } - } - - bool IParameter.IsParams { - get { return false; } - } - - bool IParameter.IsOptional { - get { return false; } - } - - bool IFreezable.IsFrozen { - get { return true; } - } - - void IFreezable.Freeze() - { - } - } + // We store the local variables in an immutable stack. + // The beginning of a block is marked by a null entry. - LocalVariable localVariableStack; + // This data structure is used to allow efficient cloning of the resolver with its local variable context. + ImmutableStack localVariableStack = ImmutableStack.Empty; /// /// Opens a new scope for local variables. /// public void PushBlock() { - localVariableStack = new LocalVariable(localVariableStack, null, DomRegion.Empty, null, null); - } - - /// - /// Opens a new scope for local variables. - /// This works like , but additionally sets to true. - /// - public void PushLambdaBlock() - { - localVariableStack = new LambdaParameter(localVariableStack, null, DomRegion.Empty, null, false, false); + localVariableStack = localVariableStack.Push(null); } /// @@ -286,39 +188,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// public void PopBlock() { - LocalVariable removedVar; + IVariable removedVar; do { - removedVar = localVariableStack; - if (removedVar == null) - throw new InvalidOperationException("Cannot execute PopBlock() without corresponding PushBlock()"); - localVariableStack = removedVar.prev; - } while (removedVar.name != null); - } - - /// - /// Adds a new variable to the current block. - /// - public IVariable AddVariable(ITypeReference type, DomRegion declarationRegion, string name, IConstantValue constantValue = null) - { - if (type == null) - throw new ArgumentNullException("type"); - if (name == null) - throw new ArgumentNullException("name"); - return localVariableStack = new LocalVariable(localVariableStack, type, declarationRegion, name, constantValue); + removedVar = localVariableStack.Peek(); + localVariableStack = localVariableStack.Pop(); + } while (removedVar != null); } /// - /// Adds a new lambda parameter to the current block. + /// Adds a new variable or lambda parameter to the current block. /// - public IParameter AddLambdaParameter(ITypeReference type, DomRegion declarationRegion, string name, bool isRef = false, bool isOut = false) + public void AddVariable(IVariable variable) { - if (type == null) - throw new ArgumentNullException("type"); - if (name == null) - throw new ArgumentNullException("name"); - LambdaParameter p = new LambdaParameter(localVariableStack, type, declarationRegion, name, isRef, isOut); - localVariableStack = p; - return p; + if (variable == null) + throw new ArgumentNullException("variable"); + localVariableStack = localVariableStack.Push(variable); } /// @@ -326,25 +210,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// public IEnumerable LocalVariables { get { - for (LocalVariable v = localVariableStack; v != null; v = v.prev) { - if (v.name != null) - yield return v; - } + return localVariableStack.Where(v => v != null); } } /// /// Gets whether the resolver is currently within a lambda expression. /// - public bool IsWithinLambdaExpression { - get { - for (LocalVariable v = localVariableStack; v != null; v = v.prev) { - if (v.name == null && v is LambdaParameter) - return true; - } - return false; - } - } + public bool IsWithinLambdaExpression { get; set; } #endregion #region Object Initializer Context @@ -385,7 +258,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// has unknown type). /// public IType CurrentObjectInitializerType { - get { return objectInitializerStack != null ? objectInitializerStack.type : SharedTypes.UnknownType; } + get { return objectInitializerStack != null ? objectInitializerStack.type : SpecialType.UnknownType; } } #endregion @@ -399,205 +272,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } #endregion - #region class OperatorMethod - static OperatorMethod[] Lift(params OperatorMethod[] methods) - { - List result = new List(methods); - foreach (OperatorMethod method in methods) { - OperatorMethod lifted = method.Lift(); - if (lifted != null) - result.Add(lifted); - } - return result.ToArray(); - } - - class OperatorMethod : Immutable, IParameterizedMember - { - static readonly IParameter[] normalParameters = new IParameter[(int)(TypeCode.String + 1 - TypeCode.Object)]; - static readonly IParameter[] nullableParameters = new IParameter[(int)(TypeCode.Decimal + 1 - TypeCode.Boolean)]; - - static OperatorMethod() - { - for (TypeCode i = TypeCode.Object; i <= TypeCode.String; i++) { - normalParameters[i - TypeCode.Object] = new DefaultParameter(i.ToTypeReference(), string.Empty); - } - for (TypeCode i = TypeCode.Boolean; i <= TypeCode.Decimal; i++) { - nullableParameters[i - TypeCode.Boolean] = new DefaultParameter(NullableType.Create(i.ToTypeReference()), string.Empty); - } - } - - protected static IParameter MakeParameter(TypeCode code) - { - return normalParameters[code - TypeCode.Object]; - } - - protected static IParameter MakeNullableParameter(IParameter normalParameter) - { - for (TypeCode i = TypeCode.Boolean; i <= TypeCode.Decimal; i++) { - if (normalParameter == normalParameters[i - TypeCode.Object]) - return nullableParameters[i - TypeCode.Boolean]; - } - throw new ArgumentException(); - } - - readonly IList parameters = new List(); - - public IList Parameters { - get { return parameters; } - } - - public ITypeReference ReturnType { - get; set; - } - - public virtual OperatorMethod Lift() - { - return null; - } - - ITypeDefinition IEntity.DeclaringTypeDefinition { - get { throw new NotSupportedException(); } - } - - IType IMember.DeclaringType { - get { return SharedTypes.UnknownType; } - } - - IMember IMember.MemberDefinition { - get { return this; } - } - - IList IMember.InterfaceImplementations { - get { return EmptyList.Instance; } - } - - bool IMember.IsVirtual { - get { return false; } - } - - bool IMember.IsOverride { - get { return false; } - } - - bool IMember.IsOverridable { - get { return false; } - } - - EntityType IEntity.EntityType { - get { return EntityType.Operator; } - } - - DomRegion IEntity.Region { - get { return DomRegion.Empty; } - } - - DomRegion IEntity.BodyRegion { - get { return DomRegion.Empty; } - } - - IList IEntity.Attributes { - get { return EmptyList.Instance; } - } - - string IEntity.Documentation { - get { return null; } - } - - Accessibility IEntity.Accessibility { - get { return Accessibility.Public; } - } - - bool IEntity.IsStatic { - get { return true; } - } - - bool IEntity.IsAbstract { - get { return false; } - } - - bool IEntity.IsSealed { - get { return false; } - } - - bool IEntity.IsShadowing { - get { return false; } - } - - bool IEntity.IsSynthetic { - get { return true; } - } - - bool IEntity.IsPrivate { - get { return false; } - } - - bool IEntity.IsPublic { - get { return true; } - } - - bool IEntity.IsProtected { - get { return false; } - } - - bool IEntity.IsInternal { - get { return false; } - } - - bool IEntity.IsProtectedOrInternal { - get { return false; } - } - - bool IEntity.IsProtectedAndInternal { - get { return false; } - } - - IProjectContent IEntity.ProjectContent { - get { throw new NotSupportedException(); } - } - - IParsedFile IEntity.ParsedFile { - get { return null; } - } - - string INamedElement.FullName { - get { return "operator"; } - } - - string INamedElement.Name { - get { return "operator"; } - } - - string INamedElement.Namespace { - get { return string.Empty; } - } - - string INamedElement.ReflectionName { - get { return "operator"; } - } - - public override string ToString() - { - StringBuilder b = new StringBuilder(); - b.Append(ReturnType + " operator("); - for (int i = 0; i < parameters.Count; i++) { - if (i > 0) - b.Append(", "); - b.Append(parameters[i].Type); - } - b.Append(')'); - return b.ToString(); - } - } - #endregion - #region ResolveUnaryOperator #region ResolveUnaryOperator method public ResolveResult ResolveUnaryOperator(UnaryOperatorType op, ResolveResult expression) { - cancellationToken.ThrowIfCancellationRequested(); - - if (SharedTypes.Dynamic.Equals(expression.Type)) - return UnaryOperatorResolveResult(SharedTypes.Dynamic, op, expression); + if (SpecialType.Dynamic.Equals(expression.Type)) + return UnaryOperatorResolveResult(SpecialType.Dynamic, op, expression); // C# 4.0 spec: §7.3.3 Unary operator overload resolution string overloadableOperatorName = GetOverloadableOperatorName(op); @@ -616,11 +296,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult getAwaiterInvocation = ResolveInvocation(getAwaiterMethodGroup, new ResolveResult[0]); var getResultMethodGroup = CreateMemberLookup().Lookup(getAwaiterInvocation, "GetResult", EmptyList.Instance, true) as MethodGroupResolveResult; if (getResultMethodGroup != null) { - var or = getResultMethodGroup.PerformOverloadResolution(context, new ResolveResult[0], allowExtensionMethods: false, conversions: conversions); - IType awaitResultType = or.GetBestCandidateWithSubstitutedTypeArguments().ReturnType.Resolve(context); + var or = getResultMethodGroup.PerformOverloadResolution(compilation, new ResolveResult[0], allowExtensionMethods: false, conversions: conversions); + IType awaitResultType = or.GetBestCandidateWithSubstitutedTypeArguments().ReturnType; return UnaryOperatorResolveResult(awaitResultType, UnaryOperatorType.Await, expression); } else { - return UnaryOperatorResolveResult(SharedTypes.UnknownType, UnaryOperatorType.Await, expression); + return UnaryOperatorResolveResult(SpecialType.UnknownType, UnaryOperatorType.Await, expression); } default: throw new ArgumentException("Invalid value for UnaryOperatorType", "op"); @@ -631,7 +311,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver bool isNullable = NullableType.IsNullable(expression.Type); // the operator is overloadable: - OverloadResolution userDefinedOperatorOR = new OverloadResolution(context, new[] { expression }, conversions: conversions); + OverloadResolution userDefinedOperatorOR = new OverloadResolution(compilation, new[] { expression }, conversions: conversions); foreach (var candidate in GetUserDefinedOperatorCandidates(type, overloadableOperatorName)) { userDefinedOperatorOR.AddCandidate(candidate); } @@ -640,7 +320,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } expression = UnaryNumericPromotion(op, ref type, isNullable, expression); - OperatorMethod[] methodGroup; + CSharpOperators.OperatorMethod[] methodGroup; + CSharpOperators operators = CSharpOperators.Get(compilation); switch (op) { case UnaryOperatorType.Increment: case UnaryOperatorType.Decrement: @@ -654,37 +335,37 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver else return new ErrorResolveResult(expression.Type); case UnaryOperatorType.Plus: - methodGroup = unaryPlusOperators; + methodGroup = operators.UnaryPlusOperators; break; case UnaryOperatorType.Minus: - methodGroup = CheckForOverflow ? checkedUnaryMinusOperators : uncheckedUnaryMinusOperators; + methodGroup = CheckForOverflow ? operators.CheckedUnaryMinusOperators : operators.UncheckedUnaryMinusOperators; break; case UnaryOperatorType.Not: - methodGroup = logicalNegationOperator; + methodGroup = operators.LogicalNegationOperators; break; case UnaryOperatorType.BitNot: if (type.Kind == TypeKind.Enum) { if (expression.IsCompileTimeConstant && !isNullable) { // evaluate as (E)(~(U)x); - var U = expression.ConstantValue.GetType().ToTypeReference().Resolve(context); + var U = compilation.FindType(expression.ConstantValue.GetType()); var unpackedEnum = new ConstantResolveResult(U, expression.ConstantValue); return CheckErrorAndResolveCast(expression.Type, ResolveUnaryOperator(op, unpackedEnum)); } else { return UnaryOperatorResolveResult(expression.Type, op, expression); } } else { - methodGroup = bitwiseComplementOperators; + methodGroup = operators.BitwiseComplementOperators; break; } default: throw new InvalidOperationException(); } - OverloadResolution builtinOperatorOR = new OverloadResolution(context, new[] { expression }, conversions: conversions); + OverloadResolution builtinOperatorOR = new OverloadResolution(compilation, new[] { expression }, conversions: conversions); foreach (var candidate in methodGroup) { builtinOperatorOR.AddCandidate(candidate); } - UnaryOperatorMethod m = (UnaryOperatorMethod)builtinOperatorOR.BestCandidate; - IType resultType = m.ReturnType.Resolve(context); + CSharpOperators.UnaryOperatorMethod m = (CSharpOperators.UnaryOperatorMethod)builtinOperatorOR.BestCandidate; + IType resultType = m.ReturnType; if (builtinOperatorOR.BestCandidateErrors != OverloadResolutionErrors.None) { // If there are any user-defined operators, prefer those over the built-in operators. // It'll be a more informative error. @@ -692,7 +373,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return CreateResolveResultForUserDefinedOperator(userDefinedOperatorOR); else return new ErrorResolveResult(resultType); - } else if (expression.IsCompileTimeConstant && !isNullable) { + } else if (expression.IsCompileTimeConstant && m.CanEvaluateAtCompileTime) { object val; try { val = m.Invoke(this, expression.ConstantValue); @@ -717,12 +398,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { // C# 4.0 spec: §7.3.6.1 TypeCode code = ReflectionHelper.GetTypeCode(type); - if (isNullable && SharedTypes.Null.Equals(type)) + if (isNullable && SpecialType.NullType.Equals(type)) code = TypeCode.SByte; // cause promotion of null to int32 switch (op) { case UnaryOperatorType.Minus: if (code == TypeCode.UInt32) { - type = KnownTypeReference.Int64.Resolve(context); + type = compilation.FindType(KnownTypeCode.Int64); return Convert(expression, MakeNullable(type, isNullable), isNullable ? Conversion.ImplicitNullableConversion : Conversion.ImplicitNumericConversion); } @@ -730,7 +411,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver case UnaryOperatorType.Plus: case UnaryOperatorType.BitNot: if (code >= TypeCode.Char && code <= TypeCode.UInt16) { - type = KnownTypeReference.Int32.Resolve(context); + type = compilation.FindType(KnownTypeCode.Int32); return Convert(expression, MakeNullable(type, isNullable), isNullable ? Conversion.ImplicitNullableConversion : Conversion.ImplicitNumericConversion); } @@ -763,112 +444,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } #endregion - - #region Unary operator class definitions - abstract class UnaryOperatorMethod : OperatorMethod - { - public abstract object Invoke(CSharpResolver resolver, object input); - } - - sealed class LambdaUnaryOperatorMethod : UnaryOperatorMethod - { - readonly Func func; - - public LambdaUnaryOperatorMethod(Func func) - { - TypeCode t = Type.GetTypeCode(typeof(T)); - this.ReturnType = t.ToTypeReference(); - this.Parameters.Add(MakeParameter(t)); - this.func = func; - } - - public override object Invoke(CSharpResolver resolver, object input) - { - return func((T)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T)), input)); - } - - public override OperatorMethod Lift() - { - return new LiftedUnaryOperatorMethod(this); - } - } - - sealed class LiftedUnaryOperatorMethod : UnaryOperatorMethod, OverloadResolution.ILiftedOperator - { - UnaryOperatorMethod baseMethod; - - public LiftedUnaryOperatorMethod(UnaryOperatorMethod baseMethod) - { - this.baseMethod = baseMethod; - this.ReturnType = NullableType.Create(baseMethod.ReturnType); - this.Parameters.Add(MakeNullableParameter(baseMethod.Parameters[0])); - } - - public override object Invoke(CSharpResolver resolver, object input) - { - if (input == null) - return null; - else - return baseMethod.Invoke(resolver, input); - } - - public IList NonLiftedParameters { - get { return baseMethod.Parameters; } - } - } - #endregion - - #region Unary operator definitions - // C# 4.0 spec: §7.7.1 Unary plus operator - static readonly OperatorMethod[] unaryPlusOperators = Lift( - new LambdaUnaryOperatorMethod(i => +i), - new LambdaUnaryOperatorMethod(i => +i), - new LambdaUnaryOperatorMethod(i => +i), - new LambdaUnaryOperatorMethod(i => +i), - new LambdaUnaryOperatorMethod(i => +i), - new LambdaUnaryOperatorMethod(i => +i), - new LambdaUnaryOperatorMethod(i => +i) - ); - - // C# 4.0 spec: §7.7.2 Unary minus operator - static readonly OperatorMethod[] uncheckedUnaryMinusOperators = Lift( - new LambdaUnaryOperatorMethod(i => unchecked(-i)), - new LambdaUnaryOperatorMethod(i => unchecked(-i)), - new LambdaUnaryOperatorMethod(i => -i), - new LambdaUnaryOperatorMethod(i => -i), - new LambdaUnaryOperatorMethod(i => -i) - ); - static readonly OperatorMethod[] checkedUnaryMinusOperators = Lift( - new LambdaUnaryOperatorMethod(i => checked(-i)), - new LambdaUnaryOperatorMethod(i => checked(-i)), - new LambdaUnaryOperatorMethod(i => -i), - new LambdaUnaryOperatorMethod(i => -i), - new LambdaUnaryOperatorMethod(i => -i) - ); - - // C# 4.0 spec: §7.7.3 Logical negation operator - static readonly OperatorMethod[] logicalNegationOperator = Lift(new LambdaUnaryOperatorMethod(b => !b)); - - // C# 4.0 spec: §7.7.4 Bitwise complement operator - static readonly OperatorMethod[] bitwiseComplementOperators = Lift( - new LambdaUnaryOperatorMethod(i => ~i), - new LambdaUnaryOperatorMethod(i => ~i), - new LambdaUnaryOperatorMethod(i => ~i), - new LambdaUnaryOperatorMethod(i => ~i) - ); - #endregion #endregion #region ResolveBinaryOperator #region ResolveBinaryOperator method public ResolveResult ResolveBinaryOperator(BinaryOperatorType op, ResolveResult lhs, ResolveResult rhs) { - cancellationToken.ThrowIfCancellationRequested(); - - if (SharedTypes.Dynamic.Equals(lhs.Type) || SharedTypes.Dynamic.Equals(rhs.Type)) { - lhs = Convert(lhs, SharedTypes.Dynamic); - rhs = Convert(rhs, SharedTypes.Dynamic); - return BinaryOperatorResolveResult(SharedTypes.Dynamic, lhs, op, rhs); + if (SpecialType.Dynamic.Equals(lhs.Type) || SpecialType.Dynamic.Equals(rhs.Type)) { + lhs = Convert(lhs, SpecialType.Dynamic); + rhs = Convert(rhs, SpecialType.Dynamic); + return BinaryOperatorResolveResult(SpecialType.Dynamic, lhs, op, rhs); } // C# 4.0 spec: §7.3.4 Binary operator overload resolution @@ -897,7 +482,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver IType rhsType = NullableType.GetUnderlyingType(rhs.Type); // the operator is overloadable: - OverloadResolution userDefinedOperatorOR = new OverloadResolution(context, new[] { lhs, rhs }, conversions: conversions); + OverloadResolution userDefinedOperatorOR = new OverloadResolution(compilation, new[] { lhs, rhs }, conversions: conversions); HashSet userOperatorCandidates = new HashSet(); userOperatorCandidates.UnionWith(GetUserDefinedOperatorCandidates(lhsType, overloadableOperatorName)); userOperatorCandidates.UnionWith(GetUserDefinedOperatorCandidates(rhsType, overloadableOperatorName)); @@ -908,14 +493,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return CreateResolveResultForUserDefinedOperator(userDefinedOperatorOR); } - if (SharedTypes.Null.Equals(lhsType) && rhsType.IsReferenceType(context) == false - || lhsType.IsReferenceType(context) == false && SharedTypes.Null.Equals(rhsType)) + if (SpecialType.NullType.Equals(lhsType) && rhsType.IsReferenceType == false + || lhsType.IsReferenceType == false && SpecialType.NullType.Equals(rhsType)) { isNullable = true; } if (op == BinaryOperatorType.ShiftLeft || op == BinaryOperatorType.ShiftRight) { // special case: the shift operators allow "var x = null << null", producing int?. - if (SharedTypes.Null.Equals(lhsType) && SharedTypes.Null.Equals(rhsType)) + if (SpecialType.NullType.Equals(lhsType) && SpecialType.NullType.Equals(rhsType)) isNullable = true; // for shift operators, do unary promotion independently on both arguments lhs = UnaryNumericPromotion(UnaryOperatorType.Plus, ref lhsType, isNullable, lhs); @@ -929,30 +514,31 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver lhsType = NullableType.GetUnderlyingType(lhs.Type); rhsType = NullableType.GetUnderlyingType(rhs.Type); - IEnumerable methodGroup; + IEnumerable methodGroup; + CSharpOperators operators = CSharpOperators.Get(compilation); switch (op) { case BinaryOperatorType.Multiply: - methodGroup = CheckForOverflow ? checkedMultiplicationOperators : uncheckedMultiplicationOperators; + methodGroup = operators.MultiplicationOperators; break; case BinaryOperatorType.Divide: - methodGroup = CheckForOverflow ? checkedDivisionOperators : uncheckedDivisionOperators; + methodGroup = operators.DivisionOperators; break; case BinaryOperatorType.Modulus: - methodGroup = CheckForOverflow ? checkedRemainderOperators : uncheckedRemainderOperators; + methodGroup = operators.RemainderOperators; break; case BinaryOperatorType.Add: - methodGroup = CheckForOverflow ? checkedAdditionOperators : uncheckedAdditionOperators; + methodGroup = operators.AdditionOperators; { if (lhsType.Kind == TypeKind.Enum) { // E operator +(E x, U y); - IType underlyingType = MakeNullable(lhsType.GetEnumUnderlyingType(context), isNullable); + IType underlyingType = MakeNullable(GetEnumUnderlyingType(lhsType), isNullable); if (TryConvert(ref rhs, underlyingType)) { return HandleEnumOperator(isNullable, lhsType, op, lhs, rhs); } } if (rhsType.Kind == TypeKind.Enum) { // E operator +(U x, E y); - IType underlyingType = MakeNullable(rhsType.GetEnumUnderlyingType(context), isNullable); + IType underlyingType = MakeNullable(GetEnumUnderlyingType(rhsType), isNullable); if (TryConvert(ref lhs, underlyingType)) { return HandleEnumOperator(isNullable, rhsType, op, lhs, rhs); } @@ -966,29 +552,29 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (lhsType is PointerType) { methodGroup = new [] { - new PointerArithmeticOperator(lhsType, lhsType, KnownTypeReference.Int32), - new PointerArithmeticOperator(lhsType, lhsType, KnownTypeReference.UInt32), - new PointerArithmeticOperator(lhsType, lhsType, KnownTypeReference.Int64), - new PointerArithmeticOperator(lhsType, lhsType, KnownTypeReference.UInt64) + PointerArithmeticOperator(lhsType, lhsType, KnownTypeCode.Int32), + PointerArithmeticOperator(lhsType, lhsType, KnownTypeCode.UInt32), + PointerArithmeticOperator(lhsType, lhsType, KnownTypeCode.Int64), + PointerArithmeticOperator(lhsType, lhsType, KnownTypeCode.UInt64) }; } else if (rhsType is PointerType) { methodGroup = new [] { - new PointerArithmeticOperator(rhsType, KnownTypeReference.Int32, rhsType), - new PointerArithmeticOperator(rhsType, KnownTypeReference.UInt32, rhsType), - new PointerArithmeticOperator(rhsType, KnownTypeReference.Int64, rhsType), - new PointerArithmeticOperator(rhsType, KnownTypeReference.UInt64, rhsType) + PointerArithmeticOperator(rhsType, KnownTypeCode.Int32, rhsType), + PointerArithmeticOperator(rhsType, KnownTypeCode.UInt32, rhsType), + PointerArithmeticOperator(rhsType, KnownTypeCode.Int64, rhsType), + PointerArithmeticOperator(rhsType, KnownTypeCode.UInt64, rhsType) }; } - if (SharedTypes.Null.Equals(lhsType) && SharedTypes.Null.Equals(rhsType)) - return new ErrorResolveResult(SharedTypes.Null); + if (SpecialType.NullType.Equals(lhsType) && SpecialType.NullType.Equals(rhsType)) + return new ErrorResolveResult(SpecialType.NullType); } break; case BinaryOperatorType.Subtract: - methodGroup = CheckForOverflow ? checkedSubtractionOperators : uncheckedSubtractionOperators; + methodGroup = operators.SubtractionOperators; { if (lhsType.Kind == TypeKind.Enum) { // E operator –(E x, U y); - IType underlyingType = MakeNullable(lhsType.GetEnumUnderlyingType(context), isNullable); + IType underlyingType = MakeNullable(GetEnumUnderlyingType(lhsType), isNullable); if (TryConvert(ref rhs, underlyingType)) { return HandleEnumOperator(isNullable, lhsType, op, lhs, rhs); } @@ -1012,7 +598,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (lhsType is PointerType) { if (rhsType is PointerType) { - IType int64 = KnownTypeReference.Int64.Resolve(context); + IType int64 = compilation.FindType(KnownTypeCode.Int64); if (lhsType.Equals(rhsType)) { return BinaryOperatorResolveResult(int64, lhs, op, rhs); } else { @@ -1020,22 +606,22 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } methodGroup = new [] { - new PointerArithmeticOperator(lhsType, lhsType, KnownTypeReference.Int32), - new PointerArithmeticOperator(lhsType, lhsType, KnownTypeReference.UInt32), - new PointerArithmeticOperator(lhsType, lhsType, KnownTypeReference.Int64), - new PointerArithmeticOperator(lhsType, lhsType, KnownTypeReference.UInt64) + PointerArithmeticOperator(lhsType, lhsType, KnownTypeCode.Int32), + PointerArithmeticOperator(lhsType, lhsType, KnownTypeCode.UInt32), + PointerArithmeticOperator(lhsType, lhsType, KnownTypeCode.Int64), + PointerArithmeticOperator(lhsType, lhsType, KnownTypeCode.UInt64) }; } - if (SharedTypes.Null.Equals(lhsType) && SharedTypes.Null.Equals(rhsType)) - return new ErrorResolveResult(SharedTypes.Null); + if (SpecialType.NullType.Equals(lhsType) && SpecialType.NullType.Equals(rhsType)) + return new ErrorResolveResult(SpecialType.NullType); } break; case BinaryOperatorType.ShiftLeft: - methodGroup = shiftLeftOperators; + methodGroup = operators.ShiftLeftOperators; break; case BinaryOperatorType.ShiftRight: - methodGroup = shiftRightOperators; + methodGroup = operators.ShiftRightOperators; break; case BinaryOperatorType.Equality: case BinaryOperatorType.InEquality: @@ -1051,26 +637,26 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // bool operator op(E x, E y); return HandleEnumComparison(op, rhsType, isNullable, lhs, rhs); } else if (lhsType is PointerType && rhsType is PointerType) { - return BinaryOperatorResolveResult(KnownTypeReference.Boolean.Resolve(context), lhs, op, rhs); + return BinaryOperatorResolveResult(compilation.FindType(KnownTypeCode.Boolean), lhs, op, rhs); } switch (op) { case BinaryOperatorType.Equality: - methodGroup = equalityOperators; + methodGroup = operators.EqualityOperators; break; case BinaryOperatorType.InEquality: - methodGroup = inequalityOperators; + methodGroup = operators.InequalityOperators; break; case BinaryOperatorType.LessThan: - methodGroup = lessThanOperators; + methodGroup = operators.LessThanOperators; break; case BinaryOperatorType.GreaterThan: - methodGroup = greaterThanOperators; + methodGroup = operators.GreaterThanOperators; break; case BinaryOperatorType.LessThanOrEqual: - methodGroup = lessThanOrEqualOperators; + methodGroup = operators.LessThanOrEqualOperators; break; case BinaryOperatorType.GreaterThanOrEqual: - methodGroup = greaterThanOrEqualOperators; + methodGroup = operators.GreaterThanOrEqualOperators; break; default: throw new InvalidOperationException(); @@ -1091,13 +677,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver switch (op) { case BinaryOperatorType.BitwiseAnd: - methodGroup = bitwiseAndOperators; + methodGroup = operators.BitwiseAndOperators; break; case BinaryOperatorType.BitwiseOr: - methodGroup = bitwiseOrOperators; + methodGroup = operators.BitwiseOrOperators; break; case BinaryOperatorType.ExclusiveOr: - methodGroup = bitwiseXorOperators; + methodGroup = operators.BitwiseXorOperators; break; default: throw new InvalidOperationException(); @@ -1105,20 +691,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } break; case BinaryOperatorType.ConditionalAnd: - methodGroup = logicalAndOperator; + methodGroup = operators.LogicalAndOperators; break; case BinaryOperatorType.ConditionalOr: - methodGroup = logicalOrOperator; + methodGroup = operators.LogicalOrOperators; break; default: throw new InvalidOperationException(); } - OverloadResolution builtinOperatorOR = new OverloadResolution(context, new[] { lhs, rhs }, conversions: conversions); + OverloadResolution builtinOperatorOR = new OverloadResolution(compilation, new[] { lhs, rhs }, conversions: conversions); foreach (var candidate in methodGroup) { builtinOperatorOR.AddCandidate(candidate); } - BinaryOperatorMethod m = (BinaryOperatorMethod)builtinOperatorOR.BestCandidate; - IType resultType = m.ReturnType.Resolve(context); + CSharpOperators.BinaryOperatorMethod m = (CSharpOperators.BinaryOperatorMethod)builtinOperatorOR.BestCandidate; + IType resultType = m.ReturnType; if (builtinOperatorOR.BestCandidateErrors != OverloadResolutionErrors.None) { // If there are any user-defined operators, prefer those over the built-in operators. // It'll be a more informative error. @@ -1147,7 +733,30 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } #endregion + #region Pointer arithmetic + CSharpOperators.BinaryOperatorMethod PointerArithmeticOperator(IType resultType, IType inputType1, KnownTypeCode inputType2) + { + return PointerArithmeticOperator(resultType, inputType1, compilation.FindType(inputType2)); + } + + CSharpOperators.BinaryOperatorMethod PointerArithmeticOperator(IType resultType, KnownTypeCode inputType1, IType inputType2) + { + return PointerArithmeticOperator(resultType, compilation.FindType(inputType1), inputType2); + } + + CSharpOperators.BinaryOperatorMethod PointerArithmeticOperator(IType resultType, IType inputType1, IType inputType2) + { + throw new NotImplementedException(); + } + #endregion + #region Enum helper methods + IType GetEnumUnderlyingType(IType enumType) + { + ITypeDefinition def = enumType.GetDefinition(); + return def != null ? def.EnumUnderlyingType : SpecialType.UnknownType; + } + /// /// Handle the case where an enum value is compared with another enum value /// bool operator op(E x, E y); @@ -1155,7 +764,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult HandleEnumComparison(BinaryOperatorType op, IType enumType, bool isNullable, ResolveResult lhs, ResolveResult rhs) { // evaluate as ((U)x op (U)y) - IType elementType = enumType.GetEnumUnderlyingType(context); + IType elementType = GetEnumUnderlyingType(enumType); if (lhs.IsCompileTimeConstant && rhs.IsCompileTimeConstant && !isNullable) { lhs = ResolveCast(elementType, lhs); if (lhs.IsError) @@ -1165,7 +774,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return rhs; return ResolveBinaryOperator(op, lhs, rhs); } - IType resultType = KnownTypeReference.Boolean.Resolve(context); + IType resultType = compilation.FindType(KnownTypeCode.Boolean); return BinaryOperatorResolveResult(resultType, lhs, op, rhs); } @@ -1176,7 +785,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult HandleEnumSubtraction(bool isNullable, IType enumType, ResolveResult lhs, ResolveResult rhs) { // evaluate as (U)((U)x – (U)y) - IType elementType = enumType.GetEnumUnderlyingType(context); + IType elementType = GetEnumUnderlyingType(enumType); if (lhs.IsCompileTimeConstant && rhs.IsCompileTimeConstant && !isNullable) { lhs = ResolveCast(elementType, lhs); if (lhs.IsError) @@ -1203,7 +812,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { // evaluate as (E)((U)x op (U)y) if (lhs.IsCompileTimeConstant && rhs.IsCompileTimeConstant && !isNullable) { - IType elementType = enumType.GetEnumUnderlyingType(context); + IType elementType = GetEnumUnderlyingType(enumType); lhs = ResolveCast(elementType, lhs); if (lhs.IsError) return lhs; @@ -1219,7 +828,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver IType MakeNullable(IType type, bool isNullable) { if (isNullable) - return NullableType.Create(type, context); + return NullableType.Create(compilation, type); else return type; } @@ -1232,10 +841,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver TypeCode lhsCode = ReflectionHelper.GetTypeCode(NullableType.GetUnderlyingType(lhs.Type)); TypeCode rhsCode = ReflectionHelper.GetTypeCode(NullableType.GetUnderlyingType(rhs.Type)); // if one of the inputs is the null literal, promote that to the type of the other operand - if (isNullable && SharedTypes.Null.Equals(lhs.Type)) { + if (isNullable && SpecialType.NullType.Equals(lhs.Type)) { lhs = CastTo(rhsCode, isNullable, lhs, allowNullableConstants); lhsCode = rhsCode; - } else if (isNullable && SharedTypes.Null.Equals(rhs.Type)) { + } else if (isNullable && SpecialType.NullType.Equals(rhs.Type)) { rhs = CastTo(lhsCode, isNullable, rhs, allowNullableConstants); rhsCode = lhsCode; } @@ -1295,7 +904,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult CastTo(TypeCode targetType, bool isNullable, ResolveResult expression, bool allowNullableConstants) { - IType elementType = targetType.ToTypeReference().Resolve(context); + IType elementType = compilation.FindType(targetType); IType nullableType = MakeNullable(elementType, isNullable); if (nullableType.Equals(expression.Type)) return expression; @@ -1356,419 +965,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } #endregion - #region Binary operator class definitions - abstract class BinaryOperatorMethod : OperatorMethod - { - public virtual bool CanEvaluateAtCompileTime { get { return true; } } - public abstract object Invoke(CSharpResolver resolver, object lhs, object rhs); - } - - sealed class PointerArithmeticOperator : BinaryOperatorMethod - { - public PointerArithmeticOperator(ITypeReference returnType, ITypeReference parameter1, ITypeReference parameter2) - { - this.ReturnType = returnType; - this.Parameters.Add(new DefaultParameter(parameter1, "x")); - this.Parameters.Add(new DefaultParameter(parameter2, "y")); - } - - public override bool CanEvaluateAtCompileTime { - get { return false; } - } - - public override object Invoke(CSharpResolver resolver, object lhs, object rhs) - { - throw new NotSupportedException(); - } - } - - sealed class LambdaBinaryOperatorMethod : BinaryOperatorMethod - { - readonly Func func; - - public LambdaBinaryOperatorMethod(Func func) - { - TypeCode t1 = Type.GetTypeCode(typeof(T1)); - this.ReturnType = t1.ToTypeReference(); - this.Parameters.Add(MakeParameter(t1)); - this.Parameters.Add(MakeParameter(Type.GetTypeCode(typeof(T2)))); - this.func = func; - } - - public override object Invoke(CSharpResolver resolver, object lhs, object rhs) - { - return func((T1)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T1)), lhs), - (T2)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T2)), rhs)); - } - - public override OperatorMethod Lift() - { - return new LiftedBinaryOperatorMethod(this); - } - } - - sealed class LiftedBinaryOperatorMethod : BinaryOperatorMethod, OverloadResolution.ILiftedOperator - { - readonly BinaryOperatorMethod baseMethod; - - public LiftedBinaryOperatorMethod(BinaryOperatorMethod baseMethod) - { - this.baseMethod = baseMethod; - this.ReturnType = NullableType.Create(baseMethod.ReturnType); - this.Parameters.Add(MakeNullableParameter(baseMethod.Parameters[0])); - this.Parameters.Add(MakeNullableParameter(baseMethod.Parameters[1])); - } - - public override bool CanEvaluateAtCompileTime { - get { return false; } - } - - public override object Invoke(CSharpResolver resolver, object lhs, object rhs) - { - throw new NotSupportedException(); // cannot use nullables at compile time - } - - public IList NonLiftedParameters { - get { return baseMethod.Parameters; } - } - } - #endregion - - #region Arithmetic operators - // C# 4.0 spec: §7.8.1 Multiplication operator - static readonly OperatorMethod[] checkedMultiplicationOperators = Lift( - new LambdaBinaryOperatorMethod ((a, b) => checked(a * b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a * b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a * b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a * b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a * b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a * b)), - new LambdaBinaryOperatorMethod((a, b) => checked(a * b)) - ); - static readonly OperatorMethod[] uncheckedMultiplicationOperators = Lift( - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a * b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a * b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a * b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a * b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a * b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a * b)), - new LambdaBinaryOperatorMethod((a, b) => unchecked(a * b)) - ); - - // C# 4.0 spec: §7.8.2 Division operator - static readonly OperatorMethod[] checkedDivisionOperators = Lift( - new LambdaBinaryOperatorMethod ((a, b) => checked(a / b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a / b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a / b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a / b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a / b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a / b)), - new LambdaBinaryOperatorMethod((a, b) => checked(a / b)) - ); - static readonly OperatorMethod[] uncheckedDivisionOperators = Lift( - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a / b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a / b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a / b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a / b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a / b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a / b)), - new LambdaBinaryOperatorMethod((a, b) => unchecked(a / b)) - ); - - // C# 4.0 spec: §7.8.3 Remainder operator - static readonly OperatorMethod[] checkedRemainderOperators = Lift( - new LambdaBinaryOperatorMethod ((a, b) => checked(a % b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a % b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a % b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a % b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a % b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a % b)), - new LambdaBinaryOperatorMethod((a, b) => checked(a % b)) - ); - static readonly OperatorMethod[] uncheckedRemainderOperators = Lift( - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a % b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a % b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a % b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a % b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a % b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a % b)), - new LambdaBinaryOperatorMethod((a, b) => unchecked(a % b)) - ); - - // C# 4.0 spec: §7.8.3 Addition operator - static readonly OperatorMethod[] checkedAdditionOperators = Lift( - new LambdaBinaryOperatorMethod ((a, b) => checked(a + b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a + b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a + b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a + b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a + b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a + b)), - new LambdaBinaryOperatorMethod((a, b) => checked(a + b)), - new StringConcatenation(TypeCode.String, TypeCode.String), - new StringConcatenation(TypeCode.String, TypeCode.Object), - new StringConcatenation(TypeCode.Object, TypeCode.String) - ); - static readonly OperatorMethod[] uncheckedAdditionOperators = Lift( - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a + b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a + b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a + b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a + b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a + b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a + b)), - new LambdaBinaryOperatorMethod((a, b) => unchecked(a + b)), - new StringConcatenation(TypeCode.String, TypeCode.String), - new StringConcatenation(TypeCode.String, TypeCode.Object), - new StringConcatenation(TypeCode.Object, TypeCode.String) - ); - // not in this list, but handled manually: enum addition, delegate combination - sealed class StringConcatenation : BinaryOperatorMethod - { - bool canEvaluateAtCompileTime; - - public StringConcatenation(TypeCode p1, TypeCode p2) - { - this.canEvaluateAtCompileTime = p1 == TypeCode.String && p2 == TypeCode.String; - this.ReturnType = KnownTypeReference.String; - this.Parameters.Add(MakeParameter(p1)); - this.Parameters.Add(MakeParameter(p2)); - } - - public override bool CanEvaluateAtCompileTime { - get { return canEvaluateAtCompileTime; } - } - - public override object Invoke(CSharpResolver resolver, object lhs, object rhs) - { - return string.Concat(lhs, rhs); - } - } - - // C# 4.0 spec: §7.8.4 Subtraction operator - static readonly OperatorMethod[] checkedSubtractionOperators = Lift( - new LambdaBinaryOperatorMethod ((a, b) => checked(a - b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a - b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a - b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a - b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a - b)), - new LambdaBinaryOperatorMethod ((a, b) => checked(a - b)), - new LambdaBinaryOperatorMethod((a, b) => checked(a - b)) - ); - static readonly OperatorMethod[] uncheckedSubtractionOperators = Lift( - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a - b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a - b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a - b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a - b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a - b)), - new LambdaBinaryOperatorMethod ((a, b) => unchecked(a - b)), - new LambdaBinaryOperatorMethod((a, b) => unchecked(a - b)) - ); - - // C# 4.0 spec: §7.8.5 Shift operators - static readonly OperatorMethod[] shiftLeftOperators = Lift( - new LambdaBinaryOperatorMethod((a, b) => a << b), - new LambdaBinaryOperatorMethod((a, b) => a << b), - new LambdaBinaryOperatorMethod((a, b) => a << b), - new LambdaBinaryOperatorMethod((a, b) => a << b) - ); - static readonly OperatorMethod[] shiftRightOperators = Lift( - new LambdaBinaryOperatorMethod((a, b) => a >> b), - new LambdaBinaryOperatorMethod((a, b) => a >> b), - new LambdaBinaryOperatorMethod((a, b) => a >> b), - new LambdaBinaryOperatorMethod((a, b) => a >> b) - ); - #endregion - - #region Equality operators - sealed class EqualityOperatorMethod : BinaryOperatorMethod - { - public readonly TypeCode Type; - public readonly bool Negate; - - public EqualityOperatorMethod(TypeCode type, bool negate) - { - this.Negate = negate; - this.Type = type; - this.ReturnType = KnownTypeReference.Boolean; - this.Parameters.Add(MakeParameter(type)); - this.Parameters.Add(MakeParameter(type)); - } - - public override bool CanEvaluateAtCompileTime { - get { return Type != TypeCode.Object; } - } - - public override object Invoke(CSharpResolver resolver, object lhs, object rhs) - { - lhs = resolver.CSharpPrimitiveCast(Type, lhs); - rhs = resolver.CSharpPrimitiveCast(Type, rhs); - bool equal; - if (Type == TypeCode.Single) { - equal = (float)lhs == (float)rhs; - } else if (Type == TypeCode.Double) { - equal = (double)lhs == (double)rhs; - } else { - equal = object.Equals(lhs, rhs); - } - return equal ^ Negate; - } - - public override OperatorMethod Lift() - { - if (Type == TypeCode.Object || Type == TypeCode.String) - return null; - else - return new LiftedEqualityOperatorMethod(this); - } - } - - sealed class LiftedEqualityOperatorMethod : BinaryOperatorMethod, OverloadResolution.ILiftedOperator - { - readonly EqualityOperatorMethod baseMethod; - - public LiftedEqualityOperatorMethod(EqualityOperatorMethod baseMethod) - { - this.baseMethod = baseMethod; - this.ReturnType = baseMethod.ReturnType; - IParameter p = MakeNullableParameter(baseMethod.Parameters[0]); - this.Parameters.Add(p); - this.Parameters.Add(p); - } - - public override bool CanEvaluateAtCompileTime { - get { return baseMethod.CanEvaluateAtCompileTime; } - } - - public override object Invoke(CSharpResolver resolver, object lhs, object rhs) - { - if (lhs == null && rhs == null) - return !baseMethod.Negate; // ==: true; !=: false - if (lhs == null || rhs == null) - return baseMethod.Negate; // ==: false; !=: true - return baseMethod.Invoke(resolver, lhs, rhs); - } - - public IList NonLiftedParameters { - get { return baseMethod.Parameters; } - } - } - - // C# 4.0 spec: §7.10 Relational and type-testing operators - static readonly TypeCode[] equalityOperatorsFor = { - TypeCode.Int32, TypeCode.UInt32, - TypeCode.Int64, TypeCode.UInt64, - TypeCode.Single, TypeCode.Double, - TypeCode.Decimal, - TypeCode.Boolean, - TypeCode.String, TypeCode.Object - }; - - static readonly OperatorMethod[] equalityOperators = Lift(equalityOperatorsFor.Select(c => new EqualityOperatorMethod(c, false)).ToArray()); - static readonly OperatorMethod[] inequalityOperators = Lift(equalityOperatorsFor.Select(c => new EqualityOperatorMethod(c, true)).ToArray()); - #endregion - - #region Relational Operators - sealed class RelationalOperatorMethod : BinaryOperatorMethod - { - readonly Func func; - - public RelationalOperatorMethod(Func func) - { - this.ReturnType = KnownTypeReference.Boolean; - this.Parameters.Add(MakeParameter(Type.GetTypeCode(typeof(T1)))); - this.Parameters.Add(MakeParameter(Type.GetTypeCode(typeof(T2)))); - this.func = func; - } - - public override object Invoke(CSharpResolver resolver, object lhs, object rhs) - { - return func((T1)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T1)), lhs), - (T2)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T2)), rhs)); - } - - public override OperatorMethod Lift() - { - return new LiftedBinaryOperatorMethod(this); - } - } - - static readonly OperatorMethod[] lessThanOperators = Lift( - new RelationalOperatorMethod ((a, b) => a < b), - new RelationalOperatorMethod ((a, b) => a < b), - new RelationalOperatorMethod ((a, b) => a < b), - new RelationalOperatorMethod ((a, b) => a < b), - new RelationalOperatorMethod ((a, b) => a < b), - new RelationalOperatorMethod ((a, b) => a < b), - new RelationalOperatorMethod((a, b) => a < b) - ); - - static readonly OperatorMethod[] lessThanOrEqualOperators = Lift( - new RelationalOperatorMethod ((a, b) => a <= b), - new RelationalOperatorMethod ((a, b) => a <= b), - new RelationalOperatorMethod ((a, b) => a <= b), - new RelationalOperatorMethod ((a, b) => a <= b), - new RelationalOperatorMethod ((a, b) => a <= b), - new RelationalOperatorMethod ((a, b) => a <= b), - new RelationalOperatorMethod((a, b) => a <= b) - ); - - static readonly OperatorMethod[] greaterThanOperators = Lift( - new RelationalOperatorMethod ((a, b) => a > b), - new RelationalOperatorMethod ((a, b) => a > b), - new RelationalOperatorMethod ((a, b) => a > b), - new RelationalOperatorMethod ((a, b) => a > b), - new RelationalOperatorMethod ((a, b) => a > b), - new RelationalOperatorMethod ((a, b) => a > b), - new RelationalOperatorMethod((a, b) => a > b) - ); - - static readonly OperatorMethod[] greaterThanOrEqualOperators = Lift( - new RelationalOperatorMethod ((a, b) => a >= b), - new RelationalOperatorMethod ((a, b) => a >= b), - new RelationalOperatorMethod ((a, b) => a >= b), - new RelationalOperatorMethod ((a, b) => a >= b), - new RelationalOperatorMethod ((a, b) => a >= b), - new RelationalOperatorMethod ((a, b) => a >= b), - new RelationalOperatorMethod((a, b) => a >= b) - ); - #endregion - - #region Bitwise operators - static readonly OperatorMethod[] logicalAndOperator = { - new LambdaBinaryOperatorMethod ((a, b) => a & b) - }; - - static readonly OperatorMethod[] bitwiseAndOperators = Lift( - new LambdaBinaryOperatorMethod ((a, b) => a & b), - new LambdaBinaryOperatorMethod ((a, b) => a & b), - new LambdaBinaryOperatorMethod ((a, b) => a & b), - new LambdaBinaryOperatorMethod((a, b) => a & b), - logicalAndOperator[0] - ); - - static readonly OperatorMethod[] logicalOrOperator = { - new LambdaBinaryOperatorMethod ((a, b) => a | b) - }; - - static readonly OperatorMethod[] bitwiseOrOperators = Lift( - new LambdaBinaryOperatorMethod ((a, b) => a | b), - new LambdaBinaryOperatorMethod ((a, b) => a | b), - new LambdaBinaryOperatorMethod ((a, b) => a | b), - new LambdaBinaryOperatorMethod((a, b) => a | b), - logicalOrOperator[0] - ); - // Note: the logic for the lifted bool? bitwise operators is wrong; - // we produce "true | null" = "null" when it should be true. However, this is irrelevant - // because bool? cannot be a compile-time type. - - static readonly OperatorMethod[] bitwiseXorOperators = Lift( - new LambdaBinaryOperatorMethod ((a, b) => a ^ b), - new LambdaBinaryOperatorMethod ((a, b) => a ^ b), - new LambdaBinaryOperatorMethod ((a, b) => a ^ b), - new LambdaBinaryOperatorMethod((a, b) => a ^ b), - new LambdaBinaryOperatorMethod ((a, b) => a ^ b) - ); - #endregion - #region Null coalescing operator ResolveResult ResolveNullCoalescingOperator(ResolveResult lhs, ResolveResult rhs) { @@ -1802,12 +998,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return EmptyList.Instance; } // C# 4.0 spec: §7.3.5 Candidate user-defined operators - var operators = type.GetMethods(context, m => m.IsOperator && m.Name == operatorName).ToList(); + var operators = type.GetMethods(m => m.IsOperator && m.Name == operatorName).ToList(); LiftUserDefinedOperators(operators); return operators; } - void LiftUserDefinedOperators(List operators) + void LiftUserDefinedOperators(List operators) { int nonLiftedMethodCount = operators.Count; // Construct lifted operators @@ -1818,29 +1014,25 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } - LiftedUserDefinedOperator LiftUserDefinedOperator(IParameterizedMember m) + LiftedUserDefinedOperator LiftUserDefinedOperator(IMethod m) { - IType returnType = m.ReturnType.Resolve(context); - if (!NullableType.IsNonNullableValueType(returnType, context)) + IType returnType = m.ReturnType; + if (!NullableType.IsNonNullableValueType(returnType)) return null; // cannot lift this operator - LiftedUserDefinedOperator liftedOperator = new LiftedUserDefinedOperator(m); for (int i = 0; i < m.Parameters.Count; i++) { - IType parameterType = m.Parameters[i].Type.Resolve(context); - if (!NullableType.IsNonNullableValueType(parameterType, context)) + if (!NullableType.IsNonNullableValueType(m.Parameters[i].Type)) return null; // cannot lift this operator - var p = new DefaultParameter(m.Parameters[i]); - p.Type = NullableType.Create(parameterType, context); - liftedOperator.Parameters.Add(p); } - liftedOperator.ReturnType = NullableType.Create(returnType, context); - return liftedOperator; + return new LiftedUserDefinedOperator(m); } - sealed class LiftedUserDefinedOperator : OperatorMethod, OverloadResolution.ILiftedOperator + sealed class LiftedUserDefinedOperator : SpecializedMethod, OverloadResolution.ILiftedOperator { internal readonly IParameterizedMember nonLiftedOperator; - public LiftedUserDefinedOperator(IParameterizedMember nonLiftedMethod) + public LiftedUserDefinedOperator(IMethod nonLiftedMethod) + : base(nonLiftedMethod.DeclaringType, (IMethod)nonLiftedMethod.MemberDefinition, + EmptyList.Instance, new MakeNullableVisitor(nonLiftedMethod.Compilation)) { this.nonLiftedOperator = nonLiftedMethod; } @@ -1861,19 +1053,39 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } - ResolveResult CreateResolveResultForUserDefinedOperator(OverloadResolution r) + sealed class MakeNullableVisitor : TypeVisitor { - LiftedUserDefinedOperator lifted = r.BestCandidate as LiftedUserDefinedOperator; - if (lifted != null) { - return new CSharpInvocationResolveResult( - null, lifted.nonLiftedOperator, lifted.ReturnType.Resolve(context), - r.GetArgumentsWithConversions(), r.BestCandidateErrors, - isLiftedOperatorInvocation: true, - argumentToParameterMap: r.GetArgumentToParameterMap() - ); - } else { - return r.CreateResolveResult(null); + readonly ICompilation compilation; + + public MakeNullableVisitor(ICompilation compilation) + { + this.compilation = compilation; + } + + public override IType VisitTypeDefinition(ITypeDefinition type) + { + return NullableType.Create(compilation, type); + } + + public override IType VisitTypeParameter(ITypeParameter type) + { + return NullableType.Create(compilation, type); } + + public override IType VisitParameterizedType(ParameterizedType type) + { + return NullableType.Create(compilation, type); + } + + public override IType VisitOtherType(IType type) + { + return NullableType.Create(compilation, type); + } + } + + ResolveResult CreateResolveResultForUserDefinedOperator(OverloadResolution r) + { + return r.CreateResolveResult(null); } #endregion @@ -1894,20 +1106,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return Convert(rr, targetType, conversions.ImplicitConversion(rr, targetType)); } - ResolveResult Convert(ResolveResult rr, ITypeReference targetType, Conversion c) + ResolveResult Convert(ResolveResult rr, IType targetType, Conversion c) { if (c == Conversion.IdentityConversion) return rr; else if (rr.IsCompileTimeConstant && c != Conversion.None) - return ResolveCast(targetType.Resolve(context), rr); + return ResolveCast(targetType, rr); else - return new ConversionResolveResult(targetType.Resolve(context), rr, c); + return new ConversionResolveResult(targetType, rr, c); } public ResolveResult ResolveCast(IType targetType, ResolveResult expression) { - cancellationToken.ThrowIfCancellationRequested(); - // C# 4.0 spec: §7.7.6 Cast expressions if (expression.IsCompileTimeConstant) { TypeCode code = ReflectionHelper.GetTypeCode(targetType); @@ -1923,7 +1133,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver else return new ErrorResolveResult(targetType); } else if (targetType.Kind == TypeKind.Enum) { - code = ReflectionHelper.GetTypeCode(targetType.GetEnumUnderlyingType(context)); + code = ReflectionHelper.GetTypeCode(GetEnumUnderlyingType(targetType)); if (code >= TypeCode.SByte && code <= TypeCode.UInt64 && expression.ConstantValue != null) { try { return new ConstantResolveResult(targetType, CSharpPrimitiveCast(code, expression.ConstantValue)); @@ -1941,7 +1151,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } - object CSharpPrimitiveCast(TypeCode targetType, object input) + internal object CSharpPrimitiveCast(TypeCode targetType, object input) { return Utils.CSharpPrimitiveCast.Cast(targetType, input, this.CheckForOverflow); } @@ -1974,8 +1184,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (typeArguments == null) throw new ArgumentNullException("typeArguments"); - cancellationToken.ThrowIfCancellationRequested(); - int k = typeArguments.Count; if (k == 0) { @@ -1983,8 +1191,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // Look in local variables foreach (IVariable v in this.LocalVariables) { if (v.Name == identifier) { - object constantValue = v.IsConst ? v.ConstantValue.Resolve(context).ConstantValue : null; - return new LocalResolveResult(v, v.Type.Resolve(context), constantValue); + return new LocalResolveResult(v); } } // Look in parameters of current method @@ -1992,7 +1199,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (parameterizedMember != null) { foreach (IParameter p in parameterizedMember.Parameters) { if (p.Name == identifier) { - return new LocalResolveResult(p, p.Type.Resolve(context)); + return new LocalResolveResult(p); } } } @@ -2054,13 +1261,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return r; } - if (typeArguments.Count == 0) { - if (identifier == "dynamic") - return new TypeResolveResult(SharedTypes.Dynamic); - else - return new UnknownIdentifierResolveResult(identifier); + if (typeArguments.Count == 0 && identifier == "dynamic") { + return new TypeResolveResult(SpecialType.Dynamic); } else { - return new UnknownTypeResolveResult(identifier, typeArguments.Count); + return new UnknownIdentifierResolveResult(identifier, typeArguments.Count); } } @@ -2084,7 +1288,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver continue; } - MemberLookup lookup = new MemberLookup(context, t, t.ProjectContent); + MemberLookup lookup = new MemberLookup(t, t.ParentAssembly); ResolveResult r; if (lookupMode == SimpleNameLookupMode.Expression || lookupMode == SimpleNameLookupMode.InvocationTarget) { r = lookup.Lookup(new TypeResolveResult(t), identifier, typeArguments, lookupMode == SimpleNameLookupMode.InvocationTarget); @@ -2102,52 +1306,51 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver int k = typeArguments.Count; // look in current namespace definitions UsingScope currentUsingScope = this.CurrentUsingScope; - for (UsingScope n = currentUsingScope; n != null; n = n.Parent) { + for (UsingScope u = currentUsingScope; u != null; u = u.Parent) { + INamespace n = u.ResolveNamespace(compilation); // first look for a namespace - if (k == 0) { - string fullName = NamespaceDeclaration.BuildQualifiedName(n.NamespaceName, identifier); - if (context.GetNamespace(fullName, StringComparer.Ordinal) != null) { - if (n.HasAlias(identifier)) - return new AmbiguousTypeResolveResult(SharedTypes.UnknownType); - return new NamespaceResolveResult(fullName); + if (k == 0 && n != null) { + INamespace childNamespace = n.GetChildNamespace(identifier); + if (childNamespace != null) { + if (u.HasAlias(identifier)) + return new AmbiguousTypeResolveResult(SpecialType.UnknownType); + return new NamespaceResolveResult(childNamespace); } } // then look for a type - ITypeDefinition def = context.GetTypeDefinition(n.NamespaceName, identifier, k, StringComparer.Ordinal); - if (def != null) { - IType result = def; - if (parameterizeResultType) { - result = new ParameterizedType(def, typeArguments); + if (n != null) { + ITypeDefinition def = n.GetTypeDefinition(identifier, k); + if (def != null) { + IType result = def; + if (parameterizeResultType) { + result = new ParameterizedType(def, typeArguments); + } + if (u.HasAlias(identifier)) + return new AmbiguousTypeResolveResult(result); + else + return new TypeResolveResult(result); } - if (n.HasAlias(identifier)) - return new AmbiguousTypeResolveResult(result); - else - return new TypeResolveResult(result); } // then look for aliases: if (k == 0) { - if (n.ExternAliases.Contains(identifier)) { + if (u.ExternAliases.Contains(identifier)) { return ResolveExternAlias(identifier); } - if (!(isInUsingDeclaration && n == currentUsingScope)) { - foreach (var pair in n.UsingAliases) { + if (!(isInUsingDeclaration && u == currentUsingScope)) { + foreach (var pair in u.UsingAliases) { if (pair.Key == identifier) { - NamespaceResolveResult ns = pair.Value.ResolveNamespace(context); - if (ns != null) - return ns; - else - return new TypeResolveResult(pair.Value.Resolve(context)); + return pair.Value.Resolve(this); } } } } // finally, look in the imported namespaces: - if (!(isInUsingDeclaration && n == currentUsingScope)) { + if (!(isInUsingDeclaration && u == currentUsingScope)) { IType firstResult = null; - foreach (var u in n.Usings) { - NamespaceResolveResult ns = u.ResolveNamespace(context); - if (ns != null) { - def = context.GetTypeDefinition(ns.NamespaceName, identifier, k, StringComparer.Ordinal); + foreach (var import in u.Usings) { + INamespace importedNamespace = import.ResolveNamespace(this); + if (importedNamespace != null) { + ITypeDefinition def = importedNamespace.GetTypeDefinition(identifier, k); if (def != null) { if (firstResult == null) { if (parameterizeResultType && k > 0) @@ -2174,7 +1377,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public ResolveResult ResolveAlias(string identifier) { if (identifier == "global") - return new NamespaceResolveResult(string.Empty); + return new NamespaceResolveResult(compilation.RootNamespace); for (UsingScope n = this.CurrentUsingScope; n != null; n = n.Parent) { if (n.ExternAliases.Contains(identifier)) { @@ -2182,17 +1385,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } foreach (var pair in n.UsingAliases) { if (pair.Key == identifier) { - return pair.Value.ResolveNamespace(context) ?? ErrorResult; + return (pair.Value.Resolve(this) as NamespaceResolveResult) ?? ErrorResult; } } } return ErrorResult; } - static ResolveResult ResolveExternAlias(string alias) + ResolveResult ResolveExternAlias(string alias) { - // TODO: implement extern alias support - return new NamespaceResolveResult(string.Empty); + INamespace ns = compilation.GetNamespaceForExternAlias(alias); + if (ns != null) + return new NamespaceResolveResult(ns); + else + return ErrorResult; } #endregion @@ -2201,14 +1407,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { // C# 4.0 spec: §7.6.4 - cancellationToken.ThrowIfCancellationRequested(); - NamespaceResolveResult nrr = target as NamespaceResolveResult; if (nrr != null) { return ResolveMemberAccessOnNamespace(nrr, identifier, typeArguments, typeArguments.Count > 0); } - if (SharedTypes.Dynamic.Equals(target.Type)) + if (SpecialType.Dynamic.Equals(target.Type)) return DynamicResult; MemberLookup lookup = CreateMemberLookup(); @@ -2234,8 +1438,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public ResolveResult ResolveMemberType(ResolveResult target, string identifier, IList typeArguments) { - cancellationToken.ThrowIfCancellationRequested(); - bool parameterizeResultType = !(typeArguments.Count != 0 && typeArguments.All(t => t.Kind == TypeKind.UnboundTypeArgument)); NamespaceResolveResult nrr = target as NamespaceResolveResult; @@ -2250,11 +1452,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult ResolveMemberAccessOnNamespace(NamespaceResolveResult nrr, string identifier, IList typeArguments, bool parameterizeResultType) { if (typeArguments.Count == 0) { - string fullName = NamespaceDeclaration.BuildQualifiedName(nrr.NamespaceName, identifier); - if (context.GetNamespace(fullName, StringComparer.Ordinal) != null) - return new NamespaceResolveResult(fullName); + INamespace childNamespace = nrr.Namespace.GetChildNamespace(identifier); + if (childNamespace != null) + return new NamespaceResolveResult(childNamespace); } - ITypeDefinition def = context.GetTypeDefinition(nrr.NamespaceName, identifier, typeArguments.Count, StringComparer.Ordinal); + ITypeDefinition def = nrr.Namespace.GetTypeDefinition(identifier, typeArguments.Count); if (def != null) { if (parameterizeResultType && typeArguments.Count > 0) return new TypeResolveResult(new ParameterizedType(def, typeArguments)); @@ -2269,7 +1471,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// public MemberLookup CreateMemberLookup() { - return new MemberLookup(context, this.CurrentTypeDefinition, this.ProjectContent); + return new MemberLookup(this.CurrentTypeDefinition, this.Compilation.MainAssembly); } #endregion @@ -2342,16 +1544,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver extensionMethodGroups = new List>(); List m; for (UsingScope scope = currentUsingScope.UsingScope; scope != null; scope = scope.Parent) { - m = GetExtensionMethods(scope.NamespaceName).ToList(); - if (m.Count > 0) - extensionMethodGroups.Add(m); + INamespace ns = scope.ResolveNamespace(compilation); + if (ns != null) { + m = GetExtensionMethods(ns).ToList(); + if (m.Count > 0) + extensionMethodGroups.Add(m); + } - m = ( - from u in scope.Usings - select u.ResolveNamespace(context) into ns - where ns != null - select ns.NamespaceName - ).Distinct().SelectMany(ns => GetExtensionMethods(ns)).ToList(); + m = scope.Usings + .Select(u => u.ResolveNamespace(this)) + .Where(importedNamespace => importedNamespace != null) + .Distinct() + .SelectMany(importedNamespace => GetExtensionMethods(importedNamespace)) + .ToList(); if (m.Count > 0) extensionMethodGroups.Add(m); } @@ -2359,10 +1564,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return extensionMethodGroups; } - IEnumerable GetExtensionMethods(string namespaceName) + IEnumerable GetExtensionMethods(INamespace ns) { + // TODO: maybe make this a property on INamespace? return - from c in context.GetTypes(namespaceName, StringComparer.Ordinal) + from c in ns.Types where c.IsStatic && c.HasExtensionMethods && c.TypeParameters.Count == 0 from m in c.Methods where m.IsExtensionMethod @@ -2387,14 +1593,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { // C# 4.0 spec: §7.6.5 - cancellationToken.ThrowIfCancellationRequested(); - - if (SharedTypes.Dynamic.Equals(target.Type)) + if (SpecialType.Dynamic.Equals(target.Type)) return DynamicResult; MethodGroupResolveResult mgrr = target as MethodGroupResolveResult; if (mgrr != null) { - OverloadResolution or = mgrr.PerformOverloadResolution(context, arguments, argumentNames, conversions: conversions); + OverloadResolution or = mgrr.PerformOverloadResolution(compilation, arguments, argumentNames, conversions: conversions); if (or.BestCandidate != null) { return or.CreateResolveResult(mgrr.TargetResult); } else { @@ -2414,10 +1618,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } IMethod invokeMethod = target.Type.GetDelegateInvokeMethod(); if (invokeMethod != null) { - OverloadResolution or = new OverloadResolution(context, arguments, argumentNames, conversions: conversions); + OverloadResolution or = new OverloadResolution(compilation, arguments, argumentNames, conversions: conversions); or.AddCandidate(invokeMethod); return new CSharpInvocationResolveResult( - target, invokeMethod, invokeMethod.ReturnType.Resolve(context), + target, invokeMethod, //invokeMethod.ReturnType.Resolve(context), or.GetArgumentsWithConversions(), or.BestCandidateErrors, isExpandedForm: or.BestCandidateIsExpandedForm, isDelegateInvocation: true, @@ -2426,7 +1630,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return ErrorResult; } - static List CreateParameters(ResolveResult[] arguments, string[] argumentNames) + List CreateParameters(ResolveResult[] arguments, string[] argumentNames) { List list = new List(); if (argumentNames == null) { @@ -2456,15 +1660,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // create the parameter: ByReferenceResolveResult brrr = arguments[i] as ByReferenceResolveResult; if (brrr != null) { - list.Add(new DefaultParameter(arguments[i].Type, argumentNames[i]) { - IsRef = brrr.IsRef, - IsOut = brrr.IsOut - }); + list.Add(new DefaultParameter(arguments[i].Type, argumentNames[i], isRef: brrr.IsRef, isOut: brrr.IsOut)); } else { // argument might be a lambda or delegate type, so we have to try to guess the delegate type IType type = arguments[i].Type; - if (SharedTypes.Null.Equals(type) || SharedTypes.UnknownType.Equals(type)) { - list.Add(new DefaultParameter(KnownTypeReference.Object, argumentNames[i])); + if (SpecialType.NullType.Equals(type) || SpecialType.UnknownType.Equals(type)) { + list.Add(new DefaultParameter(compilation.FindType(KnownTypeCode.Object), argumentNames[i])); } else { list.Add(new DefaultParameter(type, argumentNames[i])); } @@ -2491,7 +1692,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (vrr != null) return MakeParameterName(vrr.Variable.Name); - if (rr.Type != SharedTypes.UnknownType && !string.IsNullOrEmpty(rr.Type.Name)) { + if (rr.Type != SpecialType.UnknownType && !string.IsNullOrEmpty(rr.Type.Name)) { return MakeParameterName(rr.Type.Name); } else { return "parameter"; @@ -2523,14 +1724,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// ArrayAccessResolveResult, InvocationResolveResult, or ErrorResolveResult public ResolveResult ResolveIndexer(ResolveResult target, ResolveResult[] arguments, string[] argumentNames = null) { - cancellationToken.ThrowIfCancellationRequested(); - switch (target.Type.Kind) { case TypeKind.Dynamic: for (int i = 0; i < arguments.Length; i++) { - arguments[i] = Convert(arguments[i], SharedTypes.Dynamic); + arguments[i] = Convert(arguments[i], SpecialType.Dynamic); } - return new ArrayAccessResolveResult(SharedTypes.Dynamic, target, arguments); + return new ArrayAccessResolveResult(SpecialType.Dynamic, target, arguments); case TypeKind.Array: case TypeKind.Pointer: @@ -2540,7 +1739,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } // §7.6.6.2 Indexer access - OverloadResolution or = new OverloadResolution(context, arguments, argumentNames, conversions: conversions); + OverloadResolution or = new OverloadResolution(compilation, arguments, argumentNames, conversions: conversions); MemberLookup lookup = CreateMemberLookup(); var indexers = lookup.LookupIndexers(target.Type); or.AddMethodLists(indexers); @@ -2557,13 +1756,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver void AdjustArrayAccessArguments(ResolveResult[] arguments) { for (int i = 0; i < arguments.Length; i++) { - if (!(TryConvert(ref arguments[i], KnownTypeReference.Int32.Resolve(context)) || - TryConvert(ref arguments[i], KnownTypeReference.UInt32.Resolve(context)) || - TryConvert(ref arguments[i], KnownTypeReference.Int64.Resolve(context)) || - TryConvert(ref arguments[i], KnownTypeReference.UInt64.Resolve(context)))) + if (!(TryConvert(ref arguments[i], compilation.FindType(KnownTypeCode.Int32)) || + TryConvert(ref arguments[i], compilation.FindType(KnownTypeCode.UInt32)) || + TryConvert(ref arguments[i], compilation.FindType(KnownTypeCode.Int64)) || + TryConvert(ref arguments[i], compilation.FindType(KnownTypeCode.UInt64)))) { // conversion failed - arguments[i] = Convert(arguments[i], KnownTypeReference.Int32, Conversion.None); + arguments[i] = Convert(arguments[i], compilation.FindType(KnownTypeCode.Int32), Conversion.None); } } } @@ -2584,15 +1783,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// InvocationResolveResult or ErrorResolveResult public ResolveResult ResolveObjectCreation(IType type, ResolveResult[] arguments, string[] argumentNames = null) { - cancellationToken.ThrowIfCancellationRequested(); - if (type.Kind == TypeKind.Delegate && arguments.Length == 1) { return Convert(arguments[0], type); } - OverloadResolution or = new OverloadResolution(context, arguments, argumentNames, conversions: conversions); + OverloadResolution or = new OverloadResolution(compilation, arguments, argumentNames, conversions: conversions); MemberLookup lookup = CreateMemberLookup(); bool allowProtectedAccess = lookup.IsProtectedAccessAllowed(type); - var constructors = type.GetConstructors(context, m => lookup.IsAccessible(m, allowProtectedAccess)); + var constructors = type.GetConstructors(m => lookup.IsAccessible(m, allowProtectedAccess)); foreach (IMethod ctor in constructors) { or.AddCandidate(ctor); } @@ -2610,7 +1807,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// public ResolveResult ResolveSizeOf(IType type) { - IType int32 = KnownTypeReference.Int32.Resolve(context); + IType int32 = compilation.FindType(KnownTypeCode.Int32); int size; switch (ReflectionHelper.GetTypeCode(type)) { case TypeCode.Boolean: @@ -2660,7 +1857,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { ITypeDefinition t = CurrentTypeDefinition; if (t != null) { - foreach (IType baseType in t.GetBaseTypes(context)) { + foreach (IType baseType in t.DirectBaseTypes) { if (baseType.Kind != TypeKind.Unknown && baseType.Kind != TypeKind.Interface) { return new ResolveResult(baseType); } @@ -2675,12 +1872,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { // C# 4.0 spec §7.14: Conditional operator - cancellationToken.ThrowIfCancellationRequested(); - bool isValid; IType resultType; - if (SharedTypes.Dynamic.Equals(trueExpression.Type) || SharedTypes.Dynamic.Equals(falseExpression.Type)) { - resultType = SharedTypes.Dynamic; + if (SpecialType.Dynamic.Equals(trueExpression.Type) || SpecialType.Dynamic.Equals(falseExpression.Type)) { + resultType = SpecialType.Dynamic; isValid = TryConvert(ref trueExpression, resultType) & TryConvert(ref falseExpression, resultType); } else if (HasType(trueExpression) && HasType(falseExpression)) { Conversion t2f = conversions.ImplicitConversion(trueExpression.Type, falseExpression.Type); @@ -2709,7 +1904,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } else { return ErrorResult; } - isValid &= TryConvert(ref condition, KnownTypeReference.Boolean.Resolve(context)); + isValid &= TryConvert(ref condition, compilation.FindType(KnownTypeCode.Boolean)); if (isValid) { if (condition.IsCompileTimeConstant && trueExpression.IsCompileTimeConstant && falseExpression.IsCompileTimeConstant) { bool? val = condition.ConstantValue as bool?; @@ -2727,7 +1922,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver bool HasType(ResolveResult r) { - return !(SharedTypes.UnknownType.Equals(r.Type) || SharedTypes.Null.Equals(r.Type)); + return !(SpecialType.UnknownType.Equals(r.Type) || SpecialType.NullType.Equals(r.Type)); } #endregion @@ -2738,7 +1933,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return NullResult; } else { TypeCode typeCode = Type.GetTypeCode(value.GetType()); - IType type = typeCode.ToTypeReference().Resolve(context); + IType type = compilation.FindType(typeCode); return new ConstantResolveResult(type, value); } } @@ -2813,11 +2008,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (sizeArguments != null && dimensions != Math.Max(1, sizeArguments.Length)) throw new ArgumentException("dimensions and sizeArguments.Length don't match"); if (elementType == null) { - TypeInference typeInference = new TypeInference(context, conversions); + TypeInference typeInference = new TypeInference(compilation, conversions); bool success; elementType = typeInference.GetBestCommonType(initializerElements, out success); } - IType arrayType = new ArrayType(elementType, dimensions); + IType arrayType = new ArrayType(compilation, elementType, dimensions); if (sizeArguments != null) AdjustArrayAccessArguments(sizeArguments); diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/Conversions.cs b/ICSharpCode.NRefactory.CSharp/Resolver/Conversions.cs index e54b871151..1b4a0c00bf 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/Conversions.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/Conversions.cs @@ -17,10 +17,10 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; - using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.Utils; @@ -241,38 +241,38 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// /// Contains logic that determines whether an implicit conversion exists between two types. /// - public class Conversions + /// + /// Because this class internally uses a cache, it is NOT thread-safe! + /// + public sealed class Conversions { readonly Dictionary implicitConversionCache = new Dictionary(); - readonly ITypeResolveContext context; + readonly ICompilation compilation; readonly IType objectType; + int subtypeCheckNestingDepth; - public Conversions(ITypeResolveContext context) + public Conversions(ICompilation compilation) { - if (context == null) - throw new ArgumentNullException("context"); - this.context = context; - this.objectType = KnownTypeReference.Object.Resolve(context); + if (compilation == null) + throw new ArgumentNullException("compilation"); + this.compilation = compilation; + this.objectType = compilation.FindType(KnownTypeCode.Object); this.dynamicErasure = new DynamicErasure(this); } /// - /// Gets the Conversions instance for the specified . + /// Gets the Conversions instance for the specified . /// This will make use of the context's cache manager (if available) to reuse the Conversions instance. /// - public static Conversions Get(ITypeResolveContext context) + public static Conversions Get(ICompilation compilation) { - CacheManager cache = context.CacheManager; - if (cache != null) { - Conversions conversions = cache.GetThreadLocal(typeof(Conversions)) as Conversions; - if (conversions == null) { - conversions = new Conversions(context); - cache.SetThreadLocal(typeof(Conversions), conversions); - } - return conversions; - } else { - return new Conversions(context); + CacheManager cache = compilation.CacheManager; + Conversions conversions = (Conversions)cache.GetThreadLocal(typeof(Conversions)); + if (conversions == null) { + conversions = new Conversions(compilation); + cache.SetThreadLocal(typeof(Conversions), conversions); } + return conversions; } #region TypePair (for caching) @@ -482,7 +482,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public override IType VisitOtherType(IType type) { - if (type == SharedTypes.Dynamic) + if (type.Kind == TypeKind.Dynamic) return objectType; else return base.VisitOtherType(type); @@ -589,8 +589,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver bool NullLiteralConversion(IType fromType, IType toType) { // C# 4.0 spec: §6.1.5 - if (SharedTypes.Null.Equals(fromType)) { - return NullableType.IsNullable(toType) || toType.IsReferenceType(context) == true; + if (SpecialType.NullType.Equals(fromType)) { + return NullableType.IsNullable(toType) || toType.IsReferenceType == true; } else { return false; } @@ -603,7 +603,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // C# 4.0 spec: §6.1.6 // reference conversions are possible only if both types are known to be reference types - if (!(fromType.IsReferenceType(context) == true && toType.IsReferenceType(context) == true)) + if (!(fromType.IsReferenceType == true && toType.IsReferenceType == true)) return false; ArrayType fromArray = fromType as ArrayType; @@ -625,8 +625,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver || ImplicitReferenceConversion(fromArray.ElementType, toPT.GetTypeArgument(0)); } // conversion from any array to System.Array and the interfaces it implements: - ITypeDefinition systemArray = context.GetTypeDefinition("System", "Array", 0, StringComparer.Ordinal); - return systemArray != null && (systemArray.Equals(toType) || ImplicitReferenceConversion(systemArray, toType)); + IType systemArray = KnownTypeReference.Array.Resolve(compilation.TypeResolveContext); + return systemArray.Kind != TypeKind.Unknown && (systemArray.Equals(toType) || ImplicitReferenceConversion(systemArray, toType)); } // now comes the hard part: traverse the inheritance chain and figure out generics+variance @@ -636,12 +636,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // Determines whether s is a subtype of t. // Helper method used for ImplicitReferenceConversion, BoxingConversion and ImplicitTypeParameterConversion - int subtypeCheckNestingDepth; - bool IsSubtypeOf(IType s, IType t) { // conversion to dynamic + object are always possible - if (t.Equals(SharedTypes.Dynamic) || t.Equals(objectType)) + if (t.Equals(SpecialType.Dynamic) || t.Equals(objectType)) return true; try { if (++subtypeCheckNestingDepth > 10) { @@ -654,7 +652,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return false; } // let GetAllBaseTypes do the work for us - foreach (IType baseType in s.GetAllBaseTypes(context)) { + foreach (IType baseType in s.GetAllBaseTypes()) { if (IdentityOrVarianceConversion(baseType, t)) return true; } @@ -706,11 +704,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // C# 4.0 spec: §6.2.4 // reference conversions are possible only if both types are known to be reference types - if (!(fromType.IsReferenceType(context) == true && toType.IsReferenceType(context) == true)) + if (!(fromType.IsReferenceType == true && toType.IsReferenceType == true)) return false; // There's lots of additional rules, but they're not really relevant, - // as they are only used to identify invalid casts, and we don't care about reporting those. + // as they are only used to identify invalid casts, and we currently don't care about reporting those. return true; } #endregion @@ -720,7 +718,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { // C# 4.0 spec: §6.1.7 fromType = NullableType.GetUnderlyingType(fromType); - if (fromType.IsReferenceType(context) == false && toType.IsReferenceType(context) == true) + if (fromType.IsReferenceType == false && toType.IsReferenceType == true) return IsSubtypeOf(fromType, toType); else return false; @@ -730,7 +728,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { // C# 4.0 spec: §6.2.5 toType = NullableType.GetUnderlyingType(toType); - if (fromType.IsReferenceType(context) == true && toType.IsReferenceType(context) == false) + if (fromType.IsReferenceType == true && toType.IsReferenceType == false) return IsSubtypeOf(toType, fromType); else return false; @@ -776,7 +774,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { if (fromType.Kind != TypeKind.TypeParameter) return false; // not a type parameter - if (fromType.IsReferenceType(context) == true) + if (fromType.IsReferenceType == true) return false; // already handled by ImplicitReferenceConversion return IsSubtypeOf(fromType, toType); } @@ -784,7 +782,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver bool ExplicitTypeParameterConversion(IType fromType, IType toType) { if (toType.Kind == TypeKind.TypeParameter) { - return fromType.Kind == TypeKind.TypeParameter || fromType.IsReferenceType(context) == true; + return fromType.Kind == TypeKind.TypeParameter || fromType.IsReferenceType == true; } else { return fromType.Kind == TypeKind.TypeParameter && toType.Kind == TypeKind.Interface; } @@ -797,7 +795,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // C# 4.0 spec: §18.4 Pointer conversions if (fromType is PointerType && toType is PointerType && toType.ReflectionName == "System.Void*") return true; - if (SharedTypes.Null.Equals(fromType) && toType is PointerType) + if (SpecialType.NullType.Equals(fromType) && toType is PointerType) return true; return false; } @@ -881,13 +879,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver else opFilter = m => m.IsStatic && m.IsOperator && m.Name == "op_Implicit" && m.Parameters.Count == 1; - var operators = NullableType.GetUnderlyingType(fromType).GetMethods(context, opFilter) - .Concat(NullableType.GetUnderlyingType(toType).GetMethods(context, opFilter)).Distinct(); + var operators = NullableType.GetUnderlyingType(fromType).GetMethods(opFilter) + .Concat(NullableType.GetUnderlyingType(toType).GetMethods(opFilter)).Distinct(); // Determine whether one of them is applicable: List result = new List(); foreach (IMethod op in operators) { - IType sourceType = op.Parameters[0].Type.Resolve(context); - IType targetType = op.ReturnType.Resolve(context); + IType sourceType = op.Parameters[0].Type; + IType targetType = op.ReturnType; // Try if the operator is applicable: bool isApplicable; if (isExplicit) { @@ -900,11 +898,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver result.Add(new OperatorInfo(op, sourceType, targetType, false)); } // Try if the operator is applicable in lifted form: - if (NullableType.IsNonNullableValueType(sourceType, context) - && NullableType.IsNonNullableValueType(targetType, context)) + if (NullableType.IsNonNullableValueType(sourceType) + && NullableType.IsNonNullableValueType(targetType)) { - IType liftedSourceType = NullableType.Create(sourceType, context); - IType liftedTargetType = NullableType.Create(targetType, context); + IType liftedSourceType = NullableType.Create(compilation, sourceType); + IType liftedTargetType = NullableType.Create(compilation, targetType); if (isExplicit) { isApplicable = IsEncompassingOrEncompassedBy(fromType, liftedSourceType) && IsEncompassingOrEncompassedBy(liftedTargetType, toType); @@ -938,9 +936,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver IType[] dParamTypes = new IType[d.Parameters.Count]; for (int i = 0; i < dParamTypes.Length; i++) { - dParamTypes[i] = d.Parameters[i].Type.Resolve(context); + dParamTypes[i] = d.Parameters[i].Type; } - IType dReturnType = d.ReturnType.Resolve(context); + IType dReturnType = d.ReturnType; if (f.HasParameterList) { // If F contains an anonymous-function-signature, then D and F have the same number of parameters. @@ -961,7 +959,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver IParameter pF = f.Parameters[i]; if (pD.IsRef != pF.IsRef || pD.IsOut != pF.IsOut) return Conversion.None; - if (!dParamTypes[i].Equals(pF.Type.Resolve(context))) + if (!dParamTypes[i].Equals(pF.Type)) return Conversion.None; } } @@ -1002,7 +1000,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult[] args = new ResolveResult[m.Parameters.Count]; for (int i = 0; i < args.Length; i++) { IParameter param = m.Parameters[i]; - IType parameterType = param.Type.Resolve(context); + IType parameterType = param.Type; if ((param.IsRef || param.IsOut) && parameterType.Kind == TypeKind.ByReference) { parameterType = ((ByReferenceType)parameterType).ElementType; args[i] = new ByReferenceResolveResult(parameterType, param.IsOut); @@ -1010,7 +1008,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver args[i] = new ResolveResult(parameterType); } } - var or = rr.PerformOverloadResolution(context, args, allowExpandingParams: false, conversions: this); + var or = rr.PerformOverloadResolution(compilation, args, allowExpandingParams: false, conversions: this); if (or.FoundApplicableCandidate) return Conversion.MethodGroupConversion((IMethod)or.BestCandidate); else @@ -1042,15 +1040,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return 0; IType[] parameterTypes = new IType[m1.Parameters.Count]; for (int i = 0; i < parameterTypes.Length; i++) { - parameterTypes[i] = m1.Parameters[i].Type.Resolve(context); - if (!parameterTypes[i].Equals(m2.Parameters[i].Type.Resolve(context))) + parameterTypes[i] = m1.Parameters[i].Type; + if (!parameterTypes[i].Equals(m2.Parameters[i].Type)) return 0; } if (lambda.HasParameterList && parameterTypes.Length != lambda.Parameters.Count) return 0; - IType ret1 = m1.ReturnType.Resolve(context); - IType ret2 = m2.ReturnType.Resolve(context); + IType ret1 = m1.ReturnType; + IType ret2 = m2.ReturnType; if (ret1.Kind == TypeKind.Void && ret2.Kind != TypeKind.Void) return 1; if (ret1.Kind != TypeKind.Void && ret2.Kind == TypeKind.Void) diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs b/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs index 9bc635b21e..99b6e6e867 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs @@ -20,7 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading; - +using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.Utils; @@ -40,11 +40,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public sealed class FindReferences { #region Properties - /// - /// Gets/Sets the cancellation token. - /// - public CancellationToken CancellationToken { get; set; } - /// /// Gets/Sets whether to find type references even if an alias is being used. /// @@ -224,7 +219,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// /// Gets the file names that possibly contain references to the element being searched for. /// - public IList GetInterestingFileNames(IFindReferenceSearchScope searchScope, IEnumerable allTypes, ITypeResolveContext context) + public IList GetInterestingFileNames(IFindReferenceSearchScope searchScope, IEnumerable allTypes) { IEnumerable interestingTypes; if (searchScope.TopLevelTypeDefinition != null) { @@ -234,18 +229,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver interestingTypes = new [] { searchScope.TopLevelTypeDefinition.GetDefinition() }; break; case Accessibility.Protected: - interestingTypes = GetInterestingTypesProtected(allTypes, context, searchScope.TopLevelTypeDefinition); + interestingTypes = GetInterestingTypesProtected(allTypes, searchScope.TopLevelTypeDefinition); break; case Accessibility.Internal: - interestingTypes = GetInterestingTypesInternal(allTypes, context, searchScope.TopLevelTypeDefinition.ProjectContent); + interestingTypes = GetInterestingTypesInternal(allTypes, searchScope.TopLevelTypeDefinition.ParentAssembly); break; case Accessibility.ProtectedAndInternal: - interestingTypes = GetInterestingTypesProtected(allTypes, context, searchScope.TopLevelTypeDefinition) - .Intersect(GetInterestingTypesInternal(allTypes, context, searchScope.TopLevelTypeDefinition.ProjectContent)); + interestingTypes = GetInterestingTypesProtected(allTypes, searchScope.TopLevelTypeDefinition) + .Intersect(GetInterestingTypesInternal(allTypes, searchScope.TopLevelTypeDefinition.ParentAssembly)); break; case Accessibility.ProtectedOrInternal: - interestingTypes = GetInterestingTypesProtected(allTypes, context, searchScope.TopLevelTypeDefinition) - .Union(GetInterestingTypesInternal(allTypes, context, searchScope.TopLevelTypeDefinition.ProjectContent)); + interestingTypes = GetInterestingTypesProtected(allTypes, searchScope.TopLevelTypeDefinition) + .Union(GetInterestingTypesInternal(allTypes, searchScope.TopLevelTypeDefinition.ParentAssembly)); break; default: interestingTypes = allTypes; @@ -255,20 +250,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver interestingTypes = allTypes; } return (from typeDef in interestingTypes - from part in typeDef.GetParts() + from part in typeDef.Parts where part.ParsedFile != null select part.ParsedFile.FileName ).Distinct(Platform.FileNameComparer).ToList(); } - IEnumerable GetInterestingTypesProtected(IEnumerable allTypes, ITypeResolveContext context, ITypeDefinition referencedTypeDefinition) + IEnumerable GetInterestingTypesProtected(IEnumerable allTypes, ITypeDefinition referencedTypeDefinition) { - return allTypes.Where(t => t.IsDerivedFrom(referencedTypeDefinition, context)); + return allTypes.Where(t => t.IsDerivedFrom(referencedTypeDefinition)); } - IEnumerable GetInterestingTypesInternal(IEnumerable allTypes, ITypeResolveContext context, IProjectContent referencedProjectContent) + IEnumerable GetInterestingTypesInternal(IEnumerable allTypes, IAssembly referencedAssembly) { - return allTypes.Where(t => referencedProjectContent.InternalsVisibleTo(t.ProjectContent, context)); + return allTypes.Where(t => referencedAssembly.InternalsVisibleTo(t.ParentAssembly)); } #endregion @@ -282,11 +277,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// The type resolve context to use for resolving the file. /// Callback used to report the references that were found. public void FindReferencesInFile(IFindReferenceSearchScope searchScope, CSharpParsedFile parsedFile, CompilationUnit compilationUnit, - ITypeResolveContext context, FoundReferenceCallback callback) + FoundReferenceCallback callback, CancellationToken cancellationToken) { if (searchScope == null) throw new ArgumentNullException("searchScope"); - FindReferencesInFile(new[] { searchScope }, parsedFile, compilationUnit, context, callback); + FindReferencesInFile(new[] { searchScope }, parsedFile, compilationUnit, callback, cancellationToken); } /// @@ -298,7 +293,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// The type resolve context to use for resolving the file. /// Callback used to report the references that were found. public void FindReferencesInFile(IList searchScopes, CSharpParsedFile parsedFile, CompilationUnit compilationUnit, - ITypeResolveContext context, FoundReferenceCallback callback) + FoundReferenceCallback callback, CancellationToken cancellationToken) { if (searchScopes == null) throw new ArgumentNullException("searchScopes"); @@ -306,9 +301,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver throw new ArgumentNullException("parsedFile"); if (compilationUnit == null) throw new ArgumentNullException("compilationUnit"); + throw new NotImplementedException(); + /* if (context == null) throw new ArgumentNullException("context"); - this.CancellationToken.ThrowIfCancellationRequested(); + if (searchScopes.Count == 0) return; using (var ctx = context.Synchronize()) { @@ -321,7 +318,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver CSharpResolver resolver = new CSharpResolver(ctx, this.CancellationToken); ResolveVisitor v = new ResolveVisitor(resolver, parsedFile, navigator); v.Scan(compilationUnit); - } + }*/ } #endregion @@ -803,11 +800,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// The type resolve context to use for resolving the file. /// Callback used to report the references that were found. public void FindLocalReferences(IVariable variable, CSharpParsedFile parsedFile, CompilationUnit compilationUnit, - ITypeResolveContext context, FoundReferenceCallback callback) + FoundReferenceCallback callback, CancellationToken cancellationToken) { if (variable == null) throw new ArgumentNullException("variable"); - FindReferencesInFile(new FindLocalReferencesNavigator(variable), parsedFile, compilationUnit, context, callback); + FindReferencesInFile(new FindLocalReferencesNavigator(variable), parsedFile, compilationUnit, callback, cancellationToken); } class FindLocalReferencesNavigator : SearchScope diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/LambdaResolveResult.cs b/ICSharpCode.NRefactory.CSharp/Resolver/LambdaResolveResult.cs index 86a5e24c6f..9724cbc972 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/LambdaResolveResult.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/LambdaResolveResult.cs @@ -28,7 +28,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// public abstract class LambdaResolveResult : ResolveResult { - protected LambdaResolveResult() : base(SharedTypes.UnknownType) + protected LambdaResolveResult() : base(SpecialType.UnknownType) { } diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/MapTypeIntoNewContext.cs b/ICSharpCode.NRefactory.CSharp/Resolver/MapTypeIntoNewContext.cs deleted file mode 100644 index c4c03a7c99..0000000000 --- a/ICSharpCode.NRefactory.CSharp/Resolver/MapTypeIntoNewContext.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER 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 ICSharpCode.NRefactory.TypeSystem.Implementation; -using ICSharpCode.NRefactory.Utils; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// Converts a type by replacing all type definitions with the equivalent definitions in the new context. - /// - sealed class MapTypeIntoNewContext : TypeVisitor - { - readonly ITypeResolveContext context; - - public MapTypeIntoNewContext(ITypeResolveContext context) - { - if (context == null) - throw new ArgumentNullException("context"); - this.context = context; - } - - public override IType VisitTypeDefinition(ITypeDefinition type) - { - if (type.DeclaringTypeDefinition != null) { - ITypeDefinition decl = type.DeclaringTypeDefinition.AcceptVisitor(this) as ITypeDefinition; - if (decl != null) { - foreach (ITypeDefinition c in decl.NestedTypes) { - if (c.Name == type.Name && c.TypeParameterCount == type.TypeParameterCount) - return c; - } - } - return type; - } else { - return context.GetTypeDefinition(type.Namespace, type.Name, type.TypeParameterCount, StringComparer.Ordinal) ?? type; - } - } - - public override IType VisitTypeParameter(ITypeParameter type) - { - // TODO: how to map type parameters? - // It might have constraints, and those constraints might be mutually recursive. - // Maybe reintroduce ITypeParameter.Owner? - throw new NotImplementedException(); - } - } -} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/MemberLookup.cs b/ICSharpCode.NRefactory.CSharp/Resolver/MemberLookup.cs index 5b924bb795..2fe2109295 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/MemberLookup.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/MemberLookup.cs @@ -36,31 +36,25 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// /// Gets whether the member is considered to be invocable. /// - public static bool IsInvocable(IMember member, ITypeResolveContext context) + public static bool IsInvocable(IMember member) { if (member == null) throw new ArgumentNullException("member"); // C# 4.0 spec, §7.4 member lookup if (member is IEvent || member is IMethod) return true; - IType returnType = member.ReturnType.Resolve(context); - if (returnType == SharedTypes.Dynamic) - return true; - return returnType.Kind == TypeKind.Delegate; + IType returnType = member.ReturnType; + return returnType.Kind == TypeKind.Dynamic || returnType.Kind == TypeKind.Delegate; } #endregion - ITypeResolveContext context; ITypeDefinition currentTypeDefinition; - IProjectContent currentProject; + IAssembly currentAssembly; - public MemberLookup(ITypeResolveContext context, ITypeDefinition currentTypeDefinition, IProjectContent currentProject) + public MemberLookup(ITypeDefinition currentTypeDefinition, IAssembly currentAssembly) { - if (context == null) - throw new ArgumentNullException("context"); - this.context = context; this.currentTypeDefinition = currentTypeDefinition; - this.currentProject = currentProject; + this.currentAssembly = currentAssembly; } #region IsAccessible @@ -70,7 +64,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public bool IsProtectedAccessAllowed(IType targetType) { ITypeDefinition typeDef = targetType.GetDefinition(); - return typeDef != null && typeDef.IsDerivedFrom(currentTypeDefinition, context); + return typeDef != null && typeDef.IsDerivedFrom(currentTypeDefinition); } /// @@ -107,21 +101,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return (allowProtectedAccess || entity.IsStatic || entity.EntityType == EntityType.TypeDefinition) && IsProtectedAccessible(entity.DeclaringTypeDefinition); case Accessibility.Internal: - return IsInternalAccessible(entity.ProjectContent); + return IsInternalAccessible(entity.ParentAssembly); case Accessibility.ProtectedOrInternal: return (allowProtectedAccess && IsProtectedAccessible(entity.DeclaringTypeDefinition)) - || IsInternalAccessible(entity.ProjectContent); + || IsInternalAccessible(entity.ParentAssembly); case Accessibility.ProtectedAndInternal: return (allowProtectedAccess && IsProtectedAccessible(entity.DeclaringTypeDefinition)) - && IsInternalAccessible(entity.ProjectContent); + && IsInternalAccessible(entity.ParentAssembly); default: throw new Exception("Invalid value for Accessibility"); } } - bool IsInternalAccessible(IProjectContent declaringProject) + bool IsInternalAccessible(IAssembly assembly) { - return declaringProject != null && currentProject != null && declaringProject.InternalsVisibleTo(currentProject, context); + return assembly != null && currentAssembly != null && assembly.InternalsVisibleTo(currentAssembly); } bool IsProtectedAccessible(ITypeDefinition declaringType) @@ -130,7 +124,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return true; // PERF: this might hurt performance as this method is called several times (once for each member) // make sure resolving base types is cheap (caches?) or cache within the MemberLookup instance - return currentTypeDefinition != null && currentTypeDefinition.IsDerivedFrom(declaringType, context); + return currentTypeDefinition != null && currentTypeDefinition.IsDerivedFrom(declaringType); } #endregion @@ -188,15 +182,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver List lookupGroups = new List(); if (declaringType.Kind != TypeKind.TypeParameter) { - foreach (IType type in declaringType.GetNonInterfaceBaseTypes(context)) { + foreach (IType type in declaringType.GetNonInterfaceBaseTypes()) { List newNestedTypes = null; IEnumerable typeBaseTypes = null; IEnumerable nestedTypes; if (parameterizeResultType) { - nestedTypes = type.GetNestedTypes(typeArguments, context, filter, GetMemberOptions.IgnoreInheritedMembers); + nestedTypes = type.GetNestedTypes(typeArguments, filter, GetMemberOptions.IgnoreInheritedMembers); } else { - nestedTypes = type.GetNestedTypes(context, filter, GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions); + nestedTypes = type.GetNestedTypes(filter, GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions); } AddNestedTypes(type, nestedTypes, typeArgumentCount, lookupGroups, ref typeBaseTypes, ref newNestedTypes); @@ -255,7 +249,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // 2) It adds a new lookup group with the members from a declaring type. // 3) It replaces virtual members with the overridden version, placing the override in the // lookup group belonging to the base class. - foreach (IType type in targetResolveResult.Type.GetNonInterfaceBaseTypes(context)) { + foreach (IType type in targetResolveResult.Type.GetNonInterfaceBaseTypes()) { List newNestedTypes = null; List newMethods = null; @@ -267,7 +261,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // Consider nested types only if it's not an invocation. // type.GetNestedTypes() is checking the type parameter count for an exact match, // so we don't need to do that in our filter. - var nestedTypes = type.GetNestedTypes(typeArguments, context, filter, GetMemberOptions.IgnoreInheritedMembers); + var nestedTypes = type.GetNestedTypes(typeArguments, filter, GetMemberOptions.IgnoreInheritedMembers); AddNestedTypes(type, nestedTypes, typeArguments.Count, lookupGroups, ref typeBaseTypes, ref newNestedTypes); } @@ -275,13 +269,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (typeArguments.Count == 0) { // Note: IsInvocable-checking cannot be done as part of the filter; // because it must be done after type substitution. - members = type.GetMembers(context, filter, GetMemberOptions.IgnoreInheritedMembers); + members = type.GetMembers(filter, GetMemberOptions.IgnoreInheritedMembers); if (isInvocation) - members = members.Where(m => IsInvocable(m, context)); + members = members.Where(m => IsInvocable(m)); } else { // No need to check for isInvocation/isInvocable here: // we only fetch methods - members = type.GetMethods(typeArguments, context, filter, GetMemberOptions.IgnoreInheritedMembers); + members = type.GetMethods(typeArguments, filter, GetMemberOptions.IgnoreInheritedMembers); } AddMembers(type, members, lookupGroups, false, ref typeBaseTypes, ref newMethods, ref newNonMethod); @@ -314,13 +308,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver }; List lookupGroups = new List(); - foreach (IType type in targetType.GetNonInterfaceBaseTypes(context)) { + foreach (IType type in targetType.GetNonInterfaceBaseTypes()) { List newMethods = null; IMember newNonMethod = null; IEnumerable typeBaseTypes = null; - var members = type.GetProperties(context, filter, GetMemberOptions.IgnoreInheritedMembers); + var members = type.GetProperties(filter, GetMemberOptions.IgnoreInheritedMembers); AddMembers(type, members, lookupGroups, true, ref typeBaseTypes, ref newMethods, ref newNonMethod); if (newMethods != null || newNonMethod != null) @@ -366,7 +360,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (lookupGroup.AllHidden) continue; // everything is already hidden if (typeBaseTypes == null) - typeBaseTypes = type.GetNonInterfaceBaseTypes(context); + typeBaseTypes = type.GetNonInterfaceBaseTypes(); if (typeBaseTypes.Contains(lookupGroup.DeclaringType)) { lookupGroup.MethodsAreHidden = true; @@ -416,14 +410,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // in the most-derived type for (int i = lookupGroups.Count - 1; i >= 0 && !replacedVirtualMemberWithOverride; i--) { if (typeBaseTypes == null) - typeBaseTypes = type.GetNonInterfaceBaseTypes(context); + typeBaseTypes = type.GetNonInterfaceBaseTypes(); var lookupGroup = lookupGroups[i]; if (typeBaseTypes.Contains(lookupGroup.DeclaringType)) { if (method != null) { // Find the matching method, and replace it with the override for (int j = 0; j < lookupGroup.Methods.Count; j++) { - if (ParameterListComparer.Compare(context, method, lookupGroup.Methods[j])) { + if (SignatureComparer.Ordinal.Equals(method, lookupGroup.Methods[j])) { lookupGroup.Methods[j] = method; replacedVirtualMemberWithOverride = true; break; @@ -448,7 +442,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (lookupGroup.AllHidden) continue; // everything is already hidden if (typeBaseTypes == null) - typeBaseTypes = type.GetNonInterfaceBaseTypes(context); + typeBaseTypes = type.GetNonInterfaceBaseTypes(); if (typeBaseTypes.Contains(lookupGroup.DeclaringType)) { // Methods hide all non-methods; Non-methods hide everything @@ -502,7 +496,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // The mapping of virtual to overridden methods is already done, // so we can simply remove the methods from the collection interfaceLookupGroup.Methods.RemoveAll( - m => ParameterListComparer.Compare(context, classMethod, m)); + m => SignatureComparer.Ordinal.Equals(classMethod, m)); } } } @@ -558,10 +552,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } if (lookupGroups.Count > 1) { - return new AmbiguousMemberResolveResult(targetResolveResult, resultGroup.NonMethod, - resultGroup.NonMethod.ReturnType.Resolve(context)); + return new AmbiguousMemberResolveResult(targetResolveResult, resultGroup.NonMethod); } else { - return new MemberResolveResult(targetResolveResult, resultGroup.NonMethod, context); + return new MemberResolveResult(targetResolveResult, resultGroup.NonMethod); } } #endregion diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs b/ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs index 64582af816..5b724d2561 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs @@ -22,7 +22,7 @@ using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Text; - +using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; @@ -58,7 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver readonly ResolveResult targetResult; readonly string methodName; - public MethodGroupResolveResult(ResolveResult targetResult, string methodName, IList methods, IList typeArguments) : base(SharedTypes.UnknownType) + public MethodGroupResolveResult(ResolveResult targetResult, string methodName, IList methods, IList typeArguments) : base(SpecialType.UnknownType) { if (targetResult == null) throw new ArgumentNullException("targetResult"); @@ -159,13 +159,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return string.Format("[{0} with {1} method(s)]", GetType().Name, this.Methods.Count()); } - public OverloadResolution PerformOverloadResolution(ITypeResolveContext context, ResolveResult[] arguments, string[] argumentNames = null, bool allowExtensionMethods = true, bool allowExpandingParams = true, Conversions conversions = null) + public OverloadResolution PerformOverloadResolution(ICompilation compilation, ResolveResult[] arguments, string[] argumentNames = null, bool allowExtensionMethods = true, bool allowExpandingParams = true, Conversions conversions = null) { Log.WriteLine("Performing overload resolution for " + this); Log.WriteCollection(" Arguments: ", arguments); var typeArgumentArray = this.TypeArguments.ToArray(); - OverloadResolution or = new OverloadResolution(context, arguments, argumentNames, typeArgumentArray, conversions); + OverloadResolution or = new OverloadResolution(compilation, arguments, argumentNames, typeArgumentArray, conversions); or.AllowExpandingParams = allowExpandingParams; or.AddMethodLists(methodLists); @@ -185,7 +185,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver extArgumentNames = new string[argumentNames.Length + 1]; argumentNames.CopyTo(extArgumentNames, 1); } - var extOr = new OverloadResolution(context, extArguments, extArgumentNames, typeArgumentArray, conversions); + var extOr = new OverloadResolution(compilation, extArguments, extArgumentNames, typeArgumentArray, conversions); extOr.AllowExpandingParams = allowExpandingParams; extOr.IsExtensionMethodInvocation = true; diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs b/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs index 6b229c442e..ac3c58c42d 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs @@ -110,7 +110,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } - readonly ITypeResolveContext context; + readonly ICompilation compilation; readonly ResolveResult[] arguments; readonly string[] argumentNames; readonly Conversions conversions; @@ -120,17 +120,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver IType[] explicitlyGivenTypeArguments; #region Constructor - public OverloadResolution(ITypeResolveContext context, ResolveResult[] arguments, string[] argumentNames = null, IType[] typeArguments = null, Conversions conversions = null) + public OverloadResolution(ICompilation compilation, ResolveResult[] arguments, string[] argumentNames = null, IType[] typeArguments = null, Conversions conversions = null) { - if (context == null) - throw new ArgumentNullException("context"); + if (compilation == null) + throw new ArgumentNullException("compilation"); if (arguments == null) throw new ArgumentNullException("arguments"); if (argumentNames == null) argumentNames = new string[arguments.Length]; else if (argumentNames.Length != arguments.Length) throw new ArgumentException("argumentsNames.Length must be equal to arguments.Length"); - this.context = context; + this.compilation = compilation; this.arguments = arguments; this.argumentNames = argumentNames; @@ -138,7 +138,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (typeArguments != null && typeArguments.Length > 0) this.explicitlyGivenTypeArguments = typeArguments; - this.conversions = conversions ?? Conversions.Get(context); + this.conversions = conversions ?? Conversions.Get(compilation); this.AllowExpandingParams = true; } #endregion @@ -214,7 +214,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver bool ResolveParameterTypes(Candidate candidate) { for (int i = 0; i < candidate.Parameters.Count; i++) { - IType type = candidate.Parameters[i].Type.Resolve(context); + IType type = candidate.Parameters[i].Type; if (candidate.IsExpandedForm && i == candidate.Parameters.Count - 1) { ArrayType arrayType = type as ArrayType; if (arrayType != null && arrayType.Dimensions == 1) @@ -266,7 +266,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } if (foundApplicableCandidateInCurrentList && i > 0) { - foreach (IType baseType in methodList.DeclaringType.GetAllBaseTypes(context)) { + foreach (IType baseType in methodList.DeclaringType.GetAllBaseTypes()) { for (int j = 0; j < i; j++) { if (!isHiddenByDerivedType[j] && baseType.Equals(methodLists[j].DeclaringType)) isHiddenByDerivedType[j] = true; @@ -358,11 +358,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (i < explicitlyGivenTypeArguments.Length) candidate.InferredTypes[i] = explicitlyGivenTypeArguments[i]; else - candidate.InferredTypes[i] = SharedTypes.UnknownType; + candidate.InferredTypes[i] = SpecialType.UnknownType; } } } else { - TypeInference ti = new TypeInference(context, conversions); + TypeInference ti = new TypeInference(compilation, conversions); bool success; candidate.InferredTypes = ti.InferTypeArguments(method.TypeParameters, arguments, candidate.ParameterTypes, out success, classTypeArguments); if (!success) @@ -380,13 +380,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver sealed class ConstraintValidatingSubstitution : TypeParameterSubstitution { readonly Conversions conversions; - readonly ITypeResolveContext context; public bool ConstraintsValid = true; public ConstraintValidatingSubstitution(IList classTypeArguments, IList methodTypeArguments, OverloadResolution overloadResolution) : base(classTypeArguments, methodTypeArguments) { - this.context = overloadResolution.context; this.conversions = overloadResolution.conversions; } @@ -409,26 +407,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ConstraintsValid = false; break; } - ITypeParameterConstraints constraints = tp.GetConstraints(context); - if (constraints.HasReferenceTypeConstraint) { - if (typeArg.IsReferenceType(context) != true) + if (tp.HasReferenceTypeConstraint) { + if (typeArg.IsReferenceType != true) ConstraintsValid = false; } - if (constraints.HasValueTypeConstraint) { - if (!NullableType.IsNonNullableValueType(typeArg, context)) + if (tp.HasValueTypeConstraint) { + if (!NullableType.IsNonNullableValueType(typeArg)) ConstraintsValid = false; } - if (constraints.HasDefaultConstructorConstraint) { + if (tp.HasDefaultConstructorConstraint) { ITypeDefinition def = typeArg.GetDefinition(); if (def != null && def.IsAbstract) ConstraintsValid = false; ConstraintsValid &= typeArg.GetConstructors( - context, m => m.Parameters.Count == 0 && m.Accessibility == Accessibility.Public, GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions ).Any(); } - foreach (IType constraintType in constraints) { + foreach (IType constraintType in tp.DirectBaseTypes) { IType c = constraintType.AcceptVisitor(newParameterizedType.GetSubstitution()); ConstraintsValid &= conversions.IsConstraintConvertible(typeArg, c); } @@ -593,8 +589,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (r > 0) return 1; else if (r < 0) return 2; - return MoreSpecificFormalParameters(c1.Parameters.Select(p => p.Type.Resolve(context)), - c2.Parameters.Select(p => p.Type.Resolve(context))); + return MoreSpecificFormalParameters(c1.Parameters.Select(p => p.Type), c2.Parameters.Select(p => p.Type)); } static int MoreSpecificFormalParameters(IEnumerable t1, IEnumerable t2) @@ -745,7 +740,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (parameterIndex >= 0) parameterType = bestCandidate.ParameterTypes[parameterIndex]; else - parameterType = SharedTypes.UnknownType; + parameterType = SpecialType.UnknownType; args[i] = new ConversionResolveResult(parameterType, arguments[i], conversions[i]); } } @@ -773,7 +768,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return new CSharpInvocationResolveResult( targetResolveResult, member, - member.EntityType == EntityType.Constructor ? member.DeclaringType : member.ReturnType.Resolve(context), GetArgumentsWithConversions(), this.BestCandidateErrors, this.IsExtensionMethodInvocation, diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs index adc2d572f7..8379ae56e1 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs @@ -18,6 +18,7 @@ using System; using System.Threading; +using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; @@ -29,7 +30,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// public static class ResolveAtLocation { - public static ResolveResult Resolve(ITypeResolveContext context, CSharpParsedFile parsedFile, CompilationUnit cu, TextLocation location, + public static ResolveResult Resolve(ICompilation compilation, CSharpParsedFile parsedFile, CompilationUnit cu, TextLocation location, CancellationToken cancellationToken = default(CancellationToken)) { AstNode node = cu.GetNodeAt(location); @@ -39,7 +40,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (node is AstType) { resolvableNode = node; if (resolvableNode.Parent is ComposedType) { - while (resolvableNode.Parent is ComposedType) + while (resolvableNode.Parent is ComposedType) resolvableNode = resolvableNode.Parent; //node is preffered over the resolvable node. Which shouldn't be done in the case of nullables, arrays etc. node = resolvableNode; @@ -69,6 +70,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver else navigator = new NodeListResolveVisitorNavigator(new[] { resolvableNode }); + throw new NotImplementedException(); + /* using (var ctx = context.Synchronize()) { CSharpResolver resolver = new CSharpResolver(ctx, cancellationToken); ResolveVisitor v = new ResolveVisitor(resolver, parsedFile, navigator); @@ -81,7 +84,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return v.GetResolveResult(parentInvocation); else return rr; - } + }*/ } } } diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs index 932dcc38bb..1ce34e8a59 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs @@ -22,7 +22,7 @@ using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; - +using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; @@ -57,7 +57,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // The ResolveVisitor is also responsible for handling lambda expressions. static readonly ResolveResult errorResult = ErrorResolveResult.UnknownError; - static readonly ResolveResult transparentIdentifierResolveResult = new ResolveResult(SharedTypes.UnboundTypeArgument); + static readonly ResolveResult transparentIdentifierResolveResult = new ResolveResult(SpecialType.UnboundTypeArgument); readonly ResolveResult voidResult; CSharpResolver resolver; @@ -71,6 +71,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver IResolveVisitorNavigator navigator; bool resolverEnabled; List undecidedLambdas; + internal CancellationToken cancellationToken; #region Constructor /// @@ -98,23 +99,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver this.resolver = resolver; this.parsedFile = parsedFile; this.navigator = navigator ?? new ConstantModeResolveVisitorNavigator(ResolveVisitorNavigationMode.Skip, null); - this.voidResult = new ResolveResult(KnownTypeReference.Void.Resolve(resolver.Context)); - } - #endregion - - #region Properties - /// - /// Gets the TypeResolveContext used by this ResolveVisitor. - /// - public ITypeResolveContext TypeResolveContext { - get { return resolver.Context; } - } - - /// - /// Gets the CancellationToken used by this ResolveVisitor. - /// - public CancellationToken CancellationToken { - get { return resolver.cancellationToken; } + this.voidResult = new ResolveResult(resolver.Compilation.FindType(KnownTypeCode.Void)); } #endregion @@ -214,7 +199,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver resolverEnabled = true; ResolveResult result; if (!resolveResultCache.TryGetValue(node, out result)) { - resolver.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); StoreCurrentState(node); result = node.AcceptVisitor(this, null) ?? errorResult; Log.WriteLine("Resolved '{0}' to {1}", node, result); @@ -502,8 +487,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // merge undecided lambdas before leaving the using scope so that // the resolver can make better use of its cache MergeUndecidedLambdas(); - if (resolver.CurrentUsingScope != null) - return new NamespaceResolveResult(resolver.CurrentUsingScope.NamespaceName); + if (resolver.CurrentUsingScope != null && resolverEnabled) + return new NamespaceResolveResult(resolver.CurrentUsingScope.ResolveNamespace(resolver.Compilation)); else return null; } finally { @@ -513,20 +498,23 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver #endregion #region Track CurrentTypeDefinition - ResolveResult VisitTypeOrDelegate(AstNode typeDeclaration) + ResolveResult VisitTypeOrDelegate(AstNode typeDeclaration, string name, int typeParameterCount) { ITypeDefinition previousTypeDefinition = resolver.CurrentTypeDefinition; try { ITypeDefinition newTypeDefinition = null; if (resolver.CurrentTypeDefinition != null) { + int totalTypeParameterCount = resolver.CurrentTypeDefinition.TypeParameterCount; foreach (ITypeDefinition nestedType in resolver.CurrentTypeDefinition.NestedTypes) { - if (nestedType.Region.IsInside(typeDeclaration.StartLocation)) { + if (nestedType.Name == name && nestedType.TypeParameterCount == totalTypeParameterCount) { newTypeDefinition = nestedType; break; } } - } else if (parsedFile != null) { - newTypeDefinition = parsedFile.GetTopLevelTypeDefinition(typeDeclaration.StartLocation); + } else if (resolver.CurrentUsingScope != null) { + INamespace ns = resolver.CurrentUsingScope.ResolveNamespace(resolver.Compilation); + if (ns != null) + newTypeDefinition = ns.GetTypeDefinition(name, typeParameterCount); } if (newTypeDefinition != null) resolver.CurrentTypeDefinition = newTypeDefinition; @@ -553,12 +541,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult IAstVisitor.VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) { - return VisitTypeOrDelegate(typeDeclaration); + return VisitTypeOrDelegate(typeDeclaration, typeDeclaration.Name, typeDeclaration.TypeParameters.Count); } ResolveResult IAstVisitor.VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data) { - return VisitTypeOrDelegate(delegateDeclaration); + return VisitTypeOrDelegate(delegateDeclaration, delegateDeclaration.Name, delegateDeclaration.TypeParameters.Count); } #endregion @@ -583,14 +571,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver int initializerCount = fieldOrEventDeclaration.GetChildrenByRole(FieldDeclaration.Roles.Variable).Count; for (AstNode node = fieldOrEventDeclaration.FirstChild; node != null; node = node.NextSibling) { if (node.Role == FieldDeclaration.Roles.Variable) { - if (resolver.CurrentTypeDefinition != null) { - IEnumerable members; - if (fieldOrEventDeclaration is EventDeclaration) - members = resolver.CurrentTypeDefinition.Events; - else - members = resolver.CurrentTypeDefinition.Fields; - resolver.CurrentMember = members.FirstOrDefault(f => f.Region.IsInside(node.StartLocation)); - } + resolver.CurrentMember = GetMemberFromLocation(node.StartLocation); Scan(node); @@ -602,6 +583,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return voidResult; } + IMember GetMemberFromLocation(TextLocation location) + { + throw new NotImplementedException(); + } + ResolveResult IAstVisitor.VisitVariableInitializer(VariableInitializer variableInitializer, object data) { ArrayInitializerExpression aie = variableInitializer.Initializer as ArrayInitializerExpression; @@ -609,14 +595,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult result = errorResult; if (variableInitializer.Parent is FieldDeclaration || variableInitializer.Parent is EventDeclaration) { if (resolver.CurrentMember != null) { - result = new MemberResolveResult(null, resolver.CurrentMember, resolver.CurrentMember.ReturnType.Resolve(resolver.Context)); + result = new MemberResolveResult(null, resolver.CurrentMember); } } else { string identifier = variableInitializer.Name; foreach (IVariable v in resolver.LocalVariables) { if (v.Name == identifier) { - object constantValue = v.IsConst ? v.ConstantValue.Resolve(resolver.Context).ConstantValue : null; - result = new LocalResolveResult(v, v.Type.Resolve(resolver.Context), constantValue); + result = new LocalResolveResult(v); break; } } @@ -648,9 +633,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (resolverEnabled) { ResolveResult result = errorResult; if (resolver.CurrentMember != null) { - result = new MemberResolveResult(null, resolver.CurrentMember, resolver.CurrentMember.ReturnType.Resolve(resolver.Context)); + result = new MemberResolveResult(null, resolver.CurrentMember); } - ResolveAndProcessConversion(fixedVariableInitializer.CountExpression, KnownTypeReference.Int32.Resolve(resolver.Context)); + ResolveAndProcessConversion(fixedVariableInitializer.CountExpression, resolver.Compilation.FindType(KnownTypeCode.Int32)); return result; } else { ScanChildren(fixedVariableInitializer); @@ -661,14 +646,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult VisitMethodMember(AttributedNode member) { try { - if (resolver.CurrentTypeDefinition != null) { - resolver.CurrentMember = resolver.CurrentTypeDefinition.Methods.FirstOrDefault(m => m.Region.IsInside(member.StartLocation)); - } + resolver.CurrentMember = GetMemberFromLocation(member.StartLocation); ScanChildren(member); if (resolverEnabled && resolver.CurrentMember != null) - return new MemberResolveResult(null, resolver.CurrentMember, resolver.Context); + return new MemberResolveResult(null, resolver.CurrentMember); else return errorResult; } finally { @@ -700,14 +683,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult VisitPropertyMember(MemberDeclaration propertyOrIndexerDeclaration) { try { - if (resolver.CurrentTypeDefinition != null) { - resolver.CurrentMember = resolver.CurrentTypeDefinition.Properties.FirstOrDefault(p => p.Region.IsInside(propertyOrIndexerDeclaration.StartLocation)); - } + resolver.CurrentMember = GetMemberFromLocation(propertyOrIndexerDeclaration.StartLocation); for (AstNode node = propertyOrIndexerDeclaration.FirstChild; node != null; node = node.NextSibling) { if (node.Role == PropertyDeclaration.SetterRole && resolver.CurrentMember != null) { resolver.PushBlock(); - resolver.AddVariable(resolver.CurrentMember.ReturnType, DomRegion.Empty, "value"); + resolver.AddVariable(new DefaultParameter(resolver.CurrentMember.ReturnType, "value")); Scan(node); resolver.PopBlock(); } else { @@ -715,7 +696,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } if (resolverEnabled && resolver.CurrentMember != null) - return new MemberResolveResult(null, resolver.CurrentMember, resolver.Context); + return new MemberResolveResult(null, resolver.CurrentMember); else return errorResult; } finally { @@ -736,13 +717,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult IAstVisitor.VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration, object data) { try { - if (resolver.CurrentTypeDefinition != null) { - resolver.CurrentMember = resolver.CurrentTypeDefinition.Events.FirstOrDefault(e => e.Region.IsInside(eventDeclaration.StartLocation)); - } + resolver.CurrentMember = GetMemberFromLocation(eventDeclaration.StartLocation); if (resolver.CurrentMember != null) { resolver.PushBlock(); - resolver.AddVariable(resolver.CurrentMember.ReturnType, DomRegion.Empty, "value"); + resolver.AddVariable(new DefaultParameter(resolver.CurrentMember.ReturnType, "value")); ScanChildren(eventDeclaration); resolver.PopBlock(); } else { @@ -750,7 +729,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } if (resolverEnabled && resolver.CurrentMember != null) - return new MemberResolveResult(null, resolver.CurrentMember, resolver.Context); + return new MemberResolveResult(null, resolver.CurrentMember); else return errorResult; } finally { @@ -766,14 +745,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // Look in lambda parameters: foreach (IParameter p in resolver.LocalVariables.OfType()) { if (p.Name == name) - return new LocalResolveResult(p, p.Type.Resolve(resolver.Context)); + return new LocalResolveResult(p); } IParameterizedMember pm = resolver.CurrentMember as IParameterizedMember; if (pm != null) { foreach (IParameter p in pm.Parameters) { if (p.Name == name) { - return new LocalResolveResult(p, p.Type.Resolve(resolver.Context)); + return new LocalResolveResult(p); } } } @@ -812,14 +791,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult IAstVisitor.VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, object data) { try { - if (resolver.CurrentTypeDefinition != null) { - resolver.CurrentMember = resolver.CurrentTypeDefinition.Fields.FirstOrDefault(f => f.Region.IsInside(enumMemberDeclaration.StartLocation)); - } + resolver.CurrentMember = GetMemberFromLocation(enumMemberDeclaration.StartLocation); ScanChildren(enumMemberDeclaration); if (resolverEnabled && resolver.CurrentMember != null) - return new MemberResolveResult(null, resolver.CurrentMember, resolver.Context); + return new MemberResolveResult(null, resolver.CurrentMember); else return errorResult; } finally { @@ -910,6 +887,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult IAstVisitor.VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression, object data) { // 7.6.10.6 Anonymous object creation expressions + throw new NotImplementedException(); + /* if (resolver.ProjectContent == null) { ScanChildren(anonymousTypeCreateExpression); return errorResult; @@ -931,7 +910,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } ScanChildren(anonymousTypeCreateExpression); resolver.PopInitializerType(); - return new ResolveResult(anonymousType); + return new ResolveResult(anonymousType);*/ } ResolveResult IAstVisitor.VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data) @@ -986,7 +965,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } else { IType elementType = ResolveType(arrayCreateExpression.Type); foreach (var spec in additionalArraySpecifiers.Reverse()) { - elementType = new ArrayType(elementType, spec.Dimensions); + elementType = new ArrayType(resolver.Compilation, elementType, spec.Dimensions); } acrr = resolver.ResolveArrayCreation(elementType, dimensions, sizeArguments, initializerElementResults); } @@ -1169,7 +1148,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { ScanChildren(isExpression); if (resolverEnabled) - return new ResolveResult(KnownTypeReference.Boolean.Resolve(resolver.Context)); + return new ResolveResult(resolver.Compilation.FindType(KnownTypeCode.Boolean)); else return null; } @@ -1266,7 +1245,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver var addRR = memberLookup.Lookup(targetResult, "Add", EmptyList.Instance, true); var mgrr = addRR as MethodGroupResolveResult; if (mgrr != null) { - OverloadResolution or = mgrr.PerformOverloadResolution(resolver.Context, addArguments, null, false, false, resolver.conversions); + OverloadResolution or = mgrr.PerformOverloadResolution(resolver.Compilation, addArguments, null, false, false, resolver.conversions); var invocationRR = or.CreateResolveResult(targetResult); StoreResult(aie, invocationRR); ProcessConversionsInInvocation(null, aie.Elements, invocationRR); @@ -1334,7 +1313,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult IAstVisitor.VisitStackAllocExpression(StackAllocExpression stackAllocExpression, object data) { if (resolverEnabled) { - ResolveAndProcessConversion(stackAllocExpression.CountExpression, KnownTypeReference.Int32.Resolve(resolver.Context)); + ResolveAndProcessConversion(stackAllocExpression.CountExpression, resolver.Compilation.FindType(KnownTypeCode.Int32)); return new ResolveResult(new PointerType(ResolveType(stackAllocExpression.Type))); } else { ScanChildren(stackAllocExpression); @@ -1354,7 +1333,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { ScanChildren(typeOfExpression); if (resolverEnabled) - return new ResolveResult(KnownTypeReference.Type.Resolve(resolver.Context)); + return new ResolveResult(KnownTypeReference.Type.Resolve(resolver.Compilation.TypeResolveContext)); else return null; } @@ -1395,29 +1374,29 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { ScanChildren(undocumentedExpression); if (resolverEnabled) { - ITypeReference resultType; + IType resultType; switch (undocumentedExpression.UndocumentedExpressionType) { case UndocumentedExpressionType.ArgListAccess: case UndocumentedExpressionType.ArgList: - resultType = typeof(RuntimeArgumentHandle).ToTypeReference(); + resultType = resolver.Compilation.FindType(typeof(RuntimeArgumentHandle)); break; case UndocumentedExpressionType.RefValue: var tre = undocumentedExpression.Arguments.ElementAtOrDefault(1) as TypeReferenceExpression; if (tre != null) resultType = ResolveType(tre.Type); else - resultType = SharedTypes.UnknownType; + resultType = SpecialType.UnknownType; break; case UndocumentedExpressionType.RefType: - resultType = KnownTypeReference.Type; + resultType = KnownTypeReference.Type.Resolve(resolver.Compilation.TypeResolveContext); break; case UndocumentedExpressionType.MakeRef: - resultType = typeof(TypedReference).ToTypeReference(); + resultType = resolver.Compilation.FindType(typeof(TypedReference)); break; default: throw new InvalidOperationException("Invalid value for UndocumentedExpressionType"); } - return new ResolveResult(resultType.Resolve(resolver.Context)); + return new ResolveResult(resultType); } else { return null; } @@ -1658,15 +1637,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver AstNode body, bool isAnonymousMethod, bool hasParameterList, bool isAsync) { List parameters = new List(); - resolver.PushLambdaBlock(); + resolver.PushBlock(); + bool oldIsWithinLambdaExpression = resolver.IsWithinLambdaExpression; + resolver.IsWithinLambdaExpression = true; foreach (var pd in parameterDeclarations) { - ITypeReference type = MakeTypeReference(pd.Type); + IType type = ResolveType(pd.Type); if (pd.ParameterModifier == ParameterModifier.Ref || pd.ParameterModifier == ParameterModifier.Out) - type = ByReferenceTypeReference.Create(type); + type = new ByReferenceType(type); - var p = resolver.AddLambdaParameter(type, MakeRegion(pd), pd.Name, + IParameter p = new DefaultParameter(type, pd.Name, MakeRegion(pd), isRef: pd.ParameterModifier == ParameterModifier.Ref, isOut: pd.ParameterModifier == ParameterModifier.Out); + resolver.AddVariable(p); parameters.Add(p); Scan(pd); } @@ -1676,6 +1658,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // Don't scan the lambda body here - we'll do that later when analyzing the ExplicitlyTypedLambda. resolver.PopBlock(); + resolver.IsWithinLambdaExpression = oldIsWithinLambdaExpression; return lambda; } @@ -1838,7 +1821,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver internal override void EnforceMerge(ResolveVisitor parentVisitor) { - ApplyReturnType(parentVisitor, SharedTypes.UnknownType); + ApplyReturnType(parentVisitor, SpecialType.UnknownType); } } #endregion @@ -1897,9 +1880,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { this.lambda = lambda; foreach (var pd in lambda.Parameters) { - parameters.Add(new DefaultParameter(SharedTypes.UnknownType, pd.Name) { - Region = parentVisitor.MakeRegion(pd) - }); + parameters.Add(new DefaultParameter(SpecialType.UnknownType, pd.Name, parentVisitor.MakeRegion(pd))); } RegisterUndecidedLambda(); } @@ -1976,7 +1957,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // make a new hypothesis with unknown parameter types IType[] parameterTypes = new IType[parameters.Count]; for (int i = 0; i < parameterTypes.Length; i++) { - parameterTypes[i] = SharedTypes.UnknownType; + parameterTypes[i] = SpecialType.UnknownType; } return GetHypothesis(parameterTypes); } else { @@ -1998,7 +1979,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver internal override void EnforceMerge(ResolveVisitor parentVisitor) { - GetAnyHypothesis().MergeInto(parentVisitor, SharedTypes.UnknownType); + GetAnyHypothesis().MergeInto(parentVisitor, SpecialType.UnknownType); } public override bool IsImplicitlyTyped { @@ -2055,24 +2036,29 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Log.WriteLine("Analyzing " + ToString() + "..."); Log.Indent(); - visitor.resolver.PushLambdaBlock(); + bool oldInsideLambda = visitor.resolver.IsWithinLambdaExpression; + visitor.resolver.PushBlock(); + visitor.resolver.IsWithinLambdaExpression = true; lambdaParameters = new IParameter[parameterTypes.Length]; if (parameterDeclarations != null) { int i = 0; foreach (var pd in parameterDeclarations) { - lambdaParameters[i] = visitor.resolver.AddLambdaParameter(parameterTypes[i], visitor.MakeRegion(pd), pd.Name); + lambdaParameters[i] = new DefaultParameter(parameterTypes[i], pd.Name, visitor.MakeRegion(pd)); + visitor.resolver.AddVariable(lambdaParameters[i]); i++; visitor.Scan(pd); } } else { for (int i = 0; i < parameterTypes.Length; i++) { var p = lambda.Parameters[i]; - lambdaParameters[i] = visitor.resolver.AddLambdaParameter(parameterTypes[i], p.Region, p.Name); + lambdaParameters[i] = new DefaultParameter(parameterTypes[i], p.Name, p.Region); + visitor.resolver.AddVariable(lambdaParameters[i]); } } visitor.AnalyzeLambda(lambda.BodyExpression, lambda.IsAsync, out success, out isValidAsVoidMethod, out inferredReturnType, out returnExpressions, out returnValues); visitor.resolver.PopBlock(); + visitor.resolver.IsWithinLambdaExpression = false; Log.Unindent(); Log.WriteLine("Finished analyzing " + ToString()); } @@ -2209,15 +2195,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver IType GetTaskType(IType resultType) { if (resultType.Kind == TypeKind.Unknown) - return SharedTypes.UnknownType; + return SpecialType.UnknownType; if (resultType.Kind == TypeKind.Void) - return resolver.Context.GetTypeDefinition("System.Threading.Tasks", "Task", 0, StringComparer.Ordinal) ?? SharedTypes.UnknownType; + return KnownTypeReference.Task.Resolve(resolver.Compilation.TypeResolveContext); - ITypeDefinition def = resolver.Context.GetTypeDefinition("System.Threading.Tasks", "Task", 1, StringComparer.Ordinal); + ITypeDefinition def = KnownTypeReference.TaskOfT.Resolve(resolver.Compilation.TypeResolveContext).GetDefinition(); if (def != null) return new ParameterizedType(def, new[] { resultType }); else - return SharedTypes.UnknownType; + return SpecialType.UnknownType; } void AnalyzeLambda(AstNode body, bool isAsync, out bool success, out bool isValidAsVoidMethod, out IType inferredReturnType, out IList returnExpressions, out IList returnValues) @@ -2237,14 +2223,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (alv.HasVoidReturnStatements) { returnExpressions = EmptyList.Instance; returnValues = EmptyList.Instance; - inferredReturnType = KnownTypeReference.Void.Resolve(resolver.Context); + inferredReturnType = resolver.Compilation.FindType(KnownTypeCode.Void); } else { returnExpressions = alv.ReturnExpressions; returnValues = new ResolveResult[returnExpressions.Count]; for (int i = 0; i < returnValues.Count; i++) { returnValues[i] = resolveResultCache[returnExpressions[i]]; } - TypeInference ti = new TypeInference(resolver.Context, resolver.conversions); + TypeInference ti = new TypeInference(resolver.Compilation, resolver.conversions); bool tiSuccess; inferredReturnType = ti.GetBestCommonType(returnValues, out tiSuccess); // Failure to infer a return type does not make the lambda invalid, @@ -2316,7 +2302,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (!IsTask(type)) return type; if (type.TypeParameterCount == 0) - return KnownTypeReference.Void.Resolve(resolver.Context); + return resolver.Compilation.FindType(KnownTypeCode.Void); else return ((ParameterizedType)type).GetTypeArgument(0); } @@ -2380,9 +2366,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (resolverEnabled) { for (AstNode child = usingStatement.FirstChild; child != null; child = child.NextSibling) { if (child.Role == UsingStatement.ResourceAcquisitionRole && child is Expression) { - ITypeDefinition disposable = resolver.Context.GetTypeDefinition( - "System", "IDisposable", 0, StringComparer.Ordinal); - ResolveAndProcessConversion((Expression)child, disposable ?? SharedTypes.UnknownType); + ResolveAndProcessConversion((Expression)child, resolver.Compilation.FindType(KnownTypeCode.IDisposable)); } else { Scan(child); } @@ -2397,11 +2381,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult IAstVisitor.VisitFixedStatement(FixedStatement fixedStatement, object data) { resolver.PushBlock(); - ITypeReference type = MakeTypeReference(fixedStatement.Type); + AstType type = fixedStatement.Type; for (AstNode node = fixedStatement.FirstChild; node != null; node = node.NextSibling) { if (node.Role == FixedStatement.Roles.Variable) { VariableInitializer vi = (VariableInitializer)node; - resolver.AddVariable(type, MakeRegion(vi) , vi.Name); + resolver.AddVariable(MakeVariable(type, vi.NameToken)); } Scan(node); } @@ -2412,24 +2396,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult IAstVisitor.VisitForeachStatement(ForeachStatement foreachStatement, object data) { resolver.PushBlock(); - ITypeReference type; + IVariable v; if (IsVar(foreachStatement.VariableType)) { if (navigator.Scan(foreachStatement.VariableType) == ResolveVisitorNavigationMode.Resolve) { IType collectionType = Resolve(foreachStatement.InExpression).Type; - IType elementType = GetElementType(collectionType, resolver.Context, false); + IType elementType = GetElementType(collectionType, resolver.Compilation, false); StoreResult(foreachStatement.VariableType, new TypeResolveResult(elementType)); - type = elementType; + v = MakeVariable(elementType, foreachStatement.VariableNameToken); } else { Scan(foreachStatement.InExpression); - type = MakeVarTypeReference(foreachStatement.InExpression, true); + v = MakeImplicitlyTypedVariable(foreachStatement.VariableNameToken, foreachStatement.InExpression, true); } } else { Scan(foreachStatement.InExpression); - type = ResolveType(foreachStatement.VariableType); + v = MakeVariable(foreachStatement.VariableType, foreachStatement.VariableNameToken); } StoreCurrentState(foreachStatement.VariableNameToken); - IVariable v = resolver.AddVariable(type, MakeRegion(foreachStatement.VariableNameToken), foreachStatement.VariableName); - StoreResult(foreachStatement.VariableNameToken, new LocalResolveResult(v, v.Type.Resolve(resolver.Context))); + resolver.AddVariable(v); + StoreResult(foreachStatement.VariableNameToken, new LocalResolveResult(v)); Scan(foreachStatement.EmbeddedStatement); resolver.PopBlock(); return voidResult; @@ -2447,11 +2431,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { resolver.PushBlock(); if (!string.IsNullOrEmpty(catchClause.VariableName)) { - ITypeReference variableType = MakeTypeReference(catchClause.Type); DomRegion region = MakeRegion(catchClause.VariableNameToken); StoreCurrentState(catchClause.VariableNameToken); - IVariable v = resolver.AddVariable(variableType, region, catchClause.VariableName); - StoreResult(catchClause.VariableNameToken, new LocalResolveResult(v, v.Type.Resolve(resolver.Context))); + IVariable v = MakeVariable(catchClause.Type, catchClause.VariableNameToken); + resolver.AddVariable(v); + StoreResult(catchClause.VariableNameToken, new LocalResolveResult(v)); } ScanChildren(catchClause); resolver.PopBlock(); @@ -2468,38 +2452,38 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver bool needResolve = resolverEnabled || navigator.Scan(variableDeclarationStatement.Type) == ResolveVisitorNavigationMode.Resolve || navigator.Scan(vi) == ResolveVisitorNavigationMode.Resolve; - ITypeReference type; + IVariable v; if (needResolve) { StoreCurrentState(variableDeclarationStatement.Type); - type = Resolve(vi.Initializer).Type; + IType type = Resolve(vi.Initializer).Type; if (!resolveResultCache.ContainsKey(variableDeclarationStatement.Type)) { - StoreResult(variableDeclarationStatement.Type, new TypeResolveResult(type.Resolve(resolver.Context))); + StoreResult(variableDeclarationStatement.Type, new TypeResolveResult(type)); } + v = MakeVariable(type, vi.NameToken); } else { Scan(vi.Initializer); - type = MakeVarTypeReference(vi.Initializer, false); + v = MakeImplicitlyTypedVariable(vi.NameToken, vi.Initializer, false); } - IVariable v = resolver.AddVariable(type, MakeRegion(vi), vi.Name); StoreCurrentState(vi); + resolver.AddVariable(v); if (needResolve) { ResolveResult result; if (!resolveResultCache.TryGetValue(vi, out result)) { - result = new LocalResolveResult(v, type.Resolve(resolver.Context)); - StoreResult(vi, result); + StoreResult(vi, new LocalResolveResult(v)); } } } else { - ITypeReference type = MakeTypeReference(variableDeclarationStatement.Type); + AstType type = variableDeclarationStatement.Type; for (AstNode node = variableDeclarationStatement.FirstChild; node != null; node = node.NextSibling) { if (node.Role == VariableDeclarationStatement.Roles.Variable) { VariableInitializer vi = (VariableInitializer)node; - IConstantValue cv = null; if (isConst) { - cv = TypeSystemConvertVisitor.ConvertConstantValue(type, vi.Initializer, resolver.CurrentTypeDefinition, resolver.CurrentMember as IMethod, resolver.CurrentUsingScope); + resolver.AddVariable(MakeConstant(type, vi.NameToken, vi.Initializer)); + } else { + resolver.AddVariable(MakeVariable(type, vi.NameToken)); } - resolver.AddVariable(type, MakeRegion(vi), vi.Name, cv); } Scan(node); } @@ -2540,7 +2524,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (resolverEnabled) { for (AstNode child = conditionStatement.FirstChild; child != null; child = child.NextSibling) { if (child.Role == AstNode.Roles.Condition) { - ResolveAndProcessConversion((Expression)child, KnownTypeReference.Boolean.Resolve(resolver.Context)); + ResolveAndProcessConversion((Expression)child, resolver.Compilation.FindType(KnownTypeCode.Boolean)); } else { Scan(child); } @@ -2555,7 +2539,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult IAstVisitor.VisitReturnStatement(ReturnStatement returnStatement, object data) { if (resolverEnabled && !resolver.IsWithinLambdaExpression && resolver.CurrentMember != null) { - IType type = resolver.CurrentMember.ReturnType.Resolve(resolver.Context); + IType type = resolver.CurrentMember.ReturnType; if (IsTask(type)) { var methodDecl = returnStatement.Ancestors.OfType().FirstOrDefault(); if (methodDecl != null && (methodDecl.Modifiers & Modifiers.Async) == Modifiers.Async) @@ -2571,8 +2555,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult IAstVisitor.VisitYieldReturnStatement(YieldReturnStatement yieldStatement, object data) { if (resolverEnabled && resolver.CurrentMember != null) { - IType returnType = resolver.CurrentMember.ReturnType.Resolve(resolver.Context); - IType elementType = GetElementType(returnType, resolver.Context, true); + IType returnType = resolver.CurrentMember.ReturnType; + IType elementType = GetElementType(returnType, resolver.Compilation, true); ResolveAndProcessConversion(yieldStatement.Expression, elementType); } else { Scan(yieldStatement.Expression); @@ -2660,14 +2644,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return st != null && st.Identifier == "var" && st.TypeArguments.Count == 0; } - ITypeReference MakeTypeReference(AstType type) + IVariable MakeVariable(IType type, Identifier variableName) + { + throw new NotImplementedException(); + } + + IVariable MakeVariable(AstType type, Identifier variableName) + { + throw new NotImplementedException(); + } + + IVariable MakeConstant(AstType type, Identifier variableName, Expression initializer) { - return TypeSystemConvertVisitor.ConvertType(type, resolver.CurrentTypeDefinition, resolver.CurrentMember as IMethod, resolver.CurrentUsingScope, currentTypeLookupMode); + throw new NotImplementedException(); } - ITypeReference MakeVarTypeReference(Expression initializer, bool isForEach) + IVariable MakeImplicitlyTypedVariable(Identifier variableName, Expression initializer, bool isForEach) { - return new VarTypeReference(this, resolver.Clone(), initializer, isForEach); + throw new NotImplementedException(); } sealed class VarTypeReference : ITypeReference @@ -2690,7 +2684,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public IType Resolve(ITypeResolveContext context) { if (visitor == null) - return result ?? SharedTypes.UnknownType; + return result ?? SpecialType.UnknownType; visitor.ResetContext( storedContext, @@ -2698,7 +2692,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver result = visitor.Resolve(initializerExpression).Type; if (isForEach) { - result = GetElementType(result, storedContext.Context, false); + result = GetElementType(result, storedContext.Compilation, false); } }); visitor = null; @@ -2716,28 +2710,27 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } - static IType GetElementType(IType result, ITypeResolveContext context, bool allowIEnumerator) + static IType GetElementType(IType result, ICompilation compilation, bool allowIEnumerator) { - bool foundSimpleIEnumerable = false; - foreach (IType baseType in result.GetAllBaseTypes(context)) { + bool foundNonGenericIEnumerable = false; + foreach (IType baseType in result.GetAllBaseTypes()) { ITypeDefinition baseTypeDef = baseType.GetDefinition(); - if (baseTypeDef != null && ( - baseTypeDef.Name == "IEnumerable" || (allowIEnumerator && baseType.Name == "IEnumerator"))) - { - if (baseTypeDef.Namespace == "System.Collections.Generic" && baseTypeDef.TypeParameterCount == 1) { + if (baseTypeDef != null) { + KnownTypeCode typeCode = baseTypeDef.KnownTypeCode; + if (typeCode == KnownTypeCode.IEnumerableOfT || (allowIEnumerator && typeCode == KnownTypeCode.IEnumeratorOfT)) { ParameterizedType pt = baseType as ParameterizedType; if (pt != null) { return pt.GetTypeArgument(0); } - } else if (baseTypeDef.Namespace == "System.Collections" && baseTypeDef.TypeParameterCount == 0) { - foundSimpleIEnumerable = true; } + if (typeCode == KnownTypeCode.IEnumerable || (allowIEnumerator && typeCode == KnownTypeCode.IEnumerator)) + foundNonGenericIEnumerable = true; } } // System.Collections.IEnumerable found in type hierarchy -> Object is element type. - if (foundSimpleIEnumerable) - return KnownTypeReference.Object.Resolve(context); - return SharedTypes.UnknownType; + if (foundNonGenericIEnumerable) + return compilation.FindType(KnownTypeCode.Object); + return SpecialType.UnknownType; } #endregion @@ -2805,21 +2798,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { if (!resolverEnabled) return null; - IType type = MakeTypeReference(primitiveType).Resolve(resolver.Context); - if (type.Kind != TypeKind.Unknown) - return new TypeResolveResult(type); - else - return errorResult; + KnownTypeCode typeCode = TypeSystemConvertVisitor.GetTypeCodeForPrimitiveType(primitiveType.Keyword); + IType type = resolver.Compilation.FindType(typeCode); + return new TypeResolveResult(type); } ResolveResult HandleAttributeType(AstType astType) { - ScanChildren(astType); - IType type = TypeSystemConvertVisitor.ConvertAttributeType(astType, resolver.CurrentTypeDefinition, resolver.CurrentMember as IMethod, resolver.CurrentUsingScope).Resolve(resolver.Context); - if (type.Kind != TypeKind.Unknown) - return new TypeResolveResult(type); - else - return errorResult; + throw new NotImplementedException(); } ResolveResult IAstVisitor.VisitSimpleType(SimpleType simpleType, object data) @@ -2867,13 +2853,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } IType t = ResolveType(composedType.BaseType); if (composedType.HasNullableSpecifier) { - t = NullableType.Create(t, resolver.Context); + t = NullableType.Create(resolver.Compilation, t); } for (int i = 0; i < composedType.PointerRank; i++) { t = new PointerType(t); } foreach (var a in composedType.ArraySpecifiers.Reverse()) { - t = new ArrayType(t, a.Dimensions); + t = new ArrayType(resolver.Compilation, t, a.Dimensions); } return new TypeResolveResult(t); } @@ -2900,7 +2886,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { // This assumes queries are only used on IEnumerable. // We might want to look at the signature of a LINQ method (e.g. Select) instead. - return GetElementType(type, resolver.Context, false); + return GetElementType(type, resolver.Compilation, false); } sealed class QueryExpressionLambda : LambdaResolveResult @@ -2914,7 +2900,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { this.parameters = new IParameter[parameterCount]; for (int i = 0; i < parameterCount; i++) { - parameters[i] = new DefaultParameter(SharedTypes.UnknownType, "x" + i); + parameters[i] = new DefaultParameter(SpecialType.UnknownType, "x" + i); } this.bodyExpression = bodyExpression; } @@ -2986,23 +2972,22 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { ResolveResult result = null; ResolveResult expr = Resolve(queryFromClause.Expression); - IType variableType; + IVariable v; if (queryFromClause.Type.IsNull) { - variableType = GetTypeForQueryVariable(expr.Type); + v = MakeVariable(GetTypeForQueryVariable(expr.Type), queryFromClause.IdentifierToken); result = expr; } else { - variableType = ResolveType(queryFromClause.Type); + v = MakeVariable(ResolveType(queryFromClause.Type), queryFromClause.IdentifierToken); if (resolverEnabled) { // resolve the .Cast<>() call - ResolveResult methodGroup = resolver.ResolveMemberAccess(expr, "Cast", new[] { variableType }, true); + ResolveResult methodGroup = resolver.ResolveMemberAccess(expr, "Cast", new[] { v.Type }, true); result = resolver.ResolveInvocation(methodGroup, new ResolveResult[0]); } } StoreCurrentState(queryFromClause.IdentifierToken); - DomRegion region = MakeRegion(queryFromClause.IdentifierToken); - IVariable v = resolver.AddVariable(variableType, region, queryFromClause.Identifier); - StoreResult(queryFromClause.IdentifierToken, new LocalResolveResult(v, variableType)); + resolver.AddVariable(v); + StoreResult(queryFromClause.IdentifierToken, new LocalResolveResult(v)); if (resolverEnabled && currentQueryResult != null) { // this is a second 'from': resolve the .SelectMany() call @@ -3029,20 +3014,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { ResolveResult rr = Resolve(queryContinuationClause.PrecedingQuery); IType variableType = GetTypeForQueryVariable(rr.Type); - DomRegion region = MakeRegion(queryContinuationClause.IdentifierToken); StoreCurrentState(queryContinuationClause.IdentifierToken); - IVariable v = resolver.AddVariable(variableType, region, queryContinuationClause.Identifier); - StoreResult(queryContinuationClause.IdentifierToken, new LocalResolveResult(v, variableType)); + IVariable v = MakeVariable(variableType, queryContinuationClause.IdentifierToken); + resolver.AddVariable(v); + StoreResult(queryContinuationClause.IdentifierToken, new LocalResolveResult(v)); return rr; } ResolveResult IAstVisitor.VisitQueryLetClause(QueryLetClause queryLetClause, object data) { ResolveResult expr = Resolve(queryLetClause.Expression); - DomRegion region = MakeRegion(queryLetClause.IdentifierToken); StoreCurrentState(queryLetClause.IdentifierToken); - IVariable v = resolver.AddVariable(expr.Type, region, queryLetClause.Identifier); - StoreResult(queryLetClause.IdentifierToken, new LocalResolveResult(v, expr.Type)); + IVariable v = MakeVariable(expr.Type, queryLetClause.IdentifierToken); + resolver.AddVariable(v); + StoreResult(queryLetClause.IdentifierToken, new LocalResolveResult(v)); if (resolverEnabled && currentQueryResult != null) { // resolve the .Select() call ResolveResult methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "Select", EmptyList.Instance, true); @@ -3078,19 +3063,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // scan the 'Equals' expression in a context that contains only the variable 'v' CSharpResolver resolverOutsideQuery = resolver.Clone(); resolverOutsideQuery.PopBlock(); // pop all variables from the current query expression - DomRegion joinIdentifierRegion = MakeRegion(queryJoinClause.JoinIdentifierToken); - IVariable v = resolverOutsideQuery.AddVariable(variableType, joinIdentifierRegion, queryJoinClause.JoinIdentifier); + IVariable v = MakeVariable(variableType, queryJoinClause.JoinIdentifierToken); + resolverOutsideQuery.AddVariable(v); ResolveResult equalsResult = errorResult; ResetContext(resolverOutsideQuery, delegate { equalsResult = Resolve(queryJoinClause.EqualsExpression); }); StoreCurrentState(queryJoinClause.JoinIdentifierToken); - StoreResult(queryJoinClause.JoinIdentifierToken, new LocalResolveResult(v, variableType)); + StoreResult(queryJoinClause.JoinIdentifierToken, new LocalResolveResult(v)); if (queryJoinClause.IsGroupJoin) { return ResolveGroupJoin(queryJoinClause, inResult, onResult, equalsResult); } else { - resolver.AddVariable(variableType, joinIdentifierRegion, queryJoinClause.JoinIdentifier); + resolver.AddVariable(v); if (resolverEnabled && currentQueryResult != null) { QuerySelectClause selectClause = GetNextQueryClause(queryJoinClause) as QuerySelectClause; ResolveResult selectResult; @@ -3132,10 +3117,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (selectClause != null) { // from ... join ... into g select - the GroupJoin call also performs the Select operation IParameter[] selectLambdaParameters = { - new DefaultParameter(SharedTypes.UnknownType, "<>transparentIdentifier"), - new DefaultParameter(SharedTypes.UnknownType, queryJoinClause.IntoIdentifier) { - Region = intoIdentifierRegion - } + new DefaultParameter(SpecialType.UnknownType, "<>transparentIdentifier"), + new DefaultParameter(SpecialType.UnknownType, queryJoinClause.IntoIdentifier, region: intoIdentifierRegion) }; groupJoinLambda = new ImplicitlyTypedLambda(selectClause, selectLambdaParameters, this); } else { @@ -3191,15 +3174,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (inferredParameterTypes != null && inferredParameterTypes.Length == 2) groupParameterType = inferredParameterTypes[1]; else - groupParameterType = SharedTypes.UnknownType; + groupParameterType = SpecialType.UnknownType; - StoreCurrentState(queryJoinClause.IntoIdentifierToken); - groupVariable = resolver.AddVariable(groupParameterType, intoIdentifierRegion, queryJoinClause.IntoIdentifier); + groupVariable = MakeVariable(groupParameterType, queryJoinClause.IntoIdentifierToken); + resolver.AddVariable(groupVariable); } if (groupVariable != null) { - LocalResolveResult lrr = new LocalResolveResult(groupVariable, groupVariable.Type.Resolve(resolver.Context)); - StoreResult(queryJoinClause.IntoIdentifierToken, lrr); + StoreResult(queryJoinClause.IntoIdentifierToken, new LocalResolveResult(groupVariable)); } return rr; @@ -3208,7 +3190,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult IAstVisitor.VisitQueryWhereClause(QueryWhereClause queryWhereClause, object data) { ResolveResult condition = Resolve(queryWhereClause.Condition); - IType boolType = KnownTypeReference.Boolean.Resolve(resolver.Context); + IType boolType = resolver.Compilation.FindType(KnownTypeCode.Boolean); Conversion conversionToBool = resolver.conversions.ImplicitConversion(condition, boolType); ProcessConversion(queryWhereClause.Condition, condition, conversionToBool, boolType); if (resolverEnabled && currentQueryResult != null) { diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs b/ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs index c15c42e434..fa5d7cbc24 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs @@ -49,7 +49,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// public sealed class TypeInference { - readonly ITypeResolveContext context; + readonly ICompilation compilation; readonly Conversions conversions; TypeInferenceAlgorithm algorithm = TypeInferenceAlgorithm.CSharp4; @@ -58,12 +58,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver int nestingLevel; #region Constructor - public TypeInference(ITypeResolveContext context, Conversions conversions = null) + public TypeInference(ICompilation compilation) { - if (context == null) - throw new ArgumentNullException("context"); - this.context = context; - this.conversions = conversions ?? Conversions.Get(context); + if (compilation == null) + throw new ArgumentNullException("compilation"); + this.compilation = compilation; + this.conversions = Conversions.Get(compilation); + } + + internal TypeInference(ICompilation compilation, Conversions conversions) + { + Debug.Assert(compilation != null); + Debug.Assert(conversions != null); + this.compilation = compilation; + this.conversions = conversions; } #endregion @@ -78,7 +86,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver TypeInference CreateNestedInstance() { - TypeInference c = new TypeInference(context, conversions); + TypeInference c = new TypeInference(compilation, conversions); c.algorithm = algorithm; c.nestingLevel = nestingLevel + 1; return c; @@ -141,8 +149,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Log.Unindent(); Log.WriteLine(" Type inference finished " + (success ? "successfully" : "with errors") + ": " + - "M<" + string.Join(", ", this.typeParameters.Select(tp => tp.FixedTo ?? SharedTypes.UnknownType)) + ">"); - return this.typeParameters.Select(tp => tp.FixedTo ?? SharedTypes.UnknownType).ToArray(); + "M<" + string.Join(", ", this.typeParameters.Select(tp => tp.FixedTo ?? SpecialType.UnknownType)) + ">"); + return this.typeParameters.Select(tp => tp.FixedTo ?? SpecialType.UnknownType).ToArray(); } finally { Reset(); } @@ -188,7 +196,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver success = true; for (int i = 0; i < result.Length; i++) { success &= Fix(this.typeParameters[i]); - result[i] = this.typeParameters[i].FixedTo ?? SharedTypes.UnknownType; + result[i] = this.typeParameters[i].FixedTo ?? SpecialType.UnknownType; } Reset(); return result; @@ -264,7 +272,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } IType U = Ei.Type; - if (U != SharedTypes.UnknownType) { + if (U != SpecialType.UnknownType) { if (Ti is ByReferenceType) { MakeExactInference(Ei.Type, Ti); } else { @@ -348,7 +356,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (m != null) { IType[] inputTypes = new IType[m.Parameters.Count]; for (int i = 0; i < inputTypes.Length; i++) { - inputTypes[i] = m.Parameters[i].Type.Resolve(context); + inputTypes[i] = m.Parameters[i].Type; } return inputTypes; } @@ -363,7 +371,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (lrr != null && lrr.IsImplicitlyTyped || e is MethodGroupResolveResult) { IMethod m = GetDelegateOrExpressionTreeSignature(t); if (m != null) { - return new[] { m.ReturnType.Resolve(context) }; + return new[] { m.ReturnType }; } } return emptyTypeArray; @@ -465,14 +473,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver TypeParameterSubstitution substitution = GetSubstitutionForFixedTPs(); IType[] inferredParameterTypes = new IType[m.Parameters.Count]; for (int i = 0; i < inferredParameterTypes.Length; i++) { - IType parameterType = m.Parameters[i].Type.Resolve(context); + IType parameterType = m.Parameters[i].Type; inferredParameterTypes[i] = parameterType.AcceptVisitor(substitution); } inferredReturnType = lrr.GetInferredReturnType(inferredParameterTypes); } else { inferredReturnType = lrr.GetInferredReturnType(null); } - MakeLowerBoundInference(inferredReturnType, m.ReturnType.Resolve(context)); + MakeLowerBoundInference(inferredReturnType, m.ReturnType); return; } } @@ -488,8 +496,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver TypeParameterSubstitution substitution = GetSubstitutionForFixedTPs(); for (int i = 0; i < args.Length; i++) { IParameter param = m.Parameters[i]; - IType parameterType = param.Type.Resolve(context); - parameterType = parameterType.AcceptVisitor(substitution); + IType parameterType = param.Type.AcceptVisitor(substitution); if ((param.IsRef || param.IsOut) && parameterType.Kind == TypeKind.ByReference) { parameterType = ((ByReferenceType)parameterType).ElementType; args[i] = new ByReferenceResolveResult(parameterType, param.IsOut); @@ -497,18 +504,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver args[i] = new ResolveResult(parameterType); } } - var or = mgrr.PerformOverloadResolution(context, args, + var or = mgrr.PerformOverloadResolution(compilation, + args, allowExtensionMethods: false, allowExpandingParams: false); if (or.FoundApplicableCandidate && or.BestCandidateAmbiguousWith == null) { - IType returnType = or.BestCandidate.ReturnType.Resolve(context); - MakeLowerBoundInference(returnType, m.ReturnType.Resolve(context)); + IType returnType = or.BestCandidate.ReturnType; + MakeLowerBoundInference(returnType, m.ReturnType); } } return; } // Otherwise, if E is an expression with type U, then a lower-bound inference is made from U to T. - if (e.Type != SharedTypes.UnknownType) { + if (e.Type != SpecialType.UnknownType) { MakeLowerBoundInference(e.Type, t); } } @@ -517,7 +525,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { IType[] fixedTypes = new IType[typeParameters.Length]; for (int i = 0; i < fixedTypes.Length; i++) { - fixedTypes[i] = typeParameters[i].FixedTo ?? SharedTypes.UnknownType; + fixedTypes[i] = typeParameters[i].FixedTo ?? SpecialType.UnknownType; } return new TypeParameterSubstitution(classTypeArguments, fixedTypes); } @@ -534,7 +542,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (m == null) return; for (int i = 0; i < e.Parameters.Count && i < m.Parameters.Count; i++) { - MakeExactInference(e.Parameters[i].Type.Resolve(context), m.Parameters[i].Type.Resolve(context)); + MakeExactInference(e.Parameters[i].Type, m.Parameters[i].Type); } } #endregion @@ -628,7 +636,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // Handle parameterized types: if (pV != null) { ParameterizedType uniqueBaseType = null; - foreach (IType baseU in U.GetAllBaseTypes(context)) { + foreach (IType baseU in U.GetAllBaseTypes()) { ParameterizedType pU = baseU as ParameterizedType; if (pU != null && object.Equals(pU.GetDefinition(), pV.GetDefinition()) && pU.TypeParameterCount == pV.TypeParameterCount) { if (uniqueBaseType == null) @@ -642,7 +650,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver for (int i = 0; i < uniqueBaseType.TypeParameterCount; i++) { IType Ui = uniqueBaseType.GetTypeArgument(i); IType Vi = pV.GetTypeArgument(i); - if (Ui.IsReferenceType(context) == true) { + if (Ui.IsReferenceType == true) { // look for variance ITypeParameter Xi = pV.GetDefinition().TypeParameters[i]; switch (Xi.Variance) { @@ -712,7 +720,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // Handle parameterized types: if (pU != null) { ParameterizedType uniqueBaseType = null; - foreach (IType baseV in V.GetAllBaseTypes(context)) { + foreach (IType baseV in V.GetAllBaseTypes()) { ParameterizedType pV = baseV as ParameterizedType; if (pV != null && object.Equals(pU.GetDefinition(), pV.GetDefinition()) && pU.TypeParameterCount == pV.TypeParameterCount) { if (uniqueBaseType == null) @@ -726,7 +734,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver for (int i = 0; i < uniqueBaseType.TypeParameterCount; i++) { IType Ui = pU.GetTypeArgument(i); IType Vi = uniqueBaseType.GetTypeArgument(i); - if (Ui.IsReferenceType(context) == true) { + if (Ui.IsReferenceType == true) { // look for variance ITypeParameter Xi = pU.GetDefinition().TypeParameters[i]; switch (Xi.Variance) { @@ -785,12 +793,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } Log.WriteCollection("GetBestCommonType() for ", expressions); try { - this.typeParameters = new TP[1] { new TP(DummyTypeParameter.Instance) }; + DummyTypeParameter tp = new DummyTypeParameter(compilation); + this.typeParameters = new TP[1] { new TP(tp) }; foreach (ResolveResult r in expressions) { - MakeOutputTypeInference(r, DummyTypeParameter.Instance); + MakeOutputTypeInference(r, tp); } success = Fix(typeParameters[0]); - return typeParameters[0].FixedTo ?? SharedTypes.UnknownType; + return typeParameters[0].FixedTo ?? SpecialType.UnknownType; } finally { Reset(); } @@ -798,25 +807,32 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver sealed class DummyTypeParameter : AbstractType, ITypeParameter { - public static readonly DummyTypeParameter Instance = new DummyTypeParameter(); + readonly ICompilation compilation; + + public DummyTypeParameter(ICompilation compilation) + { + this.compilation = compilation; + } + + ICompilation IResolved.Compilation { + get { return compilation; } + } public override string Name { get { return "X"; } } - public override bool? IsReferenceType(ITypeResolveContext context) - { - return null; + public override bool? IsReferenceType { + get { return null; } } - public override int GetHashCode() - { - return 0; + public override TypeKind Kind { + get { return TypeKind.TypeParameter; } } - public override bool Equals(IType other) + public override ITypeReference ToTypeReference() { - return this == other; + throw new NotSupportedException(); } int ITypeParameter.Index { @@ -835,35 +851,32 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver get { return VarianceModifier.Invariant; } } - bool IFreezable.IsFrozen { - get { return true; } + DomRegion ITypeParameter.Region { + get { return DomRegion.Empty; } } - void IFreezable.Freeze() - { + IEntity ITypeParameter.Owner { + get { return null; } } - DomRegion ITypeParameter.Region { - get { return DomRegion.Empty; } + IType ITypeParameter.EffectiveBaseClass { + get { return SpecialType.UnknownType; } } - public override TypeKind Kind { - get { return TypeKind.TypeParameter; } + IList ITypeParameter.EffectiveInterfaceSet { + get { return EmptyList.Instance; } } - ITypeParameterConstraints ITypeParameter.GetConstraints(ITypeResolveContext context) - { - return DefaultTypeParameterConstraints.Empty; + bool ITypeParameter.HasDefaultConstructorConstraint { + get { return false; } } - IType ITypeParameter.GetEffectiveBaseClass(ITypeResolveContext context) - { - return KnownTypeReference.Object.Resolve(context); + bool ITypeParameter.HasReferenceTypeConstraint { + get { return false; } } - IEnumerable ITypeParameter.GetEffectiveInterfaceSet(ITypeResolveContext context) - { - return EmptyList.Instance; + bool ITypeParameter.HasValueTypeConstraint { + get { return false; } } } #endregion @@ -892,7 +905,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver static IType GetFirstTypePreferNonInterfaces(IList result) { return result.FirstOrDefault(c => c.Kind != TypeKind.Interface) - ?? result.FirstOrDefault() ?? SharedTypes.UnknownType; + ?? result.FirstOrDefault() ?? SpecialType.UnknownType; } IList FindTypesInBounds(IList lowerBounds, IList upperBounds) @@ -934,21 +947,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver List candidateTypeDefinitions; if (lowerBounds.Count > 0) { // Find candidates by using the lower bounds: - var hashSet = new HashSet(lowerBounds[0].GetAllBaseTypeDefinitions(context)); + var hashSet = new HashSet(lowerBounds[0].GetAllBaseTypeDefinitions()); for (int i = 1; i < lowerBounds.Count; i++) { - hashSet.IntersectWith(lowerBounds[i].GetAllBaseTypeDefinitions(context)); + hashSet.IntersectWith(lowerBounds[i].GetAllBaseTypeDefinitions()); } candidateTypeDefinitions = hashSet.ToList(); } else { // Find candidates by looking at all classes in the project: - candidateTypeDefinitions = context.GetAllTypes().ToList(); + candidateTypeDefinitions = compilation.GetAllTypeDefinitions().ToList(); } // Now filter out candidates that violate the upper bounds: foreach (IType ub in upperBounds) { ITypeDefinition ubDef = ub.GetDefinition(); if (ubDef != null) { - candidateTypeDefinitions.RemoveAll(c => !c.IsDerivedFrom(ubDef, context)); + candidateTypeDefinitions.RemoveAll(c => !c.IsDerivedFrom(ubDef)); } } @@ -978,9 +991,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // if there were lower bounds, we aim for the most specific candidate: // if this candidate isn't made redundant by an existing, more specific candidate: - if (!candidateTypes.Any(c => c.GetDefinition().IsDerivedFrom(candidateDef, context))) { + if (!candidateTypes.Any(c => c.GetDefinition().IsDerivedFrom(candidateDef))) { // remove all existing candidates made redundant by this candidate: - candidateTypes.RemoveAll(c => candidateDef.IsDerivedFrom(c.GetDefinition(), context)); + candidateTypes.RemoveAll(c => candidateDef.IsDerivedFrom(c.GetDefinition())); // add new candidate candidateTypes.Add(candidate); } @@ -988,9 +1001,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // if there only were upper bounds, we aim for the least specific candidate: // if this candidate isn't made redundant by an existing, less specific candidate: - if (!candidateTypes.Any(c => candidateDef.IsDerivedFrom(c.GetDefinition(), context))) { + if (!candidateTypes.Any(c => candidateDef.IsDerivedFrom(c.GetDefinition()))) { // remove all existing candidates made redundant by this candidate: - candidateTypes.RemoveAll(c => c.GetDefinition().IsDerivedFrom(candidateDef, context)); + candidateTypes.RemoveAll(c => c.GetDefinition().IsDerivedFrom(candidateDef)); // add new candidate candidateTypes.Add(candidate); } diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/AliasNamespaceReference.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/AliasNamespaceReference.cs similarity index 71% rename from ICSharpCode.NRefactory.CSharp/Resolver/AliasNamespaceReference.cs rename to ICSharpCode.NRefactory.CSharp/TypeSystem/AliasNamespaceReference.cs index 92493038a6..a6baf0189d 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/AliasNamespaceReference.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/AliasNamespaceReference.cs @@ -17,10 +17,11 @@ // DEALINGS IN THE SOFTWARE. using System; +using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; -namespace ICSharpCode.NRefactory.CSharp.Resolver +namespace ICSharpCode.NRefactory.CSharp.TypeSystem { /// /// Looks up an alias (identifier in front of :: operator). @@ -30,38 +31,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// by . /// [Serializable] - public class AliasNamespaceReference : ITypeOrNamespaceReference + public class AliasNamespaceReference : TypeOrNamespaceReference { - readonly UsingScope parentUsingScope; readonly string identifier; - public AliasNamespaceReference(string identifier, UsingScope parentUsingScope) + public AliasNamespaceReference(string identifier) { if (identifier == null) throw new ArgumentNullException("identifier"); this.identifier = identifier; - this.parentUsingScope = parentUsingScope; } public string Identifier { get { return identifier; } } - public ResolveResult DoResolve(ITypeResolveContext context) + public override ResolveResult Resolve(CSharpResolver resolver) { - CSharpResolver r = new CSharpResolver(context); - r.CurrentUsingScope = parentUsingScope; - return r.ResolveAlias(identifier); - } - - public NamespaceResolveResult ResolveNamespace(ITypeResolveContext context) - { - return DoResolve(context) as NamespaceResolveResult; - } - - public IType Resolve(ITypeResolveContext context) - { - return SharedTypes.UnknownType; + return resolver.ResolveAlias(identifier); } public override string ToString() diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/AttributeTypeReference.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/AttributeTypeReference.cs new file mode 100644 index 0000000000..c627fc3037 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/AttributeTypeReference.cs @@ -0,0 +1,93 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Linq; + +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.CSharp.TypeSystem +{ + /// + /// Type reference used within an attribute. + /// Looks up both 'withoutSuffix' and 'withSuffix' and returns the type that exists. + /// + [Serializable] + public sealed class AttributeTypeReference : ITypeReference, ISupportsInterning + { + ITypeReference withoutSuffix, withSuffix; + + public AttributeTypeReference(ITypeReference withoutSuffix, ITypeReference withSuffix) + { + if (withoutSuffix == null) + throw new ArgumentNullException("withoutSuffix"); + if (withSuffix == null) + throw new ArgumentNullException("withSuffix"); + this.withoutSuffix = withoutSuffix; + this.withSuffix = withSuffix; + } + + public IType Resolve(ITypeResolveContext context) + { + IType t1 = withoutSuffix.Resolve(context); + IType t2 = withSuffix.Resolve(context); + + if (t2.Kind == TypeKind.Unknown) return t1; + if (t1.Kind == TypeKind.Unknown) return t2; + + var attrTypeDef = KnownTypeReference.Attribute.Resolve(context).GetDefinition(); + if (attrTypeDef != null) { + bool t1IsAttribute = (t1.GetDefinition() != null && t1.GetDefinition().IsDerivedFrom(attrTypeDef)); + bool t2IsAttribute = (t2.GetDefinition() != null && t2.GetDefinition().IsDerivedFrom(attrTypeDef)); + if (t2IsAttribute && !t1IsAttribute) + return t2; + // If both types exist and are attributes, C# considers that to be an ambiguity, but we are less strict. + } + return t1; + } + + public override string ToString() + { + return withoutSuffix.ToString() + "[Attribute]"; + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + withoutSuffix = provider.Intern(withoutSuffix); + withSuffix = provider.Intern(withSuffix); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + unchecked { + return withoutSuffix.GetHashCode() + 715613 * withSuffix.GetHashCode(); + } + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + AttributeTypeReference atr = other as AttributeTypeReference; + return atr != null && this.withoutSuffix == atr.withoutSuffix && this.withSuffix == atr.withSuffix; + } + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/IExplicitInterfaceImplementation.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAssembly.cs similarity index 54% rename from ICSharpCode.NRefactory/TypeSystem/IExplicitInterfaceImplementation.cs rename to ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAssembly.cs index 1e8145f0bd..26cf4d8b00 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IExplicitInterfaceImplementation.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAssembly.cs @@ -17,46 +17,57 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Diagnostics.Contracts; +using ICSharpCode.NRefactory.TypeSystem; -namespace ICSharpCode.NRefactory.TypeSystem +namespace ICSharpCode.NRefactory.CSharp.TypeSystem { - /// - /// Represents an explicit interface implementation. - /// - #if WITH_CONTRACTS - [ContractClass(typeof(IExplicitInterfaceImplementationContract))] - #endif - public interface IExplicitInterfaceImplementation : IFreezable + public class CSharpAssembly : IAssembly { - /// - /// Gets the type of the interface. - /// - ITypeReference InterfaceType { get; } + bool IAssembly.IsMainAssembly { + get { + throw new NotImplementedException(); + } + } - /// - /// Gets the member name. - /// - string MemberName { get; } - } - - #if WITH_CONTRACTS - [ContractClassFor(typeof(IExplicitInterfaceImplementation))] - abstract class IExplicitInterfaceImplementationContract : IFreezableContract, IExplicitInterfaceImplementation - { - ITypeReference IExplicitInterfaceImplementation.InterfaceType { + IUnresolvedAssembly IAssembly.UnresolvedAssembly { + get { + throw new NotImplementedException(); + } + } + + string IAssembly.AssemblyName { get { - Contract.Ensures(Contract.Result() != null); - return null; + throw new NotImplementedException(); } } - string IExplicitInterfaceImplementation.MemberName { + System.Collections.Generic.IList IAssembly.AssemblyAttributes { get { - Contract.Ensures(Contract.Result() != null); - return null; + throw new NotImplementedException(); } } + + System.Collections.Generic.IList IAssembly.ModuleAttributes { + get { + throw new NotImplementedException(); + } + } + + INamespace IAssembly.RootNamespace { + get { + throw new NotImplementedException(); + } + } + + ICompilation IResolved.Compilation { + get { + throw new NotImplementedException(); + } + } + + bool IAssembly.InternalsVisibleTo(IAssembly assembly) + { + throw new NotImplementedException(); + } } - #endif } diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpAttribute.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAttribute.cs similarity index 71% rename from ICSharpCode.NRefactory.CSharp/Resolver/CSharpAttribute.cs rename to ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAttribute.cs index b0a04c2023..52716e76b2 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpAttribute.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAttribute.cs @@ -21,15 +21,15 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; - using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; +using ICSharpCode.NRefactory.Utils; -namespace ICSharpCode.NRefactory.CSharp.Resolver +namespace ICSharpCode.NRefactory.CSharp.TypeSystem { [Serializable] - public sealed class CSharpAttribute : Immutable, IAttribute + public sealed class CSharpAttribute : IUnresolvedAttribute { ITypeReference attributeType; DomRegion region; @@ -59,6 +59,71 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver get { return attributeType; } } + public IAttribute CreateResolvedAttribute(ITypeResolveContext context) + { + return new CSharpResolvedAttribute(context, this); + } + + sealed class CSharpResolvedAttribute : IAttribute + { + readonly ITypeResolveContext context; + readonly CSharpAttribute unresolved; + readonly IType attributeType; + + IList> namedArguments; + + public CSharpResolvedAttribute(ITypeResolveContext context, CSharpAttribute unresolved) + { + this.context = context; + this.unresolved = unresolved; + // Pretty much any access to the attribute checks the type first, so + // we don't need to use lazy-loading for that. + this.attributeType = unresolved.AttributeType.Resolve(context); + } + + DomRegion IAttribute.Region { + get { return unresolved.Region; } + } + + IType IAttribute.AttributeType { + get { return attributeType; } + } + + IMethod IAttribute.Constructor { + get { + throw new NotImplementedException(); + } + } + + IList IAttribute.PositionalArguments { + get { + throw new NotImplementedException(); + } + } + + IList> IAttribute.NamedArguments { + get { + var namedArgs = this.namedArguments; + if (namedArgs != null) { + LazyInit.ReadBarrier(); + return namedArgs; + } else { + namedArgs = new List>(); + foreach (var pair in unresolved.namedArguments) { + IMember member = attributeType.GetMembers(m => (m.EntityType == EntityType.Field || m.EntityType == EntityType.Property) && m.Name == pair.Key).FirstOrDefault(); + if (member != null) { + ResolveResult val = pair.Value.Resolve(context); + namedArgs.Add(new KeyValuePair(member, val)); + } + } + return LazyInit.GetOrSet(ref this.namedArguments, namedArgs); + } + } + } + } + } + + /* public IMethod ResolveConstructor(ITypeResolveContext context) { CSharpResolver r = new CSharpResolver(context); @@ -132,7 +197,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (constantValue != null) return constantValue.Resolve(context); else - return new ErrorResolveResult(SharedTypes.UnknownType); + return new ErrorResolveResult(SpecialType.UnknownType); } public IList> GetNamedArguments(ITypeResolveContext context) @@ -145,62 +210,5 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } } - - /// - /// Type reference used within an attribute. - /// Looks up both 'withoutSuffix' and 'withSuffix' and returns the type that exists. - /// - [Serializable] - public sealed class AttributeTypeReference : ITypeReference, ISupportsInterning - { - ITypeReference withoutSuffix, withSuffix; - - public AttributeTypeReference(ITypeReference withoutSuffix, ITypeReference withSuffix) - { - if (withoutSuffix == null) - throw new ArgumentNullException("withoutSuffix"); - if (withSuffix == null) - throw new ArgumentNullException("withSuffix"); - this.withoutSuffix = withoutSuffix; - this.withSuffix = withSuffix; - } - - public IType Resolve(ITypeResolveContext context) - { - // If both types exist, C# considers that to be an ambiguity, but we are less strict. - IType type = withoutSuffix.Resolve(context); - var attrType = context.GetTypeDefinition (typeof(System.Attribute)); - if (attrType == null) - return SharedTypes.UnknownType; - - if (type.GetDefinition() == null || !type.GetDefinition().IsDerivedFrom(attrType, context)) - type = withSuffix.Resolve(context); - - return type; - } - - public override string ToString() - { - return withoutSuffix.ToString() + "[Attribute]"; - } - - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - withoutSuffix = provider.Intern(withoutSuffix); - withSuffix = provider.Intern(withSuffix); - } - - int ISupportsInterning.GetHashCodeForInterning() - { - unchecked { - return withoutSuffix.GetHashCode() + 715613 * withSuffix.GetHashCode(); - } - } - - bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) - { - AttributeTypeReference atr = other as AttributeTypeReference; - return atr != null && this.withoutSuffix == atr.withoutSuffix && this.withSuffix == atr.withSuffix; - } - } + */ } diff --git a/ICSharpCode.NRefactory.CSharp/Parser/ParsedFile.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpParsedFile.cs similarity index 71% rename from ICSharpCode.NRefactory.CSharp/Parser/ParsedFile.cs rename to ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpParsedFile.cs index 1483d73b67..bd3ec9f677 100644 --- a/ICSharpCode.NRefactory.CSharp/Parser/ParsedFile.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpParsedFile.cs @@ -18,11 +18,10 @@ using System; using System.Collections.Generic; -using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; -namespace ICSharpCode.NRefactory.CSharp +namespace ICSharpCode.NRefactory.CSharp.TypeSystem { /// /// Represents a file that was parsed and converted for the type system. @@ -32,9 +31,9 @@ namespace ICSharpCode.NRefactory.CSharp { readonly string fileName; readonly UsingScope rootUsingScope; - IList topLevelTypeDefinitions = new List(); - IList assemblyAttributes = new List(); - IList moduleAttributes = new List(); + IList topLevelTypeDefinitions = new List(); + IList assemblyAttributes = new List(); + IList moduleAttributes = new List(); IList usingScopes = new List(); IList errors = new List (); @@ -42,10 +41,10 @@ namespace ICSharpCode.NRefactory.CSharp { base.FreezeInternal(); rootUsingScope.Freeze(); - topLevelTypeDefinitions = FreezeList(topLevelTypeDefinitions); - assemblyAttributes = FreezeList(assemblyAttributes); - moduleAttributes = FreezeList(moduleAttributes); - usingScopes = FreezeList(usingScopes); + topLevelTypeDefinitions = FreezableHelper.FreezeListAndElements(topLevelTypeDefinitions); + assemblyAttributes = FreezableHelper.FreezeListAndElements(assemblyAttributes); + moduleAttributes = FreezableHelper.FreezeListAndElements(moduleAttributes); + usingScopes = FreezableHelper.FreezeListAndElements(usingScopes); } public CSharpParsedFile(string fileName, UsingScope rootUsingScope) @@ -67,7 +66,7 @@ namespace ICSharpCode.NRefactory.CSharp public DateTime LastWriteTime { get { return lastWriteTime; } set { - CheckBeforeMutation(); + FreezableHelper.ThrowIfFrozen(this); lastWriteTime = value; } } @@ -85,19 +84,15 @@ namespace ICSharpCode.NRefactory.CSharp get { return usingScopes; } } - public IProjectContent ProjectContent { - get { return rootUsingScope.ProjectContent; } - } - - public IList TopLevelTypeDefinitions { + public IList TopLevelTypeDefinitions { get { return topLevelTypeDefinitions; } } - public IList AssemblyAttributes { + public IList AssemblyAttributes { get { return assemblyAttributes; } } - public IList ModuleAttributes { + public IList ModuleAttributes { get { return moduleAttributes; } } @@ -110,15 +105,15 @@ namespace ICSharpCode.NRefactory.CSharp return rootUsingScope; } - public ITypeDefinition GetTopLevelTypeDefinition(TextLocation location) + public IUnresolvedTypeDefinition GetTopLevelTypeDefinition(TextLocation location) { return FindEntity(topLevelTypeDefinitions, location); } - public ITypeDefinition GetInnermostTypeDefinition(TextLocation location) + public IUnresolvedTypeDefinition GetInnermostTypeDefinition(TextLocation location) { - ITypeDefinition parent = null; - ITypeDefinition type = GetTopLevelTypeDefinition(location); + IUnresolvedTypeDefinition parent = null; + IUnresolvedTypeDefinition type = GetTopLevelTypeDefinition(location); while (type != null) { parent = type; type = FindEntity(parent.NestedTypes, location); @@ -126,18 +121,15 @@ namespace ICSharpCode.NRefactory.CSharp return parent; } - public IMember GetMember(TextLocation location) + public IUnresolvedMember GetMember(TextLocation location) { - ITypeDefinition type = GetInnermostTypeDefinition(location); + IUnresolvedTypeDefinition type = GetInnermostTypeDefinition(location); if (type == null) return null; - return FindEntity(type.Methods, location) - ?? FindEntity(type.Fields, location) - ?? FindEntity(type.Properties, location) - ?? (IMember)FindEntity(type.Events, location); + return FindEntity(type.Members, location); } - static T FindEntity(IList list, TextLocation location) where T : class, IEntity + static T FindEntity(IList list, TextLocation location) where T : class, IUnresolvedEntity { // This could be improved using a binary search foreach (T entity in list) { diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ConstantValues.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/ConstantValues.cs similarity index 80% rename from ICSharpCode.NRefactory.CSharp/Resolver/ConstantValues.cs rename to ICSharpCode.NRefactory.CSharp/TypeSystem/ConstantValues.cs index c7d55970eb..2568d6c01a 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/ConstantValues.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/ConstantValues.cs @@ -19,127 +19,75 @@ using System; using System.Collections.Generic; using System.Linq; - using ICSharpCode.NRefactory.CSharp.Analysis; +using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.Utils; -namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues +namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues { // Contains representations for constant C# expressions. // We use these instead of storing the full AST to reduce the memory usage. [Serializable] - public sealed class CSharpConstantValue : Immutable, IConstantValue, ISupportsInterning + public abstract class ConstantExpression : IConstantValue { - ConstantExpression expression; - UsingScope parentUsingScope; - ITypeDefinition parentTypeDefinition; - - public CSharpConstantValue(ConstantExpression expression, UsingScope parentUsingScope, ITypeDefinition parentTypeDefinition) - { - if (expression == null) - throw new ArgumentNullException("expression"); - this.expression = expression; - this.parentUsingScope = parentUsingScope; - this.parentTypeDefinition = parentTypeDefinition; - } - - CSharpResolver CreateResolver(ITypeResolveContext context) - { - // Because constants are evaluated by the compiler, we need to evaluate them in the resolve context - // of the project where they are defined, not in that where the constant value is used. - // TODO: how do we get the correct resolve context? - return new CSharpResolver(context) { - CheckForOverflow = false, // TODO: get project-wide overflow setting - CurrentTypeDefinition = parentTypeDefinition, - CurrentUsingScope = parentUsingScope - }; - } + public abstract ResolveResult Resolve(CSharpResolver resolver); public ResolveResult Resolve(ITypeResolveContext context) { - CacheManager cache = context.CacheManager; - if (cache != null) { - ResolveResult cachedResult = cache.GetShared(this) as ResolveResult; - if (cachedResult != null) - return cachedResult; + if (context.CurrentAssembly is CSharpAssembly && context.CurrentAssembly != context.Compilation.MainAssembly) { + // The constant needs to be resolved in a different compilation. + throw new NotImplementedException(); + } else { + // Resolve in current context. + return Resolve(new CSharpResolver(context)); } - CSharpResolver resolver = CreateResolver(context); - ResolveResult rr = expression.Resolve(resolver); - // Retrieve the equivalent type in the new resolve context. - // E.g. if the constant is defined in a .NET 2.0 project, type might be Int32 from mscorlib 2.0. - // However, the calling project might be a .NET 4.0 project, so we need to return Int32 from mscorlib 4.0. - rr = MapToNewContext(rr, new MapTypeIntoNewContext(context)); - if (cache != null) - cache.SetShared(this, rr); - return rr; } - static ResolveResult MapToNewContext(ResolveResult rr, MapTypeIntoNewContext mapping) + static ResolveResult MapToNewContext(ResolveResult rr, ICompilation mainCompilation) { if (rr is TypeOfResolveResult) { return new TypeOfResolveResult( - rr.Type.AcceptVisitor(mapping), - ((TypeOfResolveResult)rr).ReferencedType.AcceptVisitor(mapping)); + rr.Type.ToTypeReference().Resolve(mainCompilation.TypeResolveContext), + ((TypeOfResolveResult)rr).ReferencedType.ToTypeReference().Resolve(mainCompilation.TypeResolveContext)); } else if (rr is ArrayCreateResolveResult) { ArrayCreateResolveResult acrr = (ArrayCreateResolveResult)rr; return new ArrayCreateResolveResult( - acrr.Type.AcceptVisitor(mapping), - MapToNewContext(acrr.SizeArguments, mapping), - MapToNewContext(acrr.InitializerElements, mapping)); + acrr.Type.ToTypeReference().Resolve(mainCompilation.TypeResolveContext), + MapToNewContext(acrr.SizeArguments, mainCompilation), + MapToNewContext(acrr.InitializerElements, mainCompilation)); } else if (rr.IsCompileTimeConstant) { return new ConstantResolveResult( - rr.Type.AcceptVisitor(mapping), + rr.Type.ToTypeReference().Resolve(mainCompilation.TypeResolveContext), rr.ConstantValue ); } else { - return new ErrorResolveResult(rr.Type.AcceptVisitor(mapping)); + return new ErrorResolveResult(rr.Type.ToTypeReference().Resolve(mainCompilation.TypeResolveContext)); } } - static ResolveResult[] MapToNewContext(ResolveResult[] input, MapTypeIntoNewContext mapping) + static ResolveResult[] MapToNewContext(ResolveResult[] input, ICompilation mainCompilation) { if (input == null) return null; ResolveResult[] output = new ResolveResult[input.Length]; for (int i = 0; i < input.Length; i++) { - output[i] = MapToNewContext(input[i], mapping); + output[i] = MapToNewContext(input[i], mainCompilation); } return output; } - - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - expression = provider.Intern(expression); - } - - int ISupportsInterning.GetHashCodeForInterning() - { - return expression.GetHashCode() - ^ (parentUsingScope != null ? parentUsingScope.GetHashCode() : 0) - ^ (parentTypeDefinition != null ? parentTypeDefinition.GetHashCode() : 0); - } - - bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) - { - CSharpConstantValue cv = other as CSharpConstantValue; - return cv != null - && expression == cv.expression - && parentUsingScope == cv.parentUsingScope - && parentTypeDefinition == cv.parentTypeDefinition; - } } /// /// Used for constants that could not be converted to IConstantValue. /// [Serializable] - public sealed class ErrorConstantValue : Immutable, IConstantValue + public sealed class ErrorConstantValue : IConstantValue { - ITypeReference type; + readonly ITypeReference type; public ErrorConstantValue(ITypeReference type) { @@ -158,7 +106,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues /// Increments an integer by a fixed amount without changing the type. /// [Serializable] - public sealed class IncrementConstantValue : Immutable, IConstantValue, ISupportsInterning + public sealed class IncrementConstantValue : IConstantValue, ISupportsInterning { IConstantValue baseValue; int incrementAmount; @@ -199,7 +147,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues int ISupportsInterning.GetHashCodeForInterning() { - return baseValue.GetHashCode() ^ incrementAmount; + unchecked { + return baseValue.GetHashCode() * 33 ^ incrementAmount; + } } bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) @@ -209,12 +159,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } - [Serializable] - public abstract class ConstantExpression - { - public abstract ResolveResult Resolve(CSharpResolver resolver); - } - /// /// C#'s equivalent to the SimpleConstantValue. /// @@ -242,10 +186,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues public override ResolveResult Resolve(CSharpResolver resolver) { - object val = value; - if (val is ITypeReference) - val = ((ITypeReference)val).Resolve(resolver.Context); - return new ConstantResolveResult(type.Resolve(resolver.Context), val); + return new ConstantResolveResult(type.Resolve(resolver.CurrentTypeResolveContext), value); } void ISupportsInterning.PrepareForInterning(IInterningProvider provider) @@ -284,7 +225,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues public override ResolveResult Resolve(CSharpResolver resolver) { - return resolver.ResolveCast(targetType.Resolve(resolver.Context), expression.Resolve(resolver)); + return resolver.ResolveCast(targetType.Resolve(resolver.CurrentTypeResolveContext), expression.Resolve(resolver)); } void ISupportsInterning.PrepareForInterning(IInterningProvider provider) @@ -324,18 +265,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues public override ResolveResult Resolve(CSharpResolver resolver) { - return resolver.ResolveSimpleName(identifier, ResolveTypes(resolver, typeArguments)); - } - - internal static IList ResolveTypes(CSharpResolver resolver, IList typeArguments) - { - if (typeArguments == null) - return EmptyList.Instance; - IType[] types = new IType[typeArguments.Count]; - for (int i = 0; i < types.Length; i++) { - types[i] = typeArguments[i].Resolve(resolver.Context); - } - return types; + return resolver.ResolveSimpleName(identifier, typeArguments.Resolve(resolver.CurrentTypeResolveContext)); } void ISupportsInterning.PrepareForInterning(IInterningProvider provider) @@ -396,10 +326,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues { ResolveResult rr; if (targetType != null) - rr = new TypeResolveResult(targetType.Resolve(resolver.Context)); + rr = new TypeResolveResult(targetType.Resolve(resolver.CurrentTypeResolveContext)); else rr = targetExpression.Resolve(resolver); - return resolver.ResolveMemberAccess(rr, memberName, ConstantIdentifierReference.ResolveTypes(resolver, typeArguments)); + return resolver.ResolveMemberAccess(rr, memberName, typeArguments.Resolve(resolver.CurrentTypeResolveContext)); } void ISupportsInterning.PrepareForInterning(IInterningProvider provider) @@ -492,7 +422,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues public override ResolveResult Resolve(CSharpResolver resolver) { - return resolver.ResolveDefaultValue(type.Resolve(resolver.Context)); + return resolver.ResolveDefaultValue(type.Resolve(resolver.CurrentTypeResolveContext)); } void ISupportsInterning.PrepareForInterning(IInterningProvider provider) @@ -677,7 +607,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues elements[i] = arrayElements[i].Resolve(resolver); } if (elementType != null) { - return resolver.ResolveArrayCreation(elementType.Resolve(resolver.Context), 1, null, elements); + return resolver.ResolveArrayCreation(elementType.Resolve(resolver.CurrentTypeResolveContext), 1, null, elements); } else { return resolver.ResolveArrayCreation(null, 1, null, elements); } diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/MemberTypeOrNamespaceReference.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/MemberTypeOrNamespaceReference.cs similarity index 59% rename from ICSharpCode.NRefactory.CSharp/Resolver/MemberTypeOrNamespaceReference.cs rename to ICSharpCode.NRefactory.CSharp/TypeSystem/MemberTypeOrNamespaceReference.cs index e702a131bd..e6e2b94074 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/MemberTypeOrNamespaceReference.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/MemberTypeOrNamespaceReference.cs @@ -19,26 +19,24 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; - +using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.Utils; -namespace ICSharpCode.NRefactory.CSharp.Resolver +namespace ICSharpCode.NRefactory.CSharp.TypeSystem { /// /// Reference to a qualified type or namespace name. /// [Serializable] - public sealed class MemberTypeOrNamespaceReference : ITypeOrNamespaceReference, ISupportsInterning + public sealed class MemberTypeOrNamespaceReference : TypeOrNamespaceReference, ISupportsInterning { - ITypeOrNamespaceReference target; - readonly ITypeDefinition parentTypeDefinition; - readonly UsingScope parentUsingScope; + TypeOrNamespaceReference target; string identifier; IList typeArguments; - public MemberTypeOrNamespaceReference(ITypeOrNamespaceReference target, string identifier, IList typeArguments, ITypeDefinition parentTypeDefinition, UsingScope parentUsingScope) + public MemberTypeOrNamespaceReference(TypeOrNamespaceReference target, string identifier, IList typeArguments) { if (target == null) throw new ArgumentNullException("target"); @@ -47,15 +45,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver this.target = target; this.identifier = identifier; this.typeArguments = typeArguments ?? EmptyList.Instance; - this.parentTypeDefinition = parentTypeDefinition; - this.parentUsingScope = parentUsingScope; } public string Identifier { get { return identifier; } } - public ITypeOrNamespaceReference Target { + public TypeOrNamespaceReference Target { get { return target; } } @@ -69,53 +65,23 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// public MemberTypeOrNamespaceReference AddSuffix(string suffix) { - return new MemberTypeOrNamespaceReference(target, identifier + suffix, typeArguments, parentTypeDefinition, parentUsingScope); + return new MemberTypeOrNamespaceReference(target, identifier + suffix, typeArguments); } - public ResolveResult DoResolve(ITypeResolveContext context) + public override ResolveResult Resolve(CSharpResolver resolver) { - CacheManager cacheManager = context.CacheManager; - if (cacheManager != null) { - ResolveResult cachedResult = cacheManager.GetShared(this) as ResolveResult;; - if (cachedResult != null) - return cachedResult; - } - - ResolveResult targetRR = target.DoResolve(context); + ResolveResult targetRR = target.Resolve(resolver); if (targetRR.IsError) return targetRR; - CSharpResolver r = new CSharpResolver(context); - r.CurrentTypeDefinition = parentTypeDefinition; - r.CurrentUsingScope = parentUsingScope; - IType[] typeArgs = new IType[typeArguments.Count]; - for (int i = 0; i < typeArgs.Length; i++) { - typeArgs[i] = typeArguments[i].Resolve(context); - } - ResolveResult rr; + IList typeArgs = typeArguments.Resolve(resolver.CurrentTypeResolveContext); using (var busyLock = BusyManager.Enter(this)) { if (busyLock.Success) { - rr = r.ResolveMemberType(targetRR, identifier, typeArgs); + return resolver.ResolveMemberType(targetRR, identifier, typeArgs); } else { // This can happen for "class Test : $Test.Base$ { public class Base {} }": return ErrorResolveResult.UnknownError; // don't cache this error } } - if (cacheManager != null) - cacheManager.SetShared(this, rr); - return rr; - } - - public NamespaceResolveResult ResolveNamespace(ITypeResolveContext context) - { - // TODO: use resolve context for original project, if possible - return DoResolve(context) as NamespaceResolveResult; - } - - public IType Resolve(ITypeResolveContext context) - { - // TODO: use resolve context for original project, if possible; then map the result type into the new context - TypeResolveResult rr = DoResolve(context) as TypeResolveResult; - return rr != null ? rr.Type : SharedTypes.UnknownType; } public override string ToString() @@ -138,10 +104,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver int hashCode = 0; unchecked { hashCode += 1000000007 * target.GetHashCode(); - if (parentTypeDefinition != null) - hashCode += 1000000009 * parentTypeDefinition.GetHashCode(); - if (parentUsingScope != null) - hashCode += 1000000021 * parentUsingScope.GetHashCode(); hashCode += 1000000033 * identifier.GetHashCode(); hashCode += 1000000087 * typeArguments.GetHashCode(); } @@ -151,9 +113,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { MemberTypeOrNamespaceReference o = other as MemberTypeOrNamespaceReference; - return o != null && this.target == o.target && this.parentTypeDefinition == o.parentTypeDefinition - && this.parentUsingScope == o.parentUsingScope && this.identifier == o.identifier - && this.typeArguments == o.typeArguments; + return o != null && this.target == o.target + && this.identifier == o.identifier && this.typeArguments == o.typeArguments; } } } diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/MethodTypeParameterWithInheritedConstraints.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/MethodTypeParameterWithInheritedConstraints.cs new file mode 100644 index 0000000000..b2492cb7fc --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/MethodTypeParameterWithInheritedConstraints.cs @@ -0,0 +1,121 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.CSharp.TypeSystem +{ + [Serializable] + public sealed class MethodTypeParameterWithInheritedConstraints : DefaultUnresolvedTypeParameter + { + public MethodTypeParameterWithInheritedConstraints(int index, string name) + : base(EntityType.Method, index, name) + { + } + + static ITypeParameter ResolveBaseTypeParameter(IMethod parentMethod, int index) + { + IMethod baseMethod = null; + if (parentMethod.IsOverride) { + foreach (IMethod m in InheritanceHelper.GetBaseMembers(parentMethod, false).OfType()) { + if (!m.IsOverride) { + baseMethod = m; + break; + } + } + } else if (parentMethod.IsExplicitInterfaceImplementation && parentMethod.InterfaceImplementations.Count == 1) { + baseMethod = parentMethod.InterfaceImplementations[0] as IMethod; + } + if (baseMethod != null && index < baseMethod.TypeParameters.Count) + return baseMethod.TypeParameters[index]; + else + return null; + } + + public override ITypeParameter CreateResolvedTypeParameter(ITypeResolveContext context) + { + if (context.CurrentMember is IMethod) { + return new ResolvedMethodTypeParameterWithInheritedConstraints(this, context); + } else { + return base.CreateResolvedTypeParameter(context); + } + } + + sealed class ResolvedMethodTypeParameterWithInheritedConstraints : AbstractResolvedTypeParameter + { + volatile ITypeParameter baseTypeParameter; + + public ResolvedMethodTypeParameterWithInheritedConstraints(MethodTypeParameterWithInheritedConstraints unresolved, ITypeResolveContext context) + : base(context.CurrentMember, unresolved.Index, unresolved.Name, unresolved.Variance, + unresolved.Attributes.CreateResolvedAttributes(context), unresolved.Region) + { + } + + ITypeParameter GetBaseTypeParameter() + { + ITypeParameter baseTP = this.baseTypeParameter; + if (baseTP == null) { + // ResolveBaseTypeParameter() is idempotent, so this is thread-safe. + this.baseTypeParameter = baseTP = ResolveBaseTypeParameter((IMethod)this.Owner, this.Index); + } + return baseTP; + } + + public override bool HasValueTypeConstraint { + get { + ITypeParameter baseTP = GetBaseTypeParameter(); + return baseTP != null ? baseTP.HasValueTypeConstraint : false; + } + } + + public override bool HasReferenceTypeConstraint { + get { + ITypeParameter baseTP = GetBaseTypeParameter(); + return baseTP != null ? baseTP.HasReferenceTypeConstraint : false; + } + } + + public override bool HasDefaultConstructorConstraint { + get { + ITypeParameter baseTP = GetBaseTypeParameter(); + return baseTP != null ? baseTP.HasDefaultConstructorConstraint : false; + } + } + + public override IEnumerable DirectBaseTypes { + get { + ITypeParameter baseTP = GetBaseTypeParameter(); + if (baseTP != null) { + // Substitute occurrences of the base method's type parameters in the constraints + // with the type parameters from the + IMethod owner = (IMethod)this.Owner; + var substitution = new TypeParameterSubstitution(null, new ProjectedList(owner.TypeParameters, t => t)); + return baseTP.DirectBaseTypes.Select(t => t.AcceptVisitor(substitution)); + } else { + return EmptyList.Instance; + } + } + } + } + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/SimpleTypeOrNamespaceReference.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/SimpleTypeOrNamespaceReference.cs similarity index 59% rename from ICSharpCode.NRefactory.CSharp/Resolver/SimpleTypeOrNamespaceReference.cs rename to ICSharpCode.NRefactory.CSharp/TypeSystem/SimpleTypeOrNamespaceReference.cs index 4a0bddf101..cf32e9cc10 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/SimpleTypeOrNamespaceReference.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/SimpleTypeOrNamespaceReference.cs @@ -20,32 +20,29 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.Utils; -namespace ICSharpCode.NRefactory.CSharp.Resolver +namespace ICSharpCode.NRefactory.CSharp.TypeSystem { /// /// Represents a simple C# name. (a single non-qualified identifier with an optional list of type arguments) /// [Serializable] - public sealed class SimpleTypeOrNamespaceReference : ITypeOrNamespaceReference, ISupportsInterning + public sealed class SimpleTypeOrNamespaceReference : TypeOrNamespaceReference, ISupportsInterning { - readonly ITypeDefinition parentTypeDefinition; - readonly UsingScope parentUsingScope; string identifier; IList typeArguments; readonly SimpleNameLookupMode lookupMode; - public SimpleTypeOrNamespaceReference(string identifier, IList typeArguments, ITypeDefinition parentTypeDefinition, UsingScope parentUsingScope, SimpleNameLookupMode lookupMode = SimpleNameLookupMode.Type) + public SimpleTypeOrNamespaceReference(string identifier, IList typeArguments, SimpleNameLookupMode lookupMode = SimpleNameLookupMode.Type) { if (identifier == null) throw new ArgumentNullException("identifier"); this.identifier = identifier; this.typeArguments = typeArguments ?? EmptyList.Instance; - this.parentTypeDefinition = parentTypeDefinition; - this.parentUsingScope = parentUsingScope; this.lookupMode = lookupMode; } @@ -63,42 +60,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// public SimpleTypeOrNamespaceReference AddSuffix(string suffix) { - return new SimpleTypeOrNamespaceReference(identifier + suffix, typeArguments, parentTypeDefinition, parentUsingScope, lookupMode); + return new SimpleTypeOrNamespaceReference(identifier + suffix, typeArguments, lookupMode); } - public ResolveResult DoResolve(ITypeResolveContext context) + public override ResolveResult Resolve(CSharpResolver resolver) { - CacheManager cacheManager = context.CacheManager; - if (cacheManager != null) { - ResolveResult cachedResult = cacheManager.GetShared(this) as ResolveResult; - if (cachedResult != null) - return cachedResult; - } - - CSharpResolver r = new CSharpResolver(context); - r.CurrentTypeDefinition = parentTypeDefinition; - r.CurrentUsingScope = parentUsingScope; - IType[] typeArgs = new IType[typeArguments.Count]; - for (int i = 0; i < typeArgs.Length; i++) { - typeArgs[i] = typeArguments[i].Resolve(context); - } - ResolveResult rr = r.LookupSimpleNameOrTypeName(identifier, typeArgs, lookupMode); - if (cacheManager != null) - cacheManager.SetShared(this, rr); - return rr; - } - - public NamespaceResolveResult ResolveNamespace(ITypeResolveContext context) - { - // TODO: use resolve context for original project, if possible - return DoResolve(context) as NamespaceResolveResult; - } - - public IType Resolve(ITypeResolveContext context) - { - // TODO: use resolve context for original project, if possible; then map the result type into the new context - TypeResolveResult rr = DoResolve(context) as TypeResolveResult; - return rr != null ? rr.Type : SharedTypes.UnknownType; + var typeArgs = typeArguments.Resolve(resolver.CurrentTypeResolveContext); + return resolver.LookupSimpleNameOrTypeName(identifier, typeArgs, lookupMode); } public override string ToString() @@ -119,11 +87,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { int hashCode = 0; unchecked { - if (parentTypeDefinition != null) - hashCode += 1000000007 * parentTypeDefinition.GetHashCode(); - if (parentUsingScope != null) - hashCode += 1000000009 * parentUsingScope.GetHashCode(); - hashCode += 1000000021 * identifier.GetHashCode(); hashCode += 1000000033 * typeArguments.GetHashCode(); hashCode += 1000000087 * (int)lookupMode; @@ -134,8 +97,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { SimpleTypeOrNamespaceReference o = other as SimpleTypeOrNamespaceReference; - return o != null && this.parentTypeDefinition == o.parentTypeDefinition - && this.parentUsingScope == o.parentUsingScope && this.identifier == o.identifier + return o != null && this.identifier == o.identifier && this.typeArguments == o.typeArguments && this.lookupMode == o.lookupMode; } } diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeOrNamespaceReference.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeOrNamespaceReference.cs new file mode 100644 index 0000000000..0c8e6b42a3 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeOrNamespaceReference.cs @@ -0,0 +1,61 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER 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.CSharp.Resolver; +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.TypeSystem +{ + /// + /// Represents a reference which could point to a type or namespace. + /// + [Serializable] + public abstract class TypeOrNamespaceReference : ITypeReference + { + /// + /// Resolves the reference and returns the ResolveResult. + /// + public abstract ResolveResult Resolve(CSharpResolver resolver); + + /// + /// Returns the namespace that is referenced; or null if no such namespace is found. + /// + public INamespace ResolveNamespace(CSharpResolver resolver) + { + NamespaceResolveResult nrr = Resolve(resolver) as NamespaceResolveResult; + return nrr != null ? nrr.Namespace : null; + } + + /// + /// Returns the type that is referenced; or if the type isn't found. + /// + public IType ResolveType(CSharpResolver resolver) + { + TypeResolveResult trr = Resolve(resolver) as TypeResolveResult; + return trr != null ? trr.Type : SpecialType.UnknownType; + } + + IType ITypeReference.Resolve(ITypeResolveContext context) + { + // TODO: use the correct compilation + return ResolveType(new CSharpResolver(context)); + } + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Parser/TypeSystemConvertVisitor.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs similarity index 72% rename from ICSharpCode.NRefactory.CSharp/Parser/TypeSystemConvertVisitor.cs rename to ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs index 1eac3f9091..34bf2a3a0a 100644 --- a/ICSharpCode.NRefactory.CSharp/Parser/TypeSystemConvertVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs @@ -22,22 +22,23 @@ using System.Diagnostics; using System.Linq; using ICSharpCode.NRefactory.CSharp.Analysis; using ICSharpCode.NRefactory.CSharp.Resolver; -using ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues; +using ICSharpCode.NRefactory.CSharp.TypeSystem; +using ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.Utils; -namespace ICSharpCode.NRefactory.CSharp +namespace ICSharpCode.NRefactory.CSharp.TypeSystem { /// /// Produces type and member definitions from the DOM. /// - public class TypeSystemConvertVisitor : DepthFirstAstVisitor + public class TypeSystemConvertVisitor : DepthFirstAstVisitor { readonly CSharpParsedFile parsedFile; UsingScope usingScope; - DefaultTypeDefinition currentTypeDefinition; - DefaultMethod currentMethod; + DefaultUnresolvedTypeDefinition currentTypeDefinition; + DefaultUnresolvedMethod currentMethod; IInterningProvider interningProvider = new SimpleInterningProvider(); @@ -53,15 +54,12 @@ namespace ICSharpCode.NRefactory.CSharp /// /// Creates a new TypeSystemConvertVisitor. /// - /// The parent project content (used as owner for the types being created). /// The file name (used for DomRegions). - public TypeSystemConvertVisitor(IProjectContent pc, string fileName) + public TypeSystemConvertVisitor(string fileName) { - if (pc == null) - throw new ArgumentNullException("pc"); if (fileName == null) throw new ArgumentNullException("fileName"); - this.parsedFile = new CSharpParsedFile(fileName, new UsingScope(pc)); + this.parsedFile = new CSharpParsedFile(fileName, new UsingScope()); this.usingScope = parsedFile.RootUsingScope; } @@ -71,7 +69,7 @@ namespace ICSharpCode.NRefactory.CSharp /// The parsed file to which members should be added. /// The current using scope. /// The current type definition. - public TypeSystemConvertVisitor(CSharpParsedFile parsedFile, UsingScope currentUsingScope = null, DefaultTypeDefinition currentTypeDefinition = null) + public TypeSystemConvertVisitor(CSharpParsedFile parsedFile, UsingScope currentUsingScope = null, DefaultUnresolvedTypeDefinition currentTypeDefinition = null) { if (parsedFile == null) throw new ArgumentNullException("parsedFile"); @@ -113,7 +111,7 @@ namespace ICSharpCode.NRefactory.CSharp } #region Compilation Unit - public override IEntity VisitCompilationUnit (CompilationUnit unit, object data) + public override IUnresolvedEntity VisitCompilationUnit (CompilationUnit unit, object data) { parsedFile.Errors = unit.Errors; return base.VisitCompilationUnit (unit, data); @@ -121,15 +119,15 @@ namespace ICSharpCode.NRefactory.CSharp #endregion #region Using Declarations - public override IEntity VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration, object data) + public override IUnresolvedEntity VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration, object data) { usingScope.ExternAliases.Add(externAliasDeclaration.Name); return null; } - public override IEntity VisitUsingDeclaration(UsingDeclaration usingDeclaration, object data) + public override IUnresolvedEntity VisitUsingDeclaration(UsingDeclaration usingDeclaration, object data) { - ITypeOrNamespaceReference u = ConvertType(usingDeclaration.Import, SimpleNameLookupMode.TypeInUsingDeclaration) as ITypeOrNamespaceReference; + TypeOrNamespaceReference u = ConvertType(usingDeclaration.Import, SimpleNameLookupMode.TypeInUsingDeclaration) as TypeOrNamespaceReference; if (u != null) { if (interningProvider != null) u = interningProvider.Intern(u); @@ -138,20 +136,20 @@ namespace ICSharpCode.NRefactory.CSharp return null; } - public override IEntity VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration, object data) + public override IUnresolvedEntity VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration, object data) { - ITypeOrNamespaceReference u = ConvertType(usingDeclaration.Import, SimpleNameLookupMode.TypeInUsingDeclaration) as ITypeOrNamespaceReference; + TypeOrNamespaceReference u = ConvertType(usingDeclaration.Import, SimpleNameLookupMode.TypeInUsingDeclaration) as TypeOrNamespaceReference; if (u != null) { if (interningProvider != null) u = interningProvider.Intern(u); - usingScope.UsingAliases.Add(new KeyValuePair(usingDeclaration.Alias, u)); + usingScope.UsingAliases.Add(new KeyValuePair(usingDeclaration.Alias, u)); } return null; } #endregion #region Namespace Declaration - public override IEntity VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) + public override IUnresolvedEntity VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) { DomRegion region = MakeRegion(namespaceDeclaration); UsingScope previousUsingScope = usingScope; @@ -167,27 +165,27 @@ namespace ICSharpCode.NRefactory.CSharp #endregion #region Type Definitions - DefaultTypeDefinition CreateTypeDefinition(string name) + DefaultUnresolvedTypeDefinition CreateTypeDefinition(string name) { - DefaultTypeDefinition newType; + DefaultUnresolvedTypeDefinition newType; if (currentTypeDefinition != null) { - newType = new DefaultTypeDefinition(currentTypeDefinition, name); + newType = new DefaultUnresolvedTypeDefinition(currentTypeDefinition, name); foreach (var typeParameter in currentTypeDefinition.TypeParameters) newType.TypeParameters.Add(typeParameter); currentTypeDefinition.NestedTypes.Add(newType); } else { - newType = new DefaultTypeDefinition(parsedFile, usingScope.NamespaceName, name); + newType = new DefaultUnresolvedTypeDefinition(usingScope.NamespaceName, name); parsedFile.TopLevelTypeDefinitions.Add(newType); } + newType.ParsedFile = parsedFile; return newType; } - public override IEntity VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) + public override IUnresolvedEntity VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) { var td = currentTypeDefinition = CreateTypeDefinition(typeDeclaration.Name); td.Region = MakeRegion(typeDeclaration); td.BodyRegion = MakeBraceRegion(typeDeclaration); - td.AddDefaultConstructorIfRequired = true; ApplyModifiers(td, typeDeclaration.Modifiers); switch (typeDeclaration.ClassType) { @@ -216,21 +214,19 @@ namespace ICSharpCode.NRefactory.CSharp member.AcceptVisitor(this, data); } - td.HasExtensionMethods = td.Methods.Any(m => m.IsExtensionMethod); - - currentTypeDefinition = (DefaultTypeDefinition)currentTypeDefinition.DeclaringTypeDefinition; + currentTypeDefinition = (DefaultUnresolvedTypeDefinition)currentTypeDefinition.DeclaringTypeDefinition; if (interningProvider != null) { td.ApplyInterningProvider(interningProvider); } return td; } - public override IEntity VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data) + public override IUnresolvedEntity VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data) { var td = currentTypeDefinition = CreateTypeDefinition(delegateDeclaration.Name); td.Kind = TypeKind.Delegate; td.Region = MakeRegion(delegateDeclaration); - td.BaseTypes.Add(multicastDelegateReference); + td.BaseTypes.Add(KnownTypeReference.MulticastDelegate); ApplyModifiers(td, delegateDeclaration.Modifiers); td.IsSealed = true; // delegates are implicitly sealed @@ -238,35 +234,40 @@ namespace ICSharpCode.NRefactory.CSharp ConvertTypeParameters(td.TypeParameters, delegateDeclaration.TypeParameters, delegateDeclaration.Constraints, EntityType.TypeDefinition); ITypeReference returnType = ConvertType(delegateDeclaration.ReturnType); - List parameters = new List(); + List parameters = new List(); ConvertParameters(parameters, delegateDeclaration.Parameters); AddDefaultMethodsToDelegate(td, returnType, parameters); foreach (AttributeSection section in delegateDeclaration.Attributes) { if (section.AttributeTarget == "return") { - ConvertAttributes(td.Methods.Single(m => m.Name == "Invoke").ReturnTypeAttributes, section); - ConvertAttributes(td.Methods.Single(m => m.Name == "EndInvoke").ReturnTypeAttributes, section); + List returnTypeAttributes = new List(); + ConvertAttributes(returnTypeAttributes, section); + IUnresolvedMethod invokeMethod = (IUnresolvedMethod)td.Members.Single(m => m.Name == "Invoke"); + IUnresolvedMethod endInvokeMethod = (IUnresolvedMethod)td.Members.Single(m => m.Name == "EndInvoke"); + foreach (IUnresolvedAttribute attr in returnTypeAttributes) { + invokeMethod.ReturnTypeAttributes.Add(attr); + endInvokeMethod.ReturnTypeAttributes.Add(attr); + } } else { ConvertAttributes(td.Attributes, section); } } - currentTypeDefinition = (DefaultTypeDefinition)currentTypeDefinition.DeclaringTypeDefinition; + currentTypeDefinition = (DefaultUnresolvedTypeDefinition)currentTypeDefinition.DeclaringTypeDefinition; if (interningProvider != null) { td.ApplyInterningProvider(interningProvider); } return td; } - static readonly ITypeReference multicastDelegateReference = typeof(MulticastDelegate).ToTypeReference(); - static readonly IParameter delegateObjectParameter = MakeParameter(KnownTypeReference.Object, "object"); - static readonly IParameter delegateIntPtrMethodParameter = MakeParameter(typeof(IntPtr).ToTypeReference(), "method"); - static readonly IParameter delegateAsyncCallbackParameter = MakeParameter(typeof(AsyncCallback).ToTypeReference(), "callback"); - static readonly IParameter delegateResultParameter = MakeParameter(typeof(IAsyncResult).ToTypeReference(), "result"); + static readonly IUnresolvedParameter delegateObjectParameter = MakeParameter(KnownTypeReference.Object, "object"); + static readonly IUnresolvedParameter delegateIntPtrMethodParameter = MakeParameter(KnownTypeReference.IntPtr, "method"); + static readonly IUnresolvedParameter delegateAsyncCallbackParameter = MakeParameter(typeof(AsyncCallback).ToTypeReference(), "callback"); + static readonly IUnresolvedParameter delegateResultParameter = MakeParameter(typeof(IAsyncResult).ToTypeReference(), "result"); - static IParameter MakeParameter(ITypeReference type, string name) + static IUnresolvedParameter MakeParameter(ITypeReference type, string name) { - DefaultParameter p = new DefaultParameter(type, name); + DefaultUnresolvedParameter p = new DefaultUnresolvedParameter(type, name); p.Freeze(); return p; } @@ -274,7 +275,7 @@ namespace ICSharpCode.NRefactory.CSharp /// /// Adds the 'Invoke', 'BeginInvoke', 'EndInvoke' methods, and a constructor, to the . /// - public static void AddDefaultMethodsToDelegate(DefaultTypeDefinition delegateType, ITypeReference returnType, IEnumerable parameters) + public static void AddDefaultMethodsToDelegate(DefaultUnresolvedTypeDefinition delegateType, ITypeReference returnType, IEnumerable parameters) { if (delegateType == null) throw new ArgumentNullException("delegateType"); @@ -283,18 +284,19 @@ namespace ICSharpCode.NRefactory.CSharp if (parameters == null) throw new ArgumentNullException("parameters"); - DomRegion region = new DomRegion(delegateType.Region.FileName, delegateType.Region.BeginLine, delegateType.Region.BeginColumn); + DomRegion region = delegateType.Region; + region = new DomRegion(region.FileName, region.BeginLine, region.BeginColumn); // remove end position - DefaultMethod invoke = new DefaultMethod(delegateType, "Invoke"); + DefaultUnresolvedMethod invoke = new DefaultUnresolvedMethod(delegateType, "Invoke"); invoke.Accessibility = Accessibility.Public; invoke.IsSynthetic = true; foreach (var p in parameters) invoke.Parameters.Add(p); invoke.ReturnType = returnType; invoke.Region = region; - delegateType.Methods.Add(invoke); + delegateType.Members.Add(invoke); - DefaultMethod beginInvoke = new DefaultMethod(delegateType, "BeginInvoke"); + DefaultUnresolvedMethod beginInvoke = new DefaultUnresolvedMethod(delegateType, "BeginInvoke"); beginInvoke.Accessibility = Accessibility.Public; beginInvoke.IsSynthetic = true; foreach (var p in parameters) @@ -303,17 +305,17 @@ namespace ICSharpCode.NRefactory.CSharp beginInvoke.Parameters.Add(delegateObjectParameter); beginInvoke.ReturnType = delegateResultParameter.Type; beginInvoke.Region = region; - delegateType.Methods.Add(beginInvoke); + delegateType.Members.Add(beginInvoke); - DefaultMethod endInvoke = new DefaultMethod(delegateType, "EndInvoke"); + DefaultUnresolvedMethod endInvoke = new DefaultUnresolvedMethod(delegateType, "EndInvoke"); endInvoke.Accessibility = Accessibility.Public; endInvoke.IsSynthetic = true; endInvoke.Parameters.Add(delegateResultParameter); endInvoke.ReturnType = invoke.ReturnType; endInvoke.Region = region; - delegateType.Methods.Add(endInvoke); + delegateType.Members.Add(endInvoke); - DefaultMethod ctor = new DefaultMethod(delegateType, ".ctor"); + DefaultUnresolvedMethod ctor = new DefaultUnresolvedMethod(delegateType, ".ctor"); ctor.EntityType = EntityType.Constructor; ctor.Accessibility = Accessibility.Public; ctor.IsSynthetic = true; @@ -321,18 +323,18 @@ namespace ICSharpCode.NRefactory.CSharp ctor.Parameters.Add(delegateIntPtrMethodParameter); ctor.ReturnType = delegateType; ctor.Region = region; - delegateType.Methods.Add(ctor); + delegateType.Members.Add(ctor); } #endregion #region Fields - public override IEntity VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) + public override IUnresolvedEntity VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) { bool isSingleField = fieldDeclaration.Variables.Count == 1; Modifiers modifiers = fieldDeclaration.Modifiers; - DefaultField field = null; + DefaultUnresolvedField field = null; foreach (VariableInitializer vi in fieldDeclaration.Variables) { - field = new DefaultField(currentTypeDefinition, vi.Name); + field = new DefaultUnresolvedField(currentTypeDefinition, vi.Name); field.Region = isSingleField ? MakeRegion(fieldDeclaration) : MakeRegion(vi); field.BodyRegion = MakeRegion(vi); @@ -348,7 +350,7 @@ namespace ICSharpCode.NRefactory.CSharp field.ConstantValue = ConvertConstantValue(field.ReturnType, vi.Initializer); } - currentTypeDefinition.Fields.Add(field); + currentTypeDefinition.Members.Add(field); if (interningProvider != null) { field.ApplyInterningProvider(interningProvider); } @@ -356,15 +358,15 @@ namespace ICSharpCode.NRefactory.CSharp return isSingleField ? field : null; } - public override IEntity VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration, object data) + public override IUnresolvedEntity VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration, object data) { // TODO: add support for fixed fields return base.VisitFixedFieldDeclaration(fixedFieldDeclaration, data); } - public override IEntity VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, object data) + public override IUnresolvedEntity VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, object data) { - DefaultField field = new DefaultField(currentTypeDefinition, enumMemberDeclaration.Name); + DefaultUnresolvedField field = new DefaultUnresolvedField(currentTypeDefinition, enumMemberDeclaration.Name); field.Region = field.BodyRegion = MakeRegion(enumMemberDeclaration); ConvertAttributes(field.Attributes, enumMemberDeclaration.Attributes); @@ -374,7 +376,7 @@ namespace ICSharpCode.NRefactory.CSharp if (!enumMemberDeclaration.Initializer.IsNull) { field.ConstantValue = ConvertConstantValue(currentTypeDefinition, enumMemberDeclaration.Initializer); } else { - IField prevField = currentTypeDefinition.Fields.LastOrDefault(); + DefaultUnresolvedField prevField = currentTypeDefinition.Members.LastOrDefault() as DefaultUnresolvedField; if (prevField == null || prevField.ConstantValue == null) { field.ConstantValue = ConvertConstantValue(currentTypeDefinition, new PrimitiveExpression(0)); } else { @@ -382,7 +384,7 @@ namespace ICSharpCode.NRefactory.CSharp } } - currentTypeDefinition.Fields.Add(field); + currentTypeDefinition.Members.Add(field); if (interningProvider != null) { field.ApplyInterningProvider(interningProvider); } @@ -391,9 +393,9 @@ namespace ICSharpCode.NRefactory.CSharp #endregion #region Methods - public override IEntity VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) + public override IUnresolvedEntity VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) { - DefaultMethod m = new DefaultMethod(currentTypeDefinition, methodDeclaration.Name); + DefaultUnresolvedMethod m = new DefaultUnresolvedMethod(currentTypeDefinition, methodDeclaration.Name); currentMethod = m; // required for resolving type parameters m.Region = MakeRegion(methodDeclaration); m.BodyRegion = MakeRegion(methodDeclaration.Body); @@ -401,7 +403,7 @@ namespace ICSharpCode.NRefactory.CSharp if (InheritsConstraints(methodDeclaration) && methodDeclaration.Constraints.Count == 0) { int index = 0; foreach (TypeParameterDeclaration tpDecl in methodDeclaration.TypeParameters) { - var tp = new TypeParameterWithInheritedConstraints(m, index++, tpDecl.Name); + var tp = new MethodTypeParameterWithInheritedConstraints(index++, tpDecl.Name); tp.Region = MakeRegion(tpDecl); ConvertAttributes(tp.Attributes, tpDecl.Attributes); tp.Variance = tpDecl.Variance; @@ -423,7 +425,7 @@ namespace ICSharpCode.NRefactory.CSharp m.InterfaceImplementations.Add(ConvertInterfaceImplementation(methodDeclaration.PrivateImplementationType, m.Name)); } - currentTypeDefinition.Methods.Add(m); + currentTypeDefinition.Members.Add(m); currentMethod = null; if (interningProvider != null) { m.ApplyInterningProvider(interningProvider); @@ -439,13 +441,14 @@ namespace ICSharpCode.NRefactory.CSharp return !methodDeclaration.PrivateImplementationType.IsNull; } - void ConvertTypeParameters(IList output, AstNodeCollection typeParameters, AstNodeCollection constraints, EntityType ownerType) + void ConvertTypeParameters(IList output, AstNodeCollection typeParameters, + AstNodeCollection constraints, EntityType ownerType) { // output might be non-empty when type parameters were copied from an outer class int index = output.Count; - List list = new List(); + List list = new List(); foreach (TypeParameterDeclaration tpDecl in typeParameters) { - DefaultTypeParameter tp = new DefaultTypeParameter(ownerType, index++, tpDecl.Name); + DefaultUnresolvedTypeParameter tp = new DefaultUnresolvedTypeParameter(ownerType, index++, tpDecl.Name); tp.Region = MakeRegion(tpDecl); ConvertAttributes(tp.Attributes, tpDecl.Attributes); tp.Variance = tpDecl.Variance; @@ -477,16 +480,17 @@ namespace ICSharpCode.NRefactory.CSharp } } - DefaultExplicitInterfaceImplementation ConvertInterfaceImplementation(AstType interfaceType, string memberName) + IMemberReference ConvertInterfaceImplementation(AstType interfaceType, string memberName) { - return new DefaultExplicitInterfaceImplementation(ConvertType(interfaceType), memberName); + throw new NotImplementedException(); + //return new DefaultExplicitInterfaceImplementation(ConvertType(interfaceType), memberName); } #endregion #region Operators - public override IEntity VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data) + public override IUnresolvedEntity VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data) { - DefaultMethod m = new DefaultMethod(currentTypeDefinition, operatorDeclaration.Name); + DefaultUnresolvedMethod m = new DefaultUnresolvedMethod(currentTypeDefinition, operatorDeclaration.Name); m.EntityType = EntityType.Operator; m.Region = MakeRegion(operatorDeclaration); m.BodyRegion = MakeRegion(operatorDeclaration.Body); @@ -499,7 +503,7 @@ namespace ICSharpCode.NRefactory.CSharp ConvertParameters(m.Parameters, operatorDeclaration.Parameters); - currentTypeDefinition.Methods.Add(m); + currentTypeDefinition.Members.Add(m); if (interningProvider != null) { m.ApplyInterningProvider(interningProvider); } @@ -508,11 +512,11 @@ namespace ICSharpCode.NRefactory.CSharp #endregion #region Constructors - public override IEntity VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) + public override IUnresolvedEntity VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) { Modifiers modifiers = constructorDeclaration.Modifiers; bool isStatic = (modifiers & Modifiers.Static) != 0; - DefaultMethod ctor = new DefaultMethod(currentTypeDefinition, isStatic ? ".cctor" : ".ctor"); + DefaultUnresolvedMethod ctor = new DefaultUnresolvedMethod(currentTypeDefinition, isStatic ? ".cctor" : ".ctor"); ctor.EntityType = EntityType.Constructor; ctor.Region = MakeRegion(constructorDeclaration); if (!constructorDeclaration.Initializer.IsNull) { @@ -530,7 +534,7 @@ namespace ICSharpCode.NRefactory.CSharp else ApplyModifiers(ctor, modifiers); - currentTypeDefinition.Methods.Add(ctor); + currentTypeDefinition.Members.Add(ctor); if (interningProvider != null) { ctor.ApplyInterningProvider(interningProvider); } @@ -539,9 +543,9 @@ namespace ICSharpCode.NRefactory.CSharp #endregion #region Destructors - public override IEntity VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration, object data) + public override IUnresolvedEntity VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration, object data) { - DefaultMethod dtor = new DefaultMethod(currentTypeDefinition, "Finalize"); + DefaultUnresolvedMethod dtor = new DefaultUnresolvedMethod(currentTypeDefinition, "Finalize"); dtor.EntityType = EntityType.Destructor; dtor.Region = MakeRegion(destructorDeclaration); dtor.BodyRegion = MakeRegion(destructorDeclaration.Body); @@ -551,7 +555,7 @@ namespace ICSharpCode.NRefactory.CSharp ConvertAttributes(dtor.Attributes, destructorDeclaration.Attributes); - currentTypeDefinition.Methods.Add(dtor); + currentTypeDefinition.Members.Add(dtor); if (interningProvider != null) { dtor.ApplyInterningProvider(interningProvider); } @@ -560,9 +564,9 @@ namespace ICSharpCode.NRefactory.CSharp #endregion #region Properties / Indexers - public override IEntity VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data) + public override IUnresolvedEntity VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data) { - DefaultProperty p = new DefaultProperty(currentTypeDefinition, propertyDeclaration.Name); + DefaultUnresolvedProperty p = new DefaultUnresolvedProperty(currentTypeDefinition, propertyDeclaration.Name); p.Region = MakeRegion(propertyDeclaration); p.BodyRegion = MakeBraceRegion(propertyDeclaration); ApplyModifiers(p, propertyDeclaration.Modifiers); @@ -574,16 +578,16 @@ namespace ICSharpCode.NRefactory.CSharp } p.Getter = ConvertAccessor(propertyDeclaration.Getter, p.Accessibility); p.Setter = ConvertAccessor(propertyDeclaration.Setter, p.Accessibility); - currentTypeDefinition.Properties.Add(p); + currentTypeDefinition.Members.Add(p); if (interningProvider != null) { p.ApplyInterningProvider(interningProvider); } return p; } - public override IEntity VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration, object data) + public override IUnresolvedEntity VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration, object data) { - DefaultProperty p = new DefaultProperty(currentTypeDefinition, "Item"); + DefaultUnresolvedProperty p = new DefaultUnresolvedProperty(currentTypeDefinition, "Item"); p.EntityType = EntityType.Indexer; p.Region = MakeRegion(indexerDeclaration); p.BodyRegion = MakeBraceRegion(indexerDeclaration); @@ -597,18 +601,18 @@ namespace ICSharpCode.NRefactory.CSharp p.Getter = ConvertAccessor(indexerDeclaration.Getter, p.Accessibility); p.Setter = ConvertAccessor(indexerDeclaration.Setter, p.Accessibility); ConvertParameters(p.Parameters, indexerDeclaration.Parameters); - currentTypeDefinition.Properties.Add(p); + currentTypeDefinition.Members.Add(p); if (interningProvider != null) { p.ApplyInterningProvider(interningProvider); } return p; } - IAccessor ConvertAccessor(Accessor accessor, Accessibility defaultAccessibility) + IUnresolvedAccessor ConvertAccessor(Accessor accessor, Accessibility defaultAccessibility) { if (accessor.IsNull) return null; - DefaultAccessor a = new DefaultAccessor(); + DefaultUnresolvedAccessor a = new DefaultUnresolvedAccessor(); a.Accessibility = GetAccessibility(accessor.Modifiers) ?? defaultAccessibility; a.Region = MakeRegion(accessor); foreach (AttributeSection section in accessor.Attributes) { @@ -623,13 +627,13 @@ namespace ICSharpCode.NRefactory.CSharp #endregion #region Events - public override IEntity VisitEventDeclaration(EventDeclaration eventDeclaration, object data) + public override IUnresolvedEntity VisitEventDeclaration(EventDeclaration eventDeclaration, object data) { bool isSingleEvent = eventDeclaration.Variables.Count == 1; Modifiers modifiers = eventDeclaration.Modifiers; - DefaultEvent ev = null; + DefaultUnresolvedEvent ev = null; foreach (VariableInitializer vi in eventDeclaration.Variables) { - ev = new DefaultEvent(currentTypeDefinition, vi.Name); + ev = new DefaultUnresolvedEvent(currentTypeDefinition, vi.Name); ev.Region = isSingleEvent ? MakeRegion(eventDeclaration) : MakeRegion(vi); ev.BodyRegion = MakeRegion(vi); @@ -639,10 +643,10 @@ namespace ICSharpCode.NRefactory.CSharp ev.ReturnType = ConvertType(eventDeclaration.ReturnType); if (eventDeclaration.Attributes.Any(a => a.AttributeTarget == "method")) { - ev.AddAccessor = ev.RemoveAccessor = new DefaultAccessor { Accessibility = ev.Accessibility }; + ev.AddAccessor = ev.RemoveAccessor = new DefaultUnresolvedAccessor { Accessibility = ev.Accessibility }; } else { // if there's no attributes on the accessors, we can re-use the shared accessor instance - ev.AddAccessor = ev.RemoveAccessor = DefaultAccessor.GetFromAccessibility(ev.Accessibility); + ev.AddAccessor = ev.RemoveAccessor = DefaultUnresolvedAccessor.GetFromAccessibility(ev.Accessibility); } foreach (AttributeSection section in eventDeclaration.Attributes) { if (section.AttributeTarget == "method") { @@ -653,7 +657,7 @@ namespace ICSharpCode.NRefactory.CSharp } } - currentTypeDefinition.Events.Add(ev); + currentTypeDefinition.Members.Add(ev); if (interningProvider != null) { ev.ApplyInterningProvider(interningProvider); } @@ -661,9 +665,9 @@ namespace ICSharpCode.NRefactory.CSharp return isSingleEvent ? ev : null; } - public override IEntity VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration, object data) + public override IUnresolvedEntity VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration, object data) { - DefaultEvent e = new DefaultEvent(currentTypeDefinition, eventDeclaration.Name); + DefaultUnresolvedEvent e = new DefaultUnresolvedEvent(currentTypeDefinition, eventDeclaration.Name); e.Region = MakeRegion(eventDeclaration); e.BodyRegion = MakeBraceRegion(eventDeclaration); ApplyModifiers(e, eventDeclaration.Modifiers); @@ -678,7 +682,7 @@ namespace ICSharpCode.NRefactory.CSharp e.AddAccessor = ConvertAccessor(eventDeclaration.AddAccessor, e.Accessibility); e.RemoveAccessor = ConvertAccessor(eventDeclaration.RemoveAccessor, e.Accessibility); - currentTypeDefinition.Events.Add(e); + currentTypeDefinition.Members.Add(e); if (interningProvider != null) { e.ApplyInterningProvider(interningProvider); } @@ -687,7 +691,7 @@ namespace ICSharpCode.NRefactory.CSharp #endregion #region Modifiers - static void ApplyModifiers(DefaultTypeDefinition td, Modifiers modifiers) + static void ApplyModifiers(DefaultUnresolvedTypeDefinition td, Modifiers modifiers) { td.Accessibility = GetAccessibility(modifiers) ?? (td.DeclaringTypeDefinition != null ? Accessibility.Private : Accessibility.Internal); td.IsAbstract = (modifiers & (Modifiers.Abstract | Modifiers.Static)) != 0; @@ -695,7 +699,7 @@ namespace ICSharpCode.NRefactory.CSharp td.IsShadowing = (modifiers & Modifiers.New) != 0; } - static void ApplyModifiers(TypeSystem.Implementation.AbstractMember m, Modifiers modifiers) + static void ApplyModifiers(AbstractUnresolvedMember m, Modifiers modifiers) { // members from interfaces are always Public+Abstract. if (m.DeclaringTypeDefinition.Kind == TypeKind.Interface) { @@ -732,7 +736,7 @@ namespace ICSharpCode.NRefactory.CSharp #endregion #region Attributes - public override IEntity VisitAttributeSection(AttributeSection attributeSection, object data) + public override IUnresolvedEntity VisitAttributeSection(AttributeSection attributeSection, object data) { // non-assembly attributes are handled by their parent entity if (attributeSection.AttributeTarget == "assembly") { @@ -743,23 +747,23 @@ namespace ICSharpCode.NRefactory.CSharp return null; } - void ConvertAttributes(IList outputList, IEnumerable attributes) + void ConvertAttributes(IList outputList, IEnumerable attributes) { foreach (AttributeSection section in attributes) { ConvertAttributes(outputList, section); } } - void ConvertAttributes(IList outputList, AttributeSection attributeSection) + void ConvertAttributes(IList outputList, AttributeSection attributeSection) { foreach (CSharp.Attribute attr in attributeSection.Attributes) { outputList.Add(ConvertAttribute(attr)); } } - internal static ITypeReference ConvertAttributeType(AstType type, ITypeDefinition parentTypeDefinition, IMethod parentMethodDefinition, UsingScope parentUsingScope) + internal static ITypeReference ConvertAttributeType(AstType type) { - ITypeReference tr = ConvertType(type, parentTypeDefinition, parentMethodDefinition, parentUsingScope, SimpleNameLookupMode.Type); + ITypeReference tr = ConvertType(type, SimpleNameLookupMode.Type); if (!type.GetChildByRole(AstNode.Roles.Identifier).IsVerbatim) { // Try to add "Attribute" suffix, but only if the identifier // (=last identifier in fully qualified name) isn't a verbatim identifier. @@ -773,10 +777,10 @@ namespace ICSharpCode.NRefactory.CSharp return tr; } - IAttribute ConvertAttribute(CSharp.Attribute attr) + CSharpAttribute ConvertAttribute(CSharp.Attribute attr) { DomRegion region = MakeRegion(attr); - ITypeReference type = ConvertAttributeType(attr.Type, currentTypeDefinition, currentMethod, usingScope); + ITypeReference type = ConvertAttributeType(attr.Type); List positionalArguments = null; List> namedCtorArguments = null; List> namedArguments = null; @@ -805,110 +809,111 @@ namespace ICSharpCode.NRefactory.CSharp #endregion #region Types - ITypeReference ConvertType(AstType type, SimpleNameLookupMode lookupMode = SimpleNameLookupMode.Type) - { - return ConvertType(type, currentTypeDefinition, currentMethod, usingScope, lookupMode); - } - - internal static ITypeReference ConvertType(AstType type, ITypeDefinition parentTypeDefinition, IMethod parentMethodDefinition, UsingScope parentUsingScope, SimpleNameLookupMode lookupMode) + public static ITypeReference ConvertType(AstType type, SimpleNameLookupMode lookupMode = SimpleNameLookupMode.Type) { SimpleType s = type as SimpleType; if (s != null) { List typeArguments = new List(); foreach (var ta in s.TypeArguments) { - typeArguments.Add(ConvertType(ta, parentTypeDefinition, parentMethodDefinition, parentUsingScope, lookupMode)); - } - if (typeArguments.Count == 0 && parentMethodDefinition != null) { - // SimpleTypeOrNamespaceReference doesn't have a 'current method' context - // so we have to handle method type parameters here. - foreach (ITypeParameter tp in parentMethodDefinition.TypeParameters) { - if (tp.Name == s.Identifier) - return tp; - } + typeArguments.Add(ConvertType(ta, lookupMode)); } if (typeArguments.Count == 0 && string.IsNullOrEmpty(s.Identifier)) { // empty SimpleType is used for typeof(List<>). - return SharedTypes.UnboundTypeArgument; + return SpecialType.UnboundTypeArgument; } - return new SimpleTypeOrNamespaceReference(s.Identifier, typeArguments, parentTypeDefinition, parentUsingScope, lookupMode); + return new SimpleTypeOrNamespaceReference(s.Identifier, typeArguments, lookupMode); } PrimitiveType p = type as PrimitiveType; if (p != null) { - switch (p.Keyword) { - case "string": - return KnownTypeReference.String; - case "int": - return KnownTypeReference.Int32; - case "uint": - return KnownTypeReference.UInt32; - case "object": - return KnownTypeReference.Object; - case "bool": - return KnownTypeReference.Boolean; - case "sbyte": - return KnownTypeReference.SByte; - case "byte": - return KnownTypeReference.Byte; - case "short": - return KnownTypeReference.Int16; - case "ushort": - return KnownTypeReference.UInt16; - case "long": - return KnownTypeReference.Int64; - case "ulong": - return KnownTypeReference.UInt64; - case "float": - return KnownTypeReference.Single; - case "double": - return KnownTypeReference.Double; - case "decimal": - return KnownTypeReference.Decimal; - case "char": - return KnownTypeReference.Char; - case "void": - return KnownTypeReference.Void; - default: - return SharedTypes.UnknownType; - } + return ConvertPrimitiveType(p.Keyword); } MemberType m = type as MemberType; if (m != null) { - ITypeOrNamespaceReference t; + TypeOrNamespaceReference t; if (m.IsDoubleColon) { SimpleType st = m.Target as SimpleType; if (st != null) { - t = new AliasNamespaceReference(st.Identifier, parentUsingScope); + t = new AliasNamespaceReference(st.Identifier); } else { t = null; } } else { - t = ConvertType(m.Target, parentTypeDefinition, parentMethodDefinition, parentUsingScope, lookupMode) as ITypeOrNamespaceReference; + t = ConvertType(m.Target, lookupMode) as TypeOrNamespaceReference; } if (t == null) - return SharedTypes.UnknownType; + return SpecialType.UnknownType; List typeArguments = new List(); foreach (var ta in m.TypeArguments) { - typeArguments.Add(ConvertType(ta, parentTypeDefinition, parentMethodDefinition, parentUsingScope, lookupMode)); + typeArguments.Add(ConvertType(ta, lookupMode)); } - return new MemberTypeOrNamespaceReference(t, m.MemberName, typeArguments, parentTypeDefinition, parentUsingScope); + return new MemberTypeOrNamespaceReference(t, m.MemberName, typeArguments); } ComposedType c = type as ComposedType; if (c != null) { - ITypeReference t = ConvertType(c.BaseType, parentTypeDefinition, parentMethodDefinition, parentUsingScope, lookupMode); + ITypeReference t = ConvertType(c.BaseType, lookupMode); if (c.HasNullableSpecifier) { t = NullableType.Create(t); } for (int i = 0; i < c.PointerRank; i++) { - t = PointerTypeReference.Create(t); + t = new PointerTypeReference(t); } foreach (var a in c.ArraySpecifiers.Reverse()) { - t = ArrayTypeReference.Create(t, a.Dimensions); + t = new ArrayTypeReference(t, a.Dimensions); } return t; } Debug.WriteLine("Unknown node used as type: " + type); - return SharedTypes.UnknownType; + return SpecialType.UnknownType; + } + + public static ITypeReference ConvertPrimitiveType(string keyword) + { + KnownTypeCode typeCode = GetTypeCodeForPrimitiveType(keyword); + if (typeCode == KnownTypeCode.None) + return SpecialType.UnknownType; + else + return KnownTypeReference.Get(typeCode); + } + + public static KnownTypeCode GetTypeCodeForPrimitiveType(string keyword) + { + switch (keyword) { + case "string": + return KnownTypeCode.String; + case "int": + return KnownTypeCode.Int32; + case "uint": + return KnownTypeCode.UInt32; + case "object": + return KnownTypeCode.Object; + case "bool": + return KnownTypeCode.Boolean; + case "sbyte": + return KnownTypeCode.SByte; + case "byte": + return KnownTypeCode.Byte; + case "short": + return KnownTypeCode.Int16; + case "ushort": + return KnownTypeCode.UInt16; + case "long": + return KnownTypeCode.Int64; + case "ulong": + return KnownTypeCode.UInt64; + case "float": + return KnownTypeCode.Single; + case "double": + return KnownTypeCode.Double; + case "decimal": + return KnownTypeCode.Decimal; + case "char": + return KnownTypeCode.Char; + case "void": + return KnownTypeCode.Void; + default: + return KnownTypeCode.None; + } } #endregion @@ -918,10 +923,11 @@ namespace ICSharpCode.NRefactory.CSharp return ConvertConstantValue(targetType, expression, currentTypeDefinition, currentMethod, usingScope); } - internal static IConstantValue ConvertConstantValue(ITypeReference targetType, AstNode expression, - ITypeDefinition parentTypeDefinition, IMethod parentMethodDefinition, UsingScope parentUsingScope) + internal static IConstantValue ConvertConstantValue( + ITypeReference targetType, AstNode expression, + IUnresolvedTypeDefinition parentTypeDefinition, IUnresolvedMethod parentMethodDefinition, UsingScope parentUsingScope) { - ConstantValueBuilder b = new ConstantValueBuilder(parentTypeDefinition, parentMethodDefinition, parentUsingScope, false); + ConstantValueBuilder b = new ConstantValueBuilder(false); ConstantExpression c = expression.AcceptVisitor(b, null); if (c == null) return new ErrorConstantValue(targetType); @@ -931,44 +937,24 @@ namespace ICSharpCode.NRefactory.CSharp return new SimpleConstantValue(targetType, pc.Value); } // cast to the desired type - return new CSharpConstantValue(new ConstantCast(targetType, c), parentUsingScope, parentTypeDefinition); + return new ConstantCast(targetType, c); } IConstantValue ConvertAttributeArgument(Expression expression) { - ConstantValueBuilder b = new ConstantValueBuilder(currentTypeDefinition, currentMethod, usingScope, true); - ConstantExpression c = expression.AcceptVisitor(b, null); - if (c == null) - return null; - PrimitiveConstantExpression pc = c as PrimitiveConstantExpression; - if (pc != null) { - // Save memory by directly using a SimpleConstantValue. - return new SimpleConstantValue(pc.Type, pc.Value); - } else { - return new CSharpConstantValue(c, usingScope, currentTypeDefinition); - } + ConstantValueBuilder b = new ConstantValueBuilder(true); + return expression.AcceptVisitor(b, null); } sealed class ConstantValueBuilder : DepthFirstAstVisitor { - readonly ITypeDefinition currentTypeDefinition; - readonly IMethod currentMethod; - readonly UsingScope usingScope; readonly bool isAttributeArgument; - public ConstantValueBuilder(ITypeDefinition currentTypeDefinition, IMethod currentMethod, UsingScope usingScope, bool isAttributeArgument) + public ConstantValueBuilder(bool isAttributeArgument) { - this.currentTypeDefinition = currentTypeDefinition; - this.currentMethod = currentMethod; - this.usingScope = usingScope; this.isAttributeArgument = isAttributeArgument; } - ITypeReference ConvertType(AstType type) - { - return TypeSystemConvertVisitor.ConvertType(type, currentTypeDefinition, currentMethod, usingScope, SimpleNameLookupMode.Type); - } - protected override ConstantExpression VisitChildren(AstNode node, object data) { return null; @@ -1102,7 +1088,7 @@ namespace ICSharpCode.NRefactory.CSharp } else { type = ConvertType(arrayCreateExpression.Type); foreach (var spec in arrayCreateExpression.AdditionalArraySpecifiers.Reverse()) { - type = ArrayTypeReference.Create(type, spec.Dimensions); + type = new ArrayTypeReference(type, spec.Dimensions); } } ConstantExpression[] elements = new ConstantExpression[initializer.Elements.Count]; @@ -1122,20 +1108,20 @@ namespace ICSharpCode.NRefactory.CSharp #endregion #region Parameters - void ConvertParameters(IList outputList, IEnumerable parameters) + void ConvertParameters(IList outputList, IEnumerable parameters) { foreach (ParameterDeclaration pd in parameters) { - DefaultParameter p = new DefaultParameter(ConvertType(pd.Type), pd.Name); + DefaultUnresolvedParameter p = new DefaultUnresolvedParameter(ConvertType(pd.Type), pd.Name); p.Region = MakeRegion(pd); ConvertAttributes(p.Attributes, pd.Attributes); switch (pd.ParameterModifier) { case ParameterModifier.Ref: p.IsRef = true; - p.Type = ByReferenceTypeReference.Create(p.Type); + p.Type = new ByReferenceTypeReference(p.Type); break; case ParameterModifier.Out: p.IsOut = true; - p.Type = ByReferenceTypeReference.Create(p.Type); + p.Type = new ByReferenceTypeReference(p.Type); break; case ParameterModifier.Params: p.IsParams = true; diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/UsingScope.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/UsingScope.cs similarity index 72% rename from ICSharpCode.NRefactory.CSharp/Resolver/UsingScope.cs rename to ICSharpCode.NRefactory.CSharp/TypeSystem/UsingScope.cs index 7a933459d0..5b61f4e5dc 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/UsingScope.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/UsingScope.cs @@ -19,10 +19,11 @@ using System; using System.Collections.Generic; using System.Linq; +using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; -namespace ICSharpCode.NRefactory.CSharp.Resolver +namespace ICSharpCode.NRefactory.CSharp.TypeSystem { /// /// Represents a scope that contains "using" statements. @@ -31,33 +32,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [Serializable] public class UsingScope : AbstractFreezable { - readonly IProjectContent projectContent; readonly UsingScope parent; DomRegion region; string namespaceName = ""; - IList usings; - IList> usingAliases; + IList usings; + IList> usingAliases; IList externAliases; - //IList childScopes; protected override void FreezeInternal() { - if (usings == null || usings.Count == 0) - usings = EmptyList.Instance; - else - usings = Array.AsReadOnly(usings.ToArray()); - - if (usingAliases == null || usingAliases.Count == 0) - usingAliases = EmptyList>.Instance; - else - usingAliases = Array.AsReadOnly(usingAliases.ToArray()); - - externAliases = FreezeList(externAliases); - //childScopes = FreezeList(childScopes); + usings = FreezableHelper.FreezeList(usings); + usingAliases = FreezableHelper.FreezeList(usingAliases); + externAliases = FreezableHelper.FreezeList(externAliases); // In current model (no child scopes), it makes sense to freeze the parent as well // to ensure the whole lookup chain is immutable. - // But we probably shouldn't do this if we add back childScopes. if (parent != null) parent.Freeze(); @@ -67,11 +56,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// /// Creates a new root using scope. /// - public UsingScope(IProjectContent projectContent) + public UsingScope() { - if (projectContent == null) - throw new ArgumentNullException("projectContent"); - this.projectContent = projectContent; } /// @@ -86,7 +72,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (namespaceName == null) throw new ArgumentNullException("namespaceName"); this.parent = parent; - this.projectContent = parent.projectContent; this.namespaceName = namespaceName; } @@ -94,14 +79,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver get { return parent; } } - public IProjectContent ProjectContent { - get { return projectContent; } - } - public DomRegion Region { get { return region; } set { - CheckBeforeMutation(); + FreezableHelper.ThrowIfFrozen(this); region = value; } } @@ -111,23 +92,23 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver set { if (value == null) throw new ArgumentNullException("NamespaceName"); - CheckBeforeMutation(); + FreezableHelper.ThrowIfFrozen(this); namespaceName = value; } } - public IList Usings { + public IList Usings { get { if (usings == null) - usings = new List(); + usings = new List(); return usings; } } - public IList> UsingAliases { + public IList> UsingAliases { get { if (usingAliases == null) - usingAliases = new List>(); + usingAliases = new List>(); return usingAliases; } } @@ -162,5 +143,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } return externAliases != null && externAliases.Contains(identifier); } + + /// + /// Resolves the namespace represented by this using scope. + /// + public INamespace ResolveNamespace(ICompilation compilation) + { + throw new NotImplementedException(); + } } } diff --git a/ICSharpCode.NRefactory.Demo/CSDemo.cs b/ICSharpCode.NRefactory.Demo/CSDemo.cs index 82dd465598..08a1d720af 100644 --- a/ICSharpCode.NRefactory.Demo/CSDemo.cs +++ b/ICSharpCode.NRefactory.Demo/CSDemo.cs @@ -172,7 +172,7 @@ namespace ICSharpCode.NRefactory.Demo } } - Lazy> builtInLibs = new Lazy>( + Lazy> builtInLibs = new Lazy>( delegate { Assembly[] assemblies = { typeof(object).Assembly, // mscorlib @@ -183,7 +183,7 @@ namespace ICSharpCode.NRefactory.Demo // typeof(Form).Assembly, // System.Windows.Forms.dll typeof(ICSharpCode.NRefactory.TypeSystem.IProjectContent).Assembly, }; - IProjectContent[] projectContents = new IProjectContent[assemblies.Length]; + IUnresolvedAssembly[] projectContents = new IUnresolvedAssembly[assemblies.Length]; Stopwatch total = Stopwatch.StartNew(); Parallel.For( 0, assemblies.Length, @@ -199,27 +199,23 @@ namespace ICSharpCode.NRefactory.Demo void ResolveButtonClick(object sender, EventArgs e) { - SimpleProjectContent project = new SimpleProjectContent(); - var parsedFile = new TypeSystemConvertVisitor(project, "dummy.cs").Convert(compilationUnit); - project.UpdateProjectContent(null, parsedFile); + IProjectContent project = new CSharpProjectContent(); + var parsedFile = compilationUnit.ToTypeSystem("dummy.cs"); + project = project.UpdateProjectContent(null, parsedFile); + project = project.AddAssemblyReferences(builtInLibs.Value); - List projects = new List(); - projects.Add(project); - projects.AddRange(builtInLibs.Value); + ICompilation compilation = project.CreateCompilation(); + CSharpResolver resolver = new CSharpResolver(compilation); - using (var context = new CompositeTypeResolveContext(projects).Synchronize()) { - CSharpResolver resolver = new CSharpResolver(context); - - IResolveVisitorNavigator navigator = null; - if (csharpTreeView.SelectedNode != null) { - navigator = new NodeListResolveVisitorNavigator(new[] { (AstNode)csharpTreeView.SelectedNode.Tag }); - } - ResolveVisitor visitor = new ResolveVisitor(resolver, parsedFile, navigator); - visitor.Scan(compilationUnit); - csharpTreeView.BeginUpdate(); - ShowResolveResultsInTree(csharpTreeView.Nodes, visitor); - csharpTreeView.EndUpdate(); + IResolveVisitorNavigator navigator = null; + if (csharpTreeView.SelectedNode != null) { + navigator = new NodeListResolveVisitorNavigator(new[] { (AstNode)csharpTreeView.SelectedNode.Tag }); } + ResolveVisitor visitor = new ResolveVisitor(resolver, parsedFile, navigator); + visitor.Scan(compilationUnit); + csharpTreeView.BeginUpdate(); + ShowResolveResultsInTree(csharpTreeView.Nodes, visitor); + csharpTreeView.EndUpdate(); } void ShowResolveResultsInTree(TreeNodeCollection c, ResolveVisitor v) @@ -256,49 +252,45 @@ namespace ICSharpCode.NRefactory.Demo if (csharpTreeView.SelectedNode == null) return; - SimpleProjectContent project = new SimpleProjectContent(); - var parsedFile = new TypeSystemConvertVisitor(project, "dummy.cs").Convert(compilationUnit); - project.UpdateProjectContent(null, parsedFile); + IProjectContent project = new CSharpProjectContent(); + var parsedFile = compilationUnit.ToTypeSystem("dummy.cs"); + project = project.UpdateProjectContent(null, parsedFile); + project = project.AddAssemblyReferences(builtInLibs.Value); - List projects = new List(); - projects.Add(project); - projects.AddRange(builtInLibs.Value); + ICompilation compilation = project.CreateCompilation(); + CSharpResolver resolver = new CSharpResolver(compilation); - using (var context = new CompositeTypeResolveContext(projects).Synchronize()) { - CSharpResolver resolver = new CSharpResolver(context); - - AstNode node = (AstNode)csharpTreeView.SelectedNode.Tag; - IResolveVisitorNavigator navigator = new NodeListResolveVisitorNavigator(new[] { node }); - ResolveVisitor visitor = new ResolveVisitor(resolver, parsedFile, navigator); - visitor.Scan(compilationUnit); - IEntity entity; - MemberResolveResult mrr = visitor.GetResolveResult(node) as MemberResolveResult; - TypeResolveResult trr = visitor.GetResolveResult(node) as TypeResolveResult; - if (mrr != null) { - entity = mrr.Member; - } else if (trr != null) { - entity = trr.Type.GetDefinition(); - } else { - return; - } - - FindReferences fr = new FindReferences(); - int referenceCount = 0; - FoundReferenceCallback callback = delegate(AstNode matchNode, ResolveResult result) { - referenceCount++; - }; - - var searchScopes = fr.GetSearchScopes(entity); - navigator = new CompositeResolveVisitorNavigator(searchScopes.Select(s => s.GetNavigator(callback)).ToArray()); - visitor = new ResolveVisitor(resolver, parsedFile, navigator); - visitor.Scan(compilationUnit); - - csharpTreeView.BeginUpdate(); - ShowResolveResultsInTree(csharpTreeView.Nodes, visitor); - csharpTreeView.EndUpdate(); - - MessageBox.Show("Found " + referenceCount + " references to " + entity.FullName); + AstNode node = (AstNode)csharpTreeView.SelectedNode.Tag; + IResolveVisitorNavigator navigator = new NodeListResolveVisitorNavigator(new[] { node }); + ResolveVisitor visitor = new ResolveVisitor(resolver, parsedFile, navigator); + visitor.Scan(compilationUnit); + IEntity entity; + MemberResolveResult mrr = visitor.GetResolveResult(node) as MemberResolveResult; + TypeResolveResult trr = visitor.GetResolveResult(node) as TypeResolveResult; + if (mrr != null) { + entity = mrr.Member; + } else if (trr != null) { + entity = trr.Type.GetDefinition(); + } else { + return; } + + FindReferences fr = new FindReferences(); + int referenceCount = 0; + FoundReferenceCallback callback = delegate(AstNode matchNode, ResolveResult result) { + referenceCount++; + }; + + var searchScopes = fr.GetSearchScopes(entity); + navigator = new CompositeResolveVisitorNavigator(searchScopes.Select(s => s.GetNavigator(callback)).ToArray()); + visitor = new ResolveVisitor(resolver, parsedFile, navigator); + visitor.Scan(compilationUnit); + + csharpTreeView.BeginUpdate(); + ShowResolveResultsInTree(csharpTreeView.Nodes, visitor); + csharpTreeView.EndUpdate(); + + MessageBox.Show("Found " + referenceCount + " references to " + entity.FullName); } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CSharpAmbienceTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CSharpAmbienceTests.cs index fe7b6a7786..1eab74f2d5 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CSharpAmbienceTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CSharpAmbienceTests.cs @@ -28,9 +28,9 @@ namespace ICSharpCode.NRefactory.CSharp [TestFixture] public class CSharpAmbienceTests { - IProjectContent mscorlib; - IProjectContent myLib; - CompositeTypeResolveContext compositeContext; + IUnresolvedAssembly mscorlib; + IUnresolvedAssembly myLib; + ICompilation compilation; CSharpAmbience ambience; public CSharpAmbienceTests() @@ -40,16 +40,16 @@ namespace ICSharpCode.NRefactory.CSharp var loader = new CecilLoader(); loader.IncludeInternalMembers = true; myLib = loader.LoadAssemblyFile(typeof(CSharpAmbienceTests).Assembly.Location); - compositeContext = new CompositeTypeResolveContext(new[] { mscorlib, myLib }); + compilation = new SimpleCompilation(myLib, mscorlib); } #region ITypeDefinition tests [Test] public void GenericType() { - var typeDef = mscorlib.GetTypeDefinition(typeof(Dictionary<,>)); + var typeDef = compilation.FindType(typeof(Dictionary<,>)).GetDefinition(); ambience.ConversionFlags = ConversionFlags.UseFullyQualifiedMemberNames | ConversionFlags.ShowTypeParameterList; - string result = ambience.ConvertEntity(typeDef, mscorlib); + string result = ambience.ConvertEntity(typeDef); Assert.AreEqual("System.Collections.Generic.Dictionary", result); } @@ -57,9 +57,9 @@ namespace ICSharpCode.NRefactory.CSharp [Test] public void GenericTypeShortName() { - var typeDef = mscorlib.GetTypeDefinition(typeof(Dictionary<,>)); + var typeDef = compilation.FindType(typeof(Dictionary<,>)).GetDefinition(); ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList; - string result = ambience.ConvertEntity(typeDef, mscorlib); + string result = ambience.ConvertEntity(typeDef); Assert.AreEqual("Dictionary", result); } @@ -67,9 +67,9 @@ namespace ICSharpCode.NRefactory.CSharp [Test] public void SimpleType() { - var typeDef = mscorlib.GetTypeDefinition(typeof(Object)); + var typeDef = compilation.FindType(typeof(Object)).GetDefinition(); ambience.ConversionFlags = ConversionFlags.UseFullyQualifiedMemberNames | ConversionFlags.ShowTypeParameterList; - string result = ambience.ConvertEntity(typeDef, mscorlib); + string result = ambience.ConvertEntity(typeDef); Assert.AreEqual("System.Object", result); } @@ -77,9 +77,9 @@ namespace ICSharpCode.NRefactory.CSharp [Test] public void SimpleTypeDefinition() { - var typeDef = mscorlib.GetTypeDefinition(typeof(Object)); + var typeDef = compilation.FindType(typeof(Object)).GetDefinition(); ambience.ConversionFlags = ConversionFlags.All & ~(ConversionFlags.UseFullyQualifiedMemberNames); - string result = ambience.ConvertEntity(typeDef, mscorlib); + string result = ambience.ConvertEntity(typeDef); Assert.AreEqual("public class Object", result); } @@ -87,9 +87,9 @@ namespace ICSharpCode.NRefactory.CSharp [Test] public void SimpleTypeDefinitionWithoutModifiers() { - var typeDef = mscorlib.GetTypeDefinition(typeof(Object)); + var typeDef = compilation.FindType(typeof(Object)).GetDefinition(); ambience.ConversionFlags = ConversionFlags.All & ~(ConversionFlags.UseFullyQualifiedMemberNames | ConversionFlags.ShowModifiers | ConversionFlags.ShowAccessibility); - string result = ambience.ConvertEntity(typeDef, mscorlib); + string result = ambience.ConvertEntity(typeDef); Assert.AreEqual("class Object", result); } @@ -97,9 +97,9 @@ namespace ICSharpCode.NRefactory.CSharp [Test] public void GenericTypeDefinitionFull() { - var typeDef = mscorlib.GetTypeDefinition(typeof(List<>)); + var typeDef = compilation.FindType(typeof(List<>)).GetDefinition(); ambience.ConversionFlags = ConversionFlags.All; - string result = ambience.ConvertEntity(typeDef, mscorlib); + string result = ambience.ConvertEntity(typeDef); Assert.AreEqual("public class System.Collections.Generic.List", result); } @@ -107,9 +107,9 @@ namespace ICSharpCode.NRefactory.CSharp [Test] public void SimpleTypeShortName() { - var typeDef = mscorlib.GetTypeDefinition(typeof(Object)); + var typeDef = compilation.FindType(typeof(Object)).GetDefinition(); ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList; - string result = ambience.ConvertEntity(typeDef, mscorlib); + string result = ambience.ConvertEntity(typeDef); Assert.AreEqual("Object", result); } @@ -117,9 +117,9 @@ namespace ICSharpCode.NRefactory.CSharp [Test] public void GenericTypeWithNested() { - var typeDef = mscorlib.GetTypeDefinition(typeof(List<>.Enumerator)); + var typeDef = compilation.FindType(typeof(List<>.Enumerator)).GetDefinition(); ambience.ConversionFlags = ConversionFlags.UseFullyQualifiedMemberNames | ConversionFlags.ShowTypeParameterList; - string result = ambience.ConvertEntity(typeDef, mscorlib); + string result = ambience.ConvertEntity(typeDef); Assert.AreEqual("System.Collections.Generic.List.Enumerator", result); } @@ -127,9 +127,9 @@ namespace ICSharpCode.NRefactory.CSharp [Test] public void GenericTypeWithNestedShortName() { - var typeDef = mscorlib.GetTypeDefinition(typeof(List<>.Enumerator)); + var typeDef = compilation.FindType(typeof(List<>.Enumerator)).GetDefinition(); ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList; - string result = ambience.ConvertEntity(typeDef, mscorlib); + string result = ambience.ConvertEntity(typeDef); Assert.AreEqual("List.Enumerator", result); } @@ -139,34 +139,31 @@ namespace ICSharpCode.NRefactory.CSharp [Test] public void SimpleField() { - var field = typeof(CSharpAmbienceTests.Program).ToTypeReference().Resolve(myLib) - .GetDefinition().Fields.Single(f => f.Name == "test"); + var field = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetFields(f => f.Name == "test").Single(); ambience.ConversionFlags = ConversionFlags.All; - string result = ambience.ConvertEntity(field, compositeContext); + string result = ambience.ConvertEntity(field); - Assert.AreEqual("private int ICSharpCode.NRefactory.CSharp.CSharpAmbienceTests.Program.test", result); + Assert.AreEqual("private int ICSharpCode.NRefactory.CSharp.CSharpAmbienceTests.Program.test;", result); } [Test] public void SimpleConstField() { - var field = typeof(CSharpAmbienceTests.Program).ToTypeReference().Resolve(myLib) - .GetDefinition().Fields.Single(f => f.Name == "TEST2"); + var field = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetFields(f => f.Name == "TEST2").Single(); ambience.ConversionFlags = ConversionFlags.All; - string result = ambience.ConvertEntity(field, compositeContext); + string result = ambience.ConvertEntity(field); - Assert.AreEqual("private const int ICSharpCode.NRefactory.CSharp.CSharpAmbienceTests.Program.TEST2", result); + Assert.AreEqual("private const int ICSharpCode.NRefactory.CSharp.CSharpAmbienceTests.Program.TEST2;", result); } [Test] public void SimpleFieldWithoutModifiers() { - var field = typeof(CSharpAmbienceTests.Program).ToTypeReference().Resolve(myLib) - .GetDefinition().Fields.Single(f => f.Name == "test"); + var field = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetFields(f => f.Name == "test").Single(); ambience.ConversionFlags = ConversionFlags.All & ~(ConversionFlags.UseFullyQualifiedMemberNames | ConversionFlags.ShowModifiers | ConversionFlags.ShowAccessibility); - string result = ambience.ConvertEntity(field, compositeContext); + string result = ambience.ConvertEntity(field); - Assert.AreEqual("int test", result); + Assert.AreEqual("int test;", result); } #endregion diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs index ab61edf510..081f802f3f 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs @@ -17,14 +17,8 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.CodeDom; -using System.CodeDom.Compiler; -using System.IO; -using System.Text.RegularExpressions; using ICSharpCode.NRefactory.CSharp.Resolver; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.TypeSystem.Implementation; -using Microsoft.CSharp; +using ICSharpCode.NRefactory.CSharp.TypeSystem; using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp @@ -33,27 +27,32 @@ namespace ICSharpCode.NRefactory.CSharp public class CodeDomConvertVisitorTests : ResolverTestBase { CodeDomConvertVisitor convertVisitor; + CSharpResolver resolver; public override void SetUp() { base.SetUp(); - AddUsing("System"); - AddUsing("System.Collections.Generic"); - AddUsing("System.Linq"); - resolver.CurrentTypeDefinition = new DefaultTypeDefinition(project, string.Empty, "MyClass"); + resolver = new CSharpResolver(compilation); + resolver.CurrentUsingScope = new UsingScope(); + resolver.CurrentUsingScope.Usings.Add(MakeReference("System")); + resolver.CurrentUsingScope.Usings.Add(MakeReference("System.Collections.Generic")); + resolver.CurrentUsingScope.Usings.Add(MakeReference("System.Linq")); + convertVisitor = new CodeDomConvertVisitor(); convertVisitor.UseFullyQualifiedTypeNames = true; } string Convert(Expression expr) { + throw new NotImplementedException(); + /* ResolveVisitor rv = new ResolveVisitor(resolver, null); rv.Scan(expr); var codeExpr = (CodeExpression)convertVisitor.Convert(expr, rv); StringWriter writer = new StringWriter(); writer.NewLine = " "; new CSharpCodeProvider().GenerateCodeFromExpression(codeExpr, writer, new CodeGeneratorOptions { IndentString = " " }); - return Regex.Replace(writer.ToString(), @"\s+", " "); + return Regex.Replace(writer.ToString(), @"\s+", " ");*/ } [Test] diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseSelfTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseSelfTests.cs index 924a3ebba1..dcb99f1f2d 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseSelfTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseSelfTests.cs @@ -19,7 +19,7 @@ using System; using System.IO; using ICSharpCode.NRefactory.Editor; -using ICSharpCode.NRefactory.TypeSystem.Implementation; +using ICSharpCode.NRefactory.TypeSystem; using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Parser @@ -46,7 +46,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser [Test] public void GenerateTypeSystem() { - SimpleProjectContent pc = new SimpleProjectContent(); + IProjectContent pc = new CSharpProjectContent(); CSharpParser parser = new CSharpParser(); parser.GenerateTypeSystemMode = true; foreach (string fileName in fileNames) { @@ -54,8 +54,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.SequentialScan)) { cu = parser.Parse(fs); } - TypeSystemConvertVisitor cv = new TypeSystemConvertVisitor(pc, fileName); - pc.UpdateProjectContent(null, cv.Convert(cu)); + pc = pc.UpdateProjectContent(null, cu.ToTypeSystem(fileName)); } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs index fa4c82ad62..e59081eab5 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs @@ -31,7 +31,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser [TestFixtureSetUp] public void FixtureSetUp() { - testCasePC = ParseTestCase(); + compilation = ParseTestCase().CreateCompilation(); } internal static IProjectContent ParseTestCase() @@ -44,11 +44,8 @@ namespace ICSharpCode.NRefactory.CSharp.Parser cu = parser.Parse(s); } - var testCasePC = new SimpleProjectContent(); - CSharpParsedFile parsedFile = new TypeSystemConvertVisitor(testCasePC, fileName).Convert(cu); - parsedFile.Freeze(); - testCasePC.UpdateProjectContent(null, parsedFile); - return testCasePC; + var parsedFile = cu.ToTypeSystem(fileName); + return new CSharpProjectContent().UpdateProjectContent(null, parsedFile).AddAssemblyReferences(new[] { CecilLoaderTests.Mscorlib }); } } @@ -62,7 +59,8 @@ namespace ICSharpCode.NRefactory.CSharp.Parser using (MemoryStream ms = new MemoryStream()) { serializer.Serialize(ms, TypeSystemConvertVisitorTests.ParseTestCase()); ms.Position = 0; - testCasePC = (IProjectContent)serializer.Deserialize(ms); + var pc = (IProjectContent)serializer.Deserialize(ms); + compilation = pc.CreateCompilation(); } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Refactoring/TypeSystemAstBuilderTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Refactoring/TypeSystemAstBuilderTests.cs index b85b674dc1..c8ff9a9e6e 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Refactoring/TypeSystemAstBuilderTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Refactoring/TypeSystemAstBuilderTests.cs @@ -22,6 +22,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; using NUnit.Framework; @@ -52,72 +53,71 @@ namespace OtherNS { } "; - SimpleProjectContent pc; - ITypeResolveContext ctx; + IProjectContent pc; + ICompilation compilation; ITypeDefinition baseClass, derivedClass, nestedClass, systemClass; CSharpParsedFile parsedFile; [SetUp] public void SetUp() { - pc = new SimpleProjectContent(); - var cu = new CSharpParser().Parse(new StringReader(program)); - parsedFile = new TypeSystemConvertVisitor(pc, "program.cs").Convert(cu); - pc.UpdateProjectContent(null, parsedFile); + pc = new CSharpProjectContent(); + parsedFile = new CSharpParser().Parse(new StringReader(program)).ToTypeSystem("program.cs"); + pc = pc.UpdateProjectContent(null, parsedFile); + pc = pc.AddAssemblyReferences(new [] { CecilLoaderTests.Mscorlib }); - ctx = new CompositeTypeResolveContext(new[] { pc, CecilLoaderTests.Mscorlib }); + compilation = pc.CreateCompilation(); - baseClass = pc.GetTypeDefinition(string.Empty, "Base", 1, StringComparer.Ordinal); + baseClass = compilation.RootNamespace.GetTypeDefinition("Base", 1); nestedClass = baseClass.NestedTypes.Single(); - derivedClass = pc.GetTypeDefinition(string.Empty, "Derived", 2, StringComparer.Ordinal); - systemClass = pc.GetTypeDefinition("NS", "System", 0, StringComparer.Ordinal); + derivedClass = compilation.RootNamespace.GetTypeDefinition("Derived", 2); + systemClass = compilation.FindType("NS.System").GetDefinition(); } TypeSystemAstBuilder CreateBuilder(ITypeDefinition currentTypeDef = null) { return new TypeSystemAstBuilder( - new CSharpResolver(ctx) { + new CSharpResolver(compilation) { CurrentUsingScope = currentTypeDef != null ? parsedFile.GetUsingScope(currentTypeDef.Region.Begin) : parsedFile.RootUsingScope, CurrentTypeDefinition = currentTypeDef }); } - string TypeToString(ITypeReference type, ITypeDefinition currentTypeDef = null) + string TypeToString(IType type, ITypeDefinition currentTypeDef = null) { var builder = CreateBuilder(currentTypeDef); - IType resolvedType = type.Resolve(ctx); - AstType node = builder.ConvertType(resolvedType); + AstType node = builder.ConvertType(type); return node.ToString(); } [Test] public void PrimitiveVoid() { - Assert.AreEqual("void", TypeToString(KnownTypeReference.Void)); + Assert.AreEqual("void", TypeToString(compilation.FindType(KnownTypeCode.Void))); } [Test] public void PrimitiveInt() { - Assert.AreEqual("int", TypeToString(KnownTypeReference.Int32)); + Assert.AreEqual("int", TypeToString(compilation.FindType(KnownTypeCode.Int32))); } [Test] public void PrimitiveDecimal() { - Assert.AreEqual("decimal", TypeToString(KnownTypeReference.Decimal)); + Assert.AreEqual("decimal", TypeToString(compilation.FindType(KnownTypeCode.Decimal))); } [Test] public void SystemType() { - Assert.AreEqual("Type", TypeToString(KnownTypeReference.Type)); + Assert.AreEqual("Type", TypeToString(compilation.FindType(KnownTypeCode.Type))); } [Test] public void ListOfNSSystem() { - var type = new ParameterizedType(ctx.GetTypeDefinition(typeof(List<>)), new[] { systemClass }); + var type = new ParameterizedType(compilation.FindType(typeof(List<>)).GetDefinition(), new[] { systemClass }); Assert.AreEqual("List", TypeToString(type)); Assert.AreEqual("List", TypeToString(type, systemClass)); } @@ -125,26 +125,26 @@ namespace OtherNS { [Test] public void NonGenericIEnumerable() { - Assert.AreEqual("System.Collections.IEnumerable", TypeToString(typeof(IEnumerable).ToTypeReference())); + Assert.AreEqual("System.Collections.IEnumerable", TypeToString(compilation.FindType(typeof(IEnumerable)))); } [Test] public void NonGenericIEnumerableWithSystemNamespaceCollision() { - Assert.AreEqual("global::System.Collections.IEnumerable", TypeToString(typeof(IEnumerable).ToTypeReference(), systemClass)); + Assert.AreEqual("global::System.Collections.IEnumerable", TypeToString(compilation.FindType(typeof(IEnumerable)), systemClass)); } [Test] public void AliasedNamespace() { - var type = typeof(System.Reflection.Assembly).ToTypeReference(); + var type = compilation.FindType(typeof(System.Reflection.Assembly)); Assert.AreEqual("R.Assembly", TypeToString(type, systemClass)); } [Test] public void AliasedType() { - var type = new ParameterizedTypeReference(ctx.GetTypeDefinition(typeof(List<>)), new[] { KnownTypeReference.Char }); + var type = new ParameterizedType(compilation.FindType(typeof(List<>)).GetDefinition(), new[] { compilation.FindType(KnownTypeCode.Char) }); Assert.AreEqual("List", TypeToString(type)); Assert.AreEqual("L", TypeToString(type, systemClass)); } @@ -159,7 +159,7 @@ namespace OtherNS { [Test] public void NestedType() { - var type = new ParameterizedTypeReference(nestedClass, new[] { KnownTypeReference.Char, KnownTypeReference.String }); + var type = new ParameterizedType(nestedClass, new[] { compilation.FindType(KnownTypeCode.Char), compilation.FindType(KnownTypeCode.String) }); Assert.AreEqual("Base.Nested", TypeToString(type)); Assert.AreEqual("Base.Nested", TypeToString(type, baseClass)); Assert.AreEqual("Base.Nested", TypeToString(type, nestedClass)); @@ -169,7 +169,7 @@ namespace OtherNS { [Test] public void NestedTypeInCurrentClass() { - var type = new ParameterizedTypeReference(nestedClass, new[] { baseClass.TypeParameters[0], KnownTypeReference.String }); + var type = new ParameterizedType(nestedClass, new[] { baseClass.TypeParameters[0], compilation.FindType(KnownTypeCode.String) }); Assert.AreEqual("Nested", TypeToString(type, baseClass)); Assert.AreEqual("Nested", TypeToString(type, nestedClass)); } @@ -177,36 +177,36 @@ namespace OtherNS { [Test] public void NestedTypeInDerivedClass() { - var type1 = new ParameterizedTypeReference(nestedClass, new[] { derivedClass.TypeParameters[0], KnownTypeReference.String }); + var type1 = new ParameterizedType(nestedClass, new[] { derivedClass.TypeParameters[0], compilation.FindType(KnownTypeCode.String) }); Assert.AreEqual("Base.Nested", TypeToString(type1, derivedClass)); - var type2 = new ParameterizedTypeReference(nestedClass, new[] { derivedClass.TypeParameters[1], KnownTypeReference.String }); + var type2 = new ParameterizedType(nestedClass, new[] { derivedClass.TypeParameters[1], compilation.FindType(KnownTypeCode.String) }); Assert.AreEqual("Nested", TypeToString(type2, derivedClass)); } [Test] public void MultidimensionalArray() { - Assert.AreEqual("byte[][,]", TypeToString(typeof(byte[][,]).ToTypeReference())); + Assert.AreEqual("byte[][,]", TypeToString(compilation.FindType(typeof(byte[][,])))); } [Test] public void Pointer() { - Assert.AreEqual("long*", TypeToString(typeof(long*).ToTypeReference())); + Assert.AreEqual("long*", TypeToString(compilation.FindType(typeof(long*)))); } [Test] public void NullableType() { - Assert.AreEqual("ulong?", TypeToString(typeof(ulong?).ToTypeReference())); + Assert.AreEqual("ulong?", TypeToString(compilation.FindType(typeof(ulong?)))); } [Test] public void AmbiguousType() { - Assert.AreEqual("System.Array", TypeToString(typeof(Array).ToTypeReference())); - Assert.AreEqual("OtherNS.Array", TypeToString(ctx.GetTypeDefinition("OtherNS", "Array", 0, StringComparer.Ordinal))); + Assert.AreEqual("System.Array", TypeToString(compilation.FindType(typeof(Array)))); + Assert.AreEqual("OtherNS.Array", TypeToString(compilation.FindType("OtherNS.Array"))); } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/AttributeTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/AttributeTests.cs index 4ca5717670..b316175c92 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/AttributeTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/AttributeTests.cs @@ -58,7 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver string program = "using System; [$LoaderOptimization(3)$] class Test { }"; var mrr = Resolve(program); Assert.AreEqual("System.LoaderOptimizationAttribute..ctor", mrr.Member.FullName); - Assert.AreEqual("System.Byte", mrr.Member.Parameters[0].Type.Resolve(context).FullName); + Assert.AreEqual("System.Byte", mrr.Member.Parameters[0].Type.FullName); } [Test] @@ -67,7 +67,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver string program = "using System; [$LoaderOptimization(LoaderOptimization.NotSpecified)$] class Test { }"; var mrr = Resolve(program); Assert.AreEqual("System.LoaderOptimizationAttribute..ctor", mrr.Member.FullName); - Assert.AreEqual("System.LoaderOptimization", mrr.Member.Parameters[0].Type.Resolve(context).FullName); + Assert.AreEqual("System.LoaderOptimization", mrr.Member.Parameters[0].Type.FullName); } [Test] @@ -103,7 +103,7 @@ enum E { A, B } Assert.AreEqual("MyNamespace.E.A", result.Member.FullName); } - [Test, Ignore("Not implemented in type system.")] + [Test] public void SD_1384() { string program = @"using System; @@ -114,7 +114,7 @@ class Flags { TypeResolveResult result = Resolve(program); Assert.AreEqual("Flags.Test", result.Type.FullName); - var rt = result.Type.GetDefinition().Attributes[0].AttributeType.Resolve(context); + var rt = result.Type.GetDefinition().Attributes[0].AttributeType; Assert.AreEqual("System.FlagsAttribute", rt.FullName); } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/BinaryOperatorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/BinaryOperatorTests.cs index 5c310bf832..582840ac49 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/BinaryOperatorTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/BinaryOperatorTests.cs @@ -29,6 +29,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [TestFixture] public unsafe class BinaryOperatorTests : ResolverTestBase { + CSharpResolver resolver; + + public override void SetUp() + { + base.SetUp(); + resolver = new CSharpResolver(compilation); + } + [Test] public void Multiplication() { @@ -509,7 +517,7 @@ class Test { Assert.IsTrue(irr.IsLiftedOperatorInvocation); Assert.AreEqual("A.op_Addition", irr.Member.FullName); // even though we're calling the lifted operator, trr.Member should be the original operator method - Assert.AreEqual("S", irr.Member.ReturnType.Resolve(context).ReflectionName); + Assert.AreEqual("S", irr.Member.ReturnType.ReflectionName); Assert.AreEqual("System.Nullable`1[[S]]", irr.Type.ReflectionName); Conversion lhsConv = ((ConversionResolveResult)irr.Arguments[0]).Conversion; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/CastTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/CastTests.cs index 2c4ea461c8..e62ffc1587 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/CastTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/CastTests.cs @@ -29,9 +29,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [TestFixture] public class CastTests : ResolverTestBase { + CSharpResolver resolver; + + public override void SetUp() + { + base.SetUp(); + resolver = new CSharpResolver(compilation); + } + void TestCast(Type targetType, ResolveResult input, Conversion expectedConversion) { - IType type = targetType.ToTypeReference().Resolve(context); + IType type = compilation.FindType(targetType); ResolveResult rr = resolver.ResolveCast(type, input); AssertType(targetType, rr); Assert.AreEqual(typeof(ConversionResolveResult), rr.GetType()); diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConditionalOperatorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConditionalOperatorTests.cs index a017fd3551..b0e02f59fc 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConditionalOperatorTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConditionalOperatorTests.cs @@ -29,6 +29,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [TestFixture] public class ConditionalOperatorTests : ResolverTestBase { + CSharpResolver resolver; + + public override void SetUp() + { + base.SetUp(); + resolver = new CSharpResolver(compilation); + } + void TestOperator(ResolveResult condition, ResolveResult trueExpr, ResolveResult falseExpr, Conversion conditionConv, Conversion trueConv, Conversion falseConv, Type expectedResultType) diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs index e1986cdb33..54bcdb782e 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs @@ -35,20 +35,27 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [TestFixture] public unsafe class ConversionsTest { - ITypeResolveContext ctx = CecilLoaderTests.Mscorlib; - Conversions conversions = new Conversions(CecilLoaderTests.Mscorlib); + ICompilation compilation; + Conversions conversions; + + [SetUp] + public void SetUp() + { + compilation = new SimpleCompilation(CecilLoaderTests.Mscorlib); + conversions = new Conversions(compilation); + } Conversion ImplicitConversion(Type from, Type to) { - IType from2 = from.ToTypeReference().Resolve(ctx); - IType to2 = to.ToTypeReference().Resolve(ctx); + IType from2 = compilation.FindType(from); + IType to2 = compilation.FindType(to); return conversions.ImplicitConversion(from2, to2); } Conversion ExplicitConversion(Type from, Type to) { - IType from2 = from.ToTypeReference().Resolve(ctx); - IType to2 = to.ToTypeReference().Resolve(ctx); + IType from2 = compilation.FindType(from); + IType to2 = compilation.FindType(to); return conversions.ExplicitConversion(from2, to2); } @@ -60,9 +67,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(object), typeof(object))); Assert.AreEqual(C.None, ImplicitConversion(typeof(bool), typeof(char))); - Assert.AreEqual(C.IdentityConversion, conversions.ImplicitConversion(SharedTypes.Dynamic, SharedTypes.Dynamic)); - Assert.AreEqual(C.IdentityConversion, conversions.ImplicitConversion(SharedTypes.UnknownType, SharedTypes.UnknownType)); - Assert.AreEqual(C.IdentityConversion, conversions.ImplicitConversion(SharedTypes.Null, SharedTypes.Null)); + Assert.AreEqual(C.IdentityConversion, conversions.ImplicitConversion(SpecialType.Dynamic, SpecialType.Dynamic)); + Assert.AreEqual(C.IdentityConversion, conversions.ImplicitConversion(SpecialType.UnknownType, SpecialType.UnknownType)); + Assert.AreEqual(C.IdentityConversion, conversions.ImplicitConversion(SpecialType.NullType, SpecialType.NullType)); } [Test] @@ -246,14 +253,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [Test] public void UnconstrainedTypeParameter() { - DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); - DefaultTypeParameter t2 = new DefaultTypeParameter(EntityType.TypeDefinition, 1, "T2"); - DefaultTypeParameter tm = new DefaultTypeParameter(EntityType.Method, 0, "TM"); + ITypeParameter t = new DefaultResolvedTypeParameter(EntityType.TypeDefinition, 0, "T"); + ITypeParameter t2 = new DefaultResolvedTypeParameter(EntityType.TypeDefinition, 1, "T2"); + ITypeParameter tm = new DefaultResolvedTypeParameter(EntityType.Method, 0, "TM"); - Assert.AreEqual(C.None, conversions.ImplicitConversion(SharedTypes.Null, t)); - Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); - Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, SharedTypes.Dynamic)); - Assert.AreEqual(C.None, conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); + Assert.AreEqual(C.None, conversions.ImplicitConversion(SpecialType.NullType, t)); + Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object))); + Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, SpecialType.Dynamic)); + Assert.AreEqual(C.None, conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType)))); Assert.AreEqual(C.IdentityConversion, conversions.ImplicitConversion(t, t)); Assert.AreEqual(C.None, conversions.ImplicitConversion(t2, t)); @@ -265,65 +272,63 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [Test] public void TypeParameterWithReferenceTypeConstraint() { - DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); - t.HasReferenceTypeConstraint = true; + ITypeParameter t = new DefaultResolvedTypeParameter(EntityType.TypeDefinition, 0, "T", hasReferenceTypeConstraint: true); - Assert.AreEqual(C.NullLiteralConversion, conversions.ImplicitConversion(SharedTypes.Null, t)); - Assert.AreEqual(C.ImplicitReferenceConversion, conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); - Assert.AreEqual(C.ImplicitReferenceConversion, conversions.ImplicitConversion(t, SharedTypes.Dynamic)); - Assert.AreEqual(C.None, conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); + Assert.AreEqual(C.NullLiteralConversion, conversions.ImplicitConversion(SpecialType.NullType, t)); + Assert.AreEqual(C.ImplicitReferenceConversion, conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object))); + Assert.AreEqual(C.ImplicitReferenceConversion, conversions.ImplicitConversion(t, SpecialType.Dynamic)); + Assert.AreEqual(C.None, conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType)))); } [Test] public void TypeParameterWithValueTypeConstraint() { - DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); - t.HasValueTypeConstraint = true; + ITypeParameter t = new DefaultResolvedTypeParameter(EntityType.TypeDefinition, 0, "T", hasValueTypeConstraint: true); - Assert.AreEqual(C.None, conversions.ImplicitConversion(SharedTypes.Null, t)); - Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); - Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, SharedTypes.Dynamic)); - Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); + Assert.AreEqual(C.None, conversions.ImplicitConversion(SpecialType.NullType, t)); + Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object))); + Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, SpecialType.Dynamic)); + Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType)))); } [Test] public void TypeParameterWithClassConstraint() { - DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); - t.Constraints.Add(ctx.GetTypeDefinition(typeof(StringComparer))); + ITypeParameter t = new DefaultResolvedTypeParameter(EntityType.TypeDefinition, 0, "T", + constraints: new[] { compilation.FindType(typeof(StringComparer)) }); Assert.AreEqual(C.NullLiteralConversion, - conversions.ImplicitConversion(SharedTypes.Null, t)); + conversions.ImplicitConversion(SpecialType.NullType, t)); Assert.AreEqual(C.ImplicitReferenceConversion, - conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); + conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object))); Assert.AreEqual(C.ImplicitReferenceConversion, - conversions.ImplicitConversion(t, SharedTypes.Dynamic)); - Assert.AreEqual(C.None, conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); + conversions.ImplicitConversion(t, SpecialType.Dynamic)); + Assert.AreEqual(C.None, conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType)))); Assert.AreEqual(C.ImplicitReferenceConversion, - conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(StringComparer)))); + conversions.ImplicitConversion(t, compilation.FindType(typeof(StringComparer)))); Assert.AreEqual(C.ImplicitReferenceConversion, - conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IComparer)))); - Assert.AreEqual(C.None, conversions.ImplicitConversion(t, typeof(IComparer).ToTypeReference().Resolve(ctx))); + conversions.ImplicitConversion(t, compilation.FindType(typeof(IComparer)))); + Assert.AreEqual(C.None, conversions.ImplicitConversion(t, compilation.FindType(typeof(IComparer)))); Assert.AreEqual(C.ImplicitReferenceConversion, - conversions.ImplicitConversion(t, typeof(IComparer).ToTypeReference().Resolve(ctx))); + conversions.ImplicitConversion(t, compilation.FindType(typeof(IComparer)))); } [Test] public void TypeParameterWithInterfaceConstraint() { - DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); - t.Constraints.Add(ctx.GetTypeDefinition(typeof(IList))); + ITypeParameter t = new DefaultResolvedTypeParameter(EntityType.TypeDefinition, 0, "T", + constraints: new [] { compilation.FindType(typeof(IList)) }); - Assert.AreEqual(C.None, conversions.ImplicitConversion(SharedTypes.Null, t)); + Assert.AreEqual(C.None, conversions.ImplicitConversion(SpecialType.NullType, t)); Assert.AreEqual(C.BoxingConversion, - conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); + conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object))); Assert.AreEqual(C.BoxingConversion, - conversions.ImplicitConversion(t, SharedTypes.Dynamic)); - Assert.AreEqual(C.None, conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); + conversions.ImplicitConversion(t, SpecialType.Dynamic)); + Assert.AreEqual(C.None, conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType)))); Assert.AreEqual(C.BoxingConversion, - conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IList)))); + conversions.ImplicitConversion(t, compilation.FindType(typeof(IList)))); Assert.AreEqual(C.BoxingConversion, - conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IEnumerable)))); + conversions.ImplicitConversion(t, compilation.FindType(typeof(IEnumerable)))); } [Test] @@ -349,9 +354,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Conversion IntegerLiteralConversion(object value, Type to) { - IType fromType = value.GetType().ToTypeReference().Resolve(ctx); + IType fromType = compilation.FindType(value.GetType()); ConstantResolveResult crr = new ConstantResolveResult(fromType, value); - IType to2 = to.ToTypeReference().Resolve(ctx); + IType to2 = compilation.FindType(to); return conversions.ImplicitConversion(crr, to2); } @@ -426,18 +431,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver int BetterConversion(Type s, Type t1, Type t2) { - IType sType = s.ToTypeReference().Resolve(ctx); - IType t1Type = t1.ToTypeReference().Resolve(ctx); - IType t2Type = t2.ToTypeReference().Resolve(ctx); + IType sType = compilation.FindType(s); + IType t1Type = compilation.FindType(t1); + IType t2Type = compilation.FindType(t2); return conversions.BetterConversion(sType, t1Type, t2Type); } int BetterConversion(object value, Type t1, Type t2) { - IType fromType = value.GetType().ToTypeReference().Resolve(ctx); + IType fromType = compilation.FindType(value.GetType()); ConstantResolveResult crr = new ConstantResolveResult(fromType, value); - IType t1Type = t1.ToTypeReference().Resolve(ctx); - IType t2Type = t2.ToTypeReference().Resolve(ctx); + IType t1Type = compilation.FindType(t1); + IType t2Type = compilation.FindType(t2); return conversions.BetterConversion(crr, t1Type, t2Type); } @@ -482,19 +487,25 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [Test] public void ExpansiveInheritance() { - SimpleProjectContent pc = new SimpleProjectContent(); - DefaultTypeDefinition a = new DefaultTypeDefinition(pc, string.Empty, "A"); - DefaultTypeDefinition b = new DefaultTypeDefinition(pc, string.Empty, "B"); + var a = new DefaultUnresolvedTypeDefinition(string.Empty, "A"); + var b = new DefaultUnresolvedTypeDefinition(string.Empty, "B"); // interface A a.Kind = TypeKind.Interface; - a.TypeParameters.Add(new DefaultTypeParameter(EntityType.TypeDefinition, 0, "U") { Variance = VarianceModifier.Contravariant }); + a.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, 0, "U") { Variance = VarianceModifier.Contravariant }); // interface B : A>> { } - DefaultTypeParameter x = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "X"); - b.TypeParameters.Add(x); - b.BaseTypes.Add(new ParameterizedType(a, new[] { new ParameterizedType(a, new [] { new ParameterizedType(b, new [] { x }) } ) })); + b.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, 0, "X")); + b.BaseTypes.Add(new ParameterizedTypeReference( + a, new[] { new ParameterizedTypeReference( + a, new [] { new ParameterizedTypeReference( + b, new [] { new TypeParameterReference(EntityType.TypeDefinition, 0) } + ) } ) })); + + ICompilation compilation = new SimpleCompilation(CecilLoaderTests.Mscorlib); + ITypeDefinition resolvedA = a.Resolve(compilation.TypeResolveContext); + ITypeDefinition resolvedB = b.Resolve(compilation.TypeResolveContext); - IType type1 = new ParameterizedType(b, new[] { KnownTypeReference.Double.Resolve(ctx) }); - IType type2 = new ParameterizedType(a, new [] { new ParameterizedType(b, new[] { KnownTypeReference.String.Resolve(ctx) }) }); + IType type1 = new ParameterizedType(resolvedB, new[] { compilation.FindType(KnownTypeCode.Double) }); + IType type2 = new ParameterizedType(resolvedA, new [] { new ParameterizedType(resolvedB, new[] { compilation.FindType(KnownTypeCode.String) }) }); Assert.IsFalse(conversions.ImplicitConversion(type1, type2)); } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs index 26fcec5e46..aca87a4fce 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs @@ -53,18 +53,18 @@ namespace XN { mrr = Resolve(program.Replace("$", "$a.F(1)$")); Assert.AreEqual("XN.XC.F", mrr.Member.FullName); - Assert.AreEqual("System.Int32", mrr.Member.Parameters[1].Type.Resolve(context).FullName); + Assert.AreEqual("System.Int32", mrr.Member.Parameters[1].Type.FullName); mrr = Resolve(program.Replace("$", "$a.F(\"text\")$")); Assert.AreEqual("XN.XC.F", mrr.Member.FullName); - Assert.AreEqual("System.String", mrr.Member.Parameters[1].Type.Resolve(context).FullName); + Assert.AreEqual("System.String", mrr.Member.Parameters[1].Type.FullName); mrr = Resolve(program.Replace("$", "$b.F(1)$")); Assert.AreEqual("B.F", mrr.Member.FullName); mrr = Resolve(program.Replace("$", "$b.F(\"text\")$")); Assert.AreEqual("XN.XC.F", mrr.Member.FullName); - Assert.AreEqual("System.String", mrr.Member.Parameters[1].Type.Resolve(context).FullName); + Assert.AreEqual("System.String", mrr.Member.Parameters[1].Type.FullName); mrr = Resolve(program.Replace("$", "$c.F(1)$")); Assert.AreEqual("C.F", mrr.Member.FullName); diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs index 0382c3c130..1c0fb6aada 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs @@ -60,9 +60,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Assert.AreEqual("System.String", result.TargetType.FullName); Assert.AreEqual(1, result.Parameters.Count); Assert.AreEqual("b", result.Parameters[0].Name); - Assert.AreEqual("System.String", result.Parameters[0].Type.Resolve(context).ReflectionName); + Assert.AreEqual("System.String", result.Parameters[0].Type.ReflectionName); - Assert.AreSame(SharedTypes.UnknownType, result.Type); + Assert.AreSame(SpecialType.UnknownType, result.Type); } [Test] @@ -304,8 +304,8 @@ class DerivedClass : MiddleClass { var m = (SpecializedMethod)rr.Member; Assert.AreEqual("X", m.TypeArguments.Single().Name); - Assert.AreEqual("T", m.Parameters[0].Type.Resolve(context).Name); - Assert.AreEqual("X", m.Parameters[1].Type.Resolve(context).Name); + Assert.AreEqual("T", m.Parameters[0].Type.Name); + Assert.AreEqual("X", m.Parameters[1].Type.Name); } [Test] diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs index 94f9dfd2da..89cfef1c1b 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs @@ -373,7 +373,7 @@ class TestClass { Assert.IsFalse(rr.IsError); SpecializedMethod m = (SpecializedMethod)rr.Member; Assert.AreEqual("System.Int32", m.TypeArguments[0].ReflectionName); - Assert.AreEqual("System.Converter`2[[``0],[System.Int32]]", m.Parameters[0].Type.Resolve(context).ReflectionName); + Assert.AreEqual("System.Converter`2[[``0],[System.Int32]]", m.Parameters[0].Type.ReflectionName); var crr = (ConversionResolveResult)rr.Arguments[0]; Assert.IsTrue(crr.Conversion.IsAnonymousFunctionConversion); diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LocalTypeInferenceTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LocalTypeInferenceTests.cs index 16017e7e54..d31f92e0c4 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LocalTypeInferenceTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LocalTypeInferenceTests.cs @@ -51,7 +51,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } "; var lrr = Resolve(program); - Assert.AreSame(SharedTypes.UnknownType, lrr.Type); + Assert.AreSame(SpecialType.UnknownType, lrr.Type); } [Test] @@ -65,7 +65,7 @@ class TestClass { $contact$.ToString(); } }"; var lrr = Resolve(program); - Assert.AreEqual(SharedTypes.UnknownType, lrr.Type); + Assert.AreEqual(SpecialType.UnknownType, lrr.Type); } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/MemberLookupTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/MemberLookupTests.cs index dd0ed646ed..b0d48eeeb8 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/MemberLookupTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/MemberLookupTests.cs @@ -20,6 +20,7 @@ using System; using System.IO; using System.Linq; +using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using NUnit.Framework; @@ -34,14 +35,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public override void SetUp() { base.SetUp(); - lookup = new MemberLookup(context, null, project); + lookup = new MemberLookup(null, compilation.MainAssembly); } CSharpParsedFile Parse(string program) { CompilationUnit cu = new CSharpParser().Parse(new StringReader(program)); - CSharpParsedFile parsedFile = new TypeSystemConvertVisitor(project, "test.cs").Convert(cu); - project.UpdateProjectContent(null, parsedFile); + CSharpParsedFile parsedFile = cu.ToTypeSystem("test.cs"); + project = project.UpdateProjectContent(null, parsedFile); + compilation = project.CreateCompilation(); return parsedFile; } @@ -58,7 +60,7 @@ class Middle : Base { class Derived : Middle { public override void Method() {} }"; - ITypeDefinition derived = Parse(program).TopLevelTypeDefinitions[2]; + ITypeDefinition derived = Parse(program).TopLevelTypeDefinitions[2].Resolve(compilation.TypeResolveContext); var rr = lookup.Lookup(new ResolveResult(derived), "Method", EmptyList.Instance, true) as MethodGroupResolveResult; Assert.AreEqual(2, rr.MethodsGroupedByDeclaringType.Count()); @@ -84,7 +86,7 @@ class Derived : Base { public override void Method(int a) {} public override void Method(string a) {} }"; - ITypeDefinition derived = Parse(program).TopLevelTypeDefinitions[1]; + ITypeDefinition derived = Parse(program).TopLevelTypeDefinitions[1].Resolve(compilation.TypeResolveContext); var rr = lookup.Lookup(new ResolveResult(derived), "Method", EmptyList.Instance, true) as MethodGroupResolveResult; Assert.AreEqual(2, rr.MethodsGroupedByDeclaringType.Count()); @@ -92,13 +94,13 @@ class Derived : Base { Assert.AreEqual("Base`1[[System.Int32]]", baseGroup.DeclaringType.ReflectionName); Assert.AreEqual(1, baseGroup.Count); Assert.AreEqual("Derived.Method", baseGroup[0].FullName); - Assert.AreEqual("System.Int32", baseGroup[0].Parameters[0].Type.Resolve(context).ReflectionName); + Assert.AreEqual("System.Int32", baseGroup[0].Parameters[0].Type.ReflectionName); var derivedGroup = rr.MethodsGroupedByDeclaringType.ElementAt(1); Assert.AreEqual("Derived", derivedGroup.DeclaringType.ReflectionName); Assert.AreEqual(1, derivedGroup.Count); Assert.AreEqual("Derived.Method", derivedGroup[0].FullName); - Assert.AreEqual("System.String", derivedGroup[0].Parameters[0].Type.Resolve(context).ReflectionName); + Assert.AreEqual("System.String", derivedGroup[0].Parameters[0].Type.ReflectionName); } [Test] @@ -111,7 +113,7 @@ class Base { class Derived : Base { public override void Method(S a) {} }"; - ITypeDefinition derived = Parse(program).TopLevelTypeDefinitions[1]; + ITypeDefinition derived = Parse(program).TopLevelTypeDefinitions[1].Resolve(compilation.TypeResolveContext); var rr = lookup.Lookup(new ResolveResult(derived), "Method", EmptyList.Instance, true) as MethodGroupResolveResult; Assert.AreEqual(1, rr.MethodsGroupedByDeclaringType.Count()); @@ -119,7 +121,7 @@ class Derived : Base { Assert.AreEqual("Base", baseGroup.DeclaringType.ReflectionName); Assert.AreEqual(1, baseGroup.Count); Assert.AreEqual("Derived.Method", baseGroup[0].FullName); - Assert.AreEqual("``0", baseGroup[0].Parameters[0].Type.Resolve(context).ReflectionName); + Assert.AreEqual("``0", baseGroup[0].Parameters[0].Type.ReflectionName); } [Test] diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs index ed47eab828..ba6e4fa47d 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; +using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; @@ -30,6 +31,25 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [TestFixture] public class NameLookupTests : ResolverTestBase { + CSharpResolver resolver; + + public override void SetUp() + { + base.SetUp(); + resolver = new CSharpResolver(compilation); + resolver.CurrentUsingScope = new UsingScope(); + } + + void AddUsing(string namespaceName) + { + resolver.CurrentUsingScope.Usings.Add(MakeReference(namespaceName)); + } + + void AddUsingAlias(string alias, string namespaceName) + { + resolver.CurrentUsingScope.UsingAliases.Add(new KeyValuePair(alias, MakeReference(namespaceName))); + } + [Test] public void SimpleNameLookupWithoutContext() { @@ -43,7 +63,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { NamespaceResolveResult nrr = (NamespaceResolveResult)resolver.ResolveSimpleName("System", new IType[0]); Assert.AreEqual("System", nrr.NamespaceName); - Assert.AreSame(SharedTypes.UnknownType, nrr.Type); + Assert.AreSame(SpecialType.UnknownType, nrr.Type); } [Test] @@ -97,7 +117,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver AddUsingAlias("x", "String"); TypeResolveResult trr = (TypeResolveResult)resolver.ResolveSimpleName("x", new IType[0]); // Unknown type (as String isn't looked up in System) - Assert.AreSame(SharedTypes.UnknownType, trr.Type); + Assert.AreSame(SpecialType.UnknownType, trr.Type); } [Test] @@ -151,7 +171,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public void FindTypeParameters() { resolver.CurrentUsingScope = MakeUsingScope("System.Collections.Generic"); - resolver.CurrentTypeDefinition = context.GetTypeDefinition(typeof(List<>)); + resolver.CurrentTypeDefinition = compilation.FindType(typeof(List<>)).GetDefinition(); resolver.CurrentMember = resolver.CurrentTypeDefinition.Methods.Single(m => m.Name == "ConvertAll"); TypeResolveResult trr; @@ -205,7 +225,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver UnknownIdentifierResolveResult result = Resolve(program); Assert.AreEqual("StringBuilder", result.Identifier); - Assert.AreSame(SharedTypes.UnknownType, result.Type); + Assert.AreSame(SpecialType.UnknownType, result.Type); } const string propertyNameAmbiguousWithTypeNameProgram = @"class A { @@ -806,7 +826,7 @@ class Test { }"; MemberResolveResult rr = Resolve(program); Assert.AreEqual("System.Nullable.Value", rr.Member.FullName); - Assert.AreEqual("System.Int32", rr.Member.ReturnType.Resolve(context).FullName); + Assert.AreEqual("System.Int32", rr.Member.ReturnType.FullName); } [Test] @@ -857,8 +877,8 @@ class B var m = (SpecializedMethod)rr.Methods.Single(); Assert.AreSame(rr.TypeArguments.Single(), m.TypeArguments.Single()); - Assert.AreEqual("T", m.Parameters[0].Type.Resolve(context).Name); - Assert.AreEqual("X", m.Parameters[1].Type.Resolve(context).Name); + Assert.AreEqual("T", m.Parameters[0].Type.Name); + Assert.AreEqual("X", m.Parameters[1].Type.Name); } [Test] diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs index 9669d5984f..da911385a8 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs @@ -52,7 +52,7 @@ class A { } "; ResolveResult result = Resolve(program); - Assert.AreSame(SharedTypes.UnknownType, result.Type); + Assert.AreSame(SpecialType.UnknownType, result.Type); } [Test] @@ -66,7 +66,7 @@ class A { "; UnknownIdentifierResolveResult result = Resolve(program); Assert.AreEqual("ThisClassDoesNotExist", result.Identifier); - Assert.AreSame(SharedTypes.UnknownType, result.Type); + Assert.AreSame(SpecialType.UnknownType, result.Type); } [Test] diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/OverloadResolutionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/OverloadResolutionTests.cs index d38174d2af..602884a099 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/OverloadResolutionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/OverloadResolutionTests.cs @@ -31,8 +31,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [TestFixture] public class OverloadResolutionTests { - readonly ITypeResolveContext context = new CompositeTypeResolveContext( - new[] { CecilLoaderTests.Mscorlib, CecilLoaderTests.SystemCore }); + /* + readonly ICompilation compilation = new SimpleCompilation( + CecilLoaderTests.SystemCore, new[] { CecilLoaderTests.Mscorlib }); readonly DefaultTypeDefinition dummyClass = new DefaultTypeDefinition(CecilLoaderTests.Mscorlib, string.Empty, "DummyClass"); ResolveResult[] MakeArgumentList(params Type[] argumentTypes) @@ -302,5 +303,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m2)); Assert.AreEqual(OverloadResolutionErrors.AmbiguousMatch, r.BestCandidateErrors); } + */ } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolveAtLocationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolveAtLocationTests.cs index 171cb3718f..7167fd81d8 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolveAtLocationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolveAtLocationTests.cs @@ -55,7 +55,7 @@ class A { void M() { Console.W$riteLine(1); }}"); Assert.AreEqual("System.Console.WriteLine", rr.Member.FullName); - Assert.AreEqual("System.Int32", rr.Member.Parameters[0].Type.Resolve(context).FullName); + Assert.AreEqual("System.Int32", rr.Member.Parameters[0].Type.FullName); } [Test] diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs index 758d31bac0..235c71448c 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs @@ -21,8 +21,8 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; - using ICSharpCode.NRefactory.CSharp.Parser; +using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; @@ -35,23 +35,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// public abstract class ResolverTestBase { - protected readonly IProjectContent mscorlib = CecilLoaderTests.Mscorlib; - protected SimpleProjectContent project; - protected ITypeResolveContext context; - protected CSharpResolver resolver; + protected readonly IUnresolvedAssembly mscorlib = CecilLoaderTests.Mscorlib; + protected IProjectContent project; + protected ICompilation compilation; [SetUp] public virtual void SetUp() { - project = new SimpleProjectContent(); - context = new CompositeTypeResolveContext(new [] { project, mscorlib, CecilLoaderTests.SystemCore }); - resolver = new CSharpResolver(context); - resolver.CurrentUsingScope = MakeUsingScope(""); + project = new CSharpProjectContent().AddAssemblyReferences(new [] { mscorlib }); + compilation = project.CreateCompilation(); } protected UsingScope MakeUsingScope(string namespaceName) { - UsingScope u = new UsingScope(project); + UsingScope u = new UsingScope(); if (!string.IsNullOrEmpty(namespaceName)) { foreach (string element in namespaceName.Split('.')) { u = new UsingScope(u, string.IsNullOrEmpty(u.NamespaceName) ? element : u.NamespaceName + "." + element); @@ -60,36 +57,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return u; } - /// - /// Adds a using to the current using scope. - /// - protected void AddUsing(string namespaceName) - { - resolver.CurrentUsingScope.Usings.Add(MakeReference(namespaceName)); - } - - /// - /// Adds a using alias to the current using scope. - /// - protected void AddUsingAlias(string alias, string target) - { - resolver.CurrentUsingScope.UsingAliases.Add(new KeyValuePair(alias, MakeReference(target))); - } - - protected ITypeOrNamespaceReference MakeReference(string namespaceName) + protected TypeOrNamespaceReference MakeReference(string namespaceName) { string[] nameParts = namespaceName.Split('.'); - ITypeOrNamespaceReference r = new SimpleTypeOrNamespaceReference(nameParts[0], new ITypeReference[0], resolver.CurrentTypeDefinition, resolver.CurrentUsingScope, SimpleNameLookupMode.TypeInUsingDeclaration); + TypeOrNamespaceReference r = new SimpleTypeOrNamespaceReference(nameParts[0], new ITypeReference[0], SimpleNameLookupMode.TypeInUsingDeclaration); for (int i = 1; i < nameParts.Length; i++) { - r = new MemberTypeOrNamespaceReference(r, nameParts[i], new ITypeReference[0], resolver.CurrentTypeDefinition, resolver.CurrentUsingScope); + r = new MemberTypeOrNamespaceReference(r, nameParts[i], new ITypeReference[0]); } return r; } protected IType ResolveType(Type type) { - IType t = type.ToTypeReference().Resolve(context); - if (SharedTypes.UnknownType.Equals(t)) + IType t = compilation.FindType(type); + if (t.Kind == TypeKind.Unknown) throw new InvalidOperationException("Could not resolve type"); return t; } @@ -97,7 +78,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver protected ConstantResolveResult MakeConstant(object value) { if (value == null) - return new ConstantResolveResult(SharedTypes.Null, null); + return new ConstantResolveResult(SpecialType.NullType, null); IType type = ResolveType(value.GetType()); if (type.Kind == TypeKind.Enum) value = Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType())); @@ -128,19 +109,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { Assert.IsFalse(rr.IsError, rr.ToString() + " is an error"); Assert.IsFalse(rr.IsCompileTimeConstant, rr.ToString() + " is a compile-time constant"); - Assert.AreEqual(expectedType.ToTypeReference().Resolve(context), rr.Type); + Assert.AreEqual(compilation.FindType(expectedType), rr.Type); } protected void AssertError(Type expectedType, ResolveResult rr) { Assert.IsTrue(rr.IsError, rr.ToString() + " is not an error, but an error was expected"); Assert.IsFalse(rr.IsCompileTimeConstant, rr.ToString() + " is a compile-time constant"); - Assert.AreEqual(expectedType.ToTypeReference().Resolve(context), rr.Type); + Assert.AreEqual(compilation.FindType(expectedType), rr.Type); } protected void TestOperator(UnaryOperatorType op, ResolveResult input, Conversion expectedConversion, Type expectedResultType) { + CSharpResolver resolver = new CSharpResolver(compilation); var rr = resolver.ResolveUnaryOperator(op, input); AssertType(expectedResultType, rr); Assert.AreEqual(typeof(OperatorResolveResult), rr.GetType()); @@ -151,6 +133,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver protected void TestOperator(ResolveResult lhs, BinaryOperatorType op, ResolveResult rhs, Conversion expectedLeftConversion, Conversion expectedRightConversion, Type expectedResultType) { + CSharpResolver resolver = new CSharpResolver(compilation); var rr = resolver.ResolveBinaryOperator(op, lhs, rhs); AssertType(expectedResultType, rr); Assert.AreEqual(typeof(OperatorResolveResult), rr.GetType()); @@ -196,10 +179,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver SetUp(); - CSharpParsedFile parsedFile = new CSharpParsedFile("test.cs", resolver.CurrentUsingScope); - TypeSystemConvertVisitor convertVisitor = new TypeSystemConvertVisitor(parsedFile); - cu.AcceptVisitor(convertVisitor, null); - project.UpdateProjectContent(null, convertVisitor.ParsedFile); + CSharpParsedFile parsedFile = cu.ToTypeSystem("code.cs"); + project = project.UpdateProjectContent(null, parsedFile); + compilation = project.CreateCompilation(); FindNodeVisitor fnv = new FindNodeVisitor(dollars[0], dollars[1]); cu.AcceptVisitor(fnv, null); @@ -209,12 +191,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Debug.WriteLine("Starting new resolver for " + fnv.ResultNode); var navigator = new NodeListResolveVisitorNavigator(new[] { fnv.ResultNode }); - ResolveResult rr; - using (var context = this.context.Synchronize()) { - ResolveVisitor rv = new ResolveVisitor(new CSharpResolver(context), convertVisitor.ParsedFile, navigator); - rv.Scan(cu); - rr = rv.GetResolveResult(fnv.ResultNode); - } + ResolveVisitor rv = new ResolveVisitor(new CSharpResolver(compilation), parsedFile, navigator); + rv.Scan(cu); + ResolveResult rr = rv.GetResolveResult(fnv.ResultNode); Assert.IsNotNull(rr, "ResolveResult is null - did something go wrong while navigating to the target node?"); Debug.WriteLine("ResolveResult is " + rr); return rr; @@ -261,12 +240,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver SetUp(); - CSharpParsedFile parsedFile = new CSharpParsedFile("test.cs", resolver.CurrentUsingScope); - TypeSystemConvertVisitor convertVisitor = new TypeSystemConvertVisitor(parsedFile, resolver.CurrentUsingScope, null); - cu.AcceptVisitor(convertVisitor, null); - project.UpdateProjectContent(null, convertVisitor.ParsedFile); + CSharpParsedFile parsedFile = cu.ToTypeSystem("test.cs"); + project = project.UpdateProjectContent(null, parsedFile); + compilation = project.CreateCompilation(); - ResolveResult rr = Resolver.ResolveAtLocation.Resolve(this.context, parsedFile, cu, dollars[0]); + ResolveResult rr = Resolver.ResolveAtLocation.Resolve(compilation, parsedFile, cu, dollars[0]); return rr; } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs index 5f43d8aae1..20a7acd5e0 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs @@ -32,13 +32,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [TestFixture] public class TypeInferenceTests { - readonly ITypeResolveContext ctx = CecilLoaderTests.Mscorlib; + readonly ICompilation compilation = new SimpleCompilation(CecilLoaderTests.Mscorlib); TypeInference ti; [SetUp] public void Setup() { - ti = new TypeInference(ctx); + ti = new TypeInference(compilation); } #region Type Inference @@ -46,8 +46,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { IType[] r = new IType[types.Length]; for (int i = 0; i < types.Length; i++) { - r[i] = types[i].ToTypeReference().Resolve(CecilLoaderTests.Mscorlib); - Assert.AreNotSame(r[i], SharedTypes.UnknownType); + r[i] = compilation.FindType(types[i]); + Assert.AreNotSame(r[i], SpecialType.UnknownType); } Array.Sort(r, (a,b)=>a.ReflectionName.CompareTo(b.ReflectionName)); return r; @@ -56,15 +56,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [Test] public void ArrayToEnumerable() { - ITypeParameter tp = new DefaultTypeParameter(EntityType.Method, 0, "T"); - IType stringType = KnownTypeReference.String.Resolve(ctx); - ITypeDefinition enumerableType = ctx.GetTypeDefinition(typeof(IEnumerable<>)); + ITypeParameter tp = new DefaultResolvedTypeParameter(EntityType.Method, 0, "T"); + IType stringType = compilation.FindType(KnownTypeCode.String); + ITypeDefinition enumerableType = compilation.FindType(KnownTypeCode.IEnumerableOfT).GetDefinition(); bool success; Assert.AreEqual( new [] { stringType }, ti.InferTypeArguments(new [] { tp }, - new [] { new ResolveResult(new ArrayType(stringType)) }, + new [] { new ResolveResult(new ArrayType(compilation, stringType)) }, new [] { new ParameterizedType(enumerableType, new [] { tp }) }, out success)); Assert.IsTrue(success); @@ -73,13 +73,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [Test] public void EnumerableToArrayInContravariantType() { - ITypeParameter tp = new DefaultTypeParameter(EntityType.Method, 0, "T"); - IType stringType = KnownTypeReference.String.Resolve(ctx); - ITypeDefinition enumerableType = ctx.GetTypeDefinition(typeof(IEnumerable<>)); - ITypeDefinition comparerType = ctx.GetTypeDefinition(typeof(IComparer<>)); + ITypeParameter tp = new DefaultResolvedTypeParameter(EntityType.Method, 0, "T"); + IType stringType = compilation.FindType(KnownTypeCode.String); + ITypeDefinition enumerableType = compilation.FindType(typeof(IEnumerable<>)).GetDefinition(); + ITypeDefinition comparerType = compilation.FindType(typeof(IComparer<>)).GetDefinition(); - var comparerOfIEnumerableOfString = new ParameterizedType(comparerType, new [] { new ParameterizedType(enumerableType, new [] { stringType} ) }); - var comparerOfTpArray = new ParameterizedType(comparerType, new [] { new ArrayType(tp) }); + var comparerOfIEnumerableOfString = new ParameterizedType(comparerType, new [] { new ParameterizedType(enumerableType, new [] { stringType } ) }); + var comparerOfTpArray = new ParameterizedType(comparerType, new [] { new ArrayType(compilation, tp) }); bool success; Assert.AreEqual( @@ -98,16 +98,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { // static void M(Func f) {} // M(int.Parse); // type inference fails - DefaultTypeParameter A = new DefaultTypeParameter(EntityType.Method, 0, "A"); - DefaultTypeParameter B = new DefaultTypeParameter(EntityType.Method, 1, "B"); + var A = new DefaultResolvedTypeParameter(EntityType.Method, 0, "A"); + var B = new DefaultResolvedTypeParameter(EntityType.Method, 1, "B"); - ITypeDefinition declType = ctx.GetTypeDefinition(typeof(int)); - var methods = new MethodListWithDeclaringType(declType, declType.Methods.Where(m => m.Name == "Parse")); + IType declType = compilation.FindType(typeof(int)); + var methods = new MethodListWithDeclaringType(declType, declType.GetMethods(m => m.Name == "Parse")); var argument = new MethodGroupResolveResult(new TypeResolveResult(declType), "Parse", new[] { methods }, new IType[0]); bool success; ti.InferTypeArguments(new [] { A, B }, new [] { argument }, - new [] { new ParameterizedType(ctx.GetTypeDefinition(typeof(Func<,>)), new[] { A, B }) }, + new [] { new ParameterizedType(compilation.FindType(typeof(Func<,>)).GetDefinition(), new[] { A, B }) }, out success); Assert.IsFalse(success); } @@ -118,17 +118,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // static void M(Func f) {} // M(Console.ReadKey); // type inference produces ConsoleKeyInfo - DefaultTypeParameter T = new DefaultTypeParameter(EntityType.Method, 0, "T"); + var T = new DefaultResolvedTypeParameter(EntityType.Method, 0, "T"); - ITypeDefinition declType = ctx.GetTypeDefinition(typeof(Console)); - var methods = new MethodListWithDeclaringType(declType, declType.Methods.Where(m => m.Name == "ReadKey")); + IType declType = compilation.FindType(typeof(Console)); + var methods = new MethodListWithDeclaringType(declType, declType.GetMethods(m => m.Name == "ReadKey")); var argument = new MethodGroupResolveResult(new TypeResolveResult(declType), "ReadKey", new[] { methods }, new IType[0]); bool success; Assert.AreEqual( - new [] { ctx.GetTypeDefinition(typeof(ConsoleKeyInfo)) }, + new [] { compilation.FindType(typeof(ConsoleKeyInfo)) }, ti.InferTypeArguments(new [] { T }, new [] { argument }, - new [] { new ParameterizedType(ctx.GetTypeDefinition(typeof(Func<>)), new[] { T }) }, + new [] { new ParameterizedType(compilation.FindType(typeof(Func<>)).GetDefinition(), new[] { T }) }, out success)); Assert.IsTrue(success); } @@ -149,7 +149,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver this.parameters = new IParameter[expectedParameterTypes.Length]; for (int i = 0; i < parameters.Length; i++) { // UnknownType because this lambda is implicitly typed - parameters[i] = new DefaultParameter(SharedTypes.UnknownType, "X" + i); + parameters[i] = new DefaultParameter(SpecialType.UnknownType, "X" + i); } } @@ -200,28 +200,28 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public void TestLambdaInference() { ITypeParameter[] typeParameters = { - new DefaultTypeParameter(EntityType.Method, 0, "X"), - new DefaultTypeParameter(EntityType.Method, 1, "Y"), - new DefaultTypeParameter(EntityType.Method, 2, "Z") + new DefaultResolvedTypeParameter(EntityType.Method, 0, "X"), + new DefaultResolvedTypeParameter(EntityType.Method, 1, "Y"), + new DefaultResolvedTypeParameter(EntityType.Method, 2, "Z") }; IType[] parameterTypes = { typeParameters[0], - new ParameterizedType(ctx.GetTypeDefinition(typeof(Func<,>)), new[] { typeParameters[0], typeParameters[1] }), - new ParameterizedType(ctx.GetTypeDefinition(typeof(Func<,>)), new[] { typeParameters[1], typeParameters[2] }) + new ParameterizedType(compilation.FindType(typeof(Func<,>)).GetDefinition(), new[] { typeParameters[0], typeParameters[1] }), + new ParameterizedType(compilation.FindType(typeof(Func<,>)).GetDefinition(), new[] { typeParameters[1], typeParameters[2] }) }; // Signature: M(X x, Func y, Func z) {} // Invocation: M(default(string), s => default(int), t => default(float)); ResolveResult[] arguments = { - new ResolveResult(KnownTypeReference.String.Resolve(ctx)), - new MockImplicitLambda(new[] { KnownTypeReference.String.Resolve(ctx) }, KnownTypeReference.Int32.Resolve(ctx)), - new MockImplicitLambda(new[] { KnownTypeReference.Int32.Resolve(ctx) }, KnownTypeReference.Single.Resolve(ctx)) + new ResolveResult(compilation.FindType(KnownTypeCode.String)), + new MockImplicitLambda(new[] { compilation.FindType(KnownTypeCode.String) }, compilation.FindType(KnownTypeCode.Int32)), + new MockImplicitLambda(new[] { compilation.FindType(KnownTypeCode.Int32) }, compilation.FindType(KnownTypeCode.Single)) }; bool success; Assert.AreEqual( new [] { - KnownTypeReference.String.Resolve(ctx), - KnownTypeReference.Int32.Resolve(ctx), - KnownTypeReference.Single.Resolve(ctx) + compilation.FindType(KnownTypeCode.String), + compilation.FindType(KnownTypeCode.Int32), + compilation.FindType(KnownTypeCode.Single) }, ti.InferTypeArguments(typeParameters, arguments, parameterTypes, out success)); Assert.IsTrue(success); @@ -230,26 +230,26 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [Test] public void ConvertAllLambdaInference() { - ITypeParameter[] classTypeParameters = { new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T") }; - ITypeParameter[] methodTypeParameters = { new DefaultTypeParameter(EntityType.Method, 0, "R") }; + ITypeParameter[] classTypeParameters = { new DefaultResolvedTypeParameter(EntityType.TypeDefinition, 0, "T") }; + ITypeParameter[] methodTypeParameters = { new DefaultResolvedTypeParameter(EntityType.Method, 0, "R") }; IType[] parameterTypes = { - new ParameterizedType(ctx.GetTypeDefinition(typeof(Converter<,>)), + new ParameterizedType(compilation.FindType(typeof(Converter<,>)).GetDefinition(), new[] { classTypeParameters[0], methodTypeParameters[0] }) }; // Signature: List.ConvertAll(Converter converter); // Invocation: listOfString.ConvertAll(s => default(int)); ResolveResult[] arguments = { - new MockImplicitLambda(new[] { KnownTypeReference.String.Resolve(ctx) }, KnownTypeReference.Int32.Resolve(ctx)) + new MockImplicitLambda(new[] { compilation.FindType(KnownTypeCode.String) }, compilation.FindType(KnownTypeCode.Int32)) }; IType[] classTypeArguments = { - KnownTypeReference.String.Resolve(ctx) + compilation.FindType(KnownTypeCode.String) }; bool success; Assert.AreEqual( - new [] { KnownTypeReference.Int32.Resolve(ctx) }, + new [] { compilation.FindType(KnownTypeCode.Int32) }, ti.InferTypeArguments(methodTypeParameters, arguments, parameterTypes, out success, classTypeArguments)); } #endregion diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnaryOperatorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnaryOperatorTests.cs index 9ab0418532..18968937e5 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnaryOperatorTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnaryOperatorTests.cs @@ -28,6 +28,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [TestFixture] public unsafe class UnaryOperatorTests : ResolverTestBase { + CSharpResolver resolver; + + public override void SetUp() + { + base.SetUp(); + resolver = new CSharpResolver(compilation); + } + [Test] public void TestAddressOf() { diff --git a/ICSharpCode.NRefactory.Tests/Documentation/IDStringTests.cs b/ICSharpCode.NRefactory.Tests/Documentation/IDStringTests.cs index cbe549f3a0..bedb76491d 100644 --- a/ICSharpCode.NRefactory.Tests/Documentation/IDStringTests.cs +++ b/ICSharpCode.NRefactory.Tests/Documentation/IDStringTests.cs @@ -30,6 +30,7 @@ namespace ICSharpCode.NRefactory.Documentation [TestFixture] public class IDStringTests { + /* class IDStringTestProjectContent : SimpleProjectContent, IDocumentationProvider { public string GetDocumentation(IEntity entity) @@ -330,6 +331,6 @@ namespace Acme IDStringProvider.GetIDString(list.Methods.Single(m => m.Name == "AddRange"))); Assert.AreEqual("M:System.Collections.Generic.List`1.ConvertAll``1(System.Converter{`0,``0})", IDStringProvider.GetIDString(list.Methods.Single(m => m.Name == "ConvertAll"))); - } + }*/ } } diff --git a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj index f6875d393a..6ad1ce4ea9 100644 --- a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj +++ b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj @@ -1,4 +1,4 @@ - + {63D3B27A-D966-4902-90B3-30290E1692F1} @@ -187,14 +187,6 @@ - - - - - - - - @@ -212,7 +204,6 @@ - \ No newline at end of file diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs index 0a3746f585..b4553fcee9 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs @@ -28,42 +28,41 @@ namespace ICSharpCode.NRefactory.TypeSystem [TestFixture] public class CecilLoaderTests : TypeSystemTests { - static readonly Lazy mscorlib = new Lazy( + static readonly Lazy mscorlib = new Lazy( delegate { return new CecilLoader().LoadAssemblyFile(typeof(object).Assembly.Location); }); - static readonly Lazy systemCore = new Lazy( + static readonly Lazy systemCore = new Lazy( delegate { return new CecilLoader().LoadAssemblyFile(typeof(System.Linq.Enumerable).Assembly.Location); }); - public static IProjectContent Mscorlib { get { return mscorlib.Value; } } - public static IProjectContent SystemCore { get { return systemCore.Value; } } - - ITypeResolveContext ctx = Mscorlib; + public static IUnresolvedAssembly Mscorlib { get { return mscorlib.Value; } } + public static IUnresolvedAssembly SystemCore { get { return systemCore.Value; } } [TestFixtureSetUp] public void FixtureSetUp() { // use "IncludeInternalMembers" so that Cecil results match C# parser results CecilLoader loader = new CecilLoader() { IncludeInternalMembers = true }; - testCasePC = loader.LoadAssemblyFile(typeof(TestCase.SimplePublicClass).Assembly.Location); + IUnresolvedAssembly asm = loader.LoadAssemblyFile(typeof(TestCase.SimplePublicClass).Assembly.Location); + compilation = new SimpleCompilation(asm, CecilLoaderTests.Mscorlib); } [Test] public void InheritanceTest() { - ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(SystemException)); - ITypeDefinition c2 = Mscorlib.GetTypeDefinition(typeof(Exception)); + ITypeDefinition c = compilation.FindType(typeof(SystemException)).GetDefinition(); + ITypeDefinition c2 = compilation.FindType(typeof(Exception)).GetDefinition(); Assert.IsNotNull(c, "c is null"); Assert.IsNotNull(c2, "c2 is null"); //Assert.AreEqual(3, c.BaseTypes.Count); // Inherited interfaces are not reported by Cecil // which matches the behaviour of our C#/VB parsers - Assert.AreEqual("System.Exception", c.BaseTypes[0].Resolve(ctx).FullName); - Assert.AreSame(c2, c.BaseTypes[0]); + Assert.AreEqual("System.Exception", c.DirectBaseTypes.First().FullName); + Assert.AreSame(c2, c.DirectBaseTypes.First()); - string[] superTypes = c.GetAllBaseTypes(ctx).Select(t => t.ToString()).ToArray(); + string[] superTypes = c.GetAllBaseTypes().Select(t => t.ToString()).ToArray(); Assert.AreEqual(new string[] { "System.Object", "System.Runtime.Serialization.ISerializable", "System.Runtime.InteropServices._Exception", @@ -74,9 +73,9 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void GenericPropertyTest() { - ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(Comparer<>)); - IProperty def = c.Properties.Single(p => p.Name == "Default"); - ParameterizedType pt = (ParameterizedType)def.ReturnType.Resolve(ctx); + ITypeDefinition c = compilation.FindType(typeof(Comparer<>)).GetDefinition(); + IProperty def = c.Members.OfType().Single(p => p.Name == "Default"); + ParameterizedType pt = (ParameterizedType)def.ReturnType; Assert.AreEqual("System.Collections.Generic.Comparer", pt.FullName); Assert.AreEqual(c.TypeParameters[0], pt.TypeArguments[0]); } @@ -84,36 +83,36 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void PointerTypeTest() { - ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(IntPtr)); + ITypeDefinition c = compilation.FindType(typeof(IntPtr)).GetDefinition(); IMethod toPointer = c.Methods.Single(p => p.Name == "ToPointer"); - Assert.AreEqual("System.Void*", toPointer.ReturnType.Resolve(ctx).ReflectionName); - Assert.IsTrue (toPointer.ReturnType.Resolve(ctx) is PointerType); - Assert.AreEqual("System.Void", ((PointerType)toPointer.ReturnType.Resolve(ctx)).ElementType.FullName); + Assert.AreEqual("System.Void*", toPointer.ReturnType.ReflectionName); + Assert.IsTrue (toPointer.ReturnType is PointerType); + Assert.AreEqual("System.Void", ((PointerType)toPointer.ReturnType).ElementType.FullName); } [Test] public void DateTimeDefaultConstructor() { - ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(DateTime)); + ITypeDefinition c = compilation.FindType(typeof(DateTime)).GetDefinition(); Assert.IsFalse(c.Methods.Any(m => m.IsConstructor && m.Parameters.Count == 0)); // struct ctor isn't declared // but it is implicit: - Assert.IsTrue(c.GetConstructors(ctx).Any(m => m.Parameters.Count == 0)); + Assert.IsTrue(c.GetConstructors().Any(m => m.Parameters.Count == 0)); } [Test] public void NoEncodingInfoDefaultConstructor() { - ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(EncodingInfo)); + ITypeDefinition c = compilation.FindType(typeof(EncodingInfo)).GetDefinition(); // EncodingInfo only has an internal constructor Assert.IsFalse(c.Methods.Any(m => m.IsConstructor)); // and no implicit ctor should be added: - Assert.AreEqual(0, c.GetConstructors(ctx).Count()); + Assert.AreEqual(0, c.GetConstructors().Count()); } [Test] public void StaticModifierTest() { - ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(Environment)); + ITypeDefinition c = compilation.FindType(typeof(Environment)).GetDefinition(); Assert.IsNotNull(c, "System.Environment not found"); Assert.IsTrue(c.IsAbstract, "class should be abstract"); Assert.IsTrue(c.IsSealed, "class should be sealed"); @@ -123,16 +122,16 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void InnerClassReferenceTest() { - ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(Environment)); + ITypeDefinition c = compilation.FindType(typeof(Environment)).GetDefinition(); Assert.IsNotNull(c, "System.Environment not found"); - ITypeReference rt = c.Methods.First(m => m.Name == "GetFolderPath").Parameters[0].Type; - Assert.AreSame(c.NestedTypes.Single(ic => ic.Name == "SpecialFolder"), rt.Resolve(ctx)); + IType rt = c.Members.OfType().First(m => m.Name == "GetFolderPath").Parameters[0].Type; + Assert.AreSame(c.NestedTypes.Single(ic => ic.Name == "SpecialFolder"), rt); } [Test] public void NestedTypesTest() { - ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(Environment.SpecialFolder)); + ITypeDefinition c = compilation.FindType(typeof(Environment.SpecialFolder)).GetDefinition(); Assert.IsNotNull(c, "c is null"); Assert.AreEqual("System.Environment.SpecialFolder", c.FullName); Assert.AreEqual("System.Environment+SpecialFolder", c.ReflectionName); @@ -141,12 +140,12 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void VoidTest() { - ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(void)); + ITypeDefinition c = compilation.FindType(typeof(void)).GetDefinition(); Assert.IsNotNull(c, "System.Void not found"); - Assert.AreEqual(0, c.GetMethods(ctx).Count()); - Assert.AreEqual(0, c.GetProperties(ctx).Count()); - Assert.AreEqual(0, c.GetEvents(ctx).Count()); - Assert.AreEqual(0, c.GetFields(ctx).Count()); + Assert.AreEqual(0, c.GetMethods().Count()); + Assert.AreEqual(0, c.GetProperties().Count()); + Assert.AreEqual(0, c.GetEvents().Count()); + Assert.AreEqual(0, c.GetFields().Count()); Assert.AreEqual( new string[] { "[System.SerializableAttribute]", @@ -159,13 +158,13 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void NestedClassInGenericClassTest() { - ITypeDefinition dictionary = Mscorlib.GetTypeDefinition(typeof(Dictionary<,>)); + ITypeDefinition dictionary = compilation.FindType(typeof(Dictionary<,>)).GetDefinition(); Assert.IsNotNull(dictionary); - ITypeDefinition valueCollection = Mscorlib.GetTypeDefinition(typeof(Dictionary<,>.ValueCollection)); + ITypeDefinition valueCollection = compilation.FindType(typeof(Dictionary<,>.ValueCollection)).GetDefinition(); Assert.IsNotNull(valueCollection); - var dictionaryRT = new ParameterizedType(dictionary, new[] { Mscorlib.GetTypeDefinition(typeof(string)), Mscorlib.GetTypeDefinition(typeof(int)) }); - IProperty valueProperty = dictionaryRT.GetProperties(ctx).Single(p => p.Name == "Values"); - IType parameterizedValueCollection = valueProperty.ReturnType.Resolve(ctx); + var dictionaryRT = new ParameterizedType(dictionary, new[] { compilation.FindType(typeof(string)).GetDefinition(), compilation.FindType(typeof(int)).GetDefinition() }); + IProperty valueProperty = dictionaryRT.GetProperties().Single(p => p.Name == "Values"); + IType parameterizedValueCollection = valueProperty.ReturnType; Assert.AreEqual("System.Collections.Generic.Dictionary`2+ValueCollection[[System.String],[System.Int32]]", parameterizedValueCollection.ReflectionName); Assert.AreSame(valueCollection, parameterizedValueCollection.GetDefinition()); } @@ -173,7 +172,7 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void ValueCollectionCountModifiers() { - ITypeDefinition valueCollection = Mscorlib.GetTypeDefinition(typeof(Dictionary<,>.ValueCollection)); + ITypeDefinition valueCollection = compilation.FindType(typeof(Dictionary<,>.ValueCollection)).GetDefinition(); Assert.AreEqual(Accessibility.Public, valueCollection.Accessibility); Assert.IsTrue(valueCollection.IsSealed); Assert.IsFalse(valueCollection.IsAbstract); @@ -190,7 +189,7 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void MathAcosModifiers() { - ITypeDefinition math = Mscorlib.GetTypeDefinition(typeof(Math)); + ITypeDefinition math = compilation.FindType(typeof(Math)).GetDefinition(); Assert.AreEqual(Accessibility.Public, math.Accessibility); Assert.IsTrue(math.IsSealed); Assert.IsTrue(math.IsAbstract); @@ -208,7 +207,7 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void EncodingModifiers() { - ITypeDefinition encoding = Mscorlib.GetTypeDefinition(typeof(Encoding)); + ITypeDefinition encoding = compilation.FindType(typeof(Encoding)).GetDefinition(); Assert.AreEqual(Accessibility.Public, encoding.Accessibility); Assert.IsFalse(encoding.IsSealed); Assert.IsTrue(encoding.IsAbstract); @@ -241,7 +240,7 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void UnicodeEncodingModifiers() { - ITypeDefinition encoding = Mscorlib.GetTypeDefinition(typeof(UnicodeEncoding)); + ITypeDefinition encoding = compilation.FindType(typeof(UnicodeEncoding)).GetDefinition(); Assert.AreEqual(Accessibility.Public, encoding.Accessibility); Assert.IsFalse(encoding.IsSealed); Assert.IsFalse(encoding.IsAbstract); @@ -258,7 +257,7 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void UTF32EncodingModifiers() { - ITypeDefinition encoding = Mscorlib.GetTypeDefinition(typeof(UTF32Encoding)); + ITypeDefinition encoding = compilation.FindType(typeof(UTF32Encoding)).GetDefinition(); Assert.AreEqual(Accessibility.Public, encoding.Accessibility); Assert.IsTrue(encoding.IsSealed); Assert.IsFalse(encoding.IsAbstract); diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs index c6bac492c4..fefe09fb97 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs @@ -31,17 +31,16 @@ namespace ICSharpCode.NRefactory.TypeSystem [TestFixture] public class GetAllBaseTypesTest { - IProjectContent mscorlib = CecilLoaderTests.Mscorlib; - ITypeResolveContext context = CecilLoaderTests.Mscorlib; + ICompilation compilation = new SimpleCompilation(CecilLoaderTests.Mscorlib); IType[] GetAllBaseTypes(Type type) { - return type.ToTypeReference().Resolve(context).GetAllBaseTypes(context).OrderBy(t => t.ReflectionName).ToArray(); + return compilation.FindType(type).GetAllBaseTypes().OrderBy(t => t.ReflectionName).ToArray(); } IType[] GetTypes(params Type[] types) { - return types.Select(t => t.ToTypeReference().Resolve(context)).OrderBy(t => t.ReflectionName).ToArray();; + return types.Select(t => compilation.FindType(t)).OrderBy(t => t.ReflectionName).ToArray();; } [Test] @@ -81,48 +80,53 @@ namespace ICSharpCode.NRefactory.TypeSystem public void ClassDerivingFromItself() { // class C : C {} - DefaultTypeDefinition c = new DefaultTypeDefinition(mscorlib, string.Empty, "C"); + var c = new DefaultUnresolvedTypeDefinition(string.Empty, "C"); c.BaseTypes.Add(c); - Assert.AreEqual(new [] { c }, c.GetAllBaseTypes(context).ToArray()); + ITypeDefinition resolvedC = c.Resolve(compilation.TypeResolveContext); + Assert.AreEqual(new [] { resolvedC }, resolvedC.GetAllBaseTypes().ToArray()); } [Test] public void TwoClassesDerivingFromEachOther() { // class C1 : C2 {} class C2 : C1 {} - DefaultTypeDefinition c1 = new DefaultTypeDefinition(mscorlib, string.Empty, "C1"); - DefaultTypeDefinition c2 = new DefaultTypeDefinition(mscorlib, string.Empty, "C2"); + var c1 = new DefaultUnresolvedTypeDefinition(string.Empty, "C1"); + var c2 = new DefaultUnresolvedTypeDefinition(string.Empty, "C2"); c1.BaseTypes.Add(c2); c2.BaseTypes.Add(c1); - Assert.AreEqual(new [] { c2, c1 }, c1.GetAllBaseTypes(context).ToArray()); + ITypeDefinition resolvedC1 = c1.Resolve(compilation.TypeResolveContext); + ITypeDefinition resolvedC2 = c2.Resolve(compilation.TypeResolveContext); + Assert.AreEqual(new [] { resolvedC2, resolvedC1 }, resolvedC1.GetAllBaseTypes().ToArray()); } [Test] public void ClassDerivingFromParameterizedVersionOfItself() { // class C : C> {} - DefaultTypeDefinition c = new DefaultTypeDefinition(mscorlib, string.Empty, "C"); - c.TypeParameters.Add(new DefaultTypeParameter(EntityType.TypeDefinition, 0, "X")); - c.BaseTypes.Add(new ParameterizedType(c, new [] { new ParameterizedType(c, new [] { c.TypeParameters[0] }) })); - Assert.AreEqual(new [] { c }, c.GetAllBaseTypes(context).ToArray()); + var c = new DefaultUnresolvedTypeDefinition(string.Empty, "C"); + c.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, 0, "X")); + c.BaseTypes.Add(new ParameterizedTypeReference(c, new [] { new ParameterizedTypeReference(c, new [] { new TypeParameterReference(EntityType.TypeDefinition, 0) }) })); + ITypeDefinition resolvedC = c.Resolve(compilation.TypeResolveContext); + Assert.AreEqual(new [] { resolvedC }, resolvedC.GetAllBaseTypes().ToArray()); } [Test] public void ClassDerivingFromTwoInstanciationsOfIEnumerable() { // class C : IEnumerable, IEnumerable {} - DefaultTypeDefinition c = new DefaultTypeDefinition(mscorlib, string.Empty, "C"); + var c = new DefaultUnresolvedTypeDefinition(string.Empty, "C"); c.BaseTypes.Add(typeof(IEnumerable).ToTypeReference()); c.BaseTypes.Add(typeof(IEnumerable).ToTypeReference()); + ITypeDefinition resolvedC = c.Resolve(compilation.TypeResolveContext); IType[] expected = { - c, - c.BaseTypes[0].Resolve(context), - c.BaseTypes[1].Resolve(context), - mscorlib.GetTypeDefinition(typeof(IEnumerable)), - mscorlib.GetTypeDefinition(typeof(object)) + resolvedC, + compilation.FindType(typeof(IEnumerable)), + compilation.FindType(typeof(IEnumerable)), + compilation.FindType(typeof(IEnumerable)), + compilation.FindType(typeof(object)) }; Assert.AreEqual(expected, - c.GetAllBaseTypes(context).OrderBy(t => t.ReflectionName).ToArray()); + resolvedC.GetAllBaseTypes().OrderBy(t => t.ReflectionName).ToArray()); } [Test] @@ -130,17 +134,18 @@ namespace ICSharpCode.NRefactory.TypeSystem { // struct S : IEquatable {} // don't use a Cecil-loaded struct for this test; we're testing the implicit addition of System.ValueType - DefaultTypeDefinition s = new DefaultTypeDefinition(mscorlib, string.Empty, "S"); + var s = new DefaultUnresolvedTypeDefinition(string.Empty, "S"); s.Kind = TypeKind.Struct; - s.BaseTypes.Add(new ParameterizedType(mscorlib.GetTypeDefinition(typeof(IEquatable<>)), new[] { s })); + s.BaseTypes.Add(new ParameterizedTypeReference(typeof(IEquatable<>).ToTypeReference(), new[] { s })); + ITypeDefinition resolvedS = s.Resolve(compilation.TypeResolveContext); IType[] expected = { - s, - s.BaseTypes[0].Resolve(context), - mscorlib.GetTypeDefinition(typeof(object)), - mscorlib.GetTypeDefinition(typeof(ValueType)) + resolvedS, + s.BaseTypes[0].Resolve(compilation.TypeResolveContext), + compilation.FindType(typeof(object)), + compilation.FindType(typeof(ValueType)) }; Assert.AreEqual(expected, - s.GetAllBaseTypes(context).OrderBy(t => t.ReflectionName).ToArray()); + resolvedS.GetAllBaseTypes().OrderBy(t => t.ReflectionName).ToArray()); } [Test] @@ -179,7 +184,7 @@ namespace ICSharpCode.NRefactory.TypeSystem GetTypes(typeof(List<>), typeof(object), typeof(IList), typeof(ICollection), typeof(IEnumerable), typeof(IEnumerable<>), typeof(ICollection<>), typeof(IList<>)), - typeof(List).ToTypeReference().Resolve(context).GetAllBaseTypeDefinitions(context).OrderBy(t => t.ReflectionName).ToArray()); + compilation.FindType(typeof(List)).GetAllBaseTypeDefinitions().OrderBy(t => t.ReflectionName).ToArray()); } [Test] @@ -190,7 +195,7 @@ namespace ICSharpCode.NRefactory.TypeSystem typeof(ICloneable), typeof(IStructuralComparable), typeof(IStructuralEquatable), typeof(IList), typeof(ICollection), typeof(IEnumerable), typeof(IEnumerable<>), typeof(ICollection<>), typeof(IList<>)), - typeof(string[]).ToTypeReference().Resolve(context).GetAllBaseTypeDefinitions(context).OrderBy(t => t.ReflectionName).ToArray()); + compilation.FindType(typeof(string[])).GetAllBaseTypeDefinitions().OrderBy(t => t.ReflectionName).ToArray()); } } } diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/GetMembersTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/GetMembersTests.cs index 2c10f4b846..f6984a8f84 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/GetMembersTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/GetMembersTests.cs @@ -27,72 +27,73 @@ namespace ICSharpCode.NRefactory.TypeSystem [TestFixture] public class GetMembersTests { - IProjectContent mscorlib = CecilLoaderTests.Mscorlib; + ICompilation compilation = new SimpleCompilation(CecilLoaderTests.Mscorlib); [Test] public void EmptyClassHasToString() { - DefaultTypeDefinition c = new DefaultTypeDefinition(mscorlib, string.Empty, "C"); - Assert.AreEqual("System.Object.ToString", c.GetMethods(mscorlib, m => m.Name == "ToString").Single().FullName); + DefaultUnresolvedTypeDefinition c = new DefaultUnresolvedTypeDefinition(string.Empty, "C"); + Assert.AreEqual("System.Object.ToString", c.Resolve(compilation.TypeResolveContext).GetMethods(m => m.Name == "ToString").Single().FullName); } [Test] public void MultipleInheritanceTest() { - DefaultTypeDefinition b1 = new DefaultTypeDefinition(mscorlib, string.Empty, "B1"); + DefaultUnresolvedTypeDefinition b1 = new DefaultUnresolvedTypeDefinition(string.Empty, "B1"); b1.Kind = TypeKind.Interface; - b1.Properties.Add(new DefaultProperty(b1, "P1")); + b1.Members.Add(new DefaultUnresolvedProperty(b1, "P1")); - DefaultTypeDefinition b2 = new DefaultTypeDefinition(mscorlib, string.Empty, "B2"); + DefaultUnresolvedTypeDefinition b2 = new DefaultUnresolvedTypeDefinition(string.Empty, "B2"); b2.Kind = TypeKind.Interface; - b2.Properties.Add(new DefaultProperty(b1, "P2")); + b2.Members.Add(new DefaultUnresolvedProperty(b2, "P2")); - DefaultTypeDefinition c = new DefaultTypeDefinition(mscorlib, string.Empty, "C"); + DefaultUnresolvedTypeDefinition c = new DefaultUnresolvedTypeDefinition(string.Empty, "C"); c.Kind = TypeKind.Interface; c.BaseTypes.Add(b1); c.BaseTypes.Add(b2); - Assert.AreEqual(new[] { "P1", "P2" }, c.GetProperties(mscorlib).Select(p => p.Name).ToArray()); + ITypeDefinition resolvedC = c.Resolve(compilation.TypeResolveContext); + Assert.AreEqual(new[] { "P1", "P2" }, resolvedC.GetProperties().Select(p => p.Name).ToArray()); // Test that there's only one copy of ToString(): - Assert.AreEqual(1, c.GetMethods(mscorlib, m => m.Name == "ToString").Count()); + Assert.AreEqual(1, resolvedC.GetMethods(m => m.Name == "ToString").Count()); } [Test] public void ArrayType() { - IType arrayType = typeof(string[]).ToTypeReference().Resolve(mscorlib); + IType arrayType = compilation.FindType(typeof(string[])); // Array inherits ToString() from System.Object - Assert.AreEqual("System.Object.ToString", arrayType.GetMethods(mscorlib, m => m.Name == "ToString").Single().FullName); - Assert.AreEqual("System.Array.GetLowerBound", arrayType.GetMethods(mscorlib, m => m.Name == "GetLowerBound").Single().FullName); - Assert.AreEqual("System.Array.Length", arrayType.GetProperties(mscorlib, p => p.Name == "Length").Single().FullName); + Assert.AreEqual("System.Object.ToString", arrayType.GetMethods(m => m.Name == "ToString").Single().FullName); + Assert.AreEqual("System.Array.GetLowerBound", arrayType.GetMethods(m => m.Name == "GetLowerBound").Single().FullName); + Assert.AreEqual("System.Array.Length", arrayType.GetProperties(p => p.Name == "Length").Single().FullName); // test indexer - IProperty indexer = arrayType.GetProperties(mscorlib, p => p.IsIndexer).Single(); + IProperty indexer = arrayType.GetProperties(p => p.IsIndexer).Single(); Assert.AreEqual("System.Array.Items", indexer.FullName); - Assert.AreEqual("System.String", indexer.ReturnType.Resolve(mscorlib).ReflectionName); + Assert.AreEqual("System.String", indexer.ReturnType.ReflectionName); Assert.AreEqual(1, indexer.Parameters.Count); - Assert.AreEqual("System.Int32", indexer.Parameters[0].Type.Resolve(mscorlib).ReflectionName); + Assert.AreEqual("System.Int32", indexer.Parameters[0].Type.ReflectionName); } [Test] public void MultidimensionalArrayType() { - IType arrayType = typeof(string[,][]).ToTypeReference().Resolve(mscorlib); + IType arrayType = compilation.FindType(typeof(string[,][])); // test indexer - IProperty indexer = arrayType.GetProperties(mscorlib, p => p.IsIndexer).Single(); + IProperty indexer = arrayType.GetProperties(p => p.IsIndexer).Single(); Assert.AreEqual("System.Array.Items", indexer.FullName); - Assert.AreEqual("System.String[]", indexer.ReturnType.Resolve(mscorlib).ReflectionName); + Assert.AreEqual("System.String[]", indexer.ReturnType.ReflectionName); Assert.AreEqual(2, indexer.Parameters.Count); - Assert.AreEqual("System.Int32", indexer.Parameters[0].Type.Resolve(mscorlib).ReflectionName); - Assert.AreEqual("System.Int32", indexer.Parameters[1].Type.Resolve(mscorlib).ReflectionName); + Assert.AreEqual("System.Int32", indexer.Parameters[0].Type.ReflectionName); + Assert.AreEqual("System.Int32", indexer.Parameters[1].Type.ReflectionName); } [Test] public void GetNestedTypesOfUnboundGenericClass() { - ITypeDefinition dictionary = mscorlib.GetTypeDefinition(typeof(Dictionary<,>)); - IType keyCollection = dictionary.GetNestedTypes(mscorlib).Single(t => t.Name == "KeyCollection"); + ITypeDefinition dictionary = compilation.FindType(typeof(Dictionary<,>)).GetDefinition(); + IType keyCollection = dictionary.GetNestedTypes().Single(t => t.Name == "KeyCollection"); // the type should be parameterized Assert.AreEqual("System.Collections.Generic.Dictionary`2+KeyCollection[[`0],[`1]]", keyCollection.ReflectionName); } @@ -100,29 +101,32 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void GetNestedTypesOfBoundGenericClass() { - IType dictionary = typeof(Dictionary).ToTypeReference().Resolve(mscorlib); - IType keyCollection = dictionary.GetNestedTypes(mscorlib).Single(t => t.Name == "KeyCollection"); - Assert.AreEqual(typeof(Dictionary.KeyCollection).ToTypeReference().Resolve(mscorlib), keyCollection); + IType dictionary = compilation.FindType(typeof(Dictionary)); + IType keyCollection = dictionary.GetNestedTypes().Single(t => t.Name == "KeyCollection"); + Assert.AreEqual(compilation.FindType(typeof(Dictionary.KeyCollection)), keyCollection); } [Test] public void GetGenericNestedTypeOfBoundGenericClass() { // class A { class B { } } - DefaultTypeDefinition a = new DefaultTypeDefinition(mscorlib, string.Empty, "A"); - a.TypeParameters.Add(new DefaultTypeParameter(EntityType.TypeDefinition, 0, "X")); + DefaultUnresolvedTypeDefinition a = new DefaultUnresolvedTypeDefinition(string.Empty, "A"); + a.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, 0, "X")); - DefaultTypeDefinition b = new DefaultTypeDefinition(a, "B"); + DefaultUnresolvedTypeDefinition b = new DefaultUnresolvedTypeDefinition(a, "B"); b.TypeParameters.Add(a.TypeParameters[0]); - b.TypeParameters.Add(new DefaultTypeParameter(EntityType.TypeDefinition, 1, "Y")); + b.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, 1, "Y")); a.NestedTypes.Add(b); + ITypeDefinition resolvedA = a.Resolve(compilation.TypeResolveContext); + ITypeDefinition resolvedB = b.Resolve(compilation.TypeResolveContext); + // A<> gets self-parameterized, B<> stays unbound - Assert.AreEqual("A`1+B`1[[`0],[]]", a.GetNestedTypes(mscorlib).Single().ReflectionName); + Assert.AreEqual("A`1+B`1[[`0],[]]", resolvedA.GetNestedTypes().Single().ReflectionName); - ParameterizedType pt = new ParameterizedType(a, new [] { KnownTypeReference.String.Resolve(mscorlib) }); - Assert.AreEqual("A`1+B`1[[System.String],[]]", pt.GetNestedTypes(mscorlib).Single().ReflectionName); + ParameterizedType pt = new ParameterizedType(resolvedA, new [] { compilation.FindType(KnownTypeCode.String) }); + Assert.AreEqual("A`1+B`1[[System.String],[]]", pt.GetNestedTypes().Single().ReflectionName); } } } diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/ReflectionHelperTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/ReflectionHelperTests.cs index 08dc839129..93aa3a9faa 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/ReflectionHelperTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/ReflectionHelperTests.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using ICSharpCode.NRefactory.TypeSystem.Implementation; using NUnit.Framework; namespace ICSharpCode.NRefactory.TypeSystem @@ -27,11 +28,11 @@ namespace ICSharpCode.NRefactory.TypeSystem [TestFixture] public unsafe class ReflectionHelperTests { - ITypeResolveContext context = CecilLoaderTests.Mscorlib; + ICompilation compilation = new SimpleCompilation(CecilLoaderTests.Mscorlib); - void TestGetClass(Type type) + void TestFindType(Type type) { - ITypeDefinition t = CecilLoaderTests.Mscorlib.GetTypeDefinition(type); + IType t = compilation.FindType(type); Assert.IsNotNull(t, type.FullName); Assert.AreEqual(type.FullName, t.ReflectionName); } @@ -39,56 +40,56 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void TestGetInnerClass() { - TestGetClass(typeof(Environment.SpecialFolder)); + TestFindType(typeof(Environment.SpecialFolder)); } [Test] public void TestGetGenericClass1() { - TestGetClass(typeof(Action<>)); + TestFindType(typeof(Action<>)); } [Test] public void TestGetGenericClass2() { - TestGetClass(typeof(Action<,>)); + TestFindType(typeof(Action<,>)); } [Test] public void TestGetInnerClassInGenericClass1() { - TestGetClass(typeof(Dictionary<,>.ValueCollection)); + TestFindType(typeof(Dictionary<,>.ValueCollection)); } [Test] public void TestGetInnerClassInGenericClass2() { - TestGetClass(typeof(Dictionary<,>.ValueCollection.Enumerator)); + TestFindType(typeof(Dictionary<,>.ValueCollection.Enumerator)); } [Test] public void TestToTypeReferenceInnerClass() { Assert.AreEqual("System.Environment+SpecialFolder", - typeof(Environment.SpecialFolder).ToTypeReference().Resolve(context).ReflectionName); + compilation.FindType(typeof(Environment.SpecialFolder)).ReflectionName); } [Test] public void TestToTypeReferenceUnboundGenericClass() { Assert.AreEqual("System.Action`1", - typeof(Action<>).ToTypeReference().Resolve(context).ReflectionName); + compilation.FindType(typeof(Action<>)).ReflectionName); Assert.AreEqual("System.Action`2", - typeof(Action<,>).ToTypeReference().Resolve(context).ReflectionName); + compilation.FindType(typeof(Action<,>)).ReflectionName); } [Test] public void TestToTypeReferenceBoundGenericClass() { Assert.AreEqual("System.Action`1[[System.String]]", - typeof(Action).ToTypeReference().Resolve(context).ReflectionName); + compilation.FindType(typeof(Action)).ReflectionName); Assert.AreEqual("System.Action`2[[System.Int32],[System.Int16]]", - typeof(Action).ToTypeReference().Resolve(context).ReflectionName); + compilation.FindType(typeof(Action)).ReflectionName); } @@ -96,75 +97,77 @@ namespace ICSharpCode.NRefactory.TypeSystem public void TestToTypeReferenceNullableType() { Assert.AreEqual("System.Nullable`1[[System.Int32]]", - typeof(int?).ToTypeReference().Resolve(context).ReflectionName); + compilation.FindType(typeof(int?)).ReflectionName); } [Test] public void TestToTypeReferenceInnerClassInUnboundGenericType() { Assert.AreEqual("System.Collections.Generic.Dictionary`2+ValueCollection", - typeof(Dictionary<,>.ValueCollection).ToTypeReference().Resolve(context).ReflectionName); + compilation.FindType(typeof(Dictionary<,>.ValueCollection)).ReflectionName); } [Test] public void TestToTypeReferenceInnerClassInBoundGenericType() { Assert.AreEqual("System.Collections.Generic.Dictionary`2+KeyCollection[[System.String],[System.Int32]]", - typeof(Dictionary.KeyCollection).ToTypeReference().Resolve(context).ReflectionName); + compilation.FindType(typeof(Dictionary.KeyCollection)).ReflectionName); } [Test] public void TestToTypeReferenceArrayType() { Assert.AreEqual(typeof(int[]).FullName, - typeof(int[]).ToTypeReference().Resolve(context).ReflectionName); + compilation.FindType(typeof(int[])).ReflectionName); } [Test] public void TestToTypeReferenceMultidimensionalArrayType() { Assert.AreEqual(typeof(int[,]).FullName, - typeof(int[,]).ToTypeReference().Resolve(context).ReflectionName); + compilation.FindType(typeof(int[,])).ReflectionName); } [Test] public void TestToTypeReferenceJaggedMultidimensionalArrayType() { Assert.AreEqual(typeof(int[,][,,]).FullName, - typeof(int[,][,,]).ToTypeReference().Resolve(context).ReflectionName); + compilation.FindType(typeof(int[,][,,])).ReflectionName); } [Test] public void TestToTypeReferencePointerType() { Assert.AreEqual(typeof(int*).FullName, - typeof(int*).ToTypeReference().Resolve(context).ReflectionName); + compilation.FindType(typeof(int*)).ReflectionName); } [Test] public void TestToTypeReferenceByReferenceType() { Assert.AreEqual(typeof(int).MakeByRefType().FullName, - typeof(int).MakeByRefType().ToTypeReference().Resolve(context).ReflectionName); + compilation.FindType(typeof(int).MakeByRefType()).ReflectionName); } [Test] public void TestToTypeReferenceGenericType() { MethodInfo convertAllInfo = typeof(List<>).GetMethod("ConvertAll"); - Type parameterType = convertAllInfo.GetParameters()[0].ParameterType; // Converter[[`0],[``0]] + ITypeReference parameterType = convertAllInfo.GetParameters()[0].ParameterType.ToTypeReference(); // Converter[[`0],[``0]] // cannot resolve generic types without knowing the parent entity: Assert.AreEqual("System.Converter`2[[?],[?]]", - parameterType.ToTypeReference().Resolve(context).ReflectionName); + parameterType.Resolve(compilation.TypeResolveContext).ReflectionName); // now try with parent entity: - IMethod convertAll = context.GetTypeDefinition(typeof(List<>)).Methods.Single(m => m.Name == "ConvertAll"); - Assert.AreEqual("System.Converter`2[[`0],[``0]]", - parameterType.ToTypeReference(entity: convertAll).Resolve(context).ReflectionName); + IMethod convertAll = compilation.FindType(typeof(List<>)).GetMethods(m => m.Name == "ConvertAll").Single(); + throw new NotImplementedException(); + //Assert.AreEqual("System.Converter`2[[`0],[``0]]", + // parameterType.Resolve(convertAll.TypeResolveContext).ReflectionName); } [Test] public void ParseReflectionName() { + var context = compilation.TypeResolveContext; Assert.AreEqual("System.Int32", ReflectionHelper.ParseReflectionName("System.Int32").Resolve(context).ReflectionName); Assert.AreEqual("System.Int32&", ReflectionHelper.ParseReflectionName("System.Int32&").Resolve(context).ReflectionName); Assert.AreEqual("System.Int32*&", ReflectionHelper.ParseReflectionName("System.Int32*&").Resolve(context).ReflectionName); @@ -178,9 +181,11 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void ParseOpenGenericReflectionName() { - IMethod convertAll = context.GetTypeDefinition(typeof(List<>)).Methods.Single(m => m.Name == "ConvertAll"); - Assert.AreEqual("System.Converter`2[[?],[?]]", ReflectionHelper.ParseReflectionName("System.Converter`2[[`0],[``0]]").Resolve(context).ReflectionName); - Assert.AreEqual("System.Converter`2[[`0],[``0]]", ReflectionHelper.ParseReflectionName("System.Converter`2[[`0],[``0]]", convertAll).Resolve(context).ReflectionName); + ITypeReference typeRef = ReflectionHelper.ParseReflectionName("System.Converter`2[[`0],[``0]]"); + Assert.AreEqual("System.Converter`2[[?],[?]]", typeRef.Resolve(compilation.TypeResolveContext).ReflectionName); + IMethod convertAll = compilation.FindType(typeof(List<>)).GetMethods(m => m.Name == "ConvertAll").Single(); + throw new NotImplementedException(); + //Assert.AreEqual("System.Converter`2[[`0],[``0]]", typeRef.Resolve(convertAll).ReflectionName); } [Test, ExpectedException(typeof(ArgumentNullException))] diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/SerializedCecilLoaderTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/SerializedCecilLoaderTests.cs index 9bbafb8516..5d39409036 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/SerializedCecilLoaderTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/SerializedCecilLoaderTests.cs @@ -18,6 +18,7 @@ using System; using System.IO; +using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.Utils; using NUnit.Framework; @@ -30,12 +31,13 @@ namespace ICSharpCode.NRefactory.TypeSystem public void FixtureSetUp() { CecilLoader loader = new CecilLoader() { IncludeInternalMembers = true }; - IProjectContent pc = loader.LoadAssemblyFile(typeof(TestCase.SimplePublicClass).Assembly.Location); + IUnresolvedAssembly pc = loader.LoadAssemblyFile(typeof(TestCase.SimplePublicClass).Assembly.Location); FastSerializer serializer = new FastSerializer(); using (MemoryStream ms = new MemoryStream()) { serializer.Serialize(ms, pc); ms.Position = 0; - testCasePC = (IProjectContent)serializer.Deserialize(ms); + var asm = (IUnresolvedAssembly)serializer.Deserialize(ms); + base.compilation = new SimpleCompilation(asm, CecilLoaderTests.Mscorlib); } } } diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/StructureTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/StructureTests.cs index ee797478b1..dcdc3ec405 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/StructureTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/StructureTests.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Reflection; using NUnit.Framework; namespace ICSharpCode.NRefactory.TypeSystem @@ -33,5 +34,41 @@ namespace ICSharpCode.NRefactory.TypeSystem } } } + + [Test] + public void System_TypeCode_corresponds_with_KnownTypeCode() + { + foreach (TypeCode typeCode in Enum.GetValues(typeof(System.TypeCode))) { + if (typeCode == TypeCode.Empty) + Assert.AreEqual("None", ((KnownTypeCode)typeCode).ToString()); + else + Assert.AreEqual(typeCode.ToString(), ((KnownTypeCode)typeCode).ToString()); + } + } + + [Test] + public void KnownTypeReference_Get_returns_correct_KnownType() + { + foreach (KnownTypeCode typeCode in Enum.GetValues(typeof(KnownTypeCode))) { + if (typeCode == KnownTypeCode.None) { + Assert.IsNull(KnownTypeReference.Get(KnownTypeCode.None)); + } else { + Assert.AreEqual(typeCode, KnownTypeReference.Get(typeCode).KnownTypeCode); + } + } + } + + [Test] + public void KnownTypeReference_has_static_fields_for_KnownTypes() + { + foreach (KnownTypeCode typeCode in Enum.GetValues(typeof(KnownTypeCode))) { + if (typeCode == KnownTypeCode.None) + continue; + FieldInfo field = typeof(KnownTypeReference).GetField(typeCode.ToString()); + Assert.IsNotNull(field, "Missing field for " + typeCode.ToString()); + KnownTypeReference ktr = (KnownTypeReference)field.GetValue(null); + Assert.AreEqual(typeCode, ktr.KnownTypeCode); + } + } } } diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeParameterTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeParameterTests.cs index 8c063289e3..1677954072 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeParameterTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeParameterTests.cs @@ -30,58 +30,54 @@ namespace ICSharpCode.NRefactory.TypeSystem public void TypeParameterDerivingFromOtherTypeParameterDoesNotInheritReferenceConstraint() { // class C where T : class where U : T - DefaultTypeDefinition c = new DefaultTypeDefinition(MinimalResolveContext.Instance, string.Empty, "C"); - DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); - DefaultTypeParameter u = new DefaultTypeParameter(EntityType.TypeDefinition, 1, "U"); - c.TypeParameters.Add(t); - c.TypeParameters.Add(u); - t.HasReferenceTypeConstraint = true; - u.Constraints.Add(t); + var c = new DefaultUnresolvedTypeDefinition(string.Empty, "C"); + c.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, 0, "T") { HasReferenceTypeConstraint = true }); + c.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, 1, "U") { + Constraints = { new TypeParameterReference(EntityType.TypeDefinition, 0) } + }); + ITypeDefinition resolvedC = c.Resolve(new SimpleCompilation(CecilLoaderTests.Mscorlib).TypeResolveContext); // At runtime, we might have T=System.ValueType and U=int, so C# can't inherit the 'class' constraint // from one type parameter to another. - Assert.AreEqual(true, t.IsReferenceType(MinimalResolveContext.Instance)); - Assert.IsNull(u.IsReferenceType(MinimalResolveContext.Instance)); + Assert.AreEqual(true, resolvedC.TypeParameters[0].IsReferenceType); + Assert.IsNull(resolvedC.TypeParameters[1].IsReferenceType); } [Test] public void ValueTypeParameterDerivingFromReferenceTypeParameter() { - // class C where T : class where U : T - DefaultTypeDefinition c = new DefaultTypeDefinition(MinimalResolveContext.Instance, string.Empty, "C"); - DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); - DefaultTypeParameter u = new DefaultTypeParameter(EntityType.TypeDefinition, 1, "U"); - c.TypeParameters.Add(t); - c.TypeParameters.Add(u); - t.HasReferenceTypeConstraint = true; - u.HasValueTypeConstraint = true; - u.Constraints.Add(t); + // class C where T : class where U : struct, T + var c = new DefaultUnresolvedTypeDefinition(string.Empty, "C"); + c.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, 0, "T") { HasReferenceTypeConstraint = true }); + c.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, 1, "U") { + HasValueTypeConstraint = true, + Constraints = { new TypeParameterReference(EntityType.TypeDefinition, 0) } + }); + ITypeDefinition resolvedC = c.Resolve(new SimpleCompilation(CecilLoaderTests.Mscorlib).TypeResolveContext); // At runtime, we might have T=System.ValueType and U=int, so C# can't inherit the 'class' constraint // from one type parameter to another. - Assert.AreEqual(true, t.IsReferenceType(MinimalResolveContext.Instance)); - Assert.AreEqual(false, u.IsReferenceType(MinimalResolveContext.Instance)); + Assert.AreEqual(true, resolvedC.TypeParameters[0].IsReferenceType); + Assert.AreEqual(false, resolvedC.TypeParameters[1].IsReferenceType); } [Test] public void TypeParameterDerivingFromOtherTypeParameterInheritsEffectiveBaseClass() { - // class C where T : class where U : T - ITypeResolveContext context = CecilLoaderTests.Mscorlib; - DefaultTypeDefinition c = new DefaultTypeDefinition(CecilLoaderTests.Mscorlib, string.Empty, "C"); - DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); - DefaultTypeParameter u = new DefaultTypeParameter(EntityType.TypeDefinition, 1, "U"); - c.TypeParameters.Add(t); - c.TypeParameters.Add(u); - t.Constraints.Add(typeof(List).ToTypeReference()); - u.Constraints.Add(t); + // class C where T : List where U : T + var c = new DefaultUnresolvedTypeDefinition(string.Empty, "C"); + c.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, 0, "T") { + Constraints = { typeof(List).ToTypeReference() } + }); + c.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, 1, "U") { + Constraints = { new TypeParameterReference(EntityType.TypeDefinition, 0) } + }); - // At runtime, we might have T=System.ValueType and U=int, so C# can't inherit the 'class' constraint - // from one type parameter to another. - Assert.AreEqual(true, t.IsReferenceType(context)); - Assert.AreEqual(true, u.IsReferenceType(context)); - Assert.AreEqual("System.Collections.Generic.List`1[[System.String]]", t.GetEffectiveBaseClass(context).ReflectionName); - Assert.AreEqual("System.Collections.Generic.List`1[[System.String]]", u.GetEffectiveBaseClass(context).ReflectionName); + ITypeDefinition resolvedC = c.Resolve(new SimpleCompilation(CecilLoaderTests.Mscorlib).TypeResolveContext); + Assert.AreEqual(true, resolvedC.TypeParameters[0].IsReferenceType); + Assert.AreEqual(true, resolvedC.TypeParameters[1].IsReferenceType); + Assert.AreEqual("System.Collections.Generic.List`1[[System.String]]", resolvedC.TypeParameters[0].EffectiveBaseClass); + Assert.AreEqual("System.Collections.Generic.List`1[[System.String]]", resolvedC.TypeParameters[1].EffectiveBaseClass); } } } diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs index aa47e69532..e6e6bd1d21 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs @@ -35,25 +35,17 @@ namespace ICSharpCode.NRefactory.TypeSystem /// public abstract class TypeSystemTests { - protected IProjectContent testCasePC; + protected ICompilation compilation; - ITypeResolveContext ctx; - - [SetUpAttribute] - public void SetUp() - { - ctx = CompositeTypeResolveContext.Combine(testCasePC, CecilLoaderTests.Mscorlib); - } - - ITypeDefinition GetClass(Type type) + ITypeDefinition GetTypeDefinition(Type type) { - return testCasePC.GetTypeDefinition(type); + return compilation.FindType(type).GetDefinition(); } [Test] public void SimplePublicClassTest() { - ITypeDefinition c = testCasePC.GetTypeDefinition(typeof(SimplePublicClass)); + ITypeDefinition c = GetTypeDefinition(typeof(SimplePublicClass)); Assert.AreEqual(typeof(SimplePublicClass).Name, c.Name); Assert.AreEqual(typeof(SimplePublicClass).FullName, c.FullName); Assert.AreEqual(typeof(SimplePublicClass).Namespace, c.Namespace); @@ -69,7 +61,7 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void SimplePublicClassMethodTest() { - ITypeDefinition c = testCasePC.GetTypeDefinition(typeof(SimplePublicClass)); + ITypeDefinition c = GetTypeDefinition(typeof(SimplePublicClass)); IMethod method = c.Methods.Single(m => m.Name == "Method"); Assert.AreEqual(typeof(SimplePublicClass).FullName + ".Method", method.FullName); @@ -78,7 +70,6 @@ namespace ICSharpCode.NRefactory.TypeSystem Assert.AreEqual(EntityType.Method, method.EntityType); Assert.IsFalse(method.IsVirtual); Assert.IsFalse(method.IsStatic); - Assert.IsTrue(method.IsFrozen); Assert.AreEqual(0, method.Parameters.Count); Assert.AreEqual(0, method.Attributes.Count); } @@ -86,43 +77,43 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void DynamicType() { - ITypeDefinition testClass = testCasePC.GetTypeDefinition(typeof(DynamicTest)); - Assert.AreEqual(SharedTypes.Dynamic, testClass.Properties.Single().ReturnType.Resolve(ctx)); + ITypeDefinition testClass = GetTypeDefinition(typeof(DynamicTest)); + Assert.AreEqual(SpecialType.Dynamic, testClass.Properties.Single().ReturnType); Assert.AreEqual(0, testClass.Properties.Single().Attributes.Count); } [Test] public void DynamicTypeInGenerics() { - ITypeDefinition testClass = testCasePC.GetTypeDefinition(typeof(DynamicTest)); + ITypeDefinition testClass = GetTypeDefinition(typeof(DynamicTest)); IMethod m1 = testClass.Methods.Single(me => me.Name == "DynamicGenerics1"); - Assert.AreEqual("System.Collections.Generic.List`1[[dynamic]]", m1.ReturnType.Resolve(ctx).ReflectionName); - Assert.AreEqual("System.Action`3[[System.Object],[dynamic[]],[System.Object]]", m1.Parameters[0].Type.Resolve(ctx).ReflectionName); + Assert.AreEqual("System.Collections.Generic.List`1[[dynamic]]", m1.ReturnType.ReflectionName); + Assert.AreEqual("System.Action`3[[System.Object],[dynamic[]],[System.Object]]", m1.Parameters[0].Type.ReflectionName); IMethod m2 = testClass.Methods.Single(me => me.Name == "DynamicGenerics2"); - Assert.AreEqual("System.Action`3[[System.Object],[dynamic],[System.Object]]", m2.Parameters[0].Type.Resolve(ctx).ReflectionName); + Assert.AreEqual("System.Action`3[[System.Object],[dynamic],[System.Object]]", m2.Parameters[0].Type.ReflectionName); IMethod m3 = testClass.Methods.Single(me => me.Name == "DynamicGenerics3"); - Assert.AreEqual("System.Action`3[[System.Int32],[dynamic],[System.Object]]", m3.Parameters[0].Type.Resolve(ctx).ReflectionName); + Assert.AreEqual("System.Action`3[[System.Int32],[dynamic],[System.Object]]", m3.Parameters[0].Type.ReflectionName); IMethod m4 = testClass.Methods.Single(me => me.Name == "DynamicGenerics4"); - Assert.AreEqual("System.Action`3[[System.Int32[]],[dynamic],[System.Object]]", m4.Parameters[0].Type.Resolve(ctx).ReflectionName); + Assert.AreEqual("System.Action`3[[System.Int32[]],[dynamic],[System.Object]]", m4.Parameters[0].Type.ReflectionName); IMethod m5 = testClass.Methods.Single(me => me.Name == "DynamicGenerics5"); - Assert.AreEqual("System.Action`3[[System.Int32*[]],[dynamic],[System.Object]]", m5.Parameters[0].Type.Resolve(ctx).ReflectionName); + Assert.AreEqual("System.Action`3[[System.Int32*[]],[dynamic],[System.Object]]", m5.Parameters[0].Type.ReflectionName); IMethod m6 = testClass.Methods.Single(me => me.Name == "DynamicGenerics6"); - Assert.AreEqual("System.Action`3[[System.Object],[dynamic],[System.Object]]&", m6.Parameters[0].Type.Resolve(ctx).ReflectionName); + Assert.AreEqual("System.Action`3[[System.Object],[dynamic],[System.Object]]&", m6.Parameters[0].Type.ReflectionName); IMethod m7 = testClass.Methods.Single(me => me.Name == "DynamicGenerics7"); - Assert.AreEqual("System.Action`3[[System.Int32[][,]],[dynamic],[System.Object]]", m7.Parameters[0].Type.Resolve(ctx).ReflectionName); + Assert.AreEqual("System.Action`3[[System.Int32[][,]],[dynamic],[System.Object]]", m7.Parameters[0].Type.ReflectionName); } [Test] public void DynamicParameterHasNoAttributes() { - ITypeDefinition testClass = testCasePC.GetTypeDefinition(typeof(DynamicTest)); + ITypeDefinition testClass = GetTypeDefinition(typeof(DynamicTest)); IMethod m1 = testClass.Methods.Single(me => me.Name == "DynamicGenerics1"); Assert.AreEqual(0, m1.Parameters[0].Attributes.Count); } @@ -130,19 +121,18 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void AssemblyAttribute() { - var attributes = testCasePC.AssemblyAttributes; - var typeTest = attributes.Single(a => a.AttributeType.Resolve(ctx).FullName == typeof(TypeTestAttribute).FullName); - var posArgs = typeTest.GetPositionalArguments(ctx); - Assert.AreEqual(3, posArgs.Count); + var attributes = compilation.MainAssembly.AssemblyAttributes; + var typeTest = attributes.Single(a => a.AttributeType.FullName == typeof(TypeTestAttribute).FullName); + Assert.AreEqual(3, typeTest.PositionalArguments.Count); // first argument is (int)42 - Assert.AreEqual(42, (int)posArgs[0].ConstantValue); + Assert.AreEqual(42, (int)typeTest.PositionalArguments[0].ConstantValue); // second argument is typeof(System.Action<>) - TypeOfResolveResult rt = (TypeOfResolveResult)posArgs[1]; + TypeOfResolveResult rt = (TypeOfResolveResult)typeTest.PositionalArguments[1]; Assert.IsFalse(rt.ReferencedType is ParameterizedType); // rt must not be constructed - it's just an unbound type Assert.AreEqual("System.Action", rt.ReferencedType.FullName); Assert.AreEqual(1, rt.ReferencedType.TypeParameterCount); // third argument is typeof(IDictionary>) - rt = (TypeOfResolveResult)posArgs[2]; + rt = (TypeOfResolveResult)typeTest.PositionalArguments[2]; ParameterizedType crt = (ParameterizedType)rt.ReferencedType; Assert.AreEqual("System.Collections.Generic.IDictionary", crt.FullName); Assert.AreEqual("System.String", crt.TypeArguments[0].FullName); @@ -153,27 +143,26 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void TypeForwardedTo_Attribute() { - var attributes = testCasePC.AssemblyAttributes; - var forwardAttribute = attributes.Single(a => a.AttributeType.Resolve(ctx).FullName == typeof(TypeForwardedToAttribute).FullName); - var posArgs = forwardAttribute.GetPositionalArguments(ctx); - Assert.AreEqual(1, posArgs.Count); - TypeOfResolveResult rt = (TypeOfResolveResult)posArgs[0]; + var attributes = compilation.MainAssembly.AssemblyAttributes; + var forwardAttribute = attributes.Single(a => a.AttributeType.FullName == typeof(TypeForwardedToAttribute).FullName); + Assert.AreEqual(1, forwardAttribute.PositionalArguments.Count); + TypeOfResolveResult rt = (TypeOfResolveResult)forwardAttribute.PositionalArguments[0]; Assert.AreEqual("System.Func`2", rt.ReferencedType.ReflectionName); } [Test] public void TestClassTypeParameters() { - var testClass = testCasePC.GetTypeDefinition(typeof(GenericClass<,>)); + var testClass = GetTypeDefinition(typeof(GenericClass<,>)); Assert.AreEqual(EntityType.TypeDefinition, testClass.TypeParameters[0].OwnerType); Assert.AreEqual(EntityType.TypeDefinition, testClass.TypeParameters[1].OwnerType); - Assert.AreSame(testClass.TypeParameters[1], testClass.TypeParameters[0].GetConstraints(ctx)[0].Resolve(ctx)); + Assert.AreSame(testClass.TypeParameters[1], testClass.TypeParameters[0].DirectBaseTypes.First()); } [Test] public void TestMethod() { - var testClass = testCasePC.GetTypeDefinition(typeof(GenericClass<,>)); + var testClass = GetTypeDefinition(typeof(GenericClass<,>)); IMethod m = testClass.Methods.Single(me => me.Name == "TestMethod"); Assert.AreEqual("K", m.TypeParameters[0].Name); @@ -181,20 +170,20 @@ namespace ICSharpCode.NRefactory.TypeSystem Assert.AreEqual(EntityType.Method, m.TypeParameters[0].OwnerType); Assert.AreEqual(EntityType.Method, m.TypeParameters[1].OwnerType); - Assert.AreEqual("System.IComparable`1[[``1]]", m.TypeParameters[0].GetConstraints(ctx)[0].Resolve(ctx).ReflectionName); - Assert.AreSame(m.TypeParameters[0], m.TypeParameters[1].GetConstraints(ctx)[0].Resolve(ctx)); + Assert.AreEqual("System.IComparable`1[[``1]]", m.TypeParameters[0].DirectBaseTypes.First().ReflectionName); + Assert.AreSame(m.TypeParameters[0], m.TypeParameters[1].DirectBaseTypes.First()); } [Test] public void GetIndex() { - var testClass = testCasePC.GetTypeDefinition(typeof(GenericClass<,>)); + var testClass = GetTypeDefinition(typeof(GenericClass<,>)); IMethod m = testClass.Methods.Single(me => me.Name == "GetIndex"); Assert.AreEqual("T", m.TypeParameters[0].Name); Assert.AreEqual(EntityType.Method, m.TypeParameters[0].OwnerType); - ParameterizedType constraint = (ParameterizedType)m.TypeParameters[0].GetConstraints(ctx)[0].Resolve(ctx); + ParameterizedType constraint = (ParameterizedType)m.TypeParameters[0].DirectBaseTypes.First(); Assert.AreEqual("IEquatable", constraint.Name); Assert.AreEqual(1, constraint.TypeParameterCount); Assert.AreEqual(1, constraint.TypeArguments.Count); @@ -204,7 +193,7 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void PropertyWithProtectedSetter() { - var testClass = testCasePC.GetTypeDefinition(typeof(PropertyTest)); + var testClass = GetTypeDefinition(typeof(PropertyTest)); IProperty p = testClass.Properties.Single(pr => pr.Name == "PropertyWithProtectedSetter"); Assert.IsTrue(p.CanGet); Assert.IsTrue(p.CanSet); @@ -216,7 +205,7 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void PropertyWithPrivateSetter() { - var testClass = testCasePC.GetTypeDefinition(typeof(PropertyTest)); + var testClass = GetTypeDefinition(typeof(PropertyTest)); IProperty p = testClass.Properties.Single(pr => pr.Name == "PropertyWithPrivateSetter"); Assert.IsTrue(p.CanGet); Assert.IsTrue(p.CanSet); @@ -228,7 +217,7 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void Indexer() { - var testClass = testCasePC.GetTypeDefinition(typeof(PropertyTest)); + var testClass = GetTypeDefinition(typeof(PropertyTest)); IProperty p = testClass.Properties.Single(pr => pr.IsIndexer); Assert.AreEqual("Item", p.Name); Assert.IsTrue(p.CanGet); @@ -241,58 +230,59 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void EnumTest() { - var e = testCasePC.GetTypeDefinition(typeof(MyEnum)); + var e = GetTypeDefinition(typeof(MyEnum)); Assert.AreEqual(TypeKind.Enum, e.Kind); - Assert.AreEqual(false, e.IsReferenceType(ctx)); - Assert.AreEqual("System.Int16", e.BaseTypes[0].Resolve(ctx).ReflectionName); - Assert.AreEqual(new[] { "System.Enum" }, e.GetBaseTypes(ctx).Select(t => t.ReflectionName).ToArray()); + Assert.AreEqual(false, e.IsReferenceType); + Assert.AreEqual("System.Int16", e.EnumUnderlyingType.ReflectionName); + Assert.AreEqual(new[] { "System.Enum" }, e.DirectBaseTypes.Select(t => t.ReflectionName).ToArray()); } [Test] public void EnumFieldsTest() { - var e = testCasePC.GetTypeDefinition(typeof(MyEnum)); - Assert.AreEqual(5, e.Fields.Count); + var e = GetTypeDefinition(typeof(MyEnum)); + IField[] fields = e.Fields.ToArray(); + Assert.AreEqual(5, fields.Length); - foreach (IField f in e.Fields) { + foreach (IField f in fields) { Assert.IsTrue(f.IsStatic); Assert.IsTrue(f.IsConst); Assert.AreEqual(Accessibility.Public, f.Accessibility); - Assert.AreSame(e, f.ConstantValue.Resolve(ctx).Type); - Assert.AreEqual(typeof(short), f.ConstantValue.Resolve(ctx).ConstantValue.GetType()); + Assert.AreSame(e, f.Type); + Assert.AreEqual(typeof(short), f.ConstantValue.GetType()); } - Assert.AreEqual("First", e.Fields[0].Name); - Assert.AreEqual(0, e.Fields[0].ConstantValue.Resolve(ctx).ConstantValue); + Assert.AreEqual("First", fields[0].Name); + Assert.AreEqual(0, fields[0].ConstantValue); - Assert.AreEqual("Second", e.Fields[1].Name); - Assert.AreSame(e, e.Fields[1].ConstantValue.Resolve(ctx).Type); - Assert.AreEqual(1, e.Fields[1].ConstantValue.Resolve(ctx).ConstantValue); + Assert.AreEqual("Second", fields[1].Name); + Assert.AreSame(e, fields[1].Type); + Assert.AreEqual(1, fields[1].ConstantValue); - Assert.AreEqual("Flag1", e.Fields[2].Name); - Assert.AreEqual(0x10, e.Fields[2].ConstantValue.Resolve(ctx).ConstantValue); + Assert.AreEqual("Flag1", fields[2].Name); + Assert.AreEqual(0x10, fields[2].ConstantValue); - Assert.AreEqual("Flag2", e.Fields[3].Name); - Assert.AreEqual(0x20, e.Fields[3].ConstantValue.Resolve(ctx).ConstantValue); + Assert.AreEqual("Flag2", fields[3].Name); + Assert.AreEqual(0x20, fields[3].ConstantValue); - Assert.AreEqual("CombinedFlags", e.Fields[4].Name); - Assert.AreEqual(0x30, e.Fields[4].ConstantValue.Resolve(ctx).ConstantValue); + Assert.AreEqual("CombinedFlags", fields[4].Name); + Assert.AreEqual(0x30, fields[4].ConstantValue); } [Test] public void GetNestedTypesFromBaseClassTest() { - ITypeDefinition d = ctx.GetTypeDefinition(typeof(Derived<,>)); + ITypeDefinition d = GetTypeDefinition(typeof(Derived<,>)); - IType pBase = d.BaseTypes.Single().Resolve(ctx); + IType pBase = d.DirectBaseTypes.Single(); Assert.AreEqual(typeof(Base<>).FullName + "[[`1]]", pBase.ReflectionName); // Base[`1].GetNestedTypes() = { Base`1+Nested`1[`1, unbound] } Assert.AreEqual(new[] { typeof(Base<>.Nested<>).FullName + "[[`1],[]]" }, - pBase.GetNestedTypes(ctx).Select(n => n.ReflectionName).ToArray()); + pBase.GetNestedTypes().Select(n => n.ReflectionName).ToArray()); // Derived.GetNestedTypes() = { Base`1+Nested`1[`1, unbound] } Assert.AreEqual(new[] { typeof(Base<>.Nested<>).FullName + "[[`1],[]]" }, - d.GetNestedTypes(ctx).Select(n => n.ReflectionName).ToArray()); + d.GetNestedTypes().Select(n => n.ReflectionName).ToArray()); // This is 'leaking' the type parameter from B as is usual when retrieving any members from an unbound type. } @@ -300,29 +290,27 @@ namespace ICSharpCode.NRefactory.TypeSystem public void ParameterizedTypeGetNestedTypesFromBaseClassTest() { // Derived[string,int].GetNestedTypes() = { Base`1+Nested`1[int, unbound] } - var d = typeof(Derived).ToTypeReference().Resolve(ctx); + var d = compilation.FindType(typeof(Derived)); Assert.AreEqual(new[] { typeof(Base<>.Nested<>).FullName + "[[System.Int32],[]]" }, - d.GetNestedTypes(ctx).Select(n => n.ReflectionName).ToArray()); + d.GetNestedTypes().Select(n => n.ReflectionName).ToArray()); } [Test] public void ConstraintsOnOverrideAreInherited() { - ITypeDefinition d = ctx.GetTypeDefinition(typeof(Derived<,>)); + ITypeDefinition d = GetTypeDefinition(typeof(Derived<,>)); ITypeParameter tp = d.Methods.Single(m => m.Name == "GenericMethodWithConstraints").TypeParameters.Single(); Assert.AreEqual("Y", tp.Name); - ITypeParameterConstraints constraints = tp.GetConstraints(ctx); - Assert.IsFalse(constraints.HasValueTypeConstraint); - Assert.IsFalse(constraints.HasReferenceTypeConstraint); - Assert.IsTrue(constraints.HasDefaultConstructorConstraint); - Assert.AreEqual(1, constraints.Count); - Assert.AreEqual("System.Collections.Generic.IComparer`1[[`1]]", constraints[0].ReflectionName); + Assert.IsFalse(tp.HasValueTypeConstraint); + Assert.IsFalse(tp.HasReferenceTypeConstraint); + Assert.IsTrue(tp.HasDefaultConstructorConstraint); + Assert.AreEqual(new string[] { "System.Collections.Generic.IComparer`1[[`1]]" }, tp.DirectBaseTypes.Select(t => t.ReflectionName).ToArray()); } [Test] public void DefaultConstructorAddedToStruct() { - var ctors = typeof(MyStructWithCtor).ToTypeReference().Resolve(ctx).GetConstructors(ctx); + var ctors = compilation.FindType(typeof(MyStructWithCtor)).GetConstructors(); Assert.AreEqual(2, ctors.Count()); Assert.IsFalse(ctors.Any(c => c.IsStatic)); } @@ -330,33 +318,32 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void SerializableAttribute() { - IAttribute attr = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Attributes.Single(); - Assert.AreEqual("System.SerializableAttribute", attr.AttributeType.Resolve(ctx).FullName); + IAttribute attr = GetTypeDefinition(typeof(NonCustomAttributes)).Attributes.Single(); + Assert.AreEqual("System.SerializableAttribute", attr.AttributeType.FullName); } [Test] public void NonSerializedAttribute() { - IField field = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Fields.Single(f => f.Name == "NonSerializedField"); - Assert.AreEqual("System.NonSerializedAttribute", field.Attributes.Single().AttributeType.Resolve(ctx).FullName); + IField field = GetTypeDefinition(typeof(NonCustomAttributes)).Fields.Single(f => f.Name == "NonSerializedField"); + Assert.AreEqual("System.NonSerializedAttribute", field.Attributes.Single().AttributeType.FullName); } [Test] public void ExplicitStructLayoutAttribute() { - IAttribute attr = ctx.GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Attributes.Single(); - Assert.AreEqual("System.Runtime.InteropServices.StructLayoutAttribute", attr.AttributeType.Resolve(ctx).FullName); - ResolveResult arg1 = attr.GetPositionalArguments(ctx).Single(); + IAttribute attr = GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Attributes.Single(); + Assert.AreEqual("System.Runtime.InteropServices.StructLayoutAttribute", attr.AttributeType.FullName); + ResolveResult arg1 = attr.PositionalArguments.Single(); Assert.AreEqual("System.Runtime.InteropServices.LayoutKind", arg1.Type.FullName); Assert.AreEqual((int)LayoutKind.Explicit, arg1.ConstantValue); - var namedArgs = attr.GetNamedArguments(ctx); - var arg2 = namedArgs[0]; + var arg2 = attr.NamedArguments[0]; Assert.AreEqual("CharSet", arg2.Key); Assert.AreEqual("System.Runtime.InteropServices.CharSet", arg2.Value.Type.FullName); Assert.AreEqual((int)CharSet.Unicode, arg2.Value.ConstantValue); - var arg3 = namedArgs[1]; + var arg3 = attr.NamedArguments[1]; Assert.AreEqual("Pack", arg3.Key); Assert.AreEqual("System.Int32", arg3.Value.Type.FullName); Assert.AreEqual(8, arg3.Value.ConstantValue); @@ -365,15 +352,15 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void FieldOffsetAttribute() { - IField field = ctx.GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field0"); - Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.Resolve(ctx).FullName); - ResolveResult arg = field.Attributes.Single().GetPositionalArguments(ctx).Single(); + IField field = GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field0"); + Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.FullName); + ResolveResult arg = field.Attributes.Single().PositionalArguments.Single(); Assert.AreEqual("System.Int32", arg.Type.FullName); Assert.AreEqual(0, arg.ConstantValue); - field = ctx.GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field100"); - Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.Resolve(ctx).FullName); - arg = field.Attributes.Single().GetPositionalArguments(ctx).Single(); + field = GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field100"); + Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.FullName); + arg = field.Attributes.Single().PositionalArguments.Single(); Assert.AreEqual("System.Int32", arg.Type.FullName); Assert.AreEqual(100, arg.ConstantValue); } @@ -381,92 +368,92 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void DllImportAttribute() { - IMethod method = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod"); + IMethod method = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod"); IAttribute dllImport = method.Attributes.Single(); - Assert.AreEqual("System.Runtime.InteropServices.DllImportAttribute", dllImport.AttributeType.Resolve(ctx).FullName); - Assert.AreEqual("unmanaged.dll", dllImport.GetPositionalArguments(ctx)[0].ConstantValue); - Assert.AreEqual((int)CharSet.Unicode, dllImport.GetNamedArguments(ctx).Single().Value.ConstantValue); + Assert.AreEqual("System.Runtime.InteropServices.DllImportAttribute", dllImport.AttributeType.FullName); + Assert.AreEqual("unmanaged.dll", dllImport.PositionalArguments[0].ConstantValue); + Assert.AreEqual((int)CharSet.Unicode, dllImport.NamedArguments.Single().Value.ConstantValue); } [Test] public void InOutParametersOnRefMethod() { - IParameter p = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod").Parameters.Single(); + IParameter p = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod").Parameters.Single(); Assert.IsTrue(p.IsRef); Assert.IsFalse(p.IsOut); Assert.AreEqual(2, p.Attributes.Count); - Assert.AreEqual("System.Runtime.InteropServices.InAttribute", p.Attributes[0].AttributeType.Resolve(ctx).FullName); - Assert.AreEqual("System.Runtime.InteropServices.OutAttribute", p.Attributes[1].AttributeType.Resolve(ctx).FullName); + Assert.AreEqual("System.Runtime.InteropServices.InAttribute", p.Attributes[0].AttributeType.FullName); + Assert.AreEqual("System.Runtime.InteropServices.OutAttribute", p.Attributes[1].AttributeType.FullName); } [Test] public void MarshalAsAttributeOnMethod() { - IMethod method = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod"); + IMethod method = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod"); IAttribute marshalAs = method.ReturnTypeAttributes.Single(); - Assert.AreEqual((int)UnmanagedType.Bool, marshalAs.GetPositionalArguments(ctx).Single().ConstantValue); + Assert.AreEqual((int)UnmanagedType.Bool, marshalAs.PositionalArguments.Single().ConstantValue); } [Test] public void MethodWithOutParameter() { - IParameter p = ctx.GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOutParameter").Parameters.Single(); + IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOutParameter").Parameters.Single(); Assert.IsFalse(p.IsRef); Assert.IsTrue(p.IsOut); Assert.AreEqual(0, p.Attributes.Count); - Assert.IsTrue(p.Type is ByReferenceTypeReference); + Assert.IsTrue(p.Type.Kind == TypeKind.ByReference); } [Test] public void MethodWithParamsArray() { - IParameter p = ctx.GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithParamsArray").Parameters.Single(); + IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithParamsArray").Parameters.Single(); Assert.IsFalse(p.IsRef); Assert.IsFalse(p.IsOut); Assert.IsTrue(p.IsParams); Assert.AreEqual(0, p.Attributes.Count); - Assert.IsTrue(p.Type is ArrayTypeReference); + Assert.IsTrue(p.Type.Kind == TypeKind.Array); } [Test] public void GenericDelegate_Variance() { - ITypeDefinition type = ctx.GetTypeDefinition(typeof(GenericDelegate<,>)); + ITypeDefinition type = GetTypeDefinition(typeof(GenericDelegate<,>)); Assert.AreEqual(VarianceModifier.Contravariant, type.TypeParameters[0].Variance); Assert.AreEqual(VarianceModifier.Covariant, type.TypeParameters[1].Variance); - Assert.AreSame(type.TypeParameters[1], type.TypeParameters[0].GetConstraints(ctx)[0].Resolve(ctx)); + Assert.AreSame(type.TypeParameters[1], type.TypeParameters[0].DirectBaseTypes.FirstOrDefault()); } [Test] public void GenericDelegate_ReferenceTypeConstraints() { - ITypeDefinition type = ctx.GetTypeDefinition(typeof(GenericDelegate<,>)); - Assert.IsFalse(type.TypeParameters[0].GetConstraints(ctx).HasReferenceTypeConstraint); - Assert.IsTrue(type.TypeParameters[1].GetConstraints(ctx).HasReferenceTypeConstraint); + ITypeDefinition type = GetTypeDefinition(typeof(GenericDelegate<,>)); + Assert.IsFalse(type.TypeParameters[0].HasReferenceTypeConstraint); + Assert.IsTrue(type.TypeParameters[1].HasReferenceTypeConstraint); - Assert.IsNull(type.TypeParameters[0].IsReferenceType(ctx)); - Assert.AreEqual(true, type.TypeParameters[1].IsReferenceType(ctx)); + Assert.IsNull(type.TypeParameters[0].IsReferenceType); + Assert.AreEqual(true, type.TypeParameters[1].IsReferenceType); } [Test] public void GenericDelegate_GetInvokeMethod() { - IType type = typeof(GenericDelegate).ToTypeReference().Resolve(ctx); + IType type = compilation.FindType(typeof(GenericDelegate)); IMethod m = type.GetDelegateInvokeMethod(); Assert.AreEqual("Invoke", m.Name); - Assert.AreEqual("System.Object", m.ReturnType.Resolve(ctx).FullName); - Assert.AreEqual("System.String", m.Parameters[0].Type.Resolve(ctx).FullName); + Assert.AreEqual("System.Object", m.ReturnType.FullName); + Assert.AreEqual("System.String", m.Parameters[0].Type.FullName); } [Test] public void ComInterfaceTest() { - ITypeDefinition type = ctx.GetTypeDefinition(typeof(IAssemblyEnum)); + ITypeDefinition type = GetTypeDefinition(typeof(IAssemblyEnum)); // [ComImport] - Assert.AreEqual(1, type.Attributes.Count(a => a.AttributeType.Resolve(ctx).FullName == typeof(ComImportAttribute).FullName)); + Assert.AreEqual(1, type.Attributes.Count(a => a.AttributeType.FullName == typeof(ComImportAttribute).FullName)); - IMethod m = type.Methods.Single(); + IMethod m = type.Members.OfType().Single(); Assert.AreEqual("GetNextAssembly", m.Name); Assert.AreEqual(Accessibility.Public, m.Accessibility); Assert.IsTrue(m.IsAbstract); @@ -476,33 +463,33 @@ namespace ICSharpCode.NRefactory.TypeSystem [Test] public void ConstantAnswer() { - ITypeDefinition type = ctx.GetTypeDefinition(typeof(ConstantTest)); - IField answer = type.Fields.Single(f => f.Name == "Answer"); + ITypeDefinition type = GetTypeDefinition(typeof(ConstantTest)); + IField answer = type.Members.OfType().Single(f => f.Name == "Answer"); Assert.IsTrue(answer.IsConst); - Assert.AreEqual(42, answer.ConstantValue.Resolve(ctx).ConstantValue); + Assert.AreEqual(42, answer.ConstantValue); } [Test] public void ConstantNullString() { - ITypeDefinition type = ctx.GetTypeDefinition(typeof(ConstantTest)); - IField answer = type.Fields.Single(f => f.Name == "NullString"); + ITypeDefinition type = GetTypeDefinition(typeof(ConstantTest)); + IField answer = type.Members.OfType().Single(f => f.Name == "NullString"); Assert.IsTrue(answer.IsConst); - Assert.IsNull(answer.ConstantValue.Resolve(ctx).ConstantValue); + Assert.IsNull(answer.ConstantValue); } [Test] public void InnerClassInGenericClassIsReferencedUsingParameterizedType() { - ITypeDefinition type = ctx.GetTypeDefinition(typeof(OuterGeneric<>)); - IField field1 = type.Fields.Single(f => f.Name == "Field1"); - IField field2 = type.Fields.Single(f => f.Name == "Field2"); - IField field3 = type.Fields.Single(f => f.Name == "Field3"); + ITypeDefinition type = GetTypeDefinition(typeof(OuterGeneric<>)); + IField field1 = type.Members.OfType().Single(f => f.Name == "Field1"); + IField field2 = type.Members.OfType().Single(f => f.Name == "Field2"); + IField field3 = type.Members.OfType().Single(f => f.Name == "Field3"); // types must be self-parameterized - Assert.AreEqual("ICSharpCode.NRefactory.TypeSystem.TestCase.OuterGeneric`1+Inner[[`0]]", field1.Type.Resolve(ctx).ReflectionName); - Assert.AreEqual("ICSharpCode.NRefactory.TypeSystem.TestCase.OuterGeneric`1+Inner[[`0]]", field2.Type.Resolve(ctx).ReflectionName); - Assert.AreEqual("ICSharpCode.NRefactory.TypeSystem.TestCase.OuterGeneric`1+Inner[[ICSharpCode.NRefactory.TypeSystem.TestCase.OuterGeneric`1+Inner[[`0]]]]", field3.Type.Resolve(ctx).ReflectionName); + Assert.AreEqual("ICSharpCode.NRefactory.TypeSystem.TestCase.OuterGeneric`1+Inner[[`0]]", field1.Type.ReflectionName); + Assert.AreEqual("ICSharpCode.NRefactory.TypeSystem.TestCase.OuterGeneric`1+Inner[[`0]]", field2.Type.ReflectionName); + Assert.AreEqual("ICSharpCode.NRefactory.TypeSystem.TestCase.OuterGeneric`1+Inner[[ICSharpCode.NRefactory.TypeSystem.TestCase.OuterGeneric`1+Inner[[`0]]]]", field3.Type.ReflectionName); } } } diff --git a/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs b/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs index c515e28110..13343bbf2f 100644 --- a/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs +++ b/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs @@ -18,7 +18,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors TypeKind GetTypeKindForAstType(CSharp.AstType type); TypeCode ResolveExpression(CSharp.Expression expression); bool? IsReferenceType(CSharp.Expression expression); - ITypeResolveContext ResolveContext { get; } + //ITypeResolveContext ResolveContext { get; } IType ResolveType(AstType type, TypeDeclaration entity = null); } @@ -1624,7 +1624,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors foreach (var type in current.ImplementsTypes) { var resolved = provider.ResolveType(type, current); - var found = resolved.GetMembers(provider.ResolveContext, m => m.EntityType == EntityType.Method && m.Name == result.Name.Name); + var found = resolved.GetMembers(m => m.EntityType == EntityType.Method && m.Name == result.Name.Name); if (found.FirstOrDefault() != null) { result.ImplementsClause.Add(new InterfaceMemberSpecifier((AstType)type.Clone(), found.FirstOrDefault().Name)); } @@ -1640,7 +1640,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors foreach (var type in current.ImplementsTypes) { var resolved = provider.ResolveType(type, current); - var found = resolved.GetMembers(provider.ResolveContext, m => m.EntityType == EntityType.Event && m.Name == result.Name.Name); + var found = resolved.GetMembers(m => m.EntityType == EntityType.Event && m.Name == result.Name.Name); if (found.FirstOrDefault() != null) { result.ImplementsClause.Add(new InterfaceMemberSpecifier((AstType)type.Clone(), found.FirstOrDefault().Name)); } diff --git a/ICSharpCode.NRefactory/Documentation/IDStringProvider.cs b/ICSharpCode.NRefactory/Documentation/IDStringProvider.cs index 0131125c58..05964e01bf 100644 --- a/ICSharpCode.NRefactory/Documentation/IDStringProvider.cs +++ b/ICSharpCode.NRefactory/Documentation/IDStringProvider.cs @@ -33,12 +33,7 @@ namespace ICSharpCode.NRefactory.Documentation /// /// Gets the ID string (C# 4.0 spec, §A.3.1) for the specified entity. /// - /// - /// The type resolve context is optional and is not needed for entities loaded from assemblies: - /// This method can get the ID string for any type reference produced by the CecilLoader without - /// having to resolve the type reference. - /// - public static string GetIDString(IEntity entity, ITypeResolveContext context = null) + public static string GetIDString(IEntity entity) { StringBuilder b = new StringBuilder(); switch (entity.EntityType) { @@ -75,13 +70,13 @@ namespace ICSharpCode.NRefactory.Documentation var parameters = parameterizedMember.Parameters; for (int i = 0; i < parameters.Count; i++) { if (i > 0) b.Append(','); - AppendTypeName(b, parameters[i].Type, context); + AppendTypeName(b, parameters[i].Type); } b.Append(')'); } if (member.EntityType == EntityType.Operator && (member.Name == "op_Implicit" || member.Name == "op_Explicit")) { b.Append('~'); - AppendTypeName(b, member.ReturnType, context); + AppendTypeName(b, member.ReturnType); } return b.ToString(); } @@ -162,123 +157,5 @@ namespace ICSharpCode.NRefactory.Documentation } } } - - static void AppendTypeName(StringBuilder b, ITypeReference type, ITypeResolveContext context) - { - IType resolvedType = type as IType; - if (resolvedType != null) { - AppendTypeName(b, resolvedType); - return; - } - KnownTypeReference knownType = type as KnownTypeReference; - if (knownType != null) { - if (!string.IsNullOrEmpty(knownType.Namespace)) { - b.Append(knownType.Namespace); - b.Append('.'); - } - b.Append(knownType.Name); - return; - } - GetClassTypeReference gctr = type as GetClassTypeReference; - if (gctr != null) { - if (!string.IsNullOrEmpty(gctr.Namespace)) { - b.Append(gctr.Namespace); - b.Append('.'); - } - b.Append(gctr.Name); - if (gctr.TypeParameterCount > 0) { - b.Append('`'); - b.Append(gctr.TypeParameterCount); - } - return; - } - NestedTypeReference ntr = type as NestedTypeReference; - if (ntr != null) { - AppendTypeName(b, ntr.DeclaringTypeReference, context); - b.Append('.'); - b.Append(ntr.Name); - if (ntr.AdditionalTypeParameterCount > 0) { - b.Append('`'); - b.Append(ntr.AdditionalTypeParameterCount); - } - return; - } - ParameterizedTypeReference pt = type as ParameterizedTypeReference; - if (pt != null && IsGetClassTypeReference(pt.GenericType)) { - AppendParameterizedTypeName(b, pt.GenericType, pt.TypeArguments, context); - return; - } - ArrayTypeReference array = type as ArrayTypeReference; - if (array != null) { - AppendTypeName(b, array.ElementType, context); - b.Append('['); - if (array.Dimensions > 1) { - for (int i = 0; i < array.Dimensions; i++) { - if (i > 0) b.Append(','); - b.Append("0:"); - } - } - b.Append(']'); - return; - } - PointerTypeReference ptr = type as PointerTypeReference; - if (ptr != null) { - AppendTypeName(b, ptr.ElementType, context); - b.Append('*'); - return; - } - ByReferenceTypeReference brtr = type as ByReferenceTypeReference; - if (brtr != null) { - AppendTypeName(b, brtr.ElementType, context); - b.Append('@'); - return; - } - if (context == null) - b.Append('?'); - else - AppendTypeName(b, type.Resolve(context)); - } - - static bool IsGetClassTypeReference(ITypeReference type) - { - NestedTypeReference ntr; - while ((ntr = type as NestedTypeReference) != null) - type = ntr.DeclaringTypeReference; - return type is GetClassTypeReference; - } - - static int AppendParameterizedTypeName(StringBuilder b, ITypeReference type, IList typeArguments, ITypeResolveContext context) - { - GetClassTypeReference gctr = type as GetClassTypeReference; - if (gctr != null) { - if (!string.IsNullOrEmpty(gctr.Namespace)) { - b.Append(gctr.Namespace); - b.Append('.'); - } - b.Append(gctr.Name); - if (gctr.TypeParameterCount > 0) { - b.Append('{'); - for (int i = 0; i < gctr.TypeParameterCount && i < typeArguments.Count; i++) { - if (i > 0) b.Append(','); - AppendTypeName(b, typeArguments[i], context); - } - b.Append('}'); - } - return gctr.TypeParameterCount; - } else { - NestedTypeReference ntr = (NestedTypeReference)type; - int outerTpc = AppendParameterizedTypeName(b, ntr.DeclaringTypeReference, typeArguments, context); - b.Append('.'); - if (ntr.AdditionalTypeParameterCount > 0) { - b.Append('{'); - for (int i = 0; i < ntr.AdditionalTypeParameterCount && i + outerTpc < typeArguments.Count; i++) { - if (i > 0) b.Append(','); - AppendTypeName(b, typeArguments[i + outerTpc], context); - } - b.Append('}'); - } - return outerTpc + ntr.AdditionalTypeParameterCount; - } - } } } diff --git a/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs b/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs index e16d15799c..ff156ed490 100644 --- a/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs +++ b/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs @@ -268,68 +268,6 @@ namespace ICSharpCode.NRefactory.Documentation } #endregion - #region Save index / Restore from index - // TODO: consider removing this code, we're just using serialization instead - - // FILE FORMAT FOR BINARY DOCUMENTATION - // long magic = 0x4244636f446c6d58 (identifies file type = 'XmlDocDB') - const long magic = 0x4244636f446c6d58; - // short version = 5 (file format version) - const short version = 5; - // string fileName (full name of .xml file) - // long fileDate (last change date of xml file in DateTime ticks) - // int testHashCode = magicTestString.GetHashCode() // (check if hash-code implementation is compatible) - // int entryCount (count of entries) - // int indexPointer (points to location where index starts in the file) - // { - // int hashcode - // int positionInFile (byte number where the docu string starts in the .xml file) - // } - - const string magicTestString = "XmlDoc-Test-String"; - - /// - /// Saves the index into a binary file. - /// Use to load the saved file. - /// - public void SaveIndex(BinaryWriter w) - { - if (w == null) - throw new ArgumentNullException("w"); - w.Write(magic); - w.Write(version); - w.Write(fileName); - w.Write(lastWriteDate.Ticks); - w.Write(magicTestString.GetHashCode()); - w.Write(index.Length); - foreach (var entry in index) { - w.Write(entry.HashCode); - w.Write(entry.PositionInFile); - } - } - - /// - /// Restores XmlDocumentationProvider from the index file (created by ). - /// - public static XmlDocumentationProvider LoadFromIndex(BinaryReader r) - { - if (r.ReadInt64() != magic) - throw new InvalidDataException("File is not a stored XmlDoc index"); - if (r.ReadInt16() != version) - throw new InvalidDataException("Index file was created by incompatible version"); - string fileName = r.ReadString(); - DateTime lastWriteDate = new DateTime(r.ReadInt64(), DateTimeKind.Utc); - if (r.ReadInt32() != magicTestString.GetHashCode()) - throw new InvalidDataException("Index file was created by another hash code algorithm"); - int indexLength = r.ReadInt32(); - IndexEntry[] index = new IndexEntry[indexLength]; - for (int i = 0; i < index.Length; i++) { - index[i] = new IndexEntry(r.ReadInt32(), r.ReadInt32()); - } - return new XmlDocumentationProvider(fileName, lastWriteDate, index); - } - #endregion - #region GetDocumentation /// public string GetDocumentation(IEntity entity) @@ -355,6 +293,7 @@ namespace ICSharpCode.NRefactory.Documentation while (--m >= 0 && index[m].HashCode == hashcode); // m is now 1 before the first item with the correct hash + XmlDocumentationCache cache = this.cache; lock (cache) { string val = cache.Get(key); if (val == null) { diff --git a/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs b/ICSharpCode.NRefactory/IAnnotatable.cs similarity index 100% rename from ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs rename to ICSharpCode.NRefactory/IAnnotatable.cs diff --git a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj index 42a6ef9797..3580a95fb5 100644 --- a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj +++ b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj @@ -67,6 +67,7 @@ + @@ -85,6 +86,7 @@ + @@ -104,40 +106,44 @@ + + - - + + - + - - - - - - - - - - + + + + + + + + + + + - + + + - @@ -147,12 +153,9 @@ - - - - + @@ -161,12 +164,10 @@ - - @@ -187,18 +188,19 @@ + + + - - diff --git a/ICSharpCode.NRefactory/Semantics/AmbiguousResolveResult.cs b/ICSharpCode.NRefactory/Semantics/AmbiguousResolveResult.cs index e2fecf1bb9..b302962a15 100644 --- a/ICSharpCode.NRefactory/Semantics/AmbiguousResolveResult.cs +++ b/ICSharpCode.NRefactory/Semantics/AmbiguousResolveResult.cs @@ -37,7 +37,7 @@ namespace ICSharpCode.NRefactory.Semantics public class AmbiguousMemberResolveResult : MemberResolveResult { - public AmbiguousMemberResolveResult(ResolveResult targetResult, IMember member, IType returnType) : base(targetResult, member, returnType) + public AmbiguousMemberResolveResult(ResolveResult targetResult, IMember member) : base(targetResult, member) { } diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ErrorResolveResult.cs b/ICSharpCode.NRefactory/Semantics/ErrorResolveResult.cs similarity index 92% rename from ICSharpCode.NRefactory.CSharp/Resolver/ErrorResolveResult.cs rename to ICSharpCode.NRefactory/Semantics/ErrorResolveResult.cs index 138453b26b..15942f7a8a 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/ErrorResolveResult.cs +++ b/ICSharpCode.NRefactory/Semantics/ErrorResolveResult.cs @@ -17,10 +17,9 @@ // DEALINGS IN THE SOFTWARE. using System; -using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; -namespace ICSharpCode.NRefactory.CSharp.Resolver +namespace ICSharpCode.NRefactory.Semantics { /// /// Represents a resolve error. @@ -30,7 +29,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// /// Gets an ErrorResolveResult instance with Type = SharedTypes.UnknownType. /// - public static readonly ErrorResolveResult UnknownError = new ErrorResolveResult(SharedTypes.UnknownType); + public static readonly ErrorResolveResult UnknownError = new ErrorResolveResult(SpecialType.UnknownType); public ErrorResolveResult(IType type) : base(type) { diff --git a/ICSharpCode.NRefactory/Semantics/InvocationResolveResult.cs b/ICSharpCode.NRefactory/Semantics/InvocationResolveResult.cs index 9ea5416924..ca91ea26f8 100644 --- a/ICSharpCode.NRefactory/Semantics/InvocationResolveResult.cs +++ b/ICSharpCode.NRefactory/Semantics/InvocationResolveResult.cs @@ -35,10 +35,8 @@ namespace ICSharpCode.NRefactory.Semantics /// public readonly IList Arguments; - public InvocationResolveResult( - ResolveResult targetResult, IParameterizedMember member, IType returnType, - IList arguments) - : base(targetResult, member, returnType) + public InvocationResolveResult(ResolveResult targetResult, IParameterizedMember member, IList arguments) + : base(targetResult, member) { this.Arguments = arguments ?? EmptyList.Instance; } diff --git a/ICSharpCode.NRefactory/Semantics/LocalResolveResult.cs b/ICSharpCode.NRefactory/Semantics/LocalResolveResult.cs index 58db073602..1bfaa3b376 100644 --- a/ICSharpCode.NRefactory/Semantics/LocalResolveResult.cs +++ b/ICSharpCode.NRefactory/Semantics/LocalResolveResult.cs @@ -27,21 +27,20 @@ namespace ICSharpCode.NRefactory.Semantics public class LocalResolveResult : ResolveResult { readonly IVariable variable; - readonly object constantValue; - public LocalResolveResult(IVariable variable, IType type, object constantValue = null) - : base(UnpackTypeIfByRefParameter(type, variable)) + public LocalResolveResult(IVariable variable) + : base(UnpackTypeIfByRefParameter(variable)) { - if (variable == null) - throw new ArgumentNullException("variable"); this.variable = variable; - this.constantValue = constantValue; } - static IType UnpackTypeIfByRefParameter(IType type, IVariable v) + static IType UnpackTypeIfByRefParameter(IVariable variable) { + if (variable == null) + throw new ArgumentNullException("variable"); + IType type = variable.Type; if (type.Kind == TypeKind.ByReference) { - IParameter p = v as IParameter; + IParameter p = variable as IParameter; if (p != null && (p.IsRef || p.IsOut)) return ((ByReferenceType)type).ElementType; } @@ -61,7 +60,7 @@ namespace ICSharpCode.NRefactory.Semantics } public override object ConstantValue { - get { return constantValue; } + get { return variable.ConstantValue; } } public override string ToString() diff --git a/ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs b/ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs index 467e735955..64f848eeef 100644 --- a/ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs +++ b/ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs @@ -33,26 +33,8 @@ namespace ICSharpCode.NRefactory.Semantics readonly object constantValue; readonly ResolveResult targetResult; - public MemberResolveResult(ResolveResult targetResult, IMember member, IType returnType) : base(returnType) - { - if (member == null) - throw new ArgumentNullException("member"); - this.targetResult = targetResult; - this.member = member; - } - - public MemberResolveResult(ResolveResult targetResult, IMember member, IType returnType, object constantValue) : base(returnType) - { - if (member == null) - throw new ArgumentNullException("member"); - this.targetResult = targetResult; - this.member = member; - this.isConstant = true; - this.constantValue = constantValue; - } - - public MemberResolveResult(ResolveResult targetResult, IMember member, ITypeResolveContext context) - : base(member.EntityType == EntityType.Constructor ? member.DeclaringType : member.ReturnType.Resolve(context)) + public MemberResolveResult(ResolveResult targetResult, IMember member) + : base(member.EntityType == EntityType.Constructor ? member.DeclaringType : member.ReturnType) { this.targetResult = targetResult; this.member = member; @@ -60,7 +42,7 @@ namespace ICSharpCode.NRefactory.Semantics if (field != null) { isConstant = field.IsConst; if (isConstant) - constantValue = field.ConstantValue.Resolve(context).ConstantValue; + constantValue = field.ConstantValue; } } diff --git a/ICSharpCode.NRefactory/Semantics/NamespaceResolveResult.cs b/ICSharpCode.NRefactory/Semantics/NamespaceResolveResult.cs index c6e2323260..425690329a 100644 --- a/ICSharpCode.NRefactory/Semantics/NamespaceResolveResult.cs +++ b/ICSharpCode.NRefactory/Semantics/NamespaceResolveResult.cs @@ -26,20 +26,24 @@ namespace ICSharpCode.NRefactory.Semantics /// public class NamespaceResolveResult : ResolveResult { - readonly string namespaceName; + readonly INamespace ns; - public NamespaceResolveResult(string namespaceName) : base(SharedTypes.UnknownType) + public NamespaceResolveResult(INamespace ns) : base(SpecialType.UnknownType) { - this.namespaceName = namespaceName; + this.ns = ns; + } + + public INamespace Namespace { + get { return ns; } } public string NamespaceName { - get { return namespaceName; } + get { return ns.FullName; } } public override string ToString() { - return string.Format("[{0} {1}]", GetType().Name, namespaceName); + return string.Format("[{0} {1}]", GetType().Name, ns); } } } diff --git a/ICSharpCode.NRefactory/Semantics/TypeResolveResult.cs b/ICSharpCode.NRefactory/Semantics/TypeResolveResult.cs index b66bee211a..fd889ee78d 100644 --- a/ICSharpCode.NRefactory/Semantics/TypeResolveResult.cs +++ b/ICSharpCode.NRefactory/Semantics/TypeResolveResult.cs @@ -31,6 +31,10 @@ namespace ICSharpCode.NRefactory.Semantics { } + public override bool IsError { + get { return this.Type.Kind == TypeKind.Unknown; } + } + public override DomRegion GetDefinitionRegion() { ITypeDefinition def = this.Type.GetDefinition(); diff --git a/ICSharpCode.NRefactory/Semantics/UnknownMemberResolveResult.cs b/ICSharpCode.NRefactory/Semantics/UnknownMemberResolveResult.cs index 1807881344..907c1a3ce4 100644 --- a/ICSharpCode.NRefactory/Semantics/UnknownMemberResolveResult.cs +++ b/ICSharpCode.NRefactory/Semantics/UnknownMemberResolveResult.cs @@ -33,7 +33,8 @@ namespace ICSharpCode.NRefactory.Semantics readonly string memberName; readonly ReadOnlyCollection typeArguments; - public UnknownMemberResolveResult(IType targetType, string memberName, IEnumerable typeArguments) : base(SharedTypes.UnknownType) + public UnknownMemberResolveResult(IType targetType, string memberName, IEnumerable typeArguments) + : base(SpecialType.UnknownType) { if (targetType == null) throw new ArgumentNullException("targetType"); @@ -74,7 +75,7 @@ namespace ICSharpCode.NRefactory.Semantics { readonly ReadOnlyCollection parameters; - public UnknownMethodResolveResult(IType targetType, string methodName, IEnumerable typeArguments, IEnumerable parameters) + public UnknownMethodResolveResult(IType targetType, string methodName, IEnumerable typeArguments, IEnumerable parameters) : base(targetType, methodName, typeArguments) { this.parameters = new ReadOnlyCollection(parameters.ToArray()); @@ -91,17 +92,23 @@ namespace ICSharpCode.NRefactory.Semantics public class UnknownIdentifierResolveResult : ResolveResult { readonly string identifier; + readonly int typeArgumentCount; - public UnknownIdentifierResolveResult(string identifier) - : base(SharedTypes.UnknownType) + public UnknownIdentifierResolveResult(string identifier, int typeArgumentCount = 0) + : base(SpecialType.UnknownType) { this.identifier = identifier; + this.typeArgumentCount = typeArgumentCount; } public string Identifier { get { return identifier; } } + public int TypeArgumentCount { + get { return typeArgumentCount; } + } + public override bool IsError { get { return true; } } diff --git a/ICSharpCode.NRefactory/Semantics/UnknownTypeResolveResult.cs b/ICSharpCode.NRefactory/Semantics/UnknownTypeResolveResult.cs deleted file mode 100644 index 64297eb54b..0000000000 --- a/ICSharpCode.NRefactory/Semantics/UnknownTypeResolveResult.cs +++ /dev/null @@ -1,67 +0,0 @@ -// -// UnknownTypeResolveResult.cs -// -// Author: -// Mike Krüger -// -// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// 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 System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using ICSharpCode.NRefactory.TypeSystem; - -namespace ICSharpCode.NRefactory.Semantics -{ - /// - /// Represents an unknown type with type parameters. - /// - public class UnknownTypeResolveResult : ResolveResult - { - readonly string identifier; - readonly int typeParameterCount; - - public UnknownTypeResolveResult(string identifier, int typeParameterCount) - : base(SharedTypes.UnknownType) - { - this.identifier = identifier; - this.typeParameterCount = typeParameterCount; - } - - public string Identifier { - get { return identifier; } - } - - public int TypeParameterCount { - get { return typeParameterCount; } - } - - public override bool IsError { - get { return true; } - } - - public override string ToString() - { - return string.Format("[{0} {1}~{2}]", GetType().Name, identifier, typeParameterCount); - } - } -} diff --git a/ICSharpCode.NRefactory/TypeSystem/Accessibility.cs b/ICSharpCode.NRefactory/TypeSystem/Accessibility.cs index c362a93b63..fb9909ec85 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Accessibility.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Accessibility.cs @@ -58,4 +58,60 @@ namespace ICSharpCode.NRefactory.TypeSystem /// C# does not support this accessibility. ProtectedAndInternal, } + + public interface IHasAccessibility + { + /// + /// Gets the accessibility of this entity. + /// + Accessibility Accessibility { get; } + + /// + /// Gets a value indicating whether this instance is private. + /// + /// + /// true if this instance is private; otherwise, false. + /// + bool IsPrivate { get; } + + /// + /// Gets a value indicating whether this instance is public. + /// + /// + /// true if this instance is public; otherwise, false. + /// + bool IsPublic { get; } + + /// + /// Gets a value indicating whether this instance is protected. + /// + /// + /// true if this instance is protected; otherwise, false. + /// + bool IsProtected { get; } + + /// + /// Gets a value indicating whether this instance is internal. + /// + /// + /// true if this instance is internal; otherwise, false. + /// + bool IsInternal { get; } + + /// + /// Gets a value indicating whether this instance is protected or internal. + /// + /// + /// true if this instance is protected or internal; otherwise, false. + /// + bool IsProtectedOrInternal { get; } + + /// + /// Gets a value indicating whether this instance is protected and internal. + /// + /// + /// true if this instance is protected and internal; otherwise, false. + /// + bool IsProtectedAndInternal { get; } + } } diff --git a/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs b/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs index 27566cb3aa..9ba380e041 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs @@ -25,15 +25,18 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Represents an array type. /// - [Serializable] - public sealed class ArrayType : TypeWithElementType, ISupportsInterning + public sealed class ArrayType : TypeWithElementType { readonly int dimensions; + readonly ICompilation compilation; - public ArrayType(IType elementType, int dimensions = 1) : base(elementType) + public ArrayType(ICompilation compilation, IType elementType, int dimensions = 1) : base(elementType) { + if (compilation == null) + throw new ArgumentNullException("compilation"); if (dimensions <= 0) throw new ArgumentOutOfRangeException("dimensions", dimensions, "dimensions must be positive"); + this.compilation = compilation; this.dimensions = dimensions; } @@ -51,9 +54,8 @@ namespace ICSharpCode.NRefactory.TypeSystem } } - public override bool? IsReferenceType(ITypeResolveContext context) - { - return true; + public override bool? IsReferenceType { + get { return true; } } public override int GetHashCode() @@ -67,40 +69,44 @@ namespace ICSharpCode.NRefactory.TypeSystem return a != null && elementType.Equals(a.elementType) && a.dimensions == dimensions; } - static readonly GetClassTypeReference systemArray = new GetClassTypeReference("System", "Array", 0); - static readonly GetClassTypeReference listInterface = new GetClassTypeReference("System.Collections.Generic", "IList", 1); - - public override IEnumerable GetBaseTypes(ITypeResolveContext context) + public override ITypeReference ToTypeReference() { - List baseTypes = new List(); - IType t = systemArray.Resolve(context); - if (t != SharedTypes.UnknownType) - baseTypes.Add(t); - if (dimensions == 1) { // single-dimensional arrays implement IList - ITypeDefinition def = listInterface.Resolve(context) as ITypeDefinition; - if (def != null) - baseTypes.Add(new ParameterizedType(def, new[] { elementType })); + return new ArrayTypeReference(elementType.ToTypeReference(), dimensions); + } + + public override IEnumerable DirectBaseTypes { + get { + List baseTypes = new List(); + IType t = compilation.FindType(KnownTypeCode.Array); + if (t.Kind != TypeKind.Unknown) + baseTypes.Add(t); + if (dimensions == 1) { // single-dimensional arrays implement IList + ITypeDefinition def = compilation.FindType(KnownTypeCode.IListOfT) as ITypeDefinition; + if (def != null) + baseTypes.Add(new ParameterizedType(def, new[] { elementType })); + } + return baseTypes; } - return baseTypes; } - public override IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + public override IEnumerable GetMethods(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - return systemArray.Resolve(context).GetMethods(context, filter, options); + return compilation.FindType(KnownTypeCode.Array).GetMethods(filter, options); } - static readonly DefaultParameter indexerParam = new DefaultParameter(KnownTypeReference.Int32, string.Empty); + //static readonly DefaultUnresolvedParameter indexerParam = new DefaultUnresolvedParameter(KnownTypeReference.Int32, string.Empty); - public override IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + public override IEnumerable GetProperties(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - ITypeDefinition arrayDef = systemArray.Resolve(context) as ITypeDefinition; + ITypeDefinition arrayDef = compilation.FindType(KnownTypeCode.Array) as ITypeDefinition; if (arrayDef != null) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == 0) { - foreach (IProperty p in arrayDef.GetProperties(context, filter, options)) { + foreach (IProperty p in arrayDef.GetProperties(filter, options)) { yield return p; } } - DefaultProperty indexer = new DefaultProperty(arrayDef, "Items") { + throw new NotImplementedException(); + /*DefaultProperty indexer = new DefaultProperty(arrayDef, "Items") { EntityType = EntityType.Indexer, ReturnType = elementType, Accessibility = Accessibility.Public, @@ -114,11 +120,11 @@ namespace ICSharpCode.NRefactory.TypeSystem indexer.Freeze(); if (filter == null || filter(indexer)) { yield return indexer; - } + }*/ } } - // Events, Fields: System.Array doesn't have any; so we can use the AbstractType default implementation + // NestedTypes, Events, Fields: System.Array doesn't have any; so we can use the AbstractType default implementation // that simply returns an empty list public override IType AcceptVisitor(TypeVisitor visitor) @@ -132,23 +138,7 @@ namespace ICSharpCode.NRefactory.TypeSystem if (e == elementType) return this; else - return new ArrayType(e, dimensions); - } - - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - elementType = provider.Intern(elementType); - } - - int ISupportsInterning.GetHashCodeForInterning() - { - return elementType.GetHashCode() ^ dimensions; - } - - bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) - { - ArrayType o = other as ArrayType; - return o != null && elementType == o.elementType && dimensions == o.dimensions; + return new ArrayType(compilation, e, dimensions); } } @@ -178,7 +168,7 @@ namespace ICSharpCode.NRefactory.TypeSystem public IType Resolve(ITypeResolveContext context) { - return new ArrayType(elementType.Resolve(context), dimensions); + return new ArrayType(context.Compilation, elementType.Resolve(context), dimensions); } public override string ToString() @@ -186,14 +176,6 @@ namespace ICSharpCode.NRefactory.TypeSystem return elementType.ToString() + "[" + new string(',', dimensions - 1) + "]"; } - public static ITypeReference Create(ITypeReference elementType, int dimensions) - { - if (elementType is IType) - return new ArrayType((IType)elementType, dimensions); - else - return new ArrayTypeReference(elementType, dimensions); - } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) { elementType = provider.Intern(elementType); diff --git a/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs b/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs index e8eb17f436..c2be96e363 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs @@ -21,7 +21,6 @@ using ICSharpCode.NRefactory.TypeSystem.Implementation; namespace ICSharpCode.NRefactory.TypeSystem { - [Serializable] public sealed class ByReferenceType : TypeWithElementType, ISupportsInterning { public ByReferenceType(IType elementType) : base(elementType) @@ -38,9 +37,8 @@ namespace ICSharpCode.NRefactory.TypeSystem } } - public override bool? IsReferenceType(ITypeResolveContext context) - { - return null; + public override bool? IsReferenceType { + get { return null; } } public override int GetHashCode() @@ -68,6 +66,11 @@ namespace ICSharpCode.NRefactory.TypeSystem return new ByReferenceType(e); } + public override ITypeReference ToTypeReference() + { + return new ByReferenceTypeReference(elementType.ToTypeReference()); + } + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) { elementType = provider.Intern(elementType); @@ -111,14 +114,6 @@ namespace ICSharpCode.NRefactory.TypeSystem return elementType.ToString() + "&"; } - public static ITypeReference Create(ITypeReference elementType) - { - if (elementType is IType) - return new ByReferenceType((IType)elementType); - else - return new ByReferenceTypeReference(elementType); - } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) { elementType = provider.Intern(elementType); diff --git a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs index a2085d64eb..314dcf0b9e 100644 --- a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs +++ b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs @@ -25,7 +25,9 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Threading; +using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem.Implementation; +using ICSharpCode.NRefactory.Utils; using Mono.Cecil; namespace ICSharpCode.NRefactory.TypeSystem @@ -38,14 +40,6 @@ namespace ICSharpCode.NRefactory.TypeSystem public class CecilLoader { #region Options - /// - /// Gets/Sets the early bind context. - /// This context is used to pre-resolve type references - setting this property will cause the CecilLoader - /// to directly reference the resolved types, and create links () to types - /// that could not be resolved. - /// - public ITypeResolveContext EarlyBindContext { get; set; } - /// /// Specifies whether to include internal members. The default is false. /// @@ -96,58 +90,51 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// IProjectContent that represents the assembly [CLSCompliant(false)] - public IProjectContent LoadAssembly(AssemblyDefinition assemblyDefinition) + public IUnresolvedAssembly LoadAssembly(AssemblyDefinition assemblyDefinition) { if (assemblyDefinition == null) throw new ArgumentNullException("assemblyDefinition"); - ITypeResolveContext oldEarlyBindContext = this.EarlyBindContext; - try { - // Read assembly and module attributes - IList assemblyAttributes = new List(); - IList moduleAttributes = new List(); - AddAttributes(assemblyDefinition, assemblyAttributes); - AddAttributes(assemblyDefinition.MainModule, moduleAttributes); - - if (this.InterningProvider != null) { - assemblyAttributes = this.InterningProvider.InternList(assemblyAttributes); - moduleAttributes = this.InterningProvider.InternList(moduleAttributes); - } else { - assemblyAttributes = new ReadOnlyCollection(assemblyAttributes); - moduleAttributes = new ReadOnlyCollection(moduleAttributes); - } - TypeStorage typeStorage = new TypeStorage(); - CecilProjectContent pc = new CecilProjectContent(typeStorage, assemblyDefinition.Name.FullName, assemblyAttributes, moduleAttributes, this.DocumentationProvider); - - this.EarlyBindContext = CompositeTypeResolveContext.Combine(pc, this.EarlyBindContext); - List types = new List(); - foreach (ModuleDefinition module in assemblyDefinition.Modules) { - foreach (TypeDefinition td in module.Types) { - this.CancellationToken.ThrowIfCancellationRequested(); - if (this.IncludeInternalMembers || (td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) { - string name = td.FullName; - if (name.Length == 0 || name[0] == '<') - continue; - if (name == "System.Void") { - var c = new VoidTypeDefinition(pc); - AddAttributes(td, c); - typeStorage.UpdateType(c); - } else { - CecilTypeDefinition c = new CecilTypeDefinition(pc, td); - types.Add(c); - typeStorage.UpdateType(c); - } - } + + // Read assembly and module attributes + IList assemblyAttributes = new List(); + IList moduleAttributes = new List(); + AddAttributes(assemblyDefinition, assemblyAttributes); + AddAttributes(assemblyDefinition.MainModule, moduleAttributes); + + if (this.InterningProvider != null) { + assemblyAttributes = this.InterningProvider.InternList(assemblyAttributes); + moduleAttributes = this.InterningProvider.InternList(moduleAttributes); + } + assemblyAttributes = FreezableHelper.FreezeListAndElements(assemblyAttributes); + moduleAttributes = FreezableHelper.FreezeListAndElements(moduleAttributes); + + /* + TypeStorage typeStorage = new TypeStorage(); + CecilProjectContent pc = new CecilProjectContent(typeStorage, assemblyDefinition.Name.FullName, assemblyAttributes, moduleAttributes, this.DocumentationProvider); + + this.EarlyBindContext = CompositeTypeResolveContext.Combine(pc, this.EarlyBindContext); + List types = new List(); + foreach (ModuleDefinition module in assemblyDefinition.Modules) { + foreach (TypeDefinition td in module.Types) { + this.CancellationToken.ThrowIfCancellationRequested(); + if (this.IncludeInternalMembers || (td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) { + string name = td.FullName; + if (name.Length == 0 || name[0] == '<') + continue; + + CecilTypeDefinition c = new CecilTypeDefinition(td); + types.Add(c); + typeStorage.UpdateType(c); } } - foreach (CecilTypeDefinition c in types) { - c.Init(this); - } - if (HasCecilReferences) - typeSystemTranslationTable[pc] = assemblyDefinition; - return pc; - } finally { - this.EarlyBindContext = oldEarlyBindContext; } + foreach (CecilTypeDefinition c in types) { + c.Init(this); + } + if (HasCecilReferences) + typeSystemTranslationTable[pc] = assemblyDefinition; + return pc;*/ + throw new NotImplementedException(); } /// @@ -157,21 +144,21 @@ namespace ICSharpCode.NRefactory.TypeSystem /// The project content used as parent for the new type. /// ITypeDefinition representing the Cecil type. [CLSCompliant(false)] - public ITypeDefinition LoadType(TypeDefinition typeDefinition, IProjectContent projectContent) + public ITypeDefinition LoadType(TypeDefinition typeDefinition) { if (typeDefinition == null) throw new ArgumentNullException("typeDefinition"); - if (projectContent == null) - throw new ArgumentNullException("projectContent"); - var c = new CecilTypeDefinition(projectContent, typeDefinition); + throw new NotImplementedException(); + /*var c = new CecilTypeDefinition(typeDefinition); c.Init(this); - return c; + return c;*/ } #endregion - #region IProjectContent implementation + #region IUnresolvedAssembly implementation + /* [Serializable] - sealed class CecilProjectContent : ProxyTypeResolveContext, IProjectContent, ISynchronizedTypeResolveContext, IDocumentationProvider + sealed class CecilProjectContent : IUnresolvedAssembly, IDocumentationProvider { readonly string assemblyName; readonly IList assemblyAttributes; @@ -207,17 +194,6 @@ namespace ICSharpCode.NRefactory.TypeSystem return "[CecilProjectContent " + assemblyName + "]"; } - public override ISynchronizedTypeResolveContext Synchronize() - { - // CecilProjectContent is immutable, so we don't need to synchronize - return this; - } - - void IDisposable.Dispose() - { - // Disposing the synchronization context has no effect - } - IParsedFile IProjectContent.GetFile(string fileName) { return null; @@ -229,7 +205,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } } - void IProjectContent.UpdateProjectContent(IParsedFile oldFile, IParsedFile newFile) + IProjectContent IProjectContent.UpdateProjectContent(IParsedFile oldFile, IParsedFile newFile) { throw new NotSupportedException(); } @@ -269,10 +245,11 @@ namespace ICSharpCode.NRefactory.TypeSystem { } } + */ #endregion #region Load Assembly From Disk - public IProjectContent LoadAssemblyFile(string fileName) + public IUnresolvedAssembly LoadAssemblyFile(string fileName) { if (fileName == null) throw new ArgumentNullException("fileName"); @@ -320,76 +297,54 @@ namespace ICSharpCode.NRefactory.TypeSystem /// The entity that owns this type reference. /// Used for generic type references. [CLSCompliant(false)] - public ITypeReference ReadTypeReference( - TypeReference type, - ICustomAttributeProvider typeAttributes = null, - IEntity entity = null) + public ITypeReference ReadTypeReference(TypeReference type, ICustomAttributeProvider typeAttributes = null) { int typeIndex = 0; - return CreateType(type, entity, typeAttributes, ref typeIndex); + return CreateType(type, typeAttributes, ref typeIndex); } - ITypeReference CreateType( - TypeReference type, - IEntity entity, - ICustomAttributeProvider typeAttributes, ref int typeIndex) + ITypeReference CreateType(TypeReference type, ICustomAttributeProvider typeAttributes, ref int typeIndex) { while (type is OptionalModifierType || type is RequiredModifierType) { type = ((TypeSpecification)type).ElementType; } if (type == null) { - return SharedTypes.UnknownType; + return SpecialType.UnknownType; } if (type is Mono.Cecil.ByReferenceType) { typeIndex++; - return ByReferenceTypeReference.Create( + return new ByReferenceTypeReference( CreateType( (type as Mono.Cecil.ByReferenceType).ElementType, - entity, typeAttributes, ref typeIndex)); + typeAttributes, ref typeIndex)); } else if (type is Mono.Cecil.PointerType) { typeIndex++; - return PointerTypeReference.Create( + return new PointerTypeReference( CreateType( (type as Mono.Cecil.PointerType).ElementType, - entity, typeAttributes, ref typeIndex)); + typeAttributes, ref typeIndex)); } else if (type is Mono.Cecil.ArrayType) { typeIndex++; - return ArrayTypeReference.Create( + return new ArrayTypeReference( CreateType( (type as Mono.Cecil.ArrayType).ElementType, - entity, typeAttributes, ref typeIndex), + typeAttributes, ref typeIndex), (type as Mono.Cecil.ArrayType).Rank); } else if (type is GenericInstanceType) { GenericInstanceType gType = (GenericInstanceType)type; - ITypeReference baseType = CreateType(gType.ElementType, entity, typeAttributes, ref typeIndex); + ITypeReference baseType = CreateType(gType.ElementType, typeAttributes, ref typeIndex); ITypeReference[] para = new ITypeReference[gType.GenericArguments.Count]; for (int i = 0; i < para.Length; ++i) { typeIndex++; - para[i] = CreateType(gType.GenericArguments[i], entity, typeAttributes, ref typeIndex); + para[i] = CreateType(gType.GenericArguments[i], typeAttributes, ref typeIndex); } - return ParameterizedTypeReference.Create(baseType, para); + return new ParameterizedTypeReference(baseType, para); } else if (type is GenericParameter) { - GenericParameter typeGP = type as GenericParameter; - if (typeGP.Owner is MethodDefinition) { - IMethod method = entity as IMethod; - if (method != null) { - if (typeGP.Position < method.TypeParameters.Count) { - return method.TypeParameters[typeGP.Position]; - } - } - return SharedTypes.UnknownType; - } else { - ITypeDefinition c = (entity as ITypeDefinition) ?? (entity is IMember ? ((IMember)entity).DeclaringTypeDefinition : null); - if (c != null && typeGP.Position < c.TypeParameters.Count) { - if (c.TypeParameters[typeGP.Position].Name == type.Name) { - return c.TypeParameters[typeGP.Position]; - } - } - return SharedTypes.UnknownType; - } + GenericParameter typeGP = (GenericParameter)type; + return new TypeParameterReference(typeGP.Owner is MethodDefinition ? EntityType.Method : EntityType.TypeDefinition, typeGP.Position); } else if (type.IsNested) { - ITypeReference typeRef = CreateType(type.DeclaringType, entity, typeAttributes, ref typeIndex); + ITypeReference typeRef = CreateType(type.DeclaringType, typeAttributes, ref typeIndex); int partTypeParameterCount; string namepart = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out partTypeParameterCount); return new NestedTypeReference(typeRef, namepart, partTypeParameterCount); @@ -400,17 +355,18 @@ namespace ICSharpCode.NRefactory.TypeSystem throw new InvalidOperationException("type.Name returned null. Type: " + type.ToString()); if (name == "Object" && ns == "System" && HasDynamicAttribute(typeAttributes, typeIndex)) { - return SharedTypes.Dynamic; + return SpecialType.Dynamic; } else { int typeParameterCount; name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name, out typeParameterCount); - var earlyBindContext = this.EarlyBindContext; + /*var earlyBindContext = this.EarlyBindContext; if (earlyBindContext != null) { IType c = earlyBindContext.GetTypeDefinition(ns, name, typeParameterCount, StringComparer.Ordinal); if (c != null) return c; } - return new GetClassTypeReference(ns, name, typeParameterCount); + return new GetClassTypeReference(ns, name, typeParameterCount);*/ + throw new NotImplementedException(); } } } @@ -439,7 +395,7 @@ namespace ICSharpCode.NRefactory.TypeSystem static readonly ITypeReference typeForwardedToAttributeTypeRef = typeof(TypeForwardedToAttribute).ToTypeReference(); static readonly ITypeReference assemblyVersionAttributeTypeRef = typeof(System.Reflection.AssemblyVersionAttribute).ToTypeReference(); - void AddAttributes(AssemblyDefinition assembly, IList outputList) + void AddAttributes(AssemblyDefinition assembly, IList outputList) { if (assembly.HasCustomAttributes) { AddCustomAttributes(assembly.CustomAttributes, outputList); @@ -450,7 +406,7 @@ namespace ICSharpCode.NRefactory.TypeSystem // AssemblyVersionAttribute if (assembly.Name.Version != null) { - var assemblyVersion = new DefaultAttribute(assemblyVersionAttributeTypeRef, new[] { KnownTypeReference.String }); + var assemblyVersion = new DefaultUnresolvedAttribute(assemblyVersionAttributeTypeRef, new[] { KnownTypeReference.String }); assemblyVersion.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.String, assembly.Name.Version.ToString())); outputList.Add(assemblyVersion); } @@ -460,7 +416,7 @@ namespace ICSharpCode.NRefactory.TypeSystem if (type.IsForwarder) { int typeParameterCount; string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); - var typeForwardedTo = new DefaultAttribute(typeForwardedToAttributeTypeRef, new[] { KnownTypeReference.Type }); + var typeForwardedTo = new DefaultUnresolvedAttribute(typeForwardedToAttributeTypeRef, new[] { KnownTypeReference.Type }); var typeRef = new GetClassTypeReference(type.Namespace, name, typeParameterCount); typeForwardedTo.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.Type, typeRef)); outputList.Add(typeForwardedTo); @@ -470,7 +426,7 @@ namespace ICSharpCode.NRefactory.TypeSystem #endregion #region Module Attributes - void AddAttributes(ModuleDefinition module, IList outputList) + void AddAttributes(ModuleDefinition module, IList outputList) { if (module.HasCustomAttributes) { AddCustomAttributes(module.CustomAttributes, outputList); @@ -479,10 +435,10 @@ namespace ICSharpCode.NRefactory.TypeSystem #endregion #region Parameter Attributes - static readonly IAttribute inAttribute = new DefaultAttribute(typeof(InAttribute).ToTypeReference(), null); - static readonly IAttribute outAttribute = new DefaultAttribute(typeof(OutAttribute).ToTypeReference(), null); + static readonly IUnresolvedAttribute inAttribute = new DefaultUnresolvedAttribute(typeof(InAttribute).ToTypeReference()); + static readonly IUnresolvedAttribute outAttribute = new DefaultUnresolvedAttribute(typeof(OutAttribute).ToTypeReference()); - void AddAttributes(ParameterDefinition parameter, DefaultParameter targetParameter) + void AddAttributes(ParameterDefinition parameter, DefaultUnresolvedParameter targetParameter) { if (!targetParameter.IsOut) { if (parameter.IsIn) @@ -502,9 +458,9 @@ namespace ICSharpCode.NRefactory.TypeSystem #region Method Attributes static readonly ITypeReference dllImportAttributeTypeRef = typeof(DllImportAttribute).ToTypeReference(); static readonly SimpleConstantValue trueValue = new SimpleConstantValue(KnownTypeReference.Boolean, true); - static readonly SimpleConstantValue falseValue = new SimpleConstantValue(KnownTypeReference.Boolean, true); + static readonly SimpleConstantValue falseValue = new SimpleConstantValue(KnownTypeReference.Boolean, false); static readonly ITypeReference callingConventionTypeRef = typeof(CallingConvention).ToTypeReference(); - static readonly IAttribute preserveSigAttribute = new DefaultAttribute(typeof(PreserveSigAttribute).ToTypeReference(), null); + static readonly IUnresolvedAttribute preserveSigAttribute = new DefaultUnresolvedAttribute(typeof(PreserveSigAttribute).ToTypeReference()); static readonly ITypeReference methodImplAttributeTypeRef = typeof(MethodImplAttribute).ToTypeReference(); static readonly ITypeReference methodImplOptionsTypeRef = typeof(MethodImplOptions).ToTypeReference(); @@ -519,20 +475,20 @@ namespace ICSharpCode.NRefactory.TypeSystem return methodDefinition.HasCustomAttributes || methodDefinition.MethodReturnType.HasCustomAttributes; } - void AddAttributes(MethodDefinition methodDefinition, IList attributes, IList returnTypeAttributes) + void AddAttributes(MethodDefinition methodDefinition, IList attributes, IList returnTypeAttributes) { MethodImplAttributes implAttributes = methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask; #region DllImportAttribute if (methodDefinition.HasPInvokeInfo) { PInvokeInfo info = methodDefinition.PInvokeInfo; - DefaultAttribute dllImport = new DefaultAttribute(dllImportAttributeTypeRef, new[] { KnownTypeReference.String }); + var dllImport = new DefaultUnresolvedAttribute(dllImportAttributeTypeRef, new[] { KnownTypeReference.String }); dllImport.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.String, info.Module.Name)); if (info.IsBestFitDisabled) - dllImport.AddNamedArgument("BestFitMapping", falseValue); + dllImport.AddNamedFieldArgument("BestFitMapping", falseValue); if (info.IsBestFitEnabled) - dllImport.AddNamedArgument("BestFitMapping", trueValue); + dllImport.AddNamedFieldArgument("BestFitMapping", trueValue); CallingConvention callingConvention; switch (info.Attributes & PInvokeAttributes.CallConvMask) { @@ -555,7 +511,7 @@ namespace ICSharpCode.NRefactory.TypeSystem throw new NotSupportedException("unknown calling convention"); } if (callingConvention != CallingConvention.Winapi) - dllImport.AddNamedArgument("CallingConvention", callingConventionTypeRef, (int)callingConvention); + dllImport.AddNamedFieldArgument("CallingConvention", callingConventionTypeRef, (int)callingConvention); CharSet charSet = CharSet.None; switch (info.Attributes & PInvokeAttributes.CharSetMask) { @@ -570,26 +526,26 @@ namespace ICSharpCode.NRefactory.TypeSystem break; } if (charSet != CharSet.None) - dllImport.AddNamedArgument("CharSet", charSetTypeRef, (int)charSet); + dllImport.AddNamedFieldArgument("CharSet", charSetTypeRef, (int)charSet); if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != methodDefinition.Name) - dllImport.AddNamedArgument("EntryPoint", KnownTypeReference.String, info.EntryPoint); + dllImport.AddNamedFieldArgument("EntryPoint", KnownTypeReference.String, info.EntryPoint); if (info.IsNoMangle) - dllImport.AddNamedArgument("ExactSpelling", trueValue); + dllImport.AddNamedFieldArgument("ExactSpelling", trueValue); if ((implAttributes & MethodImplAttributes.PreserveSig) == MethodImplAttributes.PreserveSig) implAttributes &= ~MethodImplAttributes.PreserveSig; else - dllImport.AddNamedArgument("PreserveSig", falseValue); + dllImport.AddNamedFieldArgument("PreserveSig", falseValue); if (info.SupportsLastError) - dllImport.AddNamedArgument("SetLastError", trueValue); + dllImport.AddNamedFieldArgument("SetLastError", trueValue); if (info.IsThrowOnUnmappableCharDisabled) - dllImport.AddNamedArgument("ThrowOnUnmappableChar", falseValue); + dllImport.AddNamedFieldArgument("ThrowOnUnmappableChar", falseValue); if (info.IsThrowOnUnmappableCharEnabled) - dllImport.AddNamedArgument("ThrowOnUnmappableChar", trueValue); + dllImport.AddNamedFieldArgument("ThrowOnUnmappableChar", trueValue); attributes.Add(dllImport); } @@ -604,7 +560,7 @@ namespace ICSharpCode.NRefactory.TypeSystem #region MethodImplAttribute if (implAttributes != 0) { - DefaultAttribute methodImpl = new DefaultAttribute(methodImplAttributeTypeRef, new[] { methodImplOptionsTypeRef }); + var methodImpl = new DefaultUnresolvedAttribute(methodImplAttributeTypeRef, new[] { methodImplOptionsTypeRef }); methodImpl.PositionalArguments.Add(new SimpleConstantValue(methodImplOptionsTypeRef, (int)implAttributes)); attributes.Add(methodImpl); } @@ -626,13 +582,13 @@ namespace ICSharpCode.NRefactory.TypeSystem #endregion #region Type Attributes - static readonly DefaultAttribute serializableAttribute = new DefaultAttribute(typeof(SerializableAttribute).ToTypeReference(), null); - static readonly DefaultAttribute comImportAttribute = new DefaultAttribute(typeof(ComImportAttribute).ToTypeReference(), null); + static readonly DefaultUnresolvedAttribute serializableAttribute = new DefaultUnresolvedAttribute(typeof(SerializableAttribute).ToTypeReference()); + static readonly DefaultUnresolvedAttribute comImportAttribute = new DefaultUnresolvedAttribute(typeof(ComImportAttribute).ToTypeReference()); static readonly ITypeReference structLayoutAttributeTypeRef = typeof(StructLayoutAttribute).ToTypeReference(); static readonly ITypeReference layoutKindTypeRef = typeof(LayoutKind).ToTypeReference(); static readonly ITypeReference charSetTypeRef = typeof(CharSet).ToTypeReference(); - void AddAttributes(TypeDefinition typeDefinition, ITypeDefinition targetEntity) + void AddAttributes(TypeDefinition typeDefinition, IUnresolvedTypeDefinition targetEntity) { // SerializableAttribute if (typeDefinition.IsSerializable) @@ -666,16 +622,16 @@ namespace ICSharpCode.NRefactory.TypeSystem } LayoutKind defaultLayoutKind = (typeDefinition.IsValueType && !typeDefinition.IsEnum) ? LayoutKind.Sequential: LayoutKind.Auto; if (layoutKind != defaultLayoutKind || charSet != CharSet.Ansi || typeDefinition.PackingSize > 0 || typeDefinition.ClassSize > 0) { - DefaultAttribute structLayout = new DefaultAttribute(structLayoutAttributeTypeRef, new[] { layoutKindTypeRef }); + DefaultUnresolvedAttribute structLayout = new DefaultUnresolvedAttribute(structLayoutAttributeTypeRef, new[] { layoutKindTypeRef }); structLayout.PositionalArguments.Add(new SimpleConstantValue(layoutKindTypeRef, (int)layoutKind)); if (charSet != CharSet.Ansi) { - structLayout.AddNamedArgument("CharSet", charSetTypeRef, (int)charSet); + structLayout.AddNamedFieldArgument("CharSet", charSetTypeRef, (int)charSet); } if (typeDefinition.PackingSize > 0) { - structLayout.AddNamedArgument("Pack", KnownTypeReference.Int32, (int)typeDefinition.PackingSize); + structLayout.AddNamedFieldArgument("Pack", KnownTypeReference.Int32, (int)typeDefinition.PackingSize); } if (typeDefinition.ClassSize > 0) { - structLayout.AddNamedArgument("Size", KnownTypeReference.Int32, (int)typeDefinition.ClassSize); + structLayout.AddNamedFieldArgument("Size", KnownTypeReference.Int32, (int)typeDefinition.ClassSize); } targetEntity.Attributes.Add(structLayout); } @@ -692,13 +648,13 @@ namespace ICSharpCode.NRefactory.TypeSystem #region Field Attributes static readonly ITypeReference fieldOffsetAttributeTypeRef = typeof(FieldOffsetAttribute).ToTypeReference(); - static readonly DefaultAttribute nonSerializedAttribute = new DefaultAttribute(typeof(NonSerializedAttribute).ToTypeReference(), null); + static readonly IUnresolvedAttribute nonSerializedAttribute = new DefaultUnresolvedAttribute(typeof(NonSerializedAttribute).ToTypeReference()); - void AddAttributes(FieldDefinition fieldDefinition, IEntity targetEntity) + void AddAttributes(FieldDefinition fieldDefinition, IUnresolvedEntity targetEntity) { // FieldOffsetAttribute if (fieldDefinition.HasLayoutInfo) { - DefaultAttribute fieldOffset = new DefaultAttribute(fieldOffsetAttributeTypeRef, new[] { KnownTypeReference.Int32 }); + DefaultUnresolvedAttribute fieldOffset = new DefaultUnresolvedAttribute(fieldOffsetAttributeTypeRef, new[] { KnownTypeReference.Int32 }); fieldOffset.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.Int32, fieldDefinition.Offset)); targetEntity.Attributes.Add(fieldOffset); } @@ -719,7 +675,7 @@ namespace ICSharpCode.NRefactory.TypeSystem #endregion #region Event Attributes - void AddAttributes(EventDefinition eventDefinition, IEntity targetEntity) + void AddAttributes(EventDefinition eventDefinition, IUnresolvedEntity targetEntity) { if (eventDefinition.HasCustomAttributes) { AddCustomAttributes(eventDefinition.CustomAttributes, targetEntity.Attributes); @@ -728,7 +684,7 @@ namespace ICSharpCode.NRefactory.TypeSystem #endregion #region Property Attributes - void AddAttributes(PropertyDefinition propertyDefinition, IEntity targetEntity) + void AddAttributes(PropertyDefinition propertyDefinition, IUnresolvedEntity targetEntity) { if (propertyDefinition.HasCustomAttributes) { AddCustomAttributes(propertyDefinition.CustomAttributes, targetEntity.Attributes); @@ -740,39 +696,39 @@ namespace ICSharpCode.NRefactory.TypeSystem static readonly ITypeReference marshalAsAttributeTypeRef = typeof(MarshalAsAttribute).ToTypeReference(); static readonly ITypeReference unmanagedTypeTypeRef = typeof(UnmanagedType).ToTypeReference(); - static IAttribute ConvertMarshalInfo(MarshalInfo marshalInfo) + static IUnresolvedAttribute ConvertMarshalInfo(MarshalInfo marshalInfo) { - DefaultAttribute attr = new DefaultAttribute(marshalAsAttributeTypeRef, new[] { unmanagedTypeTypeRef }); + DefaultUnresolvedAttribute attr = new DefaultUnresolvedAttribute(marshalAsAttributeTypeRef, new[] { unmanagedTypeTypeRef }); attr.PositionalArguments.Add(new SimpleConstantValue(unmanagedTypeTypeRef, (int)marshalInfo.NativeType)); FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo; if (fami != null) { - attr.AddNamedArgument("SizeConst", KnownTypeReference.Int32, (int)fami.Size); + attr.AddNamedFieldArgument("SizeConst", KnownTypeReference.Int32, (int)fami.Size); if (fami.ElementType != NativeType.None) - attr.AddNamedArgument("ArraySubType", unmanagedTypeTypeRef, (int)fami.ElementType); + attr.AddNamedFieldArgument("ArraySubType", unmanagedTypeTypeRef, (int)fami.ElementType); } SafeArrayMarshalInfo sami = marshalInfo as SafeArrayMarshalInfo; if (sami != null && sami.ElementType != VariantType.None) { - attr.AddNamedArgument("SafeArraySubType", typeof(VarEnum).ToTypeReference(), (int)sami.ElementType); + attr.AddNamedFieldArgument("SafeArraySubType", typeof(VarEnum).ToTypeReference(), (int)sami.ElementType); } ArrayMarshalInfo ami = marshalInfo as ArrayMarshalInfo; if (ami != null) { if (ami.ElementType != NativeType.Max) - attr.AddNamedArgument("ArraySubType", unmanagedTypeTypeRef, (int)ami.ElementType); + attr.AddNamedFieldArgument("ArraySubType", unmanagedTypeTypeRef, (int)ami.ElementType); if (ami.Size >= 0) - attr.AddNamedArgument("SizeConst", KnownTypeReference.Int32, (int)ami.Size); + attr.AddNamedFieldArgument("SizeConst", KnownTypeReference.Int32, (int)ami.Size); if (ami.SizeParameterMultiplier != 0 && ami.SizeParameterIndex >= 0) - attr.AddNamedArgument("SizeParamIndex", KnownTypeReference.Int16, (short)ami.SizeParameterIndex); + attr.AddNamedFieldArgument("SizeParamIndex", KnownTypeReference.Int16, (short)ami.SizeParameterIndex); } CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo; if (cmi != null) { - attr.AddNamedArgument("MarshalType", KnownTypeReference.String, cmi.ManagedType.FullName); + attr.AddNamedFieldArgument("MarshalType", KnownTypeReference.String, cmi.ManagedType.FullName); if (!string.IsNullOrEmpty(cmi.Cookie)) - attr.AddNamedArgument("MarshalCookie", KnownTypeReference.String, cmi.Cookie); + attr.AddNamedFieldArgument("MarshalCookie", KnownTypeReference.String, cmi.Cookie); } FixedSysStringMarshalInfo fssmi = marshalInfo as FixedSysStringMarshalInfo; if (fssmi != null) { - attr.AddNamedArgument("SizeConst", KnownTypeReference.Int32, (int)fssmi.Size); + attr.AddNamedFieldArgument("SizeConst", KnownTypeReference.Int32, (int)fssmi.Size); } return attr; @@ -780,7 +736,7 @@ namespace ICSharpCode.NRefactory.TypeSystem #endregion #region Custom Attributes (ReadAttribute) - void AddCustomAttributes(Mono.Collections.Generic.Collection attributes, IList targetCollection) + void AddCustomAttributes(Mono.Collections.Generic.Collection attributes, IList targetCollection) { foreach (var cecilAttribute in attributes) { TypeReference type = cecilAttribute.AttributeType; @@ -795,48 +751,188 @@ namespace ICSharpCode.NRefactory.TypeSystem } [CLSCompliant(false)] - public IAttribute ReadAttribute(CustomAttribute attribute) + public IUnresolvedAttribute ReadAttribute(CustomAttribute attribute) { if (attribute == null) throw new ArgumentNullException("attribute"); MethodReference ctor = attribute.Constructor; - ITypeReference[] ctorParameters = null; + ITypeReference attributeType = ReadTypeReference(attribute.AttributeType); + IList ctorParameterTypes = null; if (ctor.HasParameters) { - ctorParameters = new ITypeReference[ctor.Parameters.Count]; - for (int i = 0; i < ctorParameters.Length; i++) { - ctorParameters[i] = ReadTypeReference(ctor.Parameters[i].ParameterType); + ctorParameterTypes = new ITypeReference[ctor.Parameters.Count]; + for (int i = 0; i < ctorParameterTypes.Count; i++) { + ctorParameterTypes[i] = ReadTypeReference(ctor.Parameters[i].ParameterType); } } - DefaultAttribute a = new DefaultAttribute(ReadTypeReference(attribute.AttributeType), ctorParameters); - if (attribute.HasConstructorArguments) { - foreach (var arg in attribute.ConstructorArguments) { - a.PositionalArguments.Add(ReadConstantValue(arg)); + if (this.InterningProvider != null) { + attributeType = this.InterningProvider.Intern(attributeType); + ctorParameterTypes = this.InterningProvider.InternList(ctorParameterTypes); + } + return new CecilUnresolvedAttribute(attributeType, ctorParameterTypes, attribute.GetBlob()); + } + #endregion + + #region CecilUnresolvedAttribute + [Serializable] + sealed class CecilUnresolvedAttribute : IUnresolvedAttribute, ISupportsInterning + { + readonly ITypeReference attributeType; + internal readonly IList ctorParameterTypes; + internal readonly byte[] blob; + + public CecilUnresolvedAttribute(ITypeReference attributeType, IList ctorParameterTypes, byte[] blob) + { + this.attributeType = attributeType; + this.ctorParameterTypes = ctorParameterTypes; + this.blob = blob; + } + + public DomRegion Region { + get { return DomRegion.Empty; } + } + + public ITypeReference AttributeType { + get { return attributeType; } + } + + public IAttribute CreateResolvedAttribute(ITypeResolveContext context) + { + throw new NotImplementedException(); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + // We already interned our child elements in ReadAttribute(). + } + + int ISupportsInterning.GetHashCodeForInterning() + { + unchecked { + int hash = attributeType.GetHashCode() ^ ctorParameterTypes.GetHashCode(); + foreach (byte b in blob) { + hash *= 257; + hash += b; + } + return hash; } } - if (attribute.HasFields || attribute.HasProperties) { - foreach (var arg in attribute.Fields) { - a.NamedArguments.Add(new KeyValuePair(arg.Name, ReadConstantValue(arg.Argument))); + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + CecilUnresolvedAttribute o = other as CecilUnresolvedAttribute; + if (o != null && attributeType == o.attributeType && ctorParameterTypes == o.ctorParameterTypes && blob.Length == o.blob.Length) { + for (int i = 0; i < blob.Length; i++) { + if (blob[i] != o.blob[i]) + return false; + } + return true; + } else { + return false; + } + } + } + #endregion + + #region CecilResolvedAttribute + sealed class CecilResolvedAttribute : IAttribute + { + readonly ITypeResolveContext context; + readonly CecilUnresolvedAttribute unresolved; + readonly IType attributeType; + + IMethod constructor; + volatile bool constructorResolved; + + volatile IList positionalArguments; + volatile IList> namedArguments; + + public CecilResolvedAttribute(ITypeResolveContext context, CecilUnresolvedAttribute unresolved) + { + this.context = context; + this.unresolved = unresolved; + this.attributeType = unresolved.AttributeType.Resolve(context); + } + + public DomRegion Region { + get { return unresolved.Region; } + } + + public IType AttributeType { + get { return attributeType; } + } + + public IMethod Constructor { + get { + if (!constructorResolved) { + constructor = ResolveConstructor(); + constructorResolved = true; + } + return constructor; + } + } + + IMethod ResolveConstructor() + { + var parameterTypes = unresolved.ctorParameterTypes.Resolve(context); + foreach (var ctor in attributeType.GetConstructors(m => m.Parameters.Count == parameterTypes.Count)) { + bool ok = true; + for (int i = 0; i < parameterTypes.Count; i++) { + if (!ctor.Parameters[i].Type.Equals(parameterTypes[i])) { + ok = false; + break; + } + } + if (ok) + return ctor; } - foreach (var arg in attribute.Properties) { - a.NamedArguments.Add(new KeyValuePair(arg.Name, ReadConstantValue(arg.Argument))); + return null; + } + + public IList PositionalArguments { + get { + var result = this.positionalArguments; + if (result != null) + return result; + DecodeBlob(); + return positionalArguments; } } - return a; + + public IList> NamedArguments { + get { + var result = this.namedArguments; + if (result != null) + return result; + DecodeBlob(); + return namedArguments; + } + } + + public ICompilation Compilation { + get { return context.Compilation; } + } + + void DecodeBlob() + { + throw new NotImplementedException(); + } } #endregion #region Security Attributes static readonly ITypeReference securityActionTypeReference = typeof(SecurityAction).ToTypeReference(); - void AddSecurityAttributes(Mono.Collections.Generic.Collection securityDeclarations, IList targetCollection) + void AddSecurityAttributes(Mono.Collections.Generic.Collection securityDeclarations, IList targetCollection) { foreach (var secDecl in securityDeclarations) { try { foreach (var secAttribute in secDecl.SecurityAttributes) { ITypeReference attributeType = ReadTypeReference(secAttribute.AttributeType); - var a = new DefaultAttribute(attributeType, new[] { securityActionTypeReference }); + var a = new DefaultUnresolvedAttribute(attributeType, new[] { securityActionTypeReference }); a.PositionalArguments.Add(new SimpleConstantValue(securityActionTypeReference, (ushort)secDecl.Action)); + throw new NotImplementedException(); + /* if (secAttribute.HasFields || secAttribute.HasProperties) { foreach (var arg in secAttribute.Fields) { a.NamedArguments.Add(new KeyValuePair(arg.Name, ReadConstantValue(arg.Argument))); @@ -845,41 +941,18 @@ namespace ICSharpCode.NRefactory.TypeSystem a.NamedArguments.Add(new KeyValuePair(arg.Name, ReadConstantValue(arg.Argument))); } } - targetCollection.Add(a); + targetCollection.Add(a);*/ } } catch (ResolutionException) { // occurs when Cecil can't decode an argument + // TODO: use CecilAttribute so that we can do the blob decoding ourselves } } } #endregion #endregion - #region Read Constant Value - [CLSCompliant(false)] - public IConstantValue ReadConstantValue(CustomAttributeArgument arg) - { - object value = arg.Value; - if (value is CustomAttributeArgument) { - // Cecil uses this representation for boxed values - arg = (CustomAttributeArgument)value; - value = arg.Value; - } - ITypeReference type = ReadTypeReference(arg.Type); - CustomAttributeArgument[] array = value as CustomAttributeArgument[]; - if (array != null) { - // TODO: write unit test for this - // TODO: are multi-dimensional arrays possible as well? - throw new NotImplementedException(); - } - - TypeReference valueType = value as TypeReference; - if (valueType != null) - value = ReadTypeReference(valueType); - return new SimpleConstantValue(type, value); - } - #endregion - + /* #region Read Type Definition [Serializable] sealed class CecilTypeDefinition : DefaultTypeDefinition @@ -1401,7 +1474,7 @@ namespace ICSharpCode.NRefactory.TypeSystem member.ApplyInterningProvider(this.InterningProvider); if (HasCecilReferences) typeSystemTranslationTable[member] = cecilDefinition; - } + }*/ #region Type system translation table Dictionary typeSystemTranslationTable; @@ -1419,42 +1492,39 @@ namespace ICSharpCode.NRefactory.TypeSystem } [CLSCompliant(false)] - public AssemblyDefinition GetCecilObject (IProjectContent content) + public AssemblyDefinition GetCecilObject (IUnresolvedAssembly content) { return InternalGetCecilObject (content); } [CLSCompliant(false)] - public TypeDefinition GetCecilObject (ITypeDefinition type) + public TypeDefinition GetCecilObject (IUnresolvedTypeDefinition type) { if (type == null) throw new ArgumentNullException ("type"); - var cecilType = type as CecilTypeDefinition; - if (cecilType == null) - throw new ArgumentException ("type is no cecil type definition."); - return cecilType.typeDefinition; + return InternalGetCecilObject (type); } [CLSCompliant(false)] - public MethodDefinition GetCecilObject (IMethod method) + public MethodDefinition GetCecilObject (IUnresolvedMethod method) { return InternalGetCecilObject (method); } [CLSCompliant(false)] - public FieldDefinition GetCecilObject (IField field) + public FieldDefinition GetCecilObject (IUnresolvedField field) { return InternalGetCecilObject (field); } [CLSCompliant(false)] - public EventDefinition GetCecilObject (IEvent evt) + public EventDefinition GetCecilObject (IUnresolvedEvent evt) { return InternalGetCecilObject (evt); } [CLSCompliant(false)] - public PropertyDefinition GetCecilObject (IProperty property) + public PropertyDefinition GetCecilObject (IUnresolvedProperty property) { return InternalGetCecilObject (property); } diff --git a/ICSharpCode.NRefactory/TypeSystem/DomRegion.cs b/ICSharpCode.NRefactory/TypeSystem/DomRegion.cs index 523b60ed94..afa276ccc6 100644 --- a/ICSharpCode.NRefactory/TypeSystem/DomRegion.cs +++ b/ICSharpCode.NRefactory/TypeSystem/DomRegion.cs @@ -30,7 +30,7 @@ namespace ICSharpCode.NRefactory.TypeSystem readonly int beginColumn; readonly int endColumn; - public readonly static DomRegion Empty = new DomRegion(null, -1, -1); + public readonly static DomRegion Empty = new DomRegion(); public bool IsEmpty { get { @@ -161,8 +161,8 @@ namespace ICSharpCode.NRefactory.TypeSystem { return string.Format( CultureInfo.InvariantCulture, - "[DomRegion FileName={0}, BeginLine={1}, EndLine={2}, BeginColumn={3}, EndColumn={4}]", - fileName, beginLine, endLine, beginColumn, endColumn); + "[DomRegion FileName={0}, Begin=({1}, {2}), End=({3}, {4})]", + fileName, beginLine, beginColumn, endLine, endColumn); } public override bool Equals(object obj) @@ -174,15 +174,15 @@ namespace ICSharpCode.NRefactory.TypeSystem { unchecked { int hashCode = fileName != null ? fileName.GetHashCode() : 0; - hashCode ^= BeginColumn + 1100009 * BeginLine + 1200007 * BeginColumn + 1300021 * EndColumn; + hashCode ^= beginColumn + 1100009 * beginLine + 1200007 * endLine + 1300021 * endColumn; return hashCode; } } public bool Equals(DomRegion other) { - return BeginLine == other.BeginLine && BeginColumn == other.BeginColumn - && EndLine == other.EndLine && EndColumn == other.EndColumn + return beginLine == other.beginLine && beginColumn == other.beginColumn + && endLine == other.endLine && endColumn == other.endColumn && fileName == other.fileName; } diff --git a/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs b/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs index 2a98f1ccc9..e8a20fbcf6 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; +using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.Utils; @@ -39,9 +40,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// The output is ordered so that base types occur before derived types. /// - public static IEnumerable GetAllBaseTypes(this IType type, ITypeResolveContext context) + public static IEnumerable GetAllBaseTypes(this IType type) { - BaseTypeCollector collector = new BaseTypeCollector(context); + BaseTypeCollector collector = new BaseTypeCollector(); collector.CollectBaseTypes(type); return collector; } @@ -54,9 +55,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// The output is ordered so that base types occur before derived types. /// - public static IEnumerable GetNonInterfaceBaseTypes(this IType type, ITypeResolveContext context) + public static IEnumerable GetNonInterfaceBaseTypes(this IType type) { - BaseTypeCollector collector = new BaseTypeCollector(context); + BaseTypeCollector collector = new BaseTypeCollector(); collector.SkipImplementedInterfaces = true; collector.CollectBaseTypes(type); return collector; @@ -70,16 +71,14 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// This is equivalent to type.GetAllBaseTypes().Select(t => t.GetDefinition()).Where(d => d != null).Distinct(). /// - public static IEnumerable GetAllBaseTypeDefinitions(this IType type, ITypeResolveContext context) + public static IEnumerable GetAllBaseTypeDefinitions(this IType type) { if (type == null) throw new ArgumentNullException("type"); - if (context == null) - throw new ArgumentNullException("context"); HashSet typeDefinitions = new HashSet(); Func> recursion = - t => t.GetBaseTypes(context).Select(b => b.GetDefinition()).Where(d => d != null && typeDefinitions.Add(d)); + t => t.DirectBaseTypes.Select(b => b.GetDefinition()).Where(d => d != null && typeDefinitions.Add(d)); ITypeDefinition typeDef = type.GetDefinition(); if (typeDef != null) { @@ -87,7 +86,7 @@ namespace ICSharpCode.NRefactory.TypeSystem return TreeTraversal.PreOrder(typeDef, recursion); } else { return TreeTraversal.PreOrder( - type.GetBaseTypes(context).Select(b => b.GetDefinition()).Where(d => d != null && typeDefinitions.Add(d)), + type.DirectBaseTypes.Select(b => b.GetDefinition()).Where(d => d != null && typeDefinitions.Add(d)), recursion); } } @@ -95,9 +94,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Gets whether this type definition is derived from the base type defintiion. /// - public static bool IsDerivedFrom(this ITypeDefinition type, ITypeDefinition baseType, ITypeResolveContext context) + public static bool IsDerivedFrom(this ITypeDefinition type, ITypeDefinition baseType) { - return GetAllBaseTypeDefinitions(type, context).Contains(baseType); + return GetAllBaseTypeDefinitions(type).Contains(baseType); } #endregion @@ -151,50 +150,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } #endregion - #region IsEnum / IsDelegate - /// - /// Gets whether the type is an enumeration type. - /// - [Obsolete("Use type.Kind == TypeKind.Enum instead")] - public static bool IsEnum(this IType type) - { - if (type == null) - throw new ArgumentNullException("type"); - return type.Kind == TypeKind.Enum; - } - - /// - /// Gets the underlying type for this enum type. - /// - public static IType GetEnumUnderlyingType(this IType enumType, ITypeResolveContext context) - { - if (enumType == null) - throw new ArgumentNullException("enumType"); - if (context == null) - throw new ArgumentNullException("context"); - ITypeDefinition def = enumType.GetDefinition(); - if (def != null && def.Kind == TypeKind.Enum) { - if (def.BaseTypes.Count == 1) - return def.BaseTypes[0].Resolve(context); - else - return KnownTypeReference.Int32.Resolve(context); - } else { - return SharedTypes.UnknownType; - } - } - - /// - /// Gets whether the type is an delegate type. - /// - /// This method returns false for System.Delegate itself - [Obsolete("Use type.Kind == TypeKind.Delegate instead")] - public static bool IsDelegate(this IType type) - { - if (type == null) - throw new ArgumentNullException("type"); - return type.Kind == TypeKind.Delegate; - } - + #region GetDelegateInvokeMethod /// /// Gets the invoke method for a delegate type. /// @@ -207,13 +163,13 @@ namespace ICSharpCode.NRefactory.TypeSystem throw new ArgumentNullException("type"); ITypeDefinition def = type.GetDefinition(); if (def != null && def.Kind == TypeKind.Delegate) { - foreach (IMethod method in def.Methods) { - if (method.Name == "Invoke") { + foreach (IMember member in def.Members) { + if (member.Name == "Invoke" && member is IMethod) { ParameterizedType pt = type as ParameterizedType; if (pt != null) { - return new SpecializedMethod(pt, method); + return new SpecializedMethod(pt, (IMethod)member); } - return method; + return (IMethod)member; } } } @@ -221,37 +177,12 @@ namespace ICSharpCode.NRefactory.TypeSystem } #endregion - #region InternalsVisibleTo - /// - /// Gets whether the internals of this project are visible to the other project - /// - public static bool InternalsVisibleTo(this IProjectContent projectContent, IProjectContent other, ITypeResolveContext context) - { - if (projectContent == other) - return true; - // TODO: implement support for [InternalsVisibleToAttribute] - // Make sure implementation doesn't hurt performance, e.g. don't resolve all assembly attributes whenever - // this method is called - it'll be called once per internal member during lookup operations - return false; - } - #endregion - - #region GetAllTypes - /// - /// Gets all type definitions, including nested types. - /// - public static IEnumerable GetAllTypes(this ITypeResolveContext context) - { - return TreeTraversal.PreOrder(context.GetTypes(), t => t.NestedTypes); - } - #endregion - #region GetType/Member /// /// Gets the type (potentially a nested type) defined at the specified location. /// Returns null if no type is defined at that location. /// - public static ITypeDefinition GetInnermostTypeDefinition (this IParsedFile file, int line, int column) + public static IUnresolvedTypeDefinition GetInnermostTypeDefinition (this IParsedFile file, int line, int column) { return file.GetInnermostTypeDefinition (new TextLocation (line, column)); } @@ -260,22 +191,39 @@ namespace ICSharpCode.NRefactory.TypeSystem /// Gets the member defined at the specified location. /// Returns null if no member is defined at that location. /// - public static IMember GetMember (this IParsedFile file, int line, int column) + public static IUnresolvedMember GetMember (this IParsedFile file, int line, int column) { return file.GetMember (new TextLocation (line, column)); } #endregion - #region GetSubTypeDefinitions - /// - /// Gets all sub type definitions defined in a context. - /// - public static IEnumerable GetSubTypeDefinitions (this ITypeDefinition baseType, ITypeResolveContext context) + #region Resolve on collections + public static IList CreateResolvedAttributes(this IList attributes, ITypeResolveContext context) { - foreach (var contextType in context.GetAllTypes ()) { - if (contextType.IsDerivedFrom (baseType, context)) - yield return contextType; - } + if (attributes == null) + throw new ArgumentNullException("attributes"); + if (attributes.Count == 0) + return EmptyList.Instance; + else + return new ProjectedList(context, attributes, (c, a) => a.CreateResolvedAttribute(c)); + } + + public static IList Resolve(this IList typeReferences, ITypeResolveContext context) + { + if (typeReferences == null) + throw new ArgumentNullException("typeReferences"); + if (typeReferences.Count == 0) + return EmptyList.Instance; + else + return new ProjectedList(context, typeReferences, (c, t) => t.Resolve(c)); + } + + public static IList Resolve(this IList constantValues, ITypeResolveContext context) + { + if (constantValues.Count == 0) + return EmptyList.Instance; + else + return new ProjectedList(context, constantValues, (c, t) => t.Resolve(c)); } #endregion } diff --git a/ICSharpCode.NRefactory/TypeSystem/IAccessor.cs b/ICSharpCode.NRefactory/TypeSystem/IAccessor.cs index bc7d8dabbe..be33fe5cc3 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IAccessor.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IAccessor.cs @@ -24,7 +24,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Represents an accessor (property getter/setter; or event add/remove/invoke). /// - public interface IAccessor : IFreezable + public interface IUnresolvedAccessor : IHasAccessibility { /// /// Gets the accessor region. @@ -34,16 +34,34 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Gets the attributes defined on this accessor. /// - IList Attributes { get; } + IList Attributes { get; } /// /// Gets the attributes defined on the return type of the accessor. (e.g. [return: MarshalAs(...)]) /// - IList ReturnTypeAttributes { get; } + IList ReturnTypeAttributes { get; } + //IAccessor CreateResolvedAccessor(ITypeResolveContext context); + } + + /// + /// Represents an accessor (property getter/setter; or event add/remove/invoke). + /// + public interface IAccessor : IResolved, IHasAccessibility + { /// - /// Gets the accessibility of this accessor. + /// Gets the accessor region. /// - Accessibility Accessibility { get; } + DomRegion Region { get; } + + /// + /// Gets the attributes defined on this accessor. + /// + IList Attributes { get; } + + /// + /// Gets the attributes defined on the return type of the accessor. (e.g. [return: MarshalAs(...)]) + /// + IList ReturnTypeAttributes { get; } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/IAmbience.cs b/ICSharpCode.NRefactory/TypeSystem/IAmbience.cs index 44ac8fc5ad..5395fe2906 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IAmbience.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IAmbience.cs @@ -78,15 +78,11 @@ namespace ICSharpCode.NRefactory.TypeSystem public interface IAmbience { - ConversionFlags ConversionFlags { - get; - set; - } + ConversionFlags ConversionFlags { get; set; } - string ConvertEntity(IEntity e, ITypeResolveContext context); + string ConvertEntity(IEntity e); string ConvertType(IType type); - string ConvertType(ITypeReference type, ITypeResolveContext context); - string ConvertVariable(IVariable variable, ITypeResolveContext context); + string ConvertVariable(IVariable variable); string WrapAttribute(string attribute); string WrapComment(string comment); diff --git a/ICSharpCode.NRefactory/TypeSystem/IAssembly.cs b/ICSharpCode.NRefactory/TypeSystem/IAssembly.cs new file mode 100644 index 0000000000..0276ff99b9 --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/IAssembly.cs @@ -0,0 +1,93 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Represents an unresolved assembly. + /// + public interface IUnresolvedAssembly : IAssemblyReference + { + /// + /// Gets the assembly name (short name). + /// + string AssemblyName { get; } + + /// + /// Gets the list of all assembly attributes in the project. + /// + IList AssemblyAttributes { get; } + + /// + /// Gets the list of all module attributes in the project. + /// + IList ModuleAttributes { get; } + } + + public interface IAssemblyReference + { + /// + /// Resolves this assembly. + /// + IAssembly Resolve(ICompilation compilation); + } + + /// + /// Represents an assembly. + /// + public interface IAssembly : IResolved + { + /// + /// Gets the original unresolved assembly. + /// + IUnresolvedAssembly UnresolvedAssembly { get; } + + /// + /// Gets whether this assembly is the main assembly of the compilation. + /// + bool IsMainAssembly { get; } + + /// + /// Gets the assembly name (short name). + /// + string AssemblyName { get; } + + /// + /// Gets the list of all assembly attributes in the project. + /// + IList AssemblyAttributes { get; } + + /// + /// Gets the list of all module attributes in the project. + /// + IList ModuleAttributes { get; } + + /// + /// Gets whether the internals of this assembly are visible in the specified assembly. + /// + bool InternalsVisibleTo(IAssembly assembly); + + /// + /// Gets the root namespace for this assembly. + /// + INamespace RootNamespace { get; } + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/IAttribute.cs b/ICSharpCode.NRefactory/TypeSystem/IAttribute.cs index 5743278bd3..84e38ce13f 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IAttribute.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IAttribute.cs @@ -24,6 +24,31 @@ using ICSharpCode.NRefactory.Semantics; namespace ICSharpCode.NRefactory.TypeSystem { + /// + /// Represents an unresolved attribute. + /// + #if WITH_CONTRACTS + [ContractClass(typeof(IUnresolvedAttributeContract))] + #endif + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] + public interface IUnresolvedAttribute + { + /// + /// Gets the code region of this attribute. + /// + DomRegion Region { get; } + + /// + /// Gets the type of the attribute. + /// + ITypeReference AttributeType { get; } + + /// + /// Resolves the attribute. + /// + IAttribute CreateResolvedAttribute(ITypeResolveContext context); + } + /// /// Represents an attribute. /// @@ -31,7 +56,7 @@ namespace ICSharpCode.NRefactory.TypeSystem [ContractClass(typeof(IAttributeContract))] #endif [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] - public interface IAttribute : IFreezable + public interface IAttribute { /// /// Gets the code region of this attribute. @@ -41,23 +66,23 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Gets the type of the attribute. /// - ITypeReference AttributeType { get; } + IType AttributeType { get; } /// - /// Gets the positional arguments passed to the attribute. + /// Gets the constructor being used. + /// This property may return null if no matching constructor was found. /// - IList GetPositionalArguments(ITypeResolveContext context); + IMethod Constructor { get; } /// - /// Gets the named arguments passed to the attribute. + /// Gets the positional arguments. /// - IList> GetNamedArguments(ITypeResolveContext context); + IList PositionalArguments { get; } /// - /// Resolves the constructor method used for this attribute invocation. - /// Returns null if the constructor cannot be found. + /// Gets the named arguments passed to the attribute. /// - IMethod ResolveConstructor(ITypeResolveContext context); + IList> NamedArguments { get; } } #if WITH_CONTRACTS diff --git a/ICSharpCode.NRefactory/TypeSystem/ISynchronizedTypeResolveContext.cs b/ICSharpCode.NRefactory/TypeSystem/ICompilation.cs similarity index 52% rename from ICSharpCode.NRefactory/TypeSystem/ISynchronizedTypeResolveContext.cs rename to ICSharpCode.NRefactory/TypeSystem/ICompilation.cs index c3f02b1c3b..f84e02a315 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ISynchronizedTypeResolveContext.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ICompilation.cs @@ -18,25 +18,50 @@ using System; using System.Collections.Generic; -using System.Diagnostics.Contracts; +using ICSharpCode.NRefactory.Utils; namespace ICSharpCode.NRefactory.TypeSystem { - /// - /// Context representing the set of assemblies in which a type is being searched. - /// Guarantees that the list of types available in the context is not changed until Dispose() is called. - /// The Dispose() method must be called from the same thread that create the - /// ISynchronizedTypeResolveContext. - /// - /// - /// A simple implementation might enter a ReaderWriterLock when the synchronized context - /// is created, and releases the lock when Dispose() is called. - /// However, implementations based on immutable data structures are also possible. - /// - /// Calling Synchronize() on an already synchronized context is possible, but has no effect. - /// Only disposing the outermost ISynchronizedTypeResolveContext releases the lock. - /// - public interface ISynchronizedTypeResolveContext : ITypeResolveContext, IDisposable + public interface ICompilation { + /// + /// Gets the current assembly. + /// + IAssembly MainAssembly { get; } + + /// + /// Gets the type resolve context that specifies this compilation and no current assembly or entity. + /// + ITypeResolveContext TypeResolveContext { get; } + + /// + /// Gets the referenced assemblies. + /// This list does not include the current assembly. + /// + IList ReferencedAssemblies { get; } + + /// + /// Gets the root namespace of this compilation. + /// + INamespace RootNamespace { get; } + + /// + /// Gets the root namespace for a given extern alias. + /// + INamespace GetNamespaceForExternAlias(string alias); + + /// + /// Gets all type defininitions in this compilation, including nested types. + /// + IEnumerable GetAllTypeDefinitions(); + + IType FindType(KnownTypeCode typeCode); + + CacheManager CacheManager { get; } + } + + public interface IResolved + { + ICompilation Compilation { get; } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/IConstantValue.cs b/ICSharpCode.NRefactory/TypeSystem/IConstantValue.cs index 342ec2c4da..106f3f2334 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IConstantValue.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IConstantValue.cs @@ -22,29 +22,16 @@ using ICSharpCode.NRefactory.Semantics; namespace ICSharpCode.NRefactory.TypeSystem { - #if WITH_CONTRACTS - [ContractClass(typeof(IConstantValueContract))] - #endif - public interface IConstantValue : IFreezable + /// + /// Represents an unresolved constant value. + /// + public interface IConstantValue { /// /// Resolves the value of this constant. /// - /// Type resolve context where the constant value will be used. + /// Compilation context where the constant value will be used. /// Resolve result representing the constant value. ResolveResult Resolve(ITypeResolveContext context); } - - #if WITH_CONTRACTS - [ContractClassFor(typeof(IConstantValue))] - abstract class IConstantValueContract : IFreezableContract, IConstantValue - { - ResolveResult IConstantValue.Resolve(ITypeResolveContext context) - { - Contract.Requires(context != null); - Contract.Ensures(Contract.Result() != null); - return null; - } - } - #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IEntity.cs b/ICSharpCode.NRefactory/TypeSystem/IEntity.cs index ebc2349b91..444bc50e80 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IEntity.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IEntity.cs @@ -22,11 +22,14 @@ using System.Diagnostics.Contracts; namespace ICSharpCode.NRefactory.TypeSystem { - #if WITH_CONTRACTS - [ContractClass(typeof(IEntityContract))] - #endif - public interface IEntity : INamedElement, IFreezable + /// + /// Represents an unresolved entity. + /// + public interface IUnresolvedEntity : INamedElement, IHasAccessibility { + /// + /// Gets the entity type. + /// EntityType EntityType { get; } /// @@ -44,16 +47,18 @@ namespace ICSharpCode.NRefactory.TypeSystem /// For members, this is the class that contains the member. /// For nested classes, this is the outer class. For top-level entities, this property returns null. /// - ITypeDefinition DeclaringTypeDefinition { get; } - - IList Attributes { get; } + IUnresolvedTypeDefinition DeclaringTypeDefinition { get; } - string Documentation { get; } + /// + /// Gets the parsed file in which this entity is defined. + /// Returns null if this entity wasn't parsed from source code (e.g. loaded from a .dll with CecilLoader). + /// + IParsedFile ParsedFile { get; } /// - /// Gets the accessibility of this entity. + /// Gets the attributes on this entity. /// - Accessibility Accessibility { get; } + IList Attributes { get; } /// /// Gets whether this entity is static. @@ -84,137 +89,92 @@ namespace ICSharpCode.NRefactory.TypeSystem bool IsSynthetic { get; } /// - /// Gets a value indicating whether this instance is private. + /// Resolves the entity. + /// + IEntity Resolve(ITypeResolveContext context); + } + + /// + /// Represents a resolved entity. + /// + public interface IEntity : IResolved, INamedElement, IHasAccessibility + { + /// + /// Gets the original unresolved entity. /// - /// - /// true if this instance is private; otherwise, false. - /// - bool IsPrivate { get; } + IUnresolvedEntity UnresolvedEntity { get; } /// - /// Gets a value indicating whether this instance is public. + /// Gets the entity type. /// - /// - /// true if this instance is public; otherwise, false. - /// - bool IsPublic { get; } + EntityType EntityType { get; } /// - /// Gets a value indicating whether this instance is protected. + /// Gets the complete entity region (including header+body) /// - /// - /// true if this instance is protected; otherwise, false. - /// - bool IsProtected { get; } + DomRegion Region { get; } /// - /// Gets a value indicating whether this instance is internal. + /// Gets the entity body region. /// - /// - /// true if this instance is internal; otherwise, false. - /// - bool IsInternal { get; } + DomRegion BodyRegion { get; } /// - /// Gets a value indicating whether this instance is protected or internal. + /// Gets the declaring class. + /// For members, this is the class that contains the member. + /// For nested classes, this is the outer class. For top-level entities, this property returns null. /// - /// - /// true if this instance is protected or internal; otherwise, false. - /// - bool IsProtectedOrInternal { get; } + ITypeDefinition DeclaringTypeDefinition { get; } /// - /// Gets a value indicating whether this instance is protected and internal. + /// Gets/Sets the declaring type (incl. type arguments, if any). + /// This property never returns null -- for top-level entities, it returns SharedTypes.UnknownType. + /// If this is not a specialized member, the value returned is equal to . /// - /// - /// true if this instance is protected and internal; otherwise, false. - /// - bool IsProtectedAndInternal { get; } + IType DeclaringType { get; } /// /// The assembly in which this entity is defined. /// This property never returns null. /// - IProjectContent ProjectContent { get; } + IAssembly ParentAssembly { get; } /// - /// Gets the parsed file in which this entity is defined. - /// Returns null if this entity wasn't parsed (loaded with CecilLoader). + /// Gets the attributes on this entity. /// - IParsedFile ParsedFile { get; } + IList Attributes { get; } - //bool IsAccessible(IClass callingClass, bool isAccessThoughReferenceOfCurrentClass); - } - - #if WITH_CONTRACTS - [ContractClassFor(typeof(IEntity))] - abstract class IEntityContract : INamedElementContract, IEntity - { - EntityType IEntity.EntityType { - get { return default(EntityType); } - } - - DomRegion IEntity.Region { - get { return DomRegion.Empty; } - } - - DomRegion IEntity.BodyRegion { - get { return DomRegion.Empty; } - } - - ITypeDefinition IEntity.DeclaringTypeDefinition { - get { return null; } - } - - IList IEntity.Attributes { - get { - Contract.Ensures(Contract.Result>() != null); - return null; - } - } - - string IEntity.Documentation { - get { return null; } - } - - bool IEntity.IsStatic { - get { return false; } - } - - Accessibility IEntity.Accessibility { - get { return default(Accessibility); } - } - - bool IEntity.IsAbstract { - get { return false; } - } - - bool IEntity.IsSealed { - get { return false; } - } - - bool IEntity.IsShadowing { - get { return false; } - } - - bool IEntity.IsSynthetic { - get { return false; } - } - - IProjectContent IEntity.ProjectContent { - get { - Contract.Ensures(Contract.Result() != null); - return null; - } - } - - bool IFreezable.IsFrozen { - get { return false; } - } - - void IFreezable.Freeze() - { - } + /// + /// Gets the documentation for this entity. + /// + string Documentation { get; } + + /// + /// Gets whether this entity is static. + /// Returns true if either the 'static' or the 'const' modifier is set. + /// + bool IsStatic { get; } + + /// + /// Returns whether this entity is abstract. + /// + /// Static classes also count as abstract classes. + bool IsAbstract { get; } + + /// + /// Returns whether this entity is sealed. + /// + /// Static classes also count as sealed classes. + bool IsSealed { get; } + + /// + /// Gets whether this member is declared to be shadowing another member with the same name. + /// + bool IsShadowing { get; } + + /// + /// Gets whether this member is generated by a macro/compiler feature. + /// + bool IsSynthetic { get; } } - #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IEvent.cs b/ICSharpCode.NRefactory/TypeSystem/IEvent.cs index 7b709632a0..1c7c158fea 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IEvent.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IEvent.cs @@ -18,9 +18,26 @@ using System; using System.Diagnostics.Contracts; +using ICSharpCode.NRefactory.TypeSystem; namespace ICSharpCode.NRefactory.TypeSystem { + public interface IUnresolvedEvent : IUnresolvedMember + { + bool CanAdd { get; } + bool CanRemove { get; } + bool CanInvoke { get; } + + IUnresolvedAccessor AddAccessor { get; } + IUnresolvedAccessor RemoveAccessor { get; } + IUnresolvedAccessor InvokeAccessor { get; } + + /// + /// Resolves the entity. + /// + new IEvent Resolve(ITypeResolveContext context); + } + public interface IEvent : IMember { bool CanAdd { get; } diff --git a/ICSharpCode.NRefactory/TypeSystem/IField.cs b/ICSharpCode.NRefactory/TypeSystem/IField.cs index 2c0ec17e8d..8de9450ae7 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IField.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IField.cs @@ -24,15 +24,38 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Represents a field or constant. /// - #if WITH_CONTRACTS - [ContractClass(typeof(IFieldContract))] - #endif + public interface IUnresolvedField : IUnresolvedMember + { + /// + /// Gets whether this field is readonly. + /// + bool IsReadOnly { get; } + + /// + /// Gets whether this field is volatile. + /// + bool IsVolatile { get; } + + /// + /// Gets whether this field is a constant (C#-like const). + /// + bool IsConst { get; } + + /// + /// Resolves the entity. + /// + new IField Resolve(ITypeResolveContext context); + } + + /// + /// Represents a field or constant. + /// public interface IField : IMember, IVariable { /// /// Gets the name of the field. /// - new string Name { get; } // solve ambiguity between INamedElement.Name and IVariable.Name + new string Name { get; } // solve ambiguity between IMember.Name and IVariable.Name /// /// Gets the region where the field is declared. @@ -49,42 +72,4 @@ namespace ICSharpCode.NRefactory.TypeSystem /// bool IsVolatile { get; } } - - #if WITH_CONTRACTS - [ContractClassFor(typeof(IField))] - abstract class IFieldContract : IMemberContract, IField - { - string IField.Name { - get { - Contract.Ensures(Contract.Result() != null); - return null; - } - } - - bool IField.IsReadOnly { - get { return false; } - } - - bool IField.IsVolatile { - get { return false; } - } - - - string IVariable.Name { - get { return null; } - } - - ITypeReference IVariable.Type { - get { return null; } - } - - bool IVariable.IsConst { - get { return false; } - } - - IConstantValue IVariable.ConstantValue { - get { return null; } - } - } - #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IMember.cs b/ICSharpCode.NRefactory/TypeSystem/IMember.cs index 6674e02d23..82b5e7f503 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IMember.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IMember.cs @@ -19,24 +19,62 @@ using System; using System.Collections.Generic; using System.Diagnostics.Contracts; +using ICSharpCode.NRefactory.TypeSystem; namespace ICSharpCode.NRefactory.TypeSystem { /// - /// Method/field/entity. + /// Method/field/property/event. /// - #if WITH_CONTRACTS - [ContractClass(typeof(IMemberContract))] - #endif - public interface IMember : IEntity + public interface IUnresolvedMember : IUnresolvedEntity { /// - /// Gets/Sets the declaring type (incl. type arguments, if any). - /// This property never returns null -- for top-level members, it returns SharedTypes.UnknownType. - /// If this is not a specialized member, the value returned is equal to . + /// Gets the return type of this member. + /// This property never returns null. + /// + ITypeReference ReturnType { get; } + + /// + /// Gets whether this member is explicitly implementing an interface. + /// If this property is true, the member can only be called through the interfaces it implements. + /// + bool IsExplicitInterfaceImplementation { get; } + + /// + /// Gets the interfaces that are explicitly implemented by this member. + /// + IList InterfaceImplementations { get; } + + /// + /// Gets if the member is virtual. Is true only if the "virtual" modifier was used, but non-virtual + /// members can be overridden, too; if they are abstract or overriding a method. + /// + bool IsVirtual { get; } + + /// + /// Gets whether this member is overriding another member. /// - IType DeclaringType { get; } + bool IsOverride { get; } + /// + /// Gets if the member can be overridden. Returns true when the member is "abstract", "virtual" or "override" but not "sealed". + /// + bool IsOverridable { get; } + } + + public interface IMemberReference + { + /// + /// Resolves the member. + /// + IMember Resolve(ITypeResolveContext context); + } + + /// + /// Method/field/property/event. + /// + public interface IMember : IEntity + { /// /// Gets the original member definition for this member. /// Returns this if this is not a specialized member. @@ -48,76 +86,37 @@ namespace ICSharpCode.NRefactory.TypeSystem /// Gets the return type of this member. /// This property never returns null. /// - ITypeReference ReturnType { get; } + IType ReturnType { get; } + + /// + /// Gets the interface members implemented by this member (both implicitly and explicitly). + /// + IList InterfaceImplementations { get; } /// - /// Gets the list of interfaces this member is implementing explicitly. + /// Gets whether this member is explicitly implementing an interface. /// - IList InterfaceImplementations { get; } + bool IsExplicitInterfaceImplementation { get; } /// /// Gets if the member is virtual. Is true only if the "virtual" modifier was used, but non-virtual /// members can be overridden, too; if they are abstract or overriding a method. /// - bool IsVirtual { - get; - } + bool IsVirtual { get; } - bool IsOverride { - get; - } + /// + /// Gets whether this member is overriding another member. + /// + bool IsOverride { get; } /// /// Gets if the member can be overridden. Returns true when the member is "abstract", "virtual" or "override" but not "sealed". /// - bool IsOverridable { - get; - } - } - - #if WITH_CONTRACTS - [ContractClassFor(typeof(IMember))] - abstract class IMemberContract : IEntityContract, IMember - { - IType IMember.DeclaringType { - get { - Contract.Ensures(Contract.Result() != null); - return null; - } - } - - IMember IMember.MemberDefinition { - get { - Contract.Ensures(Contract.Result() != null); - return null; - } - } + bool IsOverridable { get; } - ITypeReference IMember.ReturnType { - get { - Contract.Ensures(Contract.Result() != null); - return null; - } - } - - IList IMember.InterfaceImplementations { - get { - Contract.Ensures(Contract.Result>() != null); - return null; - } - } - - bool IMember.IsVirtual { - get { return false; } - } - - bool IMember.IsOverride { - get { return false; } - } - - bool IMember.IsOverridable { - get { return false; } - } + /// + /// Creates a member reference that can be used to rediscover this member in another compilation. + /// + IMemberReference ToMemberReference(); } - #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IMethod.cs b/ICSharpCode.NRefactory/TypeSystem/IMethod.cs index 028387e403..c0e91d7e0e 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IMethod.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IMethod.cs @@ -19,15 +19,33 @@ using System; using System.Collections.Generic; using System.Diagnostics.Contracts; +using ICSharpCode.NRefactory.TypeSystem; namespace ICSharpCode.NRefactory.TypeSystem { + public interface IUnresolvedMethod : IUnresolvedParameterizedMember + { + /// + /// Gets the attributes associated with the return type. (e.g. [return: MarshalAs(...)]) + /// + IList ReturnTypeAttributes { get; } + + IList TypeParameters { get; } + + bool IsExtensionMethod { get; } + bool IsConstructor { get; } + bool IsDestructor { get; } + bool IsOperator { get; } + + /// + /// Resolves the entity. + /// + new IMethod Resolve(ITypeResolveContext context); + } + /// /// Represents a method, constructor, destructor or operator. /// - #if WITH_CONTRACTS - [ContractClass(typeof(IMethodContract))] - #endif public interface IMethod : IParameterizedMember { /// @@ -37,49 +55,9 @@ namespace ICSharpCode.NRefactory.TypeSystem IList TypeParameters { get; } - // handles is VB-specific and not part of the public API, so - // we don't really need it - //IList HandlesClauses { get; } - bool IsExtensionMethod { get; } bool IsConstructor { get; } bool IsDestructor { get; } bool IsOperator { get; } } - - #if WITH_CONTRACTS - [ContractClassFor(typeof(IMethod))] - abstract class IMethodContract : IParameterizedMemberContract, IMethod - { - IList IMethod.ReturnTypeAttributes { - get { - Contract.Ensures(Contract.Result>() != null); - return null; - } - } - - IList IMethod.TypeParameters { - get { - Contract.Ensures(Contract.Result>() != null); - return null; - } - } - - bool IMethod.IsExtensionMethod { - get { return false; } - } - - bool IMethod.IsConstructor { - get { return false; } - } - - bool IMethod.IsDestructor { - get { return false; } - } - - bool IMethod.IsOperator { - get { return false; } - } - } - #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/INamedElement.cs b/ICSharpCode.NRefactory/TypeSystem/INamedElement.cs index cb48e0de45..c53a12e8cb 100644 --- a/ICSharpCode.NRefactory/TypeSystem/INamedElement.cs +++ b/ICSharpCode.NRefactory/TypeSystem/INamedElement.cs @@ -21,9 +21,6 @@ using System.Diagnostics.Contracts; namespace ICSharpCode.NRefactory.TypeSystem { - #if WITH_CONTRACTS - [ContractClass(typeof(INamedElementContract))] - #endif public interface INamedElement { /// @@ -34,9 +31,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// "System.Collections.Generic.List" for List<string> /// "System.Environment.SpecialFolder" for Environment.SpecialFolder /// - string FullName { - get; - } + string FullName { get; } /// /// Gets the short name of the class the return type is pointing to. @@ -46,21 +41,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// "List" for List<string> /// "SpecialFolder" for Environment.SpecialFolder /// - string Name { - get; - } - - /// - /// Gets the namespace of the class the return type is pointing to. - /// - /// - /// "System" for int[]
- /// "System.Collections.Generic" for List<string> - /// "System" for Environment.SpecialFolder - ///
- string Namespace { - get; - } + string Name { get; } /// /// Gets the full reflection name of the element. @@ -75,42 +56,11 @@ namespace ICSharpCode.NRefactory.TypeSystem /// "System.Collections.Generic.List`1[[System.String]]" for List<string> /// "System.Environment+SpecialFolder" for Environment.SpecialFolder /// - string ReflectionName { - get; - } - } - - #if WITH_CONTRACTS - [ContractClassFor(typeof(INamedElement))] - abstract class INamedElementContract : INamedElement - { - string INamedElement.FullName { - get { - Contract.Ensures(!string.IsNullOrEmpty(Contract.Result())); - return null; - } - } - - string INamedElement.Name { - get { - Contract.Ensures(!string.IsNullOrEmpty(Contract.Result())); - return null; - } - } - - string INamedElement.Namespace { - get { - Contract.Ensures(Contract.Result() != null); - return null; - } - } + string ReflectionName { get; } - string INamedElement.ReflectionName { - get { - Contract.Ensures(!string.IsNullOrEmpty(Contract.Result())); - return null; - } - } + /// + /// Gets the full name of the namespace containing this entity. + /// + string Namespace { get; } } - #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/INamespace.cs b/ICSharpCode.NRefactory/TypeSystem/INamespace.cs new file mode 100644 index 0000000000..cbde65b431 --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/INamespace.cs @@ -0,0 +1,77 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Represents a resolved namespace. + /// + public interface INamespace : IResolved + { + // No pointer back to unresolved namespace: + // multiple unresolved namespaces (from different assemblies) get + // merged into one INamespace. + + /// + /// Gets the extern alias for this namespace. + /// Returns an empty string for normal namespaces. + /// + string ExternAlias { get; } + + /// + /// Gets the full name of this namespace. (e.g. "System.Collections") + /// + string FullName { get; } + + /// + /// Gets the short name of this namespace (e.g. "Collections"). + /// + string Name { get; } + + /// + /// Gets the parent namespace. + /// Returns null if this is the root namespace. + /// + INamespace ParentNamespace { get; } + + /// + /// Gets the child namespaces in this namespace. + /// + IEnumerable ChildNamespaces { get; } + + /// + /// Gets the types in this namespace. + /// + IEnumerable Types { get; } + + /// + /// Gets a direct child namespace by its short name. + /// Returns null when the namespace cannot be found. + /// + INamespace GetChildNamespace(string name); + + /// + /// Gets the type with the specified short name and type parameter count. + /// Returns null if the type cannot be found. + /// + ITypeDefinition GetTypeDefinition(string name, int typeParameterCount); + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/IParameter.cs b/ICSharpCode.NRefactory/TypeSystem/IParameter.cs index b76413d431..8ab698e69e 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IParameter.cs @@ -22,20 +22,27 @@ using System.Diagnostics.Contracts; namespace ICSharpCode.NRefactory.TypeSystem { - #if WITH_CONTRACTS - [ContractClass(typeof(IParameterContract))] - #endif - public interface IParameter : IVariable, IFreezable + public interface IUnresolvedParameter { /// - /// Gets the list of attributes. + /// Gets the name of the variable. /// - IList Attributes { get; } + string Name { get; } + + /// + /// Gets the declaration region of the variable. + /// + DomRegion Region { get; } /// - /// Gets the default value of optional parameters. + /// Gets the type of the variable. + /// + ITypeReference Type { get; } + + /// + /// Gets the list of attributes. /// - IConstantValue DefaultValue { get; } + IList Attributes { get; } /// /// Gets whether this parameter is a C# 'ref' parameter. @@ -58,52 +65,32 @@ namespace ICSharpCode.NRefactory.TypeSystem bool IsOptional { get; } } - #if WITH_CONTRACTS - [ContractClassFor(typeof(IParameter))] - abstract class IParameterContract : IVariableContract, IParameter + public interface IParameter : IVariable { - IList IParameter.Attributes { - get { - Contract.Ensures(Contract.Result>() != null); - return null; - } - } - - IConstantValue IParameter.DefaultValue { - get { return null; } - } - - DomRegion IParameter.Region { - get { return DomRegion.Empty; } - } - - bool IParameter.IsRef { - get { return false; } - } - - bool IParameter.IsOut { - get { return false; } - } + /// + /// Gets the list of attributes. + /// + IList Attributes { get; } - bool IParameter.IsParams { - get { return false; } - } + /// + /// Gets whether this parameter is a C# 'ref' parameter. + /// + bool IsRef { get; } - bool IParameter.IsOptional { - get { - IParameter @this = this; - Contract.Ensures(Contract.Result() == (@this.DefaultValue != null)); - return false; - } - } + /// + /// Gets whether this parameter is a C# 'out' parameter. + /// + bool IsOut { get; } - bool IFreezable.IsFrozen { - get { return false; } - } + /// + /// Gets whether this parameter is a C# 'params' parameter. + /// + bool IsParams { get; } - void IFreezable.Freeze() - { - } + /// + /// Gets whether this parameter is optional. + /// The default value is given by the property. + /// + bool IsOptional { get; } } - #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IParameterizedMember.cs b/ICSharpCode.NRefactory/TypeSystem/IParameterizedMember.cs index 95333b297e..43db5ab3ca 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IParameterizedMember.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IParameterizedMember.cs @@ -25,24 +25,16 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Represents a method or property. /// - #if WITH_CONTRACTS - [ContractClass(typeof(IParameterizedMemberContract))] - #endif - public interface IParameterizedMember : IMember + public interface IUnresolvedParameterizedMember : IUnresolvedMember { - IList Parameters { get; } + IList Parameters { get; } } - #if WITH_CONTRACTS - [ContractClassFor(typeof(IParameterizedMember))] - abstract class IParameterizedMemberContract : IMemberContract, IParameterizedMember + /// + /// Represents a method or property. + /// + public interface IParameterizedMember : IMember { - IList IParameterizedMember.Parameters { - get { - Contract.Ensures(Contract.Result>() != null); - return null; - } - } + IList Parameters { get; } } - #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IParsedFile.cs b/ICSharpCode.NRefactory/TypeSystem/IParsedFile.cs index 625d769448..cfa08505d9 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IParsedFile.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IParsedFile.cs @@ -24,13 +24,8 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Represents a single file that was parsed. /// - public interface IParsedFile : IFreezable + public interface IParsedFile { - /// - /// Gets the parent project content. - /// - IProjectContent ProjectContent { get; } - /// /// Returns the full path of the file. /// @@ -44,35 +39,35 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Gets all top-level type definitions. /// - IList TopLevelTypeDefinitions { get; } + IList TopLevelTypeDefinitions { get; } /// /// Gets all assembly attributes that are defined in this file. /// - IList AssemblyAttributes { get; } + IList AssemblyAttributes { get; } /// /// Gets all module attributes that are defined in this file. /// - IList ModuleAttributes { get; } + IList ModuleAttributes { get; } /// /// Gets the top-level type defined at the specified location. /// Returns null if no type is defined at that location. /// - ITypeDefinition GetTopLevelTypeDefinition(TextLocation location); + IUnresolvedTypeDefinition GetTopLevelTypeDefinition(TextLocation location); /// /// Gets the type (potentially a nested type) defined at the specified location. /// Returns null if no type is defined at that location. /// - ITypeDefinition GetInnermostTypeDefinition(TextLocation location); + IUnresolvedTypeDefinition GetInnermostTypeDefinition(TextLocation location); /// /// Gets the member defined at the specified location. /// Returns null if no member is defined at that location. /// - IMember GetMember(TextLocation location); + IUnresolvedMember GetMember(TextLocation location); /// /// Gets the parser errors. diff --git a/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs b/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs index e2d6ea5a56..358e1c3dc4 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs @@ -23,65 +23,54 @@ using System.Diagnostics.Contracts; namespace ICSharpCode.NRefactory.TypeSystem { /// - /// Mutable container of all classes in an assembly. + /// Represents an assembly consisting of source code (parsed files). /// - #if WITH_CONTRACTS - [ContractClass(typeof(IProjectContentContract))] - #endif - public interface IProjectContent : ITypeResolveContext, IAnnotatable + public interface IProjectContent : IUnresolvedAssembly { /// - /// Gets the assembly name (short name). + /// Gets a parsed file by its file name. /// - string AssemblyName { get; } + IParsedFile GetFile(string fileName); /// - /// Gets the list of all assembly attributes in the project. + /// Gets the list of all parsed files in the project content. /// - IList AssemblyAttributes { get; } + IEnumerable Files { get; } /// - /// Gets the list of all module attributes in the project. + /// Gets the referenced assemblies. /// - IList ModuleAttributes { get; } + IEnumerable AssemblyReferences { get; } /// - /// Gets a parsed file by its file name. + /// Creates a new that allows resolving within this project. /// - IParsedFile GetFile(string fileName); + /// + /// An ICompilation is immutable, it operates on a snapshot of this project. + /// + /// If the project hasn't changed since the last CreateCompilation() call, the previous compilation + /// might be reused. + /// + ICompilation CreateCompilation(); /// - /// Gets the list of all parsed files in the project content. + /// Add assembly references to this project content. /// - IEnumerable Files { get; } + IProjectContent AddAssemblyReferences(IEnumerable references); + + /// + /// Removes assembly references from this project content. + /// + IProjectContent RemoveAssemblyReferences(IEnumerable references); /// /// Removes types and attributes from oldFile from the project, and adds those from newFile. /// - /// - /// It is not allowed to call this method from within a using (var ctx = context.Synchronize()) block - /// that involves this project content: this method is a write operation and might (if implemented using locks) - /// wait until all read operations have finished, causing deadlocks within Synchronize blocks. - /// - void UpdateProjectContent(IParsedFile oldFile, IParsedFile newFile); - } - - #if WITH_CONTRACTS - [ContractClassFor(typeof(IProjectContent))] - abstract class IProjectContentContract : ITypeResolveContextContract, IProjectContent - { - IList IProjectContent.AssemblyAttributes { - get { - Contract.Ensures(Contract.Result>() != null); - return null; - } - } + IProjectContent UpdateProjectContent(IParsedFile oldFile, IParsedFile newFile); - IParsedFile IProjectContent.GetFile(string fileName) - { - Contract.Requires(fileName != null); - return; - } + /// + /// Removes types and attributes from oldFiles from the project, and adds those from newFiles. + /// + IProjectContent UpdateProjectContent(IEnumerable oldFiles, IEnumerable newFiles); } - #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IProperty.cs b/ICSharpCode.NRefactory/TypeSystem/IProperty.cs index 9155e5cd98..783c8d3913 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IProperty.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IProperty.cs @@ -20,6 +20,25 @@ using System; namespace ICSharpCode.NRefactory.TypeSystem { + /// + /// Represents a property or indexer. + /// + public interface IUnresolvedProperty : IUnresolvedParameterizedMember + { + bool CanGet { get; } + bool CanSet { get; } + + IUnresolvedAccessor Getter { get; } + IUnresolvedAccessor Setter { get; } + + bool IsIndexer { get; } + + /// + /// Resolves the entity. + /// + new IProperty Resolve(ITypeResolveContext context); + } + /// /// Represents a property or indexer. /// diff --git a/ICSharpCode.NRefactory/TypeSystem/IType.cs b/ICSharpCode.NRefactory/TypeSystem/IType.cs index 4343bd888c..c47da4079c 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IType.cs @@ -48,10 +48,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// Identical types do not necessarily use the same object reference. /// /// - #if WITH_CONTRACTS - [ContractClass(typeof(ITypeContract))] - #endif - public interface IType : ITypeReference, INamedElement, IEquatable + public interface IType : INamedElement, IEquatable { /// /// Gets the type kind. @@ -66,17 +63,11 @@ namespace ICSharpCode.NRefactory.TypeSystem /// false, if the type is a value type. /// null, if the type is not known (e.g. unconstrained generic type parameter or type not found) /// - /// - /// The resolve context is required for type parameters with a constraint "T : SomeType": - /// the type parameter is a reference type iff SomeType is a class type. - /// - bool? IsReferenceType(ITypeResolveContext context); + bool? IsReferenceType { get; } /// /// Gets the underlying type definition. /// Can return null for types which do not have a type definition (for example arrays, pointers, type parameters). - /// - /// For partial classes, this method always returns the . /// ITypeDefinition GetDefinition(); @@ -109,9 +100,17 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Gets the direct base types. /// - /// The context used for resolving type references /// Returns the direct base types including interfaces - IEnumerable GetBaseTypes(ITypeResolveContext context); + IEnumerable DirectBaseTypes { get; } + + /// + /// Creates a type reference that can be used to look up a type equivalent to this type in another compilation. + /// + /// + /// If this type is open, the resulting type reference will need to be looked up in an appropriate generic context. + /// If this type is closed, the resulting type reference can be looked up in the main resolve context of another compilation. + /// + ITypeReference ToTypeReference(); /// /// Gets inner classes (including inherited inner classes). @@ -144,7 +143,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// Base.GetNestedTypes() = { Base`1+Nested`1[`0, unbound] } /// /// - IEnumerable GetNestedTypes(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); + IEnumerable GetNestedTypes(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); // Note that we cannot 'leak' the additional type parameter as we leak the normal type parameters, because // the index might collide. For example, @@ -169,7 +168,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// and thus 'leaked' to the caller in the same way the GetMembers() method does not specialize members /// from an and 'leaks' type parameters in member signatures. /// - IEnumerable GetNestedTypes(IList typeArguments, ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); + IEnumerable GetNestedTypes(IList typeArguments, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); /// /// Gets all instance constructors for this type. @@ -184,7 +183,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// and the appropriate will be returned. /// /// - IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers); + IEnumerable GetConstructors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers); /// /// Gets all methods that can be called on this type. @@ -211,7 +210,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// the ambiguity can be avoided. /// /// - IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); + IEnumerable GetMethods(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); /// /// Gets all generic methods that can be called on this type with the specified type arguments. @@ -232,7 +231,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// and the other overload's remarks about ambiguous signatures apply here as well. /// /// - IEnumerable GetMethods(IList typeArguments, ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); + IEnumerable GetMethods(IList typeArguments, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); /// /// Gets all properties that can be called on this type. @@ -244,7 +243,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// For properties on parameterized types, type substitution will be performed on the property signature, /// and the appropriate will be returned. /// - IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); + IEnumerable GetProperties(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); /// /// Gets all fields that can be accessed on this type. @@ -256,7 +255,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// For fields on parameterized types, type substitution will be performed on the field's return type, /// and the appropriate will be returned. /// - IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); + IEnumerable GetFields(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); /// /// Gets all events that can be accessed on this type. @@ -268,7 +267,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// For fields on parameterized types, type substitution will be performed on the event's return type, /// and the appropriate will be returned. /// - IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); + IEnumerable GetEvents(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); /// /// Gets all members that can be called on this type. @@ -287,7 +286,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// method apply here as well. /// /// - IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); + IEnumerable GetMembers(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); } [Flags] @@ -307,135 +306,4 @@ namespace ICSharpCode.NRefactory.TypeSystem /// IgnoreInheritedMembers = 0x02 } - - #if WITH_CONTRACTS - [ContractClassFor(typeof(IType))] - abstract class ITypeContract : ITypeReferenceContract, IType - { - bool? IType.IsReferenceType(ITypeResolveContext context) - { - Contract.Requires(context != null); - return null; - } - - int IType.TypeParameterCount { - get { - Contract.Ensures(Contract.Result() >= 0); - return 0; - } - } - - IType IType.DeclaringType { - get { return null; } - } - - IEnumerable IType.GetBaseTypes(ITypeResolveContext context) - { - Contract.Requires(context != null); - Contract.Ensures(Contract.Result>() != null); - return null; - } - - IEnumerable IType.GetNestedTypes(ITypeResolveContext context, Predicate filter, GetMemberOptions options) - { - Contract.Requires(context != null); - Contract.Ensures(Contract.Result>() != null); - return null; - } - - IEnumerable IType.GetMethods(ITypeResolveContext context, Predicate filter, GetMemberOptions options) - { - Contract.Requires(context != null); - Contract.Ensures(Contract.Result>() != null); - return null; - } - - IEnumerable IType.GetConstructors(ITypeResolveContext context, Predicate filter, GetMemberOptions options) - { - Contract.Requires(context != null); - Contract.Ensures(Contract.Result>() != null); - return null; - } - - IEnumerable IType.GetProperties(ITypeResolveContext context, Predicate filter, GetMemberOptions options) - { - Contract.Requires(context != null); - Contract.Ensures(Contract.Result>() != null); - return null; - } - - IEnumerable IType.GetFields(ITypeResolveContext context, Predicate filter, GetMemberOptions options) - { - Contract.Requires(context != null); - Contract.Ensures(Contract.Result>() != null); - return null; - } - - IEnumerable IType.GetEvents(ITypeResolveContext context, Predicate filter, GetMemberOptions options) - { - Contract.Requires(context != null); - Contract.Ensures(Contract.Result>() != null); - return null; - } - - IEnumerable IType.GetEvents(ITypeResolveContext context, Predicate filter, GetMemberOptions options) - { - Contract.Requires(context != null); - Contract.Ensures(Contract.Result>() != null); - return null; - } - - string INamedElement.FullName { - get { - Contract.Ensures(Contract.Result() != null); - return null; - } - } - - string INamedElement.Name { - get { - Contract.Ensures(Contract.Result() != null); - return null; - } - } - - string INamedElement.Namespace { - get { - Contract.Ensures(Contract.Result() != null); - return null; - } - } - - string INamedElement.ReflectionName { - get { - Contract.Ensures(Contract.Result() != null); - return null; - } - } - - ITypeDefinition IType.GetDefinition() - { - return null; - } - - bool IEquatable.Equals(IType other) - { - return false; - } - - IType IType.AcceptVisitor(TypeVisitor visitor) - { - Contract.Requires(visitor != null); - Contract.Ensures(Contract.Result() != null); - return this; - } - - IType IType.VisitChildren(TypeVisitor visitor) - { - Contract.Requires(visitor != null); - Contract.Ensures(Contract.Result() != null); - return this; - } - } - #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs b/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs index 3cc733fcec..10f499dc68 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs @@ -22,34 +22,64 @@ using System.Diagnostics.Contracts; namespace ICSharpCode.NRefactory.TypeSystem { + /// + /// Represents an unresolved class, enum, interface, struct, delegate or VB module. + /// For partial classes, an unresolved type definition represents only a single part. + /// + public interface IUnresolvedTypeDefinition : ITypeReference, IUnresolvedEntity + { + TypeKind Kind { get; } + + IList BaseTypes { get; } + IList TypeParameters { get; } + + IList NestedTypes { get; } + IList Members { get; } + + /// + /// Resolves the type definition. + /// + new ITypeDefinition Resolve(ITypeResolveContext context); + } + /// /// Represents a class, enum, interface, struct, delegate or VB module. - /// Also used to represent a part of a partial class. + /// For partial classes, this represents the whole class. /// - #if WITH_CONTRACTS - [ContractClass(typeof(ITypeDefinitionContract))] - #endif public interface ITypeDefinition : IType, IEntity { - IList BaseTypes { get; } + /// + /// Returns all parts that contribute to this type definition. + /// Non-partial classes have a single part that represents the whole class. + /// + IList Parts { get; } + IList TypeParameters { get; } + IList NestedTypes { get; } + IList Members { get; } + + IEnumerable Fields { get; } + IEnumerable Methods { get; } + IEnumerable Properties { get; } + IEnumerable Events { get; } + /// - /// If this is a compound class (combination of class parts), this method retrieves all individual class parts. - /// Otherwise, a list containing this is returned. + /// Gets the known type code for this type definition. /// - IList GetParts(); + KnownTypeCode KnownTypeCode { get; } - IList NestedTypes { get; } - IList Fields { get; } - IList Properties { get; } - IList Methods { get; } - IList Events { get; } + /// + /// For enums: returns the underlying primitive type. + /// For all other types: returns . + /// + IType EnumUnderlyingType { get; } /// - /// Gets all members declared in this class. This is the union of Fields,Properties,Methods and Events. + /// Gets/Sets the declaring type (incl. type arguments, if any). + /// This property never returns null -- for top-level entities, it returns SharedTypes.UnknownType. /// - IEnumerable Members { get; } + new IType DeclaringType { get; } // solves ambiguity between IType.DeclaringType and IEntity.DeclaringType /// /// Gets whether this type contains extension methods. @@ -57,148 +87,4 @@ namespace ICSharpCode.NRefactory.TypeSystem /// This property is used to speed up the search for extension methods. bool HasExtensionMethods { get; } } - - #if WITH_CONTRACTS - [ContractClassFor(typeof(ITypeDefinition))] - abstract class ITypeDefinitionContract : ITypeContract, ITypeDefinition - { - ClassType ITypeDefinition.ClassType { - get { return default(ClassType); } - } - - IList ITypeDefinition.BaseTypes { - get { - Contract.Ensures(Contract.Result>() != null); - return null; - } - } - - IList ITypeDefinition.TypeParameters { - get { - Contract.Ensures(Contract.Result>() != null); - return null; - } - } - - IList ITypeDefinition.InnerClasses { - get { - Contract.Ensures(Contract.Result>() != null); - return null; - } - } - - IList ITypeDefinition.Fields { - get { - Contract.Ensures(Contract.Result>() != null); - return null; - } - } - - IList ITypeDefinition.Properties { - get { - Contract.Ensures(Contract.Result>() != null); - return null; - } - } - - IList ITypeDefinition.Methods { - get { - Contract.Ensures(Contract.Result>() != null); - return null; - } - } - - IList ITypeDefinition.Events { - get { - Contract.Ensures(Contract.Result>() != null); - return null; - } - } - - IEnumerable ITypeDefinition.Members { - get { - Contract.Ensures(Contract.Result>() != null); - return null; - } - } - - ITypeDefinition ITypeDefinition.GetCompoundClass() - { - Contract.Ensures(Contract.Result() != null); - return null; - } - - IList ITypeDefinition.GetParts() - { - Contract.Ensures(Contract.Result>() != null); - return null; - } - - bool ITypeDefinition.HasExtensionMethods { - get { return default(bool); } - } - - #region IEntity - EntityType IEntity.EntityType { - get { return EntityType.None; } - } - - DomRegion IEntity.Region { - get { return DomRegion.Empty; } - } - - DomRegion IEntity.BodyRegion { - get { return DomRegion.Empty; } - } - - ITypeDefinition IEntity.DeclaringTypeDefinition { - get { return null; } - } - - IList IEntity.Attributes { - get { return null; } - } - - string IEntity.Documentation { - get { return null; } - } - - bool IEntity.IsStatic { - get { return false; } - } - - Accessibility IEntity.Accessibility { - get { return Accessibility.None; } - } - - bool IEntity.IsAbstract { - get { return false; } - } - - bool IEntity.IsSealed { - get { return false; } - } - - bool IEntity.IsShadowing { - get { return false; } - } - - bool IEntity.IsSynthetic { - get { return false; } - } - - IProjectContent IEntity.ProjectContent { - get { return null; } - } - - bool IFreezable.IsFrozen { - get { return false; } - } - - void IFreezable.Freeze() - { - } - #endregion - } - #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs b/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs index 8f6136c250..6ce20a2893 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs @@ -26,10 +26,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Type parameter of a generic class/method. /// - #if WITH_CONTRACTS - [ContractClass(typeof(ITypeParameterContract))] - #endif - public interface ITypeParameter : IType, IFreezable + public interface IUnresolvedTypeParameter : INamedElement { /// /// Get the type of this type parameter's owner. @@ -42,6 +39,43 @@ namespace ICSharpCode.NRefactory.TypeSystem /// int Index { get; } + /// + /// Gets the list of attributes declared on this type parameter. + /// + IList Attributes { get; } + + /// + /// Gets the variance of this type parameter. + /// + VarianceModifier Variance { get; } + + /// + /// Gets the region where the type parameter is defined. + /// + DomRegion Region { get; } + } + + /// + /// Type parameter of a generic class/method. + /// + public interface ITypeParameter : IType, IResolved + { + /// + /// Get the type of this type parameter's owner. + /// + /// EntityType.TypeDefinition or EntityType.Method + EntityType OwnerType { get; } + + /// + /// Gets the owning method/class. + /// + IEntity Owner { get; } + + /// + /// Gets the index of the type parameter in the type parameter list of the owning method/class. + /// + int Index { get; } + /// /// Gets the list of attributes declared on this type parameter. /// @@ -60,24 +94,13 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Gets the effective base class of this type parameter. /// - IType GetEffectiveBaseClass(ITypeResolveContext context); + IType EffectiveBaseClass { get; } /// /// Gets the effective interface set of this type parameter. /// - IEnumerable GetEffectiveInterfaceSet(ITypeResolveContext context); + IList EffectiveInterfaceSet { get; } - /// - /// Gets the constraints of this type parameter. - /// - ITypeParameterConstraints GetConstraints(ITypeResolveContext context); - } - - /// - /// Represents the constraints on a type parameter. - /// - public interface ITypeParameterConstraints : IList - { /// /// Gets if the type parameter has the 'new()' constraint. /// @@ -92,11 +115,6 @@ namespace ICSharpCode.NRefactory.TypeSystem /// Gets if the type parameter has the 'struct' constraint. /// bool HasValueTypeConstraint { get; } - - /// - /// Applies a substitution to the constraints. - /// - ITypeParameterConstraints ApplySubstitution(TypeVisitor substitution); } /// @@ -117,87 +135,4 @@ namespace ICSharpCode.NRefactory.TypeSystem /// Contravariant }; - - #if WITH_CONTRACTS - [ContractClassFor(typeof(ITypeParameter))] - abstract class ITypeParameterContract : ITypeContract, ITypeParameter - { - int ITypeParameter.Index { - get { - Contract.Ensures(Contract.Result() >= 0); - return 0; - } - } - - IList ITypeParameter.Attributes { - get { - Contract.Ensures(Contract.Result>() != null); - return null; - } - } - - IList ITypeParameter.Constraints { - get { - Contract.Ensures(Contract.Result>() != null); - return null; - } - } - - bool ITypeParameter.HasDefaultConstructorConstraint { - get { return false; } - } - - bool ITypeParameter.HasReferenceTypeConstraint { - get { return false; } - } - - bool ITypeParameter.HasValueTypeConstraint { - get { return false; } - } - - IType ITypeParameter.BoundTo { - get { return null; } - } - - ITypeParameter ITypeParameter.UnboundTypeParameter { - get { - ITypeParameter @this = this; - Contract.Ensures((Contract.Result() != null) == (@this.BoundTo != null)); - return null; - } - } - - VarianceModifier ITypeParameter.Variance { - get { return VarianceModifier.Invariant; } - } - - bool IFreezable.IsFrozen { - get { return false; } - } - - void IFreezable.Freeze() - { - } - - EntityType ITypeParameter.OwnerType { - get { return EntityType.None; } - } - - DomRegion ITypeParameter.Region { - get { return DomRegion.Empty; } - } - - IType ITypeParameter.GetEffectiveBaseClass(ITypeResolveContext context) - { - Contract.Requires(context != null); - Contract.Ensures(Contract.Result() != null); - } - - IEnumerable ITypeParameter.GetEffectiveInterfaceSet(ITypeResolveContext context) - { - Contract.Requires(context != null); - Contract.Ensures(Contract.Result>() != null); - } - } - #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs b/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs index c5655da9b0..ad32779137 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs @@ -48,6 +48,31 @@ namespace ICSharpCode.NRefactory.TypeSystem IType Resolve(ITypeResolveContext context); } + public interface ITypeResolveContext + { + /// + /// Gets the parent compilation. + /// This property never returns null. + /// + ICompilation Compilation { get; } + + /// + /// Gets the current assembly. + /// This property may return null if this context does not specify any assembly. + /// + IAssembly CurrentAssembly { get; } + + ITypeDefinition CurrentTypeDefinition { get ;} + + IMember CurrentMember { get; } + + /// + /// Gets the current entity. + /// This property may return null if this context does not specify any entity. + /// + IEntity CurrentEntity { get; } + } + #if WITH_CONTRACTS [ContractClassFor(typeof(ITypeReference))] abstract class ITypeReferenceContract : ITypeReference diff --git a/ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs b/ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs deleted file mode 100644 index 6da0ef7fef..0000000000 --- a/ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; -using System.Diagnostics.Contracts; - -using ICSharpCode.NRefactory.Utils; - -namespace ICSharpCode.NRefactory.TypeSystem -{ - /// - /// Context representing the set of assemblies in which a type is being searched. - /// - #if WITH_CONTRACTS - [ContractClass(typeof(ITypeResolveContextContract))] - #endif - public interface ITypeResolveContext - { - /// - /// Gets the definition for a known type. - /// - /// Returns the type definition; or null if the type was not found - /// - /// This method will may only be called with the 'known types' (see members of KnownTypeReference). - /// As a special case, TypeCode.Empty is used to represent System.Void. - /// - ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode); - - /// - /// Retrieves a type. - /// - /// Namespace that contains the type - /// Name of the type - /// Number of type parameters - /// Language-specific rules for how class names are compared - /// The type definition for the class; or null if no such type exists. - /// This method never returns inner types; it can be used only with top-level types. - ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer); - - /// - /// Retrieves all top-level types. - /// - /// - /// If this method is called within using (pc.Synchronize()), then the returned enumerable is valid - /// only until the end of the synchronize block. - /// - IEnumerable GetTypes(); - - /// - /// Retrieves all types in the specified namespace. - /// - /// Namespace in which types are being retrieved. Use string.Empty for the root namespace. - /// Language-specific rules for how namespace names are compared - /// List of types within that namespace. - /// - /// If this method is called within using (var spc = pc.Synchronize()), then the returned enumerable is valid - /// only until the end of the synchronize block. - /// - IEnumerable GetTypes(string nameSpace, StringComparer nameComparer); - - /// - /// Retrieves all namespaces. - /// - /// - /// If this method is called within using (var spc = pc.Synchronize()), then the returned enumerable is valid - /// only until the end of the synchronize block. - /// - IEnumerable GetNamespaces(); - - /// - /// Gets a namespace. - /// - /// The full name of the namespace. - /// The comparer to use. - /// The full name of the namespace, if it exists; or null if the namespace does not exist. - /// - /// For StringComparer.Ordinal, the return value is either null or the input namespace. - /// For other name comparers, this method returns the declared name of the namespace. - /// - string GetNamespace(string nameSpace, StringComparer nameComparer); - - /// - /// Returns a that - /// represents the same context as this instance, but cannot be modified - /// by other threads. - /// The ISynchronizedTypeResolveContext must be disposed from the same thread - /// that called this method when it is no longer used. - /// - /// - /// A simple implementation might enter a ReaderWriterLock when the synchronized context - /// is created, and releases the lock when Dispose() is called. - /// However, implementations based on immutable data structures are also possible. - /// - ISynchronizedTypeResolveContext Synchronize(); - - /// - /// Returns the cache manager associated with this resolve context, - /// or null if caching is not allowed. - /// Whenever the resolve context changes in some way, this property must return a new object to - /// ensure that old caches are cleared. - /// - CacheManager CacheManager { get; } - } - - #if WITH_CONTRACTS - [ContractClassFor(typeof(ITypeResolveContext))] - abstract class ITypeResolveContextContract : ITypeResolveContext - { - ITypeDefinition ITypeResolveContext.GetClass(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) - { - Contract.Requires(nameSpace != null); - Contract.Requires(name != null); - Contract.Requires(typeParameterCount >= 0); - Contract.Requires(nameComparer != null); - return null; - } - - ISynchronizedTypeResolveContext ITypeResolveContext.Synchronize() - { - Contract.Ensures(Contract.Result() != null); - return null; - } - - IEnumerable ITypeResolveContext.GetTypes() - { - Contract.Ensures(Contract.Result>() != null); - return null; - } - - IEnumerable ITypeResolveContext.GetTypes(string nameSpace, StringComparer nameComparer) - { - Contract.Requires(nameSpace != null); - Contract.Requires(nameComparer != null); - Contract.Ensures(Contract.Result>() != null); - return null; - } - - IEnumerable ITypeResolveContext.GetNamespaces() - { - Contract.Ensures(Contract.Result>() != null); - return null; - } - - Utils.CacheManager ITypeResolveContext.CacheManager { - get { return null; } - } - - string ITypeResolveContext.GetNamespace(string nameSpace, StringComparer nameComparer) - { - Contract.Requires(nameSpace != null); - Contract.Requires(nameComparer != null); - return null; - } - } - #endif -} diff --git a/ICSharpCode.NRefactory/TypeSystem/IVariable.cs b/ICSharpCode.NRefactory/TypeSystem/IVariable.cs index 4adab34c48..b02a472191 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IVariable.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IVariable.cs @@ -22,7 +22,7 @@ using System.Diagnostics.Contracts; namespace ICSharpCode.NRefactory.TypeSystem { /// - /// Represents a variable (name/return type pair). + /// Represents a variable (name/type pair). /// #if WITH_CONTRACTS [ContractClass(typeof(IVariableContract))] @@ -42,17 +42,17 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Gets the type of the variable. /// - ITypeReference Type { get; } + IType Type { get; } /// - /// Gets whether this field is a constant (C#-like const). + /// Gets whether this variable is a constant (C#-like const). /// bool IsConst { get; } /// /// If this field is a constant, retrieves the value. /// - IConstantValue ConstantValue { get; } + object ConstantValue { get; } } #if WITH_CONTRACTS @@ -81,7 +81,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } } - IConstantValue IVariable.ConstantValue { + object IVariable.ConstantValue { get { return null; } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs index 7cc8cf63a7..97f33cc2e2 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs @@ -23,22 +23,44 @@ using System.Linq; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { - /// - /// Base class for immutable objects. Provides implementation for IFreezable that reports the - /// object as always-frozen. - /// - [Serializable] - public abstract class Immutable : IFreezable + public static class FreezableHelper { - bool IFreezable.IsFrozen { - get { return true; } + public static void ThrowIfFrozen(IFreezable freezable) + { + if (freezable.IsFrozen) + throw new InvalidOperationException("Cannot mutate frozen " + freezable.GetType().Name); } - void IFreezable.Freeze() + public static IList FreezeListAndElements(IList list) { + if (list != null) { + foreach (T item in list) + Freeze(item); + } + return FreezeList(list); + } + + public static IList FreezeList(IList list) + { + if (list == null || list.Count == 0) + return EmptyList.Instance; + if (list.IsReadOnly) { + // If the list is already read-only, return it directly. + // This is important, otherwise we might undo the effects of interning. + return list; + } else { + return new ReadOnlyCollection(list.ToArray()); + } + } + + public static void Freeze(object item) + { + IFreezable f = item as IFreezable; + if (f != null) + f.Freeze(); } } - + [Serializable] public abstract class AbstractFreezable : IFreezable { @@ -66,45 +88,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation { } - protected void CheckBeforeMutation() - { - if (isFrozen) - throw new InvalidOperationException("Cannot mutate frozen " + GetType().Name); - } - + /* protected static IList CopyList(IList inputList) { if (inputList == null || inputList.Count == 0) return null; else return new List(inputList); - } - - protected static IList FreezeList(IList list) where T : IFreezable - { - if (list == null || list.Count == 0) - return EmptyList.Instance; - var result = new ReadOnlyCollection(list.ToArray()); - foreach (T item in result) { - item.Freeze(); - } - return result; - } - - protected static IList FreezeList(IList list) - { - if (list == null || list.Count == 0) - return EmptyList.Instance; - else - return new ReadOnlyCollection(list.ToArray()); - } - - protected static IList FreezeList(IList list) - { - if (list == null || list.Count == 0) - return EmptyList.Instance; - else - return new ReadOnlyCollection(list.ToArray()); - } + }*/ } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs deleted file mode 100644 index 0c4c69f7a1..0000000000 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs +++ /dev/null @@ -1,318 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; -using ICSharpCode.NRefactory.Utils; - -namespace ICSharpCode.NRefactory.TypeSystem.Implementation -{ - /// - /// Base class for implementations. - /// - [Serializable] - public abstract class AbstractMember : AbstractFreezable, IMember - { - // possible optimizations to reduce the memory usage of AbstractMember: - // - put 'bool isFrozen' into flags - // - store regions in more compact form (e.g. assume both file names are identical; use ushort for columns) - - ITypeDefinition declaringTypeDefinition; - ITypeReference returnType = SharedTypes.UnknownType; - IList attributes; - IList interfaceImplementations; - DomRegion region; - DomRegion bodyRegion; - string name; - - // 1 byte per enum + 2 bytes for flags - Accessibility accessibility; - EntityType entityType; - - [CLSCompliant(false)] - protected BitVector16 flags; - const ushort FlagSealed = 0x0001; - const ushort FlagAbstract = 0x0002; - const ushort FlagShadowing = 0x0004; - const ushort FlagSynthetic = 0x0008; - const ushort FlagVirtual = 0x0010; - const ushort FlagOverride = 0x0020; - const ushort FlagStatic = 0x0040; - // Flags of form 0xY000 are reserved for use in derived classes (DefaultMethod etc.) - - protected override void FreezeInternal() - { - attributes = FreezeList(attributes); - interfaceImplementations = FreezeList(interfaceImplementations); - base.FreezeInternal(); - } - - protected AbstractMember(ITypeDefinition declaringTypeDefinition, string name, EntityType entityType) - { - if (declaringTypeDefinition == null) - throw new ArgumentNullException("declaringTypeDefinition"); - if (name == null) - throw new ArgumentNullException("name"); - this.declaringTypeDefinition = declaringTypeDefinition; - this.entityType = entityType; - this.name = name; - } - - /// - /// Copy constructor - /// - protected AbstractMember(IMember member) - { - if (member == null) - throw new ArgumentNullException("member"); - this.declaringTypeDefinition = member.DeclaringTypeDefinition; - this.returnType = member.ReturnType; - this.attributes = CopyList(member.Attributes); - this.interfaceImplementations = CopyList(member.InterfaceImplementations); - this.region = member.Region; - this.bodyRegion = member.BodyRegion; - this.name = member.Name; - this.accessibility = member.Accessibility; - this.entityType = member.EntityType; - this.IsSealed = member.IsSealed; - this.IsAbstract = member.IsAbstract; - this.IsShadowing = member.IsShadowing; - this.IsSynthetic = member.IsSynthetic; - this.IsVirtual = member.IsVirtual; - this.IsOverride = member.IsOverride; - this.IsStatic = member.IsStatic; - } - - public ITypeDefinition DeclaringTypeDefinition { - get { return declaringTypeDefinition; } - } - - public virtual IType DeclaringType { - get { return declaringTypeDefinition; } - } - - public virtual IMember MemberDefinition { - get { return this; } - } - - public ITypeReference ReturnType { - get { return returnType; } - set { - CheckBeforeMutation(); - if (value == null) - throw new ArgumentNullException(); - returnType = value; - } - } - - public IList InterfaceImplementations { - get { - if (interfaceImplementations == null) - interfaceImplementations = new List(); - return interfaceImplementations; - } - } - - public bool IsVirtual { - get { return flags[FlagVirtual]; } - set { - CheckBeforeMutation(); - flags[FlagVirtual] = value; - } - } - - public bool IsOverride { - get { return flags[FlagOverride]; } - set { - CheckBeforeMutation(); - flags[FlagOverride] = value; - } - } - - public bool IsOverridable { - get { - return (IsAbstract || IsVirtual || IsOverride) && !IsSealed; - } - } - - public EntityType EntityType { - get { return entityType; } - set { - CheckBeforeMutation(); - entityType = value; - } - } - - public DomRegion Region { - get { return region; } - set { - CheckBeforeMutation(); - region = value; - } - } - - public DomRegion BodyRegion { - get { return bodyRegion; } - set { - CheckBeforeMutation(); - bodyRegion = value; - } - } - - public IList Attributes { - get { - if (attributes == null) - attributes = new List(); - return attributes; - } - } - - public virtual string Documentation { - get { - // To save memory, we don't store the documentation provider within the member, - // but simply use our declaring type definition as documentation provider. - // If that fails, we try if the project content is a documentation provider: - IDocumentationProvider provider = declaringTypeDefinition as IDocumentationProvider - ?? declaringTypeDefinition.ProjectContent as IDocumentationProvider; - if (provider != null) - return provider.GetDocumentation(this); - else - return null; - } - } - - public Accessibility Accessibility { - get { return accessibility; } - set { - CheckBeforeMutation(); - accessibility = value; - } - } - - public bool IsStatic { - get { return flags[FlagStatic]; } - set { - CheckBeforeMutation(); - flags[FlagStatic] = value; - } - } - - public bool IsAbstract { - get { return flags[FlagAbstract]; } - set { - CheckBeforeMutation(); - flags[FlagAbstract] = value; - } - } - - public bool IsSealed { - get { return flags[FlagSealed]; } - set { - CheckBeforeMutation(); - flags[FlagSealed] = value; - } - } - - public bool IsShadowing { - get { return flags[FlagShadowing]; } - set { - CheckBeforeMutation(); - flags[FlagShadowing] = value; - } - } - - public bool IsSynthetic { - get { return flags[FlagSynthetic]; } - set { - CheckBeforeMutation(); - flags[FlagSynthetic] = value; - } - } - - public bool IsPrivate { - get { return Accessibility == Accessibility.Private; } - } - - public bool IsPublic { - get { return Accessibility == Accessibility.Public; } - } - - public bool IsProtected { - get { return Accessibility == Accessibility.Protected; } - } - - public bool IsInternal { - get { return Accessibility == Accessibility.Internal; } - } - - public bool IsProtectedOrInternal { - get { return Accessibility == Accessibility.ProtectedOrInternal; } - } - - public bool IsProtectedAndInternal { - get { return Accessibility == Accessibility.ProtectedAndInternal; } - } - - public IProjectContent ProjectContent { - get { return declaringTypeDefinition.ProjectContent; } - } - - public IParsedFile ParsedFile { - get { return declaringTypeDefinition.ParsedFile; } - } - - public string Name { - get { return name; } - set { - CheckBeforeMutation(); - if (value == null) - throw new ArgumentNullException(); - name = value; - } - } - - public virtual string FullName { - get { - return this.DeclaringType.FullName + "." + this.Name; - } - } - - public string Namespace { - get { return declaringTypeDefinition.Namespace; } - } - - public virtual string ReflectionName { - get { return this.DeclaringType.ReflectionName + "." + this.Name; } - } - - public override string ToString() - { - return "[" + EntityType + " " + ReflectionName + ":" + ReturnType + "]"; - } - - public virtual void ApplyInterningProvider(IInterningProvider provider) - { - if (provider != null) { - returnType = provider.Intern(returnType); - attributes = provider.InternList(attributes); - interfaceImplementations = provider.InternList(interfaceImplementations); - name = provider.Intern(name); - } - } - } -} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractTypeParameter.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs similarity index 59% rename from ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractTypeParameter.cs rename to ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs index 8e3f5baae6..83898c2159 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractTypeParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs @@ -19,11 +19,265 @@ using System; using System.Collections.Generic; using System.Linq; - +using System.Threading; using ICSharpCode.NRefactory.Utils; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { + public abstract class AbstractResolvedTypeParameter : ITypeParameter + { + readonly EntityType ownerType; + readonly IEntity owner; + readonly int index; + readonly string name; + readonly IList attributes; + readonly DomRegion region; + readonly VarianceModifier variance; + + protected AbstractResolvedTypeParameter(IEntity owner, int index, string name, VarianceModifier variance, IList attributes, DomRegion region) + { + if (owner == null) + throw new ArgumentNullException("owner"); + this.owner = owner; + this.ownerType = owner.EntityType; + this.index = index; + this.name = name ?? ((this.OwnerType == EntityType.Method ? "!!" : "!") + index.ToString()); + this.attributes = attributes ?? EmptyList.Instance; + this.region = region; + this.variance = variance; + } + + protected AbstractResolvedTypeParameter(EntityType ownerType, int index, string name, VarianceModifier variance, IList attributes, DomRegion region) + { + this.ownerType = ownerType; + this.index = index; + this.name = name ?? ((this.OwnerType == EntityType.Method ? "!!" : "!") + index.ToString()); + this.attributes = attributes ?? EmptyList.Instance; + this.region = region; + this.variance = variance; + } + + public EntityType OwnerType { + get { return ownerType; } + } + + public IEntity Owner { + get { return owner; } + } + + public int Index { + get { return index; } + } + + public IList Attributes { + get { return attributes; } + } + + public VarianceModifier Variance { + get { return variance; } + } + + public DomRegion Region { + get { return region; } + } + + public ICompilation Compilation { + get { return owner.Compilation; } + } + + public IType EffectiveBaseClass { + get { + throw new NotImplementedException(); + } + } + + public IList EffectiveInterfaceSet { + get { + throw new NotImplementedException(); + } + } + + public abstract bool HasDefaultConstructorConstraint { get; } + public abstract bool HasReferenceTypeConstraint { get; } + public abstract bool HasValueTypeConstraint { get; } + + public TypeKind Kind { + get { return TypeKind.TypeParameter; } + } + + public bool? IsReferenceType { + get { + if (this.HasValueTypeConstraint) + return false; + if (this.HasReferenceTypeConstraint) + return true; + + // A type parameter is known to be a reference type if it has the reference type constraint + // or its effective base class is not object or System.ValueType. + IType effectiveBaseClass = this.EffectiveBaseClass; + if (effectiveBaseClass.Kind == TypeKind.Class || effectiveBaseClass.Kind == TypeKind.Delegate) { + if (effectiveBaseClass.Namespace == "System" && effectiveBaseClass.TypeParameterCount == 0) { + switch (effectiveBaseClass.Name) { + case "Object": + case "ValueType": + case "Enum": + return null; + } + } + return true; + } else if (effectiveBaseClass.Kind == TypeKind.Struct || effectiveBaseClass.Kind == TypeKind.Enum) { + return false; + } + return null; + } + } + + IType IType.DeclaringType { + get { return null; } + } + + int IType.TypeParameterCount { + get { return 0; } + } + + public abstract IEnumerable DirectBaseTypes { get; } + + public string Name { + get { return name; } + } + + string INamedElement.Namespace { + get { return string.Empty; } + } + + string INamedElement.FullName { + get { return name; } + } + + public string ReflectionName { + get { + return (this.OwnerType == EntityType.Method ? "``" : "`") + index.ToString(); + } + } + + ITypeDefinition IType.GetDefinition() + { + return null; + } + + public IType AcceptVisitor(TypeVisitor visitor) + { + return visitor.VisitTypeParameter(this); + } + + public IType VisitChildren(TypeVisitor visitor) + { + return this; + } + + public ITypeReference ToTypeReference() + { + return new TypeParameterReference(this.OwnerType, this.Index); + } + + IEnumerable IType.GetNestedTypes(Predicate filter, GetMemberOptions options) + { + return EmptyList.Instance; + } + + IEnumerable IType.GetNestedTypes(IList typeArguments, Predicate filter, GetMemberOptions options) + { + return EmptyList.Instance; + } + + public IEnumerable GetConstructors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + if (this.HasDefaultConstructorConstraint || this.HasValueTypeConstraint) { + throw new NotImplementedException(); + //DefaultMethod m = DefaultMethod.CreateDefaultConstructor(GetDummyClassForTypeParameter(constraints)); + //if (filter(m)) + // return new [] { m }; + } + return EmptyList.Instance; + } else { + return GetMembersHelper.GetConstructors(this, filter, options); + } + } + + public IEnumerable GetMethods(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + return EmptyList.Instance; + else + return GetMembersHelper.GetMethods(this, FilterNonStatic(filter), options); + } + + public IEnumerable GetMethods(IList typeArguments, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + return EmptyList.Instance; + else + return GetMembersHelper.GetMethods(this, typeArguments, FilterNonStatic(filter), options); + } + + public IEnumerable GetProperties(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + return EmptyList.Instance; + else + return GetMembersHelper.GetProperties(this, FilterNonStatic(filter), options); + } + + public IEnumerable GetFields(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + return EmptyList.Instance; + else + return GetMembersHelper.GetFields(this, FilterNonStatic(filter), options); + } + + public IEnumerable GetEvents(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + return EmptyList.Instance; + else + return GetMembersHelper.GetEvents(this, FilterNonStatic(filter), options); + } + + public IEnumerable GetMembers(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + return EmptyList.Instance; + else + return GetMembersHelper.GetMembers(this, FilterNonStatic(filter), options); + } + + static Predicate FilterNonStatic(Predicate filter) where T : class, IMember + { + if (filter == null) + return member => !member.IsStatic; + else + return member => !member.IsStatic && filter(member); + } + + public sealed override bool Equals(object obj) + { + return Equals(obj as IType); + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + + public virtual bool Equals(IType other) + { + return this == other; // use reference equality for type parameters + } + } + + /* /// /// Base class for implementations. /// @@ -90,7 +344,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } - public abstract bool? IsReferenceType(ITypeResolveContext context); + public abstract bool? IsReferenceType { get; } protected bool? IsReferenceTypeHelper(IType effectiveBaseClass) { @@ -125,11 +379,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return null; } - IType ITypeReference.Resolve(ITypeResolveContext context) - { - return this; - } - public virtual bool Equals(IType other) { // Use reference equality for type parameters. While we could consider any types with same @@ -191,77 +440,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return c; } - public IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers) - { - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { - ITypeParameterConstraints constraints = GetConstraints(context); - if (constraints.HasDefaultConstructorConstraint || constraints.HasValueTypeConstraint) { - DefaultMethod m = DefaultMethod.CreateDefaultConstructor(GetDummyClassForTypeParameter(constraints)); - if (filter(m)) - return new [] { m }; - } - return EmptyList.Instance; - } else { - return GetMembersHelper.GetConstructors(this, context, filter, options); - } - } - - public IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) - { - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) - return EmptyList.Instance; - else - return GetMembersHelper.GetMethods(this, context, FilterNonStatic(filter), options); - } - - public IEnumerable GetMethods(IList typeArguments, ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) - { - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) - return EmptyList.Instance; - else - return GetMembersHelper.GetMethods(this, typeArguments, context, FilterNonStatic(filter), options); - } - - public IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) - { - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) - return EmptyList.Instance; - else - return GetMembersHelper.GetProperties(this, context, FilterNonStatic(filter), options); - } - - public IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) - { - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) - return EmptyList.Instance; - else - return GetMembersHelper.GetFields(this, context, FilterNonStatic(filter), options); - } - - public IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) - { - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) - return EmptyList.Instance; - else - return GetMembersHelper.GetEvents(this, context, FilterNonStatic(filter), options); - } - - public IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) - { - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) - return EmptyList.Instance; - else - return GetMembersHelper.GetMembers(this, context, FilterNonStatic(filter), options); - } - - static Predicate FilterNonStatic(Predicate filter) where T : class, IMember - { - if (filter == null) - return member => !member.IsStatic; - else - return member => !member.IsStatic && filter(member); - } - IEnumerable IType.GetNestedTypes(ITypeResolveContext context, Predicate filter, GetMemberOptions options) { return EmptyList.Instance; @@ -329,4 +507,5 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return this.name; } } + */ } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs index d05baba10a..b0d10929d4 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs @@ -51,7 +51,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation get { return this.FullName; } } - public abstract bool? IsReferenceType(ITypeResolveContext context); + public abstract bool? IsReferenceType { get; } public abstract TypeKind Kind { get; } @@ -68,72 +68,75 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return null; } - IType ITypeReference.Resolve(ITypeResolveContext context) - { - return this; + public virtual IEnumerable DirectBaseTypes { + get { return EmptyList.Instance; } } - public virtual IEnumerable GetBaseTypes(ITypeResolveContext context) - { - return EmptyList.Instance; - } + public abstract ITypeReference ToTypeReference(); - public virtual IEnumerable GetNestedTypes(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + public virtual IEnumerable GetNestedTypes(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - public virtual IEnumerable GetNestedTypes(IList typeArguments, ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + public virtual IEnumerable GetNestedTypes(IList typeArguments, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - public virtual IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + public virtual IEnumerable GetMethods(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - public virtual IEnumerable GetMethods(IList typeArguments, ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + public virtual IEnumerable GetMethods(IList typeArguments, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - public virtual IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers) + public virtual IEnumerable GetConstructors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers) { return EmptyList.Instance; } - public virtual IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + public virtual IEnumerable GetProperties(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - public virtual IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + public virtual IEnumerable GetFields(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - public virtual IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + public virtual IEnumerable GetEvents(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - public virtual IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + public virtual IEnumerable GetMembers(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - IEnumerable members = GetMethods(context, filter, options); + IEnumerable members = GetMethods(filter, options); return members - .Concat(GetProperties(context, filter, options)) - .Concat(GetFields(context, filter, options)) - .Concat(GetEvents(context, filter, options)); + .Concat(GetProperties(filter, options)) + .Concat(GetFields(filter, options)) + .Concat(GetEvents(filter, options)); } - public override bool Equals(object obj) + public override sealed bool Equals(object obj) { return Equals(obj as IType); } - public abstract override int GetHashCode(); - public abstract bool Equals(IType other); + public override int GetHashCode() + { + return base.GetHashCode(); + } + + public virtual bool Equals(IType other) + { + return this == other; // use reference equality by default + } public override string ToString() { diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractUnresolvedEntity.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractUnresolvedEntity.cs new file mode 100644 index 0000000000..2d16690419 --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractUnresolvedEntity.cs @@ -0,0 +1,304 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; +using System.Text; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Base class for implementations. + /// + [Serializable] + public abstract class AbstractUnresolvedEntity : IUnresolvedEntity, IFreezable + { + // possible optimizations to reduce the memory usage of AbstractUnresolvedEntity: + // - store regions in more compact form (e.g. assume both file names are identical; use ushort for columns) + + IUnresolvedTypeDefinition declaringTypeDefinition; + + string name = string.Empty; + IList attributes; + internal RareFields rareFields; + + // 1 byte per enum + 2 bytes for flags + EntityType entityType; + Accessibility accessibility; + internal BitVector16 flags; + + // flags for AbstractUnresolvedEntity: + internal const ushort FlagFrozen = 0x0001; + internal const ushort FlagSealed = 0x0002; + internal const ushort FlagAbstract = 0x0004; + internal const ushort FlagShadowing = 0x0008; + internal const ushort FlagSynthetic = 0x0010; + internal const ushort FlagStatic = 0x0020; + // flags for AbstractUnresolvedMember: + internal const ushort FlagExplicitInterfaceImplementation = 0x0040; + internal const ushort FlagVirtual = 0x0080; + internal const ushort FlagOverride = 0x0100; + // flags for DefaultField: + internal const ushort FlagFieldIsReadOnly = 0x1000; + internal const ushort FlagFieldIsVolatile = 0x2000; + // flags for DefaultMethod: + internal const ushort FlagExtensionMethod = 0x1000; + + public bool IsFrozen { + get { return flags[FlagFrozen]; } + } + + public void Freeze() + { + if (!flags[FlagFrozen]) { + FreezeInternal(); + flags[FlagFrozen] = true; + } + } + + protected virtual void FreezeInternal() + { + attributes = FreezableHelper.FreezeListAndElements(attributes); + if (rareFields != null) + rareFields.FreezeInternal(); + } + + public virtual void ApplyInterningProvider(IInterningProvider provider) + { + if (provider == null) + throw new ArgumentNullException("provider"); + ThrowIfFrozen(); + name = provider.Intern(name); + attributes = provider.InternList(attributes); + if (rareFields != null) + rareFields.ApplyInterningProvider(provider); + } + + [Serializable] + internal class RareFields + { + internal DomRegion region; + internal DomRegion bodyRegion; + internal IParsedFile parsedFile; + + protected internal virtual void FreezeInternal() + { + } + + public virtual void ApplyInterningProvider(IInterningProvider provider) + { + } + } + + protected void ThrowIfFrozen() + { + FreezableHelper.ThrowIfFrozen(this); + } + + public EntityType EntityType { + get { return entityType; } + set { + ThrowIfFrozen(); + entityType = value; + } + } + + internal virtual RareFields WriteRareFields() + { + ThrowIfFrozen(); + if (rareFields == null) rareFields = new RareFields(); + return rareFields; + } + + public DomRegion Region { + get { return rareFields != null ? rareFields.region : DomRegion.Empty; } + set { WriteRareFields().region = value; } + } + + public DomRegion BodyRegion { + get { return rareFields != null ? rareFields.bodyRegion : DomRegion.Empty; } + set { WriteRareFields().bodyRegion = value; } + } + + public IParsedFile ParsedFile { + get { return rareFields != null ? rareFields.parsedFile : null; } + set { WriteRareFields().parsedFile = value; } + } + + public IUnresolvedTypeDefinition DeclaringTypeDefinition { + get { return declaringTypeDefinition; } + set { + ThrowIfFrozen(); + declaringTypeDefinition = value; + } + } + + public IList Attributes { + get { + if (attributes == null) + attributes = new List(); + return attributes; + } + } + + public string Name { + get { return name; } + set { + if (value == null) + throw new ArgumentNullException(); + ThrowIfFrozen(); + name = value; + } + } + + public virtual string FullName { + get { + if (declaringTypeDefinition != null) + return declaringTypeDefinition.FullName + "." + name; + else if (!string.IsNullOrEmpty(this.Namespace)) + return this.Namespace + "." + name; + else + return name; + } + } + + public virtual string Namespace { + get { + if (declaringTypeDefinition != null) + return declaringTypeDefinition.Namespace; + else + return string.Empty; + } + set { + throw new NotSupportedException(); + } + } + + public virtual string ReflectionName { + get { + if (declaringTypeDefinition != null) + return declaringTypeDefinition.ReflectionName + "." + name; + else + return name; + } + } + + public Accessibility Accessibility { + get { return accessibility; } + set { + ThrowIfFrozen(); + accessibility = value; + } + } + + public bool IsStatic { + get { return flags[FlagStatic]; } + set { + ThrowIfFrozen(); + flags[FlagStatic] = value; + } + } + + public bool IsAbstract { + get { return flags[FlagAbstract]; } + set { + ThrowIfFrozen(); + flags[FlagAbstract] = value; + } + } + + public bool IsSealed { + get { return flags[FlagSealed]; } + set { + ThrowIfFrozen(); + flags[FlagSealed] = value; + } + } + + public bool IsShadowing { + get { return flags[FlagShadowing]; } + set { + ThrowIfFrozen(); + flags[FlagShadowing] = value; + } + } + + public bool IsSynthetic { + get { return flags[FlagSynthetic]; } + set { + ThrowIfFrozen(); + flags[FlagSynthetic] = value; + } + } + + bool IHasAccessibility.IsPrivate { + get { return accessibility == Accessibility.Private; } + } + + bool IHasAccessibility.IsPublic { + get { return accessibility == Accessibility.Public; } + } + + bool IHasAccessibility.IsProtected { + get { return accessibility == Accessibility.Protected; } + } + + bool IHasAccessibility.IsInternal { + get { return accessibility == Accessibility.Internal; } + } + + bool IHasAccessibility.IsProtectedOrInternal { + get { return accessibility == Accessibility.ProtectedOrInternal; } + } + + bool IHasAccessibility.IsProtectedAndInternal { + get { return accessibility == Accessibility.ProtectedAndInternal; } + } + + public override string ToString() + { + StringBuilder b = new StringBuilder("["); + b.Append(GetType().Name); + b.Append(' '); + if (this.DeclaringTypeDefinition != null) { + b.Append(this.DeclaringTypeDefinition.Name); + b.Append('.'); + } + b.Append(this.Name); + b.Append(']'); + return b.ToString(); + } + + public IEntity Resolve(ITypeResolveContext context) + { + /* + CacheManager cacheManager = context.CacheManager; + IEntity entity = (IEntity)cacheManager.GetShared(this); + if (entity == null) { + Freeze(); + entity = ResolveInternal(context); + entity = (IEntity)cacheManager.GetOrAddShared(this, entity); + } + return entity;*/ + throw new NotImplementedException(); + } + + protected abstract IEntity ResolveInternal(ITypeResolveContext context); + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractUnresolvedMember.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractUnresolvedMember.cs new file mode 100644 index 0000000000..7a5e9f5dc2 --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractUnresolvedMember.cs @@ -0,0 +1,131 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Base class for implementations. + /// + [Serializable] + public abstract class AbstractUnresolvedMember : AbstractUnresolvedEntity, IUnresolvedMember + { + ITypeReference returnType; + IList interfaceImplementations; + + public override void ApplyInterningProvider(IInterningProvider provider) + { + base.ApplyInterningProvider(provider); + returnType = provider.Intern(returnType); + interfaceImplementations = provider.InternList(interfaceImplementations); + } + + /* + [Serializable] + internal new class RareFields : AbstractUnresolvedEntity.RareFields + { + internal IList interfaceImplementations; + + public override void ApplyInterningProvider(IInterningProvider provider) + { + base.ApplyInterningProvider(provider); + interfaceImplementations = provider.InternList(interfaceImplementations); + } + + protected internal override void FreezeInternal() + { + interfaceImplementations = FreezableHelper.FreezeListAndElements(interfaceImplementations); + base.FreezeInternal(); + } + } + + internal override AbstractUnresolvedEntity.RareFields WriteRareFields() + { + ThrowIfFrozen(); + if (rareFields == null) rareFields = new RareFields(); + return rareFields; + }*/ + + public ITypeReference ReturnType { + get { return returnType; } + set { + ThrowIfFrozen(); + returnType = value; + } + } + + public bool IsExplicitInterfaceImplementation { + get { return flags[FlagExplicitInterfaceImplementation]; } + set { + ThrowIfFrozen(); + flags[FlagExplicitInterfaceImplementation] = value; + } + } + + /* + public IList InterfaceImplementations { + get { + RareFields rareFields = (RareFields)this.rareFields; + if (rareFields == null || rareFields.interfaceImplementations == null) { + rareFields = (RareFields)WriteRareFields(); + return rareFields.interfaceImplementations = new List(); + } + return rareFields.interfaceImplementations; + } + }*/ + + public IList InterfaceImplementations { + get { + if (interfaceImplementations == null) + interfaceImplementations = new List(); + return interfaceImplementations; + } + } + + public bool IsVirtual { + get { return flags[FlagVirtual]; } + set { + ThrowIfFrozen(); + flags[FlagVirtual] = value; + } + } + + public bool IsOverride { + get { return flags[FlagOverride]; } + set { + ThrowIfFrozen(); + flags[FlagOverride] = value; + } + } + + public bool IsOverridable { + get { + // override or virtual or abstract but not sealed + return (flags.Data & (FlagOverride | FlagVirtual | FlagAbstract)) != 0 && !this.IsSealed; + } + } + + public new IMember Resolve(ITypeResolveContext context) + { + return (IMember)base.Resolve(context); + } + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/BaseTypeCollector.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/BaseTypeCollector.cs index 98e9195384..c0d7d8c83a 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/BaseTypeCollector.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/BaseTypeCollector.cs @@ -26,7 +26,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// sealed class BaseTypeCollector : List { - readonly ITypeResolveContext context; readonly Stack activeTypes = new Stack(); /// @@ -35,11 +34,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// internal bool SkipImplementedInterfaces; - public BaseTypeCollector(ITypeResolveContext context) - { - this.context = context; - } - public void CollectBaseTypes(IType type) { IType def = type.GetDefinition() ?? type; @@ -60,7 +54,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation // Avoid outputting a type more than once - necessary for "diamond" multiple inheritance // (e.g. C implements I1 and I2, and both interfaces derive from Object) if (!this.Contains(type)) { - foreach (IType baseType in type.GetBaseTypes(context)) { + foreach (IType baseType in type.DirectBaseTypes) { if (SkipImplementedInterfaces && def != null && def.Kind != TypeKind.Interface && def.Kind != TypeKind.TypeParameter) { if (baseType.Kind == TypeKind.Interface) { // skip the interface diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/CompositeTypeResolveContext.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/CompositeTypeResolveContext.cs deleted file mode 100644 index 77b71e6b17..0000000000 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/CompositeTypeResolveContext.cs +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; -using System.Diagnostics; -using System.Linq; - -using ICSharpCode.NRefactory.Utils; - -namespace ICSharpCode.NRefactory.TypeSystem.Implementation -{ - /// - /// Represents multiple type resolve contexts. - /// - public class CompositeTypeResolveContext : ITypeResolveContext - { - /// - /// Creates a that combines the given resolve contexts. - /// If one of the input parameters is null, the other input parameter is returned directly. - /// If both input parameters are null, the function returns null. - /// - public static ITypeResolveContext Combine(ITypeResolveContext a, ITypeResolveContext b) - { - if (a == null) - return b; - if (b == null) - return a; - return new CompositeTypeResolveContext(new [] { a, b }); - } - - readonly ITypeResolveContext[] children; - - /// - /// Creates a new - /// - public CompositeTypeResolveContext(IEnumerable children) - { - if (children == null) - throw new ArgumentNullException("children"); - this.children = children.ToArray(); - foreach (ITypeResolveContext c in this.children) { - if (c == null) - throw new ArgumentException("children enumeration contains nulls"); - } - } - - private CompositeTypeResolveContext(ITypeResolveContext[] children) - { - Debug.Assert(children != null); - this.children = children; - } - - /// - public virtual ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode) - { - foreach (ITypeResolveContext context in children) { - ITypeDefinition d = context.GetKnownTypeDefinition(typeCode); - if (d != null) - return d; - } - return null; - } - - /// - public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) - { - foreach (ITypeResolveContext context in children) { - ITypeDefinition d = context.GetTypeDefinition(nameSpace, name, typeParameterCount, nameComparer); - if (d != null) - return d; - } - return null; - } - - /// - public IEnumerable GetTypes() - { - return children.SelectMany(c => c.GetTypes()); - } - - /// - public IEnumerable GetTypes(string nameSpace, StringComparer nameComparer) - { - return children.SelectMany(c => c.GetTypes(nameSpace, nameComparer)); - } - - /// - public IEnumerable GetNamespaces() - { - return children.SelectMany(c => c.GetNamespaces()).Distinct(); - } - - /// - public string GetNamespace(string nameSpace, StringComparer nameComparer) - { - foreach (ITypeResolveContext context in children) { - string r = context.GetNamespace(nameSpace, nameComparer); - if (r != null) - return r; - } - return null; - } - - /// - public virtual ISynchronizedTypeResolveContext Synchronize() - { - ISynchronizedTypeResolveContext[] sync = new ISynchronizedTypeResolveContext[children.Length]; - bool success = false; - try { - for (int i = 0; i < sync.Length; i++) { - sync[i] = children[i].Synchronize(); - if (sync[i] == null) - throw new InvalidOperationException(children[i] + ".Synchronize() returned null"); - } - var knownTypeDefinitions = new ITypeDefinition[ReflectionHelper.ByTypeCodeArraySize]; - var r = new CompositeSynchronizedTypeResolveContext(sync, knownTypeDefinitions, new CacheManager(), true); - success = true; - return r; - } finally { - if (!success) { - // something went wrong, so immediately dispose the contexts we acquired - for (int i = 0; i < sync.Length; i++) { - if (sync[i] != null) - sync[i].Dispose(); - } - } - } - } - - public virtual CacheManager CacheManager { - // We don't know if our input contexts are mutable, so, to be on the safe side, - // we don't implement caching here. - get { return null; } - } - - sealed class CompositeSynchronizedTypeResolveContext : CompositeTypeResolveContext, ISynchronizedTypeResolveContext - { - readonly CacheManager cacheManager; - readonly bool isTopLevel; - readonly ITypeDefinition[] knownTypeDefinitions; - - public CompositeSynchronizedTypeResolveContext(ITypeResolveContext[] children, ITypeDefinition[] knownTypeDefinitions, CacheManager cacheManager, bool isTopLevel) - : base(children) - { - Debug.Assert(cacheManager != null); - this.cacheManager = cacheManager; - this.knownTypeDefinitions = knownTypeDefinitions; - this.isTopLevel = isTopLevel; - } - - public void Dispose() - { - if (isTopLevel) { - foreach (ISynchronizedTypeResolveContext element in children) { - element.Dispose(); - } - // When the top-level synchronized block is closed, clear any cached data - cacheManager.Dispose(); - } - } - - public override CacheManager CacheManager { - // I expect CompositeTypeResolveContext to be used for almost all resolver operations, - // so this is the only place where implementing CacheManager is really important. - get { return cacheManager; } - } - - public override ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode) - { - ITypeDefinition typeDef = knownTypeDefinitions[(int)typeCode]; - if (typeDef != null) - return typeDef; - typeDef = base.GetKnownTypeDefinition(typeCode); - knownTypeDefinitions[(int)typeCode] = typeDef; - return typeDef; - } - - public override ISynchronizedTypeResolveContext Synchronize() - { - // re-use the same cache manager for nested synchronized contexts - if (isTopLevel) - return new CompositeSynchronizedTypeResolveContext(children, knownTypeDefinitions, cacheManager, false); - else - return this; - } - } - } -} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/CompoundTypeDefinition.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/CompoundTypeDefinition.cs index adfc5b1683..6fe80fcacc 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/CompoundTypeDefinition.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/CompoundTypeDefinition.cs @@ -22,6 +22,7 @@ using ICSharpCode.NRefactory.Utils; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { + /* /// /// Type definition that represents a partial class with multiple parts. /// @@ -30,7 +31,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation { IList parts; - private CompoundTypeDefinition(ITypeDefinition declaringTypeDefinition, string name) + private CompoundTypeDefinition(CompoundTypeDefinition declaringTypeDefinition, string name) : base(declaringTypeDefinition, name) { } @@ -51,9 +52,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation base.FreezeInternal(); } - public override IList GetParts() - { - return parts; + public override IList Parts { + get { return parts; } } public override string Documentation { @@ -149,4 +149,5 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return false; } } + */ } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs deleted file mode 100644 index a779f314f6..0000000000 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Text; - -using ICSharpCode.NRefactory.Semantics; - -namespace ICSharpCode.NRefactory.TypeSystem.Implementation -{ - /// - /// Default implementation of . - /// - [Serializable] - public sealed class DefaultAttribute : AbstractFreezable, IAttribute, ISupportsInterning - { - ITypeReference attributeType; - readonly ITypeReference[] constructorParameterTypes; - DomRegion region; - IList positionalArguments; - IList> namedArguments; - - protected override void FreezeInternal() - { - positionalArguments = FreezeList(positionalArguments); - - if (namedArguments == null || namedArguments.Count == 0) { - namedArguments = EmptyList>.Instance; - } else { - namedArguments = Array.AsReadOnly(namedArguments.ToArray()); - foreach (var pair in namedArguments) { - pair.Value.Freeze(); - } - } - - base.FreezeInternal(); - } - - public DefaultAttribute(ITypeReference attributeType, IEnumerable constructorParameterTypes) - { - if (attributeType == null) - throw new ArgumentNullException("attributeType"); - this.attributeType = attributeType; - this.constructorParameterTypes = constructorParameterTypes != null ? constructorParameterTypes.ToArray() : null; - } - - public ITypeReference AttributeType { - get { return attributeType; } - } - - public ReadOnlyCollection ConstructorParameterTypes { - get { return Array.AsReadOnly(constructorParameterTypes); } - } - - public DomRegion Region { - get { return region; } - set { - CheckBeforeMutation(); - region = value; - } - } - - public IList PositionalArguments { - get { - if (positionalArguments == null) - positionalArguments = new List(); - return positionalArguments; - } - } - - public IList GetPositionalArguments(ITypeResolveContext context) - { - return this.PositionalArguments.Select(a => a.Resolve(context)).ToList(); - } - - public IList> NamedArguments { - get { - if (namedArguments == null) - namedArguments = new List>(); - return namedArguments; - } - } - - public IList> GetNamedArguments(ITypeResolveContext context) - { - return this.NamedArguments.Select(p => new KeyValuePair(p.Key, p.Value.Resolve(context))).ToList(); - } - - public IMethod ResolveConstructor(ITypeResolveContext context) - { - IType[] parameterTypes = null; - if (constructorParameterTypes != null && constructorParameterTypes.Length > 0) { - parameterTypes = new IType[constructorParameterTypes.Length]; - for (int i = 0; i < parameterTypes.Length; i++) { - parameterTypes[i] = constructorParameterTypes[i].Resolve(context); - } - } - IMethod bestMatch = null; - foreach (IMethod ctor in attributeType.Resolve(context).GetConstructors(context)) { - if (ctor.IsStatic) - continue; - if (parameterTypes == null) { - if (ctor.Parameters.Count == 0) - return ctor; - } else if (ctor.Parameters.Count == parameterTypes.Length) { - bestMatch = ctor; - bool ok = true; - for (int i = 0; i < parameterTypes.Length; i++) { - if (ctor.Parameters[i].Type != parameterTypes[i]) { - ok = false; - break; - } - } - if (ok) - return ctor; - } - } - return bestMatch; - } - - public override string ToString() - { - StringBuilder b = new StringBuilder(); - b.Append('['); - b.Append(attributeType.ToString()); - if (this.PositionalArguments.Count + this.NamedArguments.Count > 0) { - b.Append('('); - bool first = true; - foreach (var element in this.PositionalArguments) { - if (first) first = false; else b.Append(", "); - b.Append(element.ToString()); - } - foreach (var pair in this.NamedArguments) { - if (first) first = false; else b.Append(", "); - b.Append(pair.Key); - b.Append('='); - b.Append(pair.Value.ToString()); - } - b.Append(')'); - } - b.Append(']'); - return b.ToString(); - } - - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - attributeType = provider.Intern(attributeType); - if (constructorParameterTypes != null) { - for (int i = 0; i < constructorParameterTypes.Length; i++) { - constructorParameterTypes[i] = provider.Intern(constructorParameterTypes[i]); - } - } - positionalArguments = provider.InternList(positionalArguments); - } - - int ISupportsInterning.GetHashCodeForInterning() - { - return attributeType.GetHashCode() ^ (positionalArguments != null ? positionalArguments.GetHashCode() : 0) ^ (namedArguments != null ? namedArguments.GetHashCode() : 0) ^ region.GetHashCode(); - } - - bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) - { - DefaultAttribute a = other as DefaultAttribute; - return a != null && attributeType == a.attributeType && positionalArguments == a.positionalArguments && namedArguments == a.namedArguments && region == a.region; - } - - public void AddNamedArgument(string name, ITypeReference type, object value) - { - AddNamedArgument(name, new SimpleConstantValue(type, value)); - } - - public void AddNamedArgument(string name, IConstantValue value) - { - CheckBeforeMutation(); - this.NamedArguments.Add(new KeyValuePair(name, value)); - } - } -} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs index 97818b4a64..fbd34795fb 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs @@ -18,25 +18,22 @@ using System; using System.Collections.Generic; -using System.Diagnostics.Contracts; -using System.Text; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { /// - /// Default implementation for IParameter. + /// Default implementation of . /// - [Serializable] - public sealed class DefaultParameter : AbstractFreezable, IParameter, ISupportsInterning + public sealed class DefaultParameter : IParameter { - string name = string.Empty; - ITypeReference type = SharedTypes.UnknownType; - IList attributes; - IConstantValue defaultValue; - DomRegion region; - byte flags; - - public DefaultParameter(ITypeReference type, string name) + readonly IType type; + readonly string name; + readonly DomRegion region; + readonly IList attributes; + readonly bool isRef, isOut, isParams, isOptional; + readonly object defaultValue; + + public DefaultParameter(IType type, string name) { if (type == null) throw new ArgumentNullException("type"); @@ -46,152 +43,62 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation this.name = name; } - /// - /// Copy constructor - /// - public DefaultParameter(IParameter p) - { - this.name = p.Name; - this.type = p.Type; - this.attributes = CopyList(p.Attributes); - this.defaultValue = p.DefaultValue; - this.region = p.Region; - this.IsRef = p.IsRef; - this.IsOut = p.IsOut; - this.IsParams = p.IsParams; - } - - protected override void FreezeInternal() + public DefaultParameter(IType type, string name, DomRegion region = default(DomRegion), IList attributes = null, + bool isRef = false, bool isOut = false, bool isParams = false, bool isOptional = false, object defaultValue = null) { - attributes = FreezeList(attributes); - if (defaultValue != null) - defaultValue.Freeze(); - base.FreezeInternal(); - } - - public string Name { - get { return name; } - set { - if (value == null) - throw new ArgumentNullException(); - CheckBeforeMutation(); - name = value; - } - } - - public ITypeReference Type { - get { return type; } - set { - if (value == null) - throw new ArgumentNullException(); - CheckBeforeMutation(); - type = value; - } + if (type == null) + throw new ArgumentNullException("type"); + if (name == null) + throw new ArgumentNullException("name"); + this.type = type; + this.name = name; + this.region = region; + this.attributes = attributes; + this.isRef = isRef; + this.isOut = isOut; + this.isParams = isParams; + this.isOptional = isOptional; + this.defaultValue = defaultValue; } public IList Attributes { - get { - if (attributes == null) - attributes = new List(); - return attributes; - } - } - - public IConstantValue DefaultValue { - get { return defaultValue; } - set { - CheckBeforeMutation(); - defaultValue = value; - } - } - - public DomRegion Region { - get { return region; } - set { - CheckBeforeMutation(); - region = value; - } - } - - bool HasFlag(byte flag) - { - return (this.flags & flag) != 0; - } - void SetFlag(byte flag, bool value) - { - CheckBeforeMutation(); - if (value) - this.flags |= flag; - else - this.flags &= unchecked((byte)~flag); + get { return attributes; } } public bool IsRef { - get { return HasFlag(1); } - set { SetFlag(1, value); } + get { return isRef; } } public bool IsOut { - get { return HasFlag(2); } - set { SetFlag(2, value); } + get { return isOut; } } public bool IsParams { - get { return HasFlag(4); } - set { SetFlag(4, value); } + get { return isParams; } } public bool IsOptional { - get { return this.DefaultValue != null; } - } - - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - name = provider.Intern(name); - type = provider.Intern(type); - attributes = provider.InternList(attributes); - defaultValue = provider.Intern(defaultValue); + get { return isOptional; } } - int ISupportsInterning.GetHashCodeForInterning() - { - return type.GetHashCode() ^ name.GetHashCode() - ^ (attributes != null ? attributes.GetHashCode() : 0) - ^ (defaultValue != null ? defaultValue.GetHashCode() : 0); + public string Name { + get { return name; } } - bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) - { - DefaultParameter p = other as DefaultParameter; - return p != null && type == p.type && attributes == p.attributes && name == p.name - && defaultValue == p.defaultValue && region == p.region && flags == p.flags; + public DomRegion Region { + get { return region; } } - public override string ToString() - { - StringBuilder b = new StringBuilder(); - if (IsRef) - b.Append("ref "); - if (IsOut) - b.Append("out "); - if (IsParams) - b.Append("params "); - b.Append(name); - b.Append(':'); - b.Append(type.ToString()); - if (defaultValue != null) { - b.Append(" = "); - b.Append(defaultValue.ToString()); - } - return b.ToString(); + public IType Type { + get { return type; } } bool IVariable.IsConst { get { return false; } } - IConstantValue IVariable.ConstantValue { - get { return null; } + public object ConstantValue { + get { return defaultValue; } } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedAccessor.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedAccessor.cs new file mode 100644 index 0000000000..4a4998642c --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedAccessor.cs @@ -0,0 +1,89 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + public sealed class DefaultResolvedAccessor : IAccessor + { + readonly ICompilation compilation; + readonly Accessibility accessibility; + readonly DomRegion region; + readonly IList attributes; + readonly IList returnTypeAttributes; + + public DefaultResolvedAccessor(ICompilation compilation, Accessibility accessibility, DomRegion region = default(DomRegion), IList attributes = null, IList returnTypeAttributes = null) + { + if (compilation == null) + throw new ArgumentNullException("compilation"); + this.compilation = compilation; + this.accessibility = accessibility; + this.region = region; + this.attributes = attributes ?? EmptyList.Instance; + this.returnTypeAttributes = returnTypeAttributes ?? EmptyList.Instance; + } + + public DomRegion Region { + get { return region; } + } + + public IList Attributes { + get { return attributes; } + } + + public IList ReturnTypeAttributes { + get { return returnTypeAttributes; } + } + + public ICompilation Compilation { + get { return compilation; } + } + + public Accessibility Accessibility { + get { return accessibility; } + } + + public bool IsPrivate { + get { return accessibility == Accessibility.Private; } + } + + public bool IsPublic { + get { return accessibility == Accessibility.Public; } + } + + public bool IsProtected { + get { return accessibility == Accessibility.Protected; } + } + + public bool IsInternal { + get { return accessibility == Accessibility.Internal; } + } + + public bool IsProtectedOrInternal { + get { return accessibility == Accessibility.ProtectedOrInternal; } + } + + public bool IsProtectedAndInternal { + get { return accessibility == Accessibility.ProtectedAndInternal; } + } + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeParameter.cs similarity index 67% rename from ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs rename to ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeParameter.cs index 8aff471b3c..1f7702fee9 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeParameter.cs @@ -19,11 +19,79 @@ using System; using System.Collections.Generic; using System.Linq; - +using System.Threading; using ICSharpCode.NRefactory.Utils; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { + public class DefaultResolvedTypeParameter : AbstractResolvedTypeParameter + { + readonly bool hasValueTypeConstraint; + readonly bool hasReferenceTypeConstraint; + readonly bool hasDefaultConstructorConstraint; + readonly IList constraints; + + public DefaultResolvedTypeParameter( + IEntity owner, int index, + string name = null, + VarianceModifier variance = VarianceModifier.Invariant, + IList attributes = null, + DomRegion region = default(DomRegion), + bool hasValueTypeConstraint = false, bool hasReferenceTypeConstraint = false, bool hasDefaultConstructorConstraint = false, + IList constraints = null) + : base(owner, index, name, variance, attributes, region) + { + this.hasValueTypeConstraint = hasValueTypeConstraint; + this.hasReferenceTypeConstraint = hasReferenceTypeConstraint; + this.hasDefaultConstructorConstraint = hasDefaultConstructorConstraint; + this.constraints = constraints ?? EmptyList.Instance; + } + + public DefaultResolvedTypeParameter( + EntityType ownerType, int index, + string name = null, + VarianceModifier variance = VarianceModifier.Invariant, + IList attributes = null, + DomRegion region = default(DomRegion), + bool hasValueTypeConstraint = false, bool hasReferenceTypeConstraint = false, bool hasDefaultConstructorConstraint = false, + IList constraints = null) + : base(ownerType, index, name, variance, attributes, region) + { + this.hasValueTypeConstraint = hasValueTypeConstraint; + this.hasReferenceTypeConstraint = hasReferenceTypeConstraint; + this.hasDefaultConstructorConstraint = hasDefaultConstructorConstraint; + this.constraints = constraints ?? EmptyList.Instance; + } + + public override bool HasValueTypeConstraint { + get { return hasValueTypeConstraint; } + } + + public override bool HasReferenceTypeConstraint { + get { return hasReferenceTypeConstraint; } + } + + public override bool HasDefaultConstructorConstraint { + get { return hasDefaultConstructorConstraint; } + } + + public override IEnumerable DirectBaseTypes { + get { + bool hasNonInterfaceConstraint = false; + foreach (IType c in constraints) { + yield return c; + if (c.Kind != TypeKind.Interface) + hasNonInterfaceConstraint = true; + } + // Do not add the 'System.Object' constraint if there is another constraint with a base class. + if (this.HasValueTypeConstraint || !hasNonInterfaceConstraint) { + yield return this.Compilation.FindType(this.HasValueTypeConstraint ? KnownTypeCode.ValueType : KnownTypeCode.Object); + } + } + } + } + + /* /// /// Default implementation of . /// @@ -98,10 +166,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation // protect against cyclic type parameters using (var busyLock = BusyManager.Enter(this)) { if (!busyLock.Success) - return SharedTypes.UnknownType; + return SpecialTypes.UnknownType; if (HasValueTypeConstraint) - return context.GetTypeDefinition("System", "ValueType", 0, StringComparer.Ordinal) ?? SharedTypes.UnknownType; + return context.GetTypeDefinition("System", "ValueType", 0, StringComparer.Ordinal) ?? SpecialTypes.UnknownType; List classTypeConstraints = new List(); foreach (ITypeReference constraintRef in this.Constraints) { @@ -153,9 +221,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } /* - * Interning for type parameters is disabled; we can't intern cyclic structures as might - * occur in the constraints, and incomplete interning is dangerous for type parameters - * as we use reference equality. + * Interning for type parameters is disabled; we can't intern cyclic structures as might + * occur in the constraints, and incomplete interning is dangerous for type parameters + * as we use reference equality. void ISupportsInterning.PrepareForInterning(IInterningProvider provider) { // protect against cyclic constraints @@ -184,6 +252,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return base.EqualsForInterning(o) && this.constraints == o.constraints && this.flags == o.flags; - }*/ - } + } + }*/ } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs index 1361ec794d..ca1175ac27 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs @@ -25,14 +25,13 @@ using ICSharpCode.NRefactory.Utils; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { + /* [Serializable] - public class DefaultTypeDefinition : AbstractFreezable, ITypeDefinition + public class DefaultTypeDefinition : AbstractFreezable, ITypeDefinition, ITypeDefinitionPart { readonly IProjectContent projectContent; readonly IParsedFile parsedFile; - readonly ITypeDefinition declaringTypeDefinition; - - volatile ITypeDefinition compoundTypeDefinition; + readonly DefaultTypeDefinition declaringTypeDefinition; string ns; string name; @@ -85,8 +84,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation this.name = name; this.ns = declaringTypeDefinition.Namespace; - - this.compoundTypeDefinition = this; } public DefaultTypeDefinition(IParsedFile parsedFile, string ns, string name) @@ -99,8 +96,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation this.projectContent = parsedFile.ProjectContent; this.ns = ns ?? string.Empty; this.name = name; - - this.compoundTypeDefinition = this; } public DefaultTypeDefinition(IProjectContent projectContent, string ns, string name) @@ -112,8 +107,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation this.projectContent = projectContent; this.ns = ns ?? string.Empty; this.name = name; - - this.compoundTypeDefinition = this; } public TypeKind Kind { @@ -410,15 +403,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } public IEnumerable GetBaseTypes(ITypeResolveContext context) - { - ITypeDefinition compound = this.compoundTypeDefinition; - if (compound != this) - return compound.GetBaseTypes(context); - else - return GetBaseTypesImpl(context); - } - - IEnumerable GetBaseTypesImpl(ITypeResolveContext context) { bool hasNonInterface = false; if (baseTypes != null && kind != TypeKind.Enum) { @@ -452,26 +436,31 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } - internal void SetCompoundTypeDefinition(ITypeDefinition compoundTypeDefinition) - { - this.compoundTypeDefinition = compoundTypeDefinition; + public virtual IList Parts { + get { + return new ITypeDefinitionPart[] { this }; + } } - public virtual IList GetParts() + IType ITypeReference.Resolve(ITypeResolveContext context) { - return new ITypeDefinition[] { this }; + if (context == null) + throw new ArgumentNullException("context"); + return this; } - public ITypeDefinition GetDefinition() + ITypeDefinition IType.GetDefinition() { - return compoundTypeDefinition; + return this; } - IType ITypeReference.Resolve(ITypeResolveContext context) + public ITypeDefinition GetCompoundTypeDefinition(ITypeResolveContext context) { - if (context == null) - throw new ArgumentNullException("context"); - return this; + ITypeDefinition typeDef = context.GetTypeDefinition(this.Namespace, this.Name, this.TypeParameterCount, StringComparer.Ordinal); + if (typeDef != null && typeDef.Parts.Contains(this)) + return typeDef; + else + return null; } #region GetMembers @@ -479,10 +468,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation { const GetMemberOptions opt = GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions; if ((options & opt) == opt) { - ITypeDefinition compound = this.compoundTypeDefinition; - if (compound != this) - return compound.GetNestedTypes(context, filter, options); - return ApplyFilter(this.NestedTypes, filter); } else { return GetMembersHelper.GetNestedTypes(this, context, filter, options); @@ -497,10 +482,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public virtual IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { - ITypeDefinition compound = this.compoundTypeDefinition; - if (compound != this) - return compound.GetMethods(context, filter, options); - return ApplyFilter(this.Methods, Utils.ExtensionMethods.And(m => !m.IsConstructor, filter)); } else { return GetMembersHelper.GetMethods(this, context, filter, options); @@ -515,10 +496,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public virtual IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { - ITypeDefinition compound = this.compoundTypeDefinition; - if (compound != this) - return compound.GetConstructors(context, filter, options); - return GetConstructorsImpl(filter); } else { return GetMembersHelper.GetConstructors(this, context, filter, options); @@ -551,10 +528,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public virtual IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { - ITypeDefinition compound = this.compoundTypeDefinition; - if (compound != this) - return compound.GetProperties(context, filter, options); - return ApplyFilter(this.Properties, filter); } else { return GetMembersHelper.GetProperties(this, context, filter, options); @@ -564,10 +537,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public virtual IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { - ITypeDefinition compound = this.compoundTypeDefinition; - if (compound != this) - return compound.GetFields(context, filter, options); - return ApplyFilter(this.Fields, filter); } else { return GetMembersHelper.GetFields(this, context, filter, options); @@ -577,10 +546,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public virtual IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { - ITypeDefinition compound = this.compoundTypeDefinition; - if (compound != this) - return compound.GetEvents(context, filter, options); - return ApplyFilter(this.Events, filter); } else { return GetMembersHelper.GetEvents(this, context, filter, options); @@ -613,20 +578,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation #region Equals / GetHashCode bool IEquatable.Equals(IType other) { - // Two ITypeDefinitions are considered to be equal if they have the same compound class. - ITypeDefinition typeDef = other as ITypeDefinition; - return typeDef != null && this.ProjectContent == typeDef.ProjectContent && this.GetDefinition().ReflectionName == typeDef.GetDefinition().ReflectionName; - } - - public override bool Equals(object obj) - { - ITypeDefinition typeDef = obj as ITypeDefinition; - return typeDef != null && this.ProjectContent == typeDef.ProjectContent && this.GetDefinition().ReflectionName == typeDef.GetDefinition().ReflectionName; - } - - public override int GetHashCode() - { - return RuntimeHelpers.GetHashCode(compoundTypeDefinition); + // Use reference equality for ITypeDefinitions: + // We do not want to consider different versions of the same type as equal. + return this == other; } #endregion @@ -660,4 +614,5 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return this; } } + */ } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameterConstraints.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameterConstraints.cs deleted file mode 100644 index b2961e4d64..0000000000 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameterConstraints.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; - -namespace ICSharpCode.NRefactory.TypeSystem.Implementation -{ - /// - /// Implementation of - public sealed class DefaultTypeParameterConstraints : ReadOnlyCollection, ITypeParameterConstraints - { - public static readonly ITypeParameterConstraints Empty = new DefaultTypeParameterConstraints(new IType[0], false, false, false); - - public bool HasDefaultConstructorConstraint { get; private set; } - public bool HasReferenceTypeConstraint { get; private set; } - public bool HasValueTypeConstraint { get; private set; } - - public DefaultTypeParameterConstraints(IEnumerable constraints, bool hasDefaultConstructorConstraint, bool hasReferenceTypeConstraint, bool hasValueTypeConstraint) - : base(constraints.ToArray()) - { - this.HasDefaultConstructorConstraint = hasDefaultConstructorConstraint; - this.HasReferenceTypeConstraint = hasReferenceTypeConstraint; - this.HasValueTypeConstraint = hasValueTypeConstraint; - } - - public ITypeParameterConstraints ApplySubstitution(TypeVisitor substitution) - { - if (substitution == null) - throw new ArgumentNullException("substitution"); - if (this.Count == 0) - return this; - else - return new DefaultTypeParameterConstraints( - this.Select(c => c.AcceptVisitor(substitution)), - this.HasDefaultConstructorConstraint, this.HasReferenceTypeConstraint, this.HasValueTypeConstraint); - } - } -} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAccessor.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAccessor.cs similarity index 50% rename from ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAccessor.cs rename to ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAccessor.cs index 3be4ba66d5..d0cdb85271 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAccessor.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAccessor.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; +using ICSharpCode.NRefactory.Utils; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { @@ -26,15 +27,15 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// Default implementation of . /// [Serializable] - public sealed class DefaultAccessor : AbstractFreezable, IAccessor, ISupportsInterning + public sealed class DefaultUnresolvedAccessor : AbstractFreezable, IUnresolvedAccessor, ISupportsInterning, IFreezable { - static readonly DefaultAccessor[] defaultAccessors = CreateDefaultAccessors(); + static readonly DefaultUnresolvedAccessor[] defaultAccessors = CreateDefaultAccessors(); - static DefaultAccessor[] CreateDefaultAccessors() + static DefaultUnresolvedAccessor[] CreateDefaultAccessors() { - DefaultAccessor[] accessors = new DefaultAccessor[(int)Accessibility.ProtectedAndInternal + 1]; + DefaultUnresolvedAccessor[] accessors = new DefaultUnresolvedAccessor[(int)Accessibility.ProtectedAndInternal + 1]; for (int i = 0; i < accessors.Length; i++) { - accessors[i] = new DefaultAccessor(); + accessors[i] = new DefaultUnresolvedAccessor(); accessors[i].accessibility = (Accessibility)i; accessors[i].Freeze(); } @@ -44,13 +45,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Gets the default accessor with the specified accessibility (and without attributes or region). /// - public static IAccessor GetFromAccessibility(Accessibility accessibility) + public static IUnresolvedAccessor GetFromAccessibility(Accessibility accessibility) { int index = (int)accessibility; if (index >= 0 && index < defaultAccessors.Length) { return defaultAccessors[index]; } else { - DefaultAccessor a = new DefaultAccessor(); + DefaultUnresolvedAccessor a = new DefaultUnresolvedAccessor(); a.accessibility = accessibility; a.Freeze(); return a; @@ -59,19 +60,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation Accessibility accessibility; DomRegion region; - IList attributes; - IList returnTypeAttributes; + IList attributes; + IList returnTypeAttributes; protected override void FreezeInternal() { base.FreezeInternal(); - this.attributes = FreezeList(this.attributes); + this.attributes = FreezableHelper.FreezeListAndElements(this.attributes); + this.returnTypeAttributes = FreezableHelper.FreezeListAndElements(this.returnTypeAttributes); } public Accessibility Accessibility { get { return accessibility; } set { - CheckBeforeMutation(); + FreezableHelper.ThrowIfFrozen(this); accessibility = value; } } @@ -79,31 +81,57 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public DomRegion Region { get { return region; } set { - CheckBeforeMutation(); + FreezableHelper.ThrowIfFrozen(this); region = value; } } - public IList Attributes { + public IList Attributes { get { if (attributes == null) - attributes = new List(); + attributes = new List(); return attributes; } } - public IList ReturnTypeAttributes { + public IList ReturnTypeAttributes { get { if (returnTypeAttributes == null) - returnTypeAttributes = new List(); + returnTypeAttributes = new List(); return returnTypeAttributes; } } + bool IHasAccessibility.IsPrivate { + get { return accessibility == Accessibility.Private; } + } + + bool IHasAccessibility.IsPublic { + get { return accessibility == Accessibility.Public; } + } + + bool IHasAccessibility.IsProtected { + get { return accessibility == Accessibility.Protected; } + } + + bool IHasAccessibility.IsInternal { + get { return accessibility == Accessibility.Internal; } + } + + bool IHasAccessibility.IsProtectedOrInternal { + get { return accessibility == Accessibility.ProtectedOrInternal; } + } + + bool IHasAccessibility.IsProtectedAndInternal { + get { return accessibility == Accessibility.ProtectedAndInternal; } + } + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) { - attributes = provider.InternList(attributes); - returnTypeAttributes = provider.InternList(returnTypeAttributes); + if (!this.IsFrozen) { + attributes = provider.InternList(attributes); + returnTypeAttributes = provider.InternList(returnTypeAttributes); + } } int ISupportsInterning.GetHashCodeForInterning() @@ -115,9 +143,23 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { - DefaultAccessor a = other as DefaultAccessor; - return a != null && (attributes == a.attributes && returnTypeAttributes == a.returnTypeAttributes - && accessibility == a.accessibility && region == a.region); + DefaultUnresolvedAccessor o = other as DefaultUnresolvedAccessor; + return o != null && (attributes == o.attributes && returnTypeAttributes == o.returnTypeAttributes + && accessibility == o.accessibility && region == o.region); + } + + public IAccessor Resolve(ITypeResolveContext context) + { + /* + CacheManager cacheManager = compilation.CacheManager; + IAccessor accessor = (IAccessor)cacheManager.GetShared(this); + if (accessor == null) { + Freeze(); + accessor = new DefaultResolvedAccessor(compilation, accessibility, region, attributes.Resolve(compilation), returnTypeAttributes.Resolve(compilation)); + accessor = (IAccessor)cacheManager.GetOrAddShared(this, accessor); + } + return accessor;*/ + throw new NotImplementedException(); } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAttribute.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAttribute.cs new file mode 100644 index 0000000000..95fcc25ef6 --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAttribute.cs @@ -0,0 +1,210 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Default implementation of . + /// + public class DefaultUnresolvedAttribute : AbstractFreezable, IUnresolvedAttribute, IFreezable + { + readonly ITypeReference attributeType; + DomRegion region; + IList constructorParameterTypes; + IList positionalArguments; + IList> namedArguments; + + public DefaultUnresolvedAttribute(ITypeReference attributeType) + { + if (attributeType == null) + throw new ArgumentNullException("attributeType"); + this.attributeType = attributeType; + } + + public DefaultUnresolvedAttribute(ITypeReference attributeType, IEnumerable constructorParameterTypes) + { + if (attributeType == null) + throw new ArgumentNullException("attributeType"); + this.attributeType = attributeType; + this.ConstructorParameterTypes.AddRange(constructorParameterTypes); + } + + protected override void FreezeInternal() + { + base.FreezeInternal(); + constructorParameterTypes = FreezableHelper.FreezeList(constructorParameterTypes); + namedArguments = FreezableHelper.FreezeList(namedArguments); + foreach (var pair in namedArguments) { + FreezableHelper.Freeze(pair.Key); + FreezableHelper.Freeze(pair.Value); + } + } + + public ITypeReference AttributeType { + get { return attributeType; } + } + + public DomRegion Region { + get { return region; } + set { + FreezableHelper.ThrowIfFrozen(this); + region = value; + } + } + + public IList ConstructorParameterTypes { + get { + if (constructorParameterTypes == null) + constructorParameterTypes = new List(); + return constructorParameterTypes; + } + } + + public IList PositionalArguments { + get { + if (positionalArguments == null) + positionalArguments = new List(); + return positionalArguments; + } + } + + public IList> NamedArguments { + get { + if (namedArguments == null) + namedArguments = new List>(); + return namedArguments; + } + } + + public void AddNamedFieldArgument(string fieldName, IConstantValue value) + { + throw new NotImplementedException(); + } + + public void AddNamedFieldArgument(string fieldName, ITypeReference valueType, object value) + { + AddNamedFieldArgument(fieldName, new SimpleConstantValue(valueType, value)); + } + + public void AddNamedPropertyArgument(string propertyName, IConstantValue value) + { + throw new NotImplementedException(); + } + + public void AddNamedPropertyArgument(string propertyName, ITypeReference valueType, object value) + { + AddNamedPropertyArgument(propertyName, new SimpleConstantValue(valueType, value)); + } + + public IAttribute CreateResolvedAttribute(ITypeResolveContext context) + { + throw new NotImplementedException(); + } + + sealed class DefaultResolvedAttribute : IAttribute, IResolved + { + readonly DefaultUnresolvedAttribute unresolved; + readonly ITypeResolveContext context; + readonly IType attributeType; + readonly IList positionalArguments; + + // cannot use ProjectedList because KeyValuePair is value type + IList> namedArguments; + + IMethod constructor; + volatile bool constructorResolved; + + public DefaultResolvedAttribute(DefaultUnresolvedAttribute unresolved, ITypeResolveContext context) + { + this.unresolved = unresolved; + this.context = context; + + this.attributeType = unresolved.AttributeType.Resolve(context); + this.positionalArguments = unresolved.PositionalArguments.Resolve(context); + } + + public IType AttributeType { + get { return attributeType; } + } + + public DomRegion Region { + get { return unresolved.Region; } + } + + public IMethod Constructor { + get { + if (!constructorResolved) { + constructor = ResolveConstructor(); + constructorResolved = true; + } + return constructor; + } + } + + IMethod ResolveConstructor() + { + var parameterTypes = unresolved.ConstructorParameterTypes.Resolve(context); + foreach (var ctor in attributeType.GetConstructors(m => m.Parameters.Count == parameterTypes.Count)) { + bool ok = true; + for (int i = 0; i < parameterTypes.Count; i++) { + if (!ctor.Parameters[i].Type.Equals(parameterTypes[i])) { + ok = false; + break; + } + } + if (ok) + return ctor; + } + return null; + } + + public IList PositionalArguments { + get { return positionalArguments; } + } + + public IList> NamedArguments { + get { + var namedArgs = this.namedArguments; + if (namedArgs != null) { + LazyInit.ReadBarrier(); + return namedArgs; + } else { + namedArgs = new List>(); + foreach (var pair in unresolved.NamedArguments) { + IMember member = pair.Key.Resolve(context); + if (member != null) { + ResolveResult val = pair.Value.Resolve(context); + namedArgs.Add(new KeyValuePair(member, val)); + } + } + return LazyInit.GetOrSet(ref this.namedArguments, namedArgs); + } + } + } + + public ICompilation Compilation { + get { return context.Compilation; } + } + } + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultEvent.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedEvent.cs similarity index 58% rename from ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultEvent.cs rename to ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedEvent.cs index bea77a960f..2f45adf0d1 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultEvent.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedEvent.cs @@ -21,35 +21,39 @@ using System; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { /// - /// Default implementation of . + /// Default implementation of . /// [Serializable] - public class DefaultEvent : AbstractMember, IEvent + public class DefaultUnresolvedEvent : AbstractUnresolvedMember, IUnresolvedEvent { - IAccessor addAccessor, removeAccessor, invokeAccessor; + IUnresolvedAccessor addAccessor, removeAccessor, invokeAccessor; protected override void FreezeInternal() { base.FreezeInternal(); - if (addAccessor != null) addAccessor.Freeze(); - if (removeAccessor != null) removeAccessor.Freeze(); - if (invokeAccessor != null) invokeAccessor.Freeze(); + FreezableHelper.Freeze(addAccessor); + FreezableHelper.Freeze(removeAccessor); + FreezableHelper.Freeze(invokeAccessor); } - public DefaultEvent(ITypeDefinition declaringTypeDefinition, string name) - : base(declaringTypeDefinition, name, EntityType.Event) + public override void ApplyInterningProvider(IInterningProvider provider) { + base.ApplyInterningProvider(provider); + addAccessor = provider.Intern(addAccessor); + removeAccessor = provider.Intern(removeAccessor); + invokeAccessor = provider.Intern(invokeAccessor); } - /// - /// Copy constructor - /// - protected DefaultEvent(IEvent ev) - : base(ev) + public DefaultUnresolvedEvent() { - this.addAccessor = ev.AddAccessor; - this.removeAccessor = ev.RemoveAccessor; - this.invokeAccessor = ev.InvokeAccessor; + this.EntityType = EntityType.Event; + } + + public DefaultUnresolvedEvent(IUnresolvedTypeDefinition declaringType, string name) + { + this.EntityType = EntityType.Event; + this.DeclaringTypeDefinition = declaringType; + this.Name = name; } public bool CanAdd { @@ -64,28 +68,38 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation get { return invokeAccessor != null; } } - public IAccessor AddAccessor{ + public IUnresolvedAccessor AddAccessor { get { return addAccessor; } set { - CheckBeforeMutation(); + ThrowIfFrozen(); addAccessor = value; } } - public IAccessor RemoveAccessor { + public IUnresolvedAccessor RemoveAccessor { get { return removeAccessor; } set { - CheckBeforeMutation(); + ThrowIfFrozen(); removeAccessor = value; } } - public IAccessor InvokeAccessor { + public IUnresolvedAccessor InvokeAccessor { get { return invokeAccessor; } set { - CheckBeforeMutation(); + ThrowIfFrozen(); invokeAccessor = value; } } + + public new IEvent Resolve(ITypeResolveContext context) + { + return (IEvent)base.Resolve(context); + } + + protected override IEntity ResolveInternal(ITypeResolveContext context) + { + throw new NotImplementedException(); + } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedField.cs similarity index 65% rename from ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs rename to ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedField.cs index 22c33d980d..4299405995 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedField.cs @@ -21,40 +21,35 @@ using System; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { /// - /// Default implementation of . + /// Default implementation of . /// [Serializable] - public class DefaultField : AbstractMember, IField + public class DefaultUnresolvedField : AbstractUnresolvedMember, IUnresolvedField { IConstantValue constantValue; - const ushort FlagIsReadOnly = 0x1000; - const ushort FlagIsVolatile = 0x2000; - protected override void FreezeInternal() { - if (constantValue != null) - constantValue.Freeze(); + FreezableHelper.Freeze(constantValue); base.FreezeInternal(); } - public DefaultField(ITypeDefinition declaringTypeDefinition, string name) - : base(declaringTypeDefinition, name, EntityType.Field) + public override void ApplyInterningProvider(IInterningProvider provider) { + base.ApplyInterningProvider(provider); + constantValue = provider.Intern(constantValue); } - protected DefaultField(IField f) : base(f) + public DefaultUnresolvedField() { - this.constantValue = f.ConstantValue; - this.IsReadOnly = f.IsReadOnly; - this.IsVolatile = f.IsVolatile; + this.EntityType = EntityType.Field; } - public override void ApplyInterningProvider(IInterningProvider provider) + public DefaultUnresolvedField(IUnresolvedTypeDefinition declaringType, string name) { - base.ApplyInterningProvider(provider); - if (provider != null) - constantValue = provider.Intern(constantValue); + this.EntityType = EntityType.Field; + this.DeclaringTypeDefinition = declaringType; + this.Name = name; } public bool IsConst { @@ -62,31 +57,37 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } public bool IsReadOnly { - get { return flags[FlagIsReadOnly]; } + get { return flags[FlagFieldIsReadOnly]; } set { - CheckBeforeMutation(); - flags[FlagIsReadOnly] = value; + ThrowIfFrozen(); + flags[FlagFieldIsReadOnly] = value; } } public bool IsVolatile { - get { return flags[FlagIsVolatile]; } + get { return flags[FlagFieldIsVolatile]; } set { - CheckBeforeMutation(); - flags[FlagIsVolatile] = value; + ThrowIfFrozen(); + flags[FlagFieldIsVolatile] = value; } } public IConstantValue ConstantValue { get { return constantValue; } set { - CheckBeforeMutation(); + ThrowIfFrozen(); constantValue = value; } } - ITypeReference IVariable.Type { - get { return this.ReturnType; } + public new IField Resolve(ITypeResolveContext context) + { + return (IField)base.Resolve(context); + } + + protected override IEntity ResolveInternal(ITypeResolveContext context) + { + throw new NotImplementedException(); } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedMethod.cs similarity index 59% rename from ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs rename to ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedMethod.cs index 203cd31ff2..a99d485dbf 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedMethod.cs @@ -23,41 +23,23 @@ using System.Text; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { /// - /// Default implementation of interface. + /// Default implementation of interface. /// [Serializable] - public class DefaultMethod : AbstractMember, IMethod + public class DefaultUnresolvedMethod : AbstractUnresolvedMember, IUnresolvedMethod { - IList returnTypeAttributes; - IList typeParameters; - IList parameters; - - const ushort FlagExtensionMethod = 0x1000; + IList returnTypeAttributes; + IList typeParameters; + IList parameters; protected override void FreezeInternal() { - returnTypeAttributes = FreezeList(returnTypeAttributes); - typeParameters = FreezeList(typeParameters); - parameters = FreezeList(parameters); + returnTypeAttributes = FreezableHelper.FreezeListAndElements(returnTypeAttributes); + typeParameters = FreezableHelper.FreezeListAndElements(typeParameters); + parameters = FreezableHelper.FreezeListAndElements(parameters); base.FreezeInternal(); } - public DefaultMethod(ITypeDefinition declaringTypeDefinition, string name) - : base(declaringTypeDefinition, name, EntityType.Method) - { - } - - /// - /// Copy constructor - /// - protected DefaultMethod(IMethod method) : base(method) - { - returnTypeAttributes = CopyList(method.ReturnTypeAttributes); - typeParameters = CopyList(method.TypeParameters); - parameters = CopyList(method.Parameters); - this.IsExtensionMethod = method.IsExtensionMethod; - } - public override void ApplyInterningProvider(IInterningProvider provider) { base.ApplyInterningProvider(provider); @@ -68,18 +50,30 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } - public IList ReturnTypeAttributes { + public DefaultUnresolvedMethod() + { + this.EntityType = EntityType.Method; + } + + public DefaultUnresolvedMethod(IUnresolvedTypeDefinition declaringType, string name) + { + this.EntityType = EntityType.Method; + this.DeclaringTypeDefinition = declaringType; + this.Name = name; + } + + public IList ReturnTypeAttributes { get { if (returnTypeAttributes == null) - returnTypeAttributes = new List(); + returnTypeAttributes = new List(); return returnTypeAttributes; } } - public IList TypeParameters { + public IList TypeParameters { get { if (typeParameters == null) - typeParameters = new List(); + typeParameters = new List(); return typeParameters; } } @@ -87,7 +81,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public bool IsExtensionMethod { get { return flags[FlagExtensionMethod]; } set { - CheckBeforeMutation(); + ThrowIfFrozen(); flags[FlagExtensionMethod] = value; } } @@ -104,10 +98,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation get { return this.EntityType == EntityType.Operator; } } - public IList Parameters { + public IList Parameters { get { if (parameters == null) - parameters = new List(); + parameters = new List(); return parameters; } } @@ -117,34 +111,42 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation StringBuilder b = new StringBuilder("["); b.Append(EntityType.ToString()); b.Append(' '); - b.Append(DeclaringType.Name); - b.Append('.'); + if (DeclaringTypeDefinition != null) { + b.Append(DeclaringTypeDefinition.Name); + b.Append('.'); + } b.Append(Name); b.Append('('); - var p = this.Parameters; - for (int i = 0; i < p.Count; i++) { - if (i > 0) b.Append(", "); - if (p[i] == null) - b.Append("null"); - else - b.Append(p[i].ToString()); - } + b.Append(string.Join(", ", this.Parameters)); b.Append("):"); b.Append(ReturnType.ToString()); b.Append(']'); return b.ToString(); } - public static DefaultMethod CreateDefaultConstructor(ITypeDefinition typeDefinition) + public new IMethod Resolve(ITypeResolveContext context) + { + return (IMethod)base.Resolve(context); + } + + protected override IEntity ResolveInternal(ITypeResolveContext context) { - DomRegion region = new DomRegion(typeDefinition.Region.FileName, typeDefinition.Region.BeginLine, typeDefinition.Region.BeginColumn); - return new DefaultMethod(typeDefinition, ".ctor") { + throw new NotImplementedException(); + } + /* + public static DefaultUnresolvedMethod CreateDefaultConstructor(IUnresolvedTypeDefinition typeDefinition) + { + if (typeDefinition == null) + throw new ArgumentNullException("typeDefinition"); + DomRegion region = typeDefinition.Region; + region = new DomRegion(region.FileName, region.BeginLine, region.BeginColumn); // remove endline/endcolumn + return new DefaultUnresolvedMethod(typeDefinition, ".ctor") { EntityType = EntityType.Constructor, Accessibility = typeDefinition.IsAbstract ? Accessibility.Protected : Accessibility.Public, IsSynthetic = true, Region = region, ReturnType = typeDefinition }; - } + }*/ } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedParameter.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedParameter.cs new file mode 100644 index 0000000000..d05f02b60d --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedParameter.cs @@ -0,0 +1,191 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; +using System.Diagnostics.Contracts; +using System.Text; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Default implementation for IUnresolvedParameter. + /// + [Serializable] + public sealed class DefaultUnresolvedParameter : IUnresolvedParameter, IFreezable, ISupportsInterning + { + string name = string.Empty; + ITypeReference type = SpecialType.UnknownType; + IList attributes; + IConstantValue defaultValue; + DomRegion region; + byte flags; + + public DefaultUnresolvedParameter() + { + } + + public DefaultUnresolvedParameter(ITypeReference type, string name) + { + if (type == null) + throw new ArgumentNullException("type"); + if (name == null) + throw new ArgumentNullException("name"); + this.type = type; + this.name = name; + } + + void FreezeInternal() + { + attributes = FreezableHelper.FreezeListAndElements(attributes); + FreezableHelper.Freeze(defaultValue); + } + + public string Name { + get { return name; } + set { + if (value == null) + throw new ArgumentNullException(); + FreezableHelper.ThrowIfFrozen(this); + name = value; + } + } + + public ITypeReference Type { + get { return type; } + set { + if (value == null) + throw new ArgumentNullException(); + FreezableHelper.ThrowIfFrozen(this); + type = value; + } + } + + public IList Attributes { + get { + if (attributes == null) + attributes = new List(); + return attributes; + } + } + + public IConstantValue DefaultValue { + get { return defaultValue; } + set { + FreezableHelper.ThrowIfFrozen(this); + defaultValue = value; + } + } + + public DomRegion Region { + get { return region; } + set { + FreezableHelper.ThrowIfFrozen(this); + region = value; + } + } + + bool HasFlag(byte flag) + { + return (this.flags & flag) != 0; + } + void SetFlag(byte flag, bool value) + { + FreezableHelper.ThrowIfFrozen(this); + if (value) + this.flags |= flag; + else + this.flags &= unchecked((byte)~flag); + } + + public bool IsFrozen { + get { return HasFlag(1); } + } + + public void Freeze() + { + if (!this.IsFrozen) { + FreezeInternal(); + this.flags |= 1; + } + } + + public bool IsRef { + get { return HasFlag(2); } + set { SetFlag(2, value); } + } + + public bool IsOut { + get { return HasFlag(4); } + set { SetFlag(4, value); } + } + + public bool IsParams { + get { return HasFlag(8); } + set { SetFlag(8, value); } + } + + public bool IsOptional { + get { return this.DefaultValue != null; } + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + if (!IsFrozen) { + name = provider.Intern(name); + type = provider.Intern(type); + attributes = provider.InternList(attributes); + defaultValue = provider.Intern(defaultValue); + } + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return type.GetHashCode() ^ name.GetHashCode() + ^ (attributes != null ? attributes.GetHashCode() : 0) + ^ (defaultValue != null ? defaultValue.GetHashCode() : 0) + ^ region.GetHashCode() ^ flags; + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + DefaultUnresolvedParameter p = other as DefaultUnresolvedParameter; + return p != null && type == p.type && attributes == p.attributes && name == p.name + && defaultValue == p.defaultValue && region == p.region && flags == p.flags; + } + + public override string ToString() + { + StringBuilder b = new StringBuilder(); + if (IsRef) + b.Append("ref "); + if (IsOut) + b.Append("out "); + if (IsParams) + b.Append("params "); + b.Append(name); + b.Append(':'); + b.Append(type.ToString()); + if (defaultValue != null) { + b.Append(" = "); + b.Append(defaultValue.ToString()); + } + return b.ToString(); + } + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultProperty.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedProperty.cs similarity index 61% rename from ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultProperty.cs rename to ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedProperty.cs index 8e3ec666fb..467adc66c4 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultProperty.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedProperty.cs @@ -22,52 +22,50 @@ using System.Collections.Generic; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { /// - /// Default implementation of . + /// Default implementation of . /// [Serializable] - public class DefaultProperty : AbstractMember, IProperty + public class DefaultUnresolvedProperty : AbstractUnresolvedMember, IUnresolvedProperty { - IAccessor getter, setter; - IList parameters; + IUnresolvedAccessor getter, setter; + IList parameters; protected override void FreezeInternal() { - parameters = FreezeList(parameters); - if (getter != null) getter.Freeze(); - if (setter != null) setter.Freeze(); + parameters = FreezableHelper.FreezeListAndElements(parameters); + FreezableHelper.Freeze(getter); + FreezableHelper.Freeze(setter); base.FreezeInternal(); } - public DefaultProperty(ITypeDefinition declaringTypeDefinition, string name) - : base(declaringTypeDefinition, name, EntityType.Property) + public override void ApplyInterningProvider(IInterningProvider provider) { + base.ApplyInterningProvider(provider); + getter = provider.Intern(getter); + setter = provider.Intern(setter); + parameters = provider.InternList(parameters); } - protected DefaultProperty(IProperty p) : base(p) + public DefaultUnresolvedProperty() { - this.getter = p.Getter; - this.setter = p.Setter; - this.parameters = CopyList(p.Parameters); + this.EntityType = EntityType.Property; } - public override void ApplyInterningProvider(IInterningProvider provider) + public DefaultUnresolvedProperty(IUnresolvedTypeDefinition declaringType, string name) { - base.ApplyInterningProvider(provider); - if (provider != null) { - getter = provider.Intern(getter); - setter = provider.Intern(setter); - parameters = provider.InternList(parameters); - } + this.EntityType = EntityType.Property; + this.DeclaringTypeDefinition = declaringType; + this.Name = name; } public bool IsIndexer { get { return this.EntityType == EntityType.Indexer; } } - public IList Parameters { + public IList Parameters { get { if (parameters == null) - parameters = new List(); + parameters = new List(); return parameters; } } @@ -80,20 +78,30 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation get { return setter != null; } } - public IAccessor Getter{ + public IUnresolvedAccessor Getter { get { return getter; } set { - CheckBeforeMutation(); + ThrowIfFrozen(); getter = value; } } - public IAccessor Setter { + public IUnresolvedAccessor Setter { get { return setter; } set { - CheckBeforeMutation(); + ThrowIfFrozen(); setter = value; } } + + public new IProperty Resolve(ITypeResolveContext context) + { + return (IProperty)base.Resolve(context); + } + + protected override IEntity ResolveInternal(ITypeResolveContext context) + { + throw new NotImplementedException(); + } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedTypeDefinition.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedTypeDefinition.cs new file mode 100644 index 0000000000..98482837ef --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedTypeDefinition.cs @@ -0,0 +1,120 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Represents an unresolved type definition. + /// + [Serializable] + public class DefaultUnresolvedTypeDefinition : AbstractUnresolvedEntity, IUnresolvedTypeDefinition + { + TypeKind kind = TypeKind.Class; + string namespaceName; + IList baseTypes; + IList typeParameters; + IList nestedTypes; + IList members; + + public DefaultUnresolvedTypeDefinition() + { + this.EntityType = EntityType.TypeDefinition; + } + + public DefaultUnresolvedTypeDefinition(string namespaceName, string name) + { + this.namespaceName = namespaceName; + this.Name = name; + } + + public DefaultUnresolvedTypeDefinition(IUnresolvedTypeDefinition declaringTypeDefinition, string name) + { + this.DeclaringTypeDefinition = declaringTypeDefinition; + this.namespaceName = declaringTypeDefinition.Namespace; + this.Name = name; + } + + public TypeKind Kind { + get { return kind; } + set { + ThrowIfFrozen(); + kind = value; + } + } + + public override string Namespace { + get { return namespaceName; } + set { + if (value == null) + throw new ArgumentNullException(); + ThrowIfFrozen(); + namespaceName = value; + } + } + + public IList BaseTypes { + get { + if (baseTypes == null) + baseTypes = new List(); + return baseTypes; + } + } + + public IList TypeParameters { + get { + if (typeParameters == null) + typeParameters = new List(); + return typeParameters; + } + } + + public IList NestedTypes { + get { + if (nestedTypes == null) + nestedTypes = new List(); + return nestedTypes; + } + } + + public IList Members { + get { + if (members == null) + members = new List(); + return members; + } + } + + public new ITypeDefinition Resolve(ITypeResolveContext context) + { + return (ITypeDefinition)base.Resolve(context); + } + + IType ITypeReference.Resolve(ITypeResolveContext context) + { + return (ITypeDefinition)base.Resolve(context); + } + + protected override IEntity ResolveInternal(ITypeResolveContext context) + { + throw new NotImplementedException(); + } + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedTypeParameter.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedTypeParameter.cs new file mode 100644 index 0000000000..f8c8e90058 --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedTypeParameter.cs @@ -0,0 +1,178 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; +using System.Linq; +using System.Threading; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Default implementation of . + /// + [Serializable] + public class DefaultUnresolvedTypeParameter : IUnresolvedTypeParameter, IFreezable + { + readonly IUnresolvedEntity owner; + readonly int index; + IList attributes; + IList constraints; + string name; + DomRegion region; + + EntityType ownerType; + VarianceModifier variance; + BitVector16 flags; + const ushort FlagFrozen = 0x0001; + const ushort FlagReferenceTypeConstraint = 0x0002; + const ushort FlagValueTypeConstraint = 0x0004; + const ushort FlagDefaultConstructorConstraint = 0x0008; + + public void Freeze() + { + if (!flags[FlagFrozen]) { + FreezeInternal(); + flags[FlagFrozen] = true; + } + } + + protected virtual void FreezeInternal() + { + attributes = FreezableHelper.FreezeListAndElements(attributes); + } + + public DefaultUnresolvedTypeParameter(EntityType ownerType, int index, string name = null) + { + this.ownerType = ownerType; + this.index = index; + this.name = name ?? ((owner.EntityType == EntityType.Method ? "!!" : "!") + index.ToString()); + } + + public EntityType OwnerType { + get { return ownerType; } + } + + public int Index { + get { return index; } + } + + public bool IsFrozen { + get { return flags[FlagFrozen]; } + } + + public string Name { + get { return name; } + set { + FreezableHelper.ThrowIfFrozen(this); + name = value; + } + } + + string INamedElement.FullName { + get { return name; } + } + + string INamedElement.Namespace { + get { return string.Empty; } + } + + string INamedElement.ReflectionName { + get { + if (owner.EntityType == EntityType.Method) + return "``" + index.ToString(); + else + return "`" + index.ToString(); + } + } + + public IList Attributes { + get { + if (attributes == null) + attributes = new List(); + return attributes; + } + } + + public IList Constraints { + get { + if (constraints == null) + constraints = new List(); + return constraints; + } + } + + public VarianceModifier Variance { + get { return variance; } + set { + FreezableHelper.ThrowIfFrozen(this); + variance = value; + } + } + + public DomRegion Region { + get { return region; } + set { + FreezableHelper.ThrowIfFrozen(this); + region = value; + } + } + + public bool HasDefaultConstructorConstraint { + get { return flags[FlagDefaultConstructorConstraint]; } + set { + FreezableHelper.ThrowIfFrozen(this); + flags[FlagDefaultConstructorConstraint] = value; + } + } + + public bool HasReferenceTypeConstraint { + get { return flags[FlagReferenceTypeConstraint]; } + set { + FreezableHelper.ThrowIfFrozen(this); + flags[FlagReferenceTypeConstraint] = value; + } + } + + public bool HasValueTypeConstraint { + get { return flags[FlagValueTypeConstraint]; } + set { + FreezableHelper.ThrowIfFrozen(this); + flags[FlagValueTypeConstraint] = value; + } + } + + public virtual ITypeParameter CreateResolvedTypeParameter(ITypeResolveContext context) + { + IEntity owner = null; + if (this.OwnerType == EntityType.Method) { + owner = context.CurrentMember as IMethod; + } else if (this.OwnerType == EntityType.TypeDefinition) { + owner = context.CurrentTypeDefinition; + } + if (owner == null) + throw new InvalidOperationException("Could not determine the type parameter's owner."); + return new DefaultResolvedTypeParameter( + owner, index, name, variance, + this.Attributes.CreateResolvedAttributes(context), this.Region, + this.HasValueTypeConstraint, this.HasReferenceTypeConstraint, this.HasDefaultConstructorConstraint, this.Constraints.Resolve(context) + ); + } + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs index c4fa63cafd..5c76ea65c6 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs @@ -80,6 +80,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation if (context == null) throw new ArgumentNullException("context"); + throw new NotImplementedException(); // CacheManager cache = context.CacheManager; // if (cache != null) { // IType cachedType = cache.GetShared(this) as IType; @@ -87,10 +88,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation // return cachedType; // } - IType type = context.GetTypeDefinition(nameSpace, name, typeParameterCount, StringComparer.Ordinal) ?? SharedTypes.UnknownType; +// IType type = context.GetTypeDefinition(nameSpace, name, typeParameterCount, StringComparer.Ordinal) ?? SpecialType.UnknownType; // if (cache != null) // cache.SetShared(this, type); - return type; +// return type; } public override string ToString() diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/GetMembersHelper.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/GetMembersHelper.cs index 9d8331ec8d..745030bae1 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/GetMembersHelper.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/GetMembersHelper.cs @@ -35,21 +35,21 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation static class GetMembersHelper { #region GetNestedTypes - public static IEnumerable GetNestedTypes(IType type, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + public static IEnumerable GetNestedTypes(IType type, Predicate filter, GetMemberOptions options) { - return GetNestedTypes(type, null, context, filter, options); + return GetNestedTypes(type, null, filter, options); } - public static IEnumerable GetNestedTypes(IType type, IList nestedTypeArguments, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + public static IEnumerable GetNestedTypes(IType type, IList nestedTypeArguments, Predicate filter, GetMemberOptions options) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { - return GetNestedTypesImpl(type, nestedTypeArguments, context, filter, options); + return GetNestedTypesImpl(type, nestedTypeArguments, filter, options); } else { - return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetNestedTypesImpl(t, nestedTypeArguments, context, filter, options)); + return type.GetNonInterfaceBaseTypes().SelectMany(t => GetNestedTypesImpl(t, nestedTypeArguments, filter, options)); } } - static IEnumerable GetNestedTypesImpl(IType outerType, IList nestedTypeArguments, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + static IEnumerable GetNestedTypesImpl(IType outerType, IList nestedTypeArguments, Predicate filter, GetMemberOptions options) { ITypeDefinition outerTypeDef = outerType.GetDefinition(); if (outerTypeDef == null) @@ -78,7 +78,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation if (nestedTypeArguments != null) newTypeArguments[i] = nestedTypeArguments[i - outerTypeParameterCount]; else - newTypeArguments[i] = SharedTypes.UnboundTypeArgument; + newTypeArguments[i] = SpecialType.UnboundTypeArgument; } yield return new ParameterizedType(nestedType, newTypeArguments); } @@ -87,21 +87,21 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation #endregion #region GetMethods - public static IEnumerable GetMethods(IType type, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + public static IEnumerable GetMethods(IType type, Predicate filter, GetMemberOptions options) { - return GetMethods(type, null, context, filter, options); + return GetMethods(type, null, filter, options); } - public static IEnumerable GetMethods(IType type, IList typeArguments, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + public static IEnumerable GetMethods(IType type, IList typeArguments, Predicate filter, GetMemberOptions options) { if (typeArguments != null && typeArguments.Count > 0) { filter = FilterTypeParameterCount(typeArguments.Count).And(filter); } if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { - return GetMethodsImpl(type, typeArguments, context, filter, options); + return GetMethodsImpl(type, typeArguments, filter, options); } else { - return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetMethodsImpl(t, typeArguments, context, filter, options)); + return type.GetNonInterfaceBaseTypes().SelectMany(t => GetMethodsImpl(t, typeArguments, filter, options)); } } @@ -112,9 +112,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation const GetMemberOptions declaredMembers = GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions; - static IEnumerable GetMethodsImpl(IType baseType, IList methodTypeArguments, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + static IEnumerable GetMethodsImpl(IType baseType, IList methodTypeArguments, Predicate filter, GetMemberOptions options) { - IEnumerable declaredMethods = baseType.GetMethods(context, filter, options | declaredMembers); + IEnumerable declaredMethods = baseType.GetMethods(filter, options | declaredMembers); ParameterizedType pt = baseType as ParameterizedType; if ((options & GetMemberOptions.ReturnMemberDefinitions) == 0 @@ -132,7 +132,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation else substitution = new TypeParameterSubstitution(null, methodTypeArguments); } - yield return new SpecializedMethod(baseType, m, methodTypeArguments, substitution, context); + yield return new SpecializedMethod(baseType, m, methodTypeArguments, substitution); } } else { foreach (IMethod m in declaredMethods) { @@ -143,18 +143,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation #endregion #region GetConstructors - public static IEnumerable GetConstructors(IType type, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + public static IEnumerable GetConstructors(IType type, Predicate filter, GetMemberOptions options) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { - return GetConstructorsImpl(type, context, filter, options); + return GetConstructorsImpl(type, filter, options); } else { - return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetConstructorsImpl(t, context, filter, options)); + return type.GetNonInterfaceBaseTypes().SelectMany(t => GetConstructorsImpl(t, filter, options)); } } - static IEnumerable GetConstructorsImpl(IType baseType, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + static IEnumerable GetConstructorsImpl(IType baseType, Predicate filter, GetMemberOptions options) { - IEnumerable declaredCtors = baseType.GetConstructors(context, filter, options | declaredMembers); + IEnumerable declaredCtors = baseType.GetConstructors(filter, options | declaredMembers); if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { return declaredCtors; } @@ -162,7 +162,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation ParameterizedType pt = baseType as ParameterizedType; if (pt != null) { var substitution = pt.GetSubstitution(); - return declaredCtors.Select(m => new SpecializedMethod(pt, m, null, substitution, context)); + return declaredCtors.Select(m => new SpecializedMethod(pt, m, null, substitution)); } else { return declaredCtors; } @@ -170,18 +170,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation #endregion #region GetProperties - public static IEnumerable GetProperties(IType type, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + public static IEnumerable GetProperties(IType type, Predicate filter, GetMemberOptions options) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { - return GetPropertiesImpl(type, context, filter, options); + return GetPropertiesImpl(type, filter, options); } else { - return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetPropertiesImpl(t, context, filter, options)); + return type.GetNonInterfaceBaseTypes().SelectMany(t => GetPropertiesImpl(t, filter, options)); } } - static IEnumerable GetPropertiesImpl(IType baseType, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + static IEnumerable GetPropertiesImpl(IType baseType, Predicate filter, GetMemberOptions options) { - IEnumerable declaredProperties = baseType.GetProperties(context, filter, options | declaredMembers); + IEnumerable declaredProperties = baseType.GetProperties(filter, options | declaredMembers); if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { return declaredProperties; } @@ -189,7 +189,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation ParameterizedType pt = baseType as ParameterizedType; if (pt != null) { var substitution = pt.GetSubstitution(); - return declaredProperties.Select(m => new SpecializedProperty(pt, m, substitution, context)); + return declaredProperties.Select(m => new SpecializedProperty(pt, m, substitution)); } else { return declaredProperties; } @@ -197,18 +197,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation #endregion #region GetFields - public static IEnumerable GetFields(IType type, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + public static IEnumerable GetFields(IType type, Predicate filter, GetMemberOptions options) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { - return GetFieldsImpl(type, context, filter, options); + return GetFieldsImpl(type, filter, options); } else { - return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetFieldsImpl(t, context, filter, options)); + return type.GetNonInterfaceBaseTypes().SelectMany(t => GetFieldsImpl(t, filter, options)); } } - static IEnumerable GetFieldsImpl(IType baseType, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + static IEnumerable GetFieldsImpl(IType baseType, Predicate filter, GetMemberOptions options) { - IEnumerable declaredFields = baseType.GetFields(context, filter, options | declaredMembers); + IEnumerable declaredFields = baseType.GetFields(filter, options | declaredMembers); if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { return declaredFields; } @@ -216,7 +216,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation ParameterizedType pt = baseType as ParameterizedType; if (pt != null) { var substitution = pt.GetSubstitution(); - return declaredFields.Select(m => new SpecializedField(pt, m, substitution, context)); + return declaredFields.Select(m => new SpecializedField(pt, m, substitution)); } else { return declaredFields; } @@ -224,18 +224,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation #endregion #region GetEvents - public static IEnumerable GetEvents(IType type, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + public static IEnumerable GetEvents(IType type, Predicate filter, GetMemberOptions options) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { - return GetEventsImpl(type, context, filter, options); + return GetEventsImpl(type, filter, options); } else { - return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetEventsImpl(t, context, filter, options)); + return type.GetNonInterfaceBaseTypes().SelectMany(t => GetEventsImpl(t, filter, options)); } } - static IEnumerable GetEventsImpl(IType baseType, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + static IEnumerable GetEventsImpl(IType baseType, Predicate filter, GetMemberOptions options) { - IEnumerable declaredEvents = baseType.GetEvents(context, filter, options | declaredMembers); + IEnumerable declaredEvents = baseType.GetEvents(filter, options | declaredMembers); if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { return declaredEvents; } @@ -243,7 +243,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation ParameterizedType pt = baseType as ParameterizedType; if (pt != null) { var substitution = pt.GetSubstitution(); - return declaredEvents.Select(m => new SpecializedEvent(pt, m, substitution, context)); + return declaredEvents.Select(m => new SpecializedEvent(pt, m, substitution)); } else { return declaredEvents; } @@ -251,24 +251,24 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation #endregion #region GetMembers - public static IEnumerable GetMembers(IType type, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + public static IEnumerable GetMembers(IType type, Predicate filter, GetMemberOptions options) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { - return GetMembersImpl(type, context, filter, options); + return GetMembersImpl(type, filter, options); } else { - return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetMembersImpl(t, context, filter, options)); + return type.GetNonInterfaceBaseTypes().SelectMany(t => GetMembersImpl(t, filter, options)); } } - static IEnumerable GetMembersImpl(IType baseType, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + static IEnumerable GetMembersImpl(IType baseType, Predicate filter, GetMemberOptions options) { - foreach (var m in GetMethodsImpl(baseType, null, context, filter, options)) + foreach (var m in GetMethodsImpl(baseType, null, filter, options)) yield return m; - foreach (var m in GetPropertiesImpl(baseType, context, filter, options)) + foreach (var m in GetPropertiesImpl(baseType, filter, options)) yield return m; - foreach (var m in GetFieldsImpl(baseType, context, filter, options)) + foreach (var m in GetFieldsImpl(baseType, filter, options)) yield return m; - foreach (var m in GetEventsImpl(baseType, context, filter, options)) + foreach (var m in GetEventsImpl(baseType, filter, options)) yield return m; } #endregion diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/MinimalResolveContext.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/MinimalResolveContext.cs index e87fcf87e5..4c73c719da 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/MinimalResolveContext.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/MinimalResolveContext.cs @@ -23,6 +23,7 @@ using System.Linq; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { + /* /// /// Resolve context represents the minimal mscorlib required for evaluating constants. /// @@ -177,4 +178,5 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation get { return "MinimalResolveContext"; } } } + */ } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs index 04e9385a21..e6f2a909d8 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs @@ -73,7 +73,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return type; } } - return SharedTypes.UnknownType; + return SpecialType.UnknownType; } public override string ToString() diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs deleted file mode 100644 index ee0b06ed60..0000000000 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; - -namespace ICSharpCode.NRefactory.TypeSystem.Implementation -{ - /// - /// Proxy that forwards calls to another TypeResolveContext. - /// Useful as base class for decorators. - /// - [Serializable] - public class ProxyTypeResolveContext : ITypeResolveContext - { - protected readonly ITypeResolveContext target; - - /// - /// Creates a new ProxyTypeResolveContext. - /// - public ProxyTypeResolveContext(ITypeResolveContext target) - { - if (target == null) - throw new ArgumentNullException("target"); - this.target = target; - } - - /// - public virtual ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) - { - return target.GetTypeDefinition(nameSpace, name, typeParameterCount, nameComparer); - } - - /// - public virtual IEnumerable GetTypes() - { - return target.GetTypes(); - } - - /// - public virtual IEnumerable GetTypes(string nameSpace, StringComparer nameComparer) - { - return target.GetTypes(nameSpace, nameComparer); - } - - /// - public virtual IEnumerable GetNamespaces() - { - return target.GetNamespaces(); - } - - /// - public virtual string GetNamespace(string nameSpace, StringComparer nameComparer) - { - return target.GetNamespace(nameSpace, nameComparer); - } - - /// - public virtual ISynchronizedTypeResolveContext Synchronize() - { - return target.Synchronize(); - } - - /// - public virtual Utils.CacheManager CacheManager { - // Don't forward this by default; we don't know what derived classes are doing; - // it might not be cache-safe. - get { return null; } - } - - /// - public virtual ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode) - { - return target.GetKnownTypeDefinition(typeCode); - } - } -} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleCompilation.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleCompilation.cs new file mode 100644 index 0000000000..488ebdbfa5 --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleCompilation.cs @@ -0,0 +1,94 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Simple compilation implementation. + /// + public class SimpleCompilation : ICompilation + { + readonly CacheManager cacheManager; + IAssembly mainAssembly; + IList referencedAssemblies; + + public SimpleCompilation(IUnresolvedAssembly mainAssembly, params IAssemblyReference[] assemblyReferences) + : this(mainAssembly, (IEnumerable)assemblyReferences) + { + } + + public SimpleCompilation(IUnresolvedAssembly mainAssembly, IEnumerable assemblyReferences) + { + this.cacheManager = new CacheManager(); + this.mainAssembly = mainAssembly.Resolve(this); + this.referencedAssemblies = new List(); + foreach (var asmRef in assemblyReferences) { + IAssembly asm = asmRef.Resolve(this); + if (asm != null) + this.referencedAssemblies.Add(asm); + } + this.referencedAssemblies = new ReadOnlyCollection(this.referencedAssemblies); + } + + public IAssembly MainAssembly { + get { return mainAssembly; } + } + + public IList ReferencedAssemblies { + get { return referencedAssemblies; } + } + + public ITypeResolveContext TypeResolveContext { + get { + throw new NotImplementedException(); + } + } + + public INamespace RootNamespace { + get { + throw new NotImplementedException(); + } + } + + public CacheManager CacheManager { + get { return cacheManager; } + } + + public virtual INamespace GetNamespaceForExternAlias(string alias) + { + return null; + } + + public IEnumerable GetAllTypeDefinitions() + { + return TreeTraversal.PreOrder(this.RootNamespace, ns => ns.ChildNamespaces) + .SelectMany(ns => TreeTraversal.PreOrder(ns.Types, t => t.NestedTypes)); + } + + IType ICompilation.FindType(KnownTypeCode typeCode) + { + throw new NotImplementedException(); + } + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs index 05c37c21a0..91e0e29731 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs @@ -25,7 +25,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// A simple constant value that is independent of the resolve context. /// [Serializable] - public sealed class SimpleConstantValue : Immutable, IConstantValue, ISupportsInterning + public sealed class SimpleConstantValue : IConstantValue, ISupportsInterning { ITypeReference type; object value; @@ -40,11 +40,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public ResolveResult Resolve(ITypeResolveContext context) { - if (value is ITypeReference) { - return new TypeOfResolveResult(type.Resolve(context), ((ITypeReference)value).Resolve(context)); - } else { - return new ConstantResolveResult(type.Resolve(context), value); - } + return new ConstantResolveResult(type.Resolve(context), value); } public override string ToString() diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs index 0aca7d06da..5d7f6a7e84 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs @@ -32,13 +32,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// public sealed class SimpleInterningProvider : IInterningProvider { - public SimpleInterningProvider() - { - // Intern the well-known types first; so that they are used when possible. - foreach (ITypeReference r in KnownTypeReference.AllKnownTypeReferences) - Intern(r); - } - sealed class InterningComparer : IEqualityComparer { public bool Equals(ISupportsInterning x, ISupportsInterning y) @@ -108,8 +101,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation supportsInternDict.Add(s, s); } } else if (Type.GetTypeCode(obj.GetType()) >= TypeCode.Boolean) { - // IType cannot be interned by value because ITypeParameters with different names are considered - // equal (for object.Equals), but should not be interned. + // Intern primitive types (and strings) by value object output; if (byValueDict.TryGetValue(obj, out output)) obj = (T)output; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs index 0189d3cca1..1060fab5db 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs @@ -26,6 +26,7 @@ using ICSharpCode.NRefactory.Utils; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { + /* /// /// Simple implementation that stores the list of classes/namespaces. /// Synchronization is implemented using a . @@ -355,4 +356,5 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } #endregion } + */ } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedEvent.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedEvent.cs index 9846da2d4c..3e8892f383 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedEvent.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedEvent.cs @@ -31,14 +31,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation : base(declaringType, eventDefinition) { this.eventDefinition = eventDefinition; - Initialize(GetSubstitution(declaringType), null); + Initialize(GetSubstitution(declaringType)); } - internal SpecializedEvent(IType declaringType, IEvent eventDefinition, TypeVisitor substitution, ITypeResolveContext context) + internal SpecializedEvent(IType declaringType, IEvent eventDefinition, TypeVisitor substitution) : base(declaringType, eventDefinition) { this.eventDefinition = eventDefinition; - Initialize(substitution, context); + Initialize(substitution); } public bool CanAdd { diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs index 385dbb3bc1..5e26d2cdec 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs @@ -31,14 +31,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation : base(declaringType, fieldDefinition) { this.fieldDefinition = fieldDefinition; - Initialize(GetSubstitution(declaringType), null); + Initialize(GetSubstitution(declaringType)); } - internal SpecializedField(IType declaringType, IField fieldDefinition, TypeVisitor substitution, ITypeResolveContext context) + internal SpecializedField(IType declaringType, IField fieldDefinition, TypeVisitor substitution) : base(declaringType, fieldDefinition) { this.fieldDefinition = fieldDefinition; - Initialize(substitution, context); + Initialize(substitution); } public bool IsReadOnly { @@ -49,7 +49,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation get { return fieldDefinition.IsVolatile; } } - ITypeReference IVariable.Type { + IType IVariable.Type { get { return this.ReturnType; } } @@ -57,7 +57,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation get { return fieldDefinition.IsConst; } } - public IConstantValue ConstantValue { + public object ConstantValue { get { return fieldDefinition.ConstantValue; } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs index cc9c88c0f4..bb7088fdf1 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs @@ -29,7 +29,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation { readonly IType declaringType; readonly IMember memberDefinition; - ITypeReference returnType; + IType returnType; protected SpecializedMember(IType declaringType, IMember memberDefinition) { @@ -42,9 +42,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation this.memberDefinition = memberDefinition; } - protected virtual void Initialize(TypeVisitor substitution, ITypeResolveContext context) + protected virtual void Initialize(TypeVisitor substitution) { - this.returnType = Substitute(memberDefinition.ReturnType, substitution, context); + this.returnType = Substitute(memberDefinition.ReturnType, substitution); + } + + public virtual IMemberReference ToMemberReference() + { + throw new NotImplementedException(); } internal static TypeVisitor GetSubstitution(IType declaringType) @@ -56,14 +61,12 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return null; } - internal static ITypeReference Substitute(ITypeReference type, TypeVisitor substitution, ITypeResolveContext context) + internal static IType Substitute(IType type, TypeVisitor substitution) { if (substitution == null) return type; - if (context != null) - return type.Resolve(context).AcceptVisitor(substitution); else - return SubstitutionTypeReference.Create(type, substitution); + return type.AcceptVisitor(substitution); } public IType DeclaringType { @@ -74,12 +77,12 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation get { return memberDefinition; } } - public ITypeReference ReturnType { + public IType ReturnType { get { return returnType; } } - public IList InterfaceImplementations { - get { return memberDefinition.InterfaceImplementations; } + public IUnresolvedEntity UnresolvedEntity { + get { return memberDefinition.UnresolvedEntity; } } public bool IsVirtual { @@ -114,6 +117,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation get { return memberDefinition.Attributes; } } + public IList InterfaceImplementations { + get { throw new NotImplementedException(); } + } + + public bool IsExplicitInterfaceImplementation { + get { return memberDefinition.IsExplicitInterfaceImplementation; } + } + public string Documentation { get { return memberDefinition.Documentation; } } @@ -166,14 +177,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation get { return memberDefinition.IsProtectedAndInternal; } } - public IProjectContent ProjectContent { - get { return memberDefinition.ProjectContent; } - } - - public IParsedFile ParsedFile { - get { return memberDefinition.ParsedFile; } - } - public string FullName { get { return memberDefinition.FullName; } } @@ -190,14 +193,12 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation get { return memberDefinition.ReflectionName; } } - public bool IsFrozen { - get { return memberDefinition.IsFrozen; } + public ICompilation Compilation { + get { return memberDefinition.Compilation; } } - void IFreezable.Freeze() - { - if (!memberDefinition.IsFrozen) - throw new NotSupportedException(); + public IAssembly ParentAssembly { + get { return memberDefinition.ParentAssembly; } } public override bool Equals(object obj) @@ -239,9 +240,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation { } - protected override void Initialize(TypeVisitor substitution, ITypeResolveContext context) + protected override void Initialize(TypeVisitor substitution) { - base.Initialize(substitution, context); + base.Initialize(substitution); var paramDefs = ((IParameterizedMember)this.MemberDefinition).Parameters; if (paramDefs.Count == 0) { @@ -249,9 +250,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } else { var parameters = new IParameter[paramDefs.Count]; for (int i = 0; i < parameters.Length; i++) { - ITypeReference newType = Substitute(paramDefs[i].Type, substitution, context); + IType newType = Substitute(paramDefs[i].Type, substitution); if (newType != paramDefs[i].Type) { - parameters[i] = new DefaultParameter(paramDefs[i]) { Type = newType }; + parameters[i] = new SpecializedParameter(paramDefs[i], newType); } else { parameters[i] = paramDefs[i]; } @@ -282,5 +283,57 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation b.Append(']'); return b.ToString(); } + + sealed class SpecializedParameter : IParameter + { + readonly IParameter originalParameter; + readonly IType newType; + + public SpecializedParameter(IParameter originalParameter, IType newType) + { + this.originalParameter = originalParameter; + this.newType = newType; + } + + public IList Attributes { + get { return originalParameter.Attributes; } + } + + public bool IsRef { + get { return originalParameter.IsRef; } + } + + public bool IsOut { + get { return originalParameter.IsOut; } + } + + public bool IsParams { + get { return originalParameter.IsParams; } + } + + public bool IsOptional { + get { return originalParameter.IsOptional; } + } + + public string Name { + get { return originalParameter.Name; } + } + + public DomRegion Region { + get { return originalParameter.Region; } + } + + public IType Type { + get { return newType; } + } + + public bool IsConst { + get { return originalParameter.IsConst; } + } + + public object ConstantValue { + get { return originalParameter.ConstantValue; } + } + } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs index 0814a0d33b..415e475ad3 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs @@ -36,11 +36,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation readonly IList specializedTypeParameters; public SpecializedMethod(IType declaringType, IMethod methodDefinition, IList typeArguments = null) - : this(declaringType, methodDefinition, typeArguments, GetSubstitution(declaringType, typeArguments), null) + : this(declaringType, methodDefinition, typeArguments, GetSubstitution(declaringType, typeArguments)) { } - internal SpecializedMethod(IType declaringType, IMethod methodDefinition, IList typeArguments, TypeVisitor substitution, ITypeResolveContext context) + internal protected SpecializedMethod(IType declaringType, IMethod methodDefinition, IList typeArguments, TypeVisitor substitution) : base(declaringType, methodDefinition) { if (declaringType == null) @@ -57,7 +57,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation for (int i = 0; i < specializedTypeParameters.Count; i++) { ITypeParameter tp = methodDefinition.TypeParameters[i]; if (ConstraintNeedsSpecialization(tp)) - tp = new SpecializedTypeParameter(tp, substitution); + tp = new SpecializedTypeParameter(tp, this, substitution); specializedTypeParameters[i] = tp; } } @@ -75,16 +75,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } - Initialize(substitution, null); + Initialize(substitution); } static bool ConstraintNeedsSpecialization(ITypeParameter tp) { - DefaultTypeParameter dtp = tp as DefaultTypeParameter; - if (dtp != null) - return dtp.Constraints.Count != 0; - else - return true; // we can't know if specialization will be required + // TODO: can we avoid specialization if a type parameter doesn't have any constraints? + return true; } internal static TypeVisitor GetSubstitution(IType declaringType, IList typeArguments) @@ -184,46 +181,47 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return b.ToString(); } - sealed class SpecializedTypeParameter : AbstractTypeParameter + sealed class SpecializedTypeParameter : AbstractResolvedTypeParameter { readonly ITypeParameter baseTp; - // The substition may be replaced at the end of SpecializedMethod constructor + + // not readonly: The substition may be replaced at the end of SpecializedMethod constructor internal TypeVisitor substitution; - public SpecializedTypeParameter(ITypeParameter baseTP, TypeVisitor substitution) - : base(baseTP.OwnerType, baseTP.Index, baseTP.Name) + public SpecializedTypeParameter(ITypeParameter baseTp, IMethod specializedOwner, TypeVisitor substitution) + : base(specializedOwner, baseTp.Index, baseTp.Name, baseTp.Variance, baseTp.Attributes, baseTp.Region) { - this.baseTp = baseTP; + this.baseTp = baseTp; this.substitution = substitution; - - this.Variance = baseTP.Variance; - this.Region = baseTP.Region; - this.Attributes.AddRange(baseTP.Attributes); - Freeze(); } - public override bool? IsReferenceType(ITypeResolveContext context) + public override int GetHashCode() { - bool? result = baseTp.IsReferenceType(context); - if (result != null) - return result; - IType effectiveBaseClass = baseTp.GetEffectiveBaseClass(context); - return IsReferenceTypeHelper(effectiveBaseClass); + return baseTp.GetHashCode() ^ this.Owner.GetHashCode(); } - public override IEnumerable GetEffectiveInterfaceSet(ITypeResolveContext context) + public override bool Equals(IType other) { - return baseTp.GetEffectiveInterfaceSet(context).Select(i => i.AcceptVisitor(substitution)); + SpecializedTypeParameter o = other as SpecializedTypeParameter; + return o != null && baseTp.Equals(o.baseTp) && this.Owner.Equals(o.Owner); } - public override IType GetEffectiveBaseClass(ITypeResolveContext context) - { - return baseTp.GetEffectiveBaseClass(context).AcceptVisitor(substitution); + public override bool HasValueTypeConstraint { + get { return baseTp.HasValueTypeConstraint; } } - public override ITypeParameterConstraints GetConstraints(ITypeResolveContext context) - { - return baseTp.GetConstraints(context).ApplySubstitution(substitution); + public override bool HasReferenceTypeConstraint { + get { return baseTp.HasReferenceTypeConstraint; } + } + + public override bool HasDefaultConstructorConstraint { + get { return baseTp.HasDefaultConstructorConstraint; } + } + + public override IEnumerable DirectBaseTypes { + get { + return baseTp.DirectBaseTypes.Select(t => t.AcceptVisitor(substitution)); + } } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs index 92f6eae2b5..84232c45ae 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs @@ -31,14 +31,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation : base(declaringType, propertyDefinition) { this.propertyDefinition = propertyDefinition; - Initialize(GetSubstitution(declaringType), null); + Initialize(GetSubstitution(declaringType)); } - internal SpecializedProperty(IType declaringType, IProperty propertyDefinition, TypeVisitor substitution, ITypeResolveContext context) + internal SpecializedProperty(IType declaringType, IProperty propertyDefinition, TypeVisitor substitution) : base(declaringType, propertyDefinition) { this.propertyDefinition = propertyDefinition; - Initialize(substitution, context); + Initialize(substitution); } public bool CanGet { diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SubstitutionTypeReference.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SubstitutionTypeReference.cs deleted file mode 100644 index 26579a06a2..0000000000 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SubstitutionTypeReference.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER 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; - -namespace ICSharpCode.NRefactory.TypeSystem.Implementation -{ - /// - /// A type reference that wraps another type reference; but performs a substitution in the resolved type. - /// - public class SubstitutionTypeReference : ITypeReference - { - readonly ITypeReference baseTypeReference; - readonly TypeVisitor substitution; - - public SubstitutionTypeReference(ITypeReference baseTypeReference, TypeVisitor substitution) - { - if (baseTypeReference == null) - throw new ArgumentNullException("baseTypeReference"); - if (substitution == null) - throw new ArgumentNullException("substitution"); - this.baseTypeReference = baseTypeReference; - this.substitution = substitution; - } - - public static ITypeReference Create(ITypeReference baseTypeReference, TypeVisitor substitution) - { - IType baseType = baseTypeReference as IType; - if (baseType != null && substitution != null) { - return baseType.AcceptVisitor(substitution); - } else { - return new SubstitutionTypeReference(baseTypeReference, substitution); - } - } - - public IType Resolve(ITypeResolveContext context) - { - return baseTypeReference.Resolve(context).AcceptVisitor(substitution); - } - - public override string ToString() - { - return "[SubstitutionTypeReference " + baseTypeReference + " " + substitution + "]"; - } - } -} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultExplicitInterfaceImplementation.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterReference.cs similarity index 58% rename from ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultExplicitInterfaceImplementation.cs rename to ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterReference.cs index aa857f000f..123f56e00f 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultExplicitInterfaceImplementation.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterReference.cs @@ -20,45 +20,47 @@ using System; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { - /// - /// Default implementation for IExplicitInterfaceImplementation. - /// [Serializable] - public sealed class DefaultExplicitInterfaceImplementation : Immutable, IExplicitInterfaceImplementation, ISupportsInterning + public sealed class TypeParameterReference : ITypeReference, ISupportsInterning { - public ITypeReference InterfaceType { get; private set; } - public string MemberName { get; private set; } + readonly EntityType ownerType; + readonly int index; - public DefaultExplicitInterfaceImplementation(ITypeReference interfaceType, string memberName) + public TypeParameterReference(EntityType ownerType, int index) { - if (interfaceType == null) - throw new ArgumentNullException("interfaceType"); - if (memberName == null) - throw new ArgumentNullException("memberName"); - this.InterfaceType = interfaceType; - this.MemberName = memberName; + this.ownerType = ownerType; + this.index = index; } - public override string ToString() + public IType Resolve(ITypeResolveContext context) { - return InterfaceType + "." + MemberName; + if (ownerType == EntityType.Method) { + IMethod method = context.CurrentMember as IMethod; + if (method != null && index < method.TypeParameters.Count) { + return method.TypeParameters[index]; + } + } else if (ownerType == EntityType.TypeDefinition) { + ITypeDefinition typeDef = context.CurrentTypeDefinition; + if (typeDef != null && index < typeDef.TypeParameters.Count) { + return typeDef.TypeParameters[index]; + } + } + return SpecialType.UnknownType; } void ISupportsInterning.PrepareForInterning(IInterningProvider provider) { - InterfaceType = provider.Intern(InterfaceType); - MemberName = provider.Intern(MemberName); } int ISupportsInterning.GetHashCodeForInterning() { - return InterfaceType.GetHashCode() ^ MemberName.GetHashCode(); + return index * 33 + (int)ownerType; } bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { - DefaultExplicitInterfaceImplementation o = other as DefaultExplicitInterfaceImplementation; - return InterfaceType == o.InterfaceType && MemberName == o.MemberName; + TypeParameterReference r = other as TypeParameterReference; + return r != null && index == r.index && ownerType == r.ownerType; } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterSubstitution.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterSubstitution.cs index cacfadd857..925e9e2d64 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterSubstitution.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterSubstitution.cs @@ -54,12 +54,12 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation if (index >= 0 && index < classTypeArguments.Count) return classTypeArguments[index]; else - return SharedTypes.UnknownType; + return SpecialType.UnknownType; } else if (methodTypeArguments != null && type.OwnerType == EntityType.Method) { if (index >= 0 && index < methodTypeArguments.Count) return methodTypeArguments[index]; else - return SharedTypes.UnknownType; + return SpecialType.UnknownType; } else { return base.VisitTypeParameter(type); } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterWithInheritedConstraints.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterWithInheritedConstraints.cs deleted file mode 100644 index 9b1adf2d10..0000000000 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterWithInheritedConstraints.cs +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; -using System.Linq; - -namespace ICSharpCode.NRefactory.TypeSystem.Implementation -{ - /// - /// Represents a type parameter that inherits its constraints from the overridden method in the base class. - /// - [Serializable] - public sealed class TypeParameterWithInheritedConstraints : AbstractTypeParameter - { - readonly IMethod parentMethod; - - public TypeParameterWithInheritedConstraints(IMethod parentMethod, int index, string name) - : base(EntityType.Method, index, name) - { - if (parentMethod == null) - throw new ArgumentNullException("parentMethod"); - this.parentMethod = parentMethod; - } - - ITypeParameter ResolveBaseTypeParameter(ITypeResolveContext context) - { - IMethod baseMethod = null; - if (parentMethod.IsOverride) { - foreach (IMethod m in InheritanceHelper.GetBaseMembers(parentMethod, context, false).OfType()) { - if (!m.IsOverride) { - baseMethod = m; - break; - } - } - } else if (parentMethod.InterfaceImplementations.Count == 1) { - IType interfaceType = parentMethod.InterfaceImplementations[0].InterfaceType.Resolve(context); - baseMethod = InheritanceHelper.GetMatchingMethodInBaseType(parentMethod, interfaceType, context); - } - if (baseMethod != null && this.Index < baseMethod.TypeParameters.Count) - return baseMethod.TypeParameters[this.Index]; - else - return null; - } - - public override bool? IsReferenceType(ITypeResolveContext context) - { - ITypeParameter baseTp = ResolveBaseTypeParameter(context); - if (baseTp == null) - return null; - bool? result = baseTp.IsReferenceType(context); - if (result != null) - return result; - IType effectiveBaseClass = baseTp.GetEffectiveBaseClass(context); - return IsReferenceTypeHelper(effectiveBaseClass); - } - - public override IEnumerable GetEffectiveInterfaceSet(ITypeResolveContext context) - { - ITypeParameter baseTp = ResolveBaseTypeParameter(context); - if (baseTp == null) - return EmptyList.Instance; - else - return baseTp.GetEffectiveInterfaceSet(context); - } - - public override IType GetEffectiveBaseClass(ITypeResolveContext context) - { - ITypeParameter baseTp = ResolveBaseTypeParameter(context); - if (baseTp == null) - return SharedTypes.UnknownType; - else - return baseTp.GetEffectiveBaseClass(context); - } - - public override ITypeParameterConstraints GetConstraints(ITypeResolveContext context) - { - ITypeParameter baseTp = ResolveBaseTypeParameter(context); - if (baseTp == null) - return DefaultTypeParameterConstraints.Empty; - else - return baseTp.GetConstraints(context); - } - } -} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs deleted file mode 100644 index e8c3ee98de..0000000000 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs +++ /dev/null @@ -1,404 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; -using System.Threading; -using ICSharpCode.NRefactory.Utils; - -namespace ICSharpCode.NRefactory.TypeSystem.Implementation -{ - /// - /// Stores a set of types and allows resolving them. - /// - /// - /// Concurrent read accesses are thread-safe, but a write access concurrent to any other access is not safe. - /// - [Serializable] - public sealed class TypeStorage : ITypeResolveContext, ISerializable, IDeserializationCallback - { - #region FullNameAndTypeParameterCount - struct FullNameAndTypeParameterCount - { - public readonly string Namespace; - public readonly string Name; - public readonly int TypeParameterCount; - - public FullNameAndTypeParameterCount(string nameSpace, string name, int typeParameterCount) - { - this.Namespace = nameSpace; - this.Name = name; - this.TypeParameterCount = typeParameterCount; - } - } - - sealed class FullNameAndTypeParameterCountComparer : IEqualityComparer - { - public static readonly FullNameAndTypeParameterCountComparer Ordinal = new FullNameAndTypeParameterCountComparer(StringComparer.Ordinal); - - public readonly StringComparer NameComparer; - - public FullNameAndTypeParameterCountComparer(StringComparer nameComparer) - { - this.NameComparer = nameComparer; - } - - public bool Equals(FullNameAndTypeParameterCount x, FullNameAndTypeParameterCount y) - { - return x.TypeParameterCount == y.TypeParameterCount - && NameComparer.Equals(x.Name, y.Name) - && NameComparer.Equals(x.Namespace, y.Namespace); - } - - public int GetHashCode(FullNameAndTypeParameterCount obj) - { - return NameComparer.GetHashCode(obj.Name) ^ NameComparer.GetHashCode(obj.Namespace) ^ obj.TypeParameterCount; - } - } - #endregion - - #region Type Dictionary Storage - volatile Dictionary[] _typeDicts = { - new Dictionary(FullNameAndTypeParameterCountComparer.Ordinal) - }; - readonly object dictsLock = new object(); - - Dictionary GetTypeDictionary(StringComparer nameComparer) - { - // Gets the dictionary for the specified comparer, creating it if necessary. - // New dictionaries might be added during read accesses, so this method needs to be thread-safe, - // as we allow concurrent read-accesses. - var typeDicts = this._typeDicts; - foreach (var dict in typeDicts) { - FullNameAndTypeParameterCountComparer comparer = (FullNameAndTypeParameterCountComparer)dict.Comparer; - if (comparer.NameComparer == nameComparer) - return dict; - } - - // ensure that no other thread can try to lazy-create this (or another) dict - lock (dictsLock) { - typeDicts = this._typeDicts; // fetch fresh value after locking - // try looking for it again, maybe it was added while we were waiting for a lock - // (double-checked locking pattern) - foreach (var dict in typeDicts) { - FullNameAndTypeParameterCountComparer comparer = (FullNameAndTypeParameterCountComparer)dict.Comparer; - if (comparer.NameComparer == nameComparer) - return dict; - } - - // now create new dict - var oldDict = typeDicts[0]; // Ordinal dict - var newDict = new Dictionary( - oldDict.Count, - new FullNameAndTypeParameterCountComparer(nameComparer)); - foreach (var pair in oldDict) { - // don't use Add() as there might be conflicts in the target language - newDict[pair.Key] = pair.Value; - } - - // add the new dict to the array of dicts - var newTypeDicts = new Dictionary[typeDicts.Length + 1]; - Array.Copy(typeDicts, 0, newTypeDicts, 0, typeDicts.Length); - newTypeDicts[typeDicts.Length] = newDict; - this._typeDicts = newTypeDicts; - return newDict; - } - } - #endregion - - #region Namespace Storage - class NamespaceEntry - { - /// - /// Full namespace name - /// - public readonly string Name; - - /// - /// Parent namespace - /// - public readonly NamespaceEntry Parent; - - /// - /// Number of classes in this namespace (not in sub-namespaces). - /// Note: this always refers to the number of classes from the ordinal typeDict that map - /// to this namespace when compared with the appropriate StringComparer. - /// The actual number of classes in the typeDict matching this StringComparer might be lower. - /// - public int ClassCount; - - /// - /// Number of sub-namespaces. - /// - public int SubNamespaceCount; - - public NamespaceEntry(NamespaceEntry parent, string name) - { - this.Parent = parent; - this.Name = name; - } - } - - volatile Dictionary[] _namespaceDicts = { - new Dictionary(StringComparer.Ordinal) - }; - - Dictionary GetNamespaceDictionary(StringComparer nameComparer) - { - // Gets the dictionary for the specified comparer, creating it if necessary. - // New dictionaries might be added during read accesses, so this method needs to be thread-safe, - // as we allow concurrent read-accesses. - var namespaceDicts = this._namespaceDicts; - foreach (var dict in namespaceDicts) { - if (dict.Comparer == nameComparer) - return dict; - } - - // ensure that no other thread can try to lazy-create this (or another) dict - lock (dictsLock) { - namespaceDicts = this._namespaceDicts; // fetch fresh value after locking - // try looking for it again, maybe it was added while we were waiting for a lock - // (double-checked locking pattern) - foreach (var dict in namespaceDicts) { - if (dict.Comparer == nameComparer) - return dict; - } - - // now create new dict - var newDict = new Dictionary(nameComparer); - foreach (ITypeDefinition type in _typeDicts[0].Values) { - NamespaceEntry ne = GetOrCreateNamespaceEntry(newDict, type.Namespace); - ne.ClassCount++; - } - - // add the new dict to the array of dicts - var newNamespaceDicts = new Dictionary[namespaceDicts.Length + 1]; - Array.Copy(namespaceDicts, 0, newNamespaceDicts, 0, namespaceDicts.Length); - newNamespaceDicts[namespaceDicts.Length] = newDict; - this._namespaceDicts = newNamespaceDicts; - return newDict; - } - } - - NamespaceEntry GetOrCreateNamespaceEntry(Dictionary dict, string ns) - { - NamespaceEntry ne; - if (!dict.TryGetValue(ns, out ne)) { - NamespaceEntry parentEntry; - if (string.IsNullOrEmpty(ns)) { - parentEntry = null; - } else { - int pos = ns.LastIndexOf('.'); - string parentNS = pos < 0 ? string.Empty : ns.Substring(0, pos); - parentEntry = GetOrCreateNamespaceEntry(dict, parentNS); - parentEntry.SubNamespaceCount++; - } - ne = new NamespaceEntry(parentEntry, ns); - dict.Add(ns, ne); - } - return ne; - } - #endregion - - #region ITypeResolveContext implementation - /// - public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) - { - if (nameSpace == null) - throw new ArgumentNullException("nameSpace"); - if (name == null) - throw new ArgumentNullException("name"); - if (nameComparer == null) - throw new ArgumentNullException("nameComparer"); - - var key = new FullNameAndTypeParameterCount(nameSpace, name, typeParameterCount); - ITypeDefinition result; - if (GetTypeDictionary(nameComparer).TryGetValue(key, out result)) - return result; - else - return null; - } - - /// - public ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode) - { - return GetTypeDefinition("System", ReflectionHelper.GetShortNameByTypeCode(typeCode), 0, StringComparer.Ordinal); - } - - /// - public IEnumerable GetTypes() - { - return _typeDicts[0].Values; - } - - /// - public IEnumerable GetTypes(string nameSpace, StringComparer nameComparer) - { - if (nameSpace == null) - throw new ArgumentNullException("nameSpace"); - if (nameComparer == null) - throw new ArgumentNullException("nameComparer"); - return GetTypes().Where(c => nameComparer.Equals(nameSpace, c.Namespace)); - } - - /// - public IEnumerable GetNamespaces() - { - return _namespaceDicts[0].Keys; - } - - /// - public string GetNamespace(string nameSpace, StringComparer nameComparer) - { - if (nameSpace == null) - throw new ArgumentNullException("nameSpace"); - if (nameComparer == null) - throw new ArgumentNullException("nameComparer"); - NamespaceEntry result; - if (GetNamespaceDictionary(nameComparer).TryGetValue(nameSpace, out result)) - return result.Name; - else - return null; - } - #endregion - - #region Synchronize - /// - /// TypeStorage is mutable and does not provide any means for synchronization, so this method - /// always throws a . - /// - public ISynchronizedTypeResolveContext Synchronize() - { - throw new NotSupportedException(); - } - - /// - public CacheManager CacheManager { - // TypeStorage is mutable, so caching is a bad idea. - // We could provide a CacheToken if we update it on every modication, but - // that's not worth the effort as TypeStorage is rarely directly used in resolve operations. - get { return null; } - } - #endregion - - #region RemoveType - /// - /// Removes a type definition from this project content. - /// - public bool RemoveType(ITypeDefinition typeDefinition) - { - if (typeDefinition == null) - throw new ArgumentNullException("typeDefinition"); - var key = new FullNameAndTypeParameterCount(typeDefinition.Namespace, typeDefinition.Name, typeDefinition.TypeParameterCount); - bool wasRemoved = false; - foreach (var dict in _typeDicts) { - ITypeDefinition defInDict; - if (dict.TryGetValue(key, out defInDict)) { - if (defInDict == typeDefinition) { - if (dict.Comparer == FullNameAndTypeParameterCountComparer.Ordinal) { - // Set wasRemoved flag only on removal in the ordinal comparison. - // This keeps the ClassCount consistent when there are name clashes. - wasRemoved = true; - } - dict.Remove(key); - } - } - } - if (wasRemoved) { - foreach (var dict in _namespaceDicts) { - NamespaceEntry ns; - if (dict.TryGetValue(typeDefinition.Namespace, out ns)) { - ns.ClassCount--; - RemoveNamespaceIfPossible(dict, ns); - } - } - } - return wasRemoved; - } - - void RemoveNamespaceIfPossible(Dictionary dict, NamespaceEntry ns) - { - while (ns.ClassCount == 0 && ns.SubNamespaceCount == 0) { - dict.Remove(ns.Name); - ns = ns.Parent; - if (ns == null) - break; - ns.SubNamespaceCount--; - } - } - #endregion - - #region UpdateType - /// - /// Adds the type definition to this project content. - /// Replaces existing type definitions with the same name. - /// - public void UpdateType(ITypeDefinition typeDefinition) - { - if (typeDefinition == null) - throw new ArgumentNullException("typeDefinition"); - var key = new FullNameAndTypeParameterCount(typeDefinition.Namespace, typeDefinition.Name, typeDefinition.TypeParameterCount); - // Set isNew on addition in the ordinal comparison. - // This keeps the ClassCount consistent when there are name clashes. - bool isNew = !_typeDicts[0].ContainsKey(key); - foreach (var dict in _typeDicts) { - dict[key] = typeDefinition; - } - if (isNew) { - foreach (var dict in _namespaceDicts) { - NamespaceEntry ns = GetOrCreateNamespaceEntry(dict, typeDefinition.Namespace); - ++ns.ClassCount; - } - } - } - #endregion - - #region Serialization - /// - /// Creates a new TypeStorage instance. - /// - public TypeStorage() - { - } - - SerializationInfo serializationInfo; - - private TypeStorage(SerializationInfo info, StreamingContext context) - { - this.serializationInfo = info; - } - - void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) - { - info.AddValue("Types", this.GetTypes().ToArray()); - } - - void IDeserializationCallback.OnDeserialization(object sender) - { - if (serializationInfo == null) - return; - foreach (var typeDef in (ITypeDefinition[])serializationInfo.GetValue("Types", typeof(ITypeDefinition[]))) { - UpdateType(typeDef); - } - serializationInfo = null; - } - #endregion - } -} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeWithElementType.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeWithElementType.cs index 0aa6d5cf69..6df0d99c69 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeWithElementType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeWithElementType.cs @@ -20,7 +20,6 @@ using System; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { - [Serializable] public abstract class TypeWithElementType : AbstractType { [CLSCompliant(false)] diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/VoidTypeDefinition.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/VoidTypeDefinition.cs deleted file mode 100644 index c8b2d8832f..0000000000 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/VoidTypeDefinition.cs +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; - -namespace ICSharpCode.NRefactory.TypeSystem.Implementation -{ - /// - /// Special type definition for 'void'. - /// - [Serializable] - public class VoidTypeDefinition : DefaultTypeDefinition - { - public VoidTypeDefinition(IProjectContent projectContent) - : base(projectContent, "System", "Void") - { - this.Kind = TypeKind.Void; - this.Accessibility = Accessibility.Public; - this.IsSealed = true; - } - - public override IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter, GetMemberOptions options) - { - return EmptyList.Instance; - } - - public override IEnumerable GetEvents(ITypeResolveContext context, Predicate filter, GetMemberOptions options) - { - return EmptyList.Instance; - } - - public override IEnumerable GetFields(ITypeResolveContext context, Predicate filter, GetMemberOptions options) - { - return EmptyList.Instance; - } - - public override IEnumerable GetMethods(ITypeResolveContext context, Predicate filter, GetMemberOptions options) - { - return EmptyList.Instance; - } - - public override IEnumerable GetMethods(IList typeArguments, ITypeResolveContext context, Predicate filter, GetMemberOptions options) - { - return EmptyList.Instance; - } - - public override IEnumerable GetProperties(ITypeResolveContext context, Predicate filter, GetMemberOptions options) - { - return EmptyList.Instance; - } - - public override IEnumerable GetMembers(ITypeResolveContext context, Predicate filter, GetMemberOptions options) - { - return EmptyList.Instance; - } - } -} diff --git a/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs b/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs index 5a15186c6e..6284d3222f 100644 --- a/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs +++ b/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs @@ -28,14 +28,15 @@ namespace ICSharpCode.NRefactory.TypeSystem public class InheritanceHelper { // TODO: maybe these should be extension methods? + // or even part of the interface itself? (would allow for easy caching) #region GetBaseMember /// /// Gets the base member that has the same signature. /// - public static IMember GetBaseMember(IMember member, ITypeResolveContext context) + public static IMember GetBaseMember(IMember member) { - return GetBaseMembers(member, context, false).FirstOrDefault(); + return GetBaseMembers(member, false).FirstOrDefault(); } /// @@ -44,67 +45,28 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// List of base members with the same signature. The member from the derived-most base class is returned first. /// - public static IEnumerable GetBaseMembers(IMember member, ITypeResolveContext context, bool includeImplementedInterfaces) + public static IEnumerable GetBaseMembers(IMember member, bool includeImplementedInterfaces) { if (member == null) throw new ArgumentNullException("member"); - if (context == null) - throw new ArgumentNullException("context"); + member = member.MemberDefinition; - IMethod method = member as IMethod; - IProperty property = member as IProperty; - IEvent ev = member as IEvent; - IField field = member as IField; - using (var ctx = context.Synchronize()) { - IEnumerable allBaseTypes; - if (includeImplementedInterfaces) { - allBaseTypes = member.DeclaringTypeDefinition.GetAllBaseTypes(ctx); - } else { - allBaseTypes = member.DeclaringTypeDefinition.GetNonInterfaceBaseTypes(ctx); - } - foreach (IType baseType in allBaseTypes.Reverse()) { - if (baseType == member.DeclaringTypeDefinition) - continue; - - if (method != null) { - IMethod baseMethod = GetMatchingMethodInBaseType(method, baseType, ctx); - if (baseMethod != null) - yield return baseMethod; - } - if (property != null) { - foreach (IProperty baseProperty in baseType.GetProperties( - ctx, p => p.Name == property.Name && p.Parameters.Count == property.Parameters.Count, - GetMemberOptions.IgnoreInheritedMembers)) - { - if (ParameterListComparer.Compare(ctx, property, baseProperty)) - yield return baseProperty; - } - } - if (ev != null) { - IEvent baseEvent = baseType.GetEvents(ctx, e => e.Name == ev.Name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault(); - if (baseEvent != null) - yield return baseEvent; - } - // Fields can't be overridden, but we handle them anyways, just for consistence - if (field != null) { - IField baseField = baseType.GetFields(ctx, f => f.Name == field.Name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault(); - if (baseField != null) - yield return baseField; - } - } + + IEnumerable allBaseTypes; + if (includeImplementedInterfaces) { + allBaseTypes = member.DeclaringTypeDefinition.GetAllBaseTypes(); + } else { + allBaseTypes = member.DeclaringTypeDefinition.GetNonInterfaceBaseTypes(); } - } - - internal static IMethod GetMatchingMethodInBaseType(IMethod method, IType baseType, ITypeResolveContext context) - { - foreach (IMethod baseMethod in baseType.GetMethods( - context, m => m.Name == method.Name && m.Parameters.Count == method.Parameters.Count && m.TypeParameters.Count == method.TypeParameters.Count, - GetMemberOptions.IgnoreInheritedMembers)) - { - if (ParameterListComparer.Compare(context, method, baseMethod)) - return baseMethod; + foreach (IType baseType in allBaseTypes.Reverse()) { + if (baseType == member.DeclaringTypeDefinition) + continue; + + foreach (IMember baseMember in baseType.GetMembers(m => m.Name == member.Name, GetMemberOptions.IgnoreInheritedMembers)) { + if (SignatureComparer.Ordinal.Equals(member, baseMember)) + yield return baseMember; + } } - return null; } #endregion @@ -112,39 +74,34 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Finds the member declared in 'derivedType' that has the same signature (could override) 'baseMember'. /// - public static IMember GetDerivedMember(IMember baseMember, ITypeDefinition derivedType, ITypeResolveContext context) + public static IMember GetDerivedMember(IMember baseMember, ITypeDefinition derivedType) { if (baseMember == null) throw new ArgumentNullException("baseMember"); if (derivedType == null) throw new ArgumentNullException("derivedType"); - if (context == null) - throw new ArgumentNullException("context"); + baseMember = baseMember.MemberDefinition; bool includeInterfaces = baseMember.DeclaringTypeDefinition.Kind == TypeKind.Interface; IMethod method = baseMember as IMethod; if (method != null) { - using (var ctx = context.Synchronize()) { - foreach (IMethod derivedMethod in derivedType.Methods) { - if (derivedMethod.Name == method.Name && derivedMethod.Parameters.Count == method.Parameters.Count) { - if (derivedMethod.TypeParameters.Count == method.TypeParameters.Count) { - // The method could override the base method: - if (GetBaseMembers(derivedMethod, ctx, includeInterfaces).Any(m => m.MemberDefinition == baseMember)) - return derivedMethod; - } + foreach (IMethod derivedMethod in derivedType.Methods) { + if (derivedMethod.Name == method.Name && derivedMethod.Parameters.Count == method.Parameters.Count) { + if (derivedMethod.TypeParameters.Count == method.TypeParameters.Count) { + // The method could override the base method: + if (GetBaseMembers(derivedMethod, includeInterfaces).Any(m => m.MemberDefinition == baseMember)) + return derivedMethod; } } } } IProperty property = baseMember as IProperty; if (property != null) { - using (var ctx = context.Synchronize()) { - foreach (IProperty derivedProperty in derivedType.Properties) { - if (derivedProperty.Name == property.Name && derivedProperty.Parameters.Count == property.Parameters.Count) { - // The property could override the base property: - if (GetBaseMembers(derivedProperty, ctx, includeInterfaces).Any(m => m.MemberDefinition == baseMember)) - return derivedProperty; - } + foreach (IProperty derivedProperty in derivedType.Properties) { + if (derivedProperty.Name == property.Name && derivedProperty.Parameters.Count == property.Parameters.Count) { + // The property could override the base property: + if (GetBaseMembers(derivedProperty, includeInterfaces).Any(m => m.MemberDefinition == baseMember)) + return derivedProperty; } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs b/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs index 2e5bf8849a..4c537d2b56 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs @@ -30,7 +30,6 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Represents the intersection of several types. /// - [Serializable] public class IntersectionType : AbstractType { readonly ReadOnlyCollection types; @@ -47,9 +46,13 @@ namespace ICSharpCode.NRefactory.TypeSystem public static IType Create(IEnumerable types) { - IType[] arr = types.Where(t => t != null).Distinct().ToArray(); + IType[] arr = types.Distinct().ToArray(); + foreach (IType type in arr) { + if (type == null) + throw new ArgumentNullException(); + } if (arr.Length == 0) - return SharedTypes.UnknownType; + return SpecialType.UnknownType; else if (arr.Length == 1) return arr[0]; else @@ -57,8 +60,8 @@ namespace ICSharpCode.NRefactory.TypeSystem } public override TypeKind Kind { - get { return TypeKind.Intersection; } - } + get { return TypeKind.Intersection; } + } public override string Name { get { @@ -84,14 +87,15 @@ namespace ICSharpCode.NRefactory.TypeSystem } } - public override bool? IsReferenceType(ITypeResolveContext context) - { - foreach (var t in types) { - bool? isReferenceType = t.IsReferenceType(context); - if (isReferenceType.HasValue) - return isReferenceType.Value; + public override bool? IsReferenceType { + get { + foreach (var t in types) { + bool? isReferenceType = t.IsReferenceType; + if (isReferenceType.HasValue) + return isReferenceType.Value; + } + return null; } - return null; } public override int GetHashCode() @@ -119,39 +123,43 @@ namespace ICSharpCode.NRefactory.TypeSystem return false; } - public override IEnumerable GetBaseTypes(ITypeResolveContext context) + public override IEnumerable DirectBaseTypes { + get { return types; } + } + + public override ITypeReference ToTypeReference() { - return types; + throw new NotImplementedException(); } - public override IEnumerable GetMethods(ITypeResolveContext context, Predicate filter, GetMemberOptions options) + public override IEnumerable GetMethods(Predicate filter, GetMemberOptions options) { - return GetMembersHelper.GetMethods(this, context, FilterNonStatic(filter), options); + return GetMembersHelper.GetMethods(this, FilterNonStatic(filter), options); } - public override IEnumerable GetMethods(IList typeArguments, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + public override IEnumerable GetMethods(IList typeArguments, Predicate filter, GetMemberOptions options) { - return GetMembersHelper.GetMethods(this, typeArguments, context, filter, options); + return GetMembersHelper.GetMethods(this, typeArguments, filter, options); } - public override IEnumerable GetProperties(ITypeResolveContext context, Predicate filter, GetMemberOptions options) + public override IEnumerable GetProperties(Predicate filter, GetMemberOptions options) { - return GetMembersHelper.GetProperties(this, context, FilterNonStatic(filter), options); + return GetMembersHelper.GetProperties(this, FilterNonStatic(filter), options); } - public override IEnumerable GetFields(ITypeResolveContext context, Predicate filter, GetMemberOptions options) + public override IEnumerable GetFields(Predicate filter, GetMemberOptions options) { - return GetMembersHelper.GetFields(this, context, FilterNonStatic(filter), options); + return GetMembersHelper.GetFields(this, FilterNonStatic(filter), options); } - public override IEnumerable GetEvents(ITypeResolveContext context, Predicate filter, GetMemberOptions options) + public override IEnumerable GetEvents(Predicate filter, GetMemberOptions options) { - return GetMembersHelper.GetEvents(this, context, FilterNonStatic(filter), options); + return GetMembersHelper.GetEvents(this, FilterNonStatic(filter), options); } - public override IEnumerable GetMembers(ITypeResolveContext context, Predicate filter, GetMemberOptions options) + public override IEnumerable GetMembers(Predicate filter, GetMemberOptions options) { - return GetMembersHelper.GetMembers(this, context, FilterNonStatic(filter), options); + return GetMembersHelper.GetMembers(this, FilterNonStatic(filter), options); } static Predicate FilterNonStatic(Predicate filter) where T : class, IMember diff --git a/ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs b/ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs index 938759a002..d93511c6fe 100644 --- a/ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs @@ -22,138 +22,424 @@ using ICSharpCode.NRefactory.TypeSystem.Implementation; namespace ICSharpCode.NRefactory.TypeSystem { + /// + /// Represents some well-known types. + /// + public enum KnownTypeCode + { + // The order of type codes at the beginning must correspond to those in System.TypeCode. + + /// + /// Not one of the known types. + /// + None, + /// object (System.Object) + Object, + /// System.DBNull + DBNull, + /// bool (System.Boolean) + Boolean, + /// char (System.Char) + Char, + /// sbyte (System.SByte) + SByte, + /// byte (System.Byte) + Byte, + /// short (System.Int16) + Int16, + /// ushort (System.UInt16) + UInt16, + /// int (System.Int32) + Int32, + /// uint (System.UInt32) + UInt32, + /// long (System.Int64) + Int64, + /// ulong (System.UInt64) + UInt64, + /// float (System.Single) + Single, + /// double (System.Double) + Double, + /// decimal (System.Decimal) + Decimal, + /// System.DateTime + DateTime, + /// string (System.String) + String = 18, + + // String was the last element from System.TypeCode, now our additional known types start + + /// void (System.Void) + Void, + /// System.Type + Type, + /// System.Array + Array, + /// System.Attribute + Attribute, + /// System.ValueType + ValueType, + /// System.Enum + Enum, + /// System.Delegate + Delegate, + /// System.MulticastDelegate + MulticastDelegate, + /// System.Exception + Exception, + /// System.IntPtr + IntPtr, + /// System.UIntPtr + UIntPtr, + /// System.Collections.IEnumerable + IEnumerable, + /// System.Collections.IEnumerator + IEnumerator, + /// System.Collections.Generic.IEnumerable{T} + IEnumerableOfT, + /// System.Collections.Generic.IEnumerator{T} + IEnumeratorOfT, + /// System.Collections.Generic.IList{T} + IListOfT, + /// System.Threading.Tasks.Task + Task, + /// System.Threading.Tasks.Task{T} + TaskOfT, + /// System.Nullable{T} + NullableOfT, + /// System.IDisposable + IDisposable + } + /// /// Contains well-known type references. /// [Serializable] public sealed class KnownTypeReference : ITypeReference { + static readonly KnownTypeReference[] knownTypeReferences = { + null, // None + new KnownTypeReference(KnownTypeCode.Object, "System", "Object"), + new KnownTypeReference(KnownTypeCode.DBNull, "System", "DBNull"), + new KnownTypeReference(KnownTypeCode.Boolean, "System", "Boolean"), + new KnownTypeReference(KnownTypeCode.Char, "System", "Char"), + new KnownTypeReference(KnownTypeCode.SByte, "System", "SByte"), + new KnownTypeReference(KnownTypeCode.Byte, "System", "Byte"), + new KnownTypeReference(KnownTypeCode.Int16, "System", "Int16"), + new KnownTypeReference(KnownTypeCode.UInt16, "System", "UInt16"), + new KnownTypeReference(KnownTypeCode.Int32, "System", "Int32"), + new KnownTypeReference(KnownTypeCode.UInt32, "System", "UInt32"), + new KnownTypeReference(KnownTypeCode.Int64, "System", "Int64"), + new KnownTypeReference(KnownTypeCode.UInt64, "System", "UInt64"), + new KnownTypeReference(KnownTypeCode.Single, "System", "Single"), + new KnownTypeReference(KnownTypeCode.Double, "System", "Double"), + new KnownTypeReference(KnownTypeCode.Decimal, "System", "Decimal"), + new KnownTypeReference(KnownTypeCode.DateTime, "System", "DateTime"), + null, + new KnownTypeReference(KnownTypeCode.String, "System", "String"), + new KnownTypeReference(KnownTypeCode.Void, "System", "Void"), + new KnownTypeReference(KnownTypeCode.Type, "System", "Type"), + new KnownTypeReference(KnownTypeCode.Array, "System", "Array"), + new KnownTypeReference(KnownTypeCode.Attribute, "System", "Attribute"), + new KnownTypeReference(KnownTypeCode.ValueType, "System", "ValueType"), + new KnownTypeReference(KnownTypeCode.Enum, "System", "Enum"), + new KnownTypeReference(KnownTypeCode.Delegate, "System", "Delegate"), + new KnownTypeReference(KnownTypeCode.MulticastDelegate, "System", "MulticastDelegate"), + new KnownTypeReference(KnownTypeCode.Exception, "System", "Exception"), + new KnownTypeReference(KnownTypeCode.IntPtr, "System", "IntPtr"), + new KnownTypeReference(KnownTypeCode.UIntPtr, "System", "UIntPtr"), + new KnownTypeReference(KnownTypeCode.IEnumerable, "System.Collections", "IEnumerable"), + new KnownTypeReference(KnownTypeCode.IEnumerator, "System.Collections", "IEnumerator"), + new KnownTypeReference(KnownTypeCode.IEnumerableOfT, "System.Collections.Generic", "IEnumerable", 1), + new KnownTypeReference(KnownTypeCode.IEnumeratorOfT, "System.Collections.Generic", "IEnumerator", 1), + new KnownTypeReference(KnownTypeCode.IListOfT, "System.Collections.Generic", "IList", 1), + new KnownTypeReference(KnownTypeCode.Task, "System.Threading.Tasks", "Task"), + new KnownTypeReference(KnownTypeCode.TaskOfT, "System.Threading.Tasks", "Task", 1), + new KnownTypeReference(KnownTypeCode.NullableOfT, "System", "Nullable", 1), + new KnownTypeReference(KnownTypeCode.IDisposable, "System", "IDispoable"), + }; + /// - /// Gets a type reference pointing to the void type. + /// Gets the known type reference for the specified type code. + /// Returns null for KnownTypeCode.None. /// - public static readonly ITypeReference Void = new KnownTypeReference(TypeCode.Empty); + public static KnownTypeReference Get(KnownTypeCode typeCode) + { + return knownTypeReferences[(int)typeCode]; + } /// /// Gets a type reference pointing to the object type. /// - public static readonly ITypeReference Object = new KnownTypeReference(TypeCode.Object); + public static readonly KnownTypeReference Object = Get(KnownTypeCode.Object); + + /// + /// Gets a type reference pointing to the System.DBNull type. + /// + public static readonly KnownTypeReference DBNull = Get(KnownTypeCode.DBNull); /// /// Gets a type reference pointing to the bool type. /// - public static readonly ITypeReference Boolean = new KnownTypeReference(TypeCode.Boolean); + public static readonly KnownTypeReference Boolean = Get(KnownTypeCode.Boolean); /// /// Gets a type reference pointing to the char type. /// - public static readonly ITypeReference Char = new KnownTypeReference(TypeCode.Char); + public static readonly KnownTypeReference Char = Get(KnownTypeCode.Char); /// /// Gets a type reference pointing to the sbyte type. /// - public static readonly ITypeReference SByte = new KnownTypeReference(TypeCode.SByte); + public static readonly KnownTypeReference SByte = Get(KnownTypeCode.SByte); /// /// Gets a type reference pointing to the byte type. /// - public static readonly ITypeReference Byte = new KnownTypeReference(TypeCode.Byte); + public static readonly KnownTypeReference Byte = Get(KnownTypeCode.Byte); /// /// Gets a type reference pointing to the short type. /// - public static readonly ITypeReference Int16 = new KnownTypeReference(TypeCode.Int16); + public static readonly KnownTypeReference Int16 = Get(KnownTypeCode.Int16); /// /// Gets a type reference pointing to the ushort type. /// - public static readonly ITypeReference UInt16 = new KnownTypeReference(TypeCode.UInt16); + public static readonly KnownTypeReference UInt16 = Get(KnownTypeCode.UInt16); /// /// Gets a type reference pointing to the int type. /// - public static readonly ITypeReference Int32 = new KnownTypeReference(TypeCode.Int32); + public static readonly KnownTypeReference Int32 = Get(KnownTypeCode.Int32); /// /// Gets a type reference pointing to the uint type. /// - public static readonly ITypeReference UInt32 = new KnownTypeReference(TypeCode.UInt32); + public static readonly KnownTypeReference UInt32 = Get(KnownTypeCode.UInt32); /// /// Gets a type reference pointing to the long type. /// - public static readonly ITypeReference Int64 = new KnownTypeReference(TypeCode.Int64); + public static readonly KnownTypeReference Int64 = Get(KnownTypeCode.Int64); /// /// Gets a type reference pointing to the ulong type. /// - public static readonly ITypeReference UInt64 = new KnownTypeReference(TypeCode.UInt64); + public static readonly KnownTypeReference UInt64 = Get(KnownTypeCode.UInt64); /// /// Gets a type reference pointing to the float type. /// - public static readonly ITypeReference Single = new KnownTypeReference(TypeCode.Single); + public static readonly KnownTypeReference Single = Get(KnownTypeCode.Single); /// /// Gets a type reference pointing to the double type. /// - public static readonly ITypeReference Double = new KnownTypeReference(TypeCode.Double); + public static readonly KnownTypeReference Double = Get(KnownTypeCode.Double); /// /// Gets a type reference pointing to the decimal type. /// - public static readonly ITypeReference Decimal = new KnownTypeReference(TypeCode.Decimal); + public static readonly KnownTypeReference Decimal = Get(KnownTypeCode.Decimal); + + /// + /// Gets a type reference pointing to the System.DateTime type. + /// + public static readonly KnownTypeReference DateTime = Get(KnownTypeCode.DateTime); /// /// Gets a type reference pointing to the string type. /// - public static readonly ITypeReference String = new KnownTypeReference(TypeCode.String); + public static readonly KnownTypeReference String = Get(KnownTypeCode.String); + + /// + /// Gets a type reference pointing to the void type. + /// + public static readonly KnownTypeReference Void = Get(KnownTypeCode.Void); /// /// Gets a type reference pointing to the System.Type type. /// - public static readonly ITypeReference Type = new GetClassTypeReference("System", "Type", 0); + public static readonly KnownTypeReference Type = Get(KnownTypeCode.Type); /// - /// Gets all known type references. + /// Gets a type reference pointing to the System.Array type. /// - public static IEnumerable AllKnownTypeReferences { - get { - return new[] { - Void, Object, Boolean, - SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, - String, Char, Single, Double, Decimal, - Type - }; - } - } + public static readonly KnownTypeReference Array = Get(KnownTypeCode.Array); - readonly TypeCode typeCode; + /// + /// Gets a type reference pointing to the System.Attribute type. + /// + public static readonly KnownTypeReference Attribute = Get(KnownTypeCode.Attribute); - public TypeCode TypeCode { - get { return typeCode; } - } + /// + /// Gets a type reference pointing to the System.ValueType type. + /// + public static readonly KnownTypeReference ValueType = Get(KnownTypeCode.ValueType); + + /// + /// Gets a type reference pointing to the System.Enum type. + /// + public static readonly KnownTypeReference Enum = Get(KnownTypeCode.Enum); + + /// + /// Gets a type reference pointing to the System.Delegate type. + /// + public static readonly KnownTypeReference Delegate = Get(KnownTypeCode.Delegate); - public KnownTypeReference(TypeCode typeCode) + /// + /// Gets a type reference pointing to the System.MulticastDelegate type. + /// + public static readonly KnownTypeReference MulticastDelegate = Get(KnownTypeCode.MulticastDelegate); + + /// + /// Gets a type reference pointing to the System.Exception type. + /// + public static readonly KnownTypeReference Exception = Get(KnownTypeCode.Exception); + + /// + /// Gets a type reference pointing to the System.IntPtr type. + /// + public static readonly KnownTypeReference IntPtr = Get(KnownTypeCode.IntPtr); + + /// + /// Gets a type reference pointing to the System.UIntPtr type. + /// + public static readonly KnownTypeReference UIntPtr = Get(KnownTypeCode.UIntPtr); + + /// + /// Gets a type reference pointing to the System.Collections.Generic.IList{T} type. + /// + public static readonly KnownTypeReference GenericIList = Get(KnownTypeCode.IListOfT); + + /// + /// Gets a type reference pointing to the System.Nullable{T} type. + /// + public static readonly KnownTypeReference NullableOfT = Get(KnownTypeCode.NullableOfT); + + /// + /// Gets a type reference pointing to the System.Collections.IEnumerable type. + /// + public static readonly KnownTypeReference IEnumerable = Get(KnownTypeCode.IEnumerable); + + /// + /// Gets a type reference pointing to the System.Collections.IEnumerator type. + /// + public static readonly KnownTypeReference IEnumerator = Get(KnownTypeCode.IEnumerator); + + /// + /// Gets a type reference pointing to the System.Collections.Generic.IEnumerable{T} type. + /// + public static readonly KnownTypeReference IEnumerableOfT = Get(KnownTypeCode.IEnumerableOfT); + + /// + /// Gets a type reference pointing to the System.Collections.Generic.IEnumerator{T} type. + /// + public static readonly KnownTypeReference IEnumeratorOfT = Get(KnownTypeCode.IEnumeratorOfT); + + /// + /// Gets a type reference pointing to the System.Collections.Generic.IList{T} type. + /// + public static readonly KnownTypeReference IListOfT = Get(KnownTypeCode.IListOfT); + + /// + /// Gets a type reference pointing to the System.Threading.Tasks.Task type. + /// + public static readonly KnownTypeReference Task = Get(KnownTypeCode.Task); + + /// + /// Gets a type reference pointing to the System.Threading.Tasks.Task{T} type. + /// + public static readonly KnownTypeReference TaskOfT = Get(KnownTypeCode.TaskOfT); + + /// + /// Gets a type reference pointing to the System.IDisposable type. + /// + public static readonly KnownTypeReference IDisposable = Get(KnownTypeCode.IDisposable); + + readonly KnownTypeCode knownTypeCode; + readonly string namespaceName; + readonly string name; + readonly int typeParameterCount; + + private KnownTypeReference(KnownTypeCode knownTypeCode, string namespaceName, string name, int typeParameterCount = 0) { - this.typeCode = typeCode; + this.knownTypeCode = knownTypeCode; + this.namespaceName = namespaceName; + this.name = name; + this.typeParameterCount = typeParameterCount; } - public IType Resolve(ITypeResolveContext context) - { - return context.GetKnownTypeDefinition(typeCode) ?? SharedTypes.UnknownType; + public KnownTypeCode KnownTypeCode { + get { return knownTypeCode; } } public string Namespace { - get { return "System"; } + get { return namespaceName; } } public string Name { - get { return ReflectionHelper.GetShortNameByTypeCode(typeCode); } + get { return name; } + } + + public int TypeParameterCount { + get { return typeParameterCount; } + } + + public IType Resolve(ITypeResolveContext context) + { + return context.Compilation.FindType(knownTypeCode); } public override string ToString() { - return ReflectionHelper.GetCSharpNameByTypeCode(typeCode) ?? (this.Namespace + "." + this.Name); + return GetCSharpNameByTypeCode(knownTypeCode) ?? (this.Namespace + "." + this.Name); + } + + /// + /// Gets the C# primitive type name from the known type code. + /// Returns null if there is no primitive name for the specified type. + /// + public static string GetCSharpNameByTypeCode(KnownTypeCode knownTypeCode) + { + switch (knownTypeCode) { + case KnownTypeCode.Object: + return "object"; + case KnownTypeCode.Boolean: + return "bool"; + case KnownTypeCode.Char: + return "char"; + case KnownTypeCode.SByte: + return "sbyte"; + case KnownTypeCode.Byte: + return "byte"; + case KnownTypeCode.Int16: + return "short"; + case KnownTypeCode.UInt16: + return "ushort"; + case KnownTypeCode.Int32: + return "int"; + case KnownTypeCode.UInt32: + return "uint"; + case KnownTypeCode.Int64: + return "long"; + case KnownTypeCode.UInt64: + return "ulong"; + case KnownTypeCode.Single: + return "float"; + case KnownTypeCode.Double: + return "double"; + case KnownTypeCode.Decimal: + return "decimal"; + case KnownTypeCode.String: + return "string"; + case KnownTypeCode.Void: + return "void"; + default: + return null; + } } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/NullableType.cs b/ICSharpCode.NRefactory/TypeSystem/NullableType.cs index 16ad7be8cb..204559f0e3 100644 --- a/ICSharpCode.NRefactory/TypeSystem/NullableType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/NullableType.cs @@ -34,12 +34,12 @@ namespace ICSharpCode.NRefactory.TypeSystem if (type == null) throw new ArgumentNullException("type"); ParameterizedType pt = type as ParameterizedType; - return pt != null && pt.TypeParameterCount == 1 && pt.FullName == "System.Nullable"; + return pt != null && pt.TypeParameterCount == 1 && pt.GetDefinition().KnownTypeCode == KnownTypeCode.NullableOfT; } - public static bool IsNonNullableValueType(IType type, ITypeResolveContext context) + public static bool IsNonNullableValueType(IType type) { - return type.IsReferenceType(context) == false && !IsNullable(type); + return type.IsReferenceType == false && !IsNullable(type); } /// @@ -60,22 +60,21 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Creates a nullable type. /// - public static IType Create(IType elementType, ITypeResolveContext context) + public static IType Create(ICompilation compilation, IType elementType) { + if (compilation == null) + throw new ArgumentNullException("compilation"); if (elementType == null) throw new ArgumentNullException("elementType"); - if (context == null) - throw new ArgumentNullException("context"); - ITypeDefinition nullable = context.GetTypeDefinition("System", "Nullable", 1, StringComparer.Ordinal); - if (nullable != null) - return new ParameterizedType(nullable, new [] { elementType }); + IType nullableType = compilation.FindType(KnownTypeCode.NullableOfT); + ITypeDefinition nullableTypeDef = nullableType.GetDefinition(); + if (nullableTypeDef != null) + return new ParameterizedType(nullableTypeDef, new [] { elementType }); else - return SharedTypes.UnknownType; + return nullableType; } - static readonly ITypeReference NullableReference = new GetClassTypeReference("System", "Nullable", 1); - /// /// Creates a nullable type reference. /// @@ -83,7 +82,7 @@ namespace ICSharpCode.NRefactory.TypeSystem { if (elementType == null) throw new ArgumentNullException("elementType"); - return new ParameterizedTypeReference(NullableReference, new [] { elementType }); + return new ParameterizedTypeReference(KnownTypeReference.NullableOfT, new [] { elementType }); } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/ParameterListComparer.cs b/ICSharpCode.NRefactory/TypeSystem/ParameterListComparer.cs index bf0698f339..9ce7cfb7ff 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ParameterListComparer.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ParameterListComparer.cs @@ -23,20 +23,28 @@ using ICSharpCode.NRefactory.TypeSystem.Implementation; namespace ICSharpCode.NRefactory.TypeSystem { - public static class ParameterListComparer + /// + /// Compares parameter lists by comparing the types of all parameters. + /// + /// + /// 'ref int' and 'out int' are considered to be equal. + /// "Method{T}(T a)" and "Method{S}(S b)" are also considered equal. + /// + public sealed class ParameterListComparer : IEqualityComparer> { + public static readonly ParameterListComparer Instance = new ParameterListComparer(); + // We want to consider the parameter lists "Method(T a)" and "Method(S b)" as equal. // However, the parameter types are not considered equal, as T is a different type parameter than S. // In order to compare the method signatures, we will normalize all method type parameters. sealed class NormalizeMethodTypeParameters : TypeVisitor { - public static readonly NormalizeMethodTypeParameters Instance = new NormalizeMethodTypeParameters(); - - ITypeParameter[] normalTypeParameters = { new DefaultTypeParameter(EntityType.Method, 0, string.Empty) }; + //ITypeParameter[] normalTypeParameters = { new DefaultTypeParameter(EntityType.Method, 0, string.Empty) }; public override IType VisitTypeParameter(ITypeParameter type) { - if (type.OwnerType == EntityType.Method) { + throw new NotImplementedException(); + /*if (type.OwnerType == EntityType.Method) { ITypeParameter[] tps = this.normalTypeParameters; while (type.Index >= tps.Length) { // We don't have a normal type parameter for this index, so we need to extend our array. @@ -59,28 +67,27 @@ namespace ICSharpCode.NRefactory.TypeSystem return tps[type.Index]; } else { return base.VisitTypeParameter(type); - } + }*/ } } - public static bool Compare(ITypeResolveContext context, IParameterizedMember x, IParameterizedMember y) + readonly NormalizeMethodTypeParameters normalization = new NormalizeMethodTypeParameters(); + + public bool Equals(IList x, IList y) { - var px = x.Parameters; - var py = y.Parameters; - if (px.Count != py.Count) + if (x == y) + return true; + if (x == null || y == null || x.Count != y.Count) return false; - for (int i = 0; i < px.Count; i++) { - var a = px[i]; - var b = py[i]; + for (int i = 0; i < x.Count; i++) { + var a = x[i]; + var b = y[i]; if (a == null && b == null) continue; if (a == null || b == null) return false; - IType aType = a.Type.Resolve(context); - IType bType = b.Type.Resolve(context); - - aType = aType.AcceptVisitor(NormalizeMethodTypeParameters.Instance); - bType = bType.AcceptVisitor(NormalizeMethodTypeParameters.Instance); + IType aType = a.Type.AcceptVisitor(normalization); + IType bType = b.Type.AcceptVisitor(normalization); if (!aType.Equals(bType)) return false; @@ -88,18 +95,75 @@ namespace ICSharpCode.NRefactory.TypeSystem return true; } - public static int GetHashCode(ITypeResolveContext context, IParameterizedMember obj) + public int GetHashCode(IList obj) { - int hashCode = obj.Parameters.Count; + int hashCode = obj.Count; unchecked { - foreach (IParameter p in obj.Parameters) { + foreach (IParameter p in obj) { hashCode *= 27; - IType type = p.Type.Resolve(context); - type = type.AcceptVisitor(NormalizeMethodTypeParameters.Instance); + IType type = p.Type.AcceptVisitor(normalization); hashCode += type.GetHashCode(); } } return hashCode; } } + + /// + /// Compares member signatures. + /// + /// + /// This comparer checks for equal short name, equal type parameter count, and equal parameter types (using ParameterListComparer). + /// + public sealed class SignatureComparer : IEqualityComparer + { + StringComparer nameComparer; + + public SignatureComparer(StringComparer nameComparer) + { + if (nameComparer == null) + throw new ArgumentNullException("nameComparer"); + this.nameComparer = nameComparer; + } + + /// + /// Gets a signature comparer that uses an ordinal comparison for the member name. + /// + public static readonly SignatureComparer Ordinal = new SignatureComparer(StringComparer.Ordinal); + + public bool Equals(IMember x, IMember y) + { + if (x == y) + return true; + if (x == null || y == null || x.EntityType != y.EntityType || !nameComparer.Equals(x.Name, y.Name)) + return false; + IParameterizedMember px = x as IParameterizedMember; + IParameterizedMember py = y as IParameterizedMember; + if (px != null && py != null) { + IMethod mx = x as IMethod; + IMethod my = y as IMethod; + if (mx != null && my != null && mx.TypeParameters.Count != my.TypeParameters.Count) + return false; + return ParameterListComparer.Instance.Equals(px.Parameters, py.Parameters); + } else { + return true; + } + } + + public int GetHashCode(IMember obj) + { + unchecked { + int hash = (int)obj.EntityType * 33 + nameComparer.GetHashCode(obj.Name); + IParameterizedMember pm = obj as IParameterizedMember; + if (pm != null) { + hash *= 27; + hash += ParameterListComparer.Instance.GetHashCode(pm.Parameters); + IMethod m = pm as IMethod; + if (m != null) + hash += m.TypeParameters.Count; + } + return hash; + } + } + } } diff --git a/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs b/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs index 6fa06e0bc8..841b0cfbc7 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs @@ -37,7 +37,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// the type arguments. /// [Serializable] - public sealed class ParameterizedType : Immutable, IType, ISupportsInterning + public sealed class ParameterizedType : IType, ISupportsInterning { readonly ITypeDefinition genericType; readonly IType[] typeArguments; @@ -57,6 +57,9 @@ namespace ICSharpCode.NRefactory.TypeSystem for (int i = 0; i < this.typeArguments.Length; i++) { if (this.typeArguments[i] == null) throw new ArgumentNullException("typeArguments[" + i + "]"); + IResolved r = this.typeArguments[i] as IResolved; + if (r != null && r.Compilation != genericType.Compilation) + throw new InvalidOperationException("Cannot parameterize a type with type arguments from a different compilation."); } } @@ -75,9 +78,12 @@ namespace ICSharpCode.NRefactory.TypeSystem get { return genericType.Kind; } } - public bool? IsReferenceType(ITypeResolveContext context) - { - return genericType.IsReferenceType(context); + public ICompilation Compilation { + get { return genericType.Compilation; } + } + + public bool? IsReferenceType { + get { return genericType.IsReferenceType; } } public IType DeclaringType { @@ -107,7 +113,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } public string Namespace { - get { return genericType.Namespace;} + get { return genericType.Namespace; } } public string ReflectionName { @@ -138,7 +144,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } /// - /// Same as 'parameterizedType.TypeArguments[index]', but is a bit more efficient. + /// Same as 'parameterizedType.TypeArguments[index]', but is a bit more efficient (doesn't require the read-only wrapper). /// public IType GetTypeArgument(int index) { @@ -147,12 +153,12 @@ namespace ICSharpCode.NRefactory.TypeSystem public ITypeDefinition GetDefinition() { - return genericType.GetDefinition(); + return genericType; } - public IType Resolve(ITypeResolveContext context) + public ITypeReference ToTypeReference() { - return this; + return new ParameterizedTypeReference(genericType.ToTypeReference(), typeArguments.Select(t => t.ToTypeReference())); } /// @@ -174,82 +180,83 @@ namespace ICSharpCode.NRefactory.TypeSystem return new TypeParameterSubstitution(typeArguments, methodTypeArguments); } - public IEnumerable GetBaseTypes(ITypeResolveContext context) - { - var substitution = GetSubstitution(); - return genericType.GetBaseTypes(context).Select(t => t.AcceptVisitor(substitution)); + public IEnumerable DirectBaseTypes { + get { + var substitution = GetSubstitution(); + return genericType.DirectBaseTypes.Select(t => t.AcceptVisitor(substitution)); + } } - public IEnumerable GetNestedTypes(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + public IEnumerable GetNestedTypes(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) - return genericType.GetNestedTypes(context, filter, options); + return genericType.GetNestedTypes(filter, options); else - return GetMembersHelper.GetNestedTypes(this, context, filter, options); + return GetMembersHelper.GetNestedTypes(this, filter, options); } - public IEnumerable GetNestedTypes(IList typeArguments, ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + public IEnumerable GetNestedTypes(IList typeArguments, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) - return genericType.GetNestedTypes(typeArguments, context, filter, options); + return genericType.GetNestedTypes(typeArguments, filter, options); else - return GetMembersHelper.GetNestedTypes(this, typeArguments, context, filter, options); + return GetMembersHelper.GetNestedTypes(this, typeArguments, filter, options); } - public IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers) + public IEnumerable GetConstructors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) - return genericType.GetConstructors(context, filter, options); + return genericType.GetConstructors(filter, options); else - return GetMembersHelper.GetConstructors(this, context, filter, options); + return GetMembersHelper.GetConstructors(this, filter, options); } - public IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + public IEnumerable GetMethods(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) - return genericType.GetMethods(context, filter, options); + return genericType.GetMethods(filter, options); else - return GetMembersHelper.GetMethods(this, context, filter, options); + return GetMembersHelper.GetMethods(this, filter, options); } - public IEnumerable GetMethods(IList typeArguments, ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + public IEnumerable GetMethods(IList typeArguments, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) - return genericType.GetMethods(typeArguments, context, filter, options); + return genericType.GetMethods(typeArguments, filter, options); else - return GetMembersHelper.GetMethods(this, typeArguments, context, filter, options); + return GetMembersHelper.GetMethods(this, typeArguments, filter, options); } - public IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + public IEnumerable GetProperties(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) - return genericType.GetProperties(context, filter, options); + return genericType.GetProperties(filter, options); else - return GetMembersHelper.GetProperties(this, context, filter, options); + return GetMembersHelper.GetProperties(this, filter, options); } - public IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + public IEnumerable GetFields(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) - return genericType.GetFields(context, filter, options); + return genericType.GetFields(filter, options); else - return GetMembersHelper.GetFields(this, context, filter, options); + return GetMembersHelper.GetFields(this, filter, options); } - public IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + public IEnumerable GetEvents(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) - return genericType.GetEvents(context, filter, options); + return genericType.GetEvents(filter, options); else - return GetMembersHelper.GetEvents(this, context, filter, options); + return GetMembersHelper.GetEvents(this, filter, options); } - public IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + public IEnumerable GetMembers(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) - return genericType.GetMembers(context, filter, options); + return genericType.GetMembers(filter, options); else - return GetMembersHelper.GetMembers(this, context, filter, options); + return GetMembersHelper.GetMembers(this, filter, options); } public override bool Equals(object obj) @@ -347,27 +354,6 @@ namespace ICSharpCode.NRefactory.TypeSystem [Serializable] public sealed class ParameterizedTypeReference : ITypeReference, ISupportsInterning { - public static ITypeReference Create(ITypeReference genericType, IEnumerable typeArguments) - { - if (genericType == null) - throw new ArgumentNullException("genericType"); - if (typeArguments == null) - throw new ArgumentNullException("typeArguments"); - - ITypeReference[] typeArgs = typeArguments.ToArray(); - if (typeArgs.Length == 0) { - return genericType; - } else if (genericType is ITypeDefinition && Array.TrueForAll(typeArgs, t => t is IType)) { - IType[] ta = new IType[typeArgs.Length]; - for (int i = 0; i < ta.Length; i++) { - ta[i] = (IType)typeArgs[i]; - } - return new ParameterizedType((ITypeDefinition)genericType, ta); - } else { - return new ParameterizedTypeReference(genericType, typeArgs); - } - } - ITypeReference genericType; ITypeReference[] typeArguments; @@ -397,9 +383,10 @@ namespace ICSharpCode.NRefactory.TypeSystem public IType Resolve(ITypeResolveContext context) { - ITypeDefinition baseTypeDef = genericType.Resolve(context).GetDefinition(); + IType baseType = genericType.Resolve(context); + ITypeDefinition baseTypeDef = baseType.GetDefinition(); if (baseTypeDef == null) - return SharedTypes.UnknownType; + return baseType; int tpc = baseTypeDef.TypeParameterCount; if (tpc == 0) return baseTypeDef; @@ -408,7 +395,7 @@ namespace ICSharpCode.NRefactory.TypeSystem if (i < typeArguments.Length) resolvedTypes[i] = typeArguments[i].Resolve(context); else - resolvedTypes[i] = SharedTypes.UnknownType; + resolvedTypes[i] = SpecialType.UnknownType; } return new ParameterizedType(baseTypeDef, resolvedTypes); } diff --git a/ICSharpCode.NRefactory/TypeSystem/PointerType.cs b/ICSharpCode.NRefactory/TypeSystem/PointerType.cs index 7660dadd83..bfdea46c88 100644 --- a/ICSharpCode.NRefactory/TypeSystem/PointerType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/PointerType.cs @@ -22,7 +22,6 @@ using ICSharpCode.NRefactory.TypeSystem.Implementation; namespace ICSharpCode.NRefactory.TypeSystem { - [Serializable] public sealed class PointerType : TypeWithElementType, ISupportsInterning { public PointerType(IType elementType) : base(elementType) @@ -39,9 +38,8 @@ namespace ICSharpCode.NRefactory.TypeSystem } } - public override bool? IsReferenceType(ITypeResolveContext context) - { - return null; + public override bool? IsReferenceType { + get { return null; } } public override int GetHashCode() @@ -69,6 +67,11 @@ namespace ICSharpCode.NRefactory.TypeSystem return new PointerType(e); } + public override ITypeReference ToTypeReference() + { + return new PointerTypeReference(elementType.ToTypeReference()); + } + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) { elementType = provider.Intern(elementType); @@ -112,14 +115,6 @@ namespace ICSharpCode.NRefactory.TypeSystem return elementType.ToString() + "*"; } - public static ITypeReference Create(ITypeReference elementType) - { - if (elementType is IType) - return new PointerType((IType)elementType); - else - return new PointerTypeReference(elementType); - } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) { elementType = provider.Intern(elementType); diff --git a/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs b/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs index 809f820c6c..a9e055a3fd 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs @@ -43,43 +43,23 @@ namespace ICSharpCode.NRefactory.TypeSystem /// public sealed class UnboundTypeArgument {} - #region ITypeResolveContext.GetTypeDefinition(Type) + #region ICompilation.FindType /// - /// Retrieves a type definition. + /// Retrieves the specified type in this compilation. + /// Returns if the type cannot be found in this compilation. /// - /// Returns the type definition; or null if it is not found. - /// - /// This method retrieves the type definition; consider using type.ToTypeReference().Resolve(context) instead - /// if you need an . - /// - public static ITypeDefinition GetTypeDefinition(this ITypeResolveContext context, Type type) + public static IType FindType(this ICompilation compilation, Type type) { - if (type == null) - return null; - while (type.IsArray || type.IsPointer || type.IsByRef) - type = type.GetElementType(); - if (type.IsGenericType && !type.IsGenericTypeDefinition) - type = type.GetGenericTypeDefinition(); - if (type.IsGenericParameter) - return null; - if (type.DeclaringType != null) { - ITypeDefinition declaringType = GetTypeDefinition(context, type.DeclaringType); - if (declaringType != null) { - int typeParameterCount; - string name = SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); - typeParameterCount += declaringType.TypeParameterCount; - foreach (ITypeDefinition nestedType in declaringType.NestedTypes) { - if (nestedType.Name == name && nestedType.TypeParameterCount == typeParameterCount) { - return nestedType; - } - } - } - return null; - } else { - int typeParameterCount; - string name = SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); - return context.GetTypeDefinition(type.Namespace, name, typeParameterCount, StringComparer.Ordinal); - } + return type.ToTypeReference().Resolve(compilation.TypeResolveContext); + } + + /// + /// Retrieves the specified type in this compilation. + /// Returns if the type cannot be found in this compilation. + /// + public static IType FindType(this ICompilation compilation, string reflectionTypeName) + { + return ParseReflectionName(reflectionTypeName).Resolve(compilation.TypeResolveContext); } #endregion @@ -90,55 +70,43 @@ namespace ICSharpCode.NRefactory.TypeSystem /// The type to be converted. /// The parent entity, used to fetch the ITypeParameter for generic types. /// Returns the type reference. - public static ITypeReference ToTypeReference(this Type type, IEntity entity = null) + public static ITypeReference ToTypeReference(this Type type) { if (type == null) - return SharedTypes.UnknownType; + return SpecialType.UnknownType; if (type.IsGenericType && !type.IsGenericTypeDefinition) { - ITypeReference def = ToTypeReference(type.GetGenericTypeDefinition(), entity); + ITypeReference def = ToTypeReference(type.GetGenericTypeDefinition()); Type[] arguments = type.GetGenericArguments(); ITypeReference[] args = new ITypeReference[arguments.Length]; bool allUnbound = true; for (int i = 0; i < arguments.Length; i++) { - args[i] = ToTypeReference(arguments[i], entity); - allUnbound &= args[i].Equals(SharedTypes.UnboundTypeArgument); + args[i] = ToTypeReference(arguments[i]); + allUnbound &= args[i].Equals(SpecialType.UnboundTypeArgument); } if (allUnbound) return def; else return new ParameterizedTypeReference(def, args); } else if (type.IsArray) { - return new ArrayTypeReference(ToTypeReference(type.GetElementType(), entity), type.GetArrayRank()); + return new ArrayTypeReference(ToTypeReference(type.GetElementType()), type.GetArrayRank()); } else if (type.IsPointer) { - return new PointerTypeReference(ToTypeReference(type.GetElementType(), entity)); + return new PointerTypeReference(ToTypeReference(type.GetElementType())); } else if (type.IsByRef) { - return new ByReferenceTypeReference(ToTypeReference(type.GetElementType(), entity)); + return new ByReferenceTypeReference(ToTypeReference(type.GetElementType())); } else if (type.IsGenericParameter) { if (type.DeclaringMethod != null) { - IMethod method = entity as IMethod; - if (method != null) { - if (type.GenericParameterPosition < method.TypeParameters.Count) { - return method.TypeParameters[type.GenericParameterPosition]; - } - } - return SharedTypes.UnknownType; + return new TypeParameterReference(EntityType.Method, type.GenericParameterPosition); } else { - ITypeDefinition c = (entity as ITypeDefinition) ?? (entity != null ? entity.DeclaringTypeDefinition : null); - if (c != null && type.GenericParameterPosition < c.TypeParameters.Count) { - if (c.TypeParameters[type.GenericParameterPosition].Name == type.Name) { - return c.TypeParameters[type.GenericParameterPosition]; - } - } - return SharedTypes.UnknownType; + return new TypeParameterReference(EntityType.TypeDefinition, type.GenericParameterPosition); } } else if (type.DeclaringType != null) { if (type == typeof(Dynamic)) - return SharedTypes.Dynamic; + return SpecialType.Dynamic; else if (type == typeof(Null)) - return SharedTypes.Null; + return SpecialType.NullType; else if (type == typeof(UnboundTypeArgument)) - return SharedTypes.UnboundTypeArgument; - ITypeReference baseTypeRef = ToTypeReference(type.DeclaringType, entity); + return SpecialType.UnboundTypeArgument; + ITypeReference baseTypeRef = ToTypeReference(type.DeclaringType); int typeParameterCount; string name = SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); return new NestedTypeReference(baseTypeRef, name, typeParameterCount); @@ -185,28 +153,14 @@ namespace ICSharpCode.NRefactory.TypeSystem } #endregion - #region TypeCode.ToTypeReference() - static readonly ITypeReference[] primitiveTypeReferences = { - SharedTypes.UnknownType, // TypeCode.Empty - KnownTypeReference.Object, - new GetClassTypeReference("System", "DBNull", 0), - KnownTypeReference.Boolean, - KnownTypeReference.Char, - KnownTypeReference.SByte, - KnownTypeReference.Byte, - KnownTypeReference.Int16, - KnownTypeReference.UInt16, - KnownTypeReference.Int32, - KnownTypeReference.UInt32, - KnownTypeReference.Int64, - KnownTypeReference.UInt64, - KnownTypeReference.Single, - KnownTypeReference.Double, - KnownTypeReference.Decimal, - new GetClassTypeReference("System", "DateTime", 0), - SharedTypes.UnknownType, // (TypeCode)17 has no enum value? - KnownTypeReference.String - }; + #region TypeCode support + /// + /// Retrieves a built-in type using the specified type code. + /// + public static IType FindType(this ICompilation compilation, TypeCode typeCode) + { + return compilation.FindType((KnownTypeCode)typeCode); + } /// /// Creates a reference to the specified type. @@ -215,50 +169,21 @@ namespace ICSharpCode.NRefactory.TypeSystem /// Returns the type reference. public static ITypeReference ToTypeReference(this TypeCode typeCode) { - return primitiveTypeReferences[(int)typeCode]; - } - #endregion - - #region GetTypeCode - static readonly string[] typeNamesByTypeCode = { - "Void", "Object", "DBNull", "Boolean", "Char", - "SByte", "Byte", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64", - "Single", "Double", "Decimal", "DateTime", null, "String" - }; - - static readonly string[] csharpTypeNamesByTypeCode = { - "void", "object", null, "bool", "char", - "sbyte", "byte", "short", "ushort", "int", "uint", "long", "ulong", - "float", "double", "decimal", null, null, "string" - }; - - internal static int ByTypeCodeArraySize { - get { return typeNamesByTypeCode.Length; } - } - - public static string GetShortNameByTypeCode(TypeCode typeCode) - { - return typeNamesByTypeCode[(int)typeCode]; - } - - public static string GetCSharpNameByTypeCode(TypeCode typeCode) - { - return csharpTypeNamesByTypeCode[(int)typeCode]; + return KnownTypeReference.Get((KnownTypeCode)typeCode); } /// - /// Gets the type code for the specified type, or TypeCode.Empty if none of the other type codes matches. + /// Gets the type code for the specified type, or TypeCode.Empty if none of the other type codes match. /// public static TypeCode GetTypeCode(IType type) { ITypeDefinition def = type as ITypeDefinition; - if (def != null && def.TypeParameterCount == 0 && def.Namespace == "System") { - string[] typeNames = typeNamesByTypeCode; - string name = def.Name; - for (int i = 1; i < typeNames.Length; i++) { - if (name == typeNames[i]) - return (TypeCode)i; - } + if (def != null) { + KnownTypeCode typeCode = def.KnownTypeCode; + if (typeCode <= KnownTypeCode.String && typeCode != KnownTypeCode.Void) + return (TypeCode)typeCode; + else + return TypeCode.Empty; } return TypeCode.Empty; } @@ -273,12 +198,12 @@ namespace ICSharpCode.NRefactory.TypeSystem /// If no entity is provided, type parameters are converted to . /// The syntax of the reflection type name is invalid /// A type reference that represents the reflection name. - public static ITypeReference ParseReflectionName(string reflectionTypeName, IEntity parentEntity = null) + public static ITypeReference ParseReflectionName(string reflectionTypeName) { if (reflectionTypeName == null) throw new ArgumentNullException("reflectionTypeName"); int pos = 0; - ITypeReference r = ParseReflectionName(reflectionTypeName, ref pos, parentEntity); + ITypeReference r = ParseReflectionName(reflectionTypeName, ref pos); if (pos < reflectionTypeName.Length) throw new ReflectionNameParseException(pos, "Expected end of type name"); return r; @@ -300,7 +225,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } } - static ITypeReference ParseReflectionName(string reflectionTypeName, ref int pos, IEntity entity) + static ITypeReference ParseReflectionName(string reflectionTypeName, ref int pos) { if (pos == reflectionTypeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); @@ -313,19 +238,11 @@ namespace ICSharpCode.NRefactory.TypeSystem // method type parameter reference pos++; int index = ReadTypeParameterCount(reflectionTypeName, ref pos); - IMethod method = entity as IMethod; - if (method != null && index >= 0 && index < method.TypeParameters.Count) - return method.TypeParameters[index]; - else - return SharedTypes.UnknownType; + return new TypeParameterReference(EntityType.Method, index); } else { // class type parameter reference int index = ReadTypeParameterCount(reflectionTypeName, ref pos); - ITypeDefinition c = (entity as ITypeDefinition) ?? (entity != null ? entity.DeclaringTypeDefinition : null); - if (c != null && index >= 0 && index < c.TypeParameters.Count) - return c.TypeParameters[index]; - else - return SharedTypes.UnknownType; + return new TypeParameterReference(EntityType.TypeDefinition, index); } } // not a type parameter reference: read the actual type name @@ -353,7 +270,7 @@ namespace ICSharpCode.NRefactory.TypeSystem // it's a generic type List typeArguments = new List(tpc); pos++; - typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos, entity)); + typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos)); if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') pos++; else @@ -366,7 +283,7 @@ namespace ICSharpCode.NRefactory.TypeSystem else throw new ReflectionNameParseException(pos, "Expected another type argument"); - typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos, entity)); + typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos)); if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') pos++; diff --git a/ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs b/ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs index 6fc19ae88f..d3666b2c2c 100644 --- a/ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs +++ b/ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs @@ -17,95 +17,82 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; using ICSharpCode.NRefactory.TypeSystem.Implementation; namespace ICSharpCode.NRefactory.TypeSystem { /// - /// Contains static implementations of well-known types. + /// Contains static implementations of special types. /// - public static class SharedTypes + [Serializable] + public sealed class SpecialType : AbstractType, ITypeReference { /// /// Gets the type representing resolve errors. /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "It's immutable")] - public readonly static IType UnknownType = new SharedTypeImpl(TypeKind.Unknown, "?", isReferenceType: null); + public readonly static SpecialType UnknownType = new SpecialType(TypeKind.Unknown, "?", isReferenceType: null); /// /// The null type is used as type of the null literal. It is a reference type without any members; and it is a subtype of all reference types. /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "It's immutable")] - public readonly static IType Null = new SharedTypeImpl(TypeKind.Null, "null", isReferenceType: true); + public readonly static SpecialType NullType = new SpecialType(TypeKind.Null, "null", isReferenceType: true); /// /// Type representing the C# 'dynamic' type. /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "It's immutable")] - public readonly static IType Dynamic = new SharedTypeImpl(TypeKind.Dynamic, "dynamic", isReferenceType: true); + public readonly static SpecialType Dynamic = new SpecialType(TypeKind.Dynamic, "dynamic", isReferenceType: true); /// /// A type used for unbound type arguments in partially parameterized types. /// /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "It's immutable")] - public readonly static IType UnboundTypeArgument = new SharedTypeImpl(TypeKind.UnboundTypeArgument, "", isReferenceType: null); + public readonly static SpecialType UnboundTypeArgument = new SpecialType(TypeKind.UnboundTypeArgument, "", isReferenceType: null); - /* - * I'd like to define static instances for common types like - * void, int, etc.; but there are two problems with this: - * - * SharedTypes.Void.GetDefinition().ProjectContent should return mscorlib, but - * we can't do that without providing a context. - * - * Assuming we add a context parameter to GetDefinition(): - * - * SharedType.Void.Equals(SharedType.Void.GetDefinition(x)) - * SharedType.Void.GetDefinition(y).Equals(SharedType.Void) - * should both return true. - * But if the type can have multiple definitions (multiple mscorlib versions loaded), - * then this is not possible without violating transitivity of Equals(): - * - * SharedType.Void.GetDefinition(x).Equals(SharedType.Void.GetDefinition(y)) - * would have to return true even though these are two distinct definitions. - */ + readonly TypeKind kind; + readonly string name; + readonly bool? isReferenceType; - [Serializable] - sealed class SharedTypeImpl : AbstractType + private SpecialType(TypeKind kind, string name, bool? isReferenceType) { - readonly TypeKind kind; - readonly string name; - readonly bool? isReferenceType; - - public SharedTypeImpl(TypeKind kind, string name, bool? isReferenceType) - { - this.kind = kind; - this.name = name; - this.isReferenceType = isReferenceType; - } - - public override TypeKind Kind { - get { return kind; } - } - - public override string Name { - get { return name; } - } - - public override bool? IsReferenceType(ITypeResolveContext context) - { - return isReferenceType; - } - - public override bool Equals(IType other) - { - return other != null && other.Kind == kind; - } - - public override int GetHashCode() - { - return (int)kind; - } + this.kind = kind; + this.name = name; + this.isReferenceType = isReferenceType; + } + + public override ITypeReference ToTypeReference() + { + return this; + } + + public override string Name { + get { return name; } + } + + public override TypeKind Kind { + get { return kind; } + } + + public override bool? IsReferenceType { + get { return isReferenceType; } + } + + IType ITypeReference.Resolve(ITypeResolveContext context) + { + if (context == null) + throw new ArgumentNullException("context"); + return this; + } + + [ObsoleteAttribute] + public override bool Equals(IType other) + { + return other is SpecialType && other.Kind == kind; + } + + public override int GetHashCode() + { + return 81625621 ^ (int)kind; } } } diff --git a/ICSharpCode.NRefactory/Utils/CacheManager.cs b/ICSharpCode.NRefactory/Utils/CacheManager.cs index 4068522ca2..ef01478e3c 100644 --- a/ICSharpCode.NRefactory/Utils/CacheManager.cs +++ b/ICSharpCode.NRefactory/Utils/CacheManager.cs @@ -24,14 +24,12 @@ using System.Threading; namespace ICSharpCode.NRefactory.Utils { /// - /// Allows caching values for a specific resolve context. + /// Allows caching values for a specific compilation. /// A CacheManager consists of two dictionaries: one for shared instances (shared among all threads working with that resolve context), /// and one for thread-local instances. - /// Additionally, it provides a Dispose() event that can be used to clear any external caches when - /// leaving the "using (var ctx = context.Synchronize())" block. /// /// This class is thread-safe - public sealed class CacheManager : IDisposable + public sealed class CacheManager { readonly ConcurrentDictionary sharedDict = new ConcurrentDictionary(ReferenceComparer.Instance); readonly ThreadLocal> localDict = new ThreadLocal>(() => new Dictionary(ReferenceComparer.Instance)); @@ -43,6 +41,16 @@ namespace ICSharpCode.NRefactory.Utils return val; } + public object GetOrAddShared(object key, Func valueFactory) + { + return sharedDict.GetOrAdd(key, valueFactory); + } + + public object GetOrAddShared(object key, object val) + { + return sharedDict.GetOrAdd(key, val); + } + public void SetShared(object key, object val) { sharedDict[key] = val; @@ -59,22 +67,5 @@ namespace ICSharpCode.NRefactory.Utils { localDict.Value[key] = val; } - - public event EventHandler Disposed; - - /// - /// Invokes the event. - /// - public void Dispose() - { - sharedDict.Clear(); - localDict.Dispose(); // dispose the ThreadLocal - // TODO: test whether this frees the referenced value on all threads - - // fire Disposed() only once by removing the old event handlers - EventHandler disposed = Interlocked.Exchange(ref Disposed, null); - if (disposed != null) - disposed(this, EventArgs.Empty); - } } } diff --git a/ICSharpCode.NRefactory/Utils/ImmutableStack.cs b/ICSharpCode.NRefactory/Utils/ImmutableStack.cs new file mode 100644 index 0000000000..2032f89b99 --- /dev/null +++ b/ICSharpCode.NRefactory/Utils/ImmutableStack.cs @@ -0,0 +1,114 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace ICSharpCode.NRefactory.Utils +{ + /// + /// An immutable stack. + /// + /// Using 'foreach' on the stack will return the items from top to bottom (in the order they would be popped). + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] + [Serializable] + public sealed class ImmutableStack : IEnumerable + { + /// + /// Gets the empty stack instance. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "ImmutableStack is immutable")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")] + public static readonly ImmutableStack Empty = new ImmutableStack(); + + readonly T value; + readonly ImmutableStack next; + + private ImmutableStack() + { + } + + private ImmutableStack(T value, ImmutableStack next) + { + this.value = value; + this.next = next; + } + + /// + /// Pushes an item on the stack. This does not modify the stack itself, but returns a new + /// one with the value pushed. + /// + public ImmutableStack Push(T item) + { + return new ImmutableStack(item, this); + } + + /// + /// Gets the item on the top of the stack. + /// + /// The stack is empty. + public T Peek() + { + if (IsEmpty) + throw new InvalidOperationException("Operation not valid on empty stack."); + return value; + } + + internal T UnsafePeek() + { + Debug.Assert(!IsEmpty); + return value; + } + + /// + /// Gets the stack with the top item removed. + /// + /// The stack is empty. + public ImmutableStack Pop() + { + if (IsEmpty) + throw new InvalidOperationException("Operation not valid on empty stack."); + return next; + } + + /// + /// Gets if this stack is empty. + /// + public bool IsEmpty { + get { return next == null; } + } + + /// + /// Gets an enumerator that iterates through the stack top-to-bottom. + /// + public IEnumerator GetEnumerator() + { + ImmutableStack t = this; + while (!t.IsEmpty) { + yield return t.value; + t = t.next; + } + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + + /// + public override string ToString() + { + StringBuilder b = new StringBuilder("[Stack"); + foreach (T val in this) { + b.Append(' '); + b.Append(val); + } + b.Append(']'); + return b.ToString(); + } + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ITypeOrNamespaceReference.cs b/ICSharpCode.NRefactory/Utils/LazyInit.cs similarity index 66% rename from ICSharpCode.NRefactory.CSharp/Resolver/ITypeOrNamespaceReference.cs rename to ICSharpCode.NRefactory/Utils/LazyInit.cs index f5ebaf384a..08978503c8 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/ITypeOrNamespaceReference.cs +++ b/ICSharpCode.NRefactory/Utils/LazyInit.cs @@ -17,24 +17,31 @@ // DEALINGS IN THE SOFTWARE. using System; -using ICSharpCode.NRefactory.Semantics; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; using ICSharpCode.NRefactory.TypeSystem; -namespace ICSharpCode.NRefactory.CSharp.Resolver +namespace ICSharpCode.NRefactory.Utils { - /// - /// Represents a reference which could point to a type or namespace. - /// - public interface ITypeOrNamespaceReference : ITypeReference + public static class LazyInit { - /// - /// Resolves the reference and returns the ResolveResult. - /// - ResolveResult DoResolve(ITypeResolveContext context); + static volatile object barrier = null; + + public static void ReadBarrier() + { + object tmp = barrier; + } /// - /// Returns the namespace that is referenced; or null if no such namespace is found. + /// Atomatically performs the following operation: + /// - If target is null: stores newValue in target and returns newValue. + /// - If target is not null: returns target. /// - NamespaceResolveResult ResolveNamespace(ITypeResolveContext context); + public static T GetOrSet(ref T target, T newValue) where T : class + { + T oldValue = Interlocked.CompareExchange(ref target, newValue, null); + return oldValue ?? newValue; + } } } diff --git a/ICSharpCode.NRefactory/Utils/ProjectedList.cs b/ICSharpCode.NRefactory/Utils/ProjectedList.cs new file mode 100644 index 0000000000..b5df19f0d9 --- /dev/null +++ b/ICSharpCode.NRefactory/Utils/ProjectedList.cs @@ -0,0 +1,237 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER 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 System.Collections.Generic; + +namespace ICSharpCode.NRefactory.Utils +{ + public sealed class ProjectedList : IList where TOutput : class + { + readonly IList input; + readonly Func projection; + readonly TOutput[] items; + + public ProjectedList(IList input, Func projection) + { + if (input == null) + throw new ArgumentNullException("input"); + if (projection == null) + throw new ArgumentNullException("projection"); + this.input = input; + this.projection = projection; + this.items = new TOutput[input.Count]; + } + + public TOutput this[int index] { + get { + TOutput output = items[index]; + if (output != null) { + LazyInit.ReadBarrier(); + return output; + } + return LazyInit.GetOrSet(ref items[index], projection(input[index])); + } + } + + TOutput IList.this[int index] { + get { return this[index]; } + set { + throw new NotSupportedException(); + } + } + + public int Count { + get { return items.Length; } + } + + bool ICollection.IsReadOnly { + get { return true; } + } + + int IList.IndexOf(TOutput item) + { + var comparer = EqualityComparer.Default; + for (int i = 0; i < this.Count; i++) { + if (comparer.Equals(this[i], item)) + return i; + } + return -1; + } + + void IList.Insert(int index, TOutput item) + { + throw new NotSupportedException(); + } + + void IList.RemoveAt(int index) + { + throw new NotSupportedException(); + } + + void ICollection.Add(TOutput item) + { + throw new NotSupportedException(); + } + + void ICollection.Clear() + { + throw new NotSupportedException(); + } + + bool ICollection.Contains(TOutput item) + { + var comparer = EqualityComparer.Default; + for (int i = 0; i < this.Count; i++) { + if (comparer.Equals(this[i], item)) + return true; + } + return false; + } + + void ICollection.CopyTo(TOutput[] array, int arrayIndex) + { + throw new NotImplementedException(); + } + + bool ICollection.Remove(TOutput item) + { + throw new NotImplementedException(); + } + + public IEnumerator GetEnumerator() + { + for (int i = 0; i < this.Count; i++) { + yield return this[i]; + } + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } + + public sealed class ProjectedList : IList where TOutput : class + { + readonly IList input; + readonly TContext context; + readonly Func projection; + readonly TOutput[] items; + + public ProjectedList(TContext context, IList input, Func projection) + { + if (input == null) + throw new ArgumentNullException("input"); + if (projection == null) + throw new ArgumentNullException("projection"); + this.input = input; + this.context = context; + this.projection = projection; + this.items = new TOutput[input.Count]; + } + + public TOutput this[int index] { + get { + TOutput output = items[index]; + if (output != null) { + LazyInit.ReadBarrier(); + return output; + } + return LazyInit.GetOrSet(ref items[index], projection(context, input[index])); + } + } + + TOutput IList.this[int index] { + get { return this[index]; } + set { + throw new NotSupportedException(); + } + } + + public int Count { + get { return items.Length; } + } + + bool ICollection.IsReadOnly { + get { return true; } + } + + int IList.IndexOf(TOutput item) + { + var comparer = EqualityComparer.Default; + for (int i = 0; i < this.Count; i++) { + if (comparer.Equals(this[i], item)) + return i; + } + return -1; + } + + void IList.Insert(int index, TOutput item) + { + throw new NotSupportedException(); + } + + void IList.RemoveAt(int index) + { + throw new NotSupportedException(); + } + + void ICollection.Add(TOutput item) + { + throw new NotSupportedException(); + } + + void ICollection.Clear() + { + throw new NotSupportedException(); + } + + bool ICollection.Contains(TOutput item) + { + var comparer = EqualityComparer.Default; + for (int i = 0; i < this.Count; i++) { + if (comparer.Equals(this[i], item)) + return true; + } + return false; + } + + void ICollection.CopyTo(TOutput[] array, int arrayIndex) + { + throw new NotImplementedException(); + } + + bool ICollection.Remove(TOutput item) + { + throw new NotImplementedException(); + } + + public IEnumerator GetEnumerator() + { + for (int i = 0; i < this.Count; i++) { + yield return this[i]; + } + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} diff --git a/NRefactory.sln b/NRefactory.sln index 5052f89732..f9a50314d3 100644 --- a/NRefactory.sln +++ b/NRefactory.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 -# SharpDevelop 4.1.0.7887-beta +# SharpDevelop 4.2.0.8212-alpha Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DC98210E-1646-483B-819A-2BB8272461E4}" ProjectSection(SolutionItems) = preProject README = README diff --git a/README b/README index 4c6a493aa3..58ec8c97d8 100644 --- a/README +++ b/README @@ -1,48 +1,84 @@ Overview of the NRefactory library: -ICSharpCode.Editor: - Interfaces that abstract from the text editor control used. - Maybe future AvalonEdit versions will directly implement these interfaces, but you could also write adapters for other editors. +Features: + - C# Parser + - Abstract Syntax Tree with pattern-matching support + - Semantic Analysis for C# (supports C# 4.0 + async/await) + - Code Completion for C# + - Pretty Printer for C# + - Lots of C# refactorings + - VB support is not implemented yet. -ICSharpCode.NRefactory.TypeSystem: - Contains a language-independent representation of the .NET type system. -ICSharpCode.NRefactory.TypeSystem.Implementation: - Contains base classes that help implementing the type system interfaces. +Dependencies: + .NET 4.0 + Mono.Cecil 0.9.5 + NRefactory contains a modified copy of mcs (Mono's C# compiler) for the C# parser. -ICSharpCode.NRefactory.CSharp.Ast: - Abstract Syntax Tree for C# -ICSharpCode.NRefactory.CSharp.Resolver: - Semantic analysis for C# (resolving the meaning of expressions) +How to compile: + 1. Get Mono.Cecil + Download Cecil from https://github.com/jbevain/cecil/ and unzip it into a directory named "Mono.Cecil" + next to the directory containing NRefactory. + 2. Open NRefactory.sln in your favorite .NET IDE and compile. -ICSharpCode.NRefactory.CSharp.Analysis: - Semantic analysis for C# (additional analysis functionality) -ICSharpCode.NRefactory.Documentation: - Classes for working with .xml documentation files. +Namespace overview: -ICSharpCode.NRefactory.PatternMatching: - Provides classes for pattern matching over the C# and VB ASTs. +ICSharpCode.NRefactory assembly + ICSharpCode.NRefactory.Editor: + Interfaces that abstract from the text editor control used. + Maybe future AvalonEdit versions will directly implement these interfaces, but you could also write adapters for other editors. + + ICSharpCode.NRefactory.TypeSystem: + Contains a language-independent representation of the .NET type system. + The type system is divided into two portions: unresolved and resolved type systems. + + ICSharpCode.NRefactory.TypeSystem.Implementation: + Contains default implementations for the type system interfaces. + + ICSharpCode.NRefactory.Semantics: + Contains classes used to represent the semantics of a language element. + + ICSharpCode.NRefactory.Documentation: + Classes for working with .xml documentation files. + + ICSharpCode.NRefactory.PatternMatching: + Provides classes for pattern matching over the C# and VB ASTs. + + ICSharpCode.NRefactory.Util: + Various helper classes. -ICSharpCode.NRefactory.Util: - Various helper classes. -ICSharpCode.NRefactory.VB.Ast: (in the separate ICSharpCode.NRefactory.VB assembly) - Abstract Syntax Tree for VB +ICSharpCode.NRefactory.CSharp assembly + ICSharpCode.NRefactory.CSharp: + Abstract Syntax Tree for C# + + ICSharpCode.NRefactory.CSharp.Completion: + Code completion (IntelliSense) for C# + + ICSharpCode.NRefactory.CSharp.Resolver: + Semantic analysis for C# (resolving the meaning of expressions) + + ICSharpCode.NRefactory.CSharp.Analysis: + Semantic analysis for C# (additional analysis functionality) + + ICSharpCode.NRefactory.CSharp.TypeSystem: + Contains type system implementations specific to C#. + + +ICSharpCode.NRefactory.VB assembly + ICSharpCode.NRefactory.VB: + Abstract Syntax Tree for VB -Dependencies: - .NET 3.5 or .NET 4.0 - Mono.Cecil 0.9.4 Null-Object pattern: The NRefactory library makes extensive use of the null object pattern. As a result, NullReferenceExceptions should be very rare when working with this library. - In the type system, both ITypeReference and IType use SharedTypes.UnknownType to represent + In the type system, both ITypeReference and IType use SpecialType.UnknownType to represent unknown types. - Unless the method is documented otherwise, no method or property returning a ITypeReference or - IType will return null. - When adding to this library, to try to keep such uses of null rare. + Unless the XML documentation says otherwise, no method or property returning a ITypeReference + or IType will return null. Note that the null object pattern is not used for ITypeDefinition: IProjectContent.GetClass() returns null when a type is not found. Take care to abort your @@ -83,8 +119,8 @@ Q: What is the difference between types and type references? A: If you've previously used the .NET Reflection API, the concept of type references will be new to you. - NRefactory has the concept of the "project content": every assembly/project is stored - independently from other assemblies/projects. + NRefactory has the concept of the "unresolved type system": every assembly/project is stored + in unresolved form. It is possible to load some source code into a project which contains the type reference "int[]" without having to load mscorlib into NRefactory. So inside the entities stored for the project, the array type is only referenced using an @@ -94,50 +130,39 @@ A: If you've previously used the .NET Reflection API, the concept of type refere IType Resolve(ITypeResolutionContext context); } By calling the Resolve()-method, you will get back the actual ArrayType. - At this point, you have to provide the type resolution context: - - Note that every type can also be used as type reference - the IType interface derives from - ITypeReference. - Every IType simply returns itself when the Resolve()-method is called. - Types are often directly used as references when source and target of the reference are within - the same assembly. - Because an ArrayType must have an IType as element type, we also need the ArrayTypeReference - to represent an array of a type that's not yet resolved. - When resolved, the ArrayTypeReference produces an array type: - new ArrayTypeReference(r).Resolve(context) = new ArrayType(r.Resolve(context)) + Not only type references are split up this way; pretty much every class in the type system + comes in unresolved and resolved forms. + + +Q: What is a compilation (ICompilation)? + +A: A compilation serves as the root object of the resolved type system. + It consists of a main assembly and multiple referenced assemblies, + and may also contain additional information like compiler options. Q: What's in an ITypeResolveContext? A: An ITypeResolveContext is an environment for looking up namespaces and types. - Usually, a resolve context will represent a set of projects. - Most of the time, that set will be the current project, plus the direct references of the - current project. + It consists of the current compilation, the current type definition, + and language-specific implementations may add additional information (e.g. the list of usings). - Every project content on its own is a type resolve context (IProjectContent extends - ITypeResolveContext); but (with the exception of mscorlib) isn't useful for resolving types as - you also need the references. - To represent a set of projects, the class CompositeTypeResolveContext can be used. + Generally, you cannot resolve a type reference without knowing what kind of context is expected. Q: How do I get the IType or ITypeReference for a primitive type such as string or int? -A: Please use: - TypeCode.Int32.ToTypeReference().Resolve(context) - Skip the Resolve() call if you only need the type reference. +A: To get an IType for a primitive type, use: + compilation.FindType(KnownTypeCode.Int32) - ReflectionHelper.ToTypeReference is very fast if given a TypeCode (it simply looks up an - existing type reference in an array), and your code will benefit from caching of the resolve - result (once that gets implemented for these primitive type references). + To get an ITypeReference, use: + KnownTypeReference.Int32 - Avoid using "context.GetClass(typeof(int))" - this call involves Reflection on the System.Type - being passed, cannot benefit from any caching implemented in the future, and most importantly: - it may return null. - And do you always test your code in a scenario where mscorlib isn't contained in the resolve - context? - The approach suggested above will return SharedTypes.UnknownType when the type cannot be - resolved, so you don't run into the risk of getting NullReferenceExceptions. + It is also possible to use a System.Type for retrieving a type: + compilation.FindType(typeof(int)) + or + typeof(int).ToTypeReference(). Q: Is it thread-safe? @@ -150,80 +175,26 @@ A: This question is a bit difficult to answer. can be executed concurrently. [Actually, sometimes static state is used for caches, but those uses are thread-safe.] TODO: what about the C# parser? gmcs is full of static state... + -> this is being worked on; for the time being, NRefactory uses a global lock during parsing; + so it's thread-safe but slow. Some instance methods may use hidden instance state, so it is not safe to e.g use an instance of the CSharp.Resolver.Conversions class concurrently. Instead, you need to create an instance on every thread. - In the case of project contents, it is desirable to be able to use them, and all the classes in - that project content, on multiple threads - for example, to provide code completion in an IDE - while a background thread parses more files and adds them to the project content. - - For this reason, the entity interfaces (ITypeDefinition, IMember, etc.) are designed to be - freezable. Once the Freeze() method is called, an entity instance becomes immutable and - thread-safe. - - Whether an ITypeResolveContext is thread-safe depends on the implementation: - TypeStorage: thread-safe for concurrent reads, but only if it's not written to - (see XML documentation on TypeStorage) - CecilProjectContent: immutable and thread-safe - SimpleProjectContent: fully thread-safe - CompositeTypeResolveContext: depends on the child contexts - - Usually, you'll work with a set of loaded projects (SimpleProjectContents) - and loaded external assemblies (CecilProjectContent). - A CompositeTypeResolveContext representing such a set is thread-safe. - - Hoever, some algorithms can become confused if two GetClass() calls with same arguments - produce different results (e.g. because another thread updated a class definition). - Also, there's a performance problem: if you have a composite of 15 SimpleProjectContents and - the resolve algorithm requests 100 types, that's 1500 times entering and leaving the read-lock. - Moreoever, internal caches in the library are not used when passing a mutable - ITypeResolveContext. - - The solution is to make the read lock more coarse-grained: - using (var syncContext = compositeTypeResolveContext.Synchronize()) { - resolver.ResolveStuff(syncContext); - } - On the call to Synchronize(), all 15 SimpleProjectContents are locked for reading. - The return value "syncContext" can then be used to access the type resolve context without - further synchronization overhead. - It is guaranteed not to change (within the using block), so the library may cache some - information. (TODO: give example of a cache) - Once the return value is disposed, the read-locks are released (and the caches are cleared). + The type system itself is thread-safe. Both the unresolved and the resolved type systems are + immutable. + + When you add to an IProjectContent, the existing project content isn't modified, + but a new project content is created instead. All implementations of the type system interfaces + are either immutable or freezable. + + And on the resolved type system side, ICompilation is immutable as well. + Internally, the resolved type system will resolve elements only on demand, but this is done + in a thread-safe manner. Q: What format do the .ToString() methods use? A: They don't use any particular format. They're merely intended as a debugging aid. Currently .ToString() usually matches .ReflectionName, but that may change in the future. - - -Q: Why are there extension methods IType.IsEnum() and IType.IsDelegate(), but no IType.IsStruct() - or IType.IsInterface()? - -A: Because if you're asking whether a type is a struct, it's very likely that you're asking the - wrong question. - The distinction between class/struct/interface/enum/delegate is important in the world of type - definitions, and there's ITypeDefinition.ClassType to address this. But the distinction isn't - so important in the world of types. - - If whatever you are doing works with struct-types, then it likely will also work with - enum-types, and also with type parameters with a value-type constraint. - So instead of asking IsStruct(), you really should be asking: IType.IsReferenceType == false - - Enums and delegates are special because you can do special things with those types - (e.g. subtract them from each other). - If you really need to know, you can do - "type.GetDefinition() != null && type.GetDefinition().ClassType == WhatIWant" - yourself, but for the most part you should be fine with IsReferenceType, IsEnum and IsDelegate. - - -Q: What's the difference between the .NET 3.5 and .NET 4.0 versions? - -A: As for visible API difference, not much. The .NET 4.0 build has some additional overloads for a few methods, - taking a System.Threading.CancellationToken to allow aborting a resolve run. - Internally, the .NET 4.0 version might be tiny bit more performant because it uses covariance for IEnumerable, - where the .NET 3.5 version has to allocate wrapper objects instead. - - Both versions support loading assemblies of all .NET versions (1.0 to 4.0); and both support C# 4.0. diff --git a/doc/Pattern Matching.html b/doc/Pattern Matching.html new file mode 100644 index 0000000000..88ea83e222 --- /dev/null +++ b/doc/Pattern Matching.html @@ -0,0 +1,115 @@ + +NRefactory Pattern Matching + + The pattern matching API for the C# AST is similar to how regular + expressions work in .NET, except that it's working with AstNodes + instead of characters.
+ First you declare a pattern, for example: "X a = new X(...);".
+ var pattern = new VariableDeclarationStatement {
+     Type = new AnyNode("type"),
+     Variables = {
+         new VariableInitializer {
+             Name = Pattern.AnyString,
+             Initializer = new ObjectCreateExpression {
+                 Type = new Backreference("type"),
+                 Arguments = { new Repeat(new AnyNode()) }
+                 Initializer = new OptionalNode(new AnyNode())
+             }
+         }
+     }};
+
+ This is a pattern AST - it is a C# AST using the normal C# + AST classes, but also contains special pattern nodes + (AnyNode, Repeat, OptionalNode, Backreference, NamedNode, Choice, + ...).
+ If you call
+  Match m = pattern.Match(someNode);
+
then m.Success will be true if someNode is a + VariableDeclarationStatement that declares a single variable, which + is initialized to a new object of the variable type.
+ Basically, Match performs a comparison of the pattern AST with + someNode. If the pattern AST does not contain any pattern nodes, the + match will be successful if the ASTs are syntactically identical + (whitespace/comments are not compared).
+   AnyNode will match any non-null node, and optionally store the + node it was matched against in a named capture group.
+   Backreference will match any node that is syntactically identical + to the node that was previously stored in the named capture group.
+   Repeat can be used only in AstNodeCollections and will try to + match its child pattern against any number of nodes - this is + equivalent to * (Kleene star) in regular expressions.
+   OptionalNode will match null nodes, or will try to match its child + pattern against the node. OptionalNode can also be used in + AstNodeCollections, where it is equivalent to a Repeat with + MinCount=0 and MaxCount=1.
+
+ The resulting match object can also be used to retrieve the nodes + stored in the capture groups:
+ if (m.Success) {
+     m.Get<AstType>("type").Single().ReplaceWith(new SimpleType("var"));
+ }
+
+ This feature was originally written for the decompiler in ILSpy, but + it is also very useful for refactorings. You can also implement + custom pattern nodes (derive from the Pattern base class) with + custom match logic - for example if you want to check the semantics + of a node.
+ \ No newline at end of file diff --git a/doc/TODO b/doc/TODO index 0e9a61a365..f0a970df52 100644 --- a/doc/TODO +++ b/doc/TODO @@ -1,23 +1,17 @@  Parser: -- "extern alias" declarations -- "fixed int Field[100];" (fixed-size field declarations) -- support generics -- fix bugs (see currently ignored unit tests) - put newlines into the AST - add API to report errors - allow multithreaded parsing Resolver: - Tons of unit tests for TypeSystemConvertVisitor -- Lambda expressions -- Handle attributes - Port all #D resolver unit tests to NR - Port all MD resolver unit tests to NR +- Think about removing ParameterizedType and specializing the ITypeDefinition instead. Features: - Code Completion -- Find References - Extract Method refactoring For integration into SharpDevelop: