/// <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); } }
/// <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; }