Browse Source

Improved "Extract Method" and added IsReferenceType to IReturnType

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3512 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Siegfried Pammer 18 years ago
parent
commit
e0c660f7bb
  1. 51
      src/AddIns/Misc/SharpRefactoring/Src/CSharpMethodExtractor.cs
  2. 25
      src/AddIns/Misc/SharpRefactoring/Src/MethodExtractorBase.cs
  3. 30
      src/Libraries/NRefactory/Project/Src/AstBuilder/ExpressionBuilder.cs
  4. 36
      src/Libraries/NRefactory/Project/Src/Visitors/VBNetConstructsConvertVisitor.cs
  5. 6
      src/Main/Base/Test/Utils/MockDefaultReturnType.cs
  6. 2
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AbstractReturnType.cs
  7. 8
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultReturnType.cs
  8. 4
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/GenericReturnType.cs
  9. 9
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/ProxyReturnType.cs
  10. 2
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/IReturnType.cs
  11. 9
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/CodeGenerator.cs

51
src/AddIns/Misc/SharpRefactoring/Src/CSharpMethodExtractor.cs

@ -4,18 +4,23 @@
// <owner name="Siegfried Pammer" email="sie_pam@gmx.at"/> // <owner name="Siegfried Pammer" email="sie_pam@gmx.at"/>
// <version>$Revision: 3287 $</version> // <version>$Revision: 3287 $</version>
// </file> // </file>
using ICSharpCode.SharpDevelop;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.AstBuilder;
using ICSharpCode.NRefactory.PrettyPrinter; using ICSharpCode.NRefactory.PrettyPrinter;
using ICSharpCode.NRefactory.Visitors; using ICSharpCode.NRefactory.Visitors;
using ICSharpCode.SharpDevelop.Dom.NRefactoryResolver;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.TextEditor.Document; using ICSharpCode.TextEditor.Document;
using SharpRefactoring.Transformers; using SharpRefactoring.Transformers;
using SharpRefactoring.Visitors; using SharpRefactoring.Visitors;
using Dom = ICSharpCode.SharpDevelop.Dom;
namespace SharpRefactoring namespace SharpRefactoring
{ {
@ -52,6 +57,8 @@ namespace SharpRefactoring
this.specialsList = parser.Lexer.SpecialTracker.RetrieveSpecials(); this.specialsList = parser.Lexer.SpecialTracker.RetrieveSpecials();
} }
this.currentProjectContent = ParserService.GetProjectContent(ProjectService.CurrentProject);
MethodDeclaration newMethod = new MethodDeclaration(); MethodDeclaration newMethod = new MethodDeclaration();
List<VariableDeclaration> possibleReturnValues = new List<VariableDeclaration>(); List<VariableDeclaration> possibleReturnValues = new List<VariableDeclaration>();
@ -74,7 +81,7 @@ namespace SharpRefactoring
newMethod.Modifier = parentNode.Modifier; newMethod.Modifier = parentNode.Modifier;
newMethod.Modifier &= ~(Modifiers.Internal | Modifiers.Protected | Modifiers.Private | Modifiers.Public); newMethod.Modifier &= ~(Modifiers.Internal | Modifiers.Protected | Modifiers.Private | Modifiers.Public | Modifiers.Override);
foreach (ParameterDeclarationExpression pde in parentNode.Parameters) foreach (ParameterDeclarationExpression pde in parentNode.Parameters)
{ {
@ -105,36 +112,40 @@ namespace SharpRefactoring
parentNode.AcceptVisitor(ltv, null); parentNode.AcceptVisitor(ltv, null);
Location start = new Location(this.currentSelection.StartPosition.Column + 1, this.currentSelection.StartPosition.Line + 1);
Location end = new Location(this.currentSelection.EndPosition.Column + 1, this.currentSelection.EndPosition.Line + 1);
foreach (KeyValuePair<string, List<LocalLookupVariable>> pair in ltv.Variables) { foreach (KeyValuePair<string, List<LocalLookupVariable>> pair in ltv.Variables) {
foreach (LocalLookupVariable variable in pair.Value) { foreach (LocalLookupVariable variable in pair.Value) {
if (variable.StartPos > end)
continue;
if (IsInSel(variable.StartPos, this.currentSelection) && HasOccurrencesAfter(true, this.parentNode, new Location(this.currentSelection.EndPosition.Column + 1, this.currentSelection.EndPosition.Line + 1), variable.Name, variable.StartPos, variable.EndPos)) { if (IsInSel(variable.StartPos, this.currentSelection) && HasOccurrencesAfter(true, this.parentNode, new Location(this.currentSelection.EndPosition.Column + 1, this.currentSelection.EndPosition.Line + 1), variable.Name, variable.StartPos, variable.EndPos)) {
possibleReturnValues.Add(new VariableDeclaration(variable.Name, variable.Initializer, variable.TypeRef)); possibleReturnValues.Add(new VariableDeclaration(variable.Name, variable.Initializer, variable.TypeRef));
otherReturnValues.Add(new VariableDeclaration(variable.Name, variable.Initializer, variable.TypeRef)); otherReturnValues.Add(new VariableDeclaration(variable.Name, variable.Initializer, variable.TypeRef));
} }
Location start = new Location(this.currentSelection.StartPosition.Column + 1, this.currentSelection.StartPosition.Line + 1);
Location end = new Location(this.currentSelection.EndPosition.Column + 1, this.currentSelection.EndPosition.Line + 1);
FindReferenceVisitor frv = new FindReferenceVisitor(true, variable.Name, start, end); FindReferenceVisitor frv = new FindReferenceVisitor(true, variable.Name, start, end);
parentNode.AcceptVisitor(frv, null); parentNode.AcceptVisitor(frv, null);
if ((frv.Identifiers.Count > 0) && (!(IsInSel(variable.StartPos, this.currentSelection) || IsInSel(variable.EndPos, this.currentSelection)))) { if ((frv.Identifiers.Count > 0) && (!(IsInSel(variable.StartPos, this.currentSelection) || IsInSel(variable.EndPos, this.currentSelection)))) {
bool hasOccurrences = HasOccurrencesAfter(true, this.parentNode, new Location(this.currentSelection.EndPosition.Column + 1, this.currentSelection.EndPosition.Line + 1), variable.Name, variable.StartPos, variable.EndPos); bool hasOccurrencesAfter = HasOccurrencesAfter(true, this.parentNode, new Location(this.currentSelection.EndPosition.Column + 1, this.currentSelection.EndPosition.Line + 1), variable.Name, variable.StartPos, variable.EndPos);
bool isInitialized = IsInitializedVariable(true, this.parentNode, variable); bool isInitialized = IsInitializedVariable(true, this.parentNode, variable);
bool hasAssignment = HasAssignment(newMethod, variable); bool hasAssignment = HasAssignment(newMethod, variable);
bool getsAssigned = pair.Value.Count > 0; bool getsAssigned = pair.Value.Count > 0;
if (hasOccurrences && isInitialized) if (hasOccurrencesAfter && isInitialized)
newMethod.Parameters.Add(new ParameterDeclarationExpression(variable.TypeRef, variable.Name, ParameterModifiers.Ref)); newMethod.Parameters.Add(new ParameterDeclarationExpression(variable.TypeRef, variable.Name, ParameterModifiers.Ref));
else { else {
if (hasOccurrences && hasAssignment) if (hasOccurrencesAfter && hasAssignment)
newMethod.Parameters.Add(new ParameterDeclarationExpression(variable.TypeRef, variable.Name, ParameterModifiers.Out)); newMethod.Parameters.Add(new ParameterDeclarationExpression(variable.TypeRef, variable.Name, ParameterModifiers.Out));
else { else {
if (!hasOccurrences && getsAssigned) if (!hasOccurrencesAfter && getsAssigned)
newMethod.Parameters.Add(new ParameterDeclarationExpression(variable.TypeRef, variable.Name, ParameterModifiers.None)); newMethod.Parameters.Add(new ParameterDeclarationExpression(variable.TypeRef, variable.Name, ParameterModifiers.None));
else { else {
if (!hasOccurrences && !isInitialized) if (!hasOccurrencesAfter && !isInitialized)
newMethod.Body.Children.Insert(0, new LocalVariableDeclaration(new VariableDeclaration(variable.Name, variable.Initializer, variable.TypeRef))); newMethod.Body.Children.Insert(0, new LocalVariableDeclaration(new VariableDeclaration(variable.Name, variable.Initializer, variable.TypeRef)));
else else
newMethod.Parameters.Add(new ParameterDeclarationExpression(variable.TypeRef, variable.Name, ParameterModifiers.In)); newMethod.Parameters.Add(new ParameterDeclarationExpression(variable.TypeRef, variable.Name, ParameterModifiers.In));
@ -159,12 +170,32 @@ namespace SharpRefactoring
this.beforeCallDeclarations.Add(new LocalVariableDeclaration(varDecl)); this.beforeCallDeclarations.Add(new LocalVariableDeclaration(varDecl));
} }
} }
ReplaceUnnecessaryVariableDeclarationsTransformer t = new ReplaceUnnecessaryVariableDeclarationsTransformer(paramsAsVarDecls); ReplaceUnnecessaryVariableDeclarationsTransformer t = new ReplaceUnnecessaryVariableDeclarationsTransformer(paramsAsVarDecls);
newMethod.AcceptVisitor(t, null); newMethod.AcceptVisitor(t, null);
CreateReturnStatement(newMethod, possibleReturnValues); CreateReturnStatement(newMethod, possibleReturnValues);
bool hasReturnStatement = false;
foreach (INode node in newMethod.Body.Children) {
if (node is ReturnStatement) {
hasReturnStatement = true;
}
}
if (!hasReturnStatement) {
Dom.IMember member = GetParentMember(this.textEditor, this.currentSelection.StartPosition);
Dom.IReturnType returnType = TypeVisitor.CreateReturnType(newMethod.TypeReference, member.DeclaringType, member,
this.currentSelection.StartPosition.Line, this.currentSelection.StartPosition.Column, member.DeclaringType.ProjectContent, true);
if (returnType.IsReferenceType == null || returnType.IsReferenceType == true)
newMethod.Body.AddChild(new ReturnStatement(new PrimitiveExpression(null, "null")));
else
newMethod.Body.AddChild(new ReturnStatement(ExpressionBuilder.CreateDefaultValueForType(newMethod.TypeReference)));
}
this.extractedMethod = newMethod; this.extractedMethod = newMethod;

25
src/AddIns/Misc/SharpRefactoring/Src/MethodExtractorBase.cs

@ -4,17 +4,18 @@
// <owner name="Siegfried Pammer" email="sie_pam@gmx.at"/> // <owner name="Siegfried Pammer" email="sie_pam@gmx.at"/>
// <version>$Revision: 3287 $</version> // <version>$Revision: 3287 $</version>
// </file> // </file>
using ICSharpCode.TextEditor;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.PrettyPrinter; using ICSharpCode.NRefactory.PrettyPrinter;
using ICSharpCode.NRefactory.Visitors; using ICSharpCode.NRefactory.Visitors;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.TextEditor.Document; using ICSharpCode.TextEditor.Document;
using SharpRefactoring.Visitors; using SharpRefactoring.Visitors;
using Dom = ICSharpCode.SharpDevelop.Dom; using Dom = ICSharpCode.SharpDevelop.Dom;
@ -37,6 +38,9 @@ namespace SharpRefactoring
protected VariableDeclaration returnedVariable; protected VariableDeclaration returnedVariable;
protected List<ISpecial> specialsList; protected List<ISpecial> specialsList;
protected Dom.IClass currentClass;
protected Dom.IProjectContent currentProjectContent;
public Statement Caller { public Statement Caller {
get { return caller; } get { return caller; }
} }
@ -88,19 +92,15 @@ namespace SharpRefactoring
if (this.parentNode is MethodDeclaration) newMethod.TypeReference = (this.parentNode as MethodDeclaration).TypeReference; if (this.parentNode is MethodDeclaration) newMethod.TypeReference = (this.parentNode as MethodDeclaration).TypeReference;
if (this.parentNode is PropertyDeclaration) newMethod.TypeReference = (this.parentNode as PropertyDeclaration).TypeReference; if (this.parentNode is PropertyDeclaration) newMethod.TypeReference = (this.parentNode as PropertyDeclaration).TypeReference;
if (this.parentNode is OperatorDeclaration) newMethod.TypeReference = (this.parentNode as OperatorDeclaration).TypeReference; if (this.parentNode is OperatorDeclaration) newMethod.TypeReference = (this.parentNode as OperatorDeclaration).TypeReference;
} } else {
else {
if (possibleReturnValues.Count > 0) { if (possibleReturnValues.Count > 0) {
newMethod.TypeReference = possibleReturnValues[possibleReturnValues.Count - 1].TypeReference; newMethod.TypeReference = possibleReturnValues[possibleReturnValues.Count - 1].TypeReference;
newMethod.Body.Children.Add(new ReturnStatement(new IdentifierExpression(possibleReturnValues[possibleReturnValues.Count - 1].Name))); newMethod.Body.Children.Add(new ReturnStatement(new IdentifierExpression(possibleReturnValues[possibleReturnValues.Count - 1].Name)));
this.returnedVariable = possibleReturnValues[possibleReturnValues.Count - 1];
} else {
newMethod.TypeReference = new TypeReference("void");
this.returnedVariable = null;
} }
else newMethod.TypeReference = new TypeReference("void");
}
if (newMethod.TypeReference.Type == "void") {
this.returnedVariable = null;
} else {
this.returnedVariable = possibleReturnValues[possibleReturnValues.Count - 1];
} }
} }
@ -208,6 +208,11 @@ namespace SharpRefactoring
throw new InvalidOperationException("Cannot use plain MethodExtractor, please use a language specific implementation!"); throw new InvalidOperationException("Cannot use plain MethodExtractor, please use a language specific implementation!");
} }
protected Dom.IMember GetParentMember(ICSharpCode.TextEditor.TextEditorControl textEditor, TextLocation location)
{
return GetParentMember(textEditor, location.Line, location.Column);
}
protected Dom.IMember GetParentMember(ICSharpCode.TextEditor.TextEditorControl textEditor, int line, int column) protected Dom.IMember GetParentMember(ICSharpCode.TextEditor.TextEditorControl textEditor, int line, int column)
{ {
Dom.ParseInformation parseInfo = ParserService.GetParseInformation(textEditor.FileName); Dom.ParseInformation parseInfo = ParserService.GetParseInformation(textEditor.FileName);

30
src/Libraries/NRefactory/Project/Src/AstBuilder/ExpressionBuilder.cs

@ -53,6 +53,36 @@ namespace ICSharpCode.NRefactory.AstBuilder
throw new ArgumentNullException("arguments"); throw new ArgumentNullException("arguments");
return new ObjectCreateExpression(createType, new List<Expression>(arguments)); return new ObjectCreateExpression(createType, new List<Expression>(arguments));
} }
public static Expression CreateDefaultValueForType(TypeReference type)
{
if (type != null && !type.IsArrayType) {
switch (type.SystemType) {
case "System.SByte":
case "System.Byte":
case "System.Int16":
case "System.UInt16":
case "System.Int32":
case "System.UInt32":
case "System.Int64":
case "System.UInt64":
case "System.Single":
case "System.Double":
return new PrimitiveExpression(0, "0");
case "System.Char":
return new PrimitiveExpression('\0', "'\\0'");
case "System.Object":
case "System.String":
return new PrimitiveExpression(null, "null");
case "System.Boolean":
return new PrimitiveExpression(false, "false");
default:
return new DefaultValueExpression(type);
}
} else {
return new PrimitiveExpression(null, "null");
}
}
} }
#endif #endif
} }

