/// <summary> /// Adds an item to the Implements collection. /// </summary> /// <param name="implementation">The implementation.</param> public void AddImplementation(InterfaceReference implementation) { if (implementation != null) { ImplementsBase.Add(implementation); } }
/// <summary> /// Adds an interface implementation to the type definition. /// </summary> /// <param name="interfaceReference">The interface reference.</param> public void AddInterface(InterfaceReference interfaceReference) { if (interfaceReference != null) { BaseInterfaces.Add(interfaceReference); } }
/// <summary> /// Creates a clone of this instance. /// </summary> /// <returns> /// Clone of the instance with the member element state copied. /// </returns> protected override sealed MemberElement DoMemberClone() { InterfaceMemberElement clone = DoInterfaceMemberClone(); foreach (InterfaceReference implementation in Implements) { InterfaceReference implementationClone = implementation.Clone() as InterfaceReference; clone.ImplementsBase.Add(implementation); } return(clone); }
/// <summary> /// Creates a clone of this instance /// </summary> /// <returns> /// A new object that is a copy of this instance. /// </returns> public object Clone() { InterfaceReference clone = new InterfaceReference(); // // Copy state // clone._name = _name; clone._referenceType = _referenceType; return clone; }
/// <summary> /// Creates a clone of this instance /// </summary> /// <returns> /// A new object that is a copy of this instance. /// </returns> public object Clone() { InterfaceReference clone = new InterfaceReference(); // // Copy state // clone._name = _name; clone._referenceType = _referenceType; return(clone); }
/// <summary> /// Clones an attributed element. /// </summary> /// <returns>Cloned attribute element state.</returns> protected override AttributedElement DoAttributedClone() { TypeElement clone = new TypeElement(); // // Copy state // clone._typeModifiers = _typeModifiers; clone._type = _type; foreach (InterfaceReference interfaceReference in Interfaces) { InterfaceReference referenceClone = interfaceReference.Clone() as InterfaceReference; clone.AddInterface(referenceClone); } foreach (TypeParameter typeParam in TypeParameters) { TypeParameter typeParamClone = typeParam.Clone() as TypeParameter; clone.TypeParametersBase.Add(typeParamClone); } return(clone); }
/// <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 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 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; }
public void CreateDefaultTest() { InterfaceReference reference1 = new InterfaceReference(); Assert.IsNull(reference1.Name, "Unexpected default value for Name."); Assert.AreEqual(InterfaceReferenceType.None, reference1.ReferenceType, "Unexpected default value for ReferenceType."); }
/// <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; }
public void ReferenceTypeTest() { InterfaceReference reference = new InterfaceReference(); reference.ReferenceType = InterfaceReferenceType.Class; Assert.AreEqual(InterfaceReferenceType.Class, reference.ReferenceType, "Unexpected value for ReferenceType."); }
public void NameTest() { InterfaceReference reference = new InterfaceReference(); reference.Name = "Test"; Assert.AreEqual("Test", reference.Name, "Unexpected value for Name."); }
public void CreateTest() { InterfaceReference reference1 = new InterfaceReference("IDisposable", InterfaceReferenceType.Interface); Assert.AreEqual("IDisposable", reference1.Name, "Unexpected value for Name."); Assert.AreEqual(InterfaceReferenceType.Interface, reference1.ReferenceType, "Unexpected value for ReferenceType."); }
/// <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 elements from the current point in the stream. /// </summary> /// <param name="parentElement">Parent element</param> /// <returns>A list of parsed code elements.</returns> private List<ICodeElement> ParseElements(ICodeElement parentElement) { List<ICodeElement> codeElements = new List<ICodeElement>(); List<ICommentElement> comments = new List<ICommentElement>(); List<AttributeElement> attributes = new List<AttributeElement>(); Stack<ICodeElement> enclosingElementStack = new Stack<ICodeElement>(); StringBuilder elementBuilder = new StringBuilder(DefaultBlockLength); char nextChar; bool end = false; bool lineContinuation = false; while (TryReadChar() && !end) { switch (CurrentChar) { // // Comments // case VBSymbol.BeginComment: CommentElement commentLine = ParseCommentLine(); string commentDirectiveRegionName = GetCommentDirectiveText(commentLine, Configuration.Formatting.Regions.CommentDirectiveBeginPattern, "Name"); if (commentDirectiveRegionName != null) { PushComments(codeElements, comments); RegionElement regionElement = new RegionElement(); regionElement.Name = commentDirectiveRegionName; enclosingElementStack.Push(regionElement); } else { commentDirectiveRegionName = GetCommentDirectiveText(commentLine, Configuration.Formatting.Regions.CommentDirectiveEndPattern, "Name"); if (commentDirectiveRegionName != null) { if (enclosingElementStack.Count == 0 || enclosingElementStack.Peek().ElementType != ElementType.Region) { this.OnParseError("Unmatched end region directive"); } ICodeElement enclosingElement = enclosingElementStack.Pop(); // // Add any processed comments to the region or condition directive. // if (comments.Count > 0) { foreach (ICommentElement commentElement in comments) { enclosingElement.AddChild(commentElement); } comments.Clear(); } // // Are we processing a nested region or condition directive? // if (enclosingElementStack.Count > 0) { enclosingElementStack.Peek().AddChild(enclosingElement); } else { codeElements.Add(enclosingElement); } } else { comments.Add(commentLine); } } break; // // Preprocessor // case VBSymbol.Preprocessor: // // TODO: Parse additional preprocessor directives. // string line = ReadLine().Trim(); string[] words = line.Split(WhiteSpaceCharacters, StringSplitOptions.RemoveEmptyEntries); if (words.Length > 0 && VBKeyword.Normalize(words[0]) == VBKeyword.Region) { PushComments(codeElements, comments); RegionElement regionElement = ParseRegion(line); enclosingElementStack.Push(regionElement); } else if (words.Length > 0 && (VBKeyword.Normalize(words[0]) == VBKeyword.If || VBKeyword.Normalize(words[0]) == VBKeyword.Else || VBKeyword.Normalize(words[0]) == VBKeyword.ElseIf)) { bool isIf; ConditionDirectiveElement conditionDirective = ParseConditionDirective(line.Trim(), out isIf); if (isIf) { enclosingElementStack.Push(conditionDirective); } else { if (enclosingElementStack.Count == 0 || enclosingElementStack.Peek().ElementType != ElementType.ConditionDirective) { this.OnParseError("Expected 'If' preprocessor directive."); } else { ConditionDirectiveElement previousCondition = enclosingElementStack.Peek() as ConditionDirectiveElement; while (previousCondition.ElseCondition != null) { previousCondition = previousCondition.ElseCondition; } // Add the condition to the end of the condition linked list previousCondition.ElseCondition = conditionDirective; } } } else if (words.Length > 1 && VBKeyword.Normalize(words[0]) == VBKeyword.End && (VBKeyword.Normalize(words[1]) == VBKeyword.Region || VBKeyword.Normalize(words[1]) == VBKeyword.If)) { ICodeElement enclosingElement = null; if (VBKeyword.Normalize(words[1]) == VBKeyword.Region) { if (enclosingElementStack.Count == 0 || enclosingElementStack.Peek().ElementType != ElementType.Region) { this.OnParseError("Unmatched end region directive"); } } else if (enclosingElementStack.Count == 0 || enclosingElementStack.Peek().ElementType != ElementType.ConditionDirective) { this.OnParseError("Unmatched #End If"); } enclosingElement = enclosingElementStack.Pop(); // // If there are any attributes not associated with an element (e.g. // a condition directive containing only an attribute, then // throw an error as this is currently not supported. // if (enclosingElement.ElementType == ElementType.ConditionDirective && attributes.Count > 0) { this.OnParseError("Cannot arrange files with preprocessor directives containing attributes unassociated to an element"); } if (comments.Count > 0) { foreach (ICommentElement commentElement in comments) { enclosingElement.AddChild(commentElement); } comments.Clear(); } if (enclosingElementStack.Count > 0) { enclosingElementStack.Peek().AddChild(enclosingElement); } else { codeElements.Add(enclosingElement); } } else { this.OnParseError( "Cannot arrange files with preprocessor directives " + "other than #Region, #End Region and conditional compilation directives"); } break; // // Attribute // case VBSymbol.BeginAttribute: nextChar = NextChar; // // Parse attribute // AttributeElement attributeElement = ParseAttribute(comments.AsReadOnly()); attributes.Add(attributeElement); codeElements.Add(attributeElement); comments.Clear(); break; case VBSymbol.LineContinuation: if (IsWhiteSpace(PreviousChar) && IsWhiteSpace(NextChar)) { lineContinuation = true; } else { elementBuilder.Append(CurrentChar); } break; // Eat any unneeded whitespace case ' ': case '\n': case '\r': case '\t': case ':': if (elementBuilder.Length > 0) { string processedText = elementBuilder.ToString().Trim(); if (CurrentChar == '\n') { if (!lineContinuation) { this.OnParseError( string.Format( Thread.CurrentThread.CurrentCulture, "Unhandled element text '{0}'", processedText)); } else { lineContinuation = false; } } if (elementBuilder[elementBuilder.Length - 1] != ' ') { elementBuilder.Append(' '); } } break; default: elementBuilder.Append(CurrentChar); string upperElementText = elementBuilder.ToString().ToUpperInvariant(); nextChar = NextChar; if (upperElementText == VBKeyword.End.ToUpperInvariant()) { end = true; elementBuilder = new StringBuilder(DefaultBlockLength); } else if (upperElementText == VBKeyword.Rem.ToUpperInvariant() && nextChar == ' ') { CommentElement remCommentLine = ParseCommentLine(); comments.Add(remCommentLine); elementBuilder = new StringBuilder(DefaultBlockLength); } else if (upperElementText == VBKeyword.Option.ToUpperInvariant() && IsWhiteSpace(nextChar)) { ICodeElement optionElement = ParseOption(comments.AsReadOnly()); comments.Clear(); codeElements.Add(optionElement); elementBuilder = new StringBuilder(DefaultBlockLength); } else { if (char.IsWhiteSpace(nextChar) || VBSymbol.IsVBSymbol(CurrentChar)) { string elementText = VBKeyword.Normalize(elementBuilder.ToString()); bool isImplements = elementText.StartsWith( VBKeyword.Implements, StringComparison.OrdinalIgnoreCase); bool isInherits = !isImplements && elementText.StartsWith( VBKeyword.Inherits, StringComparison.OrdinalIgnoreCase); TypeElement typeElement = parentElement as TypeElement; if ((isImplements || isInherits) && typeElement != null) { InterfaceReferenceType referenceType = InterfaceReferenceType.None; if (isInherits) { referenceType = InterfaceReferenceType.Class; } else if (isImplements) { referenceType = InterfaceReferenceType.Interface; } do { EatWhiteSpace(WhiteSpaceTypes.SpaceAndTab); if (NextChar == VBSymbol.AliasSeparator) { EatChar(VBSymbol.AliasSeparator); } string typeName = CaptureTypeName(); InterfaceReference interfaceReference = new InterfaceReference(typeName, referenceType); typeElement.AddInterface(interfaceReference); EatWhiteSpace(WhiteSpaceTypes.SpaceAndTab); } while (NextChar == VBSymbol.AliasSeparator); elementBuilder = new StringBuilder(DefaultBlockLength); } else { // // Try to parse a code element // ICodeElement element = TryParseElement(parentElement, elementBuilder, comments.AsReadOnly(), attributes.AsReadOnly()); if (element != null) { if (element is CommentedElement) { UsingElement usingElement = element as UsingElement; // // If this is the first using statement, then don't attach // header comments to the element. // if (usingElement != null && parentElement == null && codeElements.Count == 0) { foreach (ICommentElement commentElement in usingElement.HeaderComments) { if (enclosingElementStack.Count > 0) { enclosingElementStack.Peek().AddChild(commentElement); } else { codeElements.Add(commentElement); } } usingElement.ClearHeaderCommentLines(); } comments.Clear(); } if (enclosingElementStack.Count > 0) { ICodeElement enclosingElement = enclosingElementStack.Peek(); if (enclosingElement.ElementType == ElementType.ConditionDirective) { ConditionDirectiveElement conditionDirective = enclosingElement as ConditionDirectiveElement; while (conditionDirective.ElseCondition != null) { conditionDirective = conditionDirective.ElseCondition; } enclosingElement = conditionDirective; } enclosingElement.AddChild(element); } else { codeElements.Add(element); } elementBuilder = new StringBuilder(DefaultBlockLength); if (element is IAttributedElement) { foreach (AttributeElement attribute in attributes) { codeElements.Remove(attribute); } attributes = new List<AttributeElement>(); } } } } } break; } char nextCh = NextChar; } if (comments.Count > 0) { for (int commentIndex = 0; commentIndex < comments.Count; commentIndex++) { ICommentElement comment = comments[commentIndex]; codeElements.Insert(commentIndex, comment); } } // // Make sure that all region elements have been closed // if (enclosingElementStack.Count > 0) { if (enclosingElementStack.Peek().ElementType == ElementType.Region) { this.OnParseError( string.Format( CultureInfo.InvariantCulture, "Missing end region directive for '{0}'", enclosingElementStack.Peek().Name)); } else { this.OnParseError("Expected #End If"); } } if (elementBuilder.Length > 0) { this.OnParseError( string.Format( Thread.CurrentThread.CurrentCulture, "Unhandled element text '{0}'", elementBuilder)); } return codeElements; }