Browse Source

Fixed some issues in the CodeDomConvertVisitor.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
7ff012f1a5
  1. 92
      ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs
  2. 2
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs
  3. 5
      ICSharpCode.NRefactory.CSharp/Resolver/ErrorResolveResult.cs
  4. 2
      ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
  5. 2
      ICSharpCode.NRefactory.Tests/CSharp/CSharpOutputVisitorTests.cs
  6. 177
      ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs
  7. 3
      ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj

92
ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs

@ -21,11 +21,12 @@ using System.CodeDom; @@ -21,11 +21,12 @@ using System.CodeDom;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.PatternMatching;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
namespace ICSharpCode.NRefactory.CSharp
{
@ -37,12 +38,75 @@ namespace ICSharpCode.NRefactory.CSharp @@ -37,12 +38,75 @@ namespace ICSharpCode.NRefactory.CSharp
/// </remarks>
public class CodeDomConvertVisitor : IAstVisitor<object, CodeObject>
{
ITypeResolveContext context;
ITypeResolveContext context = MinimalResolveContext.Instance;
ResolveVisitor resolveVisitor;
bool useFullyQualifiedTypeNames;
/// <summary>
/// Gets/Sets whether the visitor should use fully-qualified type references.
/// </summary>
public bool UseFullyQualifiedTypeNames {
get { return useFullyQualifiedTypeNames; }
set { useFullyQualifiedTypeNames = value; }
}
/// <summary>
/// Converts a compilation unit to CodeDom.
/// </summary>
/// <param name="compilationUnit">The input compilation unit.</param>
/// <param name="context">Type resolve context, used for resolving type references.</param>
/// <param name="parsedFile">CSharpParsedFile, used for resolving.</param>
/// <returns>Converted CodeCompileUnit</returns>
/// <remarks>
/// This conversion process requires a resolver because it needs to distinguish field/property/event references etc.
/// </remarks>
public CodeCompileUnit Convert(CompilationUnit compilationUnit, ITypeResolveContext context, CSharpParsedFile parsedFile)
{
if (compilationUnit == null)
throw new ArgumentNullException("compilationUnit");
if (context == null)
throw new ArgumentNullException("context");
if (parsedFile == null)
throw new ArgumentNullException("parsedFile");
using (var ctx = context.Synchronize()) {
ResolveVisitor resolveVisitor = new ResolveVisitor(new CSharpResolver(ctx), parsedFile);
resolveVisitor.Scan(compilationUnit);
return (CodeCompileUnit)Convert(compilationUnit, resolveVisitor);
}
}
/// <summary>
/// Converts a C# AST node to CodeDom.
/// </summary>
/// <param name="node">The input node.</param>
/// <param name="resolveVisitor">The resolve visitor.
/// The visitor must be already initialized for the file containing the given node (Scan must be called).</param>
/// <returns>The node converted into CodeDom</returns>
/// <remarks>
/// This conversion process requires a resolver because it needs to distinguish field/property/event references etc.
/// </remarks>
public CodeObject Convert(AstNode node, ResolveVisitor resolveVisitor)
{
if (node == null)
throw new ArgumentNullException("node");
if (resolveVisitor == null)
throw new ArgumentNullException("resolveVisitor");
try {
this.resolveVisitor = resolveVisitor;
this.context = resolveVisitor.TypeResolveContext;
return node.AcceptVisitor(this);
} finally {
this.resolveVisitor = null;
this.context = MinimalResolveContext.Instance;
}
}
ResolveResult Resolve(AstNode node)
{
throw new NotImplementedException();
if (resolveVisitor == null)
return ErrorResolveResult.UnknownError;
else
return resolveVisitor.GetResolveResult(node);
}
CodeExpression Convert(Expression expr)
@ -79,7 +143,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -79,7 +143,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeTypeReference Convert(IType type)
{
throw new NotImplementedException();
return new CodeTypeReference(type.ReflectionName);
}
CodeStatement Convert(Statement stmt)
@ -147,25 +211,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -147,25 +211,17 @@ namespace ICSharpCode.NRefactory.CSharp
{
CodeArrayCreateExpression ace = new CodeArrayCreateExpression();
int dimensions = arrayCreateExpression.Arguments.Count;
if (dimensions > 1) {
// CodeDom does not support multi-dimensional arrays
int nestingDepth = arrayCreateExpression.AdditionalArraySpecifiers.Count;
if (dimensions > 0)
nestingDepth++;
if (nestingDepth > 1 || dimensions > 1) {
// CodeDom does not support jagged or multi-dimensional arrays
return MakeSnippetExpression(arrayCreateExpression);
}
if (arrayCreateExpression.Type.IsNull) {
ArrayType arrayType = Resolve(arrayCreateExpression).Type as ArrayType;
if (arrayType != null && arrayType.Dimensions == 1)
ace.CreateType = Convert(arrayType.ElementType);
else
return MakeSnippetExpression(arrayCreateExpression);
ace.CreateType = Convert(Resolve(arrayCreateExpression).Type);
} else {
ace.CreateType = Convert(arrayCreateExpression.Type);
IEnumerable<ArraySpecifier> additionalArraySpecifiers = arrayCreateExpression.AdditionalArraySpecifiers;
if (dimensions == 0) {
additionalArraySpecifiers = additionalArraySpecifiers.Skip(1);
}
foreach (var spec in additionalArraySpecifiers.Reverse()) {
ace.CreateType = new CodeTypeReference(ace.CreateType, spec.Dimensions);
}
}
if (arrayCreateExpression.Arguments.Count == 1) {
ace.SizeExpression = Convert(arrayCreateExpression.Arguments.Single());

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

@ -37,7 +37,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -37,7 +37,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
public class CSharpResolver
{
static readonly ResolveResult ErrorResult = new ErrorResolveResult(SharedTypes.UnknownType);
static readonly ResolveResult ErrorResult = ErrorResolveResult.UnknownError;
static readonly ResolveResult DynamicResult = new ResolveResult(SharedTypes.Dynamic);
static readonly ResolveResult NullResult = new ResolveResult(SharedTypes.Null);

5
ICSharpCode.NRefactory.CSharp/Resolver/ErrorResolveResult.cs

@ -27,6 +27,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -27,6 +27,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
public class ErrorResolveResult : ResolveResult
{
/// <summary>
/// Gets an ErrorResolveResult instance with Type = SharedTypes.UnknownType.
/// </summary>
public static readonly ErrorResolveResult UnknownError = new ErrorResolveResult(SharedTypes.UnknownType);
public ErrorResolveResult(IType type) : base(type)
{
}

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

@ -56,7 +56,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -56,7 +56,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
// The ResolveVisitor is also responsible for handling lambda expressions.
static readonly ResolveResult errorResult = new ErrorResolveResult(SharedTypes.UnknownType);
static readonly ResolveResult errorResult = ErrorResolveResult.UnknownError;
static readonly ResolveResult transparentIdentifierResolveResult = new ResolveResult(SharedTypes.UnboundTypeArgument);
readonly ResolveResult voidResult;

2
ICSharpCode.NRefactory.Tests/CSharp/OutputVisitorTests.cs → ICSharpCode.NRefactory.Tests/CSharp/CSharpOutputVisitorTests.cs

@ -23,7 +23,7 @@ using NUnit.Framework; @@ -23,7 +23,7 @@ using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp
{
[TestFixture]
public class OutputVisitorTests
public class CSharpOutputVisitorTests
{
void AssertOutput(string expected, Expression expr, CSharpFormattingOptions policy = null)
{

177
ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs

@ -0,0 +1,177 @@ @@ -0,0 +1,177 @@
// 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.CodeDom;
using System.CodeDom.Compiler;
using System.IO;
using System.Text.RegularExpressions;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using Microsoft.CSharp;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp
{
[TestFixture]
public class CodeDomConvertVisitorTests : ResolverTestBase
{
CodeDomConvertVisitor convertVisitor;
public override void SetUp()
{
base.SetUp();
AddUsing("System");
AddUsing("System.Collections.Generic");
AddUsing("System.Linq");
resolver.CurrentTypeDefinition = new DefaultTypeDefinition(project, string.Empty, "MyClass");
convertVisitor = new CodeDomConvertVisitor();
convertVisitor.UseFullyQualifiedTypeNames = true;
}
string Convert(Expression expr)
{
ResolveVisitor rv = new ResolveVisitor(resolver, null);
rv.Scan(expr);
var codeExpr = (CodeExpression)convertVisitor.Convert(expr, rv);
StringWriter writer = new StringWriter();
writer.NewLine = " ";
new CSharpCodeProvider().GenerateCodeFromExpression(codeExpr, writer, new CodeGeneratorOptions { IndentString = " " });
return Regex.Replace(writer.ToString(), @"\s+", " ");
}
[Test]
public void CreateArray()
{
Assert.AreEqual("new int[10]", Convert(
new ArrayCreateExpression {
Type = new PrimitiveType("int"),
Arguments = { new PrimitiveExpression(10) }
}));
}
[Test]
public void CreateJaggedArray()
{
Assert.AreEqual("new int[10][]", Convert(
new ArrayCreateExpression {
Type = new PrimitiveType("int"),
Arguments = { new PrimitiveExpression(10) },
AdditionalArraySpecifiers = { new ArraySpecifier() }
}));
}
[Test]
public void Create2DArray()
{
Assert.AreEqual("new int[10, 20]", Convert(
new ArrayCreateExpression {
Type = new PrimitiveType("int"),
Arguments = { new PrimitiveExpression(10), new PrimitiveExpression(20) }
}));
}
[Test]
public void CreateImplicitlyTypedArray()
{
// implicitly-typed array not supported in CodeDom, so the conversion should infer the type
Assert.AreEqual("new int[] { 1, 2, 3}", Convert(
new ArrayCreateExpression {
AdditionalArraySpecifiers = { new ArraySpecifier() },
Initializer = new ArrayInitializerExpression {
Elements = {
new PrimitiveExpression(1),
new PrimitiveExpression(2),
new PrimitiveExpression(3)
}
}
}));
}
[Test]
public void Create2DImplicitlyTypedArray()
{
Assert.AreEqual("new int[,] { { 1, 2 }, { 3, 4 }}", Convert(
new ArrayCreateExpression {
AdditionalArraySpecifiers = { new ArraySpecifier(2) },
Initializer = new ArrayInitializerExpression {
Elements = {
new ArrayInitializerExpression(new PrimitiveExpression(1), new PrimitiveExpression(2)),
new ArrayInitializerExpression(new PrimitiveExpression(3), new PrimitiveExpression(4))
}
}
}));
}
[Test]
public void AdditionOperator()
{
Assert.AreEqual("(0 + 1)", Convert(
new BinaryOperatorExpression(new PrimitiveExpression(0), BinaryOperatorType.Add, new PrimitiveExpression(1))));
}
[Test]
public void EqualityOperator()
{
Assert.AreEqual("(0 == 1)", Convert(
new BinaryOperatorExpression(new PrimitiveExpression(0), BinaryOperatorType.Equality, new PrimitiveExpression(1))));
}
[Test]
public void InEqualityOperator()
{
Assert.AreEqual("((0 == 1) == false)", Convert(
new BinaryOperatorExpression(new PrimitiveExpression(0), BinaryOperatorType.InEquality, new PrimitiveExpression(1))));
}
[Test]
public void ReferenceInEqualityOperator()
{
Assert.AreEqual("(default(object) != null)", Convert(
new BinaryOperatorExpression(new DefaultValueExpression(new PrimitiveType("object")), BinaryOperatorType.InEquality, new NullReferenceExpression())));
}
[Test]
public void StaticProperty()
{
Assert.AreEqual("System.Environment.TickCount", Convert(
new IdentifierExpression("Environment").Member("TickCount")));
}
[Test]
public void InstanceMethodInvocation()
{
Assert.AreEqual("this.Equals(null)",
Convert(new IdentifierExpression("Equals").Invoke(new NullReferenceExpression())));
}
[Test]
public void StaticMethodInvocation()
{
Assert.AreEqual("object.Equals(null, null)",
Convert(new IdentifierExpression("Equals").Invoke(new NullReferenceExpression(), new NullReferenceExpression())));
}
[Test]
public void NotOperator()
{
Assert.AreEqual("(a == false)", Convert(new UnaryOperatorExpression(UnaryOperatorType.Not, new IdentifierExpression("a"))));
}
}
}

3
ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj

@ -77,8 +77,9 @@ @@ -77,8 +77,9 @@
<ItemGroup>
<Compile Include="CSharp\Analysis\DefiniteAssignmentTests.cs" />
<Compile Include="CSharp\AstStructureTests.cs" />
<Compile Include="CSharp\CodeDomConvertVisitorTests.cs" />
<Compile Include="CSharp\InsertParenthesesVisitorTests.cs" />
<Compile Include="CSharp\OutputVisitorTests.cs" />
<Compile Include="CSharp\CSharpOutputVisitorTests.cs" />
<Compile Include="CSharp\Parser\Expression\AnonymousTypeCreateExpressionTests.cs" />
<Compile Include="CSharp\Parser\Expression\ObjectCreateExpressionTests.cs" />
<Compile Include="CSharp\Parser\GeneralScope\DelegateDeclarationTests.cs" />

Loading…
Cancel
Save