/// <summary> /// Get the return type of the constructor (never null). /// </summary> public static TypeRefBase GetReturnType(TypeRefBase thisRef, object reference) { // The 'return type' of a constructor is its declaring type, along with any type parameters TypeRefBase typeRefBase; if (reference is ConstructorDecl) { ConstructorDecl constructorDecl = (ConstructorDecl)reference; CodeObject parent = constructorDecl.Parent; if (parent == null) { // If we don't have a parent, assume we're a generated constructor for // a delegate (used for the obsolete explicit delegate creation syntax), and // use the type of the parameter as our type. // Clone the type so we can evaluate any type arguments it has later without consequences. typeRefBase = constructorDecl.Parameters[0].Type.SkipPrefixes() as TypeRefBase; typeRefBase = (typeRefBase != null ? (TypeRefBase)typeRefBase.Clone() : TypeRef.VoidRef); } else { typeRefBase = (TypeRef)parent.CreateRef(); } } else //if (reference is ConstructorInfo) { typeRefBase = TypeRef.Create(((ConstructorInfo)reference).DeclaringType); } return(typeRefBase); }
/// <summary> /// Determine the return type of the anonymous method (never null - will be 'void' instead). /// </summary> public TypeRefBase GetReturnType() { TypeRefBase returnTypeRef = null; ScanReturnTypes(ref returnTypeRef, _body); return(returnTypeRef ?? TypeRef.VoidRef); }
/// <summary> /// Determine if the specified types match the types of the method's parameters. /// </summary> public bool MatchParameters(TypeRefBase[] parameterTypes) { int parameterTypesCount = (parameterTypes != null ? parameterTypes.Length : 0); if ((_parameters != null ? _parameters.Count : 0) != parameterTypesCount) { return(false); } for (int i = 0; i < parameterTypesCount; ++i) { // Treat a null destination parameter type as a wildcard (match anything) TypeRefBase thatParameterTypeRef = parameterTypes[i]; if (thatParameterTypeRef != null) { TypeRefBase thisParameterTypeRef = _parameters[i].Type.SkipPrefixes() as TypeRefBase; // Allow any type parameters to match (necessary when looking for the base virtual method // of a method with a parameter with a TypeParameterRef type). if (thisParameterTypeRef is TypeParameterRef && thatParameterTypeRef is TypeParameterRef) { continue; } // Otherwise, require the references to be the same to match if (thisParameterTypeRef == null || !thisParameterTypeRef.IsSameRef(thatParameterTypeRef)) { return(false); } } } return(true); }
public static void AsTextPropertyInfo(CodeWriter writer, PropertyInfo propertyInfo, RenderFlags flags) { RenderFlags passFlags = flags & ~RenderFlags.Description; if (!flags.HasFlag(RenderFlags.NoPreAnnotations)) { Attribute.AsTextAttributes(writer, propertyInfo); } writer.Write(ModifiersHelpers.AsString(GetPropertyModifiers(propertyInfo))); Type propertyType = propertyInfo.PropertyType; TypeRefBase.AsTextType(writer, propertyType, passFlags); writer.Write(" "); TypeRefBase.AsTextType(writer, propertyInfo.DeclaringType, passFlags); Dot.AsTextDot(writer); if (PropertyInfoUtil.IsIndexed(propertyInfo)) { // Display the actual name instead of 'this' - it will usually be 'Item', but not always, // plus it might have a prefix (if it's an explicit interface implementation). writer.Write(propertyInfo.Name + IndexerDecl.ParseTokenStart); MethodRef.AsTextParameters(writer, propertyInfo.GetIndexParameters(), flags); writer.Write(IndexerDecl.ParseTokenEnd); } else { writer.Write(propertyInfo.Name); } }
public override void AsText(CodeWriter writer, RenderFlags flags) { if (flags.HasFlag(RenderFlags.Description)) { TypeRefBase.AsTextType(writer, GetType(), RenderFlags.None); } else { base.AsText(writer, flags); } }
/// <summary> /// Create an <see cref="UnresolvedRef"/>. /// </summary> public UnresolvedRef(TypeRefBase typeRefBase, bool copyTypeArguments) : this(typeRefBase.Name, typeRefBase.IsFirstOnLine) { Parent = typeRefBase.Parent; SetLineCol(typeRefBase); if (copyTypeArguments) { _typeArguments = typeRefBase.TypeArguments; } _arrayRanks = typeRefBase.ArrayRanks; }
/// <summary> /// Parse a <see cref="GenericMethodDecl"/> using alternate type argument delimiters. /// </summary> public static GenericMethodDecl ParseAlt(Parser parser, CodeObject parent, ParseFlags flags) { // Verify that this alternate form is inside a doc comment (subroutines will look for the appropriate // delimiters according to the parser state) in addition to passing other verifications as above. // If it doesn't seem to match the proper pattern, abort so that other types can try parsing it. if (parser.InDocComment && ((parent is TypeDecl && parser.HasUnusedIdentifier) || parser.HasUnusedTypeRefAndIdentifier) && TypeRefBase.PeekTypeArguments(parser, TypeRefBase.ParseTokenAltArgumentEnd, flags) && parser.LastPeekedTokenText == ParseTokenStart) { return(new GenericMethodDecl(parser, parent, false, flags)); } return(null); }
/// <summary> /// Determine the type of the parameter for the specified argument index. /// </summary> public override TypeRefBase GetParameterType(int argumentIndex) { if (_expression != null) { TypeRefBase invokedRef = _expression.SkipPrefixes() as TypeRefBase; if (invokedRef != null) { return(invokedRef.GetDelegateParameterType(argumentIndex)); } } return(null); }
/// <summary> /// Find the parameter on the specified <see cref="TypeRefBase"/> with the specified name. /// </summary> /// <returns>A <see cref="ParameterRef"/> to the parameter, or an <see cref="UnresolvedRef"/> if no match was found.</returns> public static SymbolicRef Find(TypeRefBase typeRefBase, string name, bool isFirstOnLine) { if (typeRefBase is MethodRef) { ParameterRef parameterRef = ((MethodRef)typeRefBase).GetParameter(name); if (parameterRef != null) { parameterRef.IsFirstOnLine = isFirstOnLine; return(parameterRef); } } return(new UnresolvedRef(name, isFirstOnLine)); }
/// <summary> /// Find a field on the specified <see cref="TypeRefBase"/> with the specified name. /// </summary> /// <returns>A <see cref="FieldRef"/> to the field, or an <see cref="UnresolvedRef"/> if no match was found.</returns> public static SymbolicRef Find(TypeRefBase typeRefBase, string name, bool isFirstOnLine) { if (typeRefBase is TypeRef) { FieldRef fieldRef = ((TypeRef)typeRefBase).GetField(name); if (fieldRef != null) { fieldRef.IsFirstOnLine = isFirstOnLine; return(fieldRef); } } return(new UnresolvedRef(name, isFirstOnLine)); }
/// <summary> /// Find a property on the specified <see cref="TypeRefBase"/> with the specified name. /// </summary> /// <returns>A <see cref="PropertyRef"/> to the property, or an <see cref="UnresolvedRef"/> if no match was found.</returns> public static SymbolicRef Find(TypeRefBase typeRefBase, string name, bool isFirstOnLine) { if (typeRefBase is TypeRef) { PropertyRef propertyRef = ((TypeRef)typeRefBase).GetProperty(name); if (propertyRef != null) { propertyRef.IsFirstOnLine = isFirstOnLine; return(propertyRef); } } return(new UnresolvedRef(name, isFirstOnLine)); }
/// <summary> /// Determine the type of the parameter for the specified argument index. /// </summary> public override TypeRefBase GetParameterType(int argumentIndex) { if (_indexerRef is IndexerRef) { TypeRefBase parameterTypeRef = MethodRef.GetParameterType(_indexerRef.Reference, argumentIndex, _expression); if (parameterTypeRef != null) { return(parameterTypeRef); } } // By default, assume we're indexing an array type return(TypeRef.IntRef); }
/// <summary> /// Find the constructor of the specified <see cref="TypeRefBase"/> with the specified signature. /// </summary> /// <returns>A <see cref="ConstructorRef"/> to the constructor, or an <see cref="UnresolvedRef"/> if no match was found.</returns> public static TypeRefBase Find(TypeRefBase typeRefBase, bool isFirstOnLine, params TypeRefBase[] parameterTypes) { if (typeRefBase is TypeRef) { ConstructorRef constructorRef = ((TypeRef)typeRefBase).GetConstructor(parameterTypes); if (constructorRef != null) { constructorRef.IsFirstOnLine = isFirstOnLine; return(constructorRef); } return(new UnresolvedRef(typeRefBase.Name, isFirstOnLine)); } return(null); }
/// <summary> /// Parse a <see cref="GenericMethodDecl"/>. /// </summary> public static new GenericMethodDecl Parse(Parser parser, CodeObject parent, ParseFlags flags) { // If our parent is a TypeDecl, verify that we have an unused identifier (a Dot operator is possible // for explicit interface implementations, but is handled by MethodDecl, which then calls the constructor // below). Otherwise, require a possible return type in addition to the identifier. Also verify that // we seem to match a type argument list pattern followed by a '('. // If it doesn't seem to match the proper pattern, abort so that other types can try parsing it. if (((parent is TypeDecl && parser.HasUnusedIdentifier) || parser.HasUnusedTypeRefAndIdentifier) && TypeRefBase.PeekTypeArguments(parser, TypeRefBase.ParseTokenArgumentEnd, flags) && parser.LastPeekedTokenText == ParseTokenStart) { return(new GenericMethodDecl(parser, parent, false, flags)); } return(null); }
public static void AsTextEventInfo(CodeWriter writer, EventInfo eventInfo, RenderFlags flags) { RenderFlags passFlags = flags & ~RenderFlags.Description; if (!flags.HasFlag(RenderFlags.NoPreAnnotations)) { Attribute.AsTextAttributes(writer, eventInfo); } writer.Write(ModifiersHelpers.AsString(GetEventModifiers(eventInfo))); TypeRefBase.AsTextType(writer, eventInfo.EventHandlerType, passFlags); writer.Write(" "); TypeRefBase.AsTextType(writer, eventInfo.DeclaringType, passFlags); writer.Write(Dot.ParseToken + eventInfo.Name); }
/// <summary> /// Get the declaring type of the specified enum member object. /// </summary> /// <param name="enumMemberObj">The enum member object (a <see cref="EnumMemberDecl"/> or <see cref="FieldInfo"/>).</param> /// <returns>The <see cref="TypeRef"/> of the declaring type, or null if it can't be determined.</returns> public static TypeRefBase GetDeclaringType(object enumMemberObj) { TypeRefBase declaringTypeRef = null; if (enumMemberObj is EnumMemberDecl) { TypeDecl declaringTypeDecl = ((EnumMemberDecl)enumMemberObj).ParentEnumDecl; declaringTypeRef = (declaringTypeDecl != null ? declaringTypeDecl.CreateRef() : null); } else if (enumMemberObj is FieldInfo) { declaringTypeRef = TypeRef.Create(((FieldInfo)enumMemberObj).DeclaringType); } return(declaringTypeRef); }
/// <summary> /// Get the declaring type of the referenced property. /// </summary> public override TypeRefBase GetDeclaringType() { TypeRefBase declaringTypeRef = GetDeclaringType(_reference); // A property reference doesn't store any type arguments for a parent type instance, so any // type arguments in any generic declaring type or its parent types will always default to // the declared type arguments. Convert them from OpenTypeParameterRefs to TypeParameterRefs // so that they don't show up as Red in the GUI. if (declaringTypeRef != null && declaringTypeRef.HasTypeArguments) { declaringTypeRef.ConvertOpenTypeParameters(); } return(declaringTypeRef); }
/// <summary> /// Find the enum value with the specified name in the specified <see cref="TypeRefBase"/>. /// </summary> /// <returns>An <see cref="EnumMemberRef"/> to the enum value, or an <see cref="UnresolvedRef"/> if no match was found.</returns> public static SymbolicRef Find(TypeRefBase typeRefBase, string name, bool isFirstOnLine) { if (typeRefBase is TypeRef && ((TypeRef)typeRefBase).IsEnum) { if (typeRefBase.Reference is Type) { return(Find(typeRefBase.Reference as Type, name, isFirstOnLine)); } if (typeRefBase.Reference is EnumDecl) { return(Find(typeRefBase.Reference as EnumDecl, name, isFirstOnLine)); } } return(new UnresolvedRef(name, isFirstOnLine)); }
protected override void AsTextInitializer(CodeWriter writer, RenderFlags flags) { // Render any omitted brackets here (after parameters and before any initializer), // skipping the first set, because they will be rendered as the arguments. if (_expression != null) { TypeRefBase typeRefBase = _expression.SkipPrefixes() as TypeRefBase; if (typeRefBase != null) { typeRefBase.AsTextArrayRanks(writer, flags); } } base.AsTextInitializer(writer, flags); }
/// <summary> /// Get the declaring type of the specified property object. /// </summary> /// <param name="propertyObj">The property object (a <see cref="PropertyDeclBase"/> or <see cref="PropertyInfo"/>).</param> /// <returns>The <see cref="TypeRef"/> of the declaring type, or null if it can't be determined.</returns> public static TypeRefBase GetDeclaringType(object propertyObj) { TypeRefBase declaringTypeRef = null; if (propertyObj is PropertyDeclBase) { TypeDecl declaringTypeDecl = ((PropertyDeclBase)propertyObj).DeclaringType; declaringTypeRef = (declaringTypeDecl != null ? declaringTypeDecl.CreateRef() : null); } else if (propertyObj is PropertyInfo) { declaringTypeRef = TypeRef.Create(((PropertyInfo)propertyObj).DeclaringType); } return(declaringTypeRef); }
/// <summary> /// Parse a <see cref="Cast"/> operator. /// </summary> public static Cast Parse(Parser parser, CodeObject parent, ParseFlags flags) { // Verify that we have a pattern of "(Type)", otherwise abort (so the expression parens logic can try parsing it). // Do NOT set the ParseFlags.Type flag here, because it might not be a type (it might be "(A * B)"). // Also, verify that we're not inside a directive expression - casts aren't legal there. if (TypeRefBase.PeekType(parser, parser.PeekNextToken(), false, flags) && !parser.InDirectiveExpression) { Token last = parser.LastPeekedToken; if (last != null && last.Text == ParseTokenEnd) { // Verify that the cast is either followed by a non-symbol, or various legal symbols (those that // can only be unary operators). Token next = parser.PeekNextToken(); if (next != null) { if (!next.IsSymbol || next.Text == ParseTokenStartGroup || next.Text == Complement.ParseToken || next.Text == Increment.ParseToken || next.Text == Decrement.ParseToken || next.Text == Not.ParseToken) { return(new Cast(parser, parent)); } // In the case of the Negative and Positive unary operators following the Cast, // it's impossible to be sure they aren't actually binary operators, such as "(v1)-v2" or // "(v1)-(v2)" (yes, programmers actually write code like that for some reason!). // For now, assume if the operator is followed by a space and/or a '(', it's a binary // operator (so we don't have a Cast). This will cover most cases, but not 100%. // Any parse issues could be easily worked around by adding parens around the entire right // expression being cast, such as "(v1)(-(v2))" to force a cast, or around either both sides // or neither side of a binary operator to avoid a cast. if (next.Text == Positive.ParseToken || next.Text == Negative.ParseToken) { next = parser.PeekNextToken(); if (next.Text != ParseTokenStartGroup && next.LeadingWhitespace.Length == 0) { return(new Cast(parser, parent)); } } } // Otherwise, fail and treat it as a grouped expression instead. } } return(null); }
public override void AsTextExpression(CodeWriter writer, RenderFlags flags) { // Display constructors as their declaring type name, including any type arguments (this // is the easy way to display them with the proper type arguments and any enclosing types, // if appropriate). UpdateLineCol(writer, flags); TypeRefBase typeRef = GetDeclaringType(); if (typeRef != null) { typeRef.AsText(writer, flags & ~RenderFlags.UpdateLineCol); } else if (_reference is ConstructorDecl) { // If we failed to get the declaring type, and we have an "orphaned" ConstructorDecl, // go ahead and display it's name. writer.WriteName(((ConstructorDecl)_reference).Name, flags); } }
protected void ScanReturnTypes(ref TypeRefBase returnTypeRef, Block body) { // Recursively scan all bodies for Return statements if (body != null) { foreach (CodeObject codeObject in body) { if (codeObject is Return) { Expression expression = ((Return)codeObject).Expression; TypeRefBase typeRef = (expression == null ? TypeRef.VoidRef : expression.SkipPrefixes() as TypeRefBase); returnTypeRef = (returnTypeRef == null ? typeRef : TypeRef.GetCommonType(returnTypeRef, typeRef)); } else if (codeObject is BlockStatement) { ScanReturnTypes(ref returnTypeRef, ((BlockStatement)codeObject).Body); } } } }
/// <summary> /// Peek ahead at the input tokens to determine if they look like a valid LocalDecl. /// </summary> public static bool PeekLocalDecl(Parser parser) { bool valid = false; // Validate that we have what appears to be a valid Type followed by an identifier if (TypeRefBase.PeekType(parser, parser.Token, false, ParseFlags.Type)) { Token next = parser.LastPeekedToken; if (next != null && next.IsIdentifier) { // Also validate that it's followed by one of ";=)," if (";=),".Contains(parser.PeekNextTokenText())) { valid = true; } } } return(valid); }
public static void AsTextFieldInfo(CodeWriter writer, FieldInfo fieldInfo, RenderFlags flags) { RenderFlags passFlags = flags & ~RenderFlags.Description; // Skip all details for enum members, including the declaring type since it will always be on the left of the dot if (!(fieldInfo.IsLiteral && fieldInfo.FieldType.IsEnum)) { if (!flags.HasFlag(RenderFlags.NoPreAnnotations)) { Attribute.AsTextAttributes(writer, fieldInfo); } writer.Write(ModifiersHelpers.AsString(GetFieldModifiers(fieldInfo))); Type fieldType = fieldInfo.FieldType; TypeRefBase.AsTextType(writer, fieldType, passFlags); writer.Write(" "); TypeRefBase.AsTextType(writer, fieldInfo.DeclaringType, passFlags); Dot.AsTextDot(writer); } writer.Write(fieldInfo.Name); }
/// <summary> /// Parse a list of type parameters. /// </summary> public static ChildList <TypeParameter> ParseList(Parser parser, CodeObject parent) { ChildList <TypeParameter> parameters = null; if (parser.TokenText == ParseTokenStart || (parser.InDocComment && parser.TokenText == ParseTokenAltStart && TypeRefBase.PeekTypeArguments(parser, TypeRefBase.ParseTokenAltArgumentEnd, ParseFlags.None))) { string argumentEnd = (parser.TokenText == ParseTokenAltStart ? ParseTokenAltEnd : ParseTokenEnd); parent.MoveAllComments(parser.LastToken); // Move any skipped comments to the parent parser.NextToken(); // Move past '<' // Create a string of possible terminators (assuming 1 char terminators for now) string terminators = argumentEnd + MethodDeclBase.ParseTokenStart + ConstraintClause.ParseTokenSeparator + Statement.ParseTokenTerminator; while (parser.Token != null && (parser.TokenText.Length != 1 || terminators.IndexOf(parser.TokenText[0]) < 0)) { TypeParameter typeParameter = new TypeParameter(parser, parent); if (typeParameter.Name != null) { if (parameters == null) { parameters = new ChildList <TypeParameter>(parent); } parameters.Add(typeParameter); if (parser.TokenText == ParseTokenSeparator) { parser.NextToken(); // Move past ',' } } else { parser.NextToken(); // Move past bad token (non-identifier) } } parser.NextToken(); // Move past '>' } return(parameters); }
/// <summary> /// Parse a <see cref="NewObject"/> or <see cref="NewArray"/> operator. /// </summary> public static NewOperator Parse(Parser parser, CodeObject parent, ParseFlags flags) { // Abort if our parent is a TypeDecl (the 'new' is probably part of a method declaration) if (parent is TypeDecl) { return(null); } NewOperator result = null; // Peek ahead to see if we have a valid non-array type TypeRefBase.PeekType(parser, parser.PeekNextToken(), true, flags | ParseFlags.Type); Token token = parser.LastPeekedToken; if (token != null) { // If we found a '[', assume NewArray if (token.Text == NewArray.ParseTokenStart) { result = new NewArray(parser, parent); } // If we found '(' or '{', assume NewObject else if (token.Text == ParameterDecl.ParseTokenStart || token.Text == Initializer.ParseTokenStart) { result = new NewObject(parser, parent); } } // Last chance - invalid code might still parse better as a NewObject, so assume that's // what it is if our parent is a VariableDecl. if (result == null && parent is VariableDecl) { result = new NewObject(parser, parent); } // If we didn't create an object, return null (the 'new' is probably part of a method declaration) return(result); }
public static void AsTextParameterInfo(CodeWriter writer, ParameterInfo parameterInfo, RenderFlags flags) { RenderFlags passFlags = flags & ~RenderFlags.Description; Attribute.AsTextAttributes(writer, parameterInfo); ParameterModifier modifier = GetParameterModifier(parameterInfo); if (modifier != ParameterModifier.None) { writer.Write(ParameterDecl.ParameterModifierToString(modifier) + " "); } Type parameterType = parameterInfo.ParameterType; if (parameterType.IsByRef) { // Dereference (remove the trailing '&') if it's a reference type parameterType = parameterType.GetElementType(); } TypeRefBase.AsTextType(writer, parameterType, passFlags); writer.Write(" " + parameterInfo.Name); }
protected static void AsTextDescription(CodeWriter writer, MemberInfo memberInfo) { const RenderFlags flags = RenderFlags.ShowParentTypes | RenderFlags.NoPreAnnotations; switch (memberInfo.MemberType) { case MemberTypes.TypeInfo: case MemberTypes.NestedType: TypeRefBase.AsTextType(writer, (Type)memberInfo, flags | RenderFlags.Description); break; case MemberTypes.Constructor: ConstructorRef.AsTextConstructorInfo(writer, (ConstructorInfo)memberInfo, flags); break; case MemberTypes.Method: MethodRef.AsTextMethodInfo(writer, (MethodInfo)memberInfo, flags); break; case MemberTypes.Property: PropertyRef.AsTextPropertyInfo(writer, (PropertyInfo)memberInfo, flags); break; case MemberTypes.Field: FieldRef.AsTextFieldInfo(writer, (FieldInfo)memberInfo, flags); break; case MemberTypes.Event: EventRef.AsTextEventInfo(writer, (EventInfo)memberInfo, flags); break; default: writer.Write(memberInfo.ToString()); break; } }
/// <summary> /// Find a property on the specified <see cref="TypeRefBase"/> with the specified name. /// </summary> /// <returns>A <see cref="PropertyRef"/> to the property, or an <see cref="UnresolvedRef"/> if no match was found.</returns> public static SymbolicRef Find(TypeRefBase typeRefBase, string name) { return(Find(typeRefBase, name, false)); }