Browse Source

ResourceToolkit:

Added ResourceSetReference as a level of abstraction between manifest resource names (or other resource set names) and actual resource files.
The resolvers now return a ResourceSetReference with the resolved resource set name even if the resource file is missing. This may be used in the future to detect missing resource files and to write unit tests for the resolvers without having to create resource files on disk.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2127 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Christian Hornung 19 years ago
parent
commit
0c41adf008
  1. 1
      src/AddIns/Misc/ResourceToolkit/Project/ResourceToolkit.csproj
  2. 18
      src/AddIns/Misc/ResourceToolkit/Project/Src/CodeCompletion/AbstractNRefactoryResourceCodeCompletionBinding.cs
  3. 23
      src/AddIns/Misc/ResourceToolkit/Project/Src/CodeCompletion/ICSharpCodeCoreResourceCodeCompletionBinding.cs
  4. 2
      src/AddIns/Misc/ResourceToolkit/Project/Src/Gui/UnusedResourceKeysCommands.cs
  5. 78
      src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/BclNRefactoryResourceResolver.cs
  6. 26
      src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/ICSharpCodeCoreNRefactoryResourceResolver.cs
  7. 115
      src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/ICSharpCodeCoreResourceResolver.cs
  8. 28
      src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/NRefactoryResourceResolver.cs
  9. 42
      src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/ResourceResolveResult.cs
  10. 73
      src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/ResourceSetReference.cs

1
src/AddIns/Misc/ResourceToolkit/Project/ResourceToolkit.csproj

@ -70,6 +70,7 @@
<Compile Include="Src\Resolver\PositionTrackingAstVisitor.cs" /> <Compile Include="Src\Resolver\PositionTrackingAstVisitor.cs" />
<Compile Include="Src\Resolver\PropertyFieldAssociationVisitor.cs" /> <Compile Include="Src\Resolver\PropertyFieldAssociationVisitor.cs" />
<Compile Include="Src\Resolver\ResourceResolveResult.cs" /> <Compile Include="Src\Resolver\ResourceResolveResult.cs" />
<Compile Include="Src\Resolver\ResourceSetReference.cs" />
<Compile Include="Src\ResourceFileContent\DefaultBclResourceFileContentFactory.cs" /> <Compile Include="Src\ResourceFileContent\DefaultBclResourceFileContentFactory.cs" />
<Compile Include="Src\ResourceFileContent\DefaultFileLocalizedResourcesFinder.cs" /> <Compile Include="Src\ResourceFileContent\DefaultFileLocalizedResourcesFinder.cs" />
<Compile Include="Src\ResourceFileContent\ILocalizedResourcesFinder.cs" /> <Compile Include="Src\ResourceFileContent\ILocalizedResourcesFinder.cs" />

18
src/AddIns/Misc/ResourceToolkit/Project/Src/CodeCompletion/AbstractNRefactoryResourceCodeCompletionBinding.cs

@ -7,6 +7,7 @@
using System; using System;
using Hornung.ResourceToolkit.Resolver; using Hornung.ResourceToolkit.Resolver;
using Hornung.ResourceToolkit.ResourceFileContent;
using ICSharpCode.NRefactory.PrettyPrinter; using ICSharpCode.NRefactory.PrettyPrinter;
using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor;
@ -25,8 +26,21 @@ namespace Hornung.ResourceToolkit.CodeCompletion
ResourceResolveResult result = ResourceResolverService.Resolve(editor, ch); ResourceResolveResult result = ResourceResolverService.Resolve(editor, ch);
if (result != null) { if (result != null) {
if (result.ResourceFileContent != null) { IResourceFileContent content;
editor.ShowCompletionWindow(new ResourceCodeCompletionDataProvider(result.ResourceFileContent, this.OutputVisitor, result.CallingClass != null ? result.CallingClass.Name+"." : null), ch); if ((content = result.ResourceFileContent) != null) {
// If the resolved resource set is the local ICSharpCode.Core resource set
// (this may happen through the ICSharpCodeCoreNRefactoryResourceResolver),
// we will have to merge in the host resource set (if available)
// for the code completion window.
if (result.ResourceSetReference.ResourceSetName == ICSharpCodeCoreResourceResolver.ICSharpCodeCoreLocalResourceSetName) {
IResourceFileContent hostContent = ICSharpCodeCoreResourceResolver.GetICSharpCodeCoreHostResourceSet(editor.FileName).ResourceFileContent;
if (hostContent != null) {
content = new MergedResourceFileContent(content, new IResourceFileContent[] { hostContent });
}
}
editor.ShowCompletionWindow(new ResourceCodeCompletionDataProvider(content, this.OutputVisitor, result.CallingClass != null ? result.CallingClass.Name+"." : null), ch);
return true; return true;
} }
} }

23
src/AddIns/Misc/ResourceToolkit/Project/Src/CodeCompletion/ICSharpCodeCoreResourceCodeCompletionBinding.cs

