Browse Source

Replace AstNode.GetResolvableNodeAt() with the ResolveAtLocation helper class.

newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
33abc64eec
  1. 78
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolveAtLocationTests.cs
  2. 26
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs
  3. 1
      ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
  4. 56
      ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs
  5. 76
      ICSharpCode.NRefactory/CSharp/Resolver/ResolveAtLocation.cs
  6. 16
      ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs
  7. 1
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

78
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolveAtLocationTests.cs

@ -0,0 +1,78 @@ @@ -0,0 +1,78 @@
// 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;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
[TestFixture]
public class ResolveAtLocationTests : ResolverTestBase
{
[Test]
public void UsingDeclaration()
{
Assert.IsNull(ResolveAtLocation("usi$ng System;"));
}
[Test]
public void UsingDeclarationNamespace()
{
var rr = ResolveAtLocation<NamespaceResolveResult>("using $System;");
Assert.AreEqual("System", rr.NamespaceName);
}
[Test]
public void CatchClauseVariable()
{
var rr = ResolveAtLocation<LocalResolveResult>("using System; public class A { void M() { try { } catch (Exception e$x) { } } }");
Assert.AreEqual("ex", rr.Variable.Name);
Assert.AreEqual("System.Exception", rr.Type.FullName);
}
[Test]
public void MethodInvocation()
{
var rr = ResolveAtLocation<InvocationResolveResult>(@"using System;
class A { void M() {
Console.W$riteLine(1);
}}");
Assert.AreEqual("System.Console.WriteLine", rr.Member.FullName);
Assert.AreEqual("System.Int32", rr.Member.Parameters[0].Type.Resolve(context).FullName);
}
[Test]
public void ImplicitlyTypedVariable()
{
var rr = ResolveAtLocation<TypeResolveResult>(@"using System;
class A { void M() {
v$ar x = Environment.TickCount;
}}");
Assert.AreEqual("System.Int32", rr.Type.FullName);
}
[Test, Ignore("Parser returns incorrect positions")]
public void BaseCtorCall()
{
var rr = ResolveAtLocation<InvocationResolveResult>(@"using System;
class A { public A() : ba$se() {} }");
Assert.AreEqual("System.Object..ctor", rr.Member.FullName);
}
}
}

26
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs

@ -254,5 +254,31 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -254,5 +254,31 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
}
protected ResolveResult ResolveAtLocation(string code)
{
CompilationUnit cu = new CSharpParser().Parse(new StringReader(code.Replace("$", "")));
AstLocation[] dollars = FindDollarSigns(code).ToArray();
Assert.AreEqual(1, dollars.Length, "Expected 1 dollar signs marking the location");
SetUp();
ParsedFile parsedFile = new ParsedFile("test.cs", resolver.CurrentUsingScope);
TypeSystemConvertVisitor convertVisitor = new TypeSystemConvertVisitor(parsedFile, resolver.CurrentUsingScope, null);
cu.AcceptVisitor(convertVisitor, null);
project.UpdateProjectContent(null, convertVisitor.ParsedFile);
ResolveResult rr = Resolver.ResolveAtLocation.Resolve(this.context, parsedFile, cu, dollars[0]);
return rr;
}
protected T ResolveAtLocation<T>(string code) where T : ResolveResult
{
ResolveResult rr = ResolveAtLocation(code);
Assert.IsNotNull(rr);
Assert.IsTrue(rr.GetType() == typeof(T), "Resolve should be " + typeof(T).Name + ", but was " + rr.GetType().Name);
return (T)rr;
}
}
}

1
ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj

@ -155,6 +155,7 @@ @@ -155,6 +155,7 @@
<Compile Include="CSharp\Resolver\LocalTypeInferenceTests.cs" />
<Compile Include="CSharp\Resolver\NameLookupTests.cs" />
<Compile Include="CSharp\Resolver\ObjectCreationTests.cs" />
<Compile Include="CSharp\Resolver\ResolveAtLocationTests.cs" />
<Compile Include="CSharp\Resolver\TypeInferenceTests.cs" />
<Compile Include="CSharp\Resolver\ConversionsTest.cs" />
<Compile Include="CSharp\Resolver\OverloadResolutionTests.cs" />

56
ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs

