// ******************************************************************************************************************************** /// <summary> /// Tries to infer the resource key being referenced from the given expression. /// </summary> static string GetKeyFromExpression(Expression expr, out bool isPrefixOnly) { isPrefixOnly = false; #if DEBUG LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver trying to get key from expression: "+expr.ToString()); #endif IndexerExpression indexer = expr as IndexerExpression; if (indexer != null) { foreach (Expression index in indexer.Indexes) { PrimitiveExpression p = index as PrimitiveExpression; if (p != null) { string key = p.Value as string; if (key != null) { #if DEBUG LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found key: "+key); #endif return key; } } } } InvocationExpression invocation = expr as InvocationExpression; if (invocation != null) { MemberReferenceExpression fre = invocation.TargetObject as MemberReferenceExpression; if (fre != null) { if (fre.MemberName == "GetString" || fre.MemberName == "GetObject" || fre.MemberName == "GetStream") { if (invocation.Arguments.Count > 0) { PrimitiveExpression p = invocation.Arguments[0] as PrimitiveExpression; if (p != null) { string key = p.Value as string; if (key != null) { #if DEBUG LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found key: "+key); #endif return key; } } } } else if (fre.MemberName == "ApplyResources") { if (invocation.Arguments.Count >= 2) { PrimitiveExpression p = invocation.Arguments[1] as PrimitiveExpression; if (p != null) { string key = p.Value as string; if (key != null) { #if DEBUG LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver found key prefix: "+key); #endif isPrefixOnly = true; return key; } } } } } } return null; }
// ******************************************************************************************************************************** /// <summary> /// Tries to infer the resource key being referenced from the given expression. /// </summary> static string GetKeyFromExpression(Expression expr) { #if DEBUG LoggingService.Debug("ResourceToolkit: ICSharpCodeCoreNRefactoryResourceResolver trying to get key from expression: "+expr.ToString()); #endif InvocationExpression invocation = expr as InvocationExpression; if (invocation != null) { MemberReferenceExpression fre = invocation.TargetObject as MemberReferenceExpression; if (fre != null) { if (fre.MemberName == "GetString") { if (invocation.Arguments.Count > 0) { PrimitiveExpression p = invocation.Arguments[0] as PrimitiveExpression; if (p != null) { string key = p.Value as string; if (key != null) { #if DEBUG LoggingService.Debug("ResourceToolkit: ICSharpCodeCoreNRefactoryResourceResolver found key: "+key); #endif return key; } } } } } } return null; }
/// <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; }
/// <summary> /// Resolves an expression in the current node's context. /// </summary> /// <param name="expression">The expression to be resolved.</param> /// <param name="context">The ExpressionContext.</param> 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()); return null; } #if DEBUG LoggingService.Debug("ResourceToolkit: PositionTrackingAstVisitor: Using this parent node for resolve: "+this.parentNodes.Peek().ToString()); #endif return NRefactoryAstCacheService.ResolveLowLevel(this.fileName, this.fileContent, this.CurrentNodeStartLocation.Y, this.CurrentNodeStartLocation.X+1, this.compilationUnit, null, expression, context); }