예제 #1
0
        /// <summary>
        /// Gets the base name and generic symbols for a type token.
        /// </summary>
        /// <param name="typeTokenProxy">Proxy object for the TypeToken being created.</param>
        /// <param name="startIndex">The start index within the symbol list.</param>
        /// <param name="unsafeCode">Indicates whether the type is within a block of unsafe code.</param>
        private void GetTypeTokenBaseName(ref CodeUnitProxy typeTokenProxy, ref int startIndex, bool unsafeCode)
        {
            Param.AssertNotNull(typeTokenProxy, "typeTokenProxy");
            Param.AssertGreaterThanOrEqualToZero(startIndex, "startIndex");
            Param.Ignore(unsafeCode);

            Symbol symbol = this.symbols.Peek(startIndex);

            // First get the full name of the type.
            int index = -1;
            while (true)
            {
                this.GatherNonTokenSymbols(typeTokenProxy, ref startIndex);
                symbol = this.symbols.Peek(startIndex);

                var innerTypeTokenProxy = new CodeUnitProxy(this.document);

                // Add the next word. The type of the next word must either be an unknown
                // word type, which will be the name of the next item in the type, or else
                // it must be the 'this' keyword. This is used when implementing an explicit
                // interface member which is an indexer.
                if (symbol.SymbolType == SymbolType.Other || symbol.SymbolType == SymbolType.This)
                {
                    innerTypeTokenProxy.Children.Add(new LiteralToken(this.document, symbol.Text, symbol.Location, this.symbols.Generated));
                }
                else
                {
                    throw new SyntaxException(this.document, symbol.LineNumber);
                }

                ++startIndex;

                // Look at the type of the next non-whitespace character.
                index = this.GetNextCodeSymbolIndex(startIndex);
                if (index == -1)
                {
                    break;
                }

                // If the next character is an opening generic bracket, get the generic.
                GenericTypeToken generic = null;

                symbol = this.symbols.Peek(index);
                if (symbol.SymbolType == SymbolType.LessThan)
                {
                    int end;
                    if (this.GetGenericArgumentList(innerTypeTokenProxy, unsafeCode, null, startIndex, out end))
                    {
                        // Create a new GenericTypeToken which represents this generic type.
                        generic = new GenericTypeToken(innerTypeTokenProxy);
                        typeTokenProxy.Children.Add(generic);

                        // Advance the symbol index.
                        startIndex = end + 1;

                        // Look at the type of the next non-whitespace character.
                        index = this.GetNextCodeSymbolIndex(startIndex);
                        if (index == -1)
                        {
                            break;
                        }
                    }
                }

                if (generic == null)
                {
                    // Since this is not a generic type, it is just a regular type token. Create and add this type token.
                    TypeToken innerType = new TypeToken(innerTypeTokenProxy);
                    typeTokenProxy.Children.Add(innerType);
                }

                // If the next character is not a dot or a qualified alias, break now.
                symbol = this.symbols.Peek(index);
                if (symbol.SymbolType != SymbolType.Dot && symbol.SymbolType != SymbolType.QualifiedAlias)
                {
                    break;
                }

                // Add any whitspace.
                this.GatherNonTokenSymbols(typeTokenProxy, ref startIndex);
                symbol = this.symbols.Peek(startIndex);

                // Add the dot or qualified alias.
                if (symbol.SymbolType == SymbolType.Dot)
                {
                    typeTokenProxy.Children.Add(new MemberAccessOperator(this.document, symbol.Text, symbol.Location, this.symbols.Generated));
                }
                else
                {
                    CsLanguageService.Debug.Assert(symbol.SymbolType == SymbolType.QualifiedAlias, "Expected a qualified alias keyword");
                    typeTokenProxy.Children.Add(new QualifiedAliasOperator(this.document, symbol.Text, symbol.Location, this.symbols.Generated));
                }

                // Get the next symbol.
                symbol = this.symbols.Peek(++startIndex);
            }
        }
예제 #2
0
        /// <summary>
        /// Reads a generic token from the document.
        /// </summary>
        /// <param name="unsafeCode">Indicates whether the code is marked as unsafe.</param>
        /// <param name="startIndex">The first index of the generic.</param>
        /// <param name="lastIndex">Returns the last index of the generic.</param>
        /// <returns>Returns the generic token, or null if the symbol manager is not sitting on a generic.</returns>
        /// <remarks>This should only be called by GetGenericToken.</remarks>
        private GenericTypeToken GetGenericTokenAux(bool unsafeCode, int startIndex, out int lastIndex)
        {
            Param.Ignore(unsafeCode);
            Param.AssertGreaterThanOrEqualToZero(startIndex, "startIndex");

            lastIndex = -1;

            // The reference to the generic token.
            var genericTokenProxy = new CodeUnitProxy(this.document);

            // Get the first symbol. This should be an unknown word type.
            Symbol firstSymbol = this.symbols.Peek(startIndex);
            CsLanguageService.Debug.Assert(firstSymbol != null && firstSymbol.SymbolType == SymbolType.Other, "Expected a text symbol");

            // This will hold the generic type if we create one.
            GenericTypeToken generic = null;

            // Create a token for the name.
            var name = new LiteralToken(this.document, firstSymbol.Text, firstSymbol.Location, this.symbols.Generated);

            // Get the argument list. This will return null if this is not a generic.
            if (this.GetGenericArgumentList(genericTokenProxy, unsafeCode, name, startIndex + 1, out lastIndex))
            {
                generic = new GenericTypeToken(genericTokenProxy);
            }

            return generic;
        }