Browse Source

Fixed bugs that caused some nodes not to be resolved in a "resolve all" run.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
7f11fe3be0
  1. 13
      ICSharpCode.NRefactory/CSharp/Ast/Expressions/BinaryOperatorExpression.cs
  2. 10
      ICSharpCode.NRefactory/CSharp/Ast/Expressions/UnaryOperatorExpression.cs
  3. 6
      ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs
  4. 64
      ICSharpCode.NRefactory/CSharp/Resolver/FindReferencedEntities.cs
  5. 2
      ICSharpCode.NRefactory/CSharp/Resolver/Log.cs
  6. 58
      ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs
  7. 1
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

13
ICSharpCode.NRefactory/CSharp/Ast/Expressions/BinaryOperatorExpression.cs

@ -128,11 +128,15 @@ namespace ICSharpCode.NRefactory.CSharp
public enum BinaryOperatorType public enum BinaryOperatorType
{ {
/// <summary>
/// Any binary operator (used in pattern matching)
/// </summary>
Any,
// We avoid 'logical or' on purpose, because it's not clear if that refers to the bitwise // We avoid 'logical or' on purpose, because it's not clear if that refers to the bitwise
// or to the short-circuiting (conditional) operator: // or to the short-circuiting (conditional) operator:
// MCS and old NRefactory used bitwise='|', logical='||' // MCS and old NRefactory used bitwise='|', logical='||'
// but the C# spec uses logical='|', conditional='||' // but the C# spec uses logical='|', conditional='||'
/// <summary>left &amp; right</summary> /// <summary>left &amp; right</summary>
BitwiseAnd, BitwiseAnd,
/// <summary>left | right</summary> /// <summary>left | right</summary>
@ -174,11 +178,6 @@ namespace ICSharpCode.NRefactory.CSharp
ShiftRight, ShiftRight,
/// <summary>left ?? right</summary> /// <summary>left ?? right</summary>
NullCoalescing, NullCoalescing
/// <summary>
/// Any binary operator (used in pattern matching)
/// </summary>
Any
} }
} }

10
ICSharpCode.NRefactory/CSharp/Ast/Expressions/UnaryOperatorExpression.cs

