Browse Source

Add IParsedFile to type system.

newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
94b4130aa9
  1. 2
      ICSharpCode.NRefactory.Demo/CSDemo.cs
  2. 5
      ICSharpCode.NRefactory/CSharp/Analysis/MinimalResolveContext.cs
  3. 40
      ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs
  4. 49
      ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs
  5. 2
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
  6. 5
      ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs
  7. 53
      ICSharpCode.NRefactory/TypeSystem/IParsedFile.cs
  8. 14
      ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs
  9. 44
      ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs
  10. 25
      ICSharpCode.NRefactory/Utils/Platform.cs

2
ICSharpCode.NRefactory.Demo/CSDemo.cs

@ -180,7 +180,7 @@ namespace ICSharpCode.NRefactory.Demo @@ -180,7 +180,7 @@ namespace ICSharpCode.NRefactory.Demo
SimpleProjectContent project = new SimpleProjectContent();
TypeSystemConvertVisitor convertVisitor = new TypeSystemConvertVisitor(project, "dummy.cs");
compilationUnit.AcceptVisitor(convertVisitor, null);
project.UpdateProjectContent(null, convertVisitor.ParsedFile.TopLevelTypeDefinitions, null, null);
project.UpdateProjectContent(null, convertVisitor.ParsedFile);
List<ITypeResolveContext> projects = new List<ITypeResolveContext>();
projects.Add(project);

5
ICSharpCode.NRefactory/CSharp/Analysis/MinimalResolveContext.cs

@ -112,5 +112,10 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -112,5 +112,10 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
{
// exit from Synchronize() block
}
IParsedFile IProjectContent.GetFile(string fileName)
{
return null;
}
}
}

40
ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs

