Browse Source

Implement CSharpAstResolver.GetExpectedType() and CSharpAstResolver.GetConversion().

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
dac8c0fd35
  1. 14
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpAstResolver.cs
  2. 23
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs
  3. 74
      ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
  4. 4
      ICSharpCode.NRefactory/Role.cs

14
ICSharpCode.NRefactory.CSharp/Resolver/CSharpAstResolver.cs

@ -139,7 +139,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -139,7 +139,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
public IType GetExpectedType(Expression expr, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
if (expr == null || expr.IsNull)
throw new ArgumentNullException("expr");
InitResolver(expr);
lock (resolveVisitor) {
return resolveVisitor.GetConversionWithTargetType(expr).TargetType;
}
}
/// <summary>
@ -147,7 +152,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -147,7 +152,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
public Conversion GetConversion(Expression expr, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
if (expr == null || expr.IsNull)
throw new ArgumentNullException("expr");
InitResolver(expr);
lock (resolveVisitor) {
return resolveVisitor.GetConversionWithTargetType(expr).Conversion;
}
}
/// <summary>

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

@ -1420,12 +1420,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1420,12 +1420,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
foreach (var importedNamespace in u.Usings) {
ITypeDefinition def = importedNamespace.GetTypeDefinition(identifier, k);
if (def != null) {
if (firstResult == null) {
if (parameterizeResultType && k > 0)
firstResult = new ParameterizedType(def, typeArguments);
else
firstResult = def;
} else {
IType resultType;
if (parameterizeResultType && k > 0)
resultType = new ParameterizedType(def, typeArguments);
else
resultType = def;
if (firstResult == null || !TopLevelTypeDefinitionIsAccessible(firstResult.GetDefinition())) {
firstResult = resultType;
} else if (TopLevelTypeDefinitionIsAccessible(def)) {
return new AmbiguousTypeResolveResult(firstResult);
}
}
@ -1438,6 +1441,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1438,6 +1441,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return null;
}
bool TopLevelTypeDefinitionIsAccessible(ITypeDefinition typeDef)
{
if (typeDef.IsInternal) {
return typeDef.ParentAssembly.InternalsVisibleTo(compilation.MainAssembly);
}
return true;
}
/// <summary>
/// Looks up an alias (identifier in front of :: operator)
/// </summary>

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

@ -68,6 +68,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -68,6 +68,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
readonly CSharpParsedFile parsedFile;
readonly Dictionary<AstNode, ResolveResult> resolveResultCache = new Dictionary<AstNode, ResolveResult>();
readonly Dictionary<AstNode, CSharpResolver> resolverBeforeDict = new Dictionary<AstNode, CSharpResolver>();
readonly Dictionary<Expression, ConversionWithTargetType> conversionDict = new Dictionary<Expression, ConversionWithTargetType>();
internal struct ConversionWithTargetType
{
public readonly Conversion Conversion;
public readonly IType TargetType;
public ConversionWithTargetType(Conversion conversion, IType targetType)
{
this.Conversion = conversion;
this.TargetType = targetType;
}
}
IResolveVisitorNavigator navigator;
bool resolverEnabled;
@ -294,8 +307,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -294,8 +307,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
afc.ExplicitlyTypedLambda.ApplyReturnType(this, afc.ReturnType);
Log.Unindent();
}
if (conversion != Conversion.IdentityConversion)
if (conversion != Conversion.IdentityConversion) {
navigator.ProcessConversion(expr, rr, conversion, targetType);
conversionDict[expr] = new ConversionWithTargetType(conversion, targetType);
}
}
void ImportConversions(ResolveVisitor childVisitor)
{
foreach (var pair in childVisitor.conversionDict) {
conversionDict.Add(pair.Key, pair.Value);
navigator.ProcessConversion(pair.Key, resolveResultCache[pair.Key], pair.Value.Conversion, pair.Value.TargetType);
}
}
/// <summary>
@ -462,6 +485,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -462,6 +485,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
return null;
}
public ConversionWithTargetType GetConversionWithTargetType(Expression expr)
{
MergeUndecidedLambdas();
ResolveParentForConversion(expr);
ConversionWithTargetType result;
if (conversionDict.TryGetValue(expr, out result)) {
return result;
} else {
ResolveResult rr = GetResolveResultIfResolved(expr);
return new ConversionWithTargetType(Conversion.IdentityConversion, rr != null ? rr.Type : SpecialType.UnknownType);
}
}
#endregion
#region Track UsingScope
@ -2179,6 +2215,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2179,6 +2215,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
foreach (var pair in visitor.resolveResultCache) {
parentVisitor.StoreResult(pair.Key, pair.Value);
}
parentVisitor.ImportConversions(visitor);
parentVisitor.undecidedLambdas.Remove(lambda);
}
@ -2218,21 +2255,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2218,21 +2255,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Log.Indent();
while (undecidedLambdas.Count > 0) {
LambdaBase lambda = undecidedLambdas[0];
AstNode parent = lambda.LambdaExpression.Parent;
// Continue going upwards until we find a node that can be resolved and provides
// an expected type.
while (ActsAsParenthesizedExpression(parent) || parent is NamedArgumentExpression || parent is ArrayInitializerExpression) {
parent = parent.Parent;
}
CSharpResolver storedResolver;
if (parent != null && resolverBeforeDict.TryGetValue(parent, out storedResolver)) {
Log.WriteLine("Trying to resolve '" + parent + "' in order to merge the lambda...");
Log.Indent();
ResetContext(storedResolver, delegate { Resolve(parent); });
Log.Unindent();
} else {
Log.WriteLine("Could not find a suitable parent for '" + lambda);
}
ResolveParentForConversion(lambda.LambdaExpression);
if (lambda.IsUndecided) {
// Lambda wasn't merged by resolving its parent -> enforce merging
Log.WriteLine("Lambda wasn't merged by conversion - enforce merging");
@ -2243,6 +2266,25 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2243,6 +2266,25 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Log.WriteLine("MergeUndecidedLambdas() finished.");
}
void ResolveParentForConversion(AstNode expression)
{
AstNode parent = expression.Parent;
// Continue going upwards until we find a node that can be resolved and provides
// an expected type.
while (ActsAsParenthesizedExpression(parent) || parent is NamedArgumentExpression || parent is ArrayInitializerExpression) {
parent = parent.Parent;
}
CSharpResolver storedResolver;
if (parent != null && resolverBeforeDict.TryGetValue(parent, out storedResolver)) {
Log.WriteLine("Trying to resolve '" + parent + "' in order to find the conversion applied to '" + expression + "'...");
Log.Indent();
ResetContext(storedResolver, delegate { Resolve(parent); });
Log.Unindent();
} else {
Log.WriteLine("Could not find a suitable parent for '" + expression);
}
}
internal static bool ActsAsParenthesizedExpression(AstNode expression)
{
return expression is ParenthesizedExpression || expression is CheckedExpression || expression is UncheckedExpression;

4
ICSharpCode.NRefactory/Role.cs

@ -48,7 +48,7 @@ namespace ICSharpCode.NRefactory @@ -48,7 +48,7 @@ namespace ICSharpCode.NRefactory
/// </summary>
/// <remarks>
/// Roles used for non-collections should always have a null object, so that no AST property returns null.
/// However, roles used for collections only may leave out the null object.
/// However, if a role used for collections only, it may leave out the null object.
/// </remarks>
public T NullObject {
get { return nullObject; }
@ -66,7 +66,7 @@ namespace ICSharpCode.NRefactory @@ -66,7 +66,7 @@ namespace ICSharpCode.NRefactory
this.name = name;
}
public Role(string name, T nullObject = null)
public Role(string name, T nullObject)
{
if (name == null)
throw new ArgumentNullException("name");

Loading…
Cancel
Save