Browse Source

Report resolve results back to the navigator.

newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
2c49c71081
  1. 2
      ICSharpCode.NRefactory/CSharp/Analysis/ControlFlow.cs
  2. 2
      ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs
  3. 4
      ICSharpCode.NRefactory/CSharp/Resolver/AmbiguousResolveResult.cs
  4. 80
      ICSharpCode.NRefactory/CSharp/Resolver/DetectSkippableNodesNavigator.cs
  5. 21
      ICSharpCode.NRefactory/CSharp/Resolver/IResolveVisitorNavigator.cs
  6. 2
      ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs
  7. 4
      ICSharpCode.NRefactory/CSharp/Resolver/NodeListResolveVisitorNavigator.cs
  8. 60
      ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs
  9. 1
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
  10. 2
      NRefactory.sln

2
ICSharpCode.NRefactory/CSharp/Analysis/ControlFlow.cs

@ -167,7 +167,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -167,7 +167,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
{
return BuildControlFlowGraph(statement, new ResolveVisitor(
new CSharpResolver(context, cancellationToken),
null, ConstantModeResolveVisitorNavigator.Skip));
null));
}
public IList<ControlFlowNode> BuildControlFlowGraph(Statement statement, ResolveVisitor resolveVisitor)

2
ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs

@ -111,7 +111,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -111,7 +111,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
public DefiniteAssignmentAnalysis(Statement rootStatement, ITypeResolveContext context, CancellationToken cancellationToken)
: this(rootStatement, new ResolveVisitor(new CSharpResolver(context ?? MinimalResolveContext.Instance, cancellationToken),
null, ConstantModeResolveVisitorNavigator.Skip))
null))
{
}

4
ICSharpCode.NRefactory/CSharp/Resolver/AmbiguousResolveResult.cs

@ -35,9 +35,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -35,9 +35,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
public class AmbiguousMemberResultResult : MemberResolveResult
public class AmbiguousMemberResolveResult : MemberResolveResult
{
public AmbiguousMemberResultResult(ResolveResult targetResult, IMember member, IType returnType) : base(targetResult, member, returnType)
public AmbiguousMemberResolveResult(ResolveResult targetResult, IMember member, IType returnType) : base(targetResult, member, returnType)
{
}

80
ICSharpCode.NRefactory/CSharp/Resolver/DetectSkippableNodesNavigator.cs

@ -0,0 +1,80 @@ @@ -0,0 +1,80 @@
// 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 System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
/// <summary>
/// When an <see cref="IResolveVisitorNavigator"/> is searching for specific nodes
/// (e.g. all IdentifierExpressions), it has to scan the whole compilation unit for those nodes.
/// However, scanning in the ResolveVisitor is expensive (e.g. any lambda that is scanned must be resolved),
/// so it makes sense to detect when a whole subtree is scan-only, and skip that tree instead.
///
/// The DetectSkippableNodesNavigator performs this job by running the input IResolveVisitorNavigator
/// over the whole AST, and detecting subtrees that are scan-only, and replaces them with Skip.
/// </summary>
public sealed class DetectSkippableNodesNavigator : IResolveVisitorNavigator
{
readonly Dictionary<AstNode, ResolveVisitorNavigationMode> dict = new Dictionary<AstNode, ResolveVisitorNavigationMode>();
IResolveVisitorNavigator navigator;
public DetectSkippableNodesNavigator(IResolveVisitorNavigator navigator, AstNode root)
{
this.navigator = navigator;
Init(root);
}
bool Init(AstNode node)
{
var mode = navigator.Scan(node);
if (mode == ResolveVisitorNavigationMode.Skip)
return false;
bool needsResolve = (mode != ResolveVisitorNavigationMode.Scan);
for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
needsResolve |= Init(child);
}
if (needsResolve) {
// If this node or any child node needs resolving, store the mode in the dictionary.
dict.Add(node, mode);
}
return needsResolve;
}
/// <inheritdoc/>
public ResolveVisitorNavigationMode Scan(AstNode node)
{
ResolveVisitorNavigationMode mode;
if (dict.TryGetValue(node, out mode)) {
return mode;
} else {
return ResolveVisitorNavigationMode.Skip;
}
}
/// <inheritdoc/>
public void Resolved(AstNode node, ResolveResult result)
{
navigator.Resolved(node, result);
}
}
}