@ -1,6 +1,6 @@
// //
// UnaryOperatorExpression.cs // UnaryOperatorExpression.cs
// //
// Author: // Author:
// Mike Krüger <mkrueger@novell.com> // Mike Krüger <mkrueger@novell.com>
// //
@ -67,7 +67,8 @@ namespace ICSharpCode.NRefactory.CSharp
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{ {
UnaryOperatorExpression o = other as UnaryOperatorExpression; UnaryOperatorExpression o = other as UnaryOperatorExpression;
return o != null && this.Operator == o.Operator && this.Expression.DoMatch(o.Expression, match); return o != null && (this.Operator == UnaryOperatorType.Any || this.Operator == o.Operator)
&& this.Expression.DoMatch(o.Expression, match);
} }
public static string GetOperatorSymbol(UnaryOperatorType op) public static string GetOperatorSymbol(UnaryOperatorType op)
@ -101,6 +102,11 @@ namespace ICSharpCode.NRefactory.CSharp
public enum UnaryOperatorType public enum UnaryOperatorType
{ {
/// <summary>
/// Any unary operator (used in pattern matching)
/// </summary>
Any,
/// <summary>Logical not (!a)</summary> /// <summary>Logical not (!a)</summary>
Not, Not,
/// <summary>Bitwise not (~a)</summary> /// <summary>Bitwise not (~a)</summary>

6
ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs

@ -86,16 +86,22 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public static Conversion UserDefinedImplicitConversion(IMethod operatorMethod, bool isLifted) public static Conversion UserDefinedImplicitConversion(IMethod operatorMethod, bool isLifted)
{ {
if (operatorMethod == null)
throw new ArgumentNullException("operatorMethod");
return new Conversion(isLifted ? liftedUserDefinedImplicitConversionKind : userDefinedImplicitConversionKind, operatorMethod); return new Conversion(isLifted ? liftedUserDefinedImplicitConversionKind : userDefinedImplicitConversionKind, operatorMethod);
} }
public static Conversion UserDefinedExplicitConversion(IMethod operatorMethod, bool isLifted) public static Conversion UserDefinedExplicitConversion(IMethod operatorMethod, bool isLifted)
{ {
if (operatorMethod == null)
throw new ArgumentNullException("operatorMethod");
return new Conversion(isLifted ? liftedUserDefinedExplicitConversionKind : userDefinedExplicitConversionKind, operatorMethod); return new Conversion(isLifted ? liftedUserDefinedExplicitConversionKind : userDefinedExplicitConversionKind, operatorMethod);
} }
public static Conversion MethodGroupConversion(IMethod chosenMethod) public static Conversion MethodGroupConversion(IMethod chosenMethod)
{ {
if (chosenMethod == null)
throw new ArgumentNullException("chosenMethod");
return new Conversion(methodGroupConversionKind, chosenMethod); return new Conversion(methodGroupConversionKind, chosenMethod);
} }

64
ICSharpCode.NRefactory/CSharp/Resolver/FindReferencedEntities.cs

@ -0,0 +1,64 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
/// <summary>
/// Find all entities that are referenced in the scanned AST.
/// </summary>
public sealed class FindReferencedEntities : IResolveVisitorNavigator
{
readonly Action<AstNode, IEntity> referenceFound;
public FindReferencedEntities(Action<AstNode, IEntity> referenceFound)
{
if (referenceFound == null)
throw new ArgumentNullException("referenceFound");
this.referenceFound = referenceFound;
}
public ResolveVisitorNavigationMode Scan(AstNode node)
{
return ResolveVisitorNavigationMode.Resolve;
}
public void Resolved(AstNode node, ResolveResult result)
{
MemberResolveResult mrr = result as MemberResolveResult;
if (mrr != null) {
referenceFound(node, mrr.Member);
}
TypeResolveResult trr = result as TypeResolveResult;
if (trr != null) {
ITypeDefinition typeDef = trr.Type.GetDefinition();
if (typeDef != null)
referenceFound(node, typeDef);
}
}
public void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType)
{
if (conversion.IsUserDefined || conversion.IsMethodGroupConversion) {
referenceFound(expression, conversion.Method);
}
}
}
}

2
ICSharpCode.NRefactory/CSharp/Resolver/Log.cs

