#develop (short for SharpDevelop) is a free IDE for .NET programming languages.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

135 lines
4.5 KiB

// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Dom.Refactoring;
using ICSharpCode.SharpDevelop.Refactoring;
namespace SharpRefactoring.ContextActions
{
/// <summary>
/// Caches common data for CheckAssignmentNull and CheckAssignmentNotNull.
/// </summary>
public class CheckAssignmentCache : IContextActionCache
{
public void Initialize(EditorContext context)
{
this.context = context;
this.VariableName = GetVariableName(context);
this.CodeGenerator = GetCodeGenerator(context);
this.Element = GetElement(context);
this.ElementRegion = (Element == null) ? DomRegion.Empty : DomRegion.FromLocation(Element.StartLocation, Element.EndLocation);
}
EditorContext context;
public bool IsActionAvailable
{
get {
return !string.IsNullOrEmpty(this.VariableName) && (this.CodeGenerator != null) && (this.context.CurrentLine.Text.Contains(";"));
}
}
public string VariableName { get; private set; }
public CodeGenerator CodeGenerator { get; private set; }
/// <summary>
/// Either AssignmentExpression or LocalVariableDeclaration.
/// </summary>
public AbstractNode Element { get; private set; }
public DomRegion ElementRegion { get; private set; }
protected string GetVariableName(EditorContext context)
{
// a = Foo() : AssignmentExpression.Left == IdentifierExpression(*identifier*)
// var a = Foo() : VariableDeclaration(*name*).Initializer != empty
var variableName = GetVariableNameFromAssignment(context.GetContainingElement<AssignmentExpression>());
if (variableName != null)
return variableName;
variableName = GetVariableNameFromVariableDeclaration(context.GetContainingElement<LocalVariableDeclaration>());
if (variableName != null)
return variableName;
return null;
}
protected AbstractNode GetElement(EditorContext context)
{
// a = Foo() : AssignmentExpression.Left == IdentifierExpression(*identifier*)
// var a = Foo() : VariableDeclaration(*name*).Initializer != empty
var assignment = context.GetContainingElement<AssignmentExpression>();
if (assignment != null)
return assignment;
var declaration = context.GetContainingElement<LocalVariableDeclaration>();
if (declaration != null)
return declaration;
return null;
}
string GetVariableNameFromAssignment(AssignmentExpression assignment)
{
if (assignment == null)
return null;
var identifier = assignment.Left as IdentifierExpression;
if (identifier == null)
return null;
if ((!ExpressionCanBeNull(assignment.Right)) || ExpressionIsValueType(assignment.Right))
// don't offer action where it makes no sense
return null;
return identifier.Identifier;
}
string GetVariableNameFromVariableDeclaration(LocalVariableDeclaration declaration)
{
if (declaration == null)
return null;
if (declaration.Variables.Count != 1)
return null;
VariableDeclaration varDecl = declaration.Variables[0];
if (!ExpressionCanBeNull(varDecl.Initializer) || ExpressionIsValueType(varDecl.Initializer))
// don't offer action where it makes no sense
return null;
return varDecl.Name;
}
bool ExpressionIsValueType(Expression expr)
{
ResolveResult rr = this.context.ResolveExpression(expr);
if (rr == null) return false; // when cannot resolve the assignment right, still offer the action
return (rr.ResolvedType != null && rr.ResolvedType.IsReferenceType == false);
}
bool ExpressionCanBeNull(Expression expr)
{
if (expr == null) return false;
if (expr.IsNull) return false;
if (expr is PrimitiveExpression) return false;
if (expr is IdentifierExpression) return true;
if (expr is MemberReferenceExpression) return true;
if (expr is InvocationExpression) return true;
if (expr is CastExpression && ((CastExpression)expr).CastType == CastType.TryCast) return true;
return false;
}
CodeGenerator GetCodeGenerator(EditorContext context)
{
var parseInfo = ParserService.GetParseInformation(context.Editor.FileName);
if (parseInfo == null)
return null;
return parseInfo.CompilationUnit.Language.CodeGenerator;
}
public IReturnType GetResolvedType(ResolveResult symbol)
{
if (symbol != null)
return symbol.ResolvedType;
return null;
}
}
}