@ -27,20 +27,17 @@ namespace Hornung.ResourceToolkit.CodeCompletion
if (editor.ActiveTextAreaControl.Caret.Offset >= 5 && editor.Document.GetText(editor.ActiveTextAreaControl.Caret.Offset-5, 5) == "${res") { if (editor.ActiveTextAreaControl.Caret.Offset >= 5 && editor.Document.GetText(editor.ActiveTextAreaControl.Caret.Offset-5, 5) == "${res") {
IResourceFileContent content = null; IResourceFileContent content = ICSharpCodeCoreResourceResolver.GetICSharpCodeCoreLocalResourceSet(editor.FileName).ResourceFileContent;
string localFile = ICSharpCodeCoreResourceResolver.GetICSharpCodeCoreLocalResourceFileName(editor.FileName); #if DEBUG
if (localFile != null) { if (content != null) {
#if DEBUG LoggingService.Debug("ResourceToolkit: Found local ICSharpCode.Core resource file: "+content.FileName);
LoggingService.Debug("ResourceToolkit: Found local ICSharpCode.Core resource file: "+localFile);
#endif
content = ResourceFileContentRegistry.GetResourceFileContent(localFile);
} }
#endif
IResourceFileContent hostContent; IResourceFileContent hostContent = ICSharpCodeCoreResourceResolver.GetICSharpCodeCoreHostResourceSet(editor.FileName).ResourceFileContent;
string hostFile = ICSharpCodeCoreResourceResolver.GetICSharpCodeCoreHostResourceFileName(editor.FileName); if (hostContent != null) {
if (hostFile != null && (hostContent = ResourceFileContentRegistry.GetResourceFileContent(hostFile)) != null) {
#if DEBUG #if DEBUG
LoggingService.Debug("ResourceToolkit: Found host ICSharpCode.Core resource file: "+hostFile); LoggingService.Debug("ResourceToolkit: Found host ICSharpCode.Core resource file: "+hostContent.FileName);
#endif #endif
if (content != null) { if (content != null) {
content = new MergedResourceFileContent(content, new IResourceFileContent[] { hostContent }); content = new MergedResourceFileContent(content, new IResourceFileContent[] { hostContent });
@ -60,8 +57,8 @@ namespace Hornung.ResourceToolkit.CodeCompletion
// Provide ${res: as code completion // Provide ${res: as code completion
// in an ICSharpCode.Core application // in an ICSharpCode.Core application
if (ICSharpCodeCoreResourceResolver.GetICSharpCodeCoreHostResourceFileName(editor.FileName) != null || if (ICSharpCodeCoreResourceResolver.GetICSharpCodeCoreHostResourceSet(editor.FileName).ResourceFileContent != null ||
ICSharpCodeCoreResourceResolver.GetICSharpCodeCoreLocalResourceFileName(editor.FileName) != null) { ICSharpCodeCoreResourceResolver.GetICSharpCodeCoreLocalResourceSet(editor.FileName).ResourceFileContent != null) {
editor.ShowCompletionWindow(new ICSharpCodeCoreTagCompletionDataProvider(), ch); editor.ShowCompletionWindow(new ICSharpCodeCoreTagCompletionDataProvider(), ch);
return true; return true;

2
src/AddIns/Misc/ResourceToolkit/Project/Src/Gui/UnusedResourceKeysCommands.cs

@ -25,7 +25,7 @@ namespace Hornung.ResourceToolkit.Gui
IFilterHost<ResourceItem> host = ((ToolBarCheckBox)this.Owner).Caller as IFilterHost<ResourceItem>; IFilterHost<ResourceItem> host = ((ToolBarCheckBox)this.Owner).Caller as IFilterHost<ResourceItem>;
if (host != null) { if (host != null) {
if (this.IsChecked) { if (this.IsChecked) {
this.icSharpCodeCoreHostResourceFileName = ICSharpCodeCoreResourceResolver.GetICSharpCodeCoreHostResourceFileName(null); this.icSharpCodeCoreHostResourceFileName = ICSharpCodeCoreResourceResolver.GetICSharpCodeCoreHostResourceSet(null).FileName;
host.RegisterFilter(this); host.RegisterFilter(this);
} else { } else {
host.UnregisterFilter(this); host.UnregisterFilter(this);

78
src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/BclNRefactoryResourceResolver.cs

@ -167,13 +167,13 @@ namespace Hornung.ResourceToolkit.Resolver
// ******************************************************************************************************************************** // ********************************************************************************************************************************
#region ResourceFileContent mapping cache #region ResourceSetReference mapping cache
static Dictionary<IMember, IResourceFileContent> cachedResourceFileContentMappings; static Dictionary<IMember, ResourceSetReference> cachedResourceSetReferenceMappings;
static BclNRefactoryResourceResolver() static BclNRefactoryResourceResolver()
{ {
cachedResourceFileContentMappings = new Dictionary<IMember, IResourceFileContent>(new MemberEqualityComparer()); cachedResourceSetReferenceMappings = new Dictionary<IMember, ResourceSetReference>(new MemberEqualityComparer());
NRefactoryAstCacheService.CacheEnabledChanged += NRefactoryCacheEnabledChanged; NRefactoryAstCacheService.CacheEnabledChanged += NRefactoryCacheEnabledChanged;
} }
@ -181,7 +181,7 @@ namespace Hornung.ResourceToolkit.Resolver
{ {
if (!NRefactoryAstCacheService.CacheEnabled) { if (!NRefactoryAstCacheService.CacheEnabled) {
// Clear cache when disabled. // Clear cache when disabled.
cachedResourceFileContentMappings.Clear(); cachedResourceSetReferenceMappings.Clear();
} }
} }
@ -199,48 +199,48 @@ namespace Hornung.ResourceToolkit.Resolver
/// </returns> /// </returns>
static ResourceResolveResult ResolveResource(ResolveResult resolveResult, Expression expr) static ResourceResolveResult ResolveResource(ResolveResult resolveResult, Expression expr)
{ {
IResourceFileContent rfc = null; ResourceSetReference rsr = null;
MemberResolveResult mrr = resolveResult as MemberResolveResult; MemberResolveResult mrr = resolveResult as MemberResolveResult;
if (mrr != null) { if (mrr != null) {
rfc = ResolveResourceFileContent(mrr.ResolvedMember); rsr = ResolveResourceSet(mrr.ResolvedMember);
} else { } else {
LocalResolveResult lrr = resolveResult as LocalResolveResult; LocalResolveResult lrr = resolveResult as LocalResolveResult;
if (lrr != null) { if (lrr != null) {
if (!lrr.IsParameter) { if (!lrr.IsParameter) {
rfc = ResolveResourceFileContent(lrr.Field); rsr = ResolveResourceSet(lrr.Field);
} }
} }
} }
if (rfc != null) { if (rsr != null) {
string key = GetKeyFromExpression(expr); string key = GetKeyFromExpression(expr);
// TODO: Add information about return type (of the resource, if present). // TODO: Add information about return type (of the resource, if present).
return new ResourceResolveResult(resolveResult.CallingClass, resolveResult.CallingMember, null, rfc, key); return new ResourceResolveResult(resolveResult.CallingClass, resolveResult.CallingMember, null, rsr, key);
} }
return null; return null;
} }
/// <summary> /// <summary>
/// Tries to determine the resource file content which is referenced by the /// Tries to determine the resource set which is referenced by the
/// resource manager which is assigned to the specified member. /// resource manager which is assigned to the specified member.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// The IResourceFileContent, if successful, or a null reference, if the /// The ResourceSetReference, if successful, or a null reference, if the
/// specified member is not a resource manager or if the /// specified member is not a resource manager or if the
/// resource file cannot be determined. /// resource file cannot be determined.
/// </returns> /// </returns>
static IResourceFileContent ResolveResourceFileContent(IMember member) static ResourceSetReference ResolveResourceSet(IMember member)
{ {
if (member != null && member.ReturnType != null && if (member != null && member.ReturnType != null &&
member.DeclaringType != null && member.DeclaringType.CompilationUnit != null) { member.DeclaringType != null && member.DeclaringType.CompilationUnit != null) {
IResourceFileContent content; ResourceSetReference rsr;
if (!NRefactoryAstCacheService.CacheEnabled || !cachedResourceFileContentMappings.TryGetValue(member, out content)) { if (!NRefactoryAstCacheService.CacheEnabled || !cachedResourceSetReferenceMappings.TryGetValue(member, out rsr)) {
string declaringFileName = member.DeclaringType.CompilationUnit.FileName; string declaringFileName = member.DeclaringType.CompilationUnit.FileName;
if (declaringFileName != null) { if (declaringFileName != null) {
@ -256,15 +256,15 @@ namespace Hornung.ResourceToolkit.Resolver
ResourceManagerInitializationFindVisitor visitor = new ResourceManagerInitializationFindVisitor(member); ResourceManagerInitializationFindVisitor visitor = new ResourceManagerInitializationFindVisitor(member);
cu.AcceptVisitor(visitor, null); cu.AcceptVisitor(visitor, null);
if (visitor.FoundFileName != null) { if (visitor.FoundResourceSet != null) {
content = ResourceFileContentRegistry.GetResourceFileContent(visitor.FoundFileName); rsr = visitor.FoundResourceSet;
if (NRefactoryAstCacheService.CacheEnabled && content != null) { if (NRefactoryAstCacheService.CacheEnabled) {
cachedResourceFileContentMappings.Add(member, content); cachedResourceSetReferenceMappings.Add(member, rsr);
} }
return content; return rsr;
} }
@ -277,7 +277,7 @@ namespace Hornung.ResourceToolkit.Resolver
} }
return content; return rsr;
} }
return null; return null;
@ -336,14 +336,14 @@ namespace Hornung.ResourceToolkit.Resolver
CompilationUnit compilationUnit; CompilationUnit compilationUnit;
string foundFileName; ResourceSetReference foundResourceSet;
/// <summary> /// <summary>
/// Gets the resource file name which the resource manager accesses, or a null reference if the file could not be determined or does not exist. /// Gets the resource set which the resource manager accesses, or a null reference if the resource set could not be determined.
/// </summary> /// </summary>
public string FoundFileName { public ResourceSetReference FoundResourceSet {
get { get {
return this.foundFileName; return this.foundResourceSet;
} }
} }
@ -439,7 +439,7 @@ namespace Hornung.ResourceToolkit.Resolver
public override object TrackedVisit(AssignmentExpression assignmentExpression, object data) public override object TrackedVisit(AssignmentExpression assignmentExpression, object data)
{ {
if (this.FoundFileName == null && // skip if already found to improve performance if (this.FoundResourceSet == null && // skip if already found to improve performance
assignmentExpression.Op == AssignmentOperatorType.Assign && this.PositionAvailable && assignmentExpression.Op == AssignmentOperatorType.Assign && this.PositionAvailable &&
(!this.isLocalVariable || this.resourceManagerMember.Region.IsInside(this.CurrentNodeStartLocation.Y, this.CurrentNodeStartLocation.X)) // skip if local variable is out of scope (!this.isLocalVariable || this.resourceManagerMember.Region.IsInside(this.CurrentNodeStartLocation.Y, this.CurrentNodeStartLocation.X)) // skip if local variable is out of scope
) { ) {
@ -582,14 +582,14 @@ namespace Hornung.ResourceToolkit.Resolver
LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found string parameter: '"+pValue+"'"); LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found string parameter: '"+pValue+"'");
#endif #endif
string fileName = NRefactoryResourceResolver.GetResourceFileNameByResourceName(this.resourceManagerMember.DeclaringType.CompilationUnit.FileName, pValue); this.foundResourceSet = NRefactoryResourceResolver.GetResourceSetReference(this.resourceManagerMember.DeclaringType.CompilationUnit.FileName, pValue);
if (fileName != null) { #if DEBUG
#if DEBUG if (this.foundResourceSet.FileName != null) {
LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found resource file: "+fileName); LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found resource file: "+this.foundResourceSet.FileName);
#endif
this.foundFileName = fileName;
break;
} }
#endif
break;
} }
@ -606,14 +606,14 @@ namespace Hornung.ResourceToolkit.Resolver
LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found typeof(...) parameter, type: '"+trr.ResolvedType.ToString()+"'"); LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found typeof(...) parameter, type: '"+trr.ResolvedType.ToString()+"'");
#endif #endif
string fileName = NRefactoryResourceResolver.GetResourceFileNameByResourceName(this.resourceManagerMember.DeclaringType.CompilationUnit.FileName, trr.ResolvedType.FullyQualifiedName); this.foundResourceSet = NRefactoryResourceResolver.GetResourceSetReference(this.resourceManagerMember.DeclaringType.CompilationUnit.FileName, trr.ResolvedType.FullyQualifiedName);
if (fileName != null) { #if DEBUG
#if DEBUG if (this.foundResourceSet.FileName != null) {
LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found resource file: "+fileName); LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found resource file: "+this.foundResourceSet.FileName);
#endif
this.foundFileName = fileName;
break;
} }
#endif
break;
} }
} }

26
src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/ICSharpCodeCoreNRefactoryResourceResolver.cs

@ -78,31 +78,9 @@ namespace Hornung.ResourceToolkit.Resolver
#endif #endif
string key = GetKeyFromExpression(expr); string key = GetKeyFromExpression(expr);
string localResourceFileName = ICSharpCodeCoreResourceResolver.GetICSharpCodeCoreLocalResourceFileName(fileName);
string hostResourceFileName = ICSharpCodeCoreResourceResolver.GetICSharpCodeCoreHostResourceFileName(fileName);
IResourceFileContent content = null;
// Merge the local and host resource file contents if available. // TODO: Add information about return type (of the resource, if present).
return new ResourceResolveResult(resolveResult.CallingClass, resolveResult.CallingMember, null, ICSharpCodeCoreResourceResolver.ResolveICSharpCodeCoreResourceSet(key, fileName), key);
if (!String.IsNullOrEmpty(localResourceFileName)) {
content = ResourceFileContentRegistry.GetResourceFileContent(localResourceFileName);
}
if (!String.IsNullOrEmpty(hostResourceFileName)) {
if (content == null) {
content = ResourceFileContentRegistry.GetResourceFileContent(hostResourceFileName);
} else {
IResourceFileContent hostContent = ResourceFileContentRegistry.GetResourceFileContent(hostResourceFileName);
if (hostContent != null) {
content = new MergedResourceFileContent(content, new IResourceFileContent[] { hostContent });
}
}
}
if (content != null) {
// TODO: Add information about return type (of the resource, if present).
return new ResourceResolveResult(resolveResult.CallingClass, resolveResult.CallingMember, null, content, key);
}
} }

115
src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/ICSharpCodeCoreResourceResolver.cs

@ -126,65 +126,59 @@ namespace Hornung.ResourceToolkit.Resolver
#endif #endif
} }
string resourceFile = ResolveICSharpCodeCoreResourceFileName(key == null ? null : key.ToString(), fileName); ResourceSetReference resource = ResolveICSharpCodeCoreResourceSet(key == null ? null : key.ToString(), fileName);
if (resourceFile != null) { #if DEBUG
// TODO: Add information about callingClass, callingMember, returnType if (resource.FileName == null) {
return new ResourceResolveResult(null, null, null, ResourceFileContentRegistry.GetResourceFileContent(resourceFile), key == null ? null : key.ToString());
} else {
LoggingService.Info("ResourceToolkit: ICSharpCodeCoreResourceResolver: Could not find the ICSharpCode.Core resource file name for the source file '"+fileName+"', key '"+(key == null ? "<null>" : key.ToString())+"'."); LoggingService.Info("ResourceToolkit: ICSharpCodeCoreResourceResolver: Could not find the ICSharpCode.Core resource file name for the source file '"+fileName+"', key '"+(key == null ? "<null>" : key.ToString())+"'.");
} }
#endif
return null; // TODO: Add information about callingClass, callingMember, returnType
return new ResourceResolveResult(null, null, null, resource, key == null ? null : key.ToString());
} }
// ******************************************************************************************************************************** // ********************************************************************************************************************************
/// <summary> /// <summary>
/// Tries to find the name of the resource file which serves as source for /// Tries to find the resource set which serves as source for
/// the resources accessed by the ICSharpCode.Core. /// the resources accessed by the ICSharpCode.Core.
/// </summary> /// </summary>
/// <param name="key">The resource key to look for. May be null.</param> /// <param name="key">The resource key to look for. May be null.</param>
/// <param name="sourceFileName">The name of the source code file that contains the reference to the resource.</param> /// <param name="sourceFileName">The name of the source code file that contains the reference to the resource.</param>
static string ResolveICSharpCodeCoreResourceFileName(string key, string sourceFileName) public static ResourceSetReference ResolveICSharpCodeCoreResourceSet(string key, string sourceFileName)
{ {
// As there is no easy way to find out the actual location of the resources // As there is no easy way to find out the actual location of the resources
// based on the source code, we just look in some standard directories. // based on the source code, we just look in some standard directories.
// Local file (SD addin or standalone application with standard directory structure) // Local set (SD addin or standalone application with standard directory structure)
string localFile = GetICSharpCodeCoreLocalResourceFileName(sourceFileName); ResourceSetReference local = GetICSharpCodeCoreLocalResourceSet(sourceFileName);
// Prefer local file, especially if the key is there. // Prefer local set, especially if the key is there.
if (localFile != null) { if (local.ResourceFileContent != null) {
if (key != null) { if (key != null) {
IResourceFileContent localContent = ResourceFileContentRegistry.GetResourceFileContent(localFile); if (local.ResourceFileContent.ContainsKey(key)) {
if (localContent != null) { return local;
if (localContent.ContainsKey(key)) {
return localFile;
}
} }
} else { } else {
return localFile; return local;
} }
} }
// Resource file of the host application // Resource set of the host application
string hostFile = GetICSharpCodeCoreHostResourceFileName(sourceFileName); ResourceSetReference host = GetICSharpCodeCoreHostResourceSet(sourceFileName);
if (key != null) { if (key != null) {
if (hostFile != null) { if (host.ResourceFileContent != null) {
IResourceFileContent hostContent = ResourceFileContentRegistry.GetResourceFileContent(hostFile); if (host.ResourceFileContent.ContainsKey(key)) {
if (hostContent != null) { return host;
if (hostContent.ContainsKey(key)) {
return hostFile;
}
} }
} }
} }
// Use local file also if the key is not there // Use local file also if the key is not there
// (allows adding of a new key) // (allows adding of a new key)
return localFile == null ? hostFile : localFile; return local.ResourceFileContent == null ? host : local;
} }
/// <summary> /// <summary>
@ -203,43 +197,63 @@ namespace Hornung.ResourceToolkit.Resolver
} }
/// <summary> /// <summary>
/// Tries to find the local string resource file used for ICSharpCode.Core resource access. /// Gets a dummy resource set name used to represent the ICSharpCode.Core
/// resource set of the local application.
/// </summary>
public const string ICSharpCodeCoreLocalResourceSetName = "[ICSharpCodeCoreLocalResourceSet]";
/// <summary>
/// Gets a dummy resource set name used to represent the ICSharpCode.Core
/// resource set of the host application.
/// </summary>
public const string ICSharpCodeCoreHostResourceSetName = "[ICSharpCodeCoreHostResourceSet]";
static readonly ResourceSetReference EmptyLocalResourceSetReference = new ResourceSetReference(ICSharpCodeCoreLocalResourceSetName, null);
static readonly ResourceSetReference EmptyHostResourceSetReference = new ResourceSetReference(ICSharpCodeCoreHostResourceSetName, null);
/// <summary>
/// Tries to find the local string resource set used for ICSharpCode.Core resource access.
/// </summary> /// </summary>
/// <param name="sourceFileName">The name of the source code file which to find the ICSharpCode.Core resource file for.</param> /// <param name="sourceFileName">The name of the source code file which to find the ICSharpCode.Core resource set for.</param>
public static string GetICSharpCodeCoreLocalResourceFileName(string sourceFileName) /// <returns>A <see cref="ResourceSetReference"/> that describes the referenced resource set. The contained file name may be <c>null</c> if the file cannot be determined.</returns>
public static ResourceSetReference GetICSharpCodeCoreLocalResourceSet(string sourceFileName)
{ {
IProject project = ProjectFileDictionaryService.GetProjectForFile(sourceFileName); IProject project = ProjectFileDictionaryService.GetProjectForFile(sourceFileName);
if (project == null || String.IsNullOrEmpty(project.Directory)) { if (project == null || String.IsNullOrEmpty(project.Directory)) {
return null; return EmptyLocalResourceSetReference;
} }
string localFile = null; string localFile;
ResourceSetReference local = null;
if (!NRefactoryAstCacheService.CacheEnabled || !cachedLocalResourceFiles.TryGetValue(project, out localFile)) { if (!NRefactoryAstCacheService.CacheEnabled || !cachedLocalResourceSets.TryGetValue(project, out local)) {
foreach (string relativePath in AddInTree.BuildItems<string>("/AddIns/ResourceToolkit/ICSharpCodeCoreResourceResolver/LocalResourcesLocations", null, false)) { foreach (string relativePath in AddInTree.BuildItems<string>("/AddIns/ResourceToolkit/ICSharpCodeCoreResourceResolver/LocalResourcesLocations", null, false)) {
if ((localFile = FindICSharpCodeCoreResourceFile(Path.GetFullPath(Path.Combine(project.Directory, relativePath)))) != null) { if ((localFile = FindICSharpCodeCoreResourceFile(Path.GetFullPath(Path.Combine(project.Directory, relativePath)))) != null) {
local = new ResourceSetReference(ICSharpCodeCoreLocalResourceSetName, localFile);
if (NRefactoryAstCacheService.CacheEnabled) { if (NRefactoryAstCacheService.CacheEnabled) {
cachedLocalResourceFiles.Add(project, localFile); cachedLocalResourceSets.Add(project, local);
} }
break; break;
} }
} }
} }
return localFile; return local ?? EmptyLocalResourceSetReference;
} }
/// <summary> /// <summary>
/// Tries to find the string resource file of the host application for ICSharpCode.Core resource access. /// Tries to find the string resource set of the host application for ICSharpCode.Core resource access.
/// </summary> /// </summary>
/// <param name="sourceFileName">The name of the source code file which to find the ICSharpCode.Core resource file for.</param> /// <param name="sourceFileName">The name of the source code file which to find the ICSharpCode.Core resource set for.</param>
public static string GetICSharpCodeCoreHostResourceFileName(string sourceFileName) /// <returns>A <see cref="ResourceSetReference"/> that describes the referenced resource set. The contained file name may be <c>null</c> if the file cannot be determined.</returns>
public static ResourceSetReference GetICSharpCodeCoreHostResourceSet(string sourceFileName)
{ {
IProject project = ProjectFileDictionaryService.GetProjectForFile(sourceFileName); IProject project = ProjectFileDictionaryService.GetProjectForFile(sourceFileName);
string hostFile = null; ResourceSetReference host = null;
string hostFile;
if (project == null || if (project == null ||
!NRefactoryAstCacheService.CacheEnabled || !cachedHostResourceFiles.TryGetValue(project, out hostFile)) { !NRefactoryAstCacheService.CacheEnabled || !cachedHostResourceSets.TryGetValue(project, out host)) {
// Get SD directory using the reference to ICSharpCode.Core // Get SD directory using the reference to ICSharpCode.Core
string coreAssemblyFullPath = GetICSharpCodeCoreFullPath(project); string coreAssemblyFullPath = GetICSharpCodeCoreFullPath(project);
@ -256,7 +270,7 @@ namespace Hornung.ResourceToolkit.Resolver
} }
if (coreAssemblyFullPath == null) { if (coreAssemblyFullPath == null) {
return null; return EmptyHostResourceSetReference;
} }
#if DEBUG #if DEBUG
@ -265,8 +279,9 @@ namespace Hornung.ResourceToolkit.Resolver
foreach (string relativePath in AddInTree.BuildItems<string>("/AddIns/ResourceToolkit/ICSharpCodeCoreResourceResolver/HostResourcesLocations", null, false)) { foreach (string relativePath in AddInTree.BuildItems<string>("/AddIns/ResourceToolkit/ICSharpCodeCoreResourceResolver/HostResourcesLocations", null, false)) {
if ((hostFile = FindICSharpCodeCoreResourceFile(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(coreAssemblyFullPath), relativePath)))) != null) { if ((hostFile = FindICSharpCodeCoreResourceFile(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(coreAssemblyFullPath), relativePath)))) != null) {
host = new ResourceSetReference(ICSharpCodeCoreHostResourceSetName, hostFile);
if (NRefactoryAstCacheService.CacheEnabled && project != null) { if (NRefactoryAstCacheService.CacheEnabled && project != null) {
cachedHostResourceFiles.Add(project, hostFile); cachedHostResourceSets.Add(project, host);
} }
break; break;
} }
@ -274,7 +289,7 @@ namespace Hornung.ResourceToolkit.Resolver
} }
return hostFile; return host ?? EmptyHostResourceSetReference;
} }
static string GetICSharpCodeCoreFullPath(IProject sourceProject) static string GetICSharpCodeCoreFullPath(IProject sourceProject)
@ -317,15 +332,15 @@ namespace Hornung.ResourceToolkit.Resolver
return coreAssemblyFullPath; return coreAssemblyFullPath;
} }
#region ICSharpCode.Core resource file mapping cache #region ICSharpCode.Core resource set mapping cache
static Dictionary<IProject, string> cachedLocalResourceFiles; static Dictionary<IProject, ResourceSetReference> cachedLocalResourceSets;
static Dictionary<IProject, string> cachedHostResourceFiles; static Dictionary<IProject, ResourceSetReference> cachedHostResourceSets;
static ICSharpCodeCoreResourceResolver() static ICSharpCodeCoreResourceResolver()
{ {
cachedLocalResourceFiles = new Dictionary<IProject, string>(); cachedLocalResourceSets = new Dictionary<IProject, ResourceSetReference>();
cachedHostResourceFiles = new Dictionary<IProject, string>(); cachedHostResourceSets = new Dictionary<IProject, ResourceSetReference>();
NRefactoryAstCacheService.CacheEnabledChanged += NRefactoryCacheEnabledChanged; NRefactoryAstCacheService.CacheEnabledChanged += NRefactoryCacheEnabledChanged;
} }
@ -333,8 +348,8 @@ namespace Hornung.ResourceToolkit.Resolver
{ {
if (!NRefactoryAstCacheService.CacheEnabled) { if (!NRefactoryAstCacheService.CacheEnabled) {
// Clear cache when disabled. // Clear cache when disabled.
cachedLocalResourceFiles.Clear(); cachedLocalResourceSets.Clear();
cachedHostResourceFiles.Clear(); cachedHostResourceSets.Clear();
} }
} }

