/// <summary> /// Initializes a new instance of the VariableDeclarationStatement class. /// </summary> /// <param name="tokens"> /// The list of tokens that form the statement. /// </param> /// <param name="constant"> /// Indicates whether the item is constant. /// </param> /// <param name="expression"> /// The inner expression. /// </param> internal VariableDeclarationStatement(CsTokenList tokens, bool constant, VariableDeclarationExpression expression) : base(StatementType.VariableDeclaration, tokens) { Param.AssertNotNull(tokens, "tokens"); Param.Ignore(constant); Param.AssertNotNull(expression, "expression"); this.constant = constant; this.expression = expression; this.AddExpression(expression); }
/// <summary> /// Reads an expression beginning with two unknown words. /// </summary> /// <param name="type"> /// The type of the variable. /// </param> /// <param name="previousPrecedence"> /// The precedence of the previous expression. /// </param> /// <param name="unsafeCode"> /// Indicates whether the code being parsed resides in an unsafe code block. /// </param> /// <returns> /// Returns the expression. /// </returns> private VariableDeclarationExpression GetVariableDeclarationExpression(Expression type, ExpressionPrecedence previousPrecedence, bool unsafeCode) { Param.AssertNotNull(type, "type"); Param.Ignore(previousPrecedence); Param.Ignore(unsafeCode); Debug.Assert( type.ExpressionType == ExpressionType.Literal || type.ExpressionType == ExpressionType.MemberAccess, "The left side of a variable declaration must either be a literal or a member access."); VariableDeclarationExpression expression = null; if (CheckPrecedence(previousPrecedence, ExpressionPrecedence.None)) { Reference<ICodePart> expressionReference = new Reference<ICodePart>(); // Convert the type expression to a literal type token expression. LiteralExpression literalType = null; if (type.ExpressionType == ExpressionType.Literal) { literalType = type as LiteralExpression; if (!(literalType.Token is TypeToken)) { literalType = null; } } if (literalType == null) { literalType = this.ConvertTypeExpression(type); } // Get each declarator. List<VariableDeclaratorExpression> declarators = new List<VariableDeclaratorExpression>(); while (true) { // Get the next word. Symbol symbol = this.GetNextSymbol(SymbolType.Other, expressionReference); // Get the identifier. LiteralExpression identifier = this.GetLiteralExpression(expressionReference, unsafeCode); if (identifier == null || identifier.Tokens.First == null) { throw new SyntaxException(this.document.SourceCode, symbol.LineNumber); } // Get the initializer if it exists. Expression initializer = null; symbol = this.GetNextSymbol(expressionReference); if (symbol.SymbolType == SymbolType.Equals) { // Add the equals token. this.tokens.Add(this.GetOperatorToken(OperatorType.Equals, expressionReference)); // Check whether this is an array initializer. symbol = this.GetNextSymbol(expressionReference); if (symbol.SymbolType == SymbolType.OpenCurlyBracket) { initializer = this.GetArrayInitializerExpression(unsafeCode); } else { initializer = this.GetNextExpression(ExpressionPrecedence.None, expressionReference, unsafeCode); } } // Create the token list for the declarator. CsTokenList partialTokens = new CsTokenList(this.tokens, identifier.Tokens.First, this.tokens.Last); // Create and add the declarator. declarators.Add(new VariableDeclaratorExpression(partialTokens, identifier, initializer)); // Now check if the next character is a comma. If so there is another declarator. symbol = this.GetNextSymbol(expressionReference); if (symbol.SymbolType != SymbolType.Comma) { // There are no more declarators. break; } // Add the comma. this.tokens.Add(this.GetToken(CsTokenType.Comma, SymbolType.Comma, expressionReference)); } // Create the token list for the expression. CsTokenList tokenList = new CsTokenList(this.tokens, type.Tokens.First, this.tokens.Last); // Create the expression. expression = new VariableDeclarationExpression(tokenList, literalType, declarators.ToArray()); expressionReference.Target = expression; } return expression; }
/// <summary> /// Parses and returns a property. /// </summary> /// <param name="parent">The parent of the element.</param> /// <param name="elementReference">A reference to the element being created.</param> /// <param name="unsafeCode">Indicates whether the code is marked as unsafe.</param> /// <param name="generated">Indicates whether the code is marked as generated code.</param> /// <param name="xmlHeader">The element's documentation header.</param> /// <param name="attributes">The attributes on the element.</param> /// <returns> /// Returns the element. /// </returns> private Property ParseProperty( CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes) { Param.AssertNotNull(parent, "parent"); Param.AssertNotNull(elementReference, "elementReference"); Param.Ignore(unsafeCode); Param.Ignore(generated); Param.Ignore(xmlHeader); Param.Ignore(attributes); Node<CsToken> previousTokenNode = this.tokens.Last; // Get the modifiers and access. AccessModifierType accessModifier = AccessModifierType.Private; // Properties within interfaces always have the access of the parent interface. Interface parentInterface = parent as Interface; if (parentInterface != null) { accessModifier = parentInterface.AccessModifier; } // Get declared modifiers. Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, PropertyModifiers); unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe); // Get the field type. TypeToken propertyType = this.GetTypeToken(elementReference, unsafeCode, true); Node<CsToken> propertyTypeNode = this.tokens.InsertLast(propertyType); // Get the name of the property. CsToken name = this.GetElementNameToken(elementReference, unsafeCode); Node<CsToken> propertyNameNode = this.tokens.InsertLast(name); // Create the declaration. Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next; CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last); Declaration declaration = new Declaration(declarationTokens, name.Text, ElementType.Property, accessModifier, modifiers); Property property = new Property(this.document, parent, xmlHeader, attributes, declaration, propertyType, unsafeCode, generated); elementReference.Target = property; if (this.IsBodiedExpression()) { this.ParseStatementContainer(property, true, unsafeCode); } else { // Parse the body of the property. this.ParseElementContainer(property, elementReference, null, unsafeCode); // Check if current property has initializer (C#6). Symbol nextSymbol = this.GetNextSymbol(SkipSymbols.WhiteSpace, elementReference, true); if (nextSymbol != null && nextSymbol.SymbolType == SymbolType.Equals) { // Get all of the variable declarators. IList<VariableDeclaratorExpression> declarators = this.ParsePropertyDeclarators(elementReference, unsafeCode, propertyType, propertyNameNode); if (declarators.Count == 0) { throw this.CreateSyntaxException(); } VariableDeclarationExpression declarationExpression = new VariableDeclarationExpression( new CsTokenList(this.tokens, declarators[0].Tokens.First, this.tokens.Last), new LiteralExpression(this.tokens, propertyTypeNode), declarators); // Get the trailing semicolon. this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, elementReference)); // Create the variable declaration statement and add it to the field. property.VariableDeclarationStatement = new VariableDeclarationStatement( new CsTokenList(this.tokens, declarators[0].Tokens.First, this.tokens.Last), false, declarationExpression); } } return property; }
/// <summary> /// Parses and returns a field. /// </summary> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="elementReference"> /// A reference to the element being created. /// </param> /// <param name="unsafeCode"> /// Indicates whether the code is marked as unsafe. /// </param> /// <param name="generated"> /// Indicates whether the code is marked as generated code. /// </param> /// <param name="xmlHeader"> /// The element's documentation header. /// </param> /// <param name="attributes"> /// The attributes on the element. /// </param> /// <returns> /// Returns the element. /// </returns> private Field ParseField( CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes) { Param.AssertNotNull(parent, "parent"); Param.AssertNotNull(elementReference, "elementReference"); Param.Ignore(unsafeCode); Param.Ignore(generated); Param.Ignore(xmlHeader); Param.Ignore(attributes); Node<CsToken> previousTokenNode = this.tokens.Last; // Get the modifiers and access. AccessModifierType accessModifier = AccessModifierType.Private; Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, FieldModifiers); unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe); // Get the field type. TypeToken fieldType = this.GetTypeToken(elementReference, unsafeCode, true); Node<CsToken> fieldTypeNode = this.tokens.InsertLast(fieldType); // Get all of the variable declarators. IList<VariableDeclaratorExpression> declarators = this.ParseFieldDeclarators(elementReference, unsafeCode, fieldType); if (declarators.Count == 0) { throw this.CreateSyntaxException(); } VariableDeclarationExpression declarationExpression = new VariableDeclarationExpression( new CsTokenList(this.tokens, declarators[0].Tokens.First, this.tokens.Last), new LiteralExpression(this.tokens, fieldTypeNode), declarators); // Create the field. Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next; CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last); Declaration declaration = new Declaration(declarationTokens, declarators[0].Identifier.Text, ElementType.Field, accessModifier, modifiers); Field field = new Field(this.document, parent, xmlHeader, attributes, declaration, fieldType, unsafeCode, generated); elementReference.Target = field; // Get the trailing semicolon. this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, elementReference)); // Create the variable declaration statement and add it to the field. field.VariableDeclarationStatement = new VariableDeclarationStatement( new CsTokenList(this.tokens, declarators[0].Tokens.First, this.tokens.Last), field.Const, declarationExpression); return field; }
/// <summary> /// The save. /// </summary> /// <param name="variableDeclarationExpression"> /// The variable declaration expression. /// </param> private void Save(VariableDeclarationExpression variableDeclarationExpression) { var savingOptions = this.saveVariablesMode != SaveVariablesMode.DoNotSaveInitializers ? SavingOptions.None : SavingOptions.UseFullyQualifiedNames; this.Save(variableDeclarationExpression.Type, this.cppWriter, savingOptions); if (this.saveVariablesMode == SaveVariablesMode.AppendRightReferene) { this.cppWriter.Write("&&"); } this.cppWriter.Write(' '); this.Save(variableDeclarationExpression.Declarators); }