private void WriteAccess(CodeAccess codeAccess) { string accessString = string.Empty; if (codeAccess != CodeAccess.None) { accessString = EnumUtilities.ToString(codeAccess).ToLowerInvariant().Replace(",", string.Empty) + " "; } WriteIndented(accessString); }
/// <summary> /// Writes the member or type access. /// </summary> /// <param name="codeAccess">The code access.</param> private void WriteAccess(CodeAccess codeAccess) { string accessString = string.Empty; if (codeAccess != CodeAccess.None) { accessString = EnumUtilities.ToString(codeAccess).Replace(",", string.Empty) + " "; accessString = accessString.Replace( EnumUtilities.ToString(CodeAccess.Internal), VBKeyword.Friend); } WriteIndented(accessString); }
/// <summary> /// Creates a new AttributedElement. /// </summary> protected AttributedElement() { _access = CodeAccess.Public; }
/// <summary> /// Parses a property. /// </summary> /// <param name="memberName">Name of the member.</param> /// <param name="returnType">Type of the return.</param> /// <param name="access">The access.</param> /// <param name="memberAttributes">The member attributes.</param> /// <param name="isExpressionBodyProperty">Set to true if the property uses the new C# 6 API where it does not even need braces, but instead can directly use an expression body (= implicit get only property).</param> /// <returns>A property code element.</returns> private PropertyElement ParseProperty(string memberName, string returnType, CodeAccess access, MemberModifiers memberAttributes, bool isExpressionBodyProperty) { PropertyElement property = new PropertyElement(); int indexStart = memberName.IndexOf(CSharpSymbol.BeginAttribute); if (indexStart >= 0) { string indexParameter = memberName.Substring(indexStart).Trim().Trim( CSharpSymbol.BeginAttribute, CSharpSymbol.EndAttribute).Trim(); property.IndexParameter = indexParameter; memberName = memberName.Substring(0, indexStart); } property.Name = memberName; property.Access = access; property.Type = returnType; property.MemberModifiers = memberAttributes; if (isExpressionBodyProperty) { property.IsExpressionBodyProperty = true; var expressionHead = new[] { CSharpSymbol.ExpressionBodyArrow1, CSharpSymbol.ExpressionBodyArrow2 }; // we can skip the first part as it already has been swallowed in order to identify the property var body = this.ParseOptionalExpression(expressionHead.Skip(1).ToArray()); if (string.IsNullOrEmpty(body)) { // in this case the expression is not optional and in fact required. this.OnParseError("Unexpected end of property. Expected " + new string(expressionHead) + " or property body with getter/setter."); } property.ExpressionBodyText = body; } else { property.BodyText = this.ParseBlock(false, property); property.AutoPropertyInitializer = this.ParseOptionalExpression(new[] { CSharpSymbol.Assignment }); } return property; }
/// <summary> /// Parses a type definition. /// </summary> /// <param name="access">The access.</param> /// <param name="typeAttributes">The type attributes.</param> /// <param name="elementType">Type of the element.</param> /// <returns>A type code element.</returns> private TypeElement ParseType( CodeAccess access, TypeModifiers typeAttributes, TypeElementType elementType) { TypeElement typeElement = new TypeElement(); EatWhiteSpace(); string className = CaptureWord(); typeElement.Name = className; typeElement.Access = access; typeElement.Type = elementType; typeElement.TypeModifiers = typeAttributes; if (elementType == TypeElementType.Enum) { EatLineContinuation(); if (NextChar == VBKeyword.As[0]) { EatWord(VBKeyword.As); string interfaceName = CaptureTypeName(); InterfaceReference interfaceReference = new InterfaceReference(interfaceName, InterfaceReferenceType.None); typeElement.AddInterface(interfaceReference); } string enumText = ParseBlock(VBKeyword.Enumeration); // TODO: Parse enum values as fields typeElement.BodyText = enumText; } else { EatWhiteSpace(); bool isGeneric = TryReadChar(VBSymbol.BeginParameterList); if (isGeneric) { EatWord(VBKeyword.Of, "Expected Of"); this.ParseTypeParameters(typeElement); } EatWhiteSpace(); // // Parse child elements // List<ICodeElement> childElements = ParseElements(typeElement); foreach (ICodeElement childElement in childElements) { typeElement.AddChild(childElement); } EatWhiteSpace(); string elementTypeString = EnumUtilities.ToString(elementType); EatWord(elementTypeString, "Expected End " + elementTypeString); } return typeElement; }
/// <summary> /// Parses a method. /// </summary> /// <param name="access">The member access.</param> /// <param name="memberAttributes">The member attributes.</param> /// <param name="isFunction">Whether or not the method is a function.</param> /// <param name="isDelegate">Whether or not the method is a delegate.</param> /// <param name="isOperator">Whether or not the method is an operator.</param> /// <param name="operatorType">Type of the operator.</param> /// <param name="inInterface">Whether or not the method is in an interface.</param> /// <param name="isExternal">Whether or not the method is external.</param> /// <param name="externalModifier">The external modifier.</param> /// <returns>A method element.</returns> private MethodElement ParseMethod( CodeAccess access, MemberModifiers memberAttributes, bool isFunction, bool isDelegate, bool isOperator, OperatorType operatorType, bool inInterface, bool isExternal, string externalModifier) { MethodElement method = new MethodElement(); method.Name = CaptureWord(); if (isOperator) { // Handle greater than/less than for the method name since these will get // excluded with < and > being alias breaks (needed by attributes). while (NextChar == VBSymbol.BeginAttribute || NextChar == VBSymbol.EndAttribute) { TryReadChar(); method.Name += CurrentChar + CaptureWord(); } } method.Access = access; method.MemberModifiers = memberAttributes; method.IsOperator = isOperator; method.OperatorType = operatorType; method[VBExtendedProperties.ExternalModifier] = externalModifier; if (isExternal) { method.MemberModifiers = method.MemberModifiers | MemberModifiers.External; EatLineContinuation(); EatWord(VBKeyword.Lib); EatLineContinuation(); EatChar(VBSymbol.BeginString); string library = CaptureWord().TrimEnd(VBSymbol.BeginString); method[VBExtendedProperties.ExternalLibrary] = library; EatLineContinuation(); if (NextChar != VBSymbol.BeginParameterList) { EatLineContinuation(); EatWord(VBKeyword.Alias); EatLineContinuation(); EatChar(VBSymbol.BeginString); string alias = CaptureWord().TrimEnd(VBSymbol.BeginString); method[VBExtendedProperties.ExternalAlias] = alias; } } EatLineContinuation(); EatChar(VBSymbol.BeginParameterList); EatWhiteSpace(); string paramsTemp = string.Empty; if (char.ToLower(NextChar) == char.ToLower(VBKeyword.Of[0])) { TryReadChar(); paramsTemp += CurrentChar; if (char.ToLower(NextChar) == char.ToLower(VBKeyword.Of[1])) { TryReadChar(); paramsTemp = string.Empty; this.ParseTypeParameters(method); EatChar(VBSymbol.BeginParameterList); EatWhiteSpace(); } } method.Parameters = paramsTemp + ParseNestedText( VBSymbol.BeginParameterList, VBSymbol.EndParameterList, false, false); if (isFunction || isOperator) { EatLineContinuation(); if (char.ToUpper(NextChar) == VBKeyword.As[0]) { EatWord(VBKeyword.As); method.Type = CaptureTypeName(); } else { method.Type = string.Empty; } } EatWhiteSpace(); string[] implements; string[] handles; bool parseHandles = !(isFunction || isOperator || isDelegate); string blockTemp = TryParseImplementsOrHandles(out implements, out handles, parseHandles); if (parseHandles) { method[VBExtendedProperties.Handles] = handles; } foreach (string implementation in implements) { InterfaceReference interfaceReference = new InterfaceReference(implementation, InterfaceReferenceType.Interface); method.AddImplementation(interfaceReference); } if ((memberAttributes & MemberModifiers.Abstract) != MemberModifiers.Abstract && !inInterface && !isExternal) { if (isFunction || isOperator) { if (isOperator) { method.BodyText = (blockTemp + this.ParseBlock(VBKeyword.Operator)).Trim(); } else if (!isDelegate) { method.BodyText = (blockTemp + this.ParseBlock(VBKeyword.Function)).Trim(); } } else if (!isDelegate) { method.BodyText = (blockTemp + this.ParseBlock(VBKeyword.Sub)).Trim(); } } return method; }
/// <summary> /// Parses a property. /// </summary> /// <param name="memberName">Name of the member.</param> /// <param name="returnType">Type of the return.</param> /// <param name="access">The access.</param> /// <param name="memberAttributes">The member attributes.</param> /// <returns>A property code element.</returns> private PropertyElement ParseProperty(string memberName, string returnType, CodeAccess access, MemberModifiers memberAttributes) { PropertyElement property = new PropertyElement(); int indexStart = memberName.IndexOf(CSharpSymbol.BeginAttribute); if (indexStart >= 0) { string indexParameter = memberName.Substring(indexStart).Trim().Trim( CSharpSymbol.BeginAttribute, CSharpSymbol.EndAttribute).Trim(); property.IndexParameter = indexParameter; memberName = memberName.Substring(0, indexStart); } property.Name = memberName; property.Access = access; property.Type = returnType; property.MemberModifiers = memberAttributes; property.BodyText = this.ParseBlock(false, property); return property; }
/// <summary> /// Parses a method. /// </summary> /// <param name="memberName">Member name.</param> /// <param name="access">Code access.</param> /// <param name="memberAttributes">Member attributes.</param> /// <param name="returnType">Return type.</param> /// <param name="isOperator">Whether or not the method is an operator.</param> /// <param name="operatorType">Type of the operator.</param> /// <returns>Method code element.</returns> private MethodElement ParseMethod( string memberName, CodeAccess access, MemberModifiers memberAttributes, string returnType, bool isOperator, OperatorType operatorType) { MethodElement method = new MethodElement(); method.Name = memberName; method.Access = access; method.Type = returnType; method.MemberModifiers = memberAttributes; method.IsOperator = isOperator; method.OperatorType = operatorType; if (isOperator && (operatorType == OperatorType.Implicit || operatorType == OperatorType.Explicit)) { method.Type = memberName; method.Name = null; } int genericIndex = memberName.LastIndexOf(CSharpSymbol.BeginGeneric); int lastQualifierIndex = memberName.LastIndexOf(CSharpSymbol.AliasQualifier); bool isGeneric = !isOperator && (genericIndex >= 0 && genericIndex < memberName.Length - 1 && (lastQualifierIndex < 0 || lastQualifierIndex < genericIndex)); if (isGeneric) { method.Name = memberName.Substring(0, genericIndex); string typeParameterString = memberName.TrimEnd(CSharpSymbol.EndGeneric).Substring( genericIndex + 1); string[] typeParameterNames = typeParameterString.Split( new char[] { CSharpSymbol.AliasSeparator, ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (string typeParameterName in typeParameterNames) { TypeParameter typeParameter = new TypeParameter(); typeParameter.Name = typeParameterName; method.AddTypeParameter(typeParameter); } } method.Parameters = this.ParseParameters(); if (isGeneric) { ParseTypeParameterConstraints(method); } EatWhiteSpace(); bool endOfStatement = NextChar == CSharpSymbol.EndOfStatement; if (endOfStatement) { TryReadChar(); method.BodyText = null; } else { method.BodyText = this.ParseBlock(true, method); } return method; }
/// <summary> /// Parses a field. /// </summary> /// <param name="isAssignment">Has field assignment.</param> /// <param name="access">Field access.</param> /// <param name="memberAttributes">The member attributes.</param> /// <param name="memberName">Name of the member.</param> /// <param name="returnType">Return type.</param> /// <param name="isVolatile">Whether or not the field is volatile.</param> /// <param name="isFixed">Whether or not the field is fixed.</param> /// <returns>A field code element.</returns> private FieldElement ParseField( bool isAssignment, CodeAccess access, MemberModifiers memberAttributes, string memberName, string returnType, bool isVolatile, bool isFixed) { FieldElement field = new FieldElement(); field.Name = memberName; field.Type = returnType; field.Access = access; field.MemberModifiers = memberAttributes; field.IsVolatile = isVolatile; field[CSharpExtendedProperties.Fixed] = isFixed; if (isAssignment) { string initialValue = ParseInitialValue(); field.InitialValue = initialValue; } EatWhiteSpace(WhiteSpaceTypes.SpaceAndTab); if (NextChar == CSharpSymbol.BeginComment) { EatChar(CSharpSymbol.BeginComment); if (NextChar == CSharpSymbol.BeginComment) { field.TrailingComment = ParseCommentLine(); } else if (NextChar == CSharpSymbol.BlockCommentModifier) { field.TrailingComment = ParseCommentBlock(); } } return field; }
/// <summary> /// Parses an event. /// </summary> /// <param name="access">Member accessibility.</param> /// <param name="memberAttributes">Member modifiers.</param> /// <returns>Event code element.</returns> private EventElement ParseEvent(CodeAccess access, MemberModifiers memberAttributes) { EventElement eventElement = new EventElement(); StringBuilder eventSignature = new StringBuilder(); while (NextChar != CSharpSymbol.EndOfStatement && NextChar != CSharpSymbol.BeginBlock) { if (TryReadChar()) { eventSignature.Append(CurrentChar); } } string[] words = eventSignature.ToString().Split(WhiteSpaceCharacters, StringSplitOptions.RemoveEmptyEntries); StringCollection wordList = new StringCollection(); wordList.AddRange(words); string name = null; string type = null; GetMemberNameAndType(wordList, out name, out type); eventElement.Type = type; eventElement.Name = name; eventElement.Access = access; eventElement.MemberModifiers = memberAttributes; EatWhiteSpace(); char nextChar = NextChar; if (nextChar == CSharpSymbol.EndOfStatement) { EatChar(CSharpSymbol.EndOfStatement); } else { eventElement.BodyText = this.ParseBlock(true, eventElement); } return eventElement; }
/// <summary> /// Parses a delegate. /// </summary> /// <param name="memberName">Member name</param> /// <param name="access">Code access</param> /// <param name="memberAttributes">Member attributes</param> /// <param name="returnType">Return type</param> /// <returns>A delegate code element.</returns> private DelegateElement ParseDelegate( string memberName, CodeAccess access, MemberModifiers memberAttributes, string returnType) { DelegateElement delegateElement = new DelegateElement(); delegateElement.Name = memberName; delegateElement.Access = access; delegateElement.Type = returnType; delegateElement.MemberModifiers = memberAttributes; int genericIndex = memberName.IndexOf(CSharpSymbol.BeginGeneric); bool isGeneric = genericIndex >= 0 && genericIndex < memberName.Length - 1; if (isGeneric) { delegateElement.Name = memberName.Substring(0, genericIndex); string typeParameterString = memberName.TrimEnd(CSharpSymbol.EndGeneric).Substring( genericIndex + 1); string[] typeParameterNames = typeParameterString.Split( new char[] { CSharpSymbol.AliasSeparator, ' ' }, StringSplitOptions.RemoveEmptyEntries); bool checkVariance = false; for (int i = 0; i < typeParameterNames.Length; i++) { string typeParameterName = typeParameterNames[i]; if (typeParameterName == "in" || typeParameterName == "out") { checkVariance = true; continue; } TypeParameter typeParameter = new TypeParameter(); if (checkVariance) { checkVariance = false; typeParameter.IsIn = typeParameterNames[i - 1] == "in"; typeParameter.IsOut = typeParameterNames[i - 1] == "out"; } typeParameter.Name = typeParameterName; delegateElement.AddTypeParameter(typeParameter); } } delegateElement.Parameters = this.ParseParameters(); if (isGeneric) { ParseTypeParameterConstraints(delegateElement); } EatChar(CSharpSymbol.EndOfStatement); return delegateElement; }
/// <summary> /// Parses an event. /// </summary> /// <param name="access">The event access.</param> /// <param name="memberAttributes">The member attributes.</param> /// <param name="isCustom">Whether or not the event is custom.</param> /// <returns>An event code element.</returns> private EventElement ParseEvent( CodeAccess access, MemberModifiers memberAttributes, bool isCustom) { EventElement eventElement = new EventElement(); string name = CaptureWord(); eventElement.Name = name; eventElement.Access = access; eventElement.MemberModifiers = memberAttributes; EatWhiteSpace(WhiteSpaceTypes.SpaceAndTab); if (NextChar == VBSymbol.BeginParameterList) { eventElement.Parameters = ParseNestedText( VBSymbol.BeginParameterList, VBSymbol.EndParameterList, true, true); } else { EatWord(VBKeyword.As); string eventType = CaptureTypeName(); if (string.IsNullOrEmpty(eventType)) { this.OnParseError("Expected type identifier"); } eventElement.Type = eventType; } string[] implements; string blockTemp = TryParseImplements(out implements); foreach (string implementation in implements) { InterfaceReference interfaceReference = new InterfaceReference(implementation, InterfaceReferenceType.Interface); eventElement.AddImplementation(interfaceReference); } if (isCustom) { eventElement.BodyText = (blockTemp + this.ParseBlock(VBKeyword.Event)).Trim(); } return eventElement; }
/// <summary> /// Parses a type definition. /// </summary> /// <param name="access">Type accessibility.</param> /// <param name="typeAttributes">Type modifiers.</param> /// <param name="elementType">Type element type.</param> /// <returns>Type code element.</returns> private TypeElement ParseType( CodeAccess access, TypeModifiers typeAttributes, TypeElementType elementType) { TypeElement typeElement = new TypeElement(); EatWhiteSpace(); string className = CaptureWord(); typeElement.Name = className; typeElement.Access = access; typeElement.Type = elementType; typeElement.TypeModifiers = typeAttributes; EatWhiteSpace(); if (elementType == TypeElementType.Enum) { EatWhiteSpace(); if (NextChar == CSharpSymbol.TypeImplements) { TryReadChar(); string interfaceName = CaptureTypeName(); InterfaceReference interfaceReference = new InterfaceReference(interfaceName, InterfaceReferenceType.None); typeElement.AddInterface(interfaceReference); } string enumText = ParseBlock(true, typeElement); // TODO: Parse enum values as fields typeElement.BodyText = enumText; } else { bool isGeneric = TryReadChar(CSharpSymbol.BeginGeneric); if (isGeneric) { string[] typeParameterNames = ParseAliasList(); foreach (string typeParameterName in typeParameterNames) { TypeParameter typeParameter = new TypeParameter(); typeParameter.Name = typeParameterName; typeElement.AddTypeParameter(typeParameter); } EatWhiteSpace(); if (!TryReadChar(CSharpSymbol.EndGeneric)) { this.OnParseError("Expected " + CSharpSymbol.EndGeneric); } } EatWhiteSpace(); bool implements = TryReadChar(CSharpSymbol.TypeImplements); if (implements) { string[] typeList = ParseAliasList(); foreach (string type in typeList) { InterfaceReference interfaceReference = new InterfaceReference(type, InterfaceReferenceType.None); typeElement.AddInterface(interfaceReference); } } EatWhiteSpace(); ParseTypeParameterConstraints(typeElement); // Associate any additional comments in the type definition with the type. ReadOnlyCollection<ICommentElement> extraComments = ParseComments(); foreach (ICommentElement comment in extraComments) { typeElement.AddHeaderComment(comment); } EatChar(CSharpSymbol.BeginBlock); EatWhiteSpace(); if (NextChar != CSharpSymbol.EndBlock) { // // Parse child elements // List<ICodeElement> childElements = ParseElements(typeElement); foreach (ICodeElement childElement in childElements) { typeElement.AddChild(childElement); } } EatChar(CSharpSymbol.EndBlock); } // // Types allow a trailing semi-colon // EatTrailingEndOfStatement(); return typeElement; }
/// <summary> /// Parses a field. /// </summary> /// <param name="wordList">The word list.</param> /// <param name="access">The field access.</param> /// <param name="memberAttributes">The member attributes.</param> /// <param name="untypedAssignment">Whether or not the field is untyped.</param> /// <returns>A field code element.</returns> private FieldElement ParseField( StringCollection wordList, CodeAccess access, MemberModifiers memberAttributes, bool untypedAssignment) { FieldElement field = new FieldElement(); StringBuilder nameBuilder = new StringBuilder(DefaultWordLength); foreach (string word in wordList) { string trimmedWord = word.Trim(' ', VBSymbol.AliasSeparator); string upperWord = trimmedWord.ToUpperInvariant(); if ((!VBKeyword.IsVBKeyword(trimmedWord) || upperWord == VBKeyword.Custom.ToUpperInvariant() || upperWord == VBKeyword.Ansi.ToUpperInvariant() || upperWord == VBKeyword.Unicode.ToUpperInvariant() || upperWord == VBKeyword.Auto.ToUpperInvariant()) && trimmedWord.Length > 0) { nameBuilder.Append(trimmedWord); nameBuilder.Append(VBSymbol.AliasSeparator); nameBuilder.Append(' '); } } field.Name = nameBuilder.ToString().TrimEnd(VBSymbol.AliasSeparator, ' '); EatWhiteSpace(); if (!untypedAssignment) { string returnType = CaptureTypeName(); if (returnType.ToUpperInvariant() == VBKeyword.New.ToUpperInvariant()) { EatWhiteSpace(WhiteSpaceTypes.SpaceAndTab); field.InitialValue = VBKeyword.New + " " + ReadCodeLine().Trim(); } else { field.Type = returnType; } } field.Access = access; field.MemberModifiers = memberAttributes; EatWhiteSpace(WhiteSpaceTypes.SpaceAndTab); bool isAssignment = NextChar == VBSymbol.Assignment || untypedAssignment; if (isAssignment) { if (!untypedAssignment) { EatChar(VBSymbol.Assignment); } string initialValue = ParseInitialValue(); field.InitialValue = initialValue; } EatWhiteSpace(WhiteSpaceTypes.SpaceAndTab); if (NextChar == VBSymbol.BeginComment) { EatChar(VBSymbol.BeginComment); string commentText = ReadLine().Trim(); if (commentText.Length > 0) { CommentElement comment = new CommentElement(commentText); field.TrailingComment = comment; } } return field; }
/// <summary> /// Parses a constructor. /// </summary> /// <param name="memberName">Member name.</param> /// <param name="access">Member accessibility.</param> /// <param name="memberAttributes">Member attributes.</param> /// <returns>Constructor code element.</returns> private ConstructorElement ParseConstructor(string memberName, CodeAccess access, MemberModifiers memberAttributes) { ConstructorElement constructor = new ConstructorElement(); constructor.Name = memberName; constructor.Access = access; constructor.MemberModifiers = memberAttributes; constructor.Parameters = this.ParseParameters(); EatWhiteSpace(); List<ICommentElement> extraComments = new List<ICommentElement>(); extraComments.AddRange(ParseComments()); EatWhiteSpace(); bool hasReference = TryReadChar(CSharpSymbol.TypeImplements); if (hasReference) { EatWhiteSpace(); extraComments.AddRange(ParseComments()); StringBuilder referenceBuilder = new StringBuilder(DefaultWordLength); EatWhiteSpace(); referenceBuilder.Append(CaptureWord()); EatWhiteSpace(); string referenceParams = ParseNestedText(CSharpSymbol.BeginParameterList, CSharpSymbol.EndParameterList, true, true); referenceBuilder.Append(CSharpSymbol.BeginParameterList); referenceBuilder.Append(referenceParams); referenceBuilder.Append(CSharpSymbol.EndParameterList); constructor.Reference = referenceBuilder.ToString(); } constructor.BodyText = this.ParseBlock(true, constructor); foreach (ICommentElement comment in extraComments) { constructor.AddHeaderComment(comment); } return constructor; }
/// <summary> /// Parses a property. /// </summary> /// <param name="access">The access.</param> /// <param name="memberAttributes">The member attributes.</param> /// <param name="isDefault">Whether or not the property is a default property</param> /// <param name="modifyAccess">The modify access.</param> /// <param name="inInterface">Whether or not the property is part of an interface.</param> /// <returns>A property code element.</returns> private PropertyElement ParseProperty( CodeAccess access, MemberModifiers memberAttributes, bool isDefault, string modifyAccess, bool inInterface) { PropertyElement property = new PropertyElement(); property.Name = CaptureWord(); property.Access = access; property.MemberModifiers = memberAttributes; property[VBExtendedProperties.Default] = isDefault; property[VBExtendedProperties.AccessModifier] = modifyAccess; EatLineContinuation(); if (NextChar == VBSymbol.BeginParameterList) { string indexParam = this.ParseParams(); if (indexParam.Length > 0) { property.IndexParameter = indexParam; } } EatWord(VBKeyword.As, "Expected As"); string type = CaptureTypeName(); if (string.IsNullOrEmpty(type)) { this.OnParseError("Expected return type"); } property.Type = type; string[] implements; string blockTemp = TryParseImplements(out implements); foreach (string implementation in implements) { InterfaceReference interfaceReference = new InterfaceReference(implementation, InterfaceReferenceType.Interface); property.AddImplementation(interfaceReference); } if ((memberAttributes & MemberModifiers.Abstract) != MemberModifiers.Abstract && !inInterface) { property.BodyText = (blockTemp + this.ParseBlock(VBKeyword.Property)).Trim(); } return property; }
/// <summary> /// Parses a delegate. /// </summary> /// <param name="memberName">Member name</param> /// <param name="access">Code access</param> /// <param name="memberAttributes">Member attributes</param> /// <param name="returnType">Return type</param> /// <returns>A delegate code element.</returns> private DelegateElement ParseDelegate( string memberName, CodeAccess access, MemberModifiers memberAttributes, string returnType) { DelegateElement delegateElement = new DelegateElement(); delegateElement.Name = memberName; delegateElement.Access = access; delegateElement.Type = returnType; delegateElement.MemberModifiers = memberAttributes; int genericIndex = memberName.IndexOf(CSharpSymbol.BeginGeneric); bool isGeneric = genericIndex >= 0 && genericIndex < memberName.Length - 1; if (isGeneric) { delegateElement.Name = memberName.Substring(0, genericIndex); string typeParameterString = memberName.TrimEnd(CSharpSymbol.EndGeneric).Substring( genericIndex + 1); string[] typeParameterNames = typeParameterString.Split( new char[] { CSharpSymbol.AliasSeparator, ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (string typeParameterName in typeParameterNames) { TypeParameter typeParameter = new TypeParameter(); typeParameter.Name = typeParameterName; delegateElement.AddTypeParameter(typeParameter); } } delegateElement.Parameters = this.ParseParameters(); if (isGeneric) { ParseTypeParameterConstraints(delegateElement); } EatChar(CSharpSymbol.EndOfStatement); return delegateElement; }
/// <summary> /// Parses a delegate. /// </summary> /// <param name="access">The member access.</param> /// <param name="memberAttributes">The member attributes.</param> /// <returns>Delegate code element.</returns> private DelegateElement ParseDelegate( CodeAccess access, MemberModifiers memberAttributes) { string delegateType = CaptureWord(); bool isFunction = false; switch (VBKeyword.Normalize(delegateType)) { case VBKeyword.Sub: isFunction = false; break; case VBKeyword.Function: isFunction = true; break; default: this.OnParseError( "Expected Sub or Function for delegate declaration"); break; } MethodElement methodElement = ParseMethod( access, memberAttributes, isFunction, true, false, OperatorType.None, false, false, null); DelegateElement delegateElement = new DelegateElement(); delegateElement.Name = methodElement.Name; delegateElement.Access = methodElement.Access; delegateElement.MemberModifiers = methodElement.MemberModifiers; delegateElement.Parameters = methodElement.Parameters; delegateElement.BodyText = methodElement.BodyText; if (isFunction) { delegateElement.Type = methodElement.Type; } foreach (TypeParameter typeParameter in methodElement.TypeParameters) { delegateElement.AddTypeParameter(typeParameter); } return delegateElement; }
/// <summary> /// Parses a method. /// </summary> /// <param name="memberName">Member name.</param> /// <param name="access">Code access.</param> /// <param name="memberAttributes">Member attributes.</param> /// <param name="returnType">Return type.</param> /// <param name="isOperator">Whether or not the method is an operator.</param> /// <param name="operatorType">Type of the operator.</param> /// <returns>Method code element.</returns> private MethodElement ParseMethod( string memberName, CodeAccess access, MemberModifiers memberAttributes, string returnType, bool isOperator, OperatorType operatorType) { MethodElement method = new MethodElement(); method.Name = memberName; method.Access = access; method.Type = returnType; method.MemberModifiers = memberAttributes; method.IsOperator = isOperator; method.OperatorType = operatorType; if (isOperator && (operatorType == OperatorType.Implicit || operatorType == OperatorType.Explicit)) { method.Type = memberName; method.Name = null; } int genericIndex = memberName.LastIndexOf(CSharpSymbol.BeginGeneric); int lastQualifierIndex = memberName.LastIndexOf(CSharpSymbol.AliasQualifier); bool isGeneric = !isOperator && (genericIndex >= 0 && genericIndex < memberName.Length - 1 && (lastQualifierIndex < 0 || lastQualifierIndex < genericIndex)); if (isGeneric) { method.Name = memberName.Substring(0, genericIndex); string typeParameterString = memberName.TrimEnd(CSharpSymbol.EndGeneric).Substring( genericIndex + 1); string[] typeParameterNames = typeParameterString.Split( new char[] { CSharpSymbol.AliasSeparator, ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (string typeParameterName in typeParameterNames) { TypeParameter typeParameter = new TypeParameter(); typeParameter.Name = typeParameterName; method.AddTypeParameter(typeParameter); } } method.Parameters = this.ParseParameters(); if (isGeneric) { ParseTypeParameterConstraints(method); } EatWhiteSpace(); bool endOfStatement = NextChar == CSharpSymbol.EndOfStatement; if (endOfStatement) { TryReadChar(); method.BodyText = null; } else { bool expression = NextChar == CSharpSymbol.Assignment; if (expression) { var expressionHead = new[] { CSharpSymbol.ExpressionBodyArrow1, CSharpSymbol.ExpressionBodyArrow2 }; // lucky for us, expressions can only have one statement (unlike expression lambdas), // therefore we must have text like this "=> followed.by.a.statement;" which ParseOptionalAssignment will automatically trim to "followed.by.a.statement" method.BodyText = this.ParseOptionalExpression(expressionHead); method.HasExpressionBody = true; if (string.IsNullOrEmpty(method.BodyText)) { // is expression, but no suitable body found this.OnParseError("Unexpected end of method. Expected " + new string(expressionHead) + " or a method body."); } } else { method.BodyText = this.ParseBlock(true, method); } } return method; }