36
src/Libraries/NRefactory/Project/Src/Visitors/VBNetConstructsConvertVisitor.cs

@ -5,10 +5,10 @@
// <version>$Revision$</version> // <version>$Revision$</version>
// </file> // </file>
using ICSharpCode.NRefactory.AstBuilder;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Ast;
using Attribute = ICSharpCode.NRefactory.Ast.Attribute; using Attribute = ICSharpCode.NRefactory.Ast.Attribute;
@ -244,7 +244,7 @@ namespace ICSharpCode.NRefactory.Visitors
methodDeclaration.Body.AcceptVisitor(visitor, null); methodDeclaration.Body.AcceptVisitor(visitor, null);
if (visitor.replacementCount > 0) { if (visitor.replacementCount > 0) {
Expression init; Expression init;
init = GetDefaultValueForType(methodDeclaration.TypeReference); init = ExpressionBuilder.CreateDefaultValueForType(methodDeclaration.TypeReference);
methodDeclaration.Body.Children.Insert(0, new LocalVariableDeclaration(new VariableDeclaration(FunctionReturnValueName, init, methodDeclaration.TypeReference))); methodDeclaration.Body.Children.Insert(0, new LocalVariableDeclaration(new VariableDeclaration(FunctionReturnValueName, init, methodDeclaration.TypeReference)));
methodDeclaration.Body.Children[0].Parent = methodDeclaration.Body; methodDeclaration.Body.Children[0].Parent = methodDeclaration.Body;
methodDeclaration.Body.AddChild(new ReturnStatement(new IdentifierExpression(FunctionReturnValueName))); methodDeclaration.Body.AddChild(new ReturnStatement(new IdentifierExpression(FunctionReturnValueName)));
@ -497,41 +497,11 @@ namespace ICSharpCode.NRefactory.Visitors
VariableDeclaration decl = localVariableDeclaration.Variables[i]; VariableDeclaration decl = localVariableDeclaration.Variables[i];
if (decl.FixedArrayInitialization.IsNull && decl.Initializer.IsNull) { if (decl.FixedArrayInitialization.IsNull && decl.Initializer.IsNull) {
TypeReference type = localVariableDeclaration.GetTypeForVariable(i); TypeReference type = localVariableDeclaration.GetTypeForVariable(i);
decl.Initializer = GetDefaultValueForType(type); decl.Initializer = ExpressionBuilder.CreateDefaultValueForType(type);
} }
} }
} }
return base.VisitLocalVariableDeclaration(localVariableDeclaration, data); return base.VisitLocalVariableDeclaration(localVariableDeclaration, data);
} }
Expression GetDefaultValueForType(TypeReference type)
{
if (type != null && !type.IsArrayType) {
switch (type.SystemType) {
case "System.SByte":
case "System.Byte":
case "System.Int16":
case "System.UInt16":
case "System.Int32":
case "System.UInt32":
case "System.Int64":
case "System.UInt64":
case "System.Single":
case "System.Double":
return new PrimitiveExpression(0, "0");
case "System.Char":
return new PrimitiveExpression('\0', "'\\0'");
case "System.Object":
case "System.String":
return new PrimitiveExpression(null, "null");
case "System.Boolean":
return new PrimitiveExpression(false, "false");
default:
return new DefaultValueExpression(type);
}
} else {
return new PrimitiveExpression(null, "null");
}
}
} }
} }

