From 70fe37f4dc39f284930872f8f6a863f7c1ed89ef Mon Sep 17 00:00:00 2001 From: DoctorKrolic Date: Mon, 2 Jun 2025 18:59:52 +0300 Subject: [PATCH 1/8] Save parse options in a syntax tree in the result of `SyntaxFactory.Parse*` methods --- eng/config/BannedSymbols.txt | 4 +- .../Portable/Syntax/CSharpSyntaxNode.cs | 6 +- .../Portable/Syntax/CSharpSyntaxTree.cs | 8 +- .../CSharp/Portable/Syntax/SyntaxFactory.cs | 127 +++++++++++++++--- .../Semantic/Semantics/SyntaxTreeRootTests.cs | 11 +- .../Test/Syntax/Syntax/SyntaxFactoryTests.cs | 38 +++++- .../Portable/Syntax/SyntaxNodeFactories.vb | 29 +++- .../Portable/Syntax/VisualBasicSyntaxNode.vb | 8 +- .../Portable/Syntax/VisualBasicSyntaxTree.vb | 6 +- .../Semantic/Semantics/SyntaxTreeRootTests.vb | 3 +- .../Test/Syntax/Syntax/SyntaxFactoryTests.vb | 11 ++ 11 files changed, 194 insertions(+), 57 deletions(-) diff --git a/eng/config/BannedSymbols.txt b/eng/config/BannedSymbols.txt index 8558e121b5dc2..9c707886b0b18 100644 --- a/eng/config/BannedSymbols.txt +++ b/eng/config/BannedSymbols.txt @@ -47,14 +47,14 @@ M:Microsoft.CodeAnalysis.Editing.SyntaxEditor.#ctor(Microsoft.CodeAnalysis.Synta M:Microsoft.CodeAnalysis.FileTextLoader.#ctor(System.String,System.Text.Encoding); use WorkspaceFileTextLoader that calls on ITextFactoryService to create SourceText M:Microsoft.CodeAnalysis.CSharp.SyntaxFactory.SyntaxTree(Microsoft.CodeAnalysis.SyntaxNode,Microsoft.CodeAnalysis.ParseOptions,System.String,System.Text.Encoding); Use CSharpSyntaxTree sublass that takes checksum algorithm M:Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParseSyntaxTree(System.String,Microsoft.CodeAnalysis.ParseOptions,System.String,System.Text.Encoding,System.Threading.CancellationToken); Use CSharpSyntaxTree sublass that takes checksum algorithm -M:Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.CreateWithoutClone(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode); Use CSharpSyntaxTree sublass that takes checksum algorithm +M:Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.CreateWithoutClone(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode,Microsoft.CodeAnalysis.CSharp.CSharpParseOptions); Use CSharpSyntaxTree sublass that takes checksum algorithm M:Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.Create(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode, Microsoft.CodeAnalysis.CSharp.CSharpParseOptions options, System.String path, System.Text.Encoding encoding); Use CSharpSyntaxTree sublass that takes checksum algorithm M:Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.ParseText(System.String,Microsoft.CodeAnalysis.CSharp.CSharpParseOptions,System.String,System.Text.Encoding,System.Threading.CancellationToken); Use API that takes SourceText M:Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.ParseText(System.String,Microsoft.CodeAnalysis.CSharp.CSharpParseOptions,System.String,System.Text.Encoding,System.Collections.Immutable.ImmutableDictionary{System.String,Microsoft.CodeAnalysis.ReportDiagnostic},System.Nullable{System.Boolean},System.Threading.CancellationToken); Use API that takes SourceText M:Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.SyntaxTree(Microsoft.CodeAnalysis.SyntaxNode,Microsoft.CodeAnalysis.ParseOptions,System.String,System.Text.Encoding); Use VisualBasicSyntaxTree sublass that takes checksum algorithm M:Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseSyntaxTree(System.String,Microsoft.CodeAnalysis.ParseOptions,System.String,System.Text.Encoding,System.Threading.CancellationToken); Use overload with SourceText M:Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseSyntaxTree(System.String,Microsoft.CodeAnalysis.ParseOptions,System.String,System.Text.Encoding,System.Collections.Immutable.ImmutableDictionary{System.String,Microsoft.CodeAnalysis.ReportDiagnostic},System.Threading.CancellationToken); Use overload with SourceText -M:Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxTree.CreateWithoutClone(Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxNode); Use VisualBasicSyntaxTree sublass that takes checksum algorithm +M:Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxTree.CreateWithoutClone(Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxNode,Microsoft.CodeAnalysis.VisualBasic.VisualBasicParseOptions); Use VisualBasicSyntaxTree sublass that takes checksum algorithm M:Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxTree.Create(Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxNode,Microsoft.CodeAnalysis.VisualBasic.VisualBasicParseOptions,System.String,System.Text.Encoding,System.Collections.Immutable.ImmutableDictionary{System.String,Microsoft.CodeAnalysis.ReportDiagnostic}); Use VisualBasicSyntaxTree sublass that takes checksum algorithm M:Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxTree.Create(Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxNode,Microsoft.CodeAnalysis.VisualBasic.VisualBasicParseOptions,System.String,System.Text.Encoding); Use VisualBasicSyntaxTree sublass that takes checksum algorithm M:Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxTree.ParseText(System.String,Microsoft.CodeAnalysis.VisualBasic.VisualBasicParseOptions,System.String,System.Text.Encoding,System.Collections.Immutable.ImmutableDictionary{System.String,Microsoft.CodeAnalysis.ReportDiagnostic},System.Threading.CancellationToken); Use overload with SourceText diff --git a/src/Compilers/CSharp/Portable/Syntax/CSharpSyntaxNode.cs b/src/Compilers/CSharp/Portable/Syntax/CSharpSyntaxNode.cs index 3b09234ad0c18..3f27691d9e952 100644 --- a/src/Compilers/CSharp/Portable/Syntax/CSharpSyntaxNode.cs +++ b/src/Compilers/CSharp/Portable/Syntax/CSharpSyntaxNode.cs @@ -9,9 +9,7 @@ using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.PooledObjects; -using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp { @@ -73,8 +71,8 @@ private static SyntaxTree ComputeSyntaxTree(CSharpSyntaxNode node) if (parent == null) { // set the tree on the root node atomically -#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site only) - Interlocked.CompareExchange(ref node._syntaxTree, CSharpSyntaxTree.CreateWithoutClone(node), null); +#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) + Interlocked.CompareExchange(ref node._syntaxTree, CSharpSyntaxTree.CreateWithoutClone(node, CSharpParseOptions.Default), null); #pragma warning restore tree = node._syntaxTree; break; diff --git a/src/Compilers/CSharp/Portable/Syntax/CSharpSyntaxTree.cs b/src/Compilers/CSharp/Portable/Syntax/CSharpSyntaxTree.cs index 6cf328da50821..103c8509f5c28 100644 --- a/src/Compilers/CSharp/Portable/Syntax/CSharpSyntaxTree.cs +++ b/src/Compilers/CSharp/Portable/Syntax/CSharpSyntaxTree.cs @@ -8,8 +8,6 @@ using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -390,10 +388,10 @@ internal static SyntaxTree CreateForDebugger(CSharpSyntaxNode root, SourceText t /// Internal helper for class to create a new syntax tree rooted at the given root node. /// This method does not create a clone of the given root, but instead preserves it's reference identity. /// - /// NOTE: This method is only intended to be used from property. + /// NOTE: This method is only intended to be used from property and SyntaxFactory.Parse* methods. /// NOTE: Do not use this method elsewhere, instead use method for creating a syntax tree. /// - internal static SyntaxTree CreateWithoutClone(CSharpSyntaxNode root) + internal static SyntaxTree CreateWithoutClone(CSharpSyntaxNode root, CSharpParseOptions options) { Debug.Assert(root != null); @@ -402,7 +400,7 @@ internal static SyntaxTree CreateWithoutClone(CSharpSyntaxNode root) encodingOpt: null, checksumAlgorithm: SourceHashAlgorithm.Sha1, path: "", - options: CSharpParseOptions.Default, + options: options, root: root, directives: default, diagnosticOptions: null, diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs index a1cbe33a1b30f..0f68712d314a4 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs @@ -1713,12 +1713,21 @@ public static TypeSyntax ParseTypeName(string text, int offset, bool consumeFull /// public static TypeSyntax ParseTypeName(string text, int offset = 0, ParseOptions? options = null, bool consumeFullText = true) { - using (var lexer = MakeLexer(text, offset, (CSharpParseOptions?)options)) + var cSharpOptions = (CSharpParseOptions?)options; + using (var lexer = MakeLexer(text, offset, cSharpOptions)) using (var parser = MakeParser(lexer)) { var node = parser.ParseTypeName(); if (consumeFullText) node = parser.ConsumeUnexpectedTokens(node); - return (TypeSyntax)node.CreateRed(); + var red = (TypeSyntax)node.CreateRed(); + if (cSharpOptions is not null) + { + Debug.Assert(red._syntaxTree is null); +#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) + red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, cSharpOptions); +#pragma warning restore + } + return red; } } @@ -1732,12 +1741,21 @@ public static TypeSyntax ParseTypeName(string text, int offset = 0, ParseOptions /// True if extra tokens in the input should be treated as an error public static ExpressionSyntax ParseExpression(string text, int offset = 0, ParseOptions? options = null, bool consumeFullText = true) { - using (var lexer = MakeLexer(text, offset, (CSharpParseOptions?)options)) + var cSharpOptions = (CSharpParseOptions?)options; + using (var lexer = MakeLexer(text, offset, cSharpOptions)) using (var parser = MakeParser(lexer)) { var node = parser.ParseExpression(); if (consumeFullText) node = parser.ConsumeUnexpectedTokens(node); - return (ExpressionSyntax)node.CreateRed(); + var red = (ExpressionSyntax)node.CreateRed(); + if (cSharpOptions is not null) + { + Debug.Assert(red._syntaxTree is null); +#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) + red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, cSharpOptions); +#pragma warning restore + } + return red; } } @@ -1751,12 +1769,21 @@ public static ExpressionSyntax ParseExpression(string text, int offset = 0, Pars /// True if extra tokens in the input should be treated as an error public static StatementSyntax ParseStatement(string text, int offset = 0, ParseOptions? options = null, bool consumeFullText = true) { - using (var lexer = MakeLexer(text, offset, (CSharpParseOptions?)options)) + var cSharpOptions = (CSharpParseOptions?)options; + using (var lexer = MakeLexer(text, offset, cSharpOptions)) using (var parser = MakeParser(lexer)) { var node = parser.ParseStatement(); if (consumeFullText) node = parser.ConsumeUnexpectedTokens(node); - return (StatementSyntax)node.CreateRed(); + var red = (StatementSyntax)node.CreateRed(); + if (cSharpOptions is not null) + { + Debug.Assert(red._syntaxTree is null); +#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) + red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, cSharpOptions); +#pragma warning restore + } + return red; } } @@ -1771,7 +1798,8 @@ public static StatementSyntax ParseStatement(string text, int offset = 0, ParseO /// True if extra tokens in the input following a declaration should be treated as an error public static MemberDeclarationSyntax? ParseMemberDeclaration(string text, int offset = 0, ParseOptions? options = null, bool consumeFullText = true) { - using (var lexer = MakeLexer(text, offset, (CSharpParseOptions?)options)) + var cSharpOptions = (CSharpParseOptions?)options; + using (var lexer = MakeLexer(text, offset, cSharpOptions)) using (var parser = MakeParser(lexer)) { var node = parser.ParseMemberDeclaration(); @@ -1780,7 +1808,15 @@ public static StatementSyntax ParseStatement(string text, int offset = 0, ParseO return null; } - return (MemberDeclarationSyntax)(consumeFullText ? parser.ConsumeUnexpectedTokens(node) : node).CreateRed(); + var red = (MemberDeclarationSyntax)(consumeFullText ? parser.ConsumeUnexpectedTokens(node) : node).CreateRed(); + if (cSharpOptions is not null) + { + Debug.Assert(red._syntaxTree is null); +#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) + red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, cSharpOptions); +#pragma warning restore + } + return red; } } @@ -1800,7 +1836,15 @@ public static CompilationUnitSyntax ParseCompilationUnit(string text, int offset using (var parser = MakeParser(lexer)) { var node = parser.ParseCompilationUnit(); - return (CompilationUnitSyntax)node.CreateRed(); + var red = (CompilationUnitSyntax)node.CreateRed(); + if (options is not null) + { + Debug.Assert(red._syntaxTree is null); +#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) + red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, options); +#pragma warning restore + } + return red; } } @@ -1814,12 +1858,21 @@ public static CompilationUnitSyntax ParseCompilationUnit(string text, int offset /// True if extra tokens in the input should be treated as an error public static ParameterListSyntax ParseParameterList(string text, int offset = 0, ParseOptions? options = null, bool consumeFullText = true) { - using (var lexer = MakeLexer(text, offset, (CSharpParseOptions?)options)) + var cSharpOptions = (CSharpParseOptions?)options; + using (var lexer = MakeLexer(text, offset, cSharpOptions)) using (var parser = MakeParser(lexer)) { var node = parser.ParseParenthesizedParameterList(forExtension: false); if (consumeFullText) node = parser.ConsumeUnexpectedTokens(node); - return (ParameterListSyntax)node.CreateRed(); + var red = (ParameterListSyntax)node.CreateRed(); + if (cSharpOptions is not null) + { + Debug.Assert(red._syntaxTree is null); +#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) + red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, cSharpOptions); +#pragma warning restore + } + return red; } } @@ -1833,12 +1886,21 @@ public static ParameterListSyntax ParseParameterList(string text, int offset = 0 /// True if extra tokens in the input should be treated as an error public static BracketedParameterListSyntax ParseBracketedParameterList(string text, int offset = 0, ParseOptions? options = null, bool consumeFullText = true) { - using (var lexer = MakeLexer(text, offset, (CSharpParseOptions?)options)) + var cSharpOptions = (CSharpParseOptions?)options; + using (var lexer = MakeLexer(text, offset, cSharpOptions)) using (var parser = MakeParser(lexer)) { var node = parser.ParseBracketedParameterList(); if (consumeFullText) node = parser.ConsumeUnexpectedTokens(node); - return (BracketedParameterListSyntax)node.CreateRed(); + var red = (BracketedParameterListSyntax)node.CreateRed(); + if (cSharpOptions is not null) + { + Debug.Assert(red._syntaxTree is null); +#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) + red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, cSharpOptions); +#pragma warning restore + } + return red; } } @@ -1852,12 +1914,21 @@ public static BracketedParameterListSyntax ParseBracketedParameterList(string te /// True if extra tokens in the input should be treated as an error public static ArgumentListSyntax ParseArgumentList(string text, int offset = 0, ParseOptions? options = null, bool consumeFullText = true) { - using (var lexer = MakeLexer(text, offset, (CSharpParseOptions?)options)) + var cSharpOptions = (CSharpParseOptions?)options; + using (var lexer = MakeLexer(text, offset, cSharpOptions)) using (var parser = MakeParser(lexer)) { var node = parser.ParseParenthesizedArgumentList(); if (consumeFullText) node = parser.ConsumeUnexpectedTokens(node); - return (ArgumentListSyntax)node.CreateRed(); + var red = (ArgumentListSyntax)node.CreateRed(); + if (cSharpOptions is not null) + { + Debug.Assert(red._syntaxTree is null); +#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) + red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, cSharpOptions); +#pragma warning restore + } + return red; } } @@ -1871,12 +1942,21 @@ public static ArgumentListSyntax ParseArgumentList(string text, int offset = 0, /// True if extra tokens in the input should be treated as an error public static BracketedArgumentListSyntax ParseBracketedArgumentList(string text, int offset = 0, ParseOptions? options = null, bool consumeFullText = true) { - using (var lexer = MakeLexer(text, offset, (CSharpParseOptions?)options)) + var cSharpOptions = (CSharpParseOptions?)options; + using (var lexer = MakeLexer(text, offset, cSharpOptions)) using (var parser = MakeParser(lexer)) { var node = parser.ParseBracketedArgumentList(); if (consumeFullText) node = parser.ConsumeUnexpectedTokens(node); - return (BracketedArgumentListSyntax)node.CreateRed(); + var red = (BracketedArgumentListSyntax)node.CreateRed(); + if (cSharpOptions is not null) + { + Debug.Assert(red._syntaxTree is null); +#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) + red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, cSharpOptions); +#pragma warning restore + } + return red; } } @@ -1890,7 +1970,8 @@ public static BracketedArgumentListSyntax ParseBracketedArgumentList(string text /// True if extra tokens in the input should be treated as an error public static AttributeArgumentListSyntax? ParseAttributeArgumentList(string text, int offset = 0, ParseOptions? options = null, bool consumeFullText = true) { - using var lexer = MakeLexer(text, offset, (CSharpParseOptions?)options); + var cSharpOptions = (CSharpParseOptions?)options; + using var lexer = MakeLexer(text, offset, cSharpOptions); using var parser = MakeParser(lexer); var node = parser.ParseAttributeArgumentList() ?? new InternalSyntax.AttributeArgumentListSyntax( @@ -1902,7 +1983,15 @@ public static BracketedArgumentListSyntax ParseBracketedArgumentList(string text annotations: null); if (consumeFullText) node = parser.ConsumeUnexpectedTokens(node); - return (AttributeArgumentListSyntax)node.CreateRed(); + var red = (AttributeArgumentListSyntax)node.CreateRed(); + if (cSharpOptions is not null) + { + Debug.Assert(red._syntaxTree is null); +#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) + red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, cSharpOptions); +#pragma warning restore + } + return red; } /// diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/SyntaxTreeRootTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/SyntaxTreeRootTests.cs index a5bdfcbdb0f5a..43b0b048eb0f2 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/SyntaxTreeRootTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/SyntaxTreeRootTests.cs @@ -4,17 +4,12 @@ #nullable disable -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System; -using System.Collections.Generic; using System.Linq; using System.Reflection; -using System.Text; -using System.Threading.Tasks; -using Xunit; -using Microsoft.CodeAnalysis.CSharp.Symbols; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Xunit; namespace Microsoft.CodeAnalysis.CSharp.Semantic.UnitTests.Semantics { @@ -32,7 +27,7 @@ public void SyntaxTreeCreateAcceptsAnySyntaxNode() public void SyntaxTreeCreateWithoutCloneAcceptsAnySyntaxNode() { var node = SyntaxFactory.CatchClause(SyntaxFactory.CatchDeclaration(SyntaxFactory.ParseTypeName(typeof(InvalidOperationException).Name)), null, SyntaxFactory.Block()); - var tree = CSharpSyntaxTree.CreateWithoutClone(node); + var tree = CSharpSyntaxTree.CreateWithoutClone(node, CSharpParseOptions.Default); CheckTree(tree); } diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxFactoryTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxFactoryTests.cs index 49178bb9c5a9e..bc2e73ce0a952 100644 --- a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxFactoryTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxFactoryTests.cs @@ -9,11 +9,11 @@ using System.Linq; using System.Text; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; using InternalSyntax = Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax; -using Microsoft.CodeAnalysis.CSharp.Test.Utilities; namespace Microsoft.CodeAnalysis.CSharp.UnitTests { @@ -678,5 +678,41 @@ public void TestParseNameWithOptions() // unsafe class C { delegate* x; } Diagnostic(ErrorCode.WRN_UnreferencedField, "x").WithArguments("C.x").WithLocation(1, 34)); } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/78510")] + public void TestParseMethodsKeepParseOptionsInTheTree() + { + var parseOptions = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.Latest); + + var argList = SyntaxFactory.ParseArgumentList("", options: parseOptions); + Assert.Same(parseOptions, argList.SyntaxTree.Options); + + var attrArgList = SyntaxFactory.ParseAttributeArgumentList("", options: parseOptions); + Assert.Same(parseOptions, attrArgList.SyntaxTree.Options); + + var bracketedArgList = SyntaxFactory.ParseBracketedArgumentList("", options: parseOptions); + Assert.Same(parseOptions, bracketedArgList.SyntaxTree.Options); + + var bracketedParamList = SyntaxFactory.ParseBracketedParameterList("", options: parseOptions); + Assert.Same(parseOptions, bracketedParamList.SyntaxTree.Options); + + var compUnit = SyntaxFactory.ParseCompilationUnit("", options: parseOptions); + Assert.Same(parseOptions, compUnit.SyntaxTree.Options); + + var expr = SyntaxFactory.ParseExpression("", options: parseOptions); + Assert.Same(parseOptions, expr.SyntaxTree.Options); + + var memberDecl = SyntaxFactory.ParseMemberDeclaration("public", options: parseOptions); + Assert.Same(parseOptions, memberDecl.SyntaxTree.Options); + + var paramList = SyntaxFactory.ParseParameterList("", options: parseOptions); + Assert.Same(parseOptions, paramList.SyntaxTree.Options); + + var statement = SyntaxFactory.ParseStatement("", options: parseOptions); + Assert.Same(parseOptions, statement.SyntaxTree.Options); + + var typeName = SyntaxFactory.ParseTypeName("", options: parseOptions); + Assert.Same(parseOptions, typeName.SyntaxTree.Options); + } } } diff --git a/src/Compilers/VisualBasic/Portable/Syntax/SyntaxNodeFactories.vb b/src/Compilers/VisualBasic/Portable/Syntax/SyntaxNodeFactories.vb index 78a47f4eb237c..e7aefacca0caf 100644 --- a/src/Compilers/VisualBasic/Portable/Syntax/SyntaxNodeFactories.vb +++ b/src/Compilers/VisualBasic/Portable/Syntax/SyntaxNodeFactories.vb @@ -7,15 +7,15 @@ ' code-generated into SyntaxNodes.vb, but some are easier to hand-write. '----------------------------------------------------------------------------------------------------------- -Imports System.Threading +Imports System.Collections.Immutable +Imports System.ComponentModel Imports System.Text +Imports System.Threading +Imports Microsoft.CodeAnalysis.Syntax Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports Microsoft.CodeAnalysis.VisualBasic.SyntaxFacts Imports InternalSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax -Imports Microsoft.CodeAnalysis.Syntax -Imports System.Collections.Immutable -Imports System.ComponentModel Namespace Microsoft.CodeAnalysis.VisualBasic @@ -196,10 +196,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ''' The input string ''' The starting offset in the string Public Shared Function ParseTypeName(text As String, Optional offset As Integer = 0, Optional options As ParseOptions = Nothing, Optional consumeFullText As Boolean = True) As TypeSyntax - Using p = New InternalSyntax.Parser(MakeSourceText(text, offset), If(DirectCast(options, VisualBasicParseOptions), VisualBasicParseOptions.Default)) + Dim vbOptions As VisualBasicParseOptions = DirectCast(options, VisualBasicParseOptions) + Using p = New InternalSyntax.Parser(MakeSourceText(text, offset), If(vbOptions, VisualBasicParseOptions.Default)) p.GetNextToken() Dim node = p.ParseGeneralType() - Return DirectCast(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node).CreateRed(Nothing, 0), TypeSyntax) + Dim red As TypeSyntax = DirectCast(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node).CreateRed(Nothing, 0), TypeSyntax) + If vbOptions IsNot Nothing Then + Debug.Assert(red._syntaxTree Is Nothing) +#Disable Warning RS0030 ' Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) + red._syntaxTree = VisualBasicSyntaxTree.CreateWithoutClone(red, vbOptions) +#Enable Warning RS0030 + End If + Return red End Using End Function @@ -246,7 +254,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ''' The starting offset in the string Public Shared Function ParseCompilationUnit(text As String, Optional offset As Integer = 0, Optional options As VisualBasicParseOptions = Nothing) As CompilationUnitSyntax Using p = New InternalSyntax.Parser(MakeSourceText(text, offset), If(options, VisualBasicParseOptions.Default)) - Return DirectCast(p.ParseCompilationUnit().CreateRed(Nothing, 0), CompilationUnitSyntax) + Dim red As CompilationUnitSyntax = DirectCast(p.ParseCompilationUnit().CreateRed(Nothing, 0), CompilationUnitSyntax) + If options IsNot Nothing Then + Debug.Assert(red._syntaxTree Is Nothing) +#Disable Warning RS0030 ' Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) + red._syntaxTree = VisualBasicSyntaxTree.CreateWithoutClone(red, options) +#Enable Warning RS0030 + End If + Return red End Using End Function diff --git a/src/Compilers/VisualBasic/Portable/Syntax/VisualBasicSyntaxNode.vb b/src/Compilers/VisualBasic/Portable/Syntax/VisualBasicSyntaxNode.vb index ae5c84381bf04..3d8e5229b22de 100644 --- a/src/Compilers/VisualBasic/Portable/Syntax/VisualBasicSyntaxNode.vb +++ b/src/Compilers/VisualBasic/Portable/Syntax/VisualBasicSyntaxNode.vb @@ -2,12 +2,8 @@ ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. -Imports System.Collections.Immutable Imports System.Collections.ObjectModel -Imports System.ComponentModel -Imports System.Reflection Imports System.Threading -Imports Microsoft.CodeAnalysis.ErrorReporting Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.Symbols @@ -70,8 +66,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic If tree Is Nothing Then Debug.Assert(rootCandidate IsNot Nothing) -#Disable Warning RS0030 ' Do not use banned APIs (CreateWithoutClone is intended to be used from this call site only) - tree = VisualBasicSyntaxTree.CreateWithoutClone(DirectCast(rootCandidate, VisualBasicSyntaxNode)) +#Disable Warning RS0030 ' Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) + tree = VisualBasicSyntaxTree.CreateWithoutClone(DirectCast(rootCandidate, VisualBasicSyntaxNode), VisualBasicParseOptions.Default) #Enable Warning RS0030 End If diff --git a/src/Compilers/VisualBasic/Portable/Syntax/VisualBasicSyntaxTree.vb b/src/Compilers/VisualBasic/Portable/Syntax/VisualBasicSyntaxTree.vb index 04ed895f802ff..2f1d0ef1c6f64 100644 --- a/src/Compilers/VisualBasic/Portable/Syntax/VisualBasicSyntaxTree.vb +++ b/src/Compilers/VisualBasic/Portable/Syntax/VisualBasicSyntaxTree.vb @@ -210,10 +210,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ''' Internal helper for class to create a new syntax tree rooted at the given root node. ''' This method does not create a clone of the given root, but instead preserves its reference identity. ''' - ''' NOTE: This method is only intended to be used from property. + ''' NOTE: This method is only intended to be used from property and SyntaxFactory.Parse* methods. ''' NOTE: Do not use this method elsewhere, instead use method for creating a syntax tree. ''' - Friend Shared Function CreateWithoutClone(root As VisualBasicSyntaxNode) As SyntaxTree + Friend Shared Function CreateWithoutClone(root As VisualBasicSyntaxNode, options As VisualBasicParseOptions) As SyntaxTree Debug.Assert(root IsNot Nothing) Return New ParsedSyntaxTree( @@ -221,7 +221,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic path:="", encodingOpt:=Nothing, checksumAlgorithm:=SourceHashAlgorithm.Sha1, - options:=VisualBasicParseOptions.Default, + options:=options, syntaxRoot:=root, isMyTemplate:=False, diagnosticOptions:=Nothing, diff --git a/src/Compilers/VisualBasic/Test/Semantic/Semantics/SyntaxTreeRootTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Semantics/SyntaxTreeRootTests.vb index 76cdf5c630995..7024c5bc413f6 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Semantics/SyntaxTreeRootTests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Semantics/SyntaxTreeRootTests.vb @@ -3,7 +3,6 @@ ' See the LICENSE file in the project root for more information. Imports System.Reflection -Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic Imports Microsoft.CodeAnalysis.VisualBasic.Syntax @@ -19,7 +18,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics Public Sub SyntaxTreeCreateWithoutCloneAcceptsAnySyntaxNode() Dim node As VisualBasicSyntaxNode = SyntaxFactory.CatchStatement(SyntaxFactory.IdentifierName("Goo"), SyntaxFactory.SimpleAsClause(SyntaxFactory.ParseTypeName(GetType(InvalidOperationException).Name)), Nothing) - Dim tree = VisualBasicSyntaxTree.CreateWithoutClone(node) + Dim tree = VisualBasicSyntaxTree.CreateWithoutClone(node, VisualBasicParseOptions.Default) CheckTree(tree) End Sub diff --git a/src/Compilers/VisualBasic/Test/Syntax/Syntax/SyntaxFactoryTests.vb b/src/Compilers/VisualBasic/Test/Syntax/Syntax/SyntaxFactoryTests.vb index 62f091c35ccd5..bb08faf2730a6 100644 --- a/src/Compilers/VisualBasic/Test/Syntax/Syntax/SyntaxFactoryTests.vb +++ b/src/Compilers/VisualBasic/Test/Syntax/Syntax/SyntaxFactoryTests.vb @@ -123,5 +123,16 @@ Integer Dim type2 = SyntaxFactory.ParseTypeName(code, options:=options) Assert.Equal("Integer", type2.ToString()) End Sub + + + Public Shared Sub TestParseMethodsKeepParseOptionsInTheTree() + Dim parseOptions = VisualBasicParseOptions.Default.WithLanguageVersion(LanguageVersion.Latest) + + Dim compUnit = SyntaxFactory.ParseCompilationUnit("", options:=parseOptions) + Assert.Same(parseOptions, compUnit.SyntaxTree.Options) + + Dim typeName = SyntaxFactory.ParseTypeName("", options:=parseOptions) + Assert.Same(parseOptions, typeName.SyntaxTree.Options) + End Sub End Class End Namespace From 5692cf690610b52fc2dca9ba1ea4d72a1d489253 Mon Sep 17 00:00:00 2001 From: DoctorKrolic Date: Wed, 4 Jun 2025 09:32:33 +0300 Subject: [PATCH 2/8] Feedback --- .../CSharp/Portable/Syntax/SyntaxFactory.cs | 132 ++++-------------- .../VisualBasic/Portable/Parser/Parser.vb | 2 +- .../Portable/Syntax/SyntaxNodeFactories.vb | 27 ++-- 3 files changed, 41 insertions(+), 120 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs index 0f68712d314a4..e92cad14330c4 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs @@ -1713,21 +1713,12 @@ public static TypeSyntax ParseTypeName(string text, int offset, bool consumeFull /// public static TypeSyntax ParseTypeName(string text, int offset = 0, ParseOptions? options = null, bool consumeFullText = true) { - var cSharpOptions = (CSharpParseOptions?)options; - using (var lexer = MakeLexer(text, offset, cSharpOptions)) + using (var lexer = MakeLexer(text, offset, (CSharpParseOptions?)options)) using (var parser = MakeParser(lexer)) { var node = parser.ParseTypeName(); if (consumeFullText) node = parser.ConsumeUnexpectedTokens(node); - var red = (TypeSyntax)node.CreateRed(); - if (cSharpOptions is not null) - { - Debug.Assert(red._syntaxTree is null); -#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) - red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, cSharpOptions); -#pragma warning restore - } - return red; + return CreateRed(node, lexer.Options); } } @@ -1741,21 +1732,12 @@ public static TypeSyntax ParseTypeName(string text, int offset = 0, ParseOptions /// True if extra tokens in the input should be treated as an error public static ExpressionSyntax ParseExpression(string text, int offset = 0, ParseOptions? options = null, bool consumeFullText = true) { - var cSharpOptions = (CSharpParseOptions?)options; - using (var lexer = MakeLexer(text, offset, cSharpOptions)) + using (var lexer = MakeLexer(text, offset, (CSharpParseOptions?)options)) using (var parser = MakeParser(lexer)) { var node = parser.ParseExpression(); if (consumeFullText) node = parser.ConsumeUnexpectedTokens(node); - var red = (ExpressionSyntax)node.CreateRed(); - if (cSharpOptions is not null) - { - Debug.Assert(red._syntaxTree is null); -#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) - red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, cSharpOptions); -#pragma warning restore - } - return red; + return CreateRed(node, lexer.Options); } } @@ -1769,21 +1751,12 @@ public static ExpressionSyntax ParseExpression(string text, int offset = 0, Pars /// True if extra tokens in the input should be treated as an error public static StatementSyntax ParseStatement(string text, int offset = 0, ParseOptions? options = null, bool consumeFullText = true) { - var cSharpOptions = (CSharpParseOptions?)options; - using (var lexer = MakeLexer(text, offset, cSharpOptions)) + using (var lexer = MakeLexer(text, offset, (CSharpParseOptions?)options)) using (var parser = MakeParser(lexer)) { var node = parser.ParseStatement(); if (consumeFullText) node = parser.ConsumeUnexpectedTokens(node); - var red = (StatementSyntax)node.CreateRed(); - if (cSharpOptions is not null) - { - Debug.Assert(red._syntaxTree is null); -#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) - red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, cSharpOptions); -#pragma warning restore - } - return red; + return CreateRed(node, lexer.Options); } } @@ -1798,8 +1771,7 @@ public static StatementSyntax ParseStatement(string text, int offset = 0, ParseO /// True if extra tokens in the input following a declaration should be treated as an error public static MemberDeclarationSyntax? ParseMemberDeclaration(string text, int offset = 0, ParseOptions? options = null, bool consumeFullText = true) { - var cSharpOptions = (CSharpParseOptions?)options; - using (var lexer = MakeLexer(text, offset, cSharpOptions)) + using (var lexer = MakeLexer(text, offset, (CSharpParseOptions?)options)) using (var parser = MakeParser(lexer)) { var node = parser.ParseMemberDeclaration(); @@ -1808,15 +1780,7 @@ public static StatementSyntax ParseStatement(string text, int offset = 0, ParseO return null; } - var red = (MemberDeclarationSyntax)(consumeFullText ? parser.ConsumeUnexpectedTokens(node) : node).CreateRed(); - if (cSharpOptions is not null) - { - Debug.Assert(red._syntaxTree is null); -#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) - red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, cSharpOptions); -#pragma warning restore - } - return red; + return CreateRed(consumeFullText ? parser.ConsumeUnexpectedTokens(node) : node, lexer.Options); } } @@ -1836,15 +1800,7 @@ public static CompilationUnitSyntax ParseCompilationUnit(string text, int offset using (var parser = MakeParser(lexer)) { var node = parser.ParseCompilationUnit(); - var red = (CompilationUnitSyntax)node.CreateRed(); - if (options is not null) - { - Debug.Assert(red._syntaxTree is null); -#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) - red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, options); -#pragma warning restore - } - return red; + return CreateRed(node, lexer.Options); } } @@ -1858,21 +1814,12 @@ public static CompilationUnitSyntax ParseCompilationUnit(string text, int offset /// True if extra tokens in the input should be treated as an error public static ParameterListSyntax ParseParameterList(string text, int offset = 0, ParseOptions? options = null, bool consumeFullText = true) { - var cSharpOptions = (CSharpParseOptions?)options; - using (var lexer = MakeLexer(text, offset, cSharpOptions)) + using (var lexer = MakeLexer(text, offset, (CSharpParseOptions?)options)) using (var parser = MakeParser(lexer)) { var node = parser.ParseParenthesizedParameterList(forExtension: false); if (consumeFullText) node = parser.ConsumeUnexpectedTokens(node); - var red = (ParameterListSyntax)node.CreateRed(); - if (cSharpOptions is not null) - { - Debug.Assert(red._syntaxTree is null); -#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) - red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, cSharpOptions); -#pragma warning restore - } - return red; + return CreateRed(node, lexer.Options); } } @@ -1886,21 +1833,12 @@ public static ParameterListSyntax ParseParameterList(string text, int offset = 0 /// True if extra tokens in the input should be treated as an error public static BracketedParameterListSyntax ParseBracketedParameterList(string text, int offset = 0, ParseOptions? options = null, bool consumeFullText = true) { - var cSharpOptions = (CSharpParseOptions?)options; - using (var lexer = MakeLexer(text, offset, cSharpOptions)) + using (var lexer = MakeLexer(text, offset, (CSharpParseOptions?)options)) using (var parser = MakeParser(lexer)) { var node = parser.ParseBracketedParameterList(); if (consumeFullText) node = parser.ConsumeUnexpectedTokens(node); - var red = (BracketedParameterListSyntax)node.CreateRed(); - if (cSharpOptions is not null) - { - Debug.Assert(red._syntaxTree is null); -#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) - red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, cSharpOptions); -#pragma warning restore - } - return red; + return CreateRed(node, lexer.Options); } } @@ -1914,21 +1852,12 @@ public static BracketedParameterListSyntax ParseBracketedParameterList(string te /// True if extra tokens in the input should be treated as an error public static ArgumentListSyntax ParseArgumentList(string text, int offset = 0, ParseOptions? options = null, bool consumeFullText = true) { - var cSharpOptions = (CSharpParseOptions?)options; - using (var lexer = MakeLexer(text, offset, cSharpOptions)) + using (var lexer = MakeLexer(text, offset, (CSharpParseOptions?)options)) using (var parser = MakeParser(lexer)) { var node = parser.ParseParenthesizedArgumentList(); if (consumeFullText) node = parser.ConsumeUnexpectedTokens(node); - var red = (ArgumentListSyntax)node.CreateRed(); - if (cSharpOptions is not null) - { - Debug.Assert(red._syntaxTree is null); -#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) - red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, cSharpOptions); -#pragma warning restore - } - return red; + return CreateRed(node, lexer.Options); } } @@ -1942,21 +1871,12 @@ public static ArgumentListSyntax ParseArgumentList(string text, int offset = 0, /// True if extra tokens in the input should be treated as an error public static BracketedArgumentListSyntax ParseBracketedArgumentList(string text, int offset = 0, ParseOptions? options = null, bool consumeFullText = true) { - var cSharpOptions = (CSharpParseOptions?)options; - using (var lexer = MakeLexer(text, offset, cSharpOptions)) + using (var lexer = MakeLexer(text, offset, (CSharpParseOptions?)options)) using (var parser = MakeParser(lexer)) { var node = parser.ParseBracketedArgumentList(); if (consumeFullText) node = parser.ConsumeUnexpectedTokens(node); - var red = (BracketedArgumentListSyntax)node.CreateRed(); - if (cSharpOptions is not null) - { - Debug.Assert(red._syntaxTree is null); -#pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) - red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, cSharpOptions); -#pragma warning restore - } - return red; + return CreateRed(node, lexer.Options); } } @@ -1970,8 +1890,7 @@ public static BracketedArgumentListSyntax ParseBracketedArgumentList(string text /// True if extra tokens in the input should be treated as an error public static AttributeArgumentListSyntax? ParseAttributeArgumentList(string text, int offset = 0, ParseOptions? options = null, bool consumeFullText = true) { - var cSharpOptions = (CSharpParseOptions?)options; - using var lexer = MakeLexer(text, offset, cSharpOptions); + using var lexer = MakeLexer(text, offset, (CSharpParseOptions?)options); using var parser = MakeParser(lexer); var node = parser.ParseAttributeArgumentList() ?? new InternalSyntax.AttributeArgumentListSyntax( @@ -1983,14 +1902,17 @@ public static BracketedArgumentListSyntax ParseBracketedArgumentList(string text annotations: null); if (consumeFullText) node = parser.ConsumeUnexpectedTokens(node); - var red = (AttributeArgumentListSyntax)node.CreateRed(); - if (cSharpOptions is not null) - { - Debug.Assert(red._syntaxTree is null); + return CreateRed(node, lexer.Options); + } + + private static TSyntax CreateRed(InternalSyntax.CSharpSyntaxNode green, CSharpParseOptions options) + where TSyntax : CSharpSyntaxNode + { + var red = (TSyntax)green.CreateRed(); + Debug.Assert(red._syntaxTree is null); #pragma warning disable RS0030 // Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) - red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, cSharpOptions); + red._syntaxTree = CSharpSyntaxTree.CreateWithoutClone(red, options); #pragma warning restore - } return red; } diff --git a/src/Compilers/VisualBasic/Portable/Parser/Parser.vb b/src/Compilers/VisualBasic/Portable/Parser/Parser.vb index 2b7dc24d71d1f..e53269bbd8342 100644 --- a/src/Compilers/VisualBasic/Portable/Parser/Parser.vb +++ b/src/Compilers/VisualBasic/Portable/Parser/Parser.vb @@ -31,7 +31,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax Private _possibleFirstStatementOnLine As PossibleFirstStatementKind = PossibleFirstStatementKind.Yes Private _recursionDepth As Integer Private _evaluatingConditionCompilationExpression As Boolean - Private ReadOnly _scanner As Scanner + Friend ReadOnly _scanner As Scanner Private ReadOnly _cancellationToken As CancellationToken Friend ReadOnly _pool As New SyntaxListPool Private ReadOnly _syntaxFactory As ContextAwareSyntaxFactory diff --git a/src/Compilers/VisualBasic/Portable/Syntax/SyntaxNodeFactories.vb b/src/Compilers/VisualBasic/Portable/Syntax/SyntaxNodeFactories.vb index e7aefacca0caf..76ac20008f6e1 100644 --- a/src/Compilers/VisualBasic/Portable/Syntax/SyntaxNodeFactories.vb +++ b/src/Compilers/VisualBasic/Portable/Syntax/SyntaxNodeFactories.vb @@ -200,14 +200,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Using p = New InternalSyntax.Parser(MakeSourceText(text, offset), If(vbOptions, VisualBasicParseOptions.Default)) p.GetNextToken() Dim node = p.ParseGeneralType() - Dim red As TypeSyntax = DirectCast(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node).CreateRed(Nothing, 0), TypeSyntax) - If vbOptions IsNot Nothing Then - Debug.Assert(red._syntaxTree Is Nothing) -#Disable Warning RS0030 ' Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) - red._syntaxTree = VisualBasicSyntaxTree.CreateWithoutClone(red, vbOptions) -#Enable Warning RS0030 + If consumeFullText Then + node = p.ConsumeUnexpectedTokens(node) End If - Return red + Return CreateRed(Of TypeSyntax)(node, p._scanner.Options) End Using End Function @@ -254,15 +250,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ''' The starting offset in the string Public Shared Function ParseCompilationUnit(text As String, Optional offset As Integer = 0, Optional options As VisualBasicParseOptions = Nothing) As CompilationUnitSyntax Using p = New InternalSyntax.Parser(MakeSourceText(text, offset), If(options, VisualBasicParseOptions.Default)) - Dim red As CompilationUnitSyntax = DirectCast(p.ParseCompilationUnit().CreateRed(Nothing, 0), CompilationUnitSyntax) - If options IsNot Nothing Then - Debug.Assert(red._syntaxTree Is Nothing) + Dim node = p.ParseCompilationUnit() + Return CreateRed(Of CompilationUnitSyntax)(node, p._scanner.Options) + End Using + End Function + + Private Shared Function CreateRed(Of TSyntax As VisualBasicSyntaxNode)(green As InternalSyntax.VisualBasicSyntaxNode, options As VisualBasicParseOptions) As TSyntax + Dim red = DirectCast(green.CreateRed(), TSyntax) + Debug.Assert(red._syntaxTree Is Nothing) #Disable Warning RS0030 ' Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) - red._syntaxTree = VisualBasicSyntaxTree.CreateWithoutClone(red, options) + red._syntaxTree = VisualBasicSyntaxTree.CreateWithoutClone(red, options) #Enable Warning RS0030 - End If - Return red - End Using + Return red End Function ''' From 6f00ddcde1fbb962520c29d57756fb0d621c8375 Mon Sep 17 00:00:00 2001 From: DoctorKrolic Date: Wed, 4 Jun 2025 09:38:50 +0300 Subject: [PATCH 3/8] Fix test --- .../Semantics/ScriptSemanticsTests.vb | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb index 12c757cc2435f..fd41504470ba5 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb @@ -45,31 +45,17 @@ F(Function() Dim semanticModel = compilation.GetSemanticModel(syntaxTree, True) Dim node5 As MemberAccessExpressionSyntax = ErrorTestsGetNode(syntaxTree) Assert.Equal("WriteLine", node5.Name.ToString()) - Assert.Null(semanticModel.GetSymbolInfo(node5.Name).Symbol) + Assert.Equal("Sub System.Console.WriteLine(value As System.Int32)", semanticModel.GetSymbolInfo(node5.Name).Symbol.ToTestDisplayString()) - compilation.AssertTheseDiagnostics( - -BC30420: 'Sub Main' was not found in 'Errors_01'. -BC30001: Statement is not valid in a namespace. -System.Console.WriteLine(1) -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - ) + compilation.AssertTheseDiagnostics() compilation = CreateCompilationWithMscorlib461({syntaxTree}, options:=TestOptions.ReleaseExe.WithScriptClassName("Script"), assemblyName:="Errors_01") semanticModel = compilation.GetSemanticModel(syntaxTree, True) node5 = ErrorTestsGetNode(syntaxTree) Assert.Equal("WriteLine", node5.Name.ToString()) - Assert.Null(semanticModel.GetSymbolInfo(node5.Name).Symbol) + Assert.Equal("Sub System.Console.WriteLine(value As System.Int32)", semanticModel.GetSymbolInfo(node5.Name).Symbol.ToTestDisplayString()) - compilation.AssertTheseDiagnostics( - -BC30420: 'Sub Main' was not found in 'Errors_01'. -BC30001: Statement is not valid in a namespace. -System.Console.WriteLine(1) -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - ) + compilation.AssertTheseDiagnostics() syntaxTree = SyntaxFactory.ParseSyntaxTree(code, options:=New VisualBasicParseOptions(kind:=SourceCodeKind.Script)) compilation = CreateCompilationWithMscorlib461AndVBRuntime({syntaxTree}, options:=TestOptions.ReleaseExe) From d0e62891d9350ffaf4c60aeeb1fefc5b096706cb Mon Sep 17 00:00:00 2001 From: DoctorKrolic Date: Wed, 4 Jun 2025 09:57:03 +0300 Subject: [PATCH 4/8] Skip test with external issue --- .../VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb index fd41504470ba5..5b23e52b78d7e 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb @@ -113,7 +113,7 @@ BC2014: the value 'Nothing' is invalid for option 'ScriptClassName' ) End Sub - + Public Sub Errors_02() Dim compilationUnit = VisualBasic.SyntaxFactory.ParseCompilationUnit("System.Console.WriteLine(1)", options:=New VisualBasicParseOptions(kind:=SourceCodeKind.Script)) From f6fef58e460bfeb647f04cae8bbd052436221dc7 Mon Sep 17 00:00:00 2001 From: DoctorKrolic Date: Tue, 17 Jun 2025 20:29:15 +0300 Subject: [PATCH 5/8] Use new helpers in all parse node methods --- .../CSharp/Portable/Syntax/SyntaxFactory.cs | 2 +- .../Portable/Syntax/SyntaxNodeFactories.vb | 34 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs index e92cad14330c4..5b57505194954 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs @@ -1694,7 +1694,7 @@ public static NameSyntax ParseName(string text, int offset = 0, bool consumeFull { var node = parser.ParseName(); if (consumeFullText) node = parser.ConsumeUnexpectedTokens(node); - return (NameSyntax)node.CreateRed(); + return CreateRed(node, lexer.Options); } } diff --git a/src/Compilers/VisualBasic/Portable/Syntax/SyntaxNodeFactories.vb b/src/Compilers/VisualBasic/Portable/Syntax/SyntaxNodeFactories.vb index 76ac20008f6e1..6f53cdd394787 100644 --- a/src/Compilers/VisualBasic/Portable/Syntax/SyntaxNodeFactories.vb +++ b/src/Compilers/VisualBasic/Portable/Syntax/SyntaxNodeFactories.vb @@ -186,7 +186,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic disallowGenericArgumentsOnLastQualifiedName:=False, allowEmptyGenericArguments:=True, allowedEmptyGenericArguments:=True) - Return DirectCast(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node).CreateRed(Nothing, 0), NameSyntax) + Return CreateRed(Of NameSyntax)(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node), p._scanner.Options) End Using End Function @@ -227,7 +227,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Using p = New InternalSyntax.Parser(MakeSourceText(text, offset), VisualBasicParseOptions.Default) p.GetNextToken() Dim node = p.ParseExpression() - Return DirectCast(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node).CreateRed(Nothing, 0), ExpressionSyntax) + Return CreateRed(Of ExpressionSyntax)(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node), p._scanner.Options) End Using End Function @@ -239,7 +239,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Public Shared Function ParseExecutableStatement(text As String, Optional offset As Integer = 0, Optional consumeFullText As Boolean = True) As StatementSyntax Using p = New InternalSyntax.Parser(MakeSourceText(text, offset), VisualBasicParseOptions.Default) Dim node = p.ParseExecutableStatement() - Return DirectCast(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node).CreateRed(Nothing, 0), StatementSyntax) + Return CreateRed(Of StatementSyntax)(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node), p._scanner.Options) End Using End Function @@ -255,15 +255,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Using End Function - Private Shared Function CreateRed(Of TSyntax As VisualBasicSyntaxNode)(green As InternalSyntax.VisualBasicSyntaxNode, options As VisualBasicParseOptions) As TSyntax - Dim red = DirectCast(green.CreateRed(), TSyntax) - Debug.Assert(red._syntaxTree Is Nothing) -#Disable Warning RS0030 ' Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) - red._syntaxTree = VisualBasicSyntaxTree.CreateWithoutClone(red, options) -#Enable Warning RS0030 - Return red - End Function - ''' ''' Parse a parameter list. ''' @@ -273,7 +264,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Using p = New InternalSyntax.Parser(MakeSourceText(text, offset), VisualBasicParseOptions.Default) p.GetNextToken() Dim node = p.ParseParameterList() - Return DirectCast(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node).CreateRed(Nothing, 0), ParameterListSyntax) + Return CreateRed(Of ParameterListSyntax)(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node), p._scanner.Options) End Using End Function @@ -286,7 +277,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Using p = New InternalSyntax.Parser(MakeSourceText(text, offset), VisualBasicParseOptions.Default) p.GetNextToken() Dim node = p.ParseParenthesizedArguments() - Return DirectCast(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node).CreateRed(Nothing, 0), ArgumentListSyntax) + Return CreateRed(Of ArgumentListSyntax)(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node), p._scanner.Options) End Using End Function @@ -312,15 +303,24 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim xmlName = InternalSyntax.SyntaxFactory.XmlName( Nothing, InternalSyntax.SyntaxFactory.XmlNameToken(parentElementName, SyntaxKind.XmlNameToken, Nothing, Nothing)) - Return DirectCast( - parser.ParseXmlAttribute( + Dim xmlAttribute = parser.ParseXmlAttribute( requireLeadingWhitespace:=False, AllowNameAsExpression:=False, - xmlElementName:=xmlName).CreateRed(Nothing, 0), BaseXmlAttributeSyntax) + xmlElementName:=xmlName) + Return CreateRed(Of BaseXmlAttributeSyntax)(xmlAttribute, scanner.Options) End Using End Using End Function + Private Shared Function CreateRed(Of TSyntax As VisualBasicSyntaxNode)(green As InternalSyntax.VisualBasicSyntaxNode, options As VisualBasicParseOptions) As TSyntax + Dim red = DirectCast(green.CreateRed(), TSyntax) + Debug.Assert(red._syntaxTree Is Nothing) +#Disable Warning RS0030 ' Do not use banned APIs (CreateWithoutClone is intended to be used from this call site) + red._syntaxTree = VisualBasicSyntaxTree.CreateWithoutClone(red, options) +#Enable Warning RS0030 + Return red + End Function + #End Region #Region "TokenFactories" From 6ac2bcb919b3f76b11100feb0c33dd221a1c063a Mon Sep 17 00:00:00 2001 From: DoctorKrolic Date: Tue, 17 Jun 2025 20:50:03 +0300 Subject: [PATCH 6/8] Verify crashes --- .../Semantics/ScriptSemanticsTests.vb | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb index 5b23e52b78d7e..a4390a9750463 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb @@ -113,8 +113,9 @@ BC2014: the value 'Nothing' is invalid for option 'ScriptClassName' ) End Sub - + + Public Sub Errors_02() Dim compilationUnit = VisualBasic.SyntaxFactory.ParseCompilationUnit("System.Console.WriteLine(1)", options:=New VisualBasicParseOptions(kind:=SourceCodeKind.Script)) Dim syntaxTree1 = compilationUnit.SyntaxTree @@ -127,30 +128,36 @@ BC2014: the value 'Nothing' is invalid for option 'ScriptClassName' Dim compilation = CreateCompilationWithMscorlib461({syntaxTree1, syntaxTree2}) Dim semanticModel1 = compilation.GetSemanticModel(syntaxTree1, True) Dim semanticModel2 = compilation.GetSemanticModel(syntaxTree2, True) - Assert.Null(semanticModel1.GetSymbolInfo(node1.Name).Symbol) - Assert.Equal("Sub System.Console.WriteLine(value As System.Int32)", semanticModel2.GetSymbolInfo(node2.Name).Symbol.ToTestDisplayString()) + Assert.Throws(Of InvalidOperationException)( + Sub() + Assert.Null(semanticModel1.GetSymbolInfo(node1.Name).Symbol) + Assert.Equal("Sub System.Console.WriteLine(value As System.Int32)", semanticModel2.GetSymbolInfo(node2.Name).Symbol.ToTestDisplayString()) - compilation.AssertTheseDiagnostics( + compilation.AssertTheseDiagnostics( BC30001: Statement is not valid in a namespace. System.Console.WriteLine(1) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ) + ) + End Sub) compilation = CreateCompilationWithMscorlib461({syntaxTree2, syntaxTree1}) semanticModel1 = compilation.GetSemanticModel(syntaxTree1, True) semanticModel2 = compilation.GetSemanticModel(syntaxTree2, True) - Assert.Null(semanticModel1.GetSymbolInfo(node1.Name).Symbol) - Assert.Equal("Sub System.Console.WriteLine(value As System.Int32)", semanticModel2.GetSymbolInfo(node2.Name).Symbol.ToTestDisplayString()) + Assert.Throws(Of InvalidOperationException)( + Sub() + Assert.Null(semanticModel1.GetSymbolInfo(node1.Name).Symbol) + Assert.Equal("Sub System.Console.WriteLine(value As System.Int32)", semanticModel2.GetSymbolInfo(node2.Name).Symbol.ToTestDisplayString()) - compilation.AssertTheseDiagnostics( - + compilation.AssertTheseDiagnostics( + BC30001: Statement is not valid in a namespace. System.Console.WriteLine(1) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ) + ) + End Sub) End Sub Private Shared Function ErrorTestsGetNode(syntaxTree As SyntaxTree) As MemberAccessExpressionSyntax From df2ec89cfd3357251c1049212f880ec3e0f8f785 Mon Sep 17 00:00:00 2001 From: DoctorKrolic Date: Tue, 17 Jun 2025 23:04:12 +0300 Subject: [PATCH 7/8] Fix test for IOperation and Used assemblies scenarios --- .../Semantic/Semantics/ScriptSemanticsTests.vb | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb index a4390a9750463..65edb50b216ab 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb @@ -125,15 +125,16 @@ BC2014: the value 'Nothing' is invalid for option 'ScriptClassName' Dim node2 As MemberAccessExpressionSyntax = ErrorTestsGetNode(syntaxTree2) Assert.Equal("WriteLine", node2.Name.ToString()) - Dim compilation = CreateCompilationWithMscorlib461({syntaxTree1, syntaxTree2}) - Dim semanticModel1 = compilation.GetSemanticModel(syntaxTree1, True) - Dim semanticModel2 = compilation.GetSemanticModel(syntaxTree2, True) Assert.Throws(Of InvalidOperationException)( Sub() + Dim compilation = CreateCompilationWithMscorlib461({syntaxTree1, syntaxTree2}) + Dim semanticModel1 = compilation.GetSemanticModel(syntaxTree1, True) + Dim semanticModel2 = compilation.GetSemanticModel(syntaxTree2, True) + Assert.Null(semanticModel1.GetSymbolInfo(node1.Name).Symbol) Assert.Equal("Sub System.Console.WriteLine(value As System.Int32)", semanticModel2.GetSymbolInfo(node2.Name).Symbol.ToTestDisplayString()) - compilation.AssertTheseDiagnostics( + Compilation.AssertTheseDiagnostics( BC30001: Statement is not valid in a namespace. System.Console.WriteLine(1) @@ -142,15 +143,16 @@ System.Console.WriteLine(1) ) End Sub) - compilation = CreateCompilationWithMscorlib461({syntaxTree2, syntaxTree1}) - semanticModel1 = compilation.GetSemanticModel(syntaxTree1, True) - semanticModel2 = compilation.GetSemanticModel(syntaxTree2, True) Assert.Throws(Of InvalidOperationException)( Sub() + Dim compilation = CreateCompilationWithMscorlib461({syntaxTree2, syntaxTree1}) + Dim semanticModel1 = compilation.GetSemanticModel(syntaxTree1, True) + Dim semanticModel2 = compilation.GetSemanticModel(syntaxTree2, True) + Assert.Null(semanticModel1.GetSymbolInfo(node1.Name).Symbol) Assert.Equal("Sub System.Console.WriteLine(value As System.Int32)", semanticModel2.GetSymbolInfo(node2.Name).Symbol.ToTestDisplayString()) - compilation.AssertTheseDiagnostics( + Compilation.AssertTheseDiagnostics( BC30001: Statement is not valid in a namespace. System.Console.WriteLine(1) From bf42049997971283c0e647cfd0c76c3ce2e0ebc8 Mon Sep 17 00:00:00 2001 From: DoctorKrolic Date: Thu, 19 Jun 2025 19:41:23 +0300 Subject: [PATCH 8/8] Expose VB parse options from its parser --- .../VisualBasic/Portable/Parser/Parser.vb | 8 +++++++- .../Portable/Syntax/SyntaxNodeFactories.vb | 14 +++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/Compilers/VisualBasic/Portable/Parser/Parser.vb b/src/Compilers/VisualBasic/Portable/Parser/Parser.vb index e53269bbd8342..7a2a53a2413a0 100644 --- a/src/Compilers/VisualBasic/Portable/Parser/Parser.vb +++ b/src/Compilers/VisualBasic/Portable/Parser/Parser.vb @@ -31,7 +31,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax Private _possibleFirstStatementOnLine As PossibleFirstStatementKind = PossibleFirstStatementKind.Yes Private _recursionDepth As Integer Private _evaluatingConditionCompilationExpression As Boolean - Friend ReadOnly _scanner As Scanner + Private ReadOnly _scanner As Scanner Private ReadOnly _cancellationToken As CancellationToken Friend ReadOnly _pool As New SyntaxListPool Private ReadOnly _syntaxFactory As ContextAwareSyntaxFactory @@ -70,6 +70,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax End If End Sub + Friend ReadOnly Property Options As VisualBasicParseOptions + Get + Return _scanner.Options + End Get + End Property + Friend ReadOnly Property IsScript As Boolean Get Return _scanner.Options.Kind = SourceCodeKind.Script diff --git a/src/Compilers/VisualBasic/Portable/Syntax/SyntaxNodeFactories.vb b/src/Compilers/VisualBasic/Portable/Syntax/SyntaxNodeFactories.vb index 6f53cdd394787..87034af48384e 100644 --- a/src/Compilers/VisualBasic/Portable/Syntax/SyntaxNodeFactories.vb +++ b/src/Compilers/VisualBasic/Portable/Syntax/SyntaxNodeFactories.vb @@ -186,7 +186,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic disallowGenericArgumentsOnLastQualifiedName:=False, allowEmptyGenericArguments:=True, allowedEmptyGenericArguments:=True) - Return CreateRed(Of NameSyntax)(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node), p._scanner.Options) + Return CreateRed(Of NameSyntax)(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node), p.Options) End Using End Function @@ -203,7 +203,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic If consumeFullText Then node = p.ConsumeUnexpectedTokens(node) End If - Return CreateRed(Of TypeSyntax)(node, p._scanner.Options) + Return CreateRed(Of TypeSyntax)(node, p.Options) End Using End Function @@ -227,7 +227,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Using p = New InternalSyntax.Parser(MakeSourceText(text, offset), VisualBasicParseOptions.Default) p.GetNextToken() Dim node = p.ParseExpression() - Return CreateRed(Of ExpressionSyntax)(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node), p._scanner.Options) + Return CreateRed(Of ExpressionSyntax)(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node), p.Options) End Using End Function @@ -239,7 +239,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Public Shared Function ParseExecutableStatement(text As String, Optional offset As Integer = 0, Optional consumeFullText As Boolean = True) As StatementSyntax Using p = New InternalSyntax.Parser(MakeSourceText(text, offset), VisualBasicParseOptions.Default) Dim node = p.ParseExecutableStatement() - Return CreateRed(Of StatementSyntax)(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node), p._scanner.Options) + Return CreateRed(Of StatementSyntax)(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node), p.Options) End Using End Function @@ -251,7 +251,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Public Shared Function ParseCompilationUnit(text As String, Optional offset As Integer = 0, Optional options As VisualBasicParseOptions = Nothing) As CompilationUnitSyntax Using p = New InternalSyntax.Parser(MakeSourceText(text, offset), If(options, VisualBasicParseOptions.Default)) Dim node = p.ParseCompilationUnit() - Return CreateRed(Of CompilationUnitSyntax)(node, p._scanner.Options) + Return CreateRed(Of CompilationUnitSyntax)(node, p.Options) End Using End Function @@ -264,7 +264,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Using p = New InternalSyntax.Parser(MakeSourceText(text, offset), VisualBasicParseOptions.Default) p.GetNextToken() Dim node = p.ParseParameterList() - Return CreateRed(Of ParameterListSyntax)(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node), p._scanner.Options) + Return CreateRed(Of ParameterListSyntax)(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node), p.Options) End Using End Function @@ -277,7 +277,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Using p = New InternalSyntax.Parser(MakeSourceText(text, offset), VisualBasicParseOptions.Default) p.GetNextToken() Dim node = p.ParseParenthesizedArguments() - Return CreateRed(Of ArgumentListSyntax)(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node), p._scanner.Options) + Return CreateRed(Of ArgumentListSyntax)(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node), p.Options) End Using End Function