21
ICSharpCode.NRefactory/CSharp/Resolver/IResolveVisitorNavigator.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
@ -26,7 +27,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -26,7 +27,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// <seealso cref="ResolveVisitor"/>
public interface IResolveVisitorNavigator
{
/// <summary>
/// Asks the navigator whether to scan, skip, or resolve a node.
/// </summary>
ResolveVisitorNavigationMode Scan(AstNode node);
/// <summary>
/// Notifies the navigator that a node was resolved.
/// </summary>
void Resolved(AstNode node, ResolveResult result);
}
/// <summary>
@ -52,16 +61,4 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -52,16 +61,4 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
ResolveAll
}
sealed class ConstantModeResolveVisitorNavigator : IResolveVisitorNavigator
{
ResolveVisitorNavigationMode mode;
public static readonly IResolveVisitorNavigator Skip = new ConstantModeResolveVisitorNavigator { mode = ResolveVisitorNavigationMode.Skip };
ResolveVisitorNavigationMode IResolveVisitorNavigator.Scan(AstNode node)
{
return mode;
}
}
}

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

@ -269,7 +269,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -269,7 +269,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return new MemberResolveResult(targetResolveResult, firstNonMethod, context);
if (firstNonMethod == null)
return new MethodGroupResolveResult(targetResolveResult, name, members.ConvertAll(m => (IMethod)m), typeArguments);
return new AmbiguousMemberResultResult(targetResolveResult, firstNonMethod, firstNonMethod.ReturnType.Resolve(context));
return new AmbiguousMemberResolveResult(targetResolveResult, firstNonMethod, firstNonMethod.ReturnType.Resolve(context));
}
static bool IsNonInterfaceType(ITypeDefinition def)

4
ICSharpCode.NRefactory/CSharp/Resolver/NodeListResolveVisitorNavigator.cs

@ -54,5 +54,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -54,5 +54,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return ResolveVisitorNavigationMode.Skip;
}
}
void IResolveVisitorNavigator.Resolved(AstNode node, ResolveResult result)
{
}
}
}

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

