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

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

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
using System;
using Hornung.ResourceToolkit.Resolver;
using Hornung.ResourceToolkit.ResourceFileContent;
using ICSharpCode.NRefactory.PrettyPrinter;
using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor;
@ -25,8 +26,21 @@ namespace Hornung.ResourceToolkit.CodeCompletion @@ -25,8 +26,21 @@ namespace Hornung.ResourceToolkit.CodeCompletion
ResourceResolveResult result = ResourceResolverService.Resolve(editor, ch);
if (result != null) {
if (result.ResourceFileContent != null) {
editor.ShowCompletionWindow(new ResourceCodeCompletionDataProvider(result.ResourceFileContent, this.OutputVisitor, result.CallingClass != null ? result.CallingClass.Name+"." : null), ch);
IResourceFileContent content;
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;
}
}

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

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

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

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

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

@ -167,13 +167,13 @@ namespace Hornung.ResourceToolkit.Resolver @@ -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()
{
cachedResourceFileContentMappings = new Dictionary<IMember, IResourceFileContent>(new MemberEqualityComparer());
cachedResourceSetReferenceMappings = new Dictionary<IMember, ResourceSetReference>(new MemberEqualityComparer());
NRefactoryAstCacheService.CacheEnabledChanged += NRefactoryCacheEnabledChanged;
}
@ -181,7 +181,7 @@ namespace Hornung.ResourceToolkit.Resolver @@ -181,7 +181,7 @@ namespace Hornung.ResourceToolkit.Resolver
{
if (!NRefactoryAstCacheService.CacheEnabled) {
// Clear cache when disabled.
cachedResourceFileContentMappings.Clear();
cachedResourceSetReferenceMappings.Clear();
}
}
@ -199,48 +199,48 @@ namespace Hornung.ResourceToolkit.Resolver @@ -199,48 +199,48 @@ namespace Hornung.ResourceToolkit.Resolver
/// </returns>
static ResourceResolveResult ResolveResource(ResolveResult resolveResult, Expression expr)
{
IResourceFileContent rfc = null;
ResourceSetReference rsr = null;
MemberResolveResult mrr = resolveResult as MemberResolveResult;
if (mrr != null) {
rfc = ResolveResourceFileContent(mrr.ResolvedMember);
rsr = ResolveResourceSet(mrr.ResolvedMember);
} else {
LocalResolveResult lrr = resolveResult as LocalResolveResult;
if (lrr != null) {
if (!lrr.IsParameter) {
rfc = ResolveResourceFileContent(lrr.Field);
rsr = ResolveResourceSet(lrr.Field);
}
}
}
if (rfc != null) {
if (rsr != null) {
string key = GetKeyFromExpression(expr);
// 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;
}
/// <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.
/// </summary>
/// <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
/// resource file cannot be determined.
/// </returns>
static IResourceFileContent ResolveResourceFileContent(IMember member)
static ResourceSetReference ResolveResourceSet(IMember member)
{
if (member != null && member.ReturnType != null &&
member.DeclaringType != null && member.DeclaringType.CompilationUnit != null) {
IResourceFileContent content;
if (!NRefactoryAstCacheService.CacheEnabled || !cachedResourceFileContentMappings.TryGetValue(member, out content)) {
ResourceSetReference rsr;
if (!NRefactoryAstCacheService.CacheEnabled || !cachedResourceSetReferenceMappings.TryGetValue(member, out rsr)) {
string declaringFileName = member.DeclaringType.CompilationUnit.FileName;
if (declaringFileName != null) {
@ -256,15 +256,15 @@ namespace Hornung.ResourceToolkit.Resolver @@ -256,15 +256,15 @@ namespace Hornung.ResourceToolkit.Resolver
ResourceManagerInitializationFindVisitor visitor = new ResourceManagerInitializationFindVisitor(member);
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) {
cachedResourceFileContentMappings.Add(member, content);
if (NRefactoryAstCacheService.CacheEnabled) {
cachedResourceSetReferenceMappings.Add(member, rsr);
}
return content;
return rsr;
}
@ -277,7 +277,7 @@ namespace Hornung.ResourceToolkit.Resolver @@ -277,7 +277,7 @@ namespace Hornung.ResourceToolkit.Resolver
}
return content;
return rsr;
}
return null;
@ -336,14 +336,14 @@ namespace Hornung.ResourceToolkit.Resolver @@ -336,14 +336,14 @@ namespace Hornung.ResourceToolkit.Resolver
CompilationUnit compilationUnit;
string foundFileName;
ResourceSetReference foundResourceSet;
/// <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>
public string FoundFileName {
public ResourceSetReference FoundResourceSet {
get {
return this.foundFileName;
return this.foundResourceSet;
}
}
@ -439,7 +439,7 @@ namespace Hornung.ResourceToolkit.Resolver @@ -439,7 +439,7 @@ namespace Hornung.ResourceToolkit.Resolver
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 &&
(!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 @@ -582,14 +582,14 @@ namespace Hornung.ResourceToolkit.Resolver
LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found string parameter: '"+pValue+"'");
#endif
string fileName = NRefactoryResourceResolver.GetResourceFileNameByResourceName(this.resourceManagerMember.DeclaringType.CompilationUnit.FileName, pValue);
if (fileName != null) {
#if DEBUG
LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found resource file: "+fileName);
#endif
this.foundFileName = fileName;
break;
this.foundResourceSet = NRefactoryResourceResolver.GetResourceSetReference(this.resourceManagerMember.DeclaringType.CompilationUnit.FileName, pValue);
#if DEBUG
if (this.foundResourceSet.FileName != null) {
LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found resource file: "+this.foundResourceSet.FileName);
}
#endif
break;
}
@ -606,14 +606,14 @@ namespace Hornung.ResourceToolkit.Resolver @@ -606,14 +606,14 @@ namespace Hornung.ResourceToolkit.Resolver
LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found typeof(...) parameter, type: '"+trr.ResolvedType.ToString()+"'");
#endif
string fileName = NRefactoryResourceResolver.GetResourceFileNameByResourceName(this.resourceManagerMember.DeclaringType.CompilationUnit.FileName, trr.ResolvedType.FullyQualifiedName);
if (fileName != null) {
#if DEBUG
LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found resource file: "+fileName);
#endif
this.foundFileName = fileName;
break;
this.foundResourceSet = NRefactoryResourceResolver.GetResourceSetReference(this.resourceManagerMember.DeclaringType.CompilationUnit.FileName, trr.ResolvedType.FullyQualifiedName);
#if DEBUG
if (this.foundResourceSet.FileName != null) {
LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found resource file: "+this.foundResourceSet.FileName);
}
#endif
break;
}
}

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

@ -78,31 +78,9 @@ namespace Hornung.ResourceToolkit.Resolver @@ -78,31 +78,9 @@ namespace Hornung.ResourceToolkit.Resolver
#endif
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.
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);
}
// TODO: Add information about return type (of the resource, if present).
return new ResourceResolveResult(resolveResult.CallingClass, resolveResult.CallingMember, null, ICSharpCodeCoreResourceResolver.ResolveICSharpCodeCoreResourceSet(key, fileName), key);
}

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

@ -126,65 +126,59 @@ namespace Hornung.ResourceToolkit.Resolver @@ -126,65 +126,59 @@ namespace Hornung.ResourceToolkit.Resolver
#endif
}
string resourceFile = ResolveICSharpCodeCoreResourceFileName(key == null ? null : key.ToString(), fileName);
ResourceSetReference resource = ResolveICSharpCodeCoreResourceSet(key == null ? null : key.ToString(), fileName);
if (resourceFile != null) {
// TODO: Add information about callingClass, callingMember, returnType
return new ResourceResolveResult(null, null, null, ResourceFileContentRegistry.GetResourceFileContent(resourceFile), key == null ? null : key.ToString());
} else {
#if DEBUG
if (resource.FileName == null) {
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>
/// 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.
/// </summary>
/// <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>
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
// based on the source code, we just look in some standard directories.
// Local file (SD addin or standalone application with standard directory structure)
string localFile = GetICSharpCodeCoreLocalResourceFileName(sourceFileName);
// Local set (SD addin or standalone application with standard directory structure)
ResourceSetReference local = GetICSharpCodeCoreLocalResourceSet(sourceFileName);
// Prefer local file, especially if the key is there.
if (localFile != null) {
// Prefer local set, especially if the key is there.
if (local.ResourceFileContent != null) {
if (key != null) {
IResourceFileContent localContent = ResourceFileContentRegistry.GetResourceFileContent(localFile);
if (localContent != null) {
if (localContent.ContainsKey(key)) {
return localFile;
}
if (local.ResourceFileContent.ContainsKey(key)) {
return local;
}
} else {
return localFile;
return local;
}
}
// Resource file of the host application
string hostFile = GetICSharpCodeCoreHostResourceFileName(sourceFileName);
// Resource set of the host application
ResourceSetReference host = GetICSharpCodeCoreHostResourceSet(sourceFileName);
if (key != null) {
if (hostFile != null) {
IResourceFileContent hostContent = ResourceFileContentRegistry.GetResourceFileContent(hostFile);
if (hostContent != null) {
if (hostContent.ContainsKey(key)) {
return hostFile;
}
if (host.ResourceFileContent != null) {
if (host.ResourceFileContent.ContainsKey(key)) {
return host;
}
}
}
// Use local file also if the key is not there
// (allows adding of a new key)
return localFile == null ? hostFile : localFile;
return local.ResourceFileContent == null ? host : local;
}
/// <summary>
@ -203,43 +197,63 @@ namespace Hornung.ResourceToolkit.Resolver @@ -203,43 +197,63 @@ namespace Hornung.ResourceToolkit.Resolver
}
/// <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>
/// <param name="sourceFileName">The name of the source code file which to find the ICSharpCode.Core resource file for.</param>
public static string GetICSharpCodeCoreLocalResourceFileName(string sourceFileName)
/// <param name="sourceFileName">The name of the source code file which to find the ICSharpCode.Core resource set for.</param>
/// <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);
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)) {
if ((localFile = FindICSharpCodeCoreResourceFile(Path.GetFullPath(Path.Combine(project.Directory, relativePath)))) != null) {
local = new ResourceSetReference(ICSharpCodeCoreLocalResourceSetName, localFile);
if (NRefactoryAstCacheService.CacheEnabled) {
cachedLocalResourceFiles.Add(project, localFile);
cachedLocalResourceSets.Add(project, local);
}
break;
}
}
}
return localFile;
return local ?? EmptyLocalResourceSetReference;
}
/// <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>
/// <param name="sourceFileName">The name of the source code file which to find the ICSharpCode.Core resource file for.</param>
public static string GetICSharpCodeCoreHostResourceFileName(string sourceFileName)
/// <param name="sourceFileName">The name of the source code file which to find the ICSharpCode.Core resource set for.</param>
/// <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);
string hostFile = null;
ResourceSetReference host = null;
string hostFile;
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
string coreAssemblyFullPath = GetICSharpCodeCoreFullPath(project);
@ -256,7 +270,7 @@ namespace Hornung.ResourceToolkit.Resolver @@ -256,7 +270,7 @@ namespace Hornung.ResourceToolkit.Resolver
}
if (coreAssemblyFullPath == null) {
return null;
return EmptyHostResourceSetReference;
}
#if DEBUG
@ -265,8 +279,9 @@ namespace Hornung.ResourceToolkit.Resolver @@ -265,8 +279,9 @@ namespace Hornung.ResourceToolkit.Resolver
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) {
host = new ResourceSetReference(ICSharpCodeCoreHostResourceSetName, hostFile);
if (NRefactoryAstCacheService.CacheEnabled && project != null) {
cachedHostResourceFiles.Add(project, hostFile);
cachedHostResourceSets.Add(project, host);
}
break;
}
@ -274,7 +289,7 @@ namespace Hornung.ResourceToolkit.Resolver @@ -274,7 +289,7 @@ namespace Hornung.ResourceToolkit.Resolver
}
return hostFile;
return host ?? EmptyHostResourceSetReference;
}
static string GetICSharpCodeCoreFullPath(IProject sourceProject)
@ -317,15 +332,15 @@ namespace Hornung.ResourceToolkit.Resolver @@ -317,15 +332,15 @@ namespace Hornung.ResourceToolkit.Resolver
return coreAssemblyFullPath;
}
#region ICSharpCode.Core resource file mapping cache
#region ICSharpCode.Core resource set mapping cache
static Dictionary<IProject, string> cachedLocalResourceFiles;
static Dictionary<IProject, string> cachedHostResourceFiles;
static Dictionary<IProject, ResourceSetReference> cachedLocalResourceSets;
static Dictionary<IProject, ResourceSetReference> cachedHostResourceSets;
static ICSharpCodeCoreResourceResolver()
{
cachedLocalResourceFiles = new Dictionary<IProject, string>();
cachedHostResourceFiles = new Dictionary<IProject, string>();
cachedLocalResourceSets = new Dictionary<IProject, ResourceSetReference>();
cachedHostResourceSets = new Dictionary<IProject, ResourceSetReference>();
NRefactoryAstCacheService.CacheEnabledChanged += NRefactoryCacheEnabledChanged;
}
@ -333,8 +348,8 @@ namespace Hornung.ResourceToolkit.Resolver @@ -333,8 +348,8 @@ namespace Hornung.ResourceToolkit.Resolver
{
if (!NRefactoryAstCacheService.CacheEnabled) {
// Clear cache when disabled.
cachedLocalResourceFiles.Clear();
cachedHostResourceFiles.Clear();
cachedLocalResourceSets.Clear();
cachedHostResourceSets.Clear();
}
}

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

