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. 8
      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 @@ -128,11 +128,15 @@ namespace ICSharpCode.NRefactory.CSharp
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
// or to the short-circuiting (conditional) operator:
// MCS and old NRefactory used bitwise='|', logical='||'
// but the C# spec uses logical='|', conditional='||'
/// <summary>left &amp; right</summary>
BitwiseAnd,
/// <summary>left | right</summary>
@ -174,11 +178,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -174,11 +178,6 @@ namespace ICSharpCode.NRefactory.CSharp
ShiftRight,
/// <summary>left ?? right</summary>
NullCoalescing,
/// <summary>
/// Any binary operator (used in pattern matching)
/// </summary>
Any
NullCoalescing
}
}

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

@ -67,7 +67,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -67,7 +67,8 @@ namespace ICSharpCode.NRefactory.CSharp
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
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)
@ -101,6 +102,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -101,6 +102,11 @@ namespace ICSharpCode.NRefactory.CSharp
public enum UnaryOperatorType
{
/// <summary>
/// Any unary operator (used in pattern matching)
/// </summary>
Any,
/// <summary>Logical not (!a)</summary>
Not,
/// <summary>Bitwise not (~a)</summary>

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

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

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

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

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

@ -359,6 +359,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -359,6 +359,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
public ResolveResult GetResolveResult(AstNode node)
{
if (IsUnresolvableNode(node))
return null;
MergeUndecidedLambdas();
ResolveResult result;
if (resolveResultCache.TryGetValue(node, out result))
@ -385,6 +388,28 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -385,6 +388,28 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
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)
{
parent = node;
@ -577,7 +602,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -577,7 +602,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (aie != null && arrayType != null) {
StoreState(aie, resolver.Clone());
List<Expression> initializerElements = new List<Expression>();
UnpackArrayInitializer(initializerElements, aie, arrayType.Dimensions);
UnpackArrayInitializer(initializerElements, aie, arrayType.Dimensions, true);
ResolveResult[] initializerElementResults = new ResolveResult[initializerElements.Count];
for (int i = 0; i < initializerElementResults.Length; i++) {
initializerElementResults[i] = Resolve(initializerElements[i]);
@ -916,11 +941,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -916,11 +941,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
initializerElementResults = null;
} else {
initializerElements = new List<Expression>();
UnpackArrayInitializer(initializerElements, arrayCreateExpression.Initializer, dimensions);
UnpackArrayInitializer(initializerElements, arrayCreateExpression.Initializer, dimensions, true);
initializerElementResults = new ResolveResult[initializerElements.Count];
for (int i = 0; i < initializerElementResults.Length; i++) {
initializerElementResults[i] = Resolve(initializerElements[i]);
}
StoreResult(arrayCreateExpression.Initializer, voidResult);
}
ArrayCreateResolveResult acrr;
@ -936,16 +962,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -936,16 +962,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
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);
if (dimensions > 1) {
foreach (var node in initializer.Elements) {
ArrayInitializerExpression aie = node as ArrayInitializerExpression;
if (aie != null)
UnpackArrayInitializer(elementList, aie, dimensions - 1);
else
if (aie != null) {
if (resolveNestedInitializesToVoid)
StoreResult(aie, voidResult);
UnpackArrayInitializer(elementList, aie, dimensions - 1, resolveNestedInitializesToVoid);
} else {
elementList.Add(node);
}
}
} else {
foreach (var expr in initializer.Elements)
@ -1215,6 +1244,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1215,6 +1244,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
resolver.PopInitializerType();
StoreResult(initializer, voidResult);
}
ResolveResult IAstVisitor<object, ResolveResult>.VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data)
@ -1672,7 +1702,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1672,7 +1702,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
visitor.ResetContext(
storedContext,
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.navigator = oldNavigator;
});
Log.Unindent();
Log.WriteLine("Finished analyzing " + this.LambdaExpression);
@ -1857,7 +1890,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1857,7 +1890,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (ok)
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);
hypotheses.Add(newHypothesis);
return newHypothesis;
@ -2050,7 +2084,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2050,7 +2084,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
void MergeUndecidedLambdas()
{
if (undecidedLambdas == null)
if (undecidedLambdas == null || undecidedLambdas.Count == 0)
return;
Log.WriteLine("MergeUndecidedLambdas()...");
Log.Indent();
@ -2097,9 +2131,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2097,9 +2131,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#region AnalyzeLambda
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;
if (expr != null) {
isValidAsVoidMethod = ExpressionPermittedAsStatement(expr);
@ -2133,7 +2164,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2133,7 +2164,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// TODO: check for compiler errors within the lambda body
success = true;
this.navigator = oldNavigator;
}
static bool ExpressionPermittedAsStatement(Expression expr)
@ -2679,7 +2709,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2679,7 +2709,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
ResolveResult target;
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 {
target = Resolve(memberType.Target);
}

1
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

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

Loading…
Cancel
Save