public override FullNamedExpression ResolveAsTypeStep(ParseContext ec, bool silent) { var errors = ec.CompilerErrorCount; var fne = ec.LookupNamespaceOrType( Name, Span, ignoreAmbiguousReferences: false, genericArity: HasTypeArguments ? TypeArguments.Count : 0); if (fne != null) { if (fne.Type == null) { return(fne); } var nested = ResolveNested(fne.Type); if (nested != null) { return(nested.ResolveAsTypeStep(ec, false)); } if (HasTypeArguments) { if (TypeManager.IsGenericType(fne.Type)) { var ct = new GenericTypeExpression(fne.Type, TypeArguments, Span); return(ct.ResolveAsTypeStep(ec, false)); } fne.OnErrorTypeArgumentsCannotBeUsed(ec, Span); } return(fne); } if (silent || errors != ec.CompilerErrorCount) { return(null); } OnErrorTypeOrNamespaceNotFound(ec); return(null); }
public FullNamedExpression ResolveNamespaceOrType(ParseContext rc, bool silent) { var resolved = Left.ResolveAsTypeStep(rc, silent); if (resolved == null) { return(null); } var languageContext = (ScriptLanguageContext)rc.Compiler.SourceUnit.LanguageContext; var hasTypeArguments = HasTypeArguments; var typeArguments = TypeArguments; var lookupIdentifier = ReflectionUtils.GetNormalizedTypeName(MemberName.MakeName(Name, typeArguments)); var ns = resolved as NamespaceExpression; if (ns != null) { MemberTracker tracker; bool found; var trackerGroup = ns.Tracker as NamespaceGroupTracker; if (trackerGroup != null) { found = trackerGroup.TryGetValue((SymbolId)lookupIdentifier, out tracker); } else { found = ns.Tracker.TryGetValue((SymbolId)lookupIdentifier, out tracker); } if (found) { var typeGroup = tracker as TypeGroup; if (typeGroup != null) { if (hasTypeArguments) { typeArguments.Resolve(rc); var genericType = typeGroup.GetTypeForArity(typeArguments.Count); if (genericType != null) { return(new TypeExpression( genericType.Type.MakeGenericType(typeArguments.ResolvedTypes))); } // ERROR! } Type nonGenericType; if (typeGroup.TryGetNonGenericType(out nonGenericType)) { return(new TypeExpression(nonGenericType)); } // ERROR! } var singleTypeTracker = tracker as TypeTracker; if (singleTypeTracker != null) { if (hasTypeArguments) { typeArguments.Resolve(rc); return(new TypeExpression( singleTypeTracker.Type.MakeGenericType(typeArguments.ResolvedTypes))); } return(new TypeExpression(singleTypeTracker.Type)); } var childNamespaceTracker = tracker as NamespaceTracker; if (childNamespaceTracker != null) { return(new NamespaceExpression(childNamespaceTracker, Span)); } // ERROR! } //FullNamedExpression retval = ns.Lookup(rc.Compiler, lookupIdentifier, loc); //if (retval == null && !silent) // ns.Error_NamespaceDoesNotExist(loc, lookupIdentifier, rc.Compiler.Report); //else if (targs != null) // retval = new GenericTypeExpr(retval.Type, targs, loc).ResolveAsTypeStep(rc, silent); return(null); } var resolvedAsType = resolved.ResolveAsTypeTerminal(rc, false); if (resolvedAsType == null) { return(null); } var expressionType = resolvedAsType.Type; if (expressionType.IsGenericParameter) { rc.Compiler.Errors.Add( rc.Compiler.SourceUnit, string.Format( "A nested type cannot be specified through a type parameter '{0}'.", expressionType.Name), resolvedAsType.Span, 704, Severity.Error); return(null); } var memberGroup = languageContext.DefaultBinderState.Binder.GetMember( MemberRequestKind.Get, expressionType, Name); if (memberGroup != null) { foreach (var nestedType in memberGroup.OfType <TypeTracker>()) { if (nestedType.IsGenericType != hasTypeArguments) { continue; } if (!hasTypeArguments) { if (nestedType.Type.GetGenericArguments().Length == typeArguments.Count) { return(new TypeExpression(nestedType.Type)); } // ERROR! } var typeGroup = nestedType as TypeGroup; if (typeGroup != null) { var matchingType = typeGroup.GetTypeForArity(typeArguments.Count); if (matchingType != null) { return(new TypeExpression(matchingType.Type)); } // ERROR! } } } //return null; var memberLookup = MemberLookup( rc, null, expressionType, expressionType, lookupIdentifier, MemberTypes.NestedType, BindingFlags.Public | BindingFlags.NonPublic, Span); if (memberLookup == null) { if (silent) { return(null); } System.Diagnostics.Debugger.Break(); //Error_IdentifierNotFound(rc, resolved, lookupIdentifier); return(null); } var typeExpression = memberLookup.ResolveAsTypeTerminal(rc, false); if (typeExpression == null) { return(null); } var theArgs = typeArguments; var declaringType = typeExpression.Type.DeclaringType; if (TypeManager.HasGenericArguments(declaringType) && !TypeManager.IsGenericTypeDefinition(expressionType)) { while (!TypeManager.IsEqual(TypeManager.DropGenericTypeArguments(expressionType), declaringType)) { expressionType = expressionType.BaseType; } var newArgs = new TypeArguments(); foreach (var decl in expressionType.GetGenericArguments()) { newArgs.Add(new TypeExpression(decl) { Span = Span }); } if (typeArguments != null) { newArgs.Add(typeArguments); } theArgs = newArgs; } if (theArgs != null) { var genericType = new GenericTypeExpression(typeExpression.Type, theArgs, Span); return(genericType.ResolveAsTypeStep(rc, false)); } return(typeExpression); }
private Expression DoResolve(ParseContext ec, Expression rightSide) { if (_resolved != null) { return(_resolved); } var type = Type; if (type != null) { throw new Exception(); } // // Resolve the expression with flow analysis turned off, we'll do the definite // assignment checks later. This is because we don't know yet what the expression // will resolve to - it may resolve to a FieldExpr and in this case we must do the // definite assignment check on the actual field and not on the whole struct. // var original = Left as NameExpression; var leftResolved = Left.Resolve(ec, ResolveFlags.VariableOrValue | ResolveFlags.Type | ResolveFlags.Intermediate | ResolveFlags.DisableStructFlowAnalysis); if (leftResolved == null) { return(null); } var typeArguments = TypeArguments; var lookupIdentifier = MemberName.MakeName(Name, typeArguments); var ns = leftResolved as NamespaceExpression; if (ns != null) { FullNamedExpression resolved = null; MemberTracker namespaceChild; bool found; var trackerGroup = ns.Tracker as NamespaceGroupTracker; if (trackerGroup != null) { found = trackerGroup.TryGetValue((SymbolId)lookupIdentifier, out namespaceChild); } else { found = ns.Tracker.TryGetValue((SymbolId)lookupIdentifier, out namespaceChild); } if (!found) { // TODO: ns.Error_NamespaceDoesNotExist(loc, lookupIdentifier, ec.Report); } else if (HasTypeArguments) { if (!typeArguments.Resolve(ec)) { return(null); } var typeTracker = namespaceChild as TypeGroup; if (typeTracker != null) { var matchingType = typeTracker.GetTypeForArity(typeArguments.Count); if (matchingType != null) { resolved = new GenericTypeExpression( matchingType.Type, typeArguments, Span).ResolveAsTypeStep(ec, false); } else { // TODO: Error? } } } else { var typeGroup = namespaceChild as TypeGroup; if (typeGroup != null) { Type nonGenericType; if (typeGroup.TryGetNonGenericType(out nonGenericType)) { resolved = new TypeExpression(nonGenericType) { Span = Span }; } else { // TODO: Error? } } else { var nestedType = namespaceChild as NestedTypeTracker; if (nestedType != null) { resolved = new TypeExpression(nestedType.Type) { Span = Span }; } else { // TODO: Error? } } } //FullNamedExpression retval = ns.Lookup(ec, lookupIdentifier, loc); if (resolved == null) { } else if (HasTypeArguments) { resolved = new GenericTypeExpression( resolved.Type, typeArguments, Span).ResolveAsTypeStep(ec, false); } _resolved = resolved; if (resolved != null) { ExpressionClass = resolved.ExpressionClass; } return(resolved); } var expressionType = leftResolved.Type; if (expressionType.IsPointer || expressionType == TypeManager.CoreTypes.Void) { // TODO: Unary.Error_OperatorCannotBeApplied(ec, loc, ".", expressionType); return(null); } var c = leftResolved as ConstantExpression; if (c != null && c.Value == null) { ec.ReportError( 1720, "Expression will always cause a 'System.NullReferenceException'.", Severity.Warning, Span); } if (typeArguments != null && !typeArguments.Resolve(ec)) { return(null); } var memberLookup = MemberLookup( ec, null, expressionType, expressionType, Name, Span); if (memberLookup == null && typeArguments != null) { memberLookup = MemberLookup( ec, null, expressionType, expressionType, lookupIdentifier, Span); } if (memberLookup == null) { var expressionClass = leftResolved.ExpressionClass; // // Extension methods are not allowed on all expression types // if (expressionClass == ExpressionClass.Value || expressionClass == ExpressionClass.Variable || expressionClass == ExpressionClass.IndexerAccess || expressionClass == ExpressionClass.PropertyAccess || expressionClass == ExpressionClass.EventAccess) { var exMethodLookup = ec.LookupExtensionMethod(expressionType, Name, Span); if (exMethodLookup != null) { exMethodLookup.ExtensionExpression = leftResolved; if ((typeArguments != null) && typeArguments.Any()) { exMethodLookup.SetTypeArguments(ec, typeArguments); } _resolved = exMethodLookup.DoResolve(ec); if (_resolved != null) { ExpressionClass = _resolved.ExpressionClass; } return(_resolved); } } Left = leftResolved; memberLookup = OnErrorMemberLookupFailed( ec, null, expressionType, expressionType, Name, null, AllMemberTypes, AllBindingFlags); if (memberLookup == null) { return(null); } } var texpr = memberLookup as TypeExpression; if (texpr != null) { if (!(leftResolved is TypeExpression) && (original == null || !original.IdenticalNameAndTypeName(ec, leftResolved, Span))) { ec.ReportError( 572, string.Format( "'{0}': cannot reference a type through an expression; try '{1}' instead.", Name, memberLookup.GetSignatureForError()), Severity.Error, Span); return(null); } if (!texpr.CheckAccessLevel(ec)) { ec.ReportError( CompilerErrors.MemberIsInaccessible, Span, TypeManager.GetCSharpName(memberLookup.Type)); return(null); } var ct = leftResolved as GenericTypeExpression; if (ct != null) { // // When looking up a nested type in a generic instance // via reflection, we always get a generic type definition // and not a generic instance - so we have to do this here. // // See gtest-172-lib.cs and gtest-172.cs for an example. // TypeArguments nestedTargs; if (HasTypeArguments) { nestedTargs = ct.TypeArguments.Clone(); nestedTargs.Add(typeArguments); } else { nestedTargs = ct.TypeArguments; } ct = new GenericTypeExpression(memberLookup.Type, nestedTargs, Span); _resolved = ct.ResolveAsTypeStep(ec, false); if (_resolved != null) { ExpressionClass = _resolved.ExpressionClass; } return(_resolved); } _resolved = memberLookup; ExpressionClass = _resolved.ExpressionClass; return(memberLookup); } var me = (MemberExpression)memberLookup; me = me.ResolveMemberAccess(ec, leftResolved, Span, original); if (me == null) { return(null); } if ((typeArguments != null) && typeArguments.Any()) { me.SetTypeArguments(ec, typeArguments); } if (original != null && !TypeManager.IsValueType(expressionType)) { if (me.IsInstance) { } } // The following DoResolve/DoResolveLValue will do the definite assignment // check. Left = leftResolved; if (rightSide != null) { return(_resolved = me.DoResolveLValue(ec, rightSide)); } return(_resolved = me.DoResolve(ec)); }
protected bool CheckConstraint( ParseContext ec, Type ptype, Expression expr, Type ctype) { // // All this is needed because we don't have // real inflated type hierarchy // if (TypeManager.HasGenericArguments(ctype)) { var types = ctype.GetGenericArguments(); var newArgs = new TypeArguments(); for (var i = 0; i < types.Length; i++) { var t = types[i]; if (t.IsGenericParameter) { var pos = t.GenericParameterPosition; if (t.DeclaringMethod == null && this is MethodConstraintChecker) { var parent = ((MethodConstraintChecker)this).DeclaringType; t = parent.GetGenericArguments()[pos]; } else { t = ArgumentTypes[pos]; } } newArgs.Add(new TypeExpression(t) { Span = Span }); } var ct = new GenericTypeExpression(ctype, newArgs, Span); if (ct.ResolveAsTypeStep(ec, false) == null) { return(false); } ctype = (ct).Type; } else if (ctype.IsGenericParameter) { var pos = ctype.GenericParameterPosition; if (ctype.DeclaringMethod == null) { // FIXME: Implement return(true); } ctype = ArgumentTypes[pos]; } var expressionType = expr.Type; if (TypeUtils.IsImplicitlyConvertible(expressionType, ctype)) { return(true); } if (Silent) { return(false); } if (TypeUtils.IsNullableType(expressionType) && ctype.IsInterface) { ec.ReportError( 313, string.Format( "The type '{0}' cannot be used as type parameter '{1}' in the generic type or method '{2}'. " + "The nullable type '{0}' never satisfies interface constraint of type '{3}'.", TypeManager.GetCSharpName(expressionType), TypeManager.GetCSharpName(ptype), GetSignatureForError(), TypeManager.GetCSharpName(ctype)), Severity.Error, Span); } else { ec.ReportError( 309, string.Format( "The type '{0}' must be convertible to '{1}' in order to " + "use it as parameter '{2}' in the generic type or method '{3}'.", TypeManager.GetInterfaces(expressionType), TypeManager.GetInterfaces(ctype), TypeManager.GetInterfaces(ptype), GetSignatureForError()), Severity.Error, Span); } return(false); }