diff --git a/src/AddIns/Misc/ResourceToolkit/Project/ResourceToolkit.csproj b/src/AddIns/Misc/ResourceToolkit/Project/ResourceToolkit.csproj index 9c1eab1832..6639d8c2c7 100644 --- a/src/AddIns/Misc/ResourceToolkit/Project/ResourceToolkit.csproj +++ b/src/AddIns/Misc/ResourceToolkit/Project/ResourceToolkit.csproj @@ -147,4 +147,4 @@ - + \ No newline at end of file diff --git a/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/BclNRefactoryResourceResolver.cs b/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/BclNRefactoryResourceResolver.cs index 9f6b1cf6e4..93dfea0995 100644 --- a/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/BclNRefactoryResourceResolver.cs +++ b/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/BclNRefactoryResourceResolver.cs @@ -66,7 +66,7 @@ namespace Hornung.ResourceToolkit.Resolver MethodGroupResolveResult methrr = resolveResult as MethodGroupResolveResult; if (methrr != null) { if ((methrr.Name == "GetString" || methrr.Name == "GetObject" || methrr.Name == "GetStream") && - (resolveResult = NRefactoryAstCacheService.ResolveNextOuterExpression(ref expressionResult, caretLine, caretColumn, fileName, expressionFinder)) != null) { + (resolveResult = NRefactoryAstCacheService.ResolveNextOuterExpression(ref expressionResult, caretLine, caretColumn, fileName, fileContent, expressionFinder)) != null) { return ResolveResource(resolveResult, expr); @@ -106,7 +106,7 @@ namespace Hornung.ResourceToolkit.Resolver // we have to call Resolve again in this case to resolve // the method reference. - if ((resolveResult = NRefactoryAstCacheService.ResolveNextOuterExpression(ref expressionResult, caretLine, caretColumn, fileName, expressionFinder)) != null) { + if ((resolveResult = NRefactoryAstCacheService.ResolveNextOuterExpression(ref expressionResult, caretLine, caretColumn, fileName, fileContent, expressionFinder)) != null) { if (resolveResult is MethodGroupResolveResult) { return this.Resolve(expressionResult, expr, resolveResult, caretLine, caretColumn, fileName, fileContent, expressionFinder, '('); @@ -127,7 +127,7 @@ namespace Hornung.ResourceToolkit.Resolver // We need the reference to Something and this is // the next outer expression. - if ((resolveResult = NRefactoryAstCacheService.ResolveNextOuterExpression(ref expressionResult, caretLine, caretColumn, fileName, expressionFinder)) != null) { + if ((resolveResult = NRefactoryAstCacheService.ResolveNextOuterExpression(ref expressionResult, caretLine, caretColumn, fileName, fileContent, expressionFinder)) != null) { return ResolveResource(resolveResult, expr); } else { return null; @@ -252,7 +252,7 @@ namespace Hornung.ResourceToolkit.Resolver return null; } - CompilationUnit cu = NRefactoryAstCacheService.GetFullAst(language.Value, declaringFileName); + CompilationUnit cu = NRefactoryAstCacheService.GetFullAst(language.Value, declaringFileName, ResourceResolverService.GetParsableFileContent(declaringFileName)); if (cu != null) { ResourceManagerInitializationFindVisitor visitor = new ResourceManagerInitializationFindVisitor(member); @@ -297,7 +297,7 @@ namespace Hornung.ResourceToolkit.Resolver if (p == null) { pc = ParserService.CurrentProjectContent; } else { - pc = ParserService.GetProjectContent(p); + pc = ResourceResolverService.GetProjectContent(p); } if (pc == null) { @@ -352,7 +352,8 @@ namespace Hornung.ResourceToolkit.Resolver /// Initializes a new instance of the class. /// /// The member which the resource manager to be found is assigned to. - public ResourceManagerInitializationFindVisitor(IMember resourceManagerMember) : base() + public ResourceManagerInitializationFindVisitor(IMember resourceManagerMember) + : base(resourceManagerMember.DeclaringType.CompilationUnit.FileName, ResourceResolverService.GetParsableFileContent(resourceManagerMember.DeclaringType.CompilationUnit.FileName)) { this.resourceManagerMember = resourceManagerMember; IField resourceManagerField = resourceManagerMember as IField; @@ -446,7 +447,7 @@ namespace Hornung.ResourceToolkit.Resolver ) { IMember resolvedMember = null; - ResolveResult rr = this.Resolve(assignmentExpression.Left, this.resourceManagerMember.DeclaringType.CompilationUnit.FileName); + ResolveResult rr = this.Resolve(assignmentExpression.Left); if (rr != null) { // Support both local variables and member variables MemberResolveResult mrr = rr as MemberResolveResult; @@ -497,7 +498,7 @@ namespace Hornung.ResourceToolkit.Resolver } else if (this.resourceManagerMember is IField && resolvedMember is IProperty) { // Find out if the resolved member is a property whose set block assigns the value to the resourceManagerMember. - PropertyFieldAssociationVisitor visitor = new PropertyFieldAssociationVisitor((IField)this.resourceManagerMember); + PropertyFieldAssociationVisitor visitor = new PropertyFieldAssociationVisitor((IField)this.resourceManagerMember, this.FileName, this.FileContent); this.compilationUnit.AcceptVisitor(visitor, null); if (visitor.AssociatedProperty != null && visitor.AssociatedProperty.CompareTo(resolvedMember) == 0) { #if DEBUG @@ -534,7 +535,7 @@ namespace Hornung.ResourceToolkit.Resolver if (prop != null) { // Resolve the property association. - PropertyFieldAssociationVisitor visitor = new PropertyFieldAssociationVisitor(prop); + PropertyFieldAssociationVisitor visitor = new PropertyFieldAssociationVisitor(prop, this.FileName, this.FileContent); this.compilationUnit.AcceptVisitor(visitor, null); // Store the association in the instance field. @@ -555,7 +556,7 @@ namespace Hornung.ResourceToolkit.Resolver // Resolve the constructor. // A type derived from the declaration type is also allowed. - MemberResolveResult mrr = this.Resolve(objectCreateExpression, this.resourceManagerMember.DeclaringType.CompilationUnit.FileName) as MemberResolveResult; + MemberResolveResult mrr = this.Resolve(objectCreateExpression) as MemberResolveResult; #if DEBUG if (mrr != null) { @@ -609,7 +610,7 @@ namespace Hornung.ResourceToolkit.Resolver LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver: Found TypeOfExpression in constructor call: " + t.ToString()); #endif - ResolveResult rr = this.Resolve(new TypeReferenceExpression(t.TypeReference), this.resourceManagerMember.DeclaringType.CompilationUnit.FileName, ExpressionContext.Type); + ResolveResult rr = this.Resolve(new TypeReferenceExpression(t.TypeReference), ExpressionContext.Type); #if DEBUG if (rr == null) { diff --git a/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/ICSharpCodeCoreResourceResolver.cs b/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/ICSharpCodeCoreResourceResolver.cs index 52f71f79a7..934592f34d 100644 --- a/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/ICSharpCodeCoreResourceResolver.cs +++ b/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/ICSharpCodeCoreResourceResolver.cs @@ -41,7 +41,7 @@ namespace Hornung.ResourceToolkit.Resolver public override bool SupportsFile(string fileName) { // Any parseable source code file may contain references - if (ICSharpCode.SharpDevelop.ParserService.GetParser(fileName) != null) { + if (ResourceResolverService.GetParser(fileName) != null) { return true; } diff --git a/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/NRefactoryAstCacheService.cs b/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/NRefactoryAstCacheService.cs index 97f57c24db..f34e8dacb6 100644 --- a/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/NRefactoryAstCacheService.cs +++ b/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/NRefactoryAstCacheService.cs @@ -75,11 +75,13 @@ namespace Hornung.ResourceToolkit.Resolver /// public static void DisableCache() { - cacheEnabled = false; - cachedAstInfo.Clear(); - cachedMemberMappings.Clear(); - LoggingService.Info("ResourceToolkit: NRefactoryAstCacheService cache disabled and cleared"); - OnCacheEnabledChanged(EventArgs.Empty); + if (CacheEnabled) { + cacheEnabled = false; + cachedAstInfo.Clear(); + cachedMemberMappings.Clear(); + LoggingService.Info("ResourceToolkit: NRefactoryAstCacheService cache disabled and cleared"); + OnCacheEnabledChanged(EventArgs.Empty); + } } /// @@ -87,13 +89,14 @@ namespace Hornung.ResourceToolkit.Resolver /// /// The language of the file. /// The file to get the AST for. + /// The content of the file to get the AST for. /// A that contains the AST for the specified file, or null if the file cannot be parsed. /// Between calls to and the file is parsed only once. On subsequent accesses the AST is retrieved from the cache. - public static CompilationUnit GetFullAst(SupportedLanguage language, string fileName) + public static CompilationUnit GetFullAst(SupportedLanguage language, string fileName, string fileContent) { CompilationUnit cu; if (!CacheEnabled || !cachedAstInfo.TryGetValue(fileName, out cu)) { - cu = Parse(language, fileName); + cu = Parse(language, fileName, fileContent); if (cu != null && CacheEnabled) { cachedAstInfo.Add(fileName, cu); } @@ -101,9 +104,9 @@ namespace Hornung.ResourceToolkit.Resolver return cu; } - static CompilationUnit Parse(SupportedLanguage language, string fileName) + static CompilationUnit Parse(SupportedLanguage language, string fileName, string fileContent) { - using(ICSharpCode.NRefactory.IParser parser = ParserFactory.CreateParser(language, new StringReader(ParserService.GetParseableFileContent(fileName)))) { + using(ICSharpCode.NRefactory.IParser parser = ParserFactory.CreateParser(language, new StringReader(fileContent))) { if (parser != null) { #if DEBUG LoggingService.Debug("ResourceToolkit: NRefactoryAstCacheService: Parsing file '"+fileName+"'"); @@ -168,17 +171,18 @@ namespace Hornung.ResourceToolkit.Resolver /// use of the cache if possible. /// /// The file name of the source code file that contains the expression to be resolved. + /// The content of the source code file that contains the expression to be resolved. /// The 1-based line number of the expression. /// The 1-based column number of the expression. /// The CompilationUnit that contains the NRefactory AST for this file. May be null (then the CompilationUnit is retrieved from the cache or the file is parsed). /// The expression to be resolved. /// The ExpressionContext of the expression. /// A ResolveResult or null if the expression cannot be resolved. - public static ResolveResult ResolveLowLevel(string fileName, int caretLine, int caretColumn, CompilationUnit compilationUnit, string expression, ExpressionContext context) + public static ResolveResult ResolveLowLevel(string fileName, string fileContent, int caretLine, int caretColumn, CompilationUnit compilationUnit, string expression, ExpressionContext context) { Expression expr = ParseExpression(fileName, expression, caretLine, caretColumn); if (expr == null) return null; - return ResolveLowLevel(fileName, caretLine, caretColumn, compilationUnit, expression, expr, context); + return ResolveLowLevel(fileName, fileContent, caretLine, caretColumn, compilationUnit, expression, expr, context); } /// @@ -186,6 +190,7 @@ namespace Hornung.ResourceToolkit.Resolver /// use of the cache if possible. /// /// The file name of the source code file that contains the expression to be resolved. + /// The content of the source code file that contains the expression to be resolved. /// The 1-based line number of the expression. /// The 1-based column number of the expression. /// The CompilationUnit that contains the NRefactory AST for this file. May be null (then the CompilationUnit is retrieved from the cache or the file is parsed). @@ -194,11 +199,14 @@ namespace Hornung.ResourceToolkit.Resolver /// The ExpressionContext of the expression. /// A ResolveResult or null if the expression cannot be resolved. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters", MessageId = "4#")] - public static ResolveResult ResolveLowLevel(string fileName, int caretLine, int caretColumn, CompilationUnit compilationUnit, string expressionString, Expression expression, ExpressionContext context) + public static ResolveResult ResolveLowLevel(string fileName, string fileContent, int caretLine, int caretColumn, CompilationUnit compilationUnit, string expressionString, Expression expression, ExpressionContext context) { if (fileName == null) { throw new ArgumentNullException("fileName"); } + if (fileContent == null) { + throw new ArgumentNullException("fileName"); + } if (expression == null) { throw new ArgumentNullException("expression"); } @@ -209,19 +217,19 @@ namespace Hornung.ResourceToolkit.Resolver return null; } - IProjectContent pc = ParserService.GetProjectContent(p); + IProjectContent pc = ResourceResolverService.GetProjectContent(p); if (pc == null) { LoggingService.Info("ResourceToolkit: NRefactoryAstCacheService: ResolveLowLevel failed. ProjectContent is null for project '"+p.ToString()+"'"); return null; } - NRefactoryResolver resolver = ParserService.CreateResolver(fileName) as NRefactoryResolver; + NRefactoryResolver resolver = ResourceResolverService.CreateResolver(fileName) as NRefactoryResolver; if (resolver == null) { resolver = new NRefactoryResolver(LanguageProperties.CSharp); } if (compilationUnit == null) { - compilationUnit = GetFullAst(resolver.Language, fileName); + compilationUnit = GetFullAst(resolver.Language, fileName, fileContent); } if (compilationUnit == null) { LoggingService.Info("ResourceToolkit: NRefactoryAstCacheService: ResolveLowLevel failed due to the compilation unit being unavailable."); @@ -280,14 +288,15 @@ namespace Hornung.ResourceToolkit.Resolver /// The 0-based line number of the expression. /// The 0-based column number of the expression. /// The file name of the source code file that contains the expression to be resolved. + /// The content of the source code file that contains the expression to be resolved. /// The ExpressionFinder for this source code file. /// A ResolveResult or null if the outer expression cannot be resolved or if the specified expression is the outermost expression. - public static ResolveResult ResolveNextOuterExpression(ref ExpressionResult expressionResult, int caretLine, int caretColumn, string fileName, IExpressionFinder expressionFinder) + public static ResolveResult ResolveNextOuterExpression(ref ExpressionResult expressionResult, int caretLine, int caretColumn, string fileName, string fileContent, IExpressionFinder expressionFinder) { if (!String.IsNullOrEmpty(expressionResult.Expression = expressionFinder.RemoveLastPart(expressionResult.Expression))) { Expression nextExpression; if ((nextExpression = ParseExpression(fileName, expressionResult.Expression, caretLine + 1, caretColumn + 1)) != null) { - return ResolveLowLevel(fileName, caretLine + 1, caretColumn + 1, null, expressionResult.Expression, nextExpression, expressionResult.Context); + return ResolveLowLevel(fileName, fileContent, caretLine + 1, caretColumn + 1, null, expressionResult.Expression, nextExpression, expressionResult.Context); } } return null; diff --git a/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/NRefactoryResourceResolver.cs b/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/NRefactoryResourceResolver.cs index 76d72360d8..d44c38ebc3 100644 --- a/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/NRefactoryResourceResolver.cs +++ b/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/NRefactoryResourceResolver.cs @@ -48,6 +48,11 @@ namespace Hornung.ResourceToolkit.Resolver } } + public static void SetResourceResolversListUnitTestOnly(IEnumerable resolversToSet) + { + resolvers = new List(resolversToSet); + } + // ******************************************************************************************************************************** /// @@ -106,7 +111,7 @@ namespace Hornung.ResourceToolkit.Resolver /// A that describes which resource is referenced by the expression at the specified position in the specified file, or null if that expression does not reference a (known) resource. protected override ResourceResolveResult Resolve(string fileName, IDocument document, int caretLine, int caretColumn, int caretOffset, char? charTyped) { - IExpressionFinder ef = ParserService.GetExpressionFinder(fileName); + IExpressionFinder ef = ResourceResolverService.GetExpressionFinder(fileName); if (ef == null) { return null; } @@ -152,7 +157,7 @@ namespace Hornung.ResourceToolkit.Resolver /// static ResourceResolveResult TryResolve(ExpressionResult result, Expression expr, int caretLine, int caretColumn, string fileName, string fileContent, IExpressionFinder expressionFinder, char? charTyped) { - ResolveResult rr = NRefactoryAstCacheService.ResolveLowLevel(fileName, caretLine+1, caretColumn+1, null, result.Expression, expr, result.Context); + ResolveResult rr = NRefactoryAstCacheService.ResolveLowLevel(fileName, fileContent, caretLine+1, caretColumn+1, null, result.Expression, expr, result.Context); if (rr != null) { ResourceResolveResult rrr; @@ -205,7 +210,7 @@ namespace Hornung.ResourceToolkit.Resolver // Find all source files that contain a type with the same // name as the resource we are looking for. List possibleSourceFiles = new List(); - IProjectContent pc = ParserService.GetProjectContent(p); + IProjectContent pc = ResourceResolverService.GetProjectContent(p); if (pc != null) { IClass resourceClass = pc.GetClass(resourceName, 0); @@ -449,7 +454,7 @@ namespace Hornung.ResourceToolkit.Resolver /// The language properties of the specified file, or null if the language cannot be determined. public static LanguageProperties GetLanguagePropertiesForFile(string fileName) { - ICSharpCode.SharpDevelop.Dom.IParser p = ParserService.GetParser(fileName); + ICSharpCode.SharpDevelop.Dom.IParser p = ResourceResolverService.GetParser(fileName); if (p == null) { return null; } diff --git a/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/PositionTrackingAstVisitor.cs b/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/PositionTrackingAstVisitor.cs index f7e8caae99..3585605f92 100644 --- a/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/PositionTrackingAstVisitor.cs +++ b/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/PositionTrackingAstVisitor.cs @@ -20,8 +20,10 @@ namespace Hornung.ResourceToolkit.Resolver /// public abstract class PositionTrackingAstVisitor : ICSharpCode.NRefactory.Visitors.NodeTrackingAstVisitor { + readonly Stack parentNodes = new Stack(); - private Stack parentNodes; + readonly string fileName; + readonly string fileContent; protected override void BeginVisit(INode node) { @@ -77,6 +79,14 @@ namespace Hornung.ResourceToolkit.Resolver } } + protected string FileName { + get { return fileName; } + } + + protected string FileContent { + get { return fileContent; } + } + // ******************************************************************************************************************************** private CompilationUnit compilationUnit; @@ -93,19 +103,17 @@ namespace Hornung.ResourceToolkit.Resolver /// Resolves an expression in the current node's context. /// /// The expression to be resolved. - /// The file name of the source file that contains the expression to be resolved. - public ResolveResult Resolve(Expression expression, string fileName) + public ResolveResult Resolve(Expression expression) { - return this.Resolve(expression, fileName, ExpressionContext.Default); + return this.Resolve(expression, ExpressionContext.Default); } /// /// Resolves an expression in the current node's context. /// /// The expression to be resolved. - /// The file name of the source file that contains the expression to be resolved. /// The ExpressionContext. - public ResolveResult Resolve(Expression expression, string fileName, ExpressionContext context) + public ResolveResult Resolve(Expression expression, ExpressionContext context) { if (!this.PositionAvailable) { LoggingService.Info("ResourceToolkit: PositionTrackingAstVisitor: Resolve failed due to position information being unavailable. Expression: "+expression.ToString()); @@ -116,7 +124,7 @@ namespace Hornung.ResourceToolkit.Resolver LoggingService.Debug("ResourceToolkit: PositionTrackingAstVisitor: Using this parent node for resolve: "+this.parentNodes.Peek().ToString()); #endif - return NRefactoryAstCacheService.ResolveLowLevel(fileName, this.CurrentNodeStartLocation.Y, this.CurrentNodeStartLocation.X+1, this.compilationUnit, null, expression, context); + return NRefactoryAstCacheService.ResolveLowLevel(this.fileName, this.fileContent, this.CurrentNodeStartLocation.Y, this.CurrentNodeStartLocation.X+1, this.compilationUnit, null, expression, context); } // ******************************************************************************************************************************** @@ -124,9 +132,18 @@ namespace Hornung.ResourceToolkit.Resolver /// /// Initializes a new instance of the class. /// - protected PositionTrackingAstVisitor() : base() + protected PositionTrackingAstVisitor(string fileName, string fileContent) + : base() { - this.parentNodes = new Stack(); + if (fileName == null) { + throw new ArgumentNullException("fileName"); + } + if (fileContent == null) { + throw new ArgumentNullException("fileContent"); + } + + this.fileName = fileName; + this.fileContent = fileContent; } } } diff --git a/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/PropertyFieldAssociationVisitor.cs b/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/PropertyFieldAssociationVisitor.cs index 280d2c2c1f..762b36759f 100644 --- a/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/PropertyFieldAssociationVisitor.cs +++ b/src/AddIns/Misc/ResourceToolkit/Project/Src/Resolver/PropertyFieldAssociationVisitor.cs @@ -115,7 +115,10 @@ namespace Hornung.ResourceToolkit.Resolver } // Resolve the expression. - MemberResolveResult mrr = this.Resolve(expr, this.memberToFind.DeclaringType.CompilationUnit.FileName) as MemberResolveResult; + if (!FileUtility.IsEqualFileName(this.FileName, this.memberToFind.DeclaringType.CompilationUnit.FileName)) { + throw new InvalidOperationException("The PropertyFieldAssociationVisitor does currently not support the case that the field is declared in a different file than the property."); + } + MemberResolveResult mrr = this.Resolve(expr) as MemberResolveResult; if (mrr != null && mrr.ResolvedMember is IField) { PropertyDeclaration pd; @@ -138,7 +141,7 @@ namespace Hornung.ResourceToolkit.Resolver if (this.memberToFind.CompareTo(mrr.ResolvedMember) == 0) { // Resolve the property. - MemberResolveResult prr = NRefactoryAstCacheService.ResolveLowLevel(this.memberToFind.DeclaringType.CompilationUnit.FileName, pd.StartLocation.Y, pd.StartLocation.X+1, null, pd.Name, ExpressionContext.Default) as MemberResolveResult; + MemberResolveResult prr = NRefactoryAstCacheService.ResolveLowLevel(this.FileName, this.FileContent, pd.StartLocation.Y, pd.StartLocation.X+1, null, pd.Name, ExpressionContext.Default) as MemberResolveResult; if (prr != null) { #if DEBUG @@ -174,7 +177,10 @@ namespace Hornung.ResourceToolkit.Resolver assignmentExpression.Op == AssignmentOperatorType.Assign && data != null) { // Resolve the expression. - MemberResolveResult mrr = this.Resolve(assignmentExpression.Left, this.memberToFind.DeclaringType.CompilationUnit.FileName) as MemberResolveResult; + if (!FileUtility.IsEqualFileName(this.FileName, this.memberToFind.DeclaringType.CompilationUnit.FileName)) { + throw new InvalidOperationException("The PropertyFieldAssociationVisitor does currently not support the case that the field is declared in a different file than the property."); + } + MemberResolveResult mrr = this.Resolve(assignmentExpression.Left) as MemberResolveResult; if (mrr != null && mrr.ResolvedMember is IField && !((IField)mrr.ResolvedMember).IsLocalVariable) { PropertyDeclaration pd; @@ -197,7 +203,7 @@ namespace Hornung.ResourceToolkit.Resolver if (this.memberToFind.CompareTo(mrr.ResolvedMember) == 0) { // Resolve the property. - MemberResolveResult prr = NRefactoryAstCacheService.ResolveLowLevel(this.memberToFind.DeclaringType.CompilationUnit.FileName, pd.StartLocation.Y, pd.StartLocation.X+1, null, pd.Name, ExpressionContext.Default) as MemberResolveResult; + MemberResolveResult prr = NRefactoryAstCacheService.ResolveLowLevel(this.FileName, this.FileContent, pd.StartLocation.Y, pd.StartLocation.X+1, null, pd.Name, ExpressionContext.Default) as MemberResolveResult; if (prr != null) { #if DEBUG @@ -230,7 +236,8 @@ namespace Hornung.ResourceToolkit.Resolver /// Initializes a new instance of the class. /// /// The property to find the associated field for. - public PropertyFieldAssociationVisitor(IProperty property) : base() + public PropertyFieldAssociationVisitor(IProperty property, string fileName, string fileContent) + : base(fileName, fileContent) { if (property == null) { throw new ArgumentNullException("property"); @@ -243,7 +250,8 @@ namespace Hornung.ResourceToolkit.Resolver /// /// The field to find the associated property for. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId = "System.ArgumentException.#ctor(System.String,System.String)")] - public PropertyFieldAssociationVisitor(IField field) : base() + public PropertyFieldAssociationVisitor(IField field, string fileName, string fileContent) + : base(fileName, fileContent) { if (field == null) { throw new ArgumentNullException("field"); diff --git a/src/AddIns/Misc/ResourceToolkit/Project/Src/ResourceFileContent/ResourceFileContentRegistry.cs b/src/AddIns/Misc/ResourceToolkit/Project/Src/ResourceFileContent/ResourceFileContentRegistry.cs index aa054fc042..8ede5a858d 100644 --- a/src/AddIns/Misc/ResourceToolkit/Project/Src/ResourceFileContent/ResourceFileContentRegistry.cs +++ b/src/AddIns/Misc/ResourceToolkit/Project/Src/ResourceFileContent/ResourceFileContentRegistry.cs @@ -42,15 +42,14 @@ namespace Hornung.ResourceToolkit.ResourceFileContent /// Gets the resource content for the specified file. /// /// The name of the file to get a resource content for. - /// The resource content for the specified file. - /// The format of the specified resource file cannot be handled. + /// The resource content for the specified file, or null if the format of the specified resource file cannot be handled. public static IResourceFileContent GetResourceFileContent(string fileName) { IResourceFileContent c; if (!resourceFileContents.TryGetValue(fileName, out c)) { c = CreateResourceFileContent(fileName); if (c == null) { - throw new NotSupportedException("The format of the resource file '"+fileName+"' cannot be handled by any registered resource file content factory."); + return null; } resourceFileContents[fileName] = c; } diff --git a/src/AddIns/Misc/ResourceToolkit/Project/Src/ResourceResolverService.cs b/src/AddIns/Misc/ResourceToolkit/Project/Src/ResourceResolverService.cs index dca4f77a89..38d085fd44 100644 --- a/src/AddIns/Misc/ResourceToolkit/Project/Src/ResourceResolverService.cs +++ b/src/AddIns/Misc/ResourceToolkit/Project/Src/ResourceResolverService.cs @@ -12,6 +12,9 @@ using System.Text; using Hornung.ResourceToolkit.Resolver; using Hornung.ResourceToolkit.ResourceFileContent; using ICSharpCode.Core; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Project; using ICSharpCode.TextEditor; using ICSharpCode.TextEditor.Document; @@ -44,6 +47,11 @@ namespace Hornung.ResourceToolkit } } + public static void SetResourceResolversListUnitTestOnly(IEnumerable resolversToSet) + { + resolvers = new List(resolversToSet); + } + // ******************************************************************************************************************************** /// @@ -133,5 +141,79 @@ namespace Hornung.ResourceToolkit return sb.ToString(); } + // ******************************************************************************************************************************** + + // The following helper methods are needed to support running + // in the unit testing mode where the addin tree is not available. + + static Dictionary presetParsersUnitTestOnly; + + public static void SetParsersUnitTestOnly(Dictionary parsers) + { + presetParsersUnitTestOnly = parsers; + } + + public static IParser GetParser(string fileName) + { + IParser p; + if (presetParsersUnitTestOnly == null) { + p = ParserService.GetParser(fileName); + } else { + presetParsersUnitTestOnly.TryGetValue(System.IO.Path.GetExtension(fileName), out p); + } + return p; + } + + public static IExpressionFinder GetExpressionFinder(string fileName) + { + IParser p = GetParser(fileName); + if (p == null) return null; + return p.CreateExpressionFinder(fileName); + } + + public static IResolver CreateResolver(string fileName) + { + IParser p = GetParser(fileName); + if (p == null) return null; + return p.CreateResolver(); + } + + static Dictionary fileContents; + + public static void SetFileContentUnitTestOnly(string fileName, string fileContent) + { + if (fileContents == null) { + fileContents = new Dictionary(); + } + fileContents[fileName] = fileContent; + } + + public static string GetParsableFileContent(string fileName) + { + if (fileContents == null) { + return ParserService.GetParseableFileContent(fileName); + } else { + return fileContents[fileName]; + } + } + + static Dictionary projectContents; + + public static void SetProjectContentUnitTestOnly(IProject project, IProjectContent projectContent) + { + if (projectContents == null) { + projectContents = new Dictionary(); + } + projectContents[project] = projectContent; + } + + public static IProjectContent GetProjectContent(IProject project) + { + if (projectContents == null) { + return ParserService.GetProjectContent(project); + } else { + return projectContents[project]; + } + } } } diff --git a/src/AddIns/Misc/ResourceToolkit/Test/AbstractResourceResolverTestFixture.cs b/src/AddIns/Misc/ResourceToolkit/Test/AbstractResourceResolverTestFixture.cs new file mode 100644 index 0000000000..fad8ebd772 --- /dev/null +++ b/src/AddIns/Misc/ResourceToolkit/Test/AbstractResourceResolverTestFixture.cs @@ -0,0 +1,85 @@ +// +// +// +// +// $Revision$ +// + +using System; + +using Hornung.ResourceToolkit; +using Hornung.ResourceToolkit.Resolver; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.TextEditor.Document; +using NUnit.Framework; + +namespace ResourceToolkit.Tests +{ + public abstract class AbstractResourceResolverTestFixture : AbstractTestProjectTestFixture + { + protected abstract string DefaultFileName { + get; + } + + protected override void DoSetUp() + { + base.DoSetUp(); + TestHelper.InitializeResolvers(); + } + + protected void EnlistTestFile(string fileName, string code, bool parseFile) + { + ResourceResolverService.SetFileContentUnitTestOnly(fileName, code); + ProjectFileDictionaryService.AddFile(fileName, this.Project); + + if (parseFile) { + IParser parser = ResourceResolverService.GetParser(fileName); + Assert.IsNotNull(parser, "Could not get parser for " + fileName+ "."); + ICompilationUnit cu = parser.Parse(this.DefaultProjectContent, fileName, code); + cu.Freeze(); + Assert.IsFalse(cu.ErrorsDuringCompile, "Errors while parsing test program."); + ParserService.RegisterParseInformation(fileName, cu); + this.DefaultProjectContent.UpdateCompilationUnit(null, cu, fileName); + } + } + + /// + /// Resolves a resource reference. + /// Line and column are 0-based. + /// + protected ResourceResolveResult Resolve(string fileName, string code, int caretLine, int caretColumn, char? charTyped, bool parseFile) + { + this.EnlistTestFile(fileName, code, parseFile); + IDocument doc = new DocumentFactory().CreateDocument(); + doc.TextContent = code; + return ResourceResolverService.Resolve(fileName, doc, caretLine, caretColumn, charTyped); + } + + /// + /// Resolves a resource reference. + /// Line and column are 0-based. + /// + protected ResourceResolveResult Resolve(string code, int caretLine, int caretColumn, char? charTyped) + { + return this.Resolve(this.DefaultFileName, code, caretLine, caretColumn, charTyped, true); + } + + protected override void DoTearDown() + { + base.DoTearDown(); + NRefactoryAstCacheService.DisableCache(); + } + + protected override void Dispose(bool disposing) + { + try { + if (disposing) { + NRefactoryAstCacheService.DisableCache(); + } + } finally { + base.Dispose(disposing); + } + } + } +} diff --git a/src/AddIns/Misc/ResourceToolkit/Test/AbstractTestProjectTestFixture.cs b/src/AddIns/Misc/ResourceToolkit/Test/AbstractTestProjectTestFixture.cs new file mode 100644 index 0000000000..632587dc35 --- /dev/null +++ b/src/AddIns/Misc/ResourceToolkit/Test/AbstractTestProjectTestFixture.cs @@ -0,0 +1,110 @@ +// +// +// +// +// $Revision$ +// + +using System; + +using Hornung.ResourceToolkit; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Project; +using NUnit.Framework; + +namespace ResourceToolkit.Tests +{ + public abstract class AbstractTestProjectTestFixture : IDisposable + { + Solution solution; + IProject project; + DefaultProjectContent defaultPC; + + [SetUp] + public void SetUp() + { + this.DoSetUp(); + } + + [TearDown] + public void TearDown() + { + this.DoTearDown(); + } + + public void Dispose() + { + this.Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) { + this.DoTearDown(); + } + } + + protected virtual void DoSetUp() + { + TestHelper.InitializeParsers(); + + this.solution = new Solution(); + this.project = this.CreateTestProject(); + ProjectService.CurrentProject = this.project; + + DefaultProjectContent pc = this.CreateNewProjectContent(this.project); + HostCallback.GetCurrentProjectContent = delegate { + return pc; + }; + ResourceResolverService.SetProjectContentUnitTestOnly(this.project, pc); + this.defaultPC = pc; + } + + protected virtual void DoTearDown() + { + if (this.defaultPC != null) { + this.defaultPC.Dispose(); + this.defaultPC = null; + } + if (this.project != null) { + this.project.Dispose(); + this.project = null; + } + if (this.solution != null) { + this.solution.Dispose(); + this.solution = null; + } + } + + protected abstract IProject CreateTestProject(); + + protected IProject Project { + get { return this.project; } + } + + protected DefaultProjectContent DefaultProjectContent { + get { return this.defaultPC; } + } + + protected Solution Solution { + get { return this.solution; } + } + + protected virtual DefaultProjectContent CreateNewProjectContent(IProject project) + { + DefaultProjectContent pc = new DefaultProjectContent(); + + pc.ReferencedContents.Add(ParserService.DefaultProjectContentRegistry.Mscorlib); + pc.ReferencedContents.Add(ParserService.DefaultProjectContentRegistry.GetProjectContentForReference("System", "System")); + + if (project != null) { + if (project.LanguageProperties != null) { + pc.Language = project.LanguageProperties; + } + } + + return pc; + } + } +} diff --git a/src/AddIns/Misc/ResourceToolkit/Test/CSharp/AbstractCSharpResourceResolverTestFixture.cs b/src/AddIns/Misc/ResourceToolkit/Test/CSharp/AbstractCSharpResourceResolverTestFixture.cs new file mode 100644 index 0000000000..c9656830ad --- /dev/null +++ b/src/AddIns/Misc/ResourceToolkit/Test/CSharp/AbstractCSharpResourceResolverTestFixture.cs @@ -0,0 +1,38 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.IO; + +using CSharpBinding; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Internal.Templates; +using ICSharpCode.SharpDevelop.Project; +using NUnit.Framework; + +namespace ResourceToolkit.Tests.CSharp +{ + public abstract class AbstractCSharpResourceResolverTestFixture : AbstractResourceResolverTestFixture + { + protected override string DefaultFileName { + get { return "a.cs"; } + } + + protected override IProject CreateTestProject() + { + ProjectCreateInformation info = new ProjectCreateInformation(); + info.ProjectName = "Test"; + info.RootNamespace = "Test"; + info.OutputProjectFileName = Path.Combine(Path.GetTempPath(), "Test.csproj"); + info.Solution = this.Solution; + + CSharpProject p = new CSharpProject(info); + return p; + } + } +} diff --git a/src/AddIns/Misc/ResourceToolkit/Test/CSharp/AnyResourceReferenceFinderTests.cs b/src/AddIns/Misc/ResourceToolkit/Test/CSharp/AnyResourceReferenceFinderTests.cs new file mode 100644 index 0000000000..c6a663873b --- /dev/null +++ b/src/AddIns/Misc/ResourceToolkit/Test/CSharp/AnyResourceReferenceFinderTests.cs @@ -0,0 +1,104 @@ +// +// +// +// +// $Revision$ +// + +using System; + +using Hornung.ResourceToolkit.Refactoring; +using Hornung.ResourceToolkit.Resolver; +using NUnit.Framework; + +namespace ResourceToolkit.Tests.CSharp +{ + /// + /// Tests the AnyResourceReferenceFinder in C#. + /// + [TestFixture] + public sealed class AnyResourceReferenceFinderTests + { + [TestFixtureSetUp] + public void FixtureSetUp() + { + TestHelper.InitializeParsers(); + TestHelper.InitializeResolvers(); + } + + // ******************************************************************************************************************************** + + static AnyResourceReferenceFinder CreateFinder() + { + return new AnyResourceReferenceFinder(); + } + + [Test] + public void NoReference() + { + const string Code = @"class A { + void B() { + DoSomething(); + } +}"; + AnyResourceReferenceFinder finder = CreateFinder(); + Assert.AreEqual(-1, finder.GetNextPossibleOffset("a.cs", Code, -1), "Incorrect offset."); + } + + [Test] + public void OneReference() + { + const string Code = @"class A { + void B() { + resMgr.GetString(""TestKey""); + } +}"; + AnyResourceReferenceFinder finder = CreateFinder(); + Assert.AreEqual(33, finder.GetNextPossibleOffset("a.cs", Code, -1), "Incorrect offset."); + Assert.AreEqual(-1, finder.GetNextPossibleOffset("a.cs", Code, 33), "Incorrect offset."); + } + + [Test] + public void TwoReferences() + { + const string Code = @"class A { + void B() { + resMgr.GetString(""TestKey""); + resMgr[""TestKey""]; + } +}"; + AnyResourceReferenceFinder finder = CreateFinder(); + Assert.AreEqual(33, finder.GetNextPossibleOffset("a.cs", Code, -1), "Incorrect offset."); + Assert.AreEqual(64, finder.GetNextPossibleOffset("a.cs", Code, 33), "Incorrect offset."); + Assert.AreEqual(-1, finder.GetNextPossibleOffset("a.cs", Code, 64), "Incorrect offset."); + } + + [Test] + public void FourReferencesMixed() + { + const string Code = @"class A { + void B() { + resMgr.GetString(""TestKey""); + X(""${res:TestKey2}""); + resMgr[""TestKey""]; + X(""${res:TestKey3}""); + } +}"; + AnyResourceReferenceFinder finder = CreateFinder(); + Assert.AreEqual(33, finder.GetNextPossibleOffset("a.cs", Code, -1), "Incorrect offset."); + Assert.AreEqual(61, finder.GetNextPossibleOffset("a.cs", Code, 33), "Incorrect offset."); + Assert.AreEqual(89, finder.GetNextPossibleOffset("a.cs", Code, 61), "Incorrect offset."); + Assert.AreEqual(108, finder.GetNextPossibleOffset("a.cs", Code, 89), "Incorrect offset."); + Assert.AreEqual(-1, finder.GetNextPossibleOffset("a.cs", Code, 108), "Incorrect offset."); + } + + // ******************************************************************************************************************************** + + [Test] + public void ResultMatch() + { + AnyResourceReferenceFinder finder = CreateFinder(); + Assert.IsTrue(finder.IsReferenceToResource(new ResourceResolveResult(null, null, null, new ResourceSetReference("SomeResources", "C:\\SomeResources.resx"), "SomeKey"))); + } + } +} diff --git a/src/AddIns/Misc/ResourceToolkit/Test/CSharp/BclNRefactoryResourceResolverTests.cs b/src/AddIns/Misc/ResourceToolkit/Test/CSharp/BclNRefactoryResourceResolverTests.cs new file mode 100644 index 0000000000..c45f4e3c98 --- /dev/null +++ b/src/AddIns/Misc/ResourceToolkit/Test/CSharp/BclNRefactoryResourceResolverTests.cs @@ -0,0 +1,815 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; + +using Hornung.ResourceToolkit; +using Hornung.ResourceToolkit.Resolver; +using NUnit.Framework; + +namespace ResourceToolkit.Tests.CSharp +{ + [TestFixture] + public sealed class BclNRefactoryResourceResolverTests : AbstractCSharpResourceResolverTestFixture + { + readonly IResourceResolver resolver = new NRefactoryResourceResolver(); + + IResourceResolver Resolver { + get { return this.resolver; } + } + + // ******************************************************************************************************************************** + + #region === Tests with local variables === + + const string CodeLocalSRMDirectInitFullName = @"class A +{ + void B() + { + System.Resources.ResourceManager mgr = new System.Resources.ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + mgr.GetString(""TestKey""); + mgr[""TestKey2""]; + } + + void C() + { + mgr.GetString(""TestKey""); + mgr[""TestKey2""]; + } +} +"; + + [Test] + public void LocalSRMDirectInitFullNameGetString() + { + ResourceResolveResult rrr = Resolve(CodeLocalSRMDirectInitFullName, 5, 18, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + [Test] + public void LocalSRMDirectInitFullNameNoIndexer() + { + ResourceResolveResult rrr = Resolve(CodeLocalSRMDirectInitFullName, 6, 7, null); + TestHelper.CheckNoReference(rrr); + } + + [Test] + public void LocalSRMDirectInitFullNameOutOfScope() + { + ResourceResolveResult rrr = Resolve(CodeLocalSRMDirectInitFullName, 11, 18, null); + TestHelper.CheckNoReference(rrr); + + rrr = Resolve(CodeLocalSRMDirectInitFullName, 12, 7, null); + TestHelper.CheckNoReference(rrr); + } + + // ******************************************************************************************************************************** + + const string CodeLocalSRMDirectInitFullNameGetStringCompletion = @"class A +{ + void B() + { + System.Resources.ResourceManager mgr = new System.Resources.ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + mgr.GetString + } +} +"; + + [Test] + public void LocalSRMDirectInitFullNameGetStringIncomplete() + { + ResourceResolveResult rrr = Resolve(CodeLocalSRMDirectInitFullNameGetStringCompletion, 5, 15, null); + TestHelper.CheckNoReference(rrr); + } + + [Test] + public void LocalSRMDirectInitFullNameGetStringCompletion() + { + ResourceResolveResult rrr = Resolve(CodeLocalSRMDirectInitFullNameGetStringCompletion, 5, 15, '('); + TestHelper.CheckReference(rrr, "Test.TestResources", null, "A", "A.B"); + } + + [Test] + public void LocalSRMDirectInitFullNameGetStringNoCompletion() + { + ResourceResolveResult rrr = Resolve(CodeLocalSRMDirectInitFullNameGetStringCompletion, 5, 15, '['); + TestHelper.CheckNoReference(rrr); + } + + const string CodeLocalSRMDirectInitFullNameGetStringCompletionBug1 = @"class A +{ + void B() + { + System.Resources.ResourceManager mgr = new System.Resources.ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + mgr.GetString(""TestKey"").Replace + } +} +"; + + [Test] + public void LocalSRMDirectInitFullNameGetStringCompletionBug1() + { + ResourceResolveResult rrr = Resolve(CodeLocalSRMDirectInitFullNameGetStringCompletionBug1, 5, 34, '('); + TestHelper.CheckNoReference(rrr); + } + + // ******************************************************************************************************************************** + + const string CodeLocalIndexerRMDirectInit = @"class IndexerRM : System.Resources.ResourceManager +{ + public IndexerRM(string name, System.Reflection.Assembly assembly) : base(name, assembly) + { + } + public string this[string key] { + get { return this.GetString(key); } + } +} + +class A +{ + void B() + { + IndexerRM mgr = new IndexerRM(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + mgr[""TestKey""]; + mgr + } +} +"; + + [Test] + public void LocalIndexerRMDirectInit() + { + ResourceResolveResult rrr = Resolve(CodeLocalIndexerRMDirectInit, 15, 7, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + [Test] + public void LocalIndexerRMDirectInitCompletionBug1() + { + ResourceResolveResult rrr = Resolve(CodeLocalIndexerRMDirectInit, 15, 16, '['); + TestHelper.CheckNoReference(rrr); + } + + [Test] + public void LocalIndexerRMDirectInitCompletion() + { + ResourceResolveResult rrr = Resolve(CodeLocalIndexerRMDirectInit, 16, 5, '['); + TestHelper.CheckReference(rrr, "Test.TestResources", null, "A", "A.B"); + } + + [Test] + public void LocalIndexerRMDirectInitNoCompletion() + { + ResourceResolveResult rrr = Resolve(CodeLocalIndexerRMDirectInit, 16, 5, null); + TestHelper.CheckNoReference(rrr); + } + + [Test] + public void LocalIndexerRMDirectInitNoCompletionWrongChar() + { + ResourceResolveResult rrr = Resolve(CodeLocalIndexerRMDirectInit, 16, 5, '('); + TestHelper.CheckNoReference(rrr); + } + + // ******************************************************************************************************************************** + + const string CodeLocalIndexerRMBug1 = @"class IndexerRM : System.Resources.ResourceManager +{ + public IndexerRM(string name, System.Reflection.Assembly assembly) : base(name, assembly) + { + } + public string this[string key] { + get { return this.GetString(key); } + } +} + +class A +{ + void B() + { + IndexerRM mgr = new IndexerRM(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + DoSomething(mgr[""TestKey""], ""[""); + } +} +"; + + [Test] + public void LocalIndexerRMBug1FirstRef() + { + ResourceResolveResult rrr = Resolve(CodeLocalIndexerRMBug1, 15, 19, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + // ******************************************************************************************************************************** + + const string CodeLocalSRMDirectInitAlias = @"using SRM = System.Resources.ResourceManager; +class A +{ + void B() + { + SRM mgr = new SRM(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + mgr.GetString(""TestKey""); + mgr[""TestKey2""]; + } +} +"; + + [Test] + public void LocalSRMDirectInitAliasGetString() + { + ResourceResolveResult rrr = Resolve(CodeLocalSRMDirectInitAlias, 6, 18, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + [Test] + public void LocalSRMDirectInitAliasNoIndexer() + { + ResourceResolveResult rrr = Resolve(CodeLocalSRMDirectInitAlias, 7, 7, null); + TestHelper.CheckNoReference(rrr); + } + + // ******************************************************************************************************************************** + + const string CodeLocalSRMDeferredInitUsing = @"using System.Resources; +class A +{ + void B() + { + ResourceManager mgr; + + mgr = new ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + mgr.GetString(""TestKey""); + } +} +"; + + [Test] + public void LocalSRMDeferredInitUsingGetString() + { + ResourceResolveResult rrr = Resolve(CodeLocalSRMDeferredInitUsing, 8, 18, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + #endregion + + // ******************************************************************************************************************************** + + #region === Tests with instance fields === + + const string CodeInstanceFieldSRMDirectInitUsing = @"using System.Resources; +class A +{ + ResourceManager mgr = new ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + + void B() + { + this.mgr.GetString(""TestKey""); + mgr.GetString(""TestKey""); + } +} +"; + + [Test] + public void InstanceFieldSRMDirectInitUsingThisGetString() + { + ResourceResolveResult rrr = Resolve(CodeInstanceFieldSRMDirectInitUsing, 7, 22, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + [Test] + public void InstanceFieldSRMDirectInitUsingGetString() + { + ResourceResolveResult rrr = Resolve(CodeInstanceFieldSRMDirectInitUsing, 8, 17, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + // ******************************************************************************************************************************** + + const string CodeInstanceFieldSRMDeferredInitThisUsing = @"using System.Resources; +class A +{ + ResourceManager mgr; + public A() + { + this.mgr = new ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + } + void B() + { + this.mgr.GetString(""TestKey""); + } +} +"; + + [Test] + public void InstanceFieldSRMDeferredInitThisUsingThisGetString() + { + ResourceResolveResult rrr = Resolve(CodeInstanceFieldSRMDeferredInitThisUsing, 10, 22, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + const string CodeInstanceFieldSRMDeferredInitUsing = @"using System.Resources; +class A +{ + ResourceManager mgr; + public A() + { + mgr = new ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + } + void B() + { + this.mgr.GetString(""TestKey""); + } +} +"; + + [Test] + public void InstanceFieldSRMDeferredInitUsingThisGetString() + { + ResourceResolveResult rrr = Resolve(CodeInstanceFieldSRMDeferredInitUsing, 10, 22, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + #endregion + + // ******************************************************************************************************************************** + + #region === Tests with static fields === + + const string CodeStaticFieldSRMDirectInitUsing = @"using System.Resources; +class A +{ + static ResourceManager mgr = new ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + + void B() + { + A.mgr.GetString(""TestKey""); + mgr.GetString(""TestKey""); + } +} +"; + + [Test] + public void StaticFieldSRMDirectInitUsingClassGetString() + { + ResourceResolveResult rrr = Resolve(CodeStaticFieldSRMDirectInitUsing, 7, 19, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + [Test] + public void StaticFieldSRMDirectInitUsingGetString() + { + ResourceResolveResult rrr = Resolve(CodeInstanceFieldSRMDirectInitUsing, 8, 17, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + // ******************************************************************************************************************************** + + const string CodeStaticFieldSRMDeferredInitClassUsing = @"using System.Resources; +class A +{ + static ResourceManager mgr; + static A() + { + A.mgr = new ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + } + void B() + { + A.mgr.GetString(""TestKey""); + } +} +"; + + [Test] + public void StaticFieldSRMDeferredInitClassUsingClassGetString() + { + ResourceResolveResult rrr = Resolve(CodeStaticFieldSRMDeferredInitClassUsing, 10, 19, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + const string CodeStaticFieldSRMDeferredInitUsing = @"using System.Resources; +class A +{ + static ResourceManager mgr; + static A() + { + mgr = new ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + } + void B() + { + A.mgr.GetString(""TestKey""); + } +} +"; + + [Test] + public void StaticFieldSRMDeferredInitUsingClassGetString() + { + ResourceResolveResult rrr = Resolve(CodeStaticFieldSRMDeferredInitUsing, 10, 19, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + #endregion + + // ******************************************************************************************************************************** + + #region === Tests with instance properties === + + const string CodeInstancePropertySRMFieldDirectInitUsing = @"using System.Resources; +class A +{ + public ResourceManager Resources { + get { return mgr; } + } + + ResourceManager mgr = new ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + + void B() + { + this.Resources.GetString(""TestKey""); + Resources.GetString(""TestKey""); + } +} +"; + + [Test] + public void InstancePropertySRMFieldDirectInitUsingThisGetString() + { + ResourceResolveResult rrr = Resolve(CodeInstancePropertySRMFieldDirectInitUsing, 11, 28, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + [Test] + public void InstancePropertySRMFieldDirectInitUsingGetString() + { + ResourceResolveResult rrr = Resolve(CodeInstancePropertySRMFieldDirectInitUsing, 12, 23, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + // ******************************************************************************************************************************** + + const string CodeInstancePropertySRMDeferredFieldInitThisUsing = @"using System.Resources; +class A +{ + ResourceManager mgr; + + public ResourceManager Resources { + get { return mgr; } + } + + public A() + { + this.mgr = new ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + } + void B() + { + this.Resources.GetString(""TestKey""); + } +} +"; + + [Test] + public void InstancePropertySRMDeferredFieldInitThisUsingThisGetString() + { + ResourceResolveResult rrr = Resolve(CodeInstancePropertySRMDeferredFieldInitThisUsing, 15, 28, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + // ******************************************************************************************************************************** + + const string CodeInstancePropertySRMDeferredPropertyInitThisUsing = @"using System.Resources; +class A +{ + ResourceManager mgr; + + public ResourceManager Resources { + get { return mgr; } + private set { mgr = value; } + } + + public A() + { + this.Resources = new ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + } + void B() + { + this.Resources.GetString(""TestKey""); + } +} +"; + + [Test] + public void InstancePropertySRMDeferredPropertyInitThisUsingThisGetString() + { + ResourceResolveResult rrr = Resolve(CodeInstancePropertySRMDeferredPropertyInitThisUsing, 16, 28, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + const string CodeInstanceFieldSRMDeferredWriteOnlyPropertyInitThisUsing = @"using System.Resources; +class A +{ + ResourceManager mgr; + + private ResourceManager Resources { + set { mgr = value; } + } + + public A() + { + this.Resources = new ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + } + void B() + { + this.mgr.GetString(""TestKey""); + } +} +"; + + [Test] + public void InstanceFieldSRMDeferredWriteOnlyPropertyInitThisUsingThisGetString() + { + ResourceResolveResult rrr = Resolve(CodeInstanceFieldSRMDeferredWriteOnlyPropertyInitThisUsing, 15, 22, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + // ******************************************************************************************************************************** + + const string CodeInstancePropertySRMInvalidReturnTypeBug = @"using System.Resources; +class A +{ + ResourceManager mgr; + + public ResourceManager Resources { + get { return mgr; } + private set { mgr = value; } + } + + public A() + { + foo bar; + bar = 1; + this.Resources = new ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + this.Resources.GetString + } +} +"; + + [Test] + public void InstancePropertySRMInvalidReturnTypeBug() + { + ResourceResolveResult rrr = Resolve(CodeInstancePropertySRMInvalidReturnTypeBug, 15, 26, '('); + TestHelper.CheckReference(rrr, "Test.TestResources", null, "A", "A.#ctor"); + } + + #endregion + + // ******************************************************************************************************************************** + + #region === Tests with static properties === + + const string CodeStaticPropertySRMFieldDirectInitUsing = @"using System.Resources; +class A +{ + public static ResourceManager Resources { + get { return mgr; } + } + + static ResourceManager mgr = new ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + + void B() + { + A.Resources.GetString(""TestKey""); + Resources.GetString(""TestKey""); + } +} +"; + + [Test] + public void StaticPropertySRMFieldDirectInitUsingClassGetString() + { + ResourceResolveResult rrr = Resolve(CodeStaticPropertySRMFieldDirectInitUsing, 11, 25, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + [Test] + public void StaticPropertySRMFieldDirectInitUsingGetString() + { + ResourceResolveResult rrr = Resolve(CodeStaticPropertySRMFieldDirectInitUsing, 12, 23, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + // ******************************************************************************************************************************** + + const string CodeStaticPropertySRMDeferredFieldInitClassUsing = @"using System.Resources; +class A +{ + static ResourceManager mgr; + + public static ResourceManager Resources { + get { return mgr; } + } + + static A() + { + A.mgr = new ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + } + void B() + { + A.Resources.GetString(""TestKey""); + } +} +"; + + [Test] + public void StaticPropertySRMDeferredFieldInitClassUsingClassGetString() + { + ResourceResolveResult rrr = Resolve(CodeStaticPropertySRMDeferredFieldInitClassUsing, 15, 25, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + // ******************************************************************************************************************************** + + const string CodeStaticPropertySRMDeferredPropertyInitClassUsing = @"using System.Resources; +class A +{ + static ResourceManager mgr; + + public static ResourceManager Resources { + get { return mgr; } + private set { mgr = value; } + } + + static A() + { + A.Resources = new ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + } + void B() + { + A.Resources.GetString(""TestKey""); + } +} +"; + + [Test] + public void StaticPropertySRMDeferredPropertyInitClassUsingClassGetString() + { + ResourceResolveResult rrr = Resolve(CodeStaticPropertySRMDeferredPropertyInitClassUsing, 16, 25, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + const string CodeStaticFieldSRMDeferredWriteOnlyPropertyInitClassUsing = @"using System.Resources; +class A +{ + static ResourceManager mgr; + + private static ResourceManager Resources { + set { mgr = value; } + } + + static A() + { + A.Resources = new ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + } + void B() + { + A.mgr.GetString(""TestKey""); + } +} +"; + + [Test] + public void StaticFieldSRMDeferredWriteOnlyPropertyInitClassUsingClassGetString() + { + ResourceResolveResult rrr = Resolve(CodeStaticFieldSRMDeferredWriteOnlyPropertyInitClassUsing, 15, 19, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + } + + #endregion + + // ******************************************************************************************************************************** + // ******************************************************************************************************************************** + + #region === Tests for specific behavior === + + const string CodeUnescapeResourceKey = @"using System.Resources; +class A { + void B() + { + ResourceManager mgr = new ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + mgr.GetString(""Some\""strange\""key""); + } +} +"; + + [Test] + public void UnescapeResourceKey() + { + ResourceResolveResult rrr = Resolve(CodeUnescapeResourceKey, 5, 17, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "Some\"strange\"key", "A", "A.B"); + } + + // ******************************************************************************************************************************** + + const string CodeSRMTypeOfInit = @"using System.Resources; +namespace Test { + class A { + void B() + { + ResourceManager mgr = new ResourceManager(typeof(A)); + mgr.GetString(""TestKey""); + } + } +} +"; + + [Test] + public void SRMTypeOfInit() + { + ResourceResolveResult rrr = Resolve(CodeSRMTypeOfInit, 6, 18, null); + TestHelper.CheckReference(rrr, "Test.A", "TestKey", "Test.A", "Test.A.B"); + } + + // ******************************************************************************************************************************** + + [Test] + public void ResolverSupportsCSharpFiles() + { + Assert.IsTrue(this.Resolver.SupportsFile("a.cs")); + } + + [Test] + public void CSharpFilePatterns() + { + List patterns = new List(this.Resolver.GetPossiblePatternsForFile("a.cs")); + Assert.Contains("GetString", patterns); + Assert.Contains("GetStream", patterns); + Assert.Contains("GetObject", patterns); + Assert.Contains("[", patterns); + Assert.AreEqual(4, patterns.Count, "Incorrect number of resource access patterns for C# files."); + } + + [Test] + public void ResolverDoesNotSupportBooFiles() + { + Assert.IsFalse(this.Resolver.SupportsFile("a.boo")); + } + + [Test] + public void UnsupportedFilePatterns() + { + IEnumerable list = this.Resolver.GetPossiblePatternsForFile("a.boo"); + Assert.IsNotNull(list, "IResourceResolver.GetPossiblePatternsForFile must not return null."); + + List patterns = new List(list); + Assert.AreEqual(0, patterns.Count); + } + + #endregion + + // ******************************************************************************************************************************** + + #region Cache tests + + const string CodeCacheTest = @"class A +{ + void B() + { + System.Resources.ResourceManager mgr = new System.Resources.ResourceManager(""Test.TestResources"", System.Reflection.Assembly.GetExecutingAssembly()); + mgr.GetString(""TestKey""); + mgr.GetString(""TestKey2""); + } +} +"; + + [Test] + public void UseAstCache() + { + NRefactoryAstCacheService.EnableCache(); + + ResourceResolveResult rrr = Resolve(CodeCacheTest, 5, 17, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + + rrr = Resolve(CodeCacheTest, 5, 17, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey", "A", "A.B"); + + rrr = Resolve(CodeCacheTest, 6, 17, null); + TestHelper.CheckReference(rrr, "Test.TestResources", "TestKey2", "A", "A.B"); + + NRefactoryAstCacheService.DisableCache(); + } + + [Test] + [ExpectedException(typeof(InvalidOperationException), ExpectedMessage="The AST cache is already enabled.")] + public void AstCacheEnableTwice() + { + NRefactoryAstCacheService.EnableCache(); + NRefactoryAstCacheService.EnableCache(); + } + + #endregion + } +} diff --git a/src/AddIns/Misc/ResourceToolkit/Test/CSharp/ICSharpCodeCoreNRefactoryResourceResolverTests.cs b/src/AddIns/Misc/ResourceToolkit/Test/CSharp/ICSharpCodeCoreNRefactoryResourceResolverTests.cs new file mode 100644 index 0000000000..9f994ec74b --- /dev/null +++ b/src/AddIns/Misc/ResourceToolkit/Test/CSharp/ICSharpCodeCoreNRefactoryResourceResolverTests.cs @@ -0,0 +1,84 @@ +// +// +// +// +// $Revision$ +// + +using System; + +using Hornung.ResourceToolkit; +using Hornung.ResourceToolkit.Resolver; +using NUnit.Framework; + +namespace ResourceToolkit.Tests.CSharp +{ + [TestFixture] + public sealed class ICSharpCodeCoreNRefactoryResourceResolverTests : AbstractCSharpResourceResolverTestFixture + { + protected override void DoSetUp() + { + base.DoSetUp(); + + const string ICSharpCodeCoreCode = @"namespace ICSharpCode.Core +{ + public class ResourceService + { + public static string GetString(string key) + { + return """"; + } + } +} +"; + this.EnlistTestFile("ICSharpCodeCore.cs", ICSharpCodeCoreCode, true); + } + + // ******************************************************************************************************************************** + + const string CodeClass = @"class A { + void B() { + ICSharpCode.Core.ResourceService.GetString(""TestKey""); + ICSharpCode.Core.ResourceService.GetString + } +}"; + + [Test] + public void GetStringClass() + { + ResourceResolveResult rrr = Resolve(CodeClass, 2, 46, null); + TestHelper.CheckReference(rrr, "[ICSharpCodeCoreHostResourceSet]", "TestKey", "A", "A.B"); + } + + [Test] + public void GetStringClassCompletion() + { + ResourceResolveResult rrr = Resolve(CodeClass, 3, 44, '('); + TestHelper.CheckReference(rrr, "[ICSharpCodeCoreHostResourceSet]", null, "A", "A.B"); + } + + // ******************************************************************************************************************************** + + const string CodeUsing = @"using ICSharpCode.Core; +class A { + void B() { + ResourceService.GetString(""TestKey""); + ResourceService.GetString + } +}"; + + [Test] + public void GetStringUsing() + { + ResourceResolveResult rrr = Resolve(CodeUsing, 3, 29, null); + TestHelper.CheckReference(rrr, "[ICSharpCodeCoreHostResourceSet]", "TestKey", "A", "A.B"); + } + + [Test] + public void GetStringUsingCompletion() + { + ResourceResolveResult rrr = Resolve(CodeUsing, 4, 27, '('); + TestHelper.CheckReference(rrr, "[ICSharpCodeCoreHostResourceSet]", null, "A", "A.B"); + } + } +} diff --git a/src/AddIns/Misc/ResourceToolkit/Test/CSharp/ICSharpCodeCoreResourceResolverTests.cs b/src/AddIns/Misc/ResourceToolkit/Test/CSharp/ICSharpCodeCoreResourceResolverTests.cs new file mode 100644 index 0000000000..9945c3ca45 --- /dev/null +++ b/src/AddIns/Misc/ResourceToolkit/Test/CSharp/ICSharpCodeCoreResourceResolverTests.cs @@ -0,0 +1,195 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; + +using Hornung.ResourceToolkit; +using Hornung.ResourceToolkit.Resolver; +using NUnit.Framework; + +namespace ResourceToolkit.Tests.CSharp +{ + [TestFixture] + public sealed class ICSharpCodeCoreResourceResolverTests : AbstractCSharpResourceResolverTestFixture + { + readonly IResourceResolver resolver = new ICSharpCodeCoreResourceResolver(); + + IResourceResolver Resolver { + get { return this.resolver; } + } + + // ******************************************************************************************************************************** + + const string CodeResourceAccess = @"class A { + string B() { + return ""${res:TestKey}""; + } +}"; + + [Test] + public void ResourceAccessStart() + { + ResourceResolveResult rrr = Resolve(CodeResourceAccess, 2, 10, null); + TestHelper.CheckReference(rrr, "[ICSharpCodeCoreHostResourceSet]", "TestKey", null, null); + } + + [Test] + public void ResourceAccessAtKey() + { + ResourceResolveResult rrr = Resolve(CodeResourceAccess, 2, 17, null); + TestHelper.CheckReference(rrr, "[ICSharpCodeCoreHostResourceSet]", "TestKey", null, null); + } + + [Test] + public void ResourceAccessAtEndOfKey() + { + ResourceResolveResult rrr = Resolve(CodeResourceAccess, 2, 23, null); + TestHelper.CheckReference(rrr, "[ICSharpCodeCoreHostResourceSet]", "TestKey", null, null); + } + + [Test] + public void NoCompletionWrongChar() + { + ResourceResolveResult rrr = Resolve(CodeResourceAccess, 2, 15, 'x'); + TestHelper.CheckNoReference(rrr); + } + + [Test] + public void ResourceAccessAtKeyWithCache() + { + NRefactoryAstCacheService.EnableCache(); + + ResourceResolveResult rrr = Resolve(CodeResourceAccess, 2, 17, null); + TestHelper.CheckReference(rrr, "[ICSharpCodeCoreHostResourceSet]", "TestKey", null, null); + + rrr = Resolve(CodeResourceAccess, 2, 17, null); + TestHelper.CheckReference(rrr, "[ICSharpCodeCoreHostResourceSet]", "TestKey", null, null); + + NRefactoryAstCacheService.DisableCache(); + } + + // ******************************************************************************************************************************** + + const string CodeBoundaryTests = @"//${res +class A { + string B() { + return ""${res:TestKey}""; + return ""${res:""; + } +} +//${res"; + + [Test] + public void StartOfDocument() + { + ResourceResolveResult rrr = Resolve(CodeBoundaryTests, 0, 0, null); + TestHelper.CheckNoReference(rrr); + } + + [Test] + public void StartOfDocumentTag() + { + ResourceResolveResult rrr = Resolve(CodeBoundaryTests, 0, 3, null); + TestHelper.CheckNoReference(rrr); + } + + [Test] + public void MiddleOfDocument() + { + ResourceResolveResult rrr = Resolve(CodeBoundaryTests, 3, 10, null); + TestHelper.CheckReference(rrr, "[ICSharpCodeCoreHostResourceSet]", "TestKey", null, null); + } + + [Test] + public void MiddleOfDocumentIncompleteTag() + { + ResourceResolveResult rrr = Resolve(CodeBoundaryTests, 4, 10, null); + TestHelper.CheckReference(rrr, "[ICSharpCodeCoreHostResourceSet]", null, null, null); + } + + [Test] + public void EndOfDocumentTag() + { + ResourceResolveResult rrr = Resolve(CodeBoundaryTests, 7, 3, null); + TestHelper.CheckNoReference(rrr); + } + + [Test] + public void EndOfDocument() + { + ResourceResolveResult rrr = Resolve(CodeBoundaryTests, 7, 6, null); + TestHelper.CheckNoReference(rrr); + } + + [Test] + public void AfterEndOfDocument() + { + ResourceResolveResult rrr = Resolve(CodeBoundaryTests, 8, 0, null); + TestHelper.CheckNoReference(rrr); + } + + // ******************************************************************************************************************************** + + const string CodeAddinFile = @" + + + +"; + + [Test] + public void ResourceAccessInAddinFile() + { + ResourceResolveResult rrr = Resolve("test.addin", CodeAddinFile, 2, 34, null, false); + TestHelper.CheckReference(rrr, "[ICSharpCodeCoreHostResourceSet]", "TestKey", null, null); + } + + // ******************************************************************************************************************************** + + [Test] + public void ResolverSupportsCSharpFiles() + { + Assert.IsTrue(this.Resolver.SupportsFile("a.cs")); + } + + [Test] + public void ResolverSupportsAddInFiles() + { + Assert.IsTrue(this.Resolver.SupportsFile("Test.AddIn")); + } + + [Test] + public void ResolverSupportsXfrmFiles() + { + Assert.IsTrue(this.Resolver.SupportsFile("Test.XFrm")); + } + + [Test] + public void CSharpFilePatterns() + { + List patterns = new List(this.Resolver.GetPossiblePatternsForFile("a.cs")); + Assert.Contains("${res:", patterns); + Assert.AreEqual(1, patterns.Count, "Incorrect number of resource access patterns for C# files."); + } + + [Test] + public void ResolverUnsupportedExtension() + { + Assert.IsFalse(this.Resolver.SupportsFile("Test.resx")); + } + + [Test] + public void UnsupportedFilePatterns() + { + IEnumerable list = this.Resolver.GetPossiblePatternsForFile("a.resx"); + Assert.IsNotNull(list, "IResourceResolver.GetPossiblePatternsForFile must not return null."); + + List patterns = new List(list); + Assert.AreEqual(0, patterns.Count); + } + } +} diff --git a/src/AddIns/Misc/ResourceToolkit/Test/CSharp/SpecificResourceReferenceFinderTests.cs b/src/AddIns/Misc/ResourceToolkit/Test/CSharp/SpecificResourceReferenceFinderTests.cs new file mode 100644 index 0000000000..0b5fd37ad3 --- /dev/null +++ b/src/AddIns/Misc/ResourceToolkit/Test/CSharp/SpecificResourceReferenceFinderTests.cs @@ -0,0 +1,118 @@ +// +// +// +// +// $Revision$ +// + +using System; + +using Hornung.ResourceToolkit.Refactoring; +using Hornung.ResourceToolkit.Resolver; +using NUnit.Framework; + +namespace ResourceToolkit.Tests.CSharp +{ + /// + /// Tests the SpecificResourceReferenceFinder in C#. + /// + [TestFixture] + public sealed class SpecificResourceReferenceFinderTests + { + [TestFixtureSetUpAttribute] + public void FixtureSetUp() + { + TestHelper.InitializeParsers(); + TestHelper.InitializeResolvers(); + } + + // ******************************************************************************************************************************** + + [Test] + [ExpectedException(typeof(ArgumentNullException))] + public void NullResourceFileName() + { + SpecificResourceReferenceFinder finder = new SpecificResourceReferenceFinder(null, "TestKey"); + } + + [Test] + [ExpectedException(typeof(ArgumentNullException))] + public void NullKey() + { + SpecificResourceReferenceFinder finder = new SpecificResourceReferenceFinder("C:\\TestResources.resx", null); + } + + // ******************************************************************************************************************************** + + static SpecificResourceReferenceFinder CreateFinder() + { + SpecificResourceReferenceFinder finder = new SpecificResourceReferenceFinder("C:\\TestResources.resx", "TestKey"); + Assert.AreEqual(finder.ResourceFileName, "C:\\TestResources.resx"); + Assert.AreEqual(finder.Key, "TestKey"); + return finder; + } + + [Test] + public void NoReference() + { + const string Code = @"class A { + void B() { + DoSomething(); + } +}"; + SpecificResourceReferenceFinder finder = CreateFinder(); + Assert.AreEqual(-1, finder.GetNextPossibleOffset("a.cs", Code, -1), "Incorrect offset."); + } + + [Test] + public void OneReference() + { + const string Code = @"class A { + void B() { + resMgr.GetString(""TestKey""); + } +}"; + SpecificResourceReferenceFinder finder = CreateFinder(); + Assert.AreEqual(44, finder.GetNextPossibleOffset("a.cs", Code, -1), "Incorrect offset."); + Assert.AreEqual(-1, finder.GetNextPossibleOffset("a.cs", Code, 44), "Incorrect offset."); + } + + [Test] + public void TwoReferences() + { + const string Code = @"class A { + void B() { + resMgr.GetString(""TestKey""); + resMgr[""TestKey""]; + } +}"; + SpecificResourceReferenceFinder finder = CreateFinder(); + Assert.AreEqual(44, finder.GetNextPossibleOffset("a.cs", Code, -1), "Incorrect offset."); + Assert.AreEqual(66, finder.GetNextPossibleOffset("a.cs", Code, 44), "Incorrect offset."); + Assert.AreEqual(-1, finder.GetNextPossibleOffset("a.cs", Code, 66), "Incorrect offset."); + } + + // ******************************************************************************************************************************** + + [Test] + public void ResultNoMatchWrongFile() + { + SpecificResourceReferenceFinder finder = CreateFinder(); + Assert.IsFalse(finder.IsReferenceToResource(new ResourceResolveResult(null, null, null, new ResourceSetReference("SomeResources", "C:\\SomeResources.resx"), "TestKey"))); + } + + [Test] + public void ResultNoMatchWrongKey() + { + SpecificResourceReferenceFinder finder = CreateFinder(); + Assert.IsFalse(finder.IsReferenceToResource(new ResourceResolveResult(null, null, null, new ResourceSetReference("TestResources", "C:\\TestResources.resx"), "SomeKey"))); + } + + [Test] + public void ResultMatch() + { + SpecificResourceReferenceFinder finder = CreateFinder(); + Assert.IsTrue(finder.IsReferenceToResource(new ResourceResolveResult(null, null, null, new ResourceSetReference("TestResources", "C:\\TestResources.resx"), "TestKey"))); + } + } +} diff --git a/src/AddIns/Misc/ResourceToolkit/Test/Properties/AssemblyInfo.cs b/src/AddIns/Misc/ResourceToolkit/Test/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..a3ecc1b316 --- /dev/null +++ b/src/AddIns/Misc/ResourceToolkit/Test/Properties/AssemblyInfo.cs @@ -0,0 +1,38 @@ +// +// +// +// +// $Revision$ +// + +#region Using directives + +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +#endregion + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ResourceToolkit Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SharpDevelop")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all the values or you can use the default the Revision and +// Build Numbers by using the '*' as shown below: +[assembly: AssemblyVersion("3.0.0.0")] diff --git a/src/AddIns/Misc/ResourceToolkit/Test/ResourceToolkit.Tests.csproj b/src/AddIns/Misc/ResourceToolkit/Test/ResourceToolkit.Tests.csproj new file mode 100644 index 0000000000..0de4c40c66 --- /dev/null +++ b/src/AddIns/Misc/ResourceToolkit/Test/ResourceToolkit.Tests.csproj @@ -0,0 +1,93 @@ + + + {DD9AE6A5-2B9D-443A-BC71-38BE578C36BD} + Debug + AnyCPU + Library + ResourceToolkit.Tests + ResourceToolkit.Tests + v3.5 + Properties + ..\..\..\..\..\bin\UnitTests\ + False + False + True + False + 4 + false + + + true + Full + DEBUG;TRACE + + + False + None + TRACE + + + False + Auto + 4194304 + AnyCPU + 4096 + + + + + ..\..\..\..\Tools\NUnit\nunit.framework.dll + + + + 3.5 + + + + 3.5 + + + + + + + + + + + + + + + + + {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D} + ICSharpCode.TextEditor + + + {2748AD25-9C63-4E12-877B-4DCE96FBED54} + ICSharpCode.SharpDevelop + + + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C} + ICSharpCode.Core + + + {924EE450-603D-49C1-A8E5-4AFAA31CE6F3} + ICSharpCode.SharpDevelop.Dom + + + {1F1AC7CD-D154-45BB-8EAF-804CA8055F5A} + CSharpBinding + + + {BF38FB72-B380-4196-AF8C-95749D726C61} + VBNetBinding + + + {461606BD-E824-4D0A-8CBA-01810B1F5E02} + ResourceToolkit + + + + \ No newline at end of file diff --git a/src/AddIns/Misc/ResourceToolkit/Test/TestHelper.cs b/src/AddIns/Misc/ResourceToolkit/Test/TestHelper.cs new file mode 100644 index 0000000000..fe8fc6495c --- /dev/null +++ b/src/AddIns/Misc/ResourceToolkit/Test/TestHelper.cs @@ -0,0 +1,97 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; + +using Hornung.ResourceToolkit; +using Hornung.ResourceToolkit.Resolver; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; + +namespace ResourceToolkit.Tests +{ + static class TestHelper + { + public static void InitializeResolvers() + { + NRefactoryResourceResolver.SetResourceResolversListUnitTestOnly( + new INRefactoryResourceResolver[] { + new BclNRefactoryResourceResolver(), + new ICSharpCodeCoreNRefactoryResourceResolver() + }); + ResourceResolverService.SetResourceResolversListUnitTestOnly( + new IResourceResolver[] { + new NRefactoryResourceResolver(), + new ICSharpCodeCoreResourceResolver() + }); + } + + public static void InitializeParsers() + { + Dictionary parsers = new Dictionary(); + parsers.Add(".cs", new CSharpBinding.Parser.TParser()); + parsers.Add(".vb", new VBNetBinding.Parser.TParser()); + ResourceResolverService.SetParsersUnitTestOnly(parsers); + } + + public static void CheckReference(ResourceResolveResult result, string expectedResourceSetName, string expectedKey, string expectedCallingClassFullName, string expectedCallingMemberFullName) + { + Assert.IsNotNull(result, "Resource reference should be detected."); + + if (expectedResourceSetName == null) { + + Assert.IsNull(result.ResourceSetReference, "Resource set reference should not be detected."); + + } else { + + Assert.IsNotNull(result.ResourceSetReference, "Resource set reference should be detected."); + Assert.IsNotNull(result.ResourceSetReference.ResourceSetName, "Resource set name must not be null."); + Assert.AreEqual(expectedResourceSetName, result.ResourceSetReference.ResourceSetName, "Incorrect resource set name."); + + } + + if (expectedKey == null) { + + Assert.IsNull(result.Key, "Resource key should not be detected."); + + } else { + + Assert.IsNotNull(result.Key, "Resource key should be detected."); + Assert.AreEqual(expectedKey, result.Key, "Incorrect resource key."); + + } + + if (expectedCallingClassFullName == null) { + + Assert.IsNull(result.CallingClass, "Calling class should not be detected."); + + } else { + + Assert.IsNotNull(result.CallingClass, "Calling class should be detected."); + Assert.AreEqual(expectedCallingClassFullName, result.CallingClass.FullyQualifiedName, "Incorrect calling class."); + + } + + if (expectedCallingMemberFullName == null) { + + Assert.IsNull(result.CallingMember, "Calling member should not be detected."); + + } else { + + Assert.IsNotNull(result.CallingMember, "Calling member should be detected."); + Assert.AreEqual(expectedCallingMemberFullName, result.CallingMember.FullyQualifiedName, "Incorrect calling member."); + + } + } + + public static void CheckNoReference(ResourceResolveResult result) + { + Assert.IsNull(result, "Resource reference should not be detected."); + } + } +} diff --git a/src/SharpDevelop.Tests.sln b/src/SharpDevelop.Tests.sln index 820bc830de..90ad1edf4f 100644 --- a/src/SharpDevelop.Tests.sln +++ b/src/SharpDevelop.Tests.sln @@ -1,11 +1,15 @@  Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 -# SharpDevelop 3.0.0.3264 +# SharpDevelop 3.0.0.3278 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AddIns", "AddIns", "{14A277EE-7DF1-4529-B639-7D1EF334C1C5}" ProjectSection(SolutionItems) = postProject EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResourceToolkit.Tests", "AddIns\Misc\ResourceToolkit\Test\ResourceToolkit.Tests.csproj", "{DD9AE6A5-2B9D-443A-BC71-38BE578C36BD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResourceToolkit", "AddIns\Misc\ResourceToolkit\Project\ResourceToolkit.csproj", "{461606BD-E824-4D0A-8CBA-01810B1F5E02}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Boo", "Boo", "{5DA95927-5F2D-46D8-9265-D092734B6F0E}" ProjectSection(SolutionItems) = postProject EndProjectSection @@ -318,6 +322,14 @@ Global {7DB80259-24D4-46C3-A024-53FF1987733D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7DB80259-24D4-46C3-A024-53FF1987733D}.Release|Any CPU.Build.0 = Release|Any CPU {7DB80259-24D4-46C3-A024-53FF1987733D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {461606BD-E824-4D0A-8CBA-01810B1F5E02}.Debug|Any CPU.Build.0 = Debug|Any CPU + {461606BD-E824-4D0A-8CBA-01810B1F5E02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {461606BD-E824-4D0A-8CBA-01810B1F5E02}.Release|Any CPU.Build.0 = Release|Any CPU + {461606BD-E824-4D0A-8CBA-01810B1F5E02}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DD9AE6A5-2B9D-443A-BC71-38BE578C36BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DD9AE6A5-2B9D-443A-BC71-38BE578C36BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD9AE6A5-2B9D-443A-BC71-38BE578C36BD}.Release|Any CPU.Build.0 = Release|Any CPU + {DD9AE6A5-2B9D-443A-BC71-38BE578C36BD}.Release|Any CPU.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -342,6 +354,8 @@ Global {9196DD8A-B4D4-4780-8742-C5762E547FC2} = {14A277EE-7DF1-4529-B639-7D1EF334C1C5} {A569DCC1-C608-45FD-B770-4F79335EF154} = {14A277EE-7DF1-4529-B639-7D1EF334C1C5} {5DA95927-5F2D-46D8-9265-D092734B6F0E} = {14A277EE-7DF1-4529-B639-7D1EF334C1C5} + {461606BD-E824-4D0A-8CBA-01810B1F5E02} = {14A277EE-7DF1-4529-B639-7D1EF334C1C5} + {DD9AE6A5-2B9D-443A-BC71-38BE578C36BD} = {14A277EE-7DF1-4529-B639-7D1EF334C1C5} {4AC2D5F1-F671-480C-A075-6BF62B3721B2} = {5DA95927-5F2D-46D8-9265-D092734B6F0E} {6FA16499-896F-4C02-BB43-1AF5C6C7C713} = {5DA95927-5F2D-46D8-9265-D092734B6F0E} {DBCF20A1-BA13-4582-BFA9-74DE4D987B73} = {5DA95927-5F2D-46D8-9265-D092734B6F0E}