@ -12,7 +12,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -12,7 +12,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// <summary>
/// Represents a file that was parsed and converted for the type system.
/// </summary>
public sealed class ParsedFile : AbstractFreezable
public sealed class ParsedFile : AbstractFreezable, IParsedFile
{
readonly string fileName;
readonly UsingScope rootUsingScope;
@ -51,6 +51,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -51,6 +51,10 @@ namespace ICSharpCode.NRefactory.CSharp
get { return usingScopes; }
}
public IProjectContent ProjectContent {
get { return rootUsingScope.ProjectContent; }
}
public IList<ITypeDefinition> TopLevelTypeDefinitions {
get { return topLevelTypeDefinitions; }
}
@ -70,9 +74,37 @@ namespace ICSharpCode.NRefactory.CSharp @@ -70,9 +74,37 @@ namespace ICSharpCode.NRefactory.CSharp
public ITypeDefinition GetTopLevelTypeDefinition(AstLocation location)
{
foreach (ITypeDefinition typeDef in topLevelTypeDefinitions) {
if (typeDef.Region.IsInside(location.Line, location.Column))
return typeDef;
return FindEntity(topLevelTypeDefinitions, location);
}
public ITypeDefinition GetTypeDefinition(AstLocation location)
{
ITypeDefinition parent = null;
ITypeDefinition type = GetTopLevelTypeDefinition(location);
while (type != null) {
parent = type;
type = FindEntity(parent.InnerClasses, location);
}
return parent;
}
public IMember GetMember(AstLocation location)
{
ITypeDefinition type = GetTypeDefinition(location);
if (type == null)
return null;
return FindEntity(type.Methods, location)
?? FindEntity(type.Fields, location)
?? FindEntity(type.Properties, location)
?? (IMember)FindEntity(type.Events, location);
}
static T FindEntity<T>(IList<T> list, AstLocation location) where T : class, IEntity
{
// This could be improved using a binary search
foreach (T entity in list) {
if (entity.Region.IsInside(location.Line, location.Column))
return entity;
}
return null;
}

49
ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs

@ -116,8 +116,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -116,8 +116,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (typeDef.DeclaringTypeDefinition != null) {
// Handle nested types
result.Target = ConvertTypeDefinition(typeDef.DeclaringTypeDefinition, typeArguments);
result.MemberName = typeDef.Name;
AddTypeArguments(result, typeArguments, OuterTypeParameterCount(typeDef), typeDef.TypeParameterCount);
} else {
// Handle top-level types
if (string.IsNullOrEmpty(typeDef.Namespace)) {
@ -126,9 +124,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -126,9 +124,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
} else {
result.Target = ConvertNamespace(typeDef.Namespace);
}
result.MemberName = typeDef.Name;
AddTypeArguments(result, typeArguments, 0, typeDef.TypeParameterCount);
}
result.MemberName = typeDef.Name;
AddTypeArguments(result, typeArguments, OuterTypeParameterCount(typeDef), typeDef.TypeParameterCount);
return result;
}
@ -173,24 +171,37 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -173,24 +171,37 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
AstType ConvertNamespace(string ns)
{
string[] parts = ns.Split('.');
AstType result;
if (IsValidNamespace(parts[0])) {
result = new SimpleType(parts[0]);
} else {
result = new MemberType {
Target = new SimpleType("global"),
IsDoubleColon = true,
MemberName = parts[0]
};
if (resolver != null) {
// Look if there's an alias to the target namespace
for (UsingScope usingScope = resolver.UsingScope; 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)
return new SimpleType(pair.Key);
}
}
}
for (int i = 1; i < parts.Length; i++) {
result = new MemberType {
Target = result,
MemberName = parts[i]
int pos = ns.LastIndexOf('.');
if (pos < 0) {
if (IsValidNamespace(ns)) {
return new SimpleType(ns);
} else {
return new MemberType {
Target = new SimpleType("global"),
IsDoubleColon = true,
MemberName = ns
};
}
} else {
string parentNamespace = ns.Substring(0, pos);
string localNamespace = ns.Substring(pos + 1);
return new MemberType {
Target = ConvertNamespace(parentNamespace),
MemberName = localNamespace
};
}
return result;
}
bool IsValidNamespace(string firstNamespacePart)

2
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -255,6 +255,7 @@ @@ -255,6 +255,7 @@
<Compile Include="TypeSystem\IntersectionType.cs" />
<Compile Include="TypeSystem\IParameter.cs" />
<Compile Include="TypeSystem\IParameterizedMember.cs" />
<Compile Include="TypeSystem\IParsedFile.cs" />
<Compile Include="TypeSystem\IProjectContent.cs" />
<Compile Include="TypeSystem\IProperty.cs" />
<Compile Include="TypeSystem\ISupportsInterning.cs" />
@ -330,6 +331,7 @@ @@ -330,6 +331,7 @@
<Compile Include="Utils\EmptyList.cs" />
<Compile Include="Utils\ExtensionMethods.cs" />
<Compile Include="Utils\GraphVizGraph.cs" />
<Compile Include="Utils\Platform.cs" />
<Compile Include="Utils\TreeTraversal.cs" />
<Compile Include="CSharp\Ast\ComposedType.cs" />
<Compile Include="CSharp\Ast\Expressions\DirectionExpression.cs" />

5
ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

@ -151,6 +151,11 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -151,6 +151,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
// Disposing the synchronization context has no effect
}
public IParsedFile GetFile(string fileName)
{
return null;
}
string IDocumentationProvider.GetDocumentation(IEntity entity)
{
if (documentationProvider != null)

53
ICSharpCode.NRefactory/TypeSystem/IParsedFile.cs

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT license (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.CSharp;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Represents a single file that was parsed.
/// </summary>
public interface IParsedFile : IFreezable
{
/// <summary>
/// Gets the parent project content.
/// </summary>
IProjectContent ProjectContent { get; }
/// <summary>
/// Returns the full path of the file.
/// </summary>
string FileName { get; }
/// <summary>
/// Gets all top-level type definitions.
/// </summary>
IList<ITypeDefinition> TopLevelTypeDefinitions { get; }
/// <summary>
/// Gets all assembly attributes that are defined in this file.
/// </summary>
IList<IAttribute> AssemblyAttributes { get; }
/// <summary>
/// Gets the top-level type defined at the specified location.
/// Returns null if no type is defined at that location.
/// </summary>
ITypeDefinition GetTopLevelTypeDefinition(AstLocation location);
/// <summary>
/// Gets the type (potentially a nested type) defined at the specified location.
/// Returns null if no type is defined at that location.
/// </summary>
ITypeDefinition GetTypeDefinition(AstLocation location);
/// <summary>
/// Gets the member defined at the specified location.
/// Returns null if no member is defined at that location.
/// </summary>
IMember GetMember(AstLocation location);
}
}

14
ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs

@ -15,7 +15,15 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -15,7 +15,15 @@ namespace ICSharpCode.NRefactory.TypeSystem
#endif
public interface IProjectContent : ITypeResolveContext
{
/// <summary>
/// Gets the list of all assembly attributes in the project.
/// </summary>
IList<IAttribute> AssemblyAttributes { get; }
/// <summary>
/// Gets a parsed file by its file name.
/// </summary>
IParsedFile GetFile(string fileName);
}
#if WITH_CONTRACTS
@ -28,6 +36,12 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -28,6 +36,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
return null;
}
}
IParsedFile IProjectContent.GetFile(string fileName)
{
Contract.Requires(fileName != null);
return;
}
}
#endif
}

