提交 c3beadd7 编写于 作者: P pgavlin

Wrap parallel code in the compilers with guards that propagate the UI culture of the main thread.

This is necessary in order to present strings that originate from external APIs (e.g. the System.XML) with proper localization when they are embedded in diagnostics.
***NO_CI***
 (changeset 1408070)
上级 ad32270a
......@@ -60,45 +60,18 @@ protected override Compilation CreateCompilation(TextWriter consoleOutput, Touch
if (Arguments.CompilationOptions.ConcurrentBuild)
{
int threadId = Thread.CurrentThread.ManagedThreadId;
System.Globalization.CultureInfo uiCulture = Thread.CurrentThread.CurrentUICulture;
Parallel.For(0, sourceFiles.Length, i =>
Parallel.For(0, sourceFiles.Length, UICultureUtilities.WithCurrentUICulture<int>(i =>
{
var currentThread = Thread.CurrentThread;
var currentThreadId = currentThread.ManagedThreadId;
System.Globalization.CultureInfo saveUICulture = null;
if (currentThreadId != threadId)
{
// New threads created by Parallel.For do not inherit CurrentUICulture by default.
saveUICulture = currentThread.CurrentUICulture;
currentThread.CurrentUICulture = uiCulture;
}
try
{
var file = sourceFiles[i];
//NOTE: order of trees is important!!
trees[i] = ParseFile(consoleOutput, parseOptions, scriptParseOptions, ref hadErrors, file, out normalizedFilePaths[i]);
}
finally
{
if (currentThreadId != threadId)
{
currentThread.CurrentUICulture = saveUICulture;
}
}
});
//NOTE: order of trees is important!!
trees[i] = ParseFile(consoleOutput, parseOptions, scriptParseOptions, ref hadErrors, sourceFiles[i], out normalizedFilePaths[i]);
}));
}
else
{
for (int i = 0; i < sourceFiles.Length; i++)
{
var file = sourceFiles[i];
//NOTE: order of trees is important!!
trees[i] = ParseFile(consoleOutput, parseOptions, scriptParseOptions, ref hadErrors, file, out normalizedFilePaths[i]);
trees[i] = ParseFile(consoleOutput, parseOptions, scriptParseOptions, ref hadErrors, sourceFiles[i], out normalizedFilePaths[i]);
}
}
......
......@@ -1953,7 +1953,7 @@ internal ImmutableArray<Diagnostic> GetDiagnostics(CompilationStage stage, bool
: DefaultParallelOptions;
Parallel.For(0, this.SyntaxTrees.Length, parallelOptions,
i => builder.AddRange(this.SyntaxTrees[i].GetDiagnostics(cancellationToken)));
UICultureUtilities.WithCurrentUICulture<int>(i => builder.AddRange(this.SyntaxTrees[i].GetDiagnostics(cancellationToken))));
}
else
{
......
......@@ -163,7 +163,7 @@ public override void VisitNamespace(NamespaceSymbol symbol)
var options = this.cancellationToken.CanBeCanceled
? new ParallelOptions() { CancellationToken = this.cancellationToken }
: CSharpCompilation.DefaultParallelOptions; // i.e. new ParallelOptions()
Parallel.ForEach(symbol.GetMembersUnordered(), options, Visit);
Parallel.ForEach(symbol.GetMembersUnordered(), options, UICultureUtilities.WithCurrentUICulture<Symbol>(Visit));
}
else
{
......@@ -209,7 +209,7 @@ public override void VisitNamedType(NamedTypeSymbol symbol)
var options = this.cancellationToken.CanBeCanceled
? new ParallelOptions() { CancellationToken = this.cancellationToken }
: CSharpCompilation.DefaultParallelOptions; //i.e. new ParallelOptions()
Parallel.ForEach(symbol.GetMembersUnordered(), options, Visit);
Parallel.ForEach(symbol.GetMembersUnordered(), options, UICultureUtilities.WithCurrentUICulture<Symbol>(Visit));
}
else
{
......
......@@ -293,18 +293,17 @@ public override object VisitNamespace(NamespaceSymbol symbol, TypeCompilationSta
private Task CompileNamespaceAsTask(NamespaceSymbol symbol)
{
return Task.Run(() =>
return Task.Run(UICultureUtilities.WithCurrentUICulture(() =>
{
try
{
try
{
CompileNamespace(symbol);
return (object)null;
}
catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
{
throw ExceptionUtilities.Unreachable;
}
}, this.cancellationToken);
CompileNamespace(symbol);
}
catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
{
throw ExceptionUtilities.Unreachable;
}
}), this.cancellationToken);
}
private void CompileNamespace(NamespaceSymbol symbol)
......@@ -340,18 +339,17 @@ public override object VisitNamedType(NamedTypeSymbol symbol, TypeCompilationSta
private Task CompileNamedTypeAsTask(NamedTypeSymbol symbol)
{
return Task.Run(() =>
return Task.Run(UICultureUtilities.WithCurrentUICulture(() =>
{
try
{
try
{
CompileNamedType(symbol);
return (object)null;
}
catch (Exception e) when (FatalError.Report(e))
{
throw ExceptionUtilities.Unreachable;
}
}, this.cancellationToken);
CompileNamedType(symbol);
}
catch (Exception e) when (FatalError.Report(e))
{
throw ExceptionUtilities.Unreachable;
}
}), this.cancellationToken);
}
private void CompileNamedType(NamedTypeSymbol symbol)
......
......@@ -26,7 +26,6 @@ internal partial class LanguageParser : SyntaxParser
// discovered was 7. Having 20 as a minimum seems reasonable in that context
//
private const int MaxUncheckedRecursionDepth = 20;
private static Action ensureSufficientExecutionStack;
// list pools - allocators for lists that are used to build sequences of nodes. The lists
// can be reused (hence pooled) since the syntax factory methods don't keep references to
......@@ -54,22 +53,6 @@ internal partial class LanguageParser : SyntaxParser
{
this.syntaxFactoryContext = new SyntaxFactoryContext();
this.syntaxFactory = new ContextAwareSyntax(syntaxFactoryContext);
// TODO (DevDiv workitem 966425): Replace with the RuntimeHelpers.EnsureSufficientExecutionStack API when
// available.
if (ensureSufficientExecutionStack == null)
{
var type = Type.GetType("System.Runtime.CompilerServices.RuntimeHelpers, mscorlib, Version=4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089");
var methodInfo = System.Reflection.IntrospectionExtensions.GetTypeInfo(type).GetDeclaredMethod("EnsureSufficientExecutionStack");
if (methodInfo != null)
{
ensureSufficientExecutionStack = (Action)methodInfo.CreateDelegate(typeof(Action));
}
else
{
ensureSufficientExecutionStack = () => { };
}
}
}
// Special Name checks
......@@ -6312,7 +6295,7 @@ public StatementSyntax ParseStatement()
this.recursionDepth++;
if (this.recursionDepth > MaxUncheckedRecursionDepth)
{
LanguageParser.ensureSufficientExecutionStack();
EnsureSufficientExecutionStackLightUp.EnsureSufficientExecutionStack();
}
if (this.IsIncrementalAndFactoryContextMatches && this.CurrentNode is CSharp.Syntax.StatementSyntax)
......@@ -8241,7 +8224,7 @@ private ExpressionSyntax ParseSubExpression(uint precedence)
if (this.recursionDepth > MaxUncheckedRecursionDepth)
{
LanguageParser.ensureSufficientExecutionStack();
EnsureSufficientExecutionStackLightUp.EnsureSufficientExecutionStack();
}
var result = ParseSubExpressionCore(precedence);
......
......@@ -50,11 +50,11 @@ internal override void ForceComplete(SourceLocation locationOpt, CancellationTok
? new ParallelOptions() { CancellationToken = cancellationToken }
: CSharpCompilation.DefaultParallelOptions;
Parallel.For(0, members.Length, po, i =>
Parallel.For(0, members.Length, po, UICultureUtilities.WithCurrentUICulture<int>(i =>
{
var member = members[i];
ForceCompleteMemberByLocation(locationOpt, member, cancellationToken);
});
}));
foreach (var member in members)
{
......
......@@ -254,6 +254,7 @@
<Compile Include="InternalUtilities\ConsList`1.cs" />
<Compile Include="InternalUtilities\DecimalUtilities.cs" />
<Compile Include="InternalUtilities\DocumentationCommentXmlNames.cs" />
<Compile Include="InternalUtilities\EnsureSufficientExecutionStackLightUp.cs" />
<Compile Include="InternalUtilities\EnumerableExtensions.ComparisonComparer.cs" />
<Compile Include="InternalUtilities\EnumerableExtensions.cs" />
<Compile Include="InternalUtilities\EnumField.cs" />
......@@ -295,6 +296,7 @@
<Compile Include="InternalUtilities\TextKeyedCache.cs" />
<Compile Include="InternalUtilities\ThreadSafeFlagOperations.cs" />
<Compile Include="InternalUtilities\ThreeState.cs" />
<Compile Include="InternalUtilities\UICultureUtilities.cs" />
<Compile Include="InternalUtilities\ValueTuple.cs" />
<Compile Include="InternalUtilities\ValueTuple`2.cs" />
<Compile Include="InternalUtilities\ValueTuple`3.cs" />
......@@ -669,4 +671,4 @@
<Import Project="..\..\..\..\packages\StyleCop.MSBuild.4.7.48.2\build\StyleCop.MSBuild.Targets" Condition="Exists('..\..\..\..\packages\StyleCop.MSBuild.4.7.48.2\build\StyleCop.MSBuild.Targets')" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</ImportGroup>
</Project>
\ No newline at end of file
</Project>
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Reflection;
namespace Roslyn.Utilities
{
internal static class EnsureSufficientExecutionStackLightUp
{
private readonly static Action s_ensureSufficientExecutionStack;
static EnsureSufficientExecutionStackLightUp()
{
// TODO (DevDiv workitem 966425): Replace with the RuntimeHelpers.EnsureSufficientExecutionStack API when available.
if (!TryGetEnsureSufficientExecutionStack(out s_ensureSufficientExecutionStack))
{
s_ensureSufficientExecutionStack = () => { };
}
}
private static bool TryGetEnsureSufficientExecutionStack(out Action ensureSufficientExecutionStack)
{
var type = System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(object)).Assembly.GetType("System.Runtime.CompilerServices.RuntimeHelpers");
if (type == null)
{
ensureSufficientExecutionStack = null;
return false;
}
foreach (var methodInfo in System.Reflection.IntrospectionExtensions.GetTypeInfo(type).GetDeclaredMethods("EnsureSufficientExecutionStack"))
{
if (methodInfo.IsStatic && !methodInfo.ContainsGenericParameters && methodInfo.ReturnType == typeof(void) && methodInfo.GetParameters().Length == 0)
{
ensureSufficientExecutionStack = (Action)methodInfo.CreateDelegate(typeof(Action));
return true;
}
}
ensureSufficientExecutionStack = null;
return false;
}
public static void EnsureSufficientExecutionStack()
{
s_ensureSufficientExecutionStack();
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Globalization;
using System.Reflection;
namespace Roslyn.Utilities
{
internal static class UICultureUtilities
{
// TODO (DevDiv 1117307): Replace with CultureInfo.CurrentUICulture.set when available.
private const string currentUICultureName = "CurrentUICulture";
private readonly static Action<CultureInfo>_setCurrentUICulture;
private static bool TryGetCurrentUICultureSetter(out Action<CultureInfo> setter)
{
const string cultureInfoTypeName = "System.Globalization.CultureInfo";
const string cultureInfoTypeNameGlobalization = cultureInfoTypeName + ", System.Globalization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
try
{
var type = Type.GetType(cultureInfoTypeNameGlobalization) ?? typeof(object).GetTypeInfo().Assembly.GetType(cultureInfoTypeName);
if ((object)type == null)
{
setter = null;
return false;
}
var currentUICultureSetter = type.GetTypeInfo().GetDeclaredProperty(currentUICultureName)?.SetMethod;
if ((object)currentUICultureSetter == null || !currentUICultureSetter.IsStatic || currentUICultureSetter.ContainsGenericParameters || currentUICultureSetter.ReturnType != typeof(void))
{
setter = null;
return false;
}
var parameters = currentUICultureSetter.GetParameters();
if (parameters.Length != 1 || parameters[0].ParameterType != typeof(CultureInfo))
{
setter = null;
return false;
}
setter = (Action<CultureInfo>)currentUICultureSetter.CreateDelegate(typeof(Action<CultureInfo>));
return true;
}
catch
{
setter = null;
return false;
}
}
private static bool TryGetCurrentThreadUICultureSetter(out Action<CultureInfo> setter)
{
const string threadTypeName = "System.Threading.Thread";
const string currentThreadName = "CurrentThread";
try
{
var type = typeof(object).GetTypeInfo().Assembly.GetType(threadTypeName);
if ((object)type == null)
{
setter = null;
return false;
}
var typeInfo = type.GetTypeInfo();
var currentThreadGetter = typeInfo.GetDeclaredProperty(currentThreadName)?.GetMethod;
if ((object)currentThreadGetter == null || !currentThreadGetter.IsStatic || currentThreadGetter.ContainsGenericParameters || currentThreadGetter.ReturnType != type || currentThreadGetter.GetParameters().Length != 0)
{
setter = null;
return false;
}
var currentUICultureSetter = typeInfo.GetDeclaredProperty(currentUICultureName)?.SetMethod;
if ((object)currentUICultureSetter == null || currentUICultureSetter.IsStatic || currentUICultureSetter.ContainsGenericParameters || currentUICultureSetter.ReturnType != typeof(void))
{
setter = null;
return false;
}
var parameters = currentUICultureSetter.GetParameters();
if (parameters.Length != 1 || parameters[0].ParameterType != typeof(CultureInfo))
{
setter = null;
return false;
}
setter = culture => {
currentUICultureSetter.Invoke(currentThreadGetter.Invoke(null, null), new[] { culture });
};
return true;
}
catch
{
setter = null;
return false;
}
}
static UICultureUtilities()
{
if (!TryGetCurrentUICultureSetter(out _setCurrentUICulture) &&
!TryGetCurrentThreadUICultureSetter(out _setCurrentUICulture))
{
_setCurrentUICulture = null;
}
}
public static Action WithCurrentUICulture(Action action)
{
if (_setCurrentUICulture == null)
{
return action;
}
var savedCulture = CultureInfo.CurrentUICulture;
return () => {
var currentCulture = CultureInfo.CurrentUICulture;
if (currentCulture != savedCulture)
{
_setCurrentUICulture(savedCulture);
try
{
action();
}
finally
{
_setCurrentUICulture(currentCulture);
}
}
else
{
action();
}
};
}
public static Action<T> WithCurrentUICulture<T>(Action<T> action)
{
if (_setCurrentUICulture == null)
{
return action;
}
var savedCulture = CultureInfo.CurrentUICulture;
return param => {
var currentCulture = CultureInfo.CurrentUICulture;
if (currentCulture != savedCulture)
{
_setCurrentUICulture(savedCulture);
try
{
action(param);
}
finally
{
_setCurrentUICulture(currentCulture);
}
}
else
{
action(param);
}
};
}
public static Func<T> WithCurrentUICulture<T>(Func<T> func)
{
if (_setCurrentUICulture == null)
{
return func;
}
var savedCulture = CultureInfo.CurrentUICulture;
return () => {
var currentCulture = CultureInfo.CurrentUICulture;
if (currentCulture != savedCulture)
{
_setCurrentUICulture(savedCulture);
try
{
return func();
}
finally
{
_setCurrentUICulture(currentCulture);
}
}
else
{
return func();
}
};
}
}
}
......@@ -7,6 +7,7 @@ Imports System.Text
Imports System.Threading.Tasks
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.Instrumentation
Imports Roslyn.Utilities
Namespace Microsoft.CodeAnalysis.VisualBasic
......@@ -75,29 +76,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim trees(sourceFiles.Length - 1) As SyntaxTree
If Arguments.CompilationOptions.ConcurrentBuild Then
Dim threadId As Integer = Threading.Thread.CurrentThread.ManagedThreadId
Dim uiCulture As System.Globalization.CultureInfo = Threading.Thread.CurrentThread.CurrentUICulture
Parallel.For(0, sourceFiles.Length,
Sub(i As Integer)
Dim currentThread = Threading.Thread.CurrentThread
Dim currentThreadId As Integer = currentThread.ManagedThreadId
Dim saveUICulture As System.Globalization.CultureInfo = Nothing
If currentThreadId <> threadId Then
' New threads created by Parallel.For do not inherit CurrentUICulture by default.
saveUICulture = currentThread.CurrentUICulture
currentThread.CurrentUICulture = uiCulture
End If
Try
' NOTE: order of trees is important!!
trees(i) = ParseFile(consoleOutput, parseOptions, scriptParseOptions, hadErrors, sourceFiles(i))
Finally
If currentThreadId <> threadId Then
currentThread.CurrentUICulture = saveUICulture
End If
End Try
End Sub)
UICultureUtilities.WithCurrentUICulture(Of Integer)(
Sub(i As Integer)
' NOTE: order of trees is important!!
trees(i) = ParseFile(consoleOutput, parseOptions, scriptParseOptions, hadErrors, sourceFiles(i))
End Sub))
Else
For i = 0 To sourceFiles.Length - 1
' NOTE: order of trees is important!!
......
......@@ -69,7 +69,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
If symbol.Modules.Length > 1 AndAlso _compilation.Options.ConcurrentBuild Then
Dim options = If(Me._cancellationToken.CanBeCanceled, New ParallelOptions() With {.CancellationToken = Me._cancellationToken}, _defaultParallelOptions)
Parallel.ForEach(symbol.Modules, options, AddressOf VisitModule)
Parallel.ForEach(symbol.Modules, options, UICultureUtilities.WithCurrentUICulture(Of ModuleSymbol)(AddressOf VisitModule))
Else
For Each m In symbol.Modules
VisitModule(m)
......@@ -95,7 +95,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
If _compilation.Options.ConcurrentBuild Then
Dim options = If(Me._cancellationToken.CanBeCanceled, New ParallelOptions() With {.CancellationToken = Me._cancellationToken}, _defaultParallelOptions)
Parallel.ForEach(symbol.GetMembersUnordered(), options, AddressOf Visit)
Parallel.ForEach(symbol.GetMembersUnordered(), options, UICultureUtilities.WithCurrentUICulture(Of Symbol)(AddressOf Visit))
Else
For Each m In symbol.GetMembersUnordered()
Visit(m)
......@@ -122,7 +122,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
If _compilation.Options.ConcurrentBuild Then
Dim options = If(Me._cancellationToken.CanBeCanceled, New ParallelOptions() With {.CancellationToken = Me._cancellationToken}, _defaultParallelOptions)
Parallel.ForEach(symbol.GetMembersUnordered(), options, AddressOf Visit)
Parallel.ForEach(symbol.GetMembersUnordered(), options, UICultureUtilities.WithCurrentUICulture(Of Symbol)(AddressOf Visit))
Else
For Each m In symbol.GetMembersUnordered()
Visit(m)
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System
Imports System.Collections.Concurrent
......@@ -477,13 +477,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private Function CompileNamespaceAsTask(symbol As NamespaceSymbol) As Task
Return Task.Run(
Sub()
Try
CompileNamespace(symbol)
Catch e As Exception When FatalError.ReportUnlessCanceled(e)
Throw ExceptionUtilities.Unreachable
End Try
End Sub,
UICultureUtilities.WithCurrentUICulture(
Sub()
Try
CompileNamespace(symbol)
Catch e As Exception When FatalError.ReportUnlessCanceled(e)
Throw ExceptionUtilities.Unreachable
End Try
End Sub),
Me._cancellationToken)
End Function
......@@ -509,13 +510,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private Function CompileNamedTypeAsTask(symbol As NamedTypeSymbol, filter As Predicate(Of Symbol)) As Task
Return Task.Run(
Sub()
Try
CompileNamedType(symbol, filter)
Catch e As Exception When FatalError.ReportUnlessCanceled(e)
Throw ExceptionUtilities.Unreachable
End Try
End Sub,
UICultureUtilities.WithCurrentUICulture(
Sub()
Try
CompileNamedType(symbol, filter)
Catch e As Exception When FatalError.ReportUnlessCanceled(e)
Throw ExceptionUtilities.Unreachable
End Try
End Sub),
Me._cancellationToken)
End Function
......
......@@ -1905,7 +1905,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
If Options.ConcurrentBuild Then
Dim options = New ParallelOptions() With {.CancellationToken = cancellationToken}
Parallel.For(0, SyntaxTrees.Length, options,
Sub(i As Integer) builder.AddRange(SyntaxTrees(i).GetDiagnostics(cancellationToken)))
UICultureUtilities.WithCurrentUICulture(Sub(i As Integer) builder.AddRange(SyntaxTrees(i).GetDiagnostics(cancellationToken))))
Else
For Each tree In SyntaxTrees
cancellationToken.ThrowIfCancellationRequested()
......
......@@ -39,7 +39,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
Try
_recursionDepth += 1
If _recursionDepth >= _maxUncheckedRecursionDepth Then
_ensureSufficientExecutionStack()
EnsureSufficientExecutionStackLightUp.EnsureSufficientExecutionStack()
End If
'// Note: this function will only ever return NULL if the flag "BailIfFirstTokenIsRejected" is set,
......
......@@ -20,8 +20,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
IfPrecededByLineBreak
End Enum
Private Shared _ensureSufficientExecutionStack As Action = Nothing
' Keep this value in sync with C# LanguageParser
Private Const _maxUncheckedRecursionDepth As Integer = 30
......@@ -61,20 +59,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
_scanner = scanner
_context = New CompilationUnitContext(Me)
_syntaxFactory = New ContextAwareSyntaxFactory(Me)
' TODO (DevDiv workitem 966425): Replace with the RuntimeHelpers.EnsureSufficientExecutionStack API when
' available.
If _ensureSufficientExecutionStack Is Nothing Then
Dim type = System.Type.GetType("System.Runtime.CompilerServices.RuntimeHelpers, mscorlib, Version=4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089")
Dim methodInfo = Reflection.IntrospectionExtensions.GetTypeInfo(type).GetDeclaredMethod("EnsureSufficientExecutionStack")
If methodInfo IsNot Nothing Then
_ensureSufficientExecutionStack = DirectCast(methodInfo.CreateDelegate(GetType(Action)), Action)
Else
_ensureSufficientExecutionStack = Sub()
End Sub
End If
End If
End Sub
Friend Sub Dispose() Implements IDisposable.Dispose
......@@ -860,7 +844,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
Try
_recursionDepth += 1
If _recursionDepth >= _maxUncheckedRecursionDepth Then
_ensureSufficientExecutionStack()
EnsureSufficientExecutionStackLightUp.EnsureSufficientExecutionStack()
End If
_hadImplicitLineContinuation = False
......
......@@ -603,10 +603,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Dim options = New ParallelOptions() With {.CancellationToken = cancellationToken}
Parallel.For(0, trees.Count, options,
Sub(i As Integer)
cancellationToken.ThrowIfCancellationRequested()
GetSourceFile(trees(i)).GenerateAllDeclarationErrors()
End Sub)
UICultureUtilities.WithCurrentUICulture(
Sub(i As Integer)
cancellationToken.ThrowIfCancellationRequested()
GetSourceFile(trees(i)).GenerateAllDeclarationErrors()
End Sub))
trees.Free()
Else
For Each tree In SyntaxTrees
......@@ -680,13 +681,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
If tasks IsNot Nothing Then
Dim worker As Task = Task.Run(
Sub()
Try
visitor(symbol)
Catch e As Exception When FatalError.ReportUnlessCanceled(e)
Throw ExceptionUtilities.Unreachable
End Try
End Sub,
UICultureUtilities.WithCurrentUICulture(
Sub()
Try
visitor(symbol)
Catch e As Exception When FatalError.ReportUnlessCanceled(e)
Throw ExceptionUtilities.Unreachable
End Try
End Sub),
cancellationToken)
tasks.Push(worker)
Else
......
......@@ -117,10 +117,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Throw New ArgumentNullException("changes")
End If
Dim scanner As Scanner
Dim scanner As scanner
If changes.Length = 1 AndAlso changes(0).Span = New TextSpan(0, Me.Length) AndAlso changes(0).NewLength = newText.Length Then
' if entire text is replaced then do a full reparse
scanner = New Scanner(newText, Options)
scanner = New scanner(newText, Options)
Else
scanner = New Blender(newText, changes, Me, Me.Options)
End If
......@@ -231,7 +231,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
options = If(options, VisualBasicParseOptions.Default)
Dim node As InternalSyntax.CompilationUnitSyntax
Using parser As New Parser(text, options, cancellationToken)
Using parser As New parser(text, options, cancellationToken)
node = parser.ParseCompilationUnit()
End Using
......@@ -521,7 +521,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Friend Function IsAnyPreprocessorSymbolDefined(conditionalSymbolNames As IEnumerable(Of String), atNode As SyntaxNodeOrToken) As Boolean
Debug.Assert(conditionalSymbolNames IsNot Nothing)
Dim conditionalSymbolsMap As ConditionalSymbolsMap = Me.ConditionalSymbols
Dim conditionalSymbolsMap As conditionalSymbolsMap = Me.ConditionalSymbols
If conditionalSymbolsMap Is Nothing Then
Return False
End If
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册