Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove dependency on all Roslyn assemblies from build host #73497

Merged
merged 4 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Roslyn.sln
Original file line number Diff line number Diff line change
Expand Up @@ -1698,6 +1698,8 @@ Global
src\ExpressionEvaluator\Core\Source\ResultProvider\ResultProvider.projitems*{abdbac1e-350e-4dc3-bb45-3504404545ee}*SharedItemsImports = 5
src\ExpressionEvaluator\VisualBasic\Source\ResultProvider\BasicResultProvider.projitems*{ace53515-482c-4c6a-e2d2-4242a687dfee}*SharedItemsImports = 5
src\Compilers\CSharp\csc\CscCommandLine.projitems*{b021ccbc-b2af-4560-af28-ed055f0ed696}*SharedItemsImports = 13
src\Dependencies\Collections\Microsoft.CodeAnalysis.Collections.projitems*{b1481d94-682e-46ec-adbe-a16eb46feee9}*SharedItemsImports = 5
src\Dependencies\PooledObjects\Microsoft.CodeAnalysis.PooledObjects.projitems*{b1481d94-682e-46ec-adbe-a16eb46feee9}*SharedItemsImports = 5
src\Compilers\CSharp\CSharpAnalyzerDriver\CSharpAnalyzerDriver.projitems*{b501a547-c911-4a05-ac6e-274a50dff30e}*SharedItemsImports = 5
src\ExpressionEvaluator\Core\Source\ResultProvider\ResultProvider.projitems*{bb3ca047-5d00-48d4-b7d3-233c1265c065}*SharedItemsImports = 13
src\ExpressionEvaluator\CSharp\Source\ResultProvider\CSharpResultProvider.projitems*{bf9dac1e-3a5e-4dc3-bb44-9a64e0d4e9d4}*SharedItemsImports = 5
Expand Down
7 changes: 6 additions & 1 deletion src/Compilers/Core/Portable/CaseInsensitiveComparison.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ namespace Microsoft.CodeAnalysis
/// <summary>
/// Case-insensitive operations (mostly comparison) on unicode strings.
/// </summary>
public static class CaseInsensitiveComparison
#if COMPILERCORE
public
#else
internal
#endif
static class CaseInsensitiveComparison
{
// PERF: Cache a TextInfo for Unicode ToLower since this will be accessed very frequently
private static readonly TextInfo s_unicodeCultureTextInfo = GetUnicodeCulture().TextInfo;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -764,19 +764,6 @@ public static ImmutableArray<T> Distinct<T>(this ImmutableArray<T> array, IEqual
return result;
}

internal static bool HasAnyErrors<T>(this ImmutableArray<T> diagnostics) where T : Diagnostic
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved

{
foreach (var diagnostic in diagnostics)
{
if (diagnostic.Severity == DiagnosticSeverity.Error)
{
return true;
}
}

return false;
}

// In DEBUG, swap the first and last elements of a read-only array, yielding a new read only array.
// This helps to avoid depending on accidentally sorted arrays.
internal static ImmutableArray<T> ConditionallyDeOrder<T>(this ImmutableArray<T> array)
Expand Down Expand Up @@ -1034,8 +1021,8 @@ internal static void CreateNameToMembersMap<TKey, TNamespaceOrTypeSymbol, TNamed
where TNamedTypeSymbol : class, TNamespaceOrTypeSymbol
where TNamespaceSymbol : class, TNamespaceOrTypeSymbol
{
foreach (var (name, value) in dictionary)
result.Add(name, createMembers(value));
foreach (var entry in dictionary)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid dependency on KeyValuePair deconstructor extension

result.Add(entry.Key, createMembers(entry.Value));

return;

Expand Down Expand Up @@ -1076,11 +1063,11 @@ internal static Dictionary<TKey, ImmutableArray<TNamedTypeSymbol>> GetTypesFromM

var dictionary = new Dictionary<TKey, ImmutableArray<TNamedTypeSymbol>>(capacity, comparer);

foreach (var (name, members) in map)
foreach (var entry in map)
{
var namedTypes = getOrCreateNamedTypes(members);
var namedTypes = getOrCreateNamedTypes(entry.Value);
if (namedTypes.Length > 0)
dictionary.Add(name, namedTypes);
dictionary.Add(entry.Key, namedTypes);
}

return dictionary;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections.Immutable;

namespace Microsoft.CodeAnalysis;

internal static class DiagnosticArrayExtensions
{
internal static bool HasAnyErrors<T>(this ImmutableArray<T> diagnostics) where T : Diagnostic
{
foreach (var diagnostic in diagnostics)
{
if (diagnostic.Severity == DiagnosticSeverity.Error)
{
return true;
}
}

return false;
}
}
2 changes: 1 addition & 1 deletion src/Compilers/Core/Portable/EncodedStringText.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ private static SourceText Decode(
data.Seek(0, SeekOrigin.Begin);

// For small streams, see if we can read the byte buffer directly.
if (encoding.GetMaxCharCountOrThrowIfHuge(data) < LargeObjectHeapLimitInChars)
if (encoding.TryGetMaxCharCount(data.Length, out int maxCharCount) && maxCharCount < LargeObjectHeapLimitInChars)
{
if (TryGetBytesFromStream(data, out ArraySegment<byte> bytes) && bytes.Offset == 0 && bytes.Array is object)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,13 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.CodeAnalysis;
using System;
using System.Diagnostics;
using System.IO;
using System.Text;

namespace Microsoft.CodeAnalysis
{
internal static partial class EncodingExtensions
{
/// <summary>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved and simplified

/// Get maximum char count needed to decode the entire stream.
/// </summary>
/// <exception cref="IOException">Stream is so big that max char count can't fit in <see cref="int"/>.</exception>
internal static int GetMaxCharCountOrThrowIfHuge(this Encoding encoding, Stream stream)
{
Debug.Assert(stream.CanSeek);
long length = stream.Length;

if (encoding.TryGetMaxCharCount(length, out int maxCharCount))
{
return maxCharCount;
}

#if CODE_STYLE
throw new IOException(CodeStyleResources.Stream_is_too_long);
#elif WORKSPACE
throw new IOException(WorkspacesResources.Stream_is_too_long);
#else
throw new IOException(CodeAnalysisResources.StreamIsTooLong);
#endif
}

internal static bool TryGetMaxCharCount(this Encoding encoding, long length, out int maxCharCount)
{
maxCharCount = 0;
Expand Down
39 changes: 0 additions & 39 deletions src/Compilers/Core/Portable/InternalUtilities/EnumUtilties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,45 +11,6 @@ namespace Roslyn.Utilities
{
internal static class EnumUtilities
{
/// <summary>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved, renamed and simplified

/// Convert a boxed primitive (generally of the backing type of an enum) into a ulong.
/// </summary>
/// <remarks>
/// </remarks>
internal static ulong ConvertEnumUnderlyingTypeToUInt64(object value, SpecialType specialType)
{
RoslynDebug.Assert(value != null);
Debug.Assert(value.GetType().GetTypeInfo().IsPrimitive);

unchecked
{
switch (specialType)
{
case SpecialType.System_SByte:
return (ulong)(sbyte)value;
case SpecialType.System_Int16:
return (ulong)(short)value;
case SpecialType.System_Int32:
return (ulong)(int)value;
case SpecialType.System_Int64:
return (ulong)(long)value;
case SpecialType.System_Byte:
return (byte)value;
case SpecialType.System_UInt16:
return (ushort)value;
case SpecialType.System_UInt32:
return (uint)value;
case SpecialType.System_UInt64:
return (ulong)value;

default:
// not using ExceptionUtilities.UnexpectedValue() because this is used by the Services layer
// which doesn't have those utilities.
throw new InvalidOperationException(string.Format("{0} is not a valid underlying type for an enum", specialType));
}
}
}

internal static T[] GetValues<T>() where T : struct
{
return (T[])Enum.GetValues(typeof(T));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,8 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using System.Threading;
using Microsoft.CodeAnalysis.PooledObjects;

namespace Roslyn.Utilities
{
Expand Down
27 changes: 27 additions & 0 deletions src/Compilers/Core/Portable/SpecialTypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Diagnostics;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis
Expand Down Expand Up @@ -364,5 +365,31 @@ public static SpecialType FromRuntimeTypeOfLiteralValue(object value)
/// </summary>
public static bool CanOptimizeBehavior(this SpecialType specialType)
=> specialType is >= SpecialType.System_Object and <= SpecialType.System_Runtime_CompilerServices_InlineArrayAttribute;

/// <summary>
/// Convert a boxed primitive (generally of the backing type of an enum) into a ulong.
/// </summary>
internal static ulong ConvertUnderlyingValueToUInt64(this SpecialType enumUnderlyingType, object value)
{
RoslynDebug.Assert(value != null);
Debug.Assert(value.GetType().IsPrimitive);

unchecked
{
return enumUnderlyingType switch
{
SpecialType.System_SByte => (ulong)(sbyte)value,
SpecialType.System_Int16 => (ulong)(short)value,
SpecialType.System_Int32 => (ulong)(int)value,
SpecialType.System_Int64 => (ulong)(long)value,
SpecialType.System_Byte => (byte)value,
SpecialType.System_UInt16 => (ushort)value,
SpecialType.System_UInt32 => (uint)value,
SpecialType.System_UInt64 => (ulong)value,
_ => throw ExceptionUtilities.UnexpectedValue(enumUnderlyingType),
};
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ private void AddFlagsEnumConstantValue(
{
Debug.Assert(enumType.EnumUnderlyingType is not null);
var underlyingSpecialType = enumType.EnumUnderlyingType.SpecialType;
var constantValueULong = EnumUtilities.ConvertEnumUnderlyingTypeToUInt64(constantValue, underlyingSpecialType);
var constantValueULong = underlyingSpecialType.ConvertUnderlyingValueToUInt64(constantValue);

var result = constantValueULong;

Expand Down Expand Up @@ -321,7 +321,7 @@ private static void GetSortedEnumFields(
var field = (IFieldSymbol)member;
if (field.HasConstantValue)
{
var enumField = new EnumField(field.Name, EnumUtilities.ConvertEnumUnderlyingTypeToUInt64(field.ConstantValue, underlyingSpecialType), field);
var enumField = new EnumField(field.Name, underlyingSpecialType.ConvertUnderlyingValueToUInt64(field.ConstantValue), field);
enumFields.Add(enumField);
}
}
Expand All @@ -334,7 +334,7 @@ private void AddNonFlagsEnumConstantValue(INamedTypeSymbol enumType, object cons
{
Debug.Assert(enumType.EnumUnderlyingType is not null);
var underlyingSpecialType = enumType.EnumUnderlyingType.SpecialType;
var constantValueULong = EnumUtilities.ConvertEnumUnderlyingTypeToUInt64(constantValue, underlyingSpecialType);
var constantValueULong = underlyingSpecialType.ConvertUnderlyingValueToUInt64(constantValue);

var enumFields = ArrayBuilder<EnumField>.GetInstance();
GetSortedEnumFields(enumType, enumFields);
Expand Down
7 changes: 6 additions & 1 deletion src/Compilers/Core/Portable/Symbols/LanguageNames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ namespace Microsoft.CodeAnalysis
/// <summary>
/// A class that provides constants for common language names.
/// </summary>
public static class LanguageNames
#if COMPILERCORE
public
#else
internal
#endif
static class LanguageNames
{
/// <summary>
/// The common name used for the C# language.
Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/Core/Portable/Text/LargeText.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ internal static SourceText Decode(Stream stream, Encoding encoding, SourceHashAl
return SourceText.From(string.Empty, encoding, checksumAlgorithm);
}

var maxCharRemainingGuess = encoding.GetMaxCharCountOrThrowIfHuge(stream);
var maxCharRemainingGuess = GetMaxCharCountOrThrowIfHuge(encoding, stream);
Debug.Assert(longLength > 0 && longLength <= int.MaxValue); // GetMaxCharCountOrThrowIfHuge should have thrown.
int length = (int)longLength;

Expand Down
18 changes: 17 additions & 1 deletion src/Compilers/Core/Portable/Text/SourceText.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ public static SourceText From(
if (stream.CanSeek)
{
// If the resulting string would end up on the large object heap, then use LargeEncodedText.
if (encoding.GetMaxCharCountOrThrowIfHuge(stream) >= LargeObjectHeapLimitInChars)
if (GetMaxCharCountOrThrowIfHuge(encoding, stream) >= LargeObjectHeapLimitInChars)
{
return LargeText.Decode(stream, encoding, checksumAlgorithm, throwIfBinaryDetected, canBeEmbedded);
}
Expand Down Expand Up @@ -1260,5 +1260,21 @@ public override event EventHandler<TextChangeEventArgs> TextChanged
}
}
}

/// <summary>
/// Get maximum char count needed to decode the entire stream.
/// </summary>
/// <exception cref="IOException">Stream is so big that max char count can't fit in <see cref="int"/>.</exception>
internal static int GetMaxCharCountOrThrowIfHuge(Encoding encoding, Stream stream)
{
Debug.Assert(stream.CanSeek);

if (encoding.TryGetMaxCharCount(stream.Length, out int maxCharCount))
{
return maxCharCount;
}

throw new IOException(CodeAnalysisResources.StreamIsTooLong);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ private async Task<bool> LoadOrReloadProjectAsync(ProjectToLoad projectToLoad, T

var loadedFile = await buildHost.LoadProjectFileAsync(projectPath, languageName, cancellationToken);
var diagnosticLogItems = await loadedFile.GetDiagnosticLogItemsAsync(cancellationToken);
if (diagnosticLogItems.Any(item => item.Kind is WorkspaceDiagnosticKind.Failure))
if (diagnosticLogItems.Any(item => item.Kind is DiagnosticLogItemKind.Error))
{
await LogDiagnosticsAsync(diagnosticLogItems);
// We have total failures in evaluation, no point in continuing.
Expand Down Expand Up @@ -292,7 +292,7 @@ private async Task<bool> LoadOrReloadProjectAsync(ProjectToLoad projectToLoad, T
{
// Since our LogDiagnosticsAsync helper takes DiagnosticLogItems, let's just make one for this
var message = string.Format(LanguageServerResources.Exception_thrown_0, e);
var diagnosticLogItem = new DiagnosticLogItem(WorkspaceDiagnosticKind.Failure, message, projectPath);
var diagnosticLogItem = new DiagnosticLogItem(DiagnosticLogItemKind.Error, message, projectPath);
await LogDiagnosticsAsync([diagnosticLogItem]);

return false;
Expand All @@ -303,10 +303,10 @@ async Task LogDiagnosticsAsync(ImmutableArray<DiagnosticLogItem> diagnosticLogIt
foreach (var logItem in diagnosticLogItems)
{
var projectName = Path.GetFileName(projectPath);
_logger.Log(logItem.Kind is WorkspaceDiagnosticKind.Failure ? LogLevel.Error : LogLevel.Warning, $"{logItem.Kind} while loading {logItem.ProjectFilePath}: {logItem.Message}");
_logger.Log(logItem.Kind is DiagnosticLogItemKind.Error ? LogLevel.Error : LogLevel.Warning, $"{logItem.Kind} while loading {logItem.ProjectFilePath}: {logItem.Message}");
}

var worstLspMessageKind = diagnosticLogItems.Any(logItem => logItem.Kind is WorkspaceDiagnosticKind.Failure) ? LSP.MessageType.Error : LSP.MessageType.Warning;
var worstLspMessageKind = diagnosticLogItems.Any(logItem => logItem.Kind is DiagnosticLogItemKind.Error) ? LSP.MessageType.Error : LSP.MessageType.Warning;

string message;

Expand Down
10 changes: 3 additions & 7 deletions src/Workspaces/Core/MSBuild.BuildHost/BuildHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

extern alias workspaces;
using System.Collections.Immutable;
using System.IO;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -101,11 +101,7 @@ private bool TryEnsureMSBuildLoaded(string projectOrSolutionFilePath)
}
}

#if NET472 || NET6_0 // If we're compiling against net472 or net6.0, we get our MemberNotNull from the workspaces assembly. It has it in the net6.0 case since we're consuming the netstandard2.0 version of Workspaces.
[workspaces::System.Diagnostics.CodeAnalysis.MemberNotNull(nameof(_buildManager))]
#else // If we're compiling against net7.0 or higher, then we're getting it staright from the framework.
[System.Diagnostics.CodeAnalysis.MemberNotNull(nameof(_buildManager))]
#endif
[MemberNotNull(nameof(_buildManager))]
tmat marked this conversation as resolved.
Show resolved Hide resolved
[MethodImpl(MethodImplOptions.NoInlining)] // Do not inline this, since this creates MSBuild types which are being loaded by the caller
private void CreateBuildManager()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,6 @@ public CSharpProjectFile(CSharpProjectFileLoader loader, MSB.Evaluation.Project?
{
}

protected override SourceCodeKind GetSourceCodeKind(string documentFileName)
=> SourceCodeKind.Regular;

public override string GetDocumentExtension(SourceCodeKind sourceCodeKind)
=> ".cs";

protected override IEnumerable<MSB.Framework.ITaskItem> GetCompilerCommandLineArgs(MSB.Execution.ProjectInstance executedProject)
=> executedProject.GetItems(ItemNames.CscCommandLineArgs);

Expand Down
Loading