28
src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/NRefactoryResourceResolver.cs

@ -168,9 +168,9 @@ namespace Hornung.ResourceToolkit.Resolver
/// </summary> /// </summary>
/// <param name="sourceFileName">The name of the source code file which the reference occurs in.</param> /// <param name="sourceFileName">The name of the source code file which the reference occurs in.</param>
/// <param name="resourceName">The manifest resource name to find the resource file for.</param> /// <param name="resourceName">The manifest resource name to find the resource file for.</param>
/// <returns>The name of the file that contains the resources with the specified manifest resource name, or <c>null</c> if the file name cannot be determined.</returns> /// <returns>A <see cref="ResourceSetReference"/> with the specified resource set name and the name of the file that contains the resources with the specified manifest resource name, or <c>null</c> if the file name cannot be determined.</returns>
/// <exception cref="ArgumentNullException">The <paramref name="resourceName"/> parameter is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">The <paramref name="resourceName"/> parameter is <c>null</c>.</exception>
public static string GetResourceFileNameByResourceName(string sourceFileName, string resourceName) public static ResourceSetReference GetResourceSetReference(string sourceFileName, string resourceName)
{ {
if (resourceName == null) { if (resourceName == null) {
throw new ArgumentNullException("resourceName"); throw new ArgumentNullException("resourceName");
@ -186,7 +186,7 @@ namespace Hornung.ResourceToolkit.Resolver
// Look for a resource file in the project with the exact name. // Look for a resource file in the project with the exact name.
if ((fileName = FindResourceFileName(Path.Combine(p.Directory, resourceName.Substring(p.RootNamespace.Length+1).Replace('.', Path.DirectorySeparatorChar)))) != null) { if ((fileName = FindResourceFileName(Path.Combine(p.Directory, resourceName.Substring(p.RootNamespace.Length+1).Replace('.', Path.DirectorySeparatorChar)))) != null) {
return fileName; return new ResourceSetReference(resourceName, fileName);
} }
} }
@ -248,7 +248,7 @@ namespace Hornung.ResourceToolkit.Resolver
// over localized resource file // over localized resource file
IResourceFileContent rfc = ResourceFileContentRegistry.GetResourceFileContent(fileName); IResourceFileContent rfc = ResourceFileContentRegistry.GetResourceFileContent(fileName);
if (rfc.Culture.Equals(CultureInfo.InvariantCulture)) { if (rfc.Culture.Equals(CultureInfo.InvariantCulture)) {
return fileName; return new ResourceSetReference(resourceName, fileName);
} }
} }
@ -259,20 +259,22 @@ namespace Hornung.ResourceToolkit.Resolver
// Fall back to any found resource file // Fall back to any found resource file
// if no culture-invariant resource file was found // if no culture-invariant resource file was found
if (fileName != null) { if (fileName != null) {
return fileName; return new ResourceSetReference(resourceName, fileName);
} }
// Find resource files with the same name as the source file // Find resource files with the same name as the source file
// and in the same directory. // and in the same directory.
if ((fileName = FindResourceFileName(possibleSourceFile)) != null) { if ((fileName = FindResourceFileName(possibleSourceFile)) != null) {
return fileName; return new ResourceSetReference(resourceName, fileName);
} }
} }
} else { } else {
LoggingService.Info("ResourceToolkit: NRefactoryResourceResolver.GetResourceFileNameByResourceName could not determine the project for the source file '"+(sourceFileName ?? "<null>")+"'."); #if DEBUG
LoggingService.Info("ResourceToolkit: NRefactoryResourceResolver.GetResourceSetReference could not determine the project for the source file '"+(sourceFileName ?? "<null>")+"'.");
#endif
if (sourceFileName != null) { if (sourceFileName != null) {
@ -286,14 +288,14 @@ namespace Hornung.ResourceToolkit.Resolver
while (true) { while (true) {
#if DEBUG #if DEBUG
LoggingService.Debug("ResourceToolkit: NRefactoryResourceResolver.GetResourceFileNameByResourceName: looking for a resource file like '"+Path.Combine(directory, resourcePart)+"'"); LoggingService.Debug("ResourceToolkit: NRefactoryResourceResolver.GetResourceSetReference: looking for a resource file like '"+Path.Combine(directory, resourcePart)+"'");
#endif #endif
if ((fileName = FindResourceFileName(Path.Combine(directory, resourcePart.Replace('.', Path.DirectorySeparatorChar)))) != null) { if ((fileName = FindResourceFileName(Path.Combine(directory, resourcePart.Replace('.', Path.DirectorySeparatorChar)))) != null) {
return fileName; return new ResourceSetReference(resourceName, fileName);
} }
if ((fileName = FindResourceFileName(Path.Combine(directory, resourcePart))) != null) { if ((fileName = FindResourceFileName(Path.Combine(directory, resourcePart))) != null) {
return fileName; return new ResourceSetReference(resourceName, fileName);
} }
if (resourcePart.Contains(".")) { if (resourcePart.Contains(".")) {
@ -308,9 +310,11 @@ namespace Hornung.ResourceToolkit.Resolver
} }
LoggingService.Info("ResourceToolkit: NRefactoryResourceResolver.GetResourceFileNameByResourceName is unable to find a suitable resource file for '"+resourceName+"'"); #if DEBUG
LoggingService.Info("ResourceToolkit: NRefactoryResourceResolver.GetResourceSetReference is unable to find a suitable resource file for '"+resourceName+"'");
#endif
return null; return new ResourceSetReference(resourceName, null);
} }
// ******************************************************************************************************************************** // ********************************************************************************************************************************

42
src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/ResourceResolveResult.cs

@ -17,15 +17,27 @@ namespace Hornung.ResourceToolkit.Resolver
public class ResourceResolveResult : ResolveResult public class ResourceResolveResult : ResolveResult
{ {
IResourceFileContent resourceFileContent; ResourceSetReference resourceSetReference;
string key; string key;
/// <summary> /// <summary>
/// Gets the <see cref="IResourceFileContent" /> of the resource being referenced. /// Gets the <see cref="ResourceSetReference"/> that describes the resource set being referenced.
/// </summary>
public ResourceSetReference ResourceSetReference {
get { return this.resourceSetReference; }
}
/// <summary>
/// Gets the <see cref="IResourceFileContent"/> for the referenced resource set.
/// May be <c>null</c>.
/// </summary> /// </summary>
public IResourceFileContent ResourceFileContent { public IResourceFileContent ResourceFileContent {
get { get {
return this.resourceFileContent; if (this.ResourceSetReference == null ||
this.ResourceSetReference.FileName == null) {
return null;
}
return this.ResourceSetReference.ResourceFileContent;
} }
} }
@ -33,29 +45,27 @@ namespace Hornung.ResourceToolkit.Resolver
/// Gets the resource key being referenced. May be null if the key is unknown/not yet typed. /// Gets the resource key being referenced. May be null if the key is unknown/not yet typed.
/// </summary> /// </summary>
public string Key { public string Key {
get { get { return this.key; }
return this.key;
}
} }
/// <summary> /// <summary>
/// Gets the resource file name that contains the resource being referenced. /// Gets the resource file name that contains the resource being referenced.
/// Only valid if both <see cref="ResourceFileContent"/> and <see cref="Key"/> are not <c>null</c>. /// Only valid if <see cref="ResourceSetReference"/> is not <c>null</c>
/// and the <see cref="ResourceSetReference"/> contains a valid file name.
/// </summary> /// </summary>
public string FileName { public string FileName {
get { get {
if (this.ResourceFileContent == null || this.Key == null) {
return null;
}
IMultiResourceFileContent mrfc = this.ResourceFileContent as IMultiResourceFileContent; IMultiResourceFileContent mrfc = this.ResourceFileContent as IMultiResourceFileContent;
if (mrfc != null) { if (mrfc != null && this.Key != null) {
return mrfc.GetFileNameForKey(this.Key); return mrfc.GetFileNameForKey(this.Key);
} else { } else if (this.ResourceFileContent != null) {
return this.ResourceFileContent.FileName; return this.ResourceFileContent.FileName;
} else if (this.ResourceSetReference != null) {
return this.ResourceSetReference.FileName;
} }
return null;
} }
} }
@ -65,12 +75,12 @@ namespace Hornung.ResourceToolkit.Resolver
/// <param name="callingClass">The class that contains the reference to the resource.</param> /// <param name="callingClass">The class that contains the reference to the resource.</param>
/// <param name="callingMember">The member that contains the reference to the resource.</param> /// <param name="callingMember">The member that contains the reference to the resource.</param>
/// <param name="returnType">The type of the resource being referenced.</param> /// <param name="returnType">The type of the resource being referenced.</param>
/// <param name="resourceFileContent">The <see cref="IResourceFileContent"/> that contains the resource being referenced.</param> /// <param name="resourceSetReference">The <see cref="ResourceSetReference"/> that describes the resource set being referenced.</param>
/// <param name="key">The resource key being referenced.</param> /// <param name="key">The resource key being referenced.</param>
public ResourceResolveResult(IClass callingClass, IMember callingMember, IReturnType returnType, IResourceFileContent resourceFileContent, string key) public ResourceResolveResult(IClass callingClass, IMember callingMember, IReturnType returnType, ResourceSetReference resourceSetReference, string key)
: base(callingClass, callingMember, returnType) : base(callingClass, callingMember, returnType)
{ {
this.resourceFileContent = resourceFileContent; this.resourceSetReference = resourceSetReference;
this.key = key; this.key = key;
} }

73
src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/ResourceSetReference.cs

@ -0,0 +1,73 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Christian Hornung" email="c-hornung@gmx.de"/>
// <version>$Revision$</version>
// </file>
using System;
using Hornung.ResourceToolkit.ResourceFileContent;
namespace Hornung.ResourceToolkit.Resolver
{
/// <summary>
/// Describes a reference to a resource set (this typically means a file,
/// but a resource set reference can exist when the actual file it refers to
/// is missing).
/// </summary>
public class ResourceSetReference
{
readonly string resourceSetName;
readonly string fileName;
/// <summary>
/// Gets the resource set name of this reference.
/// This typically corresponds to the manifest resource name.
/// This property never returns <c>null</c>.
/// </summary>
public string ResourceSetName {
get { return resourceSetName; }
}
/// <summary>
/// Gets the name of the file that contains the referenced resource set.
/// This property may return <c>null</c> if the file name cannot be
/// determined unambiguously or if the file is missing.
/// </summary>
public string FileName {
get { return fileName; }
}
/// <summary>
/// Gets the <see cref="IResourceFileContent"/> for the referenced resource set.
/// This property may return <c>null</c> if the file name cannot be
/// determined unambiguously or if the file is missing.
/// </summary>
public IResourceFileContent ResourceFileContent {
get {
if (this.FileName == null) return null;
return ResourceFileContentRegistry.GetResourceFileContent(this.FileName);
}
}
/// <summary>
/// Initializes a new instance of the <see cref="ResourceSetReference"/> class.
/// </summary>
/// <param name="resourceSetName">The resource set name of the reference.</param>
/// <param name="fileName">The name of the file that contains the referenced resource set. May be <c>null</c>.</param>
/// <exception cref="ArgumentNullException">The <paramref name="resourceSetName"/> parameter is <c>null</c>.</exception>
/// <exception cref="ArgumentException">The <paramref name="resourceSetName"/> parameter is empty.</exception>
public ResourceSetReference(string resourceSetName, string fileName)
{
if (resourceSetName == null) {
throw new ArgumentNullException("resourceSetName");
} else if (resourceSetName.Length == 0) {
throw new ArgumentException("The resourceSetName must not be empty.", "resourceSetName");
}
this.resourceSetName = resourceSetName;
this.fileName = fileName;
}
}
}
Loading…
Cancel
Save