6
src/Main/Base/Test/Utils/MockDefaultReturnType.cs

@ -148,5 +148,11 @@ namespace ICSharpCode.SharpDevelop.Tests.Utils
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Nullable<bool> IsReferenceType {
get {
throw new NotImplementedException();
}
}
} }
} }

2
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AbstractReturnType.cs

@ -129,5 +129,7 @@ namespace ICSharpCode.SharpDevelop.Dom
{ {
return null; return null;
} }
public virtual bool? IsReferenceType { get { return null; } }
} }
} }

8
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultReturnType.cs

@ -226,5 +226,13 @@ namespace ICSharpCode.SharpDevelop.Dom
return c.DotNetName; return c.DotNetName;
} }
} }
public override Nullable<bool> IsReferenceType {
get {
return (this.c.ClassType == ClassType.Class
|| this.c.ClassType == ClassType.Interface
|| this.c.ClassType == ClassType.Delegate);
}
}
} }
} }

4
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/GenericReturnType.cs

@ -117,6 +117,10 @@ namespace ICSharpCode.SharpDevelop.Dom
return list; return list;
} }
public override Nullable<bool> IsReferenceType {
get { return null; }
}
public override string ToString() public override string ToString()
{ {
return String.Format("[GenericReturnType: {0}]", typeParameter); return String.Format("[GenericReturnType: {0}]", typeParameter);

9
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/ProxyReturnType.cs

@ -217,5 +217,14 @@ namespace ICSharpCode.SharpDevelop.Dom
{ {
return CastToDecoratingReturnType<ConstructedReturnType>(); return CastToDecoratingReturnType<ConstructedReturnType>();
} }
public virtual bool? IsReferenceType {
get {
IReturnType baseType = BaseType;
bool? tmp = (baseType != null && TryEnter()) ? baseType.IsReferenceType : null;
Leave();
return tmp;
}
}
} }
} }

2
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/IReturnType.cs

@ -126,5 +126,7 @@ namespace ICSharpCode.SharpDevelop.Dom
bool IsConstructedReturnType { get; } bool IsConstructedReturnType { get; }
ConstructedReturnType CastToConstructedReturnType(); ConstructedReturnType CastToConstructedReturnType();
bool? IsReferenceType { get; }
} }
} }

9
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/CodeGenerator.cs

@ -717,5 +717,14 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring
document.EndUndoableAction(); document.EndUndoableAction();
} }
#endregion #endregion
public static NR.Expression CreateDefaultValueForType(IReturnType type)
{
if (type.IsReferenceType != null && type.IsReferenceType != false) {
return null;
}
return null;
}
} }
} }

Loading…
Cancel
Save