| File: VisualBasicParserUtilities.cs | Web Access |
| Project: src\msbuild\src\Tasks\Microsoft.Build.Tasks.csproj (Microsoft.Build.Tasks.Core) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.IO; using System.Text; using Microsoft.Build.Shared.LanguageParser; #nullable disable namespace Microsoft.Build.Tasks { /// <summary> /// Specific-purpose utility functions for parsing VB. /// </summary> internal static class VisualBasicParserUtilities { /// <summary> /// Parse a VB file and get the first class name, fully qualified with namespace. /// </summary> /// <param name="binaryStream"></param> /// <returns></returns> internal static ExtractedClassName GetFirstClassNameFullyQualified(Stream binaryStream) { try { VisualBasicTokenizer tokens = new VisualBasicTokenizer(binaryStream, /* forceANSI */ false); return Extract(tokens); } catch (DecoderFallbackException) { // There was no BOM and there are non UTF8 sequences. Fall back to ANSI. VisualBasicTokenizer tokens = new VisualBasicTokenizer(binaryStream, /* forceANSI */ true); return Extract(tokens); } } /// <summary> /// Extract the class name. /// </summary> /// <param name="tokens"></param> /// <returns></returns> private static ExtractedClassName Extract(VisualBasicTokenizer tokens) { var state = new ParseState(); var result = new ExtractedClassName(); foreach (Token t in tokens) { // Search first for keywords that we care about. if (t is KeywordToken) { state.Reset(); if (t.EqualsIgnoreCase("namespace")) { state.ResolvingNamespace = true; if (state.InsideConditionalDirective) { result.IsInsideConditionalBlock = true; } } else if (t.EqualsIgnoreCase("class")) { state.ResolvingClass = true; if (state.InsideConditionalDirective) { result.IsInsideConditionalBlock = true; } } else if (t.EqualsIgnoreCase("end")) { state.PopNamespacePart(); } } else if (t is VisualBasicTokenizer.LineTerminatorToken) { if (state.ResolvingNamespace) { state.PushNamespacePart(state.Namespace); } state.Reset(); } else if (t is VisualBasicTokenizer.SeparatorToken) { if (state.ResolvingNamespace) { if (t.InnerText == ".") { state.Namespace += "."; } } } else if (t is IdentifierToken) { // If we're resolving a namespace, then this is part of the namespace. if (state.ResolvingNamespace) { state.Namespace += t.InnerText; } // If we're resolving a class, then we're done. We found the class name. else if (state.ResolvingClass) { // We're done. result.Name = state.ComposeQualifiedClassName(t.InnerText); return result; } } else if (t is OpenConditionalDirectiveToken) { state.OpenConditionalDirective(); } else if (t is CloseConditionalDirectiveToken) { state.CloseConditionalDirective(); } } return result; } } }