// ******************************************************************************************************************************** /// <summary> /// Gets a list of patterns that can be searched for in the specified file /// to find possible resource references that are supported by this /// resolver. /// </summary> /// <param name="fileName">The name of the file to get a list of possible patterns for.</param> public IEnumerable <string> GetPossiblePatternsForFile(string fileName) { return(new string[] { "GetString", "GetObject", "GetStream", "ApplyResources", (NRefactoryResourceResolver.GetLanguagePropertiesForFile(fileName) ?? LanguageProperties.None).IndexerExpressionStartToken }); }
/// <summary> /// Tries to determine the resource set which is referenced by the /// resource manager which is assigned to the specified member. /// </summary> /// <param name="member">The referenced member to examine.</param> /// <returns> /// 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 ResourceSetReference ResolveResourceSet(IMember member) { if (member != null && member.ReturnType != null && member.DeclaringType != null && member.DeclaringType.CompilationUnit != null) { ResourceSetReference rsr; if (!NRefactoryAstCacheService.CacheEnabled || !cachedResourceSetReferenceMappings.TryGetValue(member, out rsr)) { string declaringFileName = member.DeclaringType.CompilationUnit.FileName; if (declaringFileName != null) { if (IsResourceManager(member.ReturnType, declaringFileName)) { SupportedLanguage?language = NRefactoryResourceResolver.GetFileLanguage(declaringFileName); if (language == null) { return(null); } CompilationUnit cu = NRefactoryAstCacheService.GetFullAst(language.Value, declaringFileName, ResourceResolverService.GetParsableFileContent(declaringFileName)); if (cu != null) { ResourceManagerInitializationFindVisitor visitor = new ResourceManagerInitializationFindVisitor(member); cu.AcceptVisitor(visitor, null); if (visitor.FoundResourceSet != null) { rsr = visitor.FoundResourceSet; if (NRefactoryAstCacheService.CacheEnabled) { cachedResourceSetReferenceMappings.Add(member, rsr); } return(rsr); } } } } return(null); } return(rsr); } return(null); }
// ******************************************************************************************************************************** /// <summary> /// Parses an expression with NRefactory. /// </summary> /// <param name="fileName">The file name of the source code file that contains the expression.</param> /// <param name="expression">The expression to parse.</param> /// <param name="caretLine">The 1-based line number of the expression.</param> /// <param name="caretColumn">The 1-based column number of the expression.</param> /// <returns>The parsed expression or <c>null</c> if the expression cannot be parsed or the language of the source code file is not supported.</returns> public static Expression ParseExpression(string fileName, string expression, int caretLine, int caretColumn) { SupportedLanguage?l = NRefactoryResourceResolver.GetFileLanguage(fileName); if (l == null) { return(null); } using (ICSharpCode.NRefactory.IParser p = ICSharpCode.NRefactory.ParserFactory.CreateParser(l.Value, new System.IO.StringReader(expression))) { Expression expr = p.ParseExpression(); if (expr != null) { expr.AcceptVisitor(new SetAllNodePointsAstVisitor(new Location(caretColumn, caretLine), new Location(caretColumn + 1, caretLine)), null); } return(expr); } }
public override object TrackedVisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data) { if (data as bool? ?? false) { #if DEBUG LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found object initialization: " + objectCreateExpression.ToString()); #endif // Resolve the constructor. // A type derived from the declaration type is also allowed. MemberResolveResult mrr = this.Resolve(objectCreateExpression) as MemberResolveResult; #if DEBUG if (mrr != null) { LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver: resolved constructor: " + mrr.ResolvedMember.ToString()); } #endif if (mrr != null && mrr.ResolvedMember is IMethod && (mrr.ResolvedMember.DeclaringType.CompareTo(this.resourceManagerMember.ReturnType.GetUnderlyingClass()) == 0 || mrr.ResolvedMember.DeclaringType.IsTypeInInheritanceTree(this.resourceManagerMember.ReturnType.GetUnderlyingClass())) ) { #if DEBUG LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver: This is the correct constructor."); #endif // This most probably is the resource manager initialization we are looking for. // Find a parameter that indicates the resources being referenced. foreach (Expression param in objectCreateExpression.Parameters) { PrimitiveExpression p = param as PrimitiveExpression; if (p != null) { string pValue = p.Value as string; if (!String.IsNullOrEmpty(pValue)) { #if DEBUG LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found string parameter: '" + pValue + "'"); #endif 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; } continue; } // Support typeof(...) TypeOfExpression t = param as TypeOfExpression; if (t != null && this.PositionAvailable) { #if DEBUG LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver: Found TypeOfExpression in constructor call: " + t.ToString()); #endif ResolveResult rr = this.Resolve(new TypeReferenceExpression(t.TypeReference), ExpressionContext.Type); #if DEBUG if (rr == null) { LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver: The TypeReference of the TypeOfExpression could not be resolved."); } else { LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver: The TypeReference resolved to: " + rr.ToString()); } #endif if (rr != null) { #if DEBUG LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found typeof(...) parameter, type: '" + rr.ResolvedType.ToString() + "'"); #endif this.foundResourceSet = NRefactoryResourceResolver.GetResourceSetReference(this.resourceManagerMember.DeclaringType.CompilationUnit.FileName, rr.ResolvedType.FullyQualifiedName); #if DEBUG if (this.foundResourceSet.FileName != null) { LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found resource file: " + this.foundResourceSet.FileName); } #endif break; } } } } } return(base.TrackedVisitObjectCreateExpression(objectCreateExpression, data)); }
/// <summary> /// Tries to find a resource reference in the specified expression. /// </summary> /// <param name="expressionResult">The ExpressionResult for the expression.</param> /// <param name="expr">The AST representation of the full expression.</param> /// <param name="resolveResult">SharpDevelop's ResolveResult for the expression.</param> /// <param name="caretLine">The 0-based line where the expression is located.</param> /// <param name="caretColumn">The 0-based column where the expression is located.</param> /// <param name="fileName">The name of the source file where the expression is located.</param> /// <param name="fileContent">The content of the source file where the expression is located.</param> /// <param name="expressionFinder">The ExpressionFinder for the file.</param> /// <param name="charTyped">The character that has been typed at the caret position but is not yet in the buffer (this is used when invoked from code completion), or <c>null</c>.</param> /// <returns>A ResourceResolveResult describing the referenced resource, or <c>null</c>, if this expression does not reference a resource using the standard .NET framework classes.</returns> public ResourceResolveResult Resolve(ExpressionResult expressionResult, Expression expr, ResolveResult resolveResult, int caretLine, int caretColumn, string fileName, string fileContent, IExpressionFinder expressionFinder, char?charTyped) { /* * We need to catch the following cases here: * * Something.GetString( * Something.GetString("...") * Something.ApplyResources(obj, "...") * Something[ * Something["..."] * */ if (charTyped == '(') { // Something.GetString // This is a MethodResolveResult and we need the reference to "Something", // which is the next outer expression. // This is only valid when invoked from code completion // and the method invocation character ('(' in C# and VB) // has been typed. // This code is also reused when reducing a complete InvocationExpression // (MemberResolveResult) to the method reference by passing '(' as // charTyped explicitly. MethodGroupResolveResult methrr = resolveResult as MethodGroupResolveResult; if (methrr != null) { if ((methrr.Name == "GetString" || methrr.Name == "GetObject" || methrr.Name == "GetStream" || methrr.Name == "ApplyResources") && (resolveResult = NRefactoryAstCacheService.ResolveNextOuterExpression(ref expressionResult, caretLine, caretColumn, fileName, fileContent, expressionFinder)) != null) { return(ResolveResource(resolveResult, expr)); } else { return(null); } } } // Do not use "else if" here. // '(' is also the IndexerExpressionStartToken for VB, // so the "else" block further down might still apply. if (charTyped == null) { // A MemberResolveResult with a complete expression // must only be considered a valid resource reference // when Resolve is not invoked from code completion // (i.e. charTyped == null) because this indicates // that the resource reference is already before the typed character // and we are not interested in the following expression. // This may happen when typing something like: // Something.GetString("...")[ MemberResolveResult mrr = resolveResult as MemberResolveResult; if (mrr != null) { if (mrr.ResolvedMember is IMethod && (mrr.ResolvedMember.Name == "GetString" || mrr.ResolvedMember.Name == "GetObject" || mrr.ResolvedMember.Name == "GetStream" || mrr.ResolvedMember.Name == "ApplyResources")) { // Something.GetString("...") // This is a MemberResolveResult and we need the reference to "Something". // The expression finder may only remove the string literal, so // we have to call Resolve again in this case to resolve // the method reference. 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, '(')); } else { return(ResolveResource(resolveResult, expr)); } } else { return(null); } } else if (expr is IndexerExpression && IsResourceManager(mrr.ResolvedMember.DeclaringType.DefaultReturnType, fileName)) { // Something["..."] is an IndexerExpression. // We need the reference to Something and this is // the next outer expression. if ((resolveResult = NRefactoryAstCacheService.ResolveNextOuterExpression(ref expressionResult, caretLine, caretColumn, fileName, fileContent, expressionFinder)) != null) { return(ResolveResource(resolveResult, expr)); } else { return(null); } } } } else { // This request is triggered from code completion. // The only case that has not been caught above is: // Something[ // The reference to "Something" is already in this expression. // So we have to test the trigger character against the // indexer expression start token of the file's language. LanguageProperties lp = NRefactoryResourceResolver.GetLanguagePropertiesForFile(fileName); if (lp != null && !String.IsNullOrEmpty(lp.IndexerExpressionStartToken) && lp.IndexerExpressionStartToken[0] == charTyped) { #if DEBUG LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver: Indexer expression start typed, ResolveResult: " + resolveResult.ToString()); LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver: -> Expression: " + expr.ToString()); #endif return(ResolveResource(resolveResult, expr)); } } return(null); }