@ -168,7 +168,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -168,7 +168,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// lambdas must be resolved so that they get stored in the 'undecided' list only once
goto case ResolveVisitorNavigationMode.Resolve;
}
resolverBeforeDict[node] = resolver.Clone();
StoreState(node, resolver.Clone());
node.AcceptVisitor(this, null);
break;
case ResolveVisitorNavigationMode.Resolve:
@ -192,9 +192,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -192,9 +192,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ResolveResult result;
if (!resolveResultCache.TryGetValue(node, out result)) {
resolver.cancellationToken.ThrowIfCancellationRequested();
resolverBeforeDict[node] = resolver.Clone();
result = resolveResultCache[node] = node.AcceptVisitor(this, null) ?? errorResult;
StoreState(node, resolver.Clone());
result = node.AcceptVisitor(this, null) ?? errorResult;
Log.WriteLine("Resolved '{0}' to {1}", node, result);
StoreResult(node, result);
ProcessConversionsInResult(result);
}
if (wasScan)
@ -202,6 +203,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -202,6 +203,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return result;
}
void StoreState(AstNode node, CSharpResolver resolverState)
{
Debug.Assert(resolverState != null);
resolverBeforeDict.Add(node, resolverState);
}
void StoreResult(AstNode node, ResolveResult result)
{
Debug.Assert(result != null);
resolveResultCache.Add(node, result);
if (navigator != null)
navigator.Resolved(node, result);
}
protected override ResolveResult VisitChildren(AstNode node, object data)
{
ScanChildren(node);
@ -1148,21 +1163,26 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1148,21 +1163,26 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// rr = Resolve(memberReferenceExpression)
IdentifierExpression identifierExpression = memberReferenceExpression.Target as IdentifierExpression;
if (identifierExpression != null && identifierExpression.TypeArguments.Count == 0) {
if (identifierExpression != null && identifierExpression.TypeArguments.Count == 0
&& !resolveResultCache.ContainsKey(identifierExpression))
{
// Special handling for §7.6.4.1 Identicial simple names and type names
StoreState(identifierExpression, resolver.Clone());
ResolveResult target = resolver.ResolveSimpleName(identifierExpression.Identifier, EmptyList<IType>.Instance);
TypeResolveResult trr;
if (IsVariableReferenceWithSameType(target, identifierExpression.Identifier, out trr)) {
// It's ambiguous
ResolveResult rr = ResolveMemberReferenceOnGivenTarget(target, memberReferenceExpression);
resolveResultCache[identifierExpression] = IsStaticResult(rr, null) ? trr : target;
Log.WriteLine("Ambiguous simple name '{0}' was resolved to {1}",
identifierExpression, resolveResultCache[identifierExpression]);
ResolveResult simpleNameRR = IsStaticResult(rr, null) ? trr : target;
Log.WriteLine("Ambiguous simple name '{0}' was resolved to {1}", identifierExpression, simpleNameRR);
StoreResult(identifierExpression, simpleNameRR);
ProcessConversionsInResult(simpleNameRR);
return rr;
} else {
// It's not ambiguous
resolveResultCache[identifierExpression] = target;
Log.WriteLine("Simple name '{0}' was resolved to {1}", identifierExpression, target);
StoreResult(identifierExpression, target);
ProcessConversionsInResult(target);
if (resolverEnabled) {
return ResolveMemberReferenceOnGivenTarget(target, memberReferenceExpression);
} else {
@ -1203,24 +1223,30 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1203,24 +1223,30 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
MemberReferenceExpression mre = invocationExpression.Target as MemberReferenceExpression;
IdentifierExpression identifierExpression = mre != null ? mre.Target as IdentifierExpression : null;
if (identifierExpression != null && identifierExpression.TypeArguments.Count == 0) {
if (identifierExpression != null && identifierExpression.TypeArguments.Count == 0
&& !resolveResultCache.ContainsKey(identifierExpression))
{
// Special handling for §7.6.4.1 Identicial simple names and type names
ResolveResult idRR = resolver.ResolveSimpleName(identifierExpression.Identifier, EmptyList<IType>.Instance);
ResolveResult target = ResolveMemberReferenceOnGivenTarget(idRR, mre);
resolveResultCache[mre] = target;
Log.WriteLine("Member reference '{0}' on potentially-ambiguous simple-name was resolved to {1}", mre, target);
StoreResult(mre, target);
ProcessConversionsInResult(target);
TypeResolveResult trr;
if (IsVariableReferenceWithSameType(idRR, identifierExpression.Identifier, out trr)) {
// It's ambiguous
ResolveResult rr = ResolveInvocationOnGivenTarget(target, invocationExpression);
resolveResultCache[identifierExpression] = IsStaticResult(target, rr) ? trr : idRR;
ResolveResult simpleNameRR = IsStaticResult(target, rr) ? trr : idRR;
Log.WriteLine("Ambiguous simple name '{0}' was resolved to {1}",
identifierExpression, resolveResultCache[identifierExpression]);
identifierExpression, simpleNameRR);
StoreResult(identifierExpression, simpleNameRR);
ProcessConversionsInResult(simpleNameRR);
return rr;
} else {
// It's not ambiguous
Log.WriteLine("Simple name '{0}' was resolved to {1}", identifierExpression, idRR);
resolveResultCache[identifierExpression] = idRR;
StoreResult(identifierExpression, idRR);
ProcessConversionsInResult(idRR);
if (resolverEnabled) {
return ResolveInvocationOnGivenTarget(target, invocationExpression);
} else {
@ -1658,10 +1684,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1658,10 +1684,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
visitor.MergeUndecidedLambdas();
Log.WriteLine("Merging " + ToString());
foreach (var pair in visitor.resolveResultCache) {
parentVisitor.resolveResultCache.Add(pair.Key, pair.Value);
parentVisitor.StoreResult(pair.Key, pair.Value);
}
foreach (var pair in visitor.resolverBeforeDict) {
parentVisitor.resolverBeforeDict.Add(pair.Key, pair.Value);
parentVisitor.StoreState(pair.Key, pair.Value);
}
parentVisitor.undecidedLambdas.Remove(lambda);
}
@ -2034,9 +2060,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2034,9 +2060,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// so we just do it here and store the result in the resolver cache.
IType actualType = typeRef.Resolve(resolver.Context);
if (actualType.Kind != TypeKind.Unknown) {
resolveResultCache.Add(type, new TypeResolveResult(actualType));
StoreResult(type, new TypeResolveResult(actualType));
} else {
resolveResultCache.Add(type, errorResult);
StoreResult(type, errorResult);
}
return actualType;
} else {

1
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -102,6 +102,7 @@ @@ -102,6 +102,7 @@
<Compile Include="CSharp\Ast\GeneralScope\TypeParameterDeclaration.cs" />
<Compile Include="CSharp\Ast\MemberType.cs" />
<Compile Include="CSharp\Refactoring\TypeSystemAstBuilder.cs" />
<Compile Include="CSharp\Resolver\DetectSkippableNodesNavigator.cs" />
<Compile Include="CSharp\Resolver\OperatorResolveResult.cs" />
<Compile Include="CSharp\Resolver\ConversionResolveResult.cs" />
<Compile Include="CSharp\Resolver\CSharpAttribute.cs" />

2
NRefactory.sln

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
# SharpDevelop 4.1.0.7590-alpha
# SharpDevelop 4.1.0.7800-beta
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DC98210E-1646-483B-819A-2BB8272461E4}"
ProjectSection(SolutionItems) = postProject
README = README

Loading…
Cancel
Save