@ -35,7 +35,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary> /// </summary>
static class Log static class Log
{ {
const bool logEnabled = true; const bool logEnabled = false;
[Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")] [Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")]
internal static void WriteLine(string text) internal static void WriteLine(string text)

58
ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs

@ -359,6 +359,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary> /// </summary>
public ResolveResult GetResolveResult(AstNode node) public ResolveResult GetResolveResult(AstNode node)
{ {
if (IsUnresolvableNode(node))
return null;
MergeUndecidedLambdas(); MergeUndecidedLambdas();
ResolveResult result; ResolveResult result;
if (resolveResultCache.TryGetValue(node, out result)) if (resolveResultCache.TryGetValue(node, out result))
@ -385,6 +388,28 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return null; return null;
} }
/// <summary>
/// Gets whether the specified node is unresolvable.
/// </summary>
public static bool IsUnresolvableNode(AstNode node)
{
return (node.NodeType == NodeType.Whitespace || node is ArraySpecifier || node is NamedArgumentExpression);
}
/// <summary>
/// Gets the resolve result for the specified node.
/// If the node was not resolved by the navigator, this method will return null.
/// </summary>
public ResolveResult GetResolveResultIfResolved(AstNode node)
{
MergeUndecidedLambdas();
ResolveResult result;
if (resolveResultCache.TryGetValue(node, out result))
return result;
else
return null;
}
CSharpResolver GetPreviouslyScannedContext(AstNode node, out AstNode parent) CSharpResolver GetPreviouslyScannedContext(AstNode node, out AstNode parent)
{ {
parent = node; parent = node;
@ -577,7 +602,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (aie != null && arrayType != null) { if (aie != null && arrayType != null) {
StoreState(aie, resolver.Clone()); StoreState(aie, resolver.Clone());
List<Expression> initializerElements = new List<Expression>(); List<Expression> initializerElements = new List<Expression>();
UnpackArrayInitializer(initializerElements, aie, arrayType.Dimensions); UnpackArrayInitializer(initializerElements, aie, arrayType.Dimensions, true);
ResolveResult[] initializerElementResults = new ResolveResult[initializerElements.Count]; ResolveResult[] initializerElementResults = new ResolveResult[initializerElements.Count];
for (int i = 0; i < initializerElementResults.Length; i++) { for (int i = 0; i < initializerElementResults.Length; i++) {
initializerElementResults[i] = Resolve(initializerElements[i]); initializerElementResults[i] = Resolve(initializerElements[i]);
@ -916,11 +941,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
initializerElementResults = null; initializerElementResults = null;
} else { } else {
initializerElements = new List<Expression>(); initializerElements = new List<Expression>();
UnpackArrayInitializer(initializerElements, arrayCreateExpression.Initializer, dimensions); UnpackArrayInitializer(initializerElements, arrayCreateExpression.Initializer, dimensions, true);
initializerElementResults = new ResolveResult[initializerElements.Count]; initializerElementResults = new ResolveResult[initializerElements.Count];
for (int i = 0; i < initializerElementResults.Length; i++) { for (int i = 0; i < initializerElementResults.Length; i++) {
initializerElementResults[i] = Resolve(initializerElements[i]); initializerElementResults[i] = Resolve(initializerElements[i]);
} }
StoreResult(arrayCreateExpression.Initializer, voidResult);
} }
ArrayCreateResolveResult acrr; ArrayCreateResolveResult acrr;
@ -936,16 +962,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return acrr; return acrr;
} }
void UnpackArrayInitializer(List<Expression> elementList, ArrayInitializerExpression initializer, int dimensions) void UnpackArrayInitializer(List<Expression> elementList, ArrayInitializerExpression initializer, int dimensions, bool resolveNestedInitializesToVoid)
{ {
Debug.Assert(dimensions >= 1); Debug.Assert(dimensions >= 1);
if (dimensions > 1) { if (dimensions > 1) {
foreach (var node in initializer.Elements) { foreach (var node in initializer.Elements) {
ArrayInitializerExpression aie = node as ArrayInitializerExpression; ArrayInitializerExpression aie = node as ArrayInitializerExpression;
if (aie != null) if (aie != null) {
UnpackArrayInitializer(elementList, aie, dimensions - 1); if (resolveNestedInitializesToVoid)
else StoreResult(aie, voidResult);
UnpackArrayInitializer(elementList, aie, dimensions - 1, resolveNestedInitializesToVoid);
} else {
elementList.Add(node); elementList.Add(node);
}
} }
} else { } else {
foreach (var expr in initializer.Elements) foreach (var expr in initializer.Elements)
@ -1215,6 +1244,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
} }
resolver.PopInitializerType(); resolver.PopInitializerType();
StoreResult(initializer, voidResult);
} }
ResolveResult IAstVisitor<object, ResolveResult>.VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data) ResolveResult IAstVisitor<object, ResolveResult>.VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data)
@ -1672,7 +1702,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
visitor.ResetContext( visitor.ResetContext(
storedContext, storedContext,
delegate { delegate {
var oldNavigator = visitor.navigator;
visitor.navigator = new ConstantModeResolveVisitorNavigator(ResolveVisitorNavigationMode.Resolve, oldNavigator);
visitor.AnalyzeLambda(body, out success, out isValidAsVoidMethod, out inferredReturnType, out returnExpressions, out returnValues); visitor.AnalyzeLambda(body, out success, out isValidAsVoidMethod, out inferredReturnType, out returnExpressions, out returnValues);
visitor.navigator = oldNavigator;
}); });
Log.Unindent(); Log.Unindent();
Log.WriteLine("Finished analyzing " + this.LambdaExpression); Log.WriteLine("Finished analyzing " + this.LambdaExpression);
@ -1857,7 +1890,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (ok) if (ok)
return h; return h;
} }
ResolveVisitor visitor = new ResolveVisitor(storedContext.Clone(), parsedFile); var resolveAll = new ConstantModeResolveVisitorNavigator(ResolveVisitorNavigationMode.Resolve, null);
ResolveVisitor visitor = new ResolveVisitor(storedContext.Clone(), parsedFile, resolveAll);
var newHypothesis = new LambdaTypeHypothesis(this, parameterTypes, visitor, lambda != null ? lambda.Parameters : null); var newHypothesis = new LambdaTypeHypothesis(this, parameterTypes, visitor, lambda != null ? lambda.Parameters : null);
hypotheses.Add(newHypothesis); hypotheses.Add(newHypothesis);
return newHypothesis; return newHypothesis;
@ -2050,7 +2084,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
void MergeUndecidedLambdas() void MergeUndecidedLambdas()
{ {
if (undecidedLambdas == null) if (undecidedLambdas == null || undecidedLambdas.Count == 0)
return; return;
Log.WriteLine("MergeUndecidedLambdas()..."); Log.WriteLine("MergeUndecidedLambdas()...");
Log.Indent(); Log.Indent();
@ -2097,9 +2131,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#region AnalyzeLambda #region AnalyzeLambda
void AnalyzeLambda(AstNode body, out bool success, out bool isValidAsVoidMethod, out IType inferredReturnType, out IList<Expression> returnExpressions, out IList<ResolveResult> returnValues) void AnalyzeLambda(AstNode body, out bool success, out bool isValidAsVoidMethod, out IType inferredReturnType, out IList<Expression> returnExpressions, out IList<ResolveResult> returnValues)
{ {
var oldNavigator = this.navigator;
this.navigator = new ConstantModeResolveVisitorNavigator(ResolveVisitorNavigationMode.Resolve, oldNavigator);
Expression expr = body as Expression; Expression expr = body as Expression;
if (expr != null) { if (expr != null) {
isValidAsVoidMethod = ExpressionPermittedAsStatement(expr); isValidAsVoidMethod = ExpressionPermittedAsStatement(expr);
@ -2133,7 +2164,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// TODO: check for compiler errors within the lambda body // TODO: check for compiler errors within the lambda body
success = true; success = true;
this.navigator = oldNavigator;
} }
static bool ExpressionPermittedAsStatement(Expression expr) static bool ExpressionPermittedAsStatement(Expression expr)
@ -2679,7 +2709,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
ResolveResult target; ResolveResult target;
if (memberType.IsDoubleColon && memberType.Target is SimpleType) { if (memberType.IsDoubleColon && memberType.Target is SimpleType) {
target = resolver.ResolveAlias(((SimpleType)memberType.Target).Identifier); SimpleType t = (SimpleType)memberType.Target;
target = resolver.ResolveAlias(t.Identifier);
StoreResult(t, target);
} else { } else {
target = Resolve(memberType.Target); target = Resolve(memberType.Target);
} }

1
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -102,6 +102,7 @@
<Compile Include="CSharp\Refactoring\TypeSystemAstBuilder.cs" /> <Compile Include="CSharp\Refactoring\TypeSystemAstBuilder.cs" />
<Compile Include="CSharp\Resolver\CompositeResolveVisitorNavigator.cs" /> <Compile Include="CSharp\Resolver\CompositeResolveVisitorNavigator.cs" />
<Compile Include="CSharp\Resolver\DetectSkippableNodesNavigator.cs" /> <Compile Include="CSharp\Resolver\DetectSkippableNodesNavigator.cs" />
<Compile Include="CSharp\Resolver\FindReferencedEntities.cs" />
<Compile Include="CSharp\Resolver\FindReferences.cs" /> <Compile Include="CSharp\Resolver\FindReferences.cs" />
<Compile Include="CSharp\Resolver\Log.cs" /> <Compile Include="CSharp\Resolver\Log.cs" />
<Compile Include="CSharp\Resolver\OperatorResolveResult.cs" /> <Compile Include="CSharp\Resolver\OperatorResolveResult.cs" />

Loading…
Cancel
Save