43 changed files with 1197 additions and 1391 deletions
@ -0,0 +1,86 @@
@@ -0,0 +1,86 @@
|
||||
// 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; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp.TypeSystem |
||||
{ |
||||
public sealed class CSharpTypeResolveContext : ITypeResolveContext |
||||
{ |
||||
readonly IAssembly assembly; |
||||
readonly UsingScope currentUsingScope; |
||||
readonly ITypeDefinition currentTypeDefinition; |
||||
readonly IMember currentMember; |
||||
|
||||
public CSharpTypeResolveContext(IAssembly assembly, UsingScope usingScope = null, ITypeDefinition typeDefinition = null, IMember member = null) |
||||
{ |
||||
if (assembly == null) |
||||
throw new ArgumentNullException("assembly"); |
||||
this.assembly = assembly; |
||||
this.currentUsingScope = usingScope; |
||||
this.currentTypeDefinition = typeDefinition; |
||||
this.currentMember = member; |
||||
} |
||||
|
||||
public UsingScope CurrentUsingScope { |
||||
get { return currentUsingScope; } |
||||
} |
||||
|
||||
public ICompilation Compilation { |
||||
get { return assembly.Compilation; } |
||||
} |
||||
|
||||
public IAssembly CurrentAssembly { |
||||
get { return assembly; } |
||||
} |
||||
|
||||
public ITypeDefinition CurrentTypeDefinition { |
||||
get { return currentTypeDefinition; } |
||||
} |
||||
|
||||
public IMember CurrentMember { |
||||
get { return currentMember; } |
||||
} |
||||
|
||||
public CSharpTypeResolveContext WithCurrentTypeDefinition(ITypeDefinition typeDefinition) |
||||
{ |
||||
return new CSharpTypeResolveContext(assembly, currentUsingScope, typeDefinition, currentMember); |
||||
} |
||||
|
||||
ITypeResolveContext ITypeResolveContext.WithCurrentTypeDefinition(ITypeDefinition typeDefinition) |
||||
{ |
||||
return WithCurrentTypeDefinition(typeDefinition); |
||||
} |
||||
|
||||
public CSharpTypeResolveContext WithCurrentMember(IMember member) |
||||
{ |
||||
return new CSharpTypeResolveContext(assembly, currentUsingScope, currentTypeDefinition, member); |
||||
} |
||||
|
||||
ITypeResolveContext ITypeResolveContext.WithCurrentMember(IMember member) |
||||
{ |
||||
return WithCurrentMember(member); |
||||
} |
||||
|
||||
public CSharpTypeResolveContext WithUsingScope(UsingScope usingScope) |
||||
{ |
||||
return new CSharpTypeResolveContext(assembly, usingScope, currentTypeDefinition, currentMember); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
// 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; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp.TypeSystem |
||||
{ |
||||
[Serializable] |
||||
public class CSharpUnresolvedTypeDefinition : DefaultUnresolvedTypeDefinition |
||||
{ |
||||
readonly UsingScope usingScope; |
||||
|
||||
public CSharpUnresolvedTypeDefinition(UsingScope usingScope, string name) |
||||
: base(usingScope.NamespaceName, name) |
||||
{ |
||||
this.usingScope = usingScope; |
||||
} |
||||
|
||||
public CSharpUnresolvedTypeDefinition(CSharpUnresolvedTypeDefinition declaringTypeDefinition, string name) |
||||
: base(declaringTypeDefinition, name) |
||||
{ |
||||
this.usingScope = declaringTypeDefinition.usingScope; |
||||
} |
||||
|
||||
public override ITypeResolveContext CreateResolveContext(ITypeResolveContext parentContext) |
||||
{ |
||||
return new CSharpTypeResolveContext(parentContext.CurrentAssembly, usingScope, parentContext.CurrentTypeDefinition); |
||||
} |
||||
} |
||||
} |
||||
@ -1,153 +0,0 @@
@@ -1,153 +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 |
||||
{ |
||||
/* |
||||
/// <summary>
|
||||
/// Type definition that represents a partial class with multiple parts.
|
||||
/// </summary>
|
||||
[Serializable] |
||||
public class CompoundTypeDefinition : DefaultTypeDefinition |
||||
{ |
||||
IList<ITypeDefinition> parts; |
||||
|
||||
private CompoundTypeDefinition(CompoundTypeDefinition declaringTypeDefinition, string name) |
||||
: base(declaringTypeDefinition, name) |
||||
{ |
||||
} |
||||
|
||||
private CompoundTypeDefinition(IParsedFile parsedFile, string ns, string name) |
||||
: base(parsedFile, ns, name) |
||||
{ |
||||
} |
||||
|
||||
private CompoundTypeDefinition(IProjectContent projectContent, string ns, string name) |
||||
: base(projectContent, ns, name) |
||||
{ |
||||
} |
||||
|
||||
protected override void FreezeInternal() |
||||
{ |
||||
parts = FreezeList(parts); |
||||
base.FreezeInternal(); |
||||
} |
||||
|
||||
public override IList<ITypeDefinitionPart> Parts { |
||||
get { return parts; } |
||||
} |
||||
|
||||
public override string Documentation { |
||||
get { return parts[0].Documentation; } |
||||
} |
||||
|
||||
public static ITypeDefinition Create(IList<ITypeDefinition> parts) |
||||
{ |
||||
if (parts == null || parts.Count == 0) |
||||
throw new ArgumentException("parts"); |
||||
|
||||
ITypeDefinition mainPart = parts[0]; |
||||
for (int i = 1; i < parts.Count; i++) { |
||||
if (PreferAsMainPart(parts[i], mainPart)) |
||||
mainPart = parts[i]; |
||||
} |
||||
if (parts.Count == 1) { |
||||
((DefaultTypeDefinition)mainPart).SetCompoundTypeDefinition(mainPart); |
||||
return mainPart; |
||||
} |
||||
|
||||
CompoundTypeDefinition compound; |
||||
if (mainPart.DeclaringTypeDefinition != null) { |
||||
throw new NotImplementedException("nested compound types not implemented"); |
||||
} else { |
||||
if (mainPart.ParsedFile != null) |
||||
compound = new CompoundTypeDefinition(mainPart.ParsedFile, mainPart.Namespace, mainPart.Name); |
||||
else |
||||
compound = new CompoundTypeDefinition(mainPart.ProjectContent, mainPart.Namespace, mainPart.Name); |
||||
} |
||||
compound.parts = parts; |
||||
compound.Kind = mainPart.Kind; |
||||
compound.Region = mainPart.Region; |
||||
compound.BodyRegion = mainPart.BodyRegion; |
||||
compound.TypeParameters.AddRange(mainPart.TypeParameters); |
||||
compound.IsSynthetic = mainPart.IsSynthetic; |
||||
compound.Accessibility = mainPart.Accessibility; |
||||
|
||||
bool allPartsFrozen = true; |
||||
foreach (DefaultTypeDefinition part in parts) { |
||||
compound.BaseTypes.AddRange(part.BaseTypes); |
||||
compound.Attributes.AddRange(part.Attributes); |
||||
compound.NestedTypes.AddRange(part.NestedTypes); |
||||
compound.Methods.AddRange(part.Methods); |
||||
compound.Properties.AddRange(part.Properties); |
||||
compound.Events.AddRange(part.Events); |
||||
compound.Fields.AddRange(part.Fields); |
||||
|
||||
if (part.IsAbstract) |
||||
compound.IsAbstract = true; |
||||
if (part.IsSealed) |
||||
compound.IsSealed = true; |
||||
if (part.IsShadowing) |
||||
compound.IsShadowing = true; |
||||
if (part.HasExtensionMethods) |
||||
compound.HasExtensionMethods = true; |
||||
if (part.AddDefaultConstructorIfRequired) |
||||
compound.AddDefaultConstructorIfRequired = true; |
||||
|
||||
// internal is the default, so use another part's accessibility until we find a non-internal accessibility
|
||||
if (compound.Accessibility == Accessibility.Internal) |
||||
compound.Accessibility = part.Accessibility; |
||||
|
||||
allPartsFrozen &= part.IsFrozen; |
||||
} |
||||
|
||||
if (allPartsFrozen) { |
||||
// If all parts are frozen, also freeze the compound typedef.
|
||||
compound.Freeze(); |
||||
} |
||||
// Publish the compound class via part.compoundTypeDefinition only after it has been frozen.
|
||||
foreach (DefaultTypeDefinition part in parts) { |
||||
part.SetCompoundTypeDefinition(compound); |
||||
} |
||||
|
||||
return compound; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets whether part1 should be preferred as main part over part2.
|
||||
/// </summary>
|
||||
static bool PreferAsMainPart(ITypeDefinition part1, ITypeDefinition part2) |
||||
{ |
||||
if (part1.IsSynthetic != part2.IsSynthetic) |
||||
return part2.IsSynthetic; // prefer non-synthetic part
|
||||
string file1 = part1.Region.FileName; |
||||
string file2 = part2.Region.FileName; |
||||
if ((file1 != null) != (file2 != null)) |
||||
return file1 != null; // prefer part with file name
|
||||
if (file1 != null && file2 != null) { |
||||
return file1.Length < file2.Length; // prefer shorter file name (file without Designer suffix)
|
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
*/ |
||||
} |
||||
@ -1,618 +0,0 @@
@@ -1,618 +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.Globalization; |
||||
using System.Linq; |
||||
using System.Runtime.CompilerServices; |
||||
using ICSharpCode.NRefactory.Utils; |
||||
|
||||
namespace ICSharpCode.NRefactory.TypeSystem.Implementation |
||||
{ |
||||
/* |
||||
[Serializable] |
||||
public class DefaultTypeDefinition : AbstractFreezable, ITypeDefinition, ITypeDefinitionPart |
||||
{ |
||||
readonly IProjectContent projectContent; |
||||
readonly IParsedFile parsedFile; |
||||
readonly DefaultTypeDefinition declaringTypeDefinition; |
||||
|
||||
string ns; |
||||
string name; |
||||
|
||||
IList<ITypeReference> baseTypes; |
||||
IList<ITypeParameter> typeParameters; |
||||
IList<ITypeDefinition> nestedTypes; |
||||
IList<IField> fields; |
||||
IList<IMethod> methods; |
||||
IList<IProperty> properties; |
||||
IList<IEvent> events; |
||||
IList<IAttribute> attributes; |
||||
|
||||
DomRegion region; |
||||
DomRegion bodyRegion; |
||||
|
||||
// 1 byte per enum + 2 bytes for flags
|
||||
TypeKind kind = TypeKind.Class; |
||||
Accessibility accessibility; |
||||
BitVector16 flags; |
||||
const ushort FlagSealed = 0x0001; |
||||
const ushort FlagAbstract = 0x0002; |
||||
const ushort FlagShadowing = 0x0004; |
||||
const ushort FlagSynthetic = 0x0008; |
||||
const ushort FlagAddDefaultConstructorIfRequired = 0x0010; |
||||
const ushort FlagHasExtensionMethods = 0x0020; |
||||
|
||||
protected override void FreezeInternal() |
||||
{ |
||||
baseTypes = FreezeList(baseTypes); |
||||
typeParameters = FreezeList(typeParameters); |
||||
nestedTypes = FreezeList(nestedTypes); |
||||
fields = FreezeList(fields); |
||||
methods = FreezeList(methods); |
||||
properties = FreezeList(properties); |
||||
events = FreezeList(events); |
||||
attributes = FreezeList(attributes); |
||||
base.FreezeInternal(); |
||||
} |
||||
|
||||
public DefaultTypeDefinition(ITypeDefinition declaringTypeDefinition, string name) |
||||
{ |
||||
if (declaringTypeDefinition == null) |
||||
throw new ArgumentNullException("declaringTypeDefinition"); |
||||
if (string.IsNullOrEmpty(name)) |
||||
throw new ArgumentException("name"); |
||||
this.projectContent = declaringTypeDefinition.ProjectContent; |
||||
this.parsedFile = declaringTypeDefinition.ParsedFile; |
||||
this.declaringTypeDefinition = declaringTypeDefinition; |
||||
|
||||
this.name = name; |
||||
this.ns = declaringTypeDefinition.Namespace; |
||||
} |
||||
|
||||
public DefaultTypeDefinition(IParsedFile parsedFile, string ns, string name) |
||||
{ |
||||
if (parsedFile == null) |
||||
throw new ArgumentNullException("parsedFile"); |
||||
if (string.IsNullOrEmpty(name)) |
||||
throw new ArgumentException("name"); |
||||
this.parsedFile = parsedFile; |
||||
this.projectContent = parsedFile.ProjectContent; |
||||
this.ns = ns ?? string.Empty; |
||||
this.name = name; |
||||
} |
||||
|
||||
public DefaultTypeDefinition(IProjectContent projectContent, string ns, string name) |
||||
{ |
||||
if (projectContent == null) |
||||
throw new ArgumentNullException("projectContent"); |
||||
if (string.IsNullOrEmpty(name)) |
||||
throw new ArgumentException("name"); |
||||
this.projectContent = projectContent; |
||||
this.ns = ns ?? string.Empty; |
||||
this.name = name; |
||||
} |
||||
|
||||
public TypeKind Kind { |
||||
get { return kind; } |
||||
set { |
||||
CheckBeforeMutation(); |
||||
kind = value; |
||||
} |
||||
} |
||||
|
||||
public bool? IsReferenceType(ITypeResolveContext context) |
||||
{ |
||||
switch (kind) { |
||||
case TypeKind.Class: |
||||
case TypeKind.Interface: |
||||
case TypeKind.Delegate: |
||||
return true; |
||||
case TypeKind.Enum: |
||||
case TypeKind.Struct: |
||||
return false; |
||||
default: |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
public IList<ITypeReference> BaseTypes { |
||||
get { |
||||
if (baseTypes == null) |
||||
baseTypes = new List<ITypeReference>(); |
||||
return baseTypes; |
||||
} |
||||
} |
||||
|
||||
public void ApplyInterningProvider(IInterningProvider provider) |
||||
{ |
||||
if (provider != null) { |
||||
ns = provider.Intern(ns); |
||||
name = provider.Intern(name); |
||||
baseTypes = provider.InternList(baseTypes); |
||||
typeParameters = provider.InternList(typeParameters); |
||||
attributes = provider.InternList(attributes); |
||||
} |
||||
} |
||||
|
||||
public IList<ITypeParameter> TypeParameters { |
||||
get { |
||||
if (typeParameters == null) |
||||
typeParameters = new List<ITypeParameter>(); |
||||
return typeParameters; |
||||
} |
||||
} |
||||
|
||||
public IList<ITypeDefinition> NestedTypes { |
||||
get { |
||||
if (nestedTypes == null) |
||||
nestedTypes = new List<ITypeDefinition>(); |
||||
return nestedTypes; |
||||
} |
||||
} |
||||
|
||||
public IList<IField> Fields { |
||||
get { |
||||
if (fields == null) |
||||
fields = new List<IField>(); |
||||
return fields; |
||||
} |
||||
} |
||||
|
||||
public IList<IProperty> Properties { |
||||
get { |
||||
if (properties == null) |
||||
properties = new List<IProperty>(); |
||||
return properties; |
||||
} |
||||
} |
||||
|
||||
public IList<IMethod> Methods { |
||||
get { |
||||
if (methods == null) |
||||
methods = new List<IMethod>(); |
||||
return methods; |
||||
} |
||||
} |
||||
|
||||
public IList<IEvent> Events { |
||||
get { |
||||
if (events == null) |
||||
events = new List<IEvent>(); |
||||
return events; |
||||
} |
||||
} |
||||
|
||||
public IEnumerable<IMember> Members { |
||||
get { |
||||
IEnumerable<IMember> members = this.Fields; |
||||
return members |
||||
.Concat(this.Properties) |
||||
.Concat(this.Methods) |
||||
.Concat(this.Events); |
||||
} |
||||
} |
||||
|
||||
[NonSerialized] |
||||
volatile string cachedFullName; |
||||
|
||||
public string FullName { |
||||
get { |
||||
string fullName = this.cachedFullName; |
||||
if (fullName == null) { |
||||
// Initialize the cache on demand. Because this might happen after the type definition gets frozen,
|
||||
// the initialization must be thread-safe.
|
||||
if (declaringTypeDefinition != null) { |
||||
fullName = declaringTypeDefinition.FullName + "." + this.name; |
||||
} else if (string.IsNullOrEmpty(ns)) { |
||||
fullName = this.name; |
||||
} else { |
||||
fullName = this.ns + "." + this.name; |
||||
} |
||||
this.cachedFullName = fullName; |
||||
} |
||||
return fullName; |
||||
} |
||||
} |
||||
|
||||
public string Name { |
||||
get { return this.name; } |
||||
} |
||||
|
||||
public string Namespace { |
||||
get { return this.ns; } |
||||
} |
||||
|
||||
public string ReflectionName { |
||||
get { |
||||
if (declaringTypeDefinition != null) { |
||||
int tpCount = this.TypeParameterCount - declaringTypeDefinition.TypeParameterCount; |
||||
string combinedName; |
||||
if (tpCount > 0) |
||||
combinedName = declaringTypeDefinition.ReflectionName + "+" + this.Name + "`" + tpCount.ToString(CultureInfo.InvariantCulture); |
||||
else |
||||
combinedName = declaringTypeDefinition.ReflectionName + "+" + this.Name; |
||||
return combinedName; |
||||
} else { |
||||
int tpCount = this.TypeParameterCount; |
||||
if (string.IsNullOrEmpty(ns)) { |
||||
if (tpCount > 0) |
||||
return this.Name + "`" + tpCount.ToString(CultureInfo.InvariantCulture); |
||||
else |
||||
return this.Name; |
||||
} else { |
||||
if (tpCount > 0) |
||||
return this.Namespace + "." + this.Name + "`" + tpCount.ToString(CultureInfo.InvariantCulture); |
||||
else |
||||
return this.Namespace + "." + this.Name; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
public int TypeParameterCount { |
||||
get { return typeParameters != null ? typeParameters.Count : 0; } |
||||
} |
||||
|
||||
public EntityType EntityType { |
||||
get { return EntityType.TypeDefinition; } |
||||
} |
||||
|
||||
public DomRegion Region { |
||||
get { return region; } |
||||
set { |
||||
CheckBeforeMutation(); |
||||
region = value; |
||||
} |
||||
} |
||||
|
||||
public DomRegion BodyRegion { |
||||
get { return bodyRegion; } |
||||
set { |
||||
CheckBeforeMutation(); |
||||
bodyRegion = value; |
||||
} |
||||
} |
||||
|
||||
public ITypeDefinition DeclaringTypeDefinition { |
||||
get { return declaringTypeDefinition; } |
||||
} |
||||
|
||||
public IType DeclaringType { |
||||
get { return declaringTypeDefinition; } |
||||
} |
||||
|
||||
public IList<IAttribute> Attributes { |
||||
get { |
||||
if (attributes == null) |
||||
attributes = new List<IAttribute>(); |
||||
return attributes; |
||||
} |
||||
} |
||||
|
||||
public virtual string Documentation { |
||||
get { |
||||
// To save memory, we don't store the documentation provider within the type,
|
||||
// but use our the project content as a documentation provider:
|
||||
IDocumentationProvider provider = 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 IsAbstract && IsSealed; } |
||||
} |
||||
|
||||
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 bool HasExtensionMethods { |
||||
get { return flags[FlagHasExtensionMethods]; } |
||||
set { |
||||
CheckBeforeMutation(); |
||||
flags[FlagHasExtensionMethods] = value; |
||||
} |
||||
} |
||||
|
||||
public IProjectContent ProjectContent { |
||||
get { return projectContent; } |
||||
} |
||||
|
||||
public IParsedFile ParsedFile { |
||||
get { return parsedFile; } |
||||
} |
||||
|
||||
public IEnumerable<IType> GetBaseTypes(ITypeResolveContext context) |
||||
{ |
||||
bool hasNonInterface = false; |
||||
if (baseTypes != null && kind != TypeKind.Enum) { |
||||
foreach (ITypeReference baseTypeRef in baseTypes) { |
||||
IType baseType = baseTypeRef.Resolve(context); |
||||
if (baseType.Kind != TypeKind.Interface) |
||||
hasNonInterface = true; |
||||
yield return baseType; |
||||
} |
||||
} |
||||
if (!hasNonInterface && !(this.Name == "Object" && this.Namespace == "System" && this.TypeParameterCount == 0)) { |
||||
string primitiveBaseType; |
||||
switch (kind) { |
||||
case TypeKind.Enum: |
||||
primitiveBaseType = "Enum"; |
||||
break; |
||||
case TypeKind.Struct: |
||||
case TypeKind.Void: |
||||
primitiveBaseType = "ValueType"; |
||||
break; |
||||
case TypeKind.Delegate: |
||||
primitiveBaseType = "Delegate"; |
||||
break; |
||||
default: |
||||
primitiveBaseType = "Object"; |
||||
break; |
||||
} |
||||
IType t = context.GetTypeDefinition("System", primitiveBaseType, 0, StringComparer.Ordinal); |
||||
if (t != null) |
||||
yield return t; |
||||
} |
||||
} |
||||
|
||||
public virtual IList<ITypeDefinitionPart> Parts { |
||||
get { |
||||
return new ITypeDefinitionPart[] { this }; |
||||
} |
||||
} |
||||
|
||||
IType ITypeReference.Resolve(ITypeResolveContext context) |
||||
{ |
||||
if (context == null) |
||||
throw new ArgumentNullException("context"); |
||||
return this; |
||||
} |
||||
|
||||
ITypeDefinition IType.GetDefinition() |
||||
{ |
||||
return this; |
||||
} |
||||
|
||||
public ITypeDefinition GetCompoundTypeDefinition(ITypeResolveContext context) |
||||
{ |
||||
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
|
||||
public IEnumerable<IType> GetNestedTypes(ITypeResolveContext context, Predicate<ITypeDefinition> filter = null, GetMemberOptions options = GetMemberOptions.None) |
||||
{ |
||||
const GetMemberOptions opt = GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions; |
||||
if ((options & opt) == opt) { |
||||
return ApplyFilter(this.NestedTypes, filter); |
||||
} else { |
||||
return GetMembersHelper.GetNestedTypes(this, context, filter, options); |
||||
} |
||||
} |
||||
|
||||
public IEnumerable<IType> GetNestedTypes(IList<IType> typeArguments, ITypeResolveContext context, Predicate<ITypeDefinition> filter = null, GetMemberOptions options = GetMemberOptions.None) |
||||
{ |
||||
return GetMembersHelper.GetNestedTypes(this, typeArguments, context, filter, options); |
||||
} |
||||
|
||||
public virtual IEnumerable<IMethod> GetMethods(ITypeResolveContext context, Predicate<IMethod> filter = null, GetMemberOptions options = GetMemberOptions.None) |
||||
{ |
||||
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { |
||||
return ApplyFilter(this.Methods, Utils.ExtensionMethods.And(m => !m.IsConstructor, filter)); |
||||
} else { |
||||
return GetMembersHelper.GetMethods(this, context, filter, options); |
||||
} |
||||
} |
||||
|
||||
public virtual IEnumerable<IMethod> GetMethods(IList<IType> typeArguments, ITypeResolveContext context, Predicate<IMethod> filter = null, GetMemberOptions options = GetMemberOptions.None) |
||||
{ |
||||
return GetMembersHelper.GetMethods(this, typeArguments, context, filter, options); |
||||
} |
||||
|
||||
public virtual IEnumerable<IMethod> GetConstructors(ITypeResolveContext context, Predicate<IMethod> filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers) |
||||
{ |
||||
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { |
||||
return GetConstructorsImpl(filter); |
||||
} else { |
||||
return GetMembersHelper.GetConstructors(this, context, filter, options); |
||||
} |
||||
} |
||||
|
||||
IEnumerable<IMethod> GetConstructorsImpl(Predicate<IMethod> filter) |
||||
{ |
||||
bool foundCtor = false; |
||||
foreach (IMethod m in this.Methods) { |
||||
if (m.IsConstructor && !m.IsStatic) { |
||||
foundCtor = true; |
||||
if (filter == null || filter(m)) { |
||||
yield return m; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (this.AddDefaultConstructorIfRequired) { |
||||
if (kind == TypeKind.Class && !foundCtor && !this.IsStatic |
||||
|| kind == TypeKind.Enum || kind == TypeKind.Struct) |
||||
{ |
||||
var m = DefaultMethod.CreateDefaultConstructor(this); |
||||
if (filter == null || filter(m)) |
||||
yield return m; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public virtual IEnumerable<IProperty> GetProperties(ITypeResolveContext context, Predicate<IProperty> filter = null, GetMemberOptions options = GetMemberOptions.None) |
||||
{ |
||||
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { |
||||
return ApplyFilter(this.Properties, filter); |
||||
} else { |
||||
return GetMembersHelper.GetProperties(this, context, filter, options); |
||||
} |
||||
} |
||||
|
||||
public virtual IEnumerable<IField> GetFields(ITypeResolveContext context, Predicate<IField> filter = null, GetMemberOptions options = GetMemberOptions.None) |
||||
{ |
||||
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { |
||||
return ApplyFilter(this.Fields, filter); |
||||
} else { |
||||
return GetMembersHelper.GetFields(this, context, filter, options); |
||||
} |
||||
} |
||||
|
||||
public virtual IEnumerable<IEvent> GetEvents(ITypeResolveContext context, Predicate<IEvent> filter = null, GetMemberOptions options = GetMemberOptions.None) |
||||
{ |
||||
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { |
||||
return ApplyFilter(this.Events, filter); |
||||
} else { |
||||
return GetMembersHelper.GetEvents(this, context, filter, options); |
||||
} |
||||
} |
||||
|
||||
public virtual IEnumerable<IMember> GetMembers(ITypeResolveContext context, Predicate<IMember> filter = null, GetMemberOptions options = GetMemberOptions.None) |
||||
{ |
||||
return GetMembersHelper.GetMembers(this, context, filter, options); |
||||
} |
||||
|
||||
static IEnumerable<T> ApplyFilter<T>(IList<T> enumerable, Predicate<T> filter) where T : class |
||||
{ |
||||
if (enumerable.Count == 0) |
||||
return EmptyList<T>.Instance; |
||||
if (filter == null) |
||||
return enumerable; |
||||
else |
||||
return ApplyFilterImpl(enumerable, filter); |
||||
} |
||||
|
||||
static IEnumerable<T> ApplyFilterImpl<T>(IList<T> enumerable, Predicate<T> filter) where T : class |
||||
{ |
||||
foreach (T item in enumerable) |
||||
if (filter(item)) |
||||
yield return item; |
||||
} |
||||
#endregion
|
||||
|
||||
#region Equals / GetHashCode
|
||||
bool IEquatable<IType>.Equals(IType other) |
||||
{ |
||||
// Use reference equality for ITypeDefinitions:
|
||||
// We do not want to consider different versions of the same type as equal.
|
||||
return this == other; |
||||
} |
||||
#endregion
|
||||
|
||||
public override string ToString() |
||||
{ |
||||
return ReflectionName; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets whether a default constructor should be added to this class if it is required.
|
||||
/// Such automatic default constructors will not appear in ITypeDefinition.Methods, but will be present
|
||||
/// in IType.GetMethods().
|
||||
/// </summary>
|
||||
/// <remarks>This way of creating the default constructor is necessary because
|
||||
/// we cannot create it directly in the IClass - we need to consider partial classes.</remarks>
|
||||
public bool AddDefaultConstructorIfRequired { |
||||
get { return flags[FlagAddDefaultConstructorIfRequired]; } |
||||
set { |
||||
CheckBeforeMutation(); |
||||
flags[FlagAddDefaultConstructorIfRequired] = value; |
||||
} |
||||
} |
||||
|
||||
public IType AcceptVisitor(TypeVisitor visitor) |
||||
{ |
||||
return visitor.VisitTypeDefinition(this); |
||||
} |
||||
|
||||
public IType VisitChildren(TypeVisitor visitor) |
||||
{ |
||||
return this; |
||||
} |
||||
} |
||||
*/ |
||||
} |
||||
@ -0,0 +1,64 @@
@@ -0,0 +1,64 @@
|
||||
// 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 |
||||
{ |
||||
[Serializable] |
||||
public 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; |
||||
} |
||||
} |
||||
|
||||
[Serializable] |
||||
public sealed class FullNameAndTypeParameterCountComparer : IEqualityComparer<FullNameAndTypeParameterCount> |
||||
{ |
||||
public static readonly FullNameAndTypeParameterCountComparer Ordinal = new FullNameAndTypeParameterCountComparer(StringComparer.Ordinal); |
||||
public static readonly FullNameAndTypeParameterCountComparer OrdinalIgnoreCase = new FullNameAndTypeParameterCountComparer(StringComparer.OrdinalIgnoreCase); |
||||
|
||||
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; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,146 @@
@@ -0,0 +1,146 @@
|
||||
// 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.Utils; |
||||
|
||||
namespace ICSharpCode.NRefactory.TypeSystem.Implementation |
||||
{ |
||||
/// <summary>
|
||||
/// A merged namespace.
|
||||
/// </summary>
|
||||
public sealed class MergedNamespace : INamespace |
||||
{ |
||||
readonly string externAlias; |
||||
readonly ICompilation compilation; |
||||
readonly INamespace parentNamespace; |
||||
readonly INamespace[] namespaces; |
||||
Dictionary<string, INamespace> childNamespaces; |
||||
|
||||
/// <summary>
|
||||
/// Creates a new merged root namespace.
|
||||
/// </summary>
|
||||
/// <param name="namespaces">The individual namespaces being merged.</param>
|
||||
/// <param name="externAlias">The extern alias for this namespace.</param>
|
||||
public MergedNamespace(ICompilation compilation, INamespace[] namespaces, string externAlias = null) |
||||
{ |
||||
if (compilation == null) |
||||
throw new ArgumentNullException("compilation"); |
||||
if (namespaces == null) |
||||
throw new ArgumentNullException("namespaces"); |
||||
this.compilation = compilation; |
||||
this.namespaces = namespaces; |
||||
this.externAlias = externAlias; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Creates a new merged child namespace.
|
||||
/// </summary>
|
||||
/// <param name="parentNamespace">The parent merged namespace.</param>
|
||||
/// <param name="namespaces">The individual namespaces being merged.</param>
|
||||
public MergedNamespace(INamespace parentNamespace, INamespace[] namespaces) |
||||
{ |
||||
if (parentNamespace == null) |
||||
throw new ArgumentNullException("parentNamespace"); |
||||
if (namespaces == null) |
||||
throw new ArgumentNullException("namespaces"); |
||||
this.parentNamespace = parentNamespace; |
||||
this.namespaces = namespaces; |
||||
this.compilation = parentNamespace.Compilation; |
||||
this.externAlias = parentNamespace.ExternAlias; |
||||
} |
||||
|
||||
public string ExternAlias { |
||||
get { return externAlias; } |
||||
} |
||||
|
||||
public string FullName { |
||||
get { return namespaces[0].FullName; } |
||||
} |
||||
|
||||
public string Name { |
||||
get { return namespaces[0].Name; } |
||||
} |
||||
|
||||
public INamespace ParentNamespace { |
||||
get { return parentNamespace; } |
||||
} |
||||
|
||||
public IEnumerable<ITypeDefinition> Types { |
||||
get { |
||||
return namespaces.SelectMany(ns => ns.Types); |
||||
} |
||||
} |
||||
|
||||
public ICompilation Compilation { |
||||
get { return compilation; } |
||||
} |
||||
|
||||
public IEnumerable<INamespace> ChildNamespaces { |
||||
get { return GetChildNamespaces().Values; } |
||||
} |
||||
|
||||
public INamespace GetChildNamespace(string name) |
||||
{ |
||||
INamespace ns; |
||||
if (GetChildNamespaces().TryGetValue(name, out ns)) |
||||
return ns; |
||||
else |
||||
return null; |
||||
} |
||||
|
||||
Dictionary<string, INamespace> GetChildNamespaces() |
||||
{ |
||||
var result = this.childNamespaces; |
||||
if (result != null) { |
||||
LazyInit.ReadBarrier(); |
||||
return result; |
||||
} else { |
||||
result = new Dictionary<string, INamespace>(compilation.NameComparer); |
||||
foreach (var g in namespaces.SelectMany(ns => ns.ChildNamespaces).GroupBy(ns => ns.Name, compilation.NameComparer)) { |
||||
result.Add(g.Key, new MergedNamespace(this, g.ToArray())); |
||||
} |
||||
return LazyInit.GetOrSet(ref this.childNamespaces, result); |
||||
} |
||||
} |
||||
|
||||
public ITypeDefinition GetTypeDefinition(string name, int typeParameterCount) |
||||
{ |
||||
ITypeDefinition anyTypeDef = null; |
||||
foreach (var ns in namespaces) { |
||||
ITypeDefinition typeDef = ns.GetTypeDefinition(name, typeParameterCount); |
||||
if (typeDef != null) { |
||||
if (typeDef.IsPublic || (typeDef.IsInternal && typeDef.ParentAssembly.InternalsVisibleTo(compilation.MainAssembly))) { |
||||
// Prefer accessible types over non-accessible types.
|
||||
return typeDef; |
||||
} |
||||
anyTypeDef = typeDef; |
||||
} |
||||
} |
||||
return anyTypeDef; |
||||
} |
||||
|
||||
public override string ToString() |
||||
{ |
||||
return string.Format("[MergedNamespace {0}{1} (from {2} assemblies)]", externAlias != null ? externAlias + "::" : null, this.FullName, this.namespaces.Length); |
||||
} |
||||
} |
||||
} |
||||
@ -1,360 +0,0 @@
@@ -1,360 +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.Runtime.Serialization; |
||||
using System.Threading; |
||||
using ICSharpCode.NRefactory.Utils; |
||||
|
||||
namespace ICSharpCode.NRefactory.TypeSystem.Implementation |
||||
{ |
||||
/* |
||||
/// <summary>
|
||||
/// Simple <see cref="IProjectContent"/> implementation that stores the list of classes/namespaces.
|
||||
/// Synchronization is implemented using a <see cref="ReaderWriterLockSlim"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Compared with <see cref="TypeStorage"/>, this class adds support for the IProjectContent interface,
|
||||
/// for partial classes, and for multi-threading.
|
||||
/// </remarks>
|
||||
[Serializable] |
||||
public class SimpleProjectContent : AbstractAnnotatable, IProjectContent, ISerializable, IDeserializationCallback |
||||
{ |
||||
readonly TypeStorage types = new TypeStorage(); |
||||
readonly ReaderWriterLockSlim readerWriterLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); |
||||
readonly Dictionary<string, IParsedFile> fileDict = new Dictionary<string, IParsedFile>(Platform.FileNameComparer); |
||||
|
||||
#region Constructor
|
||||
/// <summary>
|
||||
/// Creates a new SimpleProjectContent instance.
|
||||
/// </summary>
|
||||
public SimpleProjectContent() |
||||
{ |
||||
} |
||||
#endregion
|
||||
|
||||
public virtual string AssemblyName { |
||||
get { return string.Empty; } |
||||
} |
||||
|
||||
#region AssemblyAttributes
|
||||
readonly List<IAttribute> assemblyAttributes = new List<IAttribute>(); // mutable assembly attribute storage
|
||||
readonly List<IAttribute> moduleAttributes = new List<IAttribute>(); |
||||
|
||||
volatile IAttribute[] readOnlyAssemblyAttributes = {}; // volatile field with copy for reading threads
|
||||
volatile IAttribute[] readOnlyModuleAttributes = {}; |
||||
|
||||
/// <inheritdoc/>
|
||||
public IList<IAttribute> AssemblyAttributes { |
||||
get { return readOnlyAssemblyAttributes; } |
||||
} |
||||
|
||||
/// <inheritdoc/>
|
||||
public IList<IAttribute> ModuleAttributes { |
||||
get { return readOnlyModuleAttributes; } |
||||
} |
||||
|
||||
static bool AddRemoveAttributes(ICollection<IAttribute> removedAttributes, ICollection<IAttribute> addedAttributes, |
||||
List<IAttribute> attributeStorage) |
||||
{ |
||||
// API uses ICollection instead of IEnumerable to discourage users from evaluating
|
||||
// the list inside the lock (this method is called inside the write lock)
|
||||
// [[not an issue anymore; the user now passes IParsedFile]]
|
||||
bool hasChanges = false; |
||||
if (removedAttributes != null && removedAttributes.Count > 0) { |
||||
if (attributeStorage.RemoveAll(removedAttributes.Contains) > 0) |
||||
hasChanges = true; |
||||
} |
||||
if (addedAttributes != null) { |
||||
attributeStorage.AddRange(addedAttributes); |
||||
hasChanges = true; |
||||
} |
||||
return hasChanges; |
||||
} |
||||
|
||||
void AddRemoveAssemblyAttributes(ICollection<IAttribute> removedAttributes, ICollection<IAttribute> addedAttributes) |
||||
{ |
||||
if (AddRemoveAttributes(removedAttributes, addedAttributes, assemblyAttributes)) |
||||
readOnlyAssemblyAttributes = assemblyAttributes.ToArray(); |
||||
} |
||||
|
||||
void AddRemoveModuleAttributes(ICollection<IAttribute> removedAttributes, ICollection<IAttribute> addedAttributes) |
||||
{ |
||||
if (AddRemoveAttributes(removedAttributes, addedAttributes, moduleAttributes)) |
||||
readOnlyModuleAttributes = moduleAttributes.ToArray(); |
||||
} |
||||
#endregion
|
||||
|
||||
#region AddType
|
||||
void AddType(ITypeDefinition typeDefinition) |
||||
{ |
||||
if (typeDefinition == null) |
||||
throw new ArgumentNullException("typeDefinition"); |
||||
if (typeDefinition.ProjectContent != this) |
||||
throw new ArgumentException("Cannot add a type definition that belongs to another project content"); |
||||
|
||||
ITypeDefinition existingTypeDef = types.GetTypeDefinition(typeDefinition.Namespace, typeDefinition.Name, typeDefinition.TypeParameterCount, StringComparer.Ordinal); |
||||
if (existingTypeDef != null) { |
||||
// Add a part to a compound class
|
||||
var newParts = new List<ITypeDefinition>(existingTypeDef.GetParts()); |
||||
newParts.Add(typeDefinition); |
||||
types.UpdateType(CompoundTypeDefinition.Create(newParts)); |
||||
} else { |
||||
types.UpdateType(typeDefinition); |
||||
} |
||||
} |
||||
#endregion
|
||||
|
||||
#region RemoveType
|
||||
void RemoveType(ITypeDefinition typeDefinition) |
||||
{ |
||||
var compoundTypeDef = typeDefinition.GetDefinition() as CompoundTypeDefinition; |
||||
if (compoundTypeDef != null) { |
||||
// Remove one part from a compound class
|
||||
var newParts = new List<ITypeDefinition>(compoundTypeDef.GetParts()); |
||||
// We cannot use newParts.Remove() because we need to use reference equality
|
||||
for (int i = 0; i < newParts.Count; i++) { |
||||
if (newParts[i] == typeDefinition) { |
||||
newParts.RemoveAt(i); |
||||
((DefaultTypeDefinition)typeDefinition).SetCompoundTypeDefinition(typeDefinition); |
||||
break; |
||||
} |
||||
} |
||||
types.UpdateType(CompoundTypeDefinition.Create(newParts)); |
||||
} else { |
||||
types.RemoveType(typeDefinition); |
||||
} |
||||
} |
||||
#endregion
|
||||
|
||||
#region UpdateProjectContent
|
||||
/// <summary>
|
||||
/// Removes types and attributes from oldFile from the project, and adds those from newFile.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The update is done inside a write lock; when other threads access this project content
|
||||
/// from within a <c>using (Synchronize())</c> block, they will not see intermediate (inconsistent) state.
|
||||
/// </remarks>
|
||||
public void UpdateProjectContent(IParsedFile oldFile, IParsedFile newFile) |
||||
{ |
||||
if (oldFile != null && newFile != null) { |
||||
if (!Platform.FileNameComparer.Equals(oldFile.FileName, newFile.FileName)) |
||||
throw new ArgumentException("When both oldFile and newFile are specified, they must use the same file name."); |
||||
} |
||||
readerWriterLock.EnterWriteLock(); |
||||
try { |
||||
if (oldFile != null) { |
||||
foreach (var element in oldFile.TopLevelTypeDefinitions) { |
||||
RemoveType(element); |
||||
} |
||||
if (newFile == null) { |
||||
fileDict.Remove(oldFile.FileName); |
||||
} |
||||
} |
||||
if (newFile != null) { |
||||
foreach (var element in newFile.TopLevelTypeDefinitions) { |
||||
AddType(element); |
||||
} |
||||
fileDict[newFile.FileName] = newFile; |
||||
} |
||||
AddRemoveAssemblyAttributes(oldFile != null ? oldFile.AssemblyAttributes : null, |
||||
newFile != null ? newFile.AssemblyAttributes : null); |
||||
|
||||
AddRemoveModuleAttributes(oldFile != null ? oldFile.ModuleAttributes : null, |
||||
newFile != null ? newFile.ModuleAttributes : null); |
||||
} finally { |
||||
readerWriterLock.ExitWriteLock(); |
||||
} |
||||
} |
||||
#endregion
|
||||
|
||||
#region IProjectContent implementation
|
||||
public ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode) |
||||
{ |
||||
readerWriterLock.EnterReadLock(); |
||||
try { |
||||
return types.GetKnownTypeDefinition(typeCode); |
||||
} finally { |
||||
readerWriterLock.ExitReadLock(); |
||||
} |
||||
} |
||||
|
||||
public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) |
||||
{ |
||||
readerWriterLock.EnterReadLock(); |
||||
try { |
||||
return types.GetTypeDefinition(nameSpace, name, typeParameterCount, nameComparer); |
||||
} finally { |
||||
readerWriterLock.ExitReadLock(); |
||||
} |
||||
} |
||||
|
||||
public IEnumerable<ITypeDefinition> GetTypes() |
||||
{ |
||||
readerWriterLock.EnterReadLock(); |
||||
try { |
||||
// make a copy with ToArray() for thread-safe access
|
||||
return types.GetTypes().ToArray(); |
||||
} finally { |
||||
readerWriterLock.ExitReadLock(); |
||||
} |
||||
} |
||||
|
||||
public IEnumerable<ITypeDefinition> GetTypes(string nameSpace, StringComparer nameComparer) |
||||
{ |
||||
readerWriterLock.EnterReadLock(); |
||||
try { |
||||
// make a copy with ToArray() for thread-safe access
|
||||
return types.GetTypes(nameSpace, nameComparer).ToArray(); |
||||
} finally { |
||||
readerWriterLock.ExitReadLock(); |
||||
} |
||||
} |
||||
|
||||
public IEnumerable<string> GetNamespaces() |
||||
{ |
||||
readerWriterLock.EnterReadLock(); |
||||
try { |
||||
// make a copy with ToArray() for thread-safe access
|
||||
return types.GetNamespaces().ToArray(); |
||||
} finally { |
||||
readerWriterLock.ExitReadLock(); |
||||
} |
||||
} |
||||
|
||||
public string GetNamespace(string nameSpace, StringComparer nameComparer) |
||||
{ |
||||
readerWriterLock.EnterReadLock(); |
||||
try { |
||||
return types.GetNamespace(nameSpace, nameComparer); |
||||
} finally { |
||||
readerWriterLock.ExitReadLock(); |
||||
} |
||||
} |
||||
|
||||
public IParsedFile GetFile(string fileName) |
||||
{ |
||||
readerWriterLock.EnterReadLock(); |
||||
try { |
||||
IParsedFile file; |
||||
if (fileDict.TryGetValue(fileName, out file)) |
||||
return file; |
||||
else |
||||
return null; |
||||
} finally { |
||||
readerWriterLock.ExitReadLock(); |
||||
} |
||||
} |
||||
|
||||
public IEnumerable<IParsedFile> Files { |
||||
get { |
||||
readerWriterLock.EnterReadLock(); |
||||
try { |
||||
return fileDict.Values.ToArray(); |
||||
} finally { |
||||
readerWriterLock.ExitReadLock(); |
||||
} |
||||
} |
||||
} |
||||
#endregion
|
||||
|
||||
#region Synchronization
|
||||
public CacheManager CacheManager { |
||||
get { return null; } |
||||
} |
||||
|
||||
public ISynchronizedTypeResolveContext Synchronize() |
||||
{ |
||||
// don't acquire the lock on OutOfMemoryException etc.
|
||||
ISynchronizedTypeResolveContext sync = new ReadWriteSynchronizedTypeResolveContext(types, readerWriterLock); |
||||
readerWriterLock.EnterReadLock(); |
||||
return sync; |
||||
} |
||||
|
||||
sealed class ReadWriteSynchronizedTypeResolveContext : ProxyTypeResolveContext, ISynchronizedTypeResolveContext |
||||
{ |
||||
ReaderWriterLockSlim readerWriterLock; |
||||
|
||||
public ReadWriteSynchronizedTypeResolveContext(ITypeResolveContext target, ReaderWriterLockSlim readerWriterLock) |
||||
: base(target) |
||||
{ |
||||
this.readerWriterLock = readerWriterLock; |
||||
} |
||||
|
||||
public void Dispose() |
||||
{ |
||||
if (readerWriterLock != null) { |
||||
readerWriterLock.ExitReadLock(); |
||||
readerWriterLock = null; |
||||
} |
||||
} |
||||
|
||||
public override ISynchronizedTypeResolveContext Synchronize() |
||||
{ |
||||
// nested Synchronize() calls don't need any locking
|
||||
return new ReadWriteSynchronizedTypeResolveContext(target, null); |
||||
} |
||||
} |
||||
#endregion
|
||||
|
||||
#region Serialization
|
||||
SerializationInfo serializationInfo; |
||||
|
||||
protected SimpleProjectContent(SerializationInfo info, StreamingContext context) |
||||
{ |
||||
this.serializationInfo = info; |
||||
assemblyAttributes.AddRange((IAttribute[])info.GetValue("AssemblyAttributes", typeof(IAttribute[]))); |
||||
readOnlyAssemblyAttributes = assemblyAttributes.ToArray(); |
||||
moduleAttributes.AddRange((IAttribute[])info.GetValue("ModuleAttributes", typeof(IAttribute[]))); |
||||
readOnlyModuleAttributes = moduleAttributes.ToArray(); |
||||
} |
||||
|
||||
public virtual void OnDeserialization(object sender) |
||||
{ |
||||
// We need to do this in OnDeserialization because at the time the deserialization
|
||||
// constructor runs, type.FullName/file.FileName may not be deserialized yet.
|
||||
if (serializationInfo != null) { |
||||
foreach (var typeDef in (ITypeDefinition[])serializationInfo.GetValue("Types", typeof(ITypeDefinition[]))) { |
||||
types.UpdateType(typeDef); |
||||
} |
||||
foreach (IParsedFile file in (IParsedFile[])serializationInfo.GetValue("Files", typeof(IParsedFile[]))) { |
||||
fileDict.Add(file.FileName, file); |
||||
} |
||||
serializationInfo = null; |
||||
} |
||||
} |
||||
|
||||
public virtual void GetObjectData(SerializationInfo info, StreamingContext context) |
||||
{ |
||||
readerWriterLock.EnterReadLock(); |
||||
try { |
||||
info.AddValue("Types", types.GetTypes().ToArray()); |
||||
info.AddValue("AssemblyAttributes", readOnlyAssemblyAttributes); |
||||
info.AddValue("ModuleAttributes", readOnlyModuleAttributes); |
||||
info.AddValue("Files", fileDict.Values.ToArray()); |
||||
} finally { |
||||
readerWriterLock.ExitReadLock(); |
||||
} |
||||
} |
||||
#endregion
|
||||
} |
||||
*/ |
||||
} |
||||
Loading…
Reference in new issue