@ -562,62 +562,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -562,62 +562,6 @@ namespace ICSharpCode.NRefactory.CSharp
return result;
}
public AstNode GetResolveableNodeAt (int line, int column)
{
return GetResolveableNodeAt (new AstLocation (line, column));
}
/// <summary>
/// Gets a node that can be resolved at location.
/// </summary>
public AstNode GetResolveableNodeAt (AstLocation location)
{
return GetNodeAt (location, delegate (AstNode n) {
if (n is TypeDeclaration) {
var decl = (TypeDeclaration)n;
return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation;
}
if (n is DelegateDeclaration) {
var decl = (DelegateDeclaration)n;
return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation;
}
if (n is MemberDeclaration) {
var decl = (MemberDeclaration)n;
return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation;
}
if (n is ConstructorDeclaration) {
var decl = (ConstructorDeclaration)n;
return decl.IdentifierToken.StartLocation <= location && location <= decl.IdentifierToken.EndLocation;
}
if (n is DestructorDeclaration) {
var decl = (DestructorDeclaration)n;
return decl.IdentifierToken.StartLocation <= location && location <= decl.IdentifierToken.EndLocation;
}
if (n is VariableInitializer) {
var decl = (VariableInitializer)n;
return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation;
}
if (n is ParameterDeclaration) {
var decl = (ParameterDeclaration)n;
return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation;
}
if (n is MemberReferenceExpression) {
var decl = (MemberReferenceExpression)n;
return decl.MemberNameToken.StartLocation <= location && location <= decl.MemberNameToken.EndLocation;
}
return n is IdentifierExpression || n is AstType;
});
}
public IEnumerable<AstNode> GetNodesBetween (int startLine, int startColumn, int endLine, int endColumn)
{
return GetNodesBetween (new AstLocation (startLine, startColumn), new AstLocation (endLine, endColumn));

76
ICSharpCode.NRefactory/CSharp/Resolver/ResolveAtLocation.cs

@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
// 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.Threading;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
/// <summary>
/// Helper class that resolves the node at a specified location.
/// Can be used for implementing tool tips.
/// </summary>
public static class ResolveAtLocation
{
public static ResolveResult Resolve(ITypeResolveContext context, ParsedFile parsedFile, CompilationUnit cu, AstLocation location,
CancellationToken cancellationToken = default(CancellationToken))
{
AstNode node = cu.GetNodeAt(location);
AstNode resolvableNode;
if (node is Identifier) {
resolvableNode = node.Parent;
} else if (node.NodeType == NodeType.Token) {
if (node.Parent is ConstructorInitializer) {
resolvableNode = node.Parent;
} else {
return null;
}
} else {
// don't resolve arbitrary nodes - we don't want to show tooltips for everything
return null;
}
InvocationExpression parentInvocation = null;
if ((resolvableNode is IdentifierExpression || resolvableNode is MemberReferenceExpression || resolvableNode is PointerReferenceExpression)) {
// we also need to resolve the invocation
parentInvocation = resolvableNode.Parent as InvocationExpression;
}
IResolveVisitorNavigator navigator;
if (parentInvocation != null)
navigator = new NodeListResolveVisitorNavigator(new[] { resolvableNode, parentInvocation });
else
navigator = new NodeListResolveVisitorNavigator(new[] { resolvableNode });
using (var ctx = context.Synchronize()) {
CSharpResolver resolver = new CSharpResolver(ctx, cancellationToken);
ResolveVisitor v = new ResolveVisitor(resolver, parsedFile, navigator);
v.Scan(cu);
// Prefer the RR from the token itself, if it was assigned a ResolveResult
// (this can happen with the identifiers in various nodes such as catch clauses or foreach statements)
ResolveResult rr = v.GetResolveResult(node) ?? v.GetResolveResult(resolvableNode);
if (rr is MethodGroupResolveResult && parentInvocation != null)
return v.GetResolveResult(parentInvocation);
else
return rr;
}
}
}
}

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

@ -2076,17 +2076,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2076,17 +2076,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public override ResolveResult VisitCatchClause(CatchClause catchClause, object data)
{
resolver.PushBlock();
IVariable v = null;
if (catchClause.VariableName != null) {
v = resolver.AddVariable(MakeTypeReference(catchClause.Type, null, false), MakeRegion(catchClause.VariableNameToken), catchClause.VariableName);
ITypeReference variableType = MakeTypeReference(catchClause.Type, null, false);
DomRegion region = MakeRegion(catchClause.VariableNameToken);
IVariable v = resolver.AddVariable(variableType, region, catchClause.VariableName);
StoreResult(catchClause.VariableNameToken, new LocalResolveResult(v, v.Type.Resolve(resolver.Context)));
}
ScanChildren(catchClause);
resolver.PopBlock();
if (resolverEnabled && v != null) {
return new LocalResolveResult(v, v.Type.Resolve(resolver.Context));
} else {
return null;
}
return voidResult;
}
#endregion
@ -2420,7 +2418,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2420,7 +2418,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
currentTypeLookupMode = SimpleNameLookupMode.TypeInUsingDeclaration;
ScanChildren(usingDeclaration);
currentTypeLookupMode = SimpleNameLookupMode.Type;
return null;
return voidResult;
}
public override ResolveResult VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration, object data)
@ -2428,7 +2426,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2428,7 +2426,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
currentTypeLookupMode = SimpleNameLookupMode.TypeInUsingDeclaration;
ScanChildren(usingDeclaration);
currentTypeLookupMode = SimpleNameLookupMode.Type;
return null;
return voidResult;
}
#endregion

1
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -110,6 +110,7 @@ @@ -110,6 +110,7 @@
<Compile Include="CSharp\Resolver\InvocationResolveResult.cs" />
<Compile Include="CSharp\Resolver\LambdaResolveResult.cs" />
<Compile Include="CSharp\Resolver\MapTypeIntoNewContext.cs" />
<Compile Include="CSharp\Resolver\ResolveAtLocation.cs" />
<Compile Include="CSharp\Resolver\SimpleNameLookupMode.cs" />
<Compile Include="Documentation\IDStringProvider.cs" />
<Compile Include="PatternMatching\BacktrackingInfo.cs" />

Loading…
Cancel
Save