@ -168,9 +168,9 @@ namespace Hornung.ResourceToolkit.Resolver @@ -168,9 +168,9 @@ namespace Hornung.ResourceToolkit.Resolver
/// </summary>
/// <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>
/// <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>
public static string GetResourceFileNameByResourceName(string sourceFileName, string resourceName)
public static ResourceSetReference GetResourceSetReference(string sourceFileName, string resourceName)
{
if (resourceName == null) {
throw new ArgumentNullException("resourceName");
@ -186,7 +186,7 @@ namespace Hornung.ResourceToolkit.Resolver @@ -186,7 +186,7 @@ namespace Hornung.ResourceToolkit.Resolver
// 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) {
return fileName;
return new ResourceSetReference(resourceName, fileName);
}
}
@ -248,7 +248,7 @@ namespace Hornung.ResourceToolkit.Resolver @@ -248,7 +248,7 @@ namespace Hornung.ResourceToolkit.Resolver
// over localized resource file
IResourceFileContent rfc = ResourceFileContentRegistry.GetResourceFileContent(fileName);
if (rfc.Culture.Equals(CultureInfo.InvariantCulture)) {
return fileName;
return new ResourceSetReference(resourceName, fileName);
}
}
@ -259,20 +259,22 @@ namespace Hornung.ResourceToolkit.Resolver @@ -259,20 +259,22 @@ namespace Hornung.ResourceToolkit.Resolver
// Fall back to any found resource file
// if no culture-invariant resource file was found
if (fileName != null) {
return fileName;
return new ResourceSetReference(resourceName, fileName);
}
// Find resource files with the same name as the source file
// and in the same directory.
if ((fileName = FindResourceFileName(possibleSourceFile)) != null) {
return fileName;
return new ResourceSetReference(resourceName, fileName);
}
}
} 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) {
@ -286,14 +288,14 @@ namespace Hornung.ResourceToolkit.Resolver @@ -286,14 +288,14 @@ namespace Hornung.ResourceToolkit.Resolver
while (true) {
#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
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) {
return fileName;
return new ResourceSetReference(resourceName, fileName);
}
if (resourcePart.Contains(".")) {
@ -308,9 +310,11 @@ namespace Hornung.ResourceToolkit.Resolver @@ -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 @@ -17,15 +17,27 @@ namespace Hornung.ResourceToolkit.Resolver
public class ResourceResolveResult : ResolveResult
{
IResourceFileContent resourceFileContent;
ResourceSetReference resourceSetReference;
string key;
/// <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>
public IResourceFileContent ResourceFileContent {
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 @@ -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.
/// </summary>
public string Key {
get {
return this.key;
}
get { return this.key; }
}
/// <summary>
/// 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>
public string FileName {
get {
if (this.ResourceFileContent == null || this.Key == null) {
return null;
}
IMultiResourceFileContent mrfc = this.ResourceFileContent as IMultiResourceFileContent;
if (mrfc != null) {
if (mrfc != null && this.Key != null) {
return mrfc.GetFileNameForKey(this.Key);
} else {
} else if (this.ResourceFileContent != null) {
return this.ResourceFileContent.FileName;
} else if (this.ResourceSetReference != null) {
return this.ResourceSetReference.FileName;
}
return null;
}
}
@ -65,12 +75,12 @@ namespace Hornung.ResourceToolkit.Resolver @@ -65,12 +75,12 @@ namespace Hornung.ResourceToolkit.Resolver
/// <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="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>
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)
{
this.resourceFileContent = resourceFileContent;
this.resourceSetReference = resourceSetReference;
this.key = key;
}

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

@ -0,0 +1,73 @@ @@ -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