44
ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs

@ -27,6 +27,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -27,6 +27,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
readonly TypeStorage types = new TypeStorage();
readonly ReaderWriterLockSlim readerWriterLock = new ReaderWriterLockSlim();
readonly Dictionary<string, IParsedFile> fileDict = new Dictionary<string, IParsedFile>(Platform.FileNameComparer);
#region AssemblyAttributes
readonly List<IAttribute> assemblyAttributes = new List<IAttribute>(); // mutable assembly attribute storage
@ -35,13 +36,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -35,13 +36,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
/// <inheritdoc/>
public IList<IAttribute> AssemblyAttributes {
get { return readOnlyAssemblyAttributes; }
get { return readOnlyAssemblyAttributes; }
}
void AddRemoveAssemblyAttributes(ICollection<IAttribute> addedAttributes, ICollection<IAttribute> removedAttributes)
{
// 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 (assemblyAttributes.RemoveAll(removedAttributes.Contains) > 0)
@ -80,31 +82,35 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -80,31 +82,35 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
#region UpdateProjectContent
/// <summary>
/// Removes oldTypes from the project, adds newTypes.
/// Removes oldAssemblyAttributes, adds newAssemblyAttributes.
/// 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(ICollection<ITypeDefinition> oldTypes = null,
ICollection<ITypeDefinition> newTypes = null,
ICollection<IAttribute> oldAssemblyAttributes = null,
ICollection<IAttribute> newAssemblyAttributes = null)
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 (oldTypes != null) {
foreach (var element in oldTypes) {
if (oldFile != null) {
foreach (var element in oldFile.TopLevelTypeDefinitions) {
RemoveType(element);
}
if (newFile == null) {
fileDict.Remove(oldFile.FileName);
}
}
if (newTypes != null) {
foreach (var element in newTypes) {
if (newFile != null) {
foreach (var element in newFile.TopLevelTypeDefinitions) {
AddType(element);
}
fileDict[newFile.FileName] = newFile;
}
AddRemoveAssemblyAttributes(oldAssemblyAttributes, newAssemblyAttributes);
AddRemoveAssemblyAttributes(oldFile != null ? oldFile.AssemblyAttributes : null, newFile != null ? newFile.AssemblyAttributes : null);
} finally {
readerWriterLock.ExitWriteLock();
}
@ -164,6 +170,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -164,6 +170,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
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();
}
}
#endregion
#region Synchronization

25
ICSharpCode.NRefactory/Utils/Platform.cs

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT license (for details please see \doc\license.txt)
using System;
namespace ICSharpCode.NRefactory.Utils
{
/// <summary>
/// Platform-specific code.
/// </summary>
static class Platform
{
public static StringComparer FileNameComparer {
get {
switch (Environment.OSVersion.Platform) {
case PlatformID.Unix:
case PlatformID.MacOSX:
return StringComparer.Ordinal;
default:
return StringComparer.OrdinalIgnoreCase;
}
}
}
}
}
Loading…
Cancel
Save