/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/Test/Utilities/CSharp/TestSources.cs
592 строки
17 KB
Jan Jones
Unsafe evolution: avoid interior effect of `unsafe` modifier on members (#83452)
07 май 2026, 15:33
Не верифицирован
07 май 2026, 15:33
927e375
Код
Авторство
О чём код?
// 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. #nullable disable namespace Microsoft.CodeAnalysis.CSharp.Test.Utilities { internal static class TestSources { internal static readonly string Span = @" namespace System { public readonly ref struct Span<T> { internal readonly T[] arr; internal readonly int start; public ref T this[int i] => ref arr[start + i]; public override int GetHashCode() => 1; public int Length { get; } public bool IsEmpty => Length == 0; unsafe public Span(void* pointer, int length) { unsafe { this.arr = Helpers.ToArray<T>(pointer, length); } this.start = 0; this.Length = length; } public Span(T[] arr) { this.arr = arr; this.start = 0; this.Length = arr is null ? 0 : arr.Length; } public Span(T[] arr, int start, int length) { if (start + length > arr?.Length) { throw new ArgumentOutOfRangeException(); } this.arr = arr; this.start = start; this.Length = length; } public static Span<T> Empty => default; public void CopyTo(Span<T> other) { Array.Copy(arr, start, other.arr, other.start, Length); } /// <summary>Gets an enumerator for this span.</summary> public Enumerator GetEnumerator() => new Enumerator(this); /// <summary>Enumerates the elements of a <see cref=""Span{T}""/>.</summary> public ref struct Enumerator { /// <summary>The span being enumerated.</summary> private readonly Span<T> _span; /// <summary>The next index to yield.</summary> private int _index; /// <summary>Initialize the enumerator.</summary> /// <param name=""span"">The span to enumerate.</param> internal Enumerator(Span<T> span) { _span = span; _index = -1; } /// <summary>Advances the enumerator to the next element of the span.</summary> public bool MoveNext() { int index = _index + 1; if (index < _span.Length) { _index = index; return true; } return false; } /// <summary>Gets the element at the current position of the enumerator.</summary> public ref T Current { get => ref _span[_index]; } } public static implicit operator Span<T>(T[] array) => new Span<T>(array); public static implicit operator ReadOnlySpan<T>(Span<T> span) => new ReadOnlySpan<T>(span.arr); public Span<T> Slice(int offset, int length) => new Span<T>(this.arr, offset, length); public Span<T> Slice(int offset) => Slice(offset, Length - offset); } public readonly ref struct ReadOnlySpan<T> { private readonly T[] arr; private readonly int start; public ref readonly T this[int i] => ref arr[start + i]; public override int GetHashCode() => 2; public int Length { get; } public bool IsEmpty => Length == 0; unsafe public ReadOnlySpan(void* pointer, int length) { unsafe { this.arr = Helpers.ToArray<T>(pointer, length); } this.start = 0; this.Length = length; } public ReadOnlySpan(T[] arr) { this.arr = arr; this.start = 0; this.Length = arr is null ? 0 : arr.Length; } public ReadOnlySpan(T[] arr, int start, int length) { if (start + length > arr?.Length) { throw new ArgumentOutOfRangeException(); } this.arr = arr; this.start = start; this.Length = length; } public static ReadOnlySpan<T> Empty => default; public void CopyTo(Span<T> other) { Array.Copy(arr, start, other.arr, other.start, Length); } /// <summary>Gets an enumerator for this span.</summary> public Enumerator GetEnumerator() => new Enumerator(this); /// <summary>Enumerates the elements of a <see cref=""Span{T}""/>.</summary> public ref struct Enumerator { /// <summary>The span being enumerated.</summary> private readonly ReadOnlySpan<T> _span; /// <summary>The next index to yield.</summary> private int _index; /// <summary>Initialize the enumerator.</summary> /// <param name=""span"">The span to enumerate.</param> internal Enumerator(ReadOnlySpan<T> span) { _span = span; _index = -1; } /// <summary>Advances the enumerator to the next element of the span.</summary> public bool MoveNext() { int index = _index + 1; if (index < _span.Length) { _index = index; return true; } return false; } /// <summary>Gets the element at the current position of the enumerator.</summary> public ref readonly T Current { get => ref _span[_index]; } } public static implicit operator ReadOnlySpan<T>(T[] array) => array == null ? default : new ReadOnlySpan<T>(array); // NOTE: This is defined on String in the BCL (and the target type is non-generic ReadOnlySpan<char>). public static implicit operator ReadOnlySpan<T>(string stringValue) => string.IsNullOrEmpty(stringValue) ? default : new ReadOnlySpan<T>((T[])(object)stringValue.ToCharArray()); public ReadOnlySpan<T> Slice(int offset, int length) => new ReadOnlySpan<T>(this.arr, offset, length); public ReadOnlySpan<T> Slice(int offset) => Slice(offset, Length - offset); #nullable enable public static ReadOnlySpan<T> CastUp<TDerived>(ReadOnlySpan<TDerived> items) where TDerived : class?, T { return new ReadOnlySpan<T>(items.arr, items.start, items.Length); } #nullable restore } public readonly ref struct SpanLike<T> { public readonly Span<T> field; } public enum Color: sbyte { Red, Green, Blue } public static class Helpers { public static unsafe T[] ToArray<T>(void* ptr, int count) { unsafe { if (ptr == null) { return null; } if (typeof(T) == typeof(sbyte)) { var arr = new sbyte[count]; for(int i = 0; i < count; i++) { arr[i] = ((sbyte*)ptr)[i]; } return (T[])(object)arr; } if (typeof(T) == typeof(byte)) { var arr = new byte[count]; for(int i = 0; i < count; i++) { arr[i] = ((byte*)ptr)[i]; } return (T[])(object)arr; } if (typeof(T) == typeof(short)) { var arr = new short[count]; for(int i = 0; i < count; i++) { arr[i] = ((short*)ptr)[i]; } return (T[])(object)arr; } if (typeof(T) == typeof(ushort)) { var arr = new ushort[count]; for(int i = 0; i < count; i++) { arr[i] = ((ushort*)ptr)[i]; } return (T[])(object)arr; } if (typeof(T) == typeof(int)) { var arr = new int[count]; for(int i = 0; i < count; i++) { arr[i] = ((int*)ptr)[i]; } return (T[])(object)arr; } if (typeof(T) == typeof(uint)) { var arr = new uint[count]; for(int i = 0; i < count; i++) { arr[i] = ((uint*)ptr)[i]; } return (T[])(object)arr; } if (typeof(T) == typeof(long)) { var arr = new long[count]; for(int i = 0; i < count; i++) { arr[i] = ((long*)ptr)[i]; } return (T[])(object)arr; } if (typeof(T) == typeof(ulong)) { var arr = new ulong[count]; for(int i = 0; i < count; i++) { arr[i] = ((ulong*)ptr)[i]; } return (T[])(object)arr; } if (typeof(T) == typeof(char)) { var arr = new char[count]; for(int i = 0; i < count; i++) { arr[i] = ((char*)ptr)[i]; } return (T[])(object)arr; } if (typeof(T) == typeof(Color)) { var arr = new Color[count]; for(int i = 0; i < count; i++) { arr[i] = ((Color*)ptr)[i]; } return (T[])(object)arr; } throw new Exception(""add a case for: "" + typeof(T)); } } } }"; internal static readonly string Index = @" namespace System { using System.Runtime.CompilerServices; public readonly struct Index : IEquatable<Index> { private readonly int _value; [MethodImpl(MethodImplOptions.AggressiveInlining)] public Index(int value, bool fromEnd = false) { if (value < 0) { throw new ArgumentOutOfRangeException(); } if (fromEnd) _value = ~value; else _value = value; } // The following private constructors mainly created for perf reason to avoid the checks private Index(int value) { _value = value; } /// <summary>Create an Index pointing at first element.</summary> public static Index Start => new Index(0); /// <summary>Create an Index pointing at beyond last element.</summary> public static Index End => new Index(~0); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Index FromStart(int value) { if (value < 0) { throw new ArgumentOutOfRangeException(); } return new Index(value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Index FromEnd(int value) { if (value < 0) { throw new ArgumentOutOfRangeException(); } return new Index(~value); } /// <summary>Returns the index value.</summary> public int Value { get { if (_value < 0) return ~_value; else return _value; } } public bool IsFromEnd => _value < 0; [MethodImpl(MethodImplOptions.AggressiveInlining)] public int GetOffset(int length) { int offset; if (IsFromEnd) offset = length - (~_value); else offset = _value; return offset; } public override bool Equals(object value) => value is Index && _value == ((Index)value)._value; public bool Equals (Index other) => _value == other._value; public override int GetHashCode() => _value; public static implicit operator Index(int value) => FromStart(value); public override string ToString() => IsFromEnd ? ""^"" + Value.ToString() : Value.ToString(); } }"; internal static readonly string Range = @" namespace System { using System.Runtime.CompilerServices; public readonly struct Range { public Index Start { get; } public Index End { get; } public Range(Index start, Index end) { Start = start; End = end; } public static Range StartAt(Index start) => new Range(start, Index.End); public static Range EndAt(Index end) => new Range(Index.Start, end); public static Range All => new Range(Index.Start, Index.End); [MethodImpl(MethodImplOptions.AggressiveInlining)] public OffsetAndLength GetOffsetAndLength(int length) { int start; Index startIndex = Start; if (startIndex.IsFromEnd) start = length - startIndex.Value; else start = startIndex.Value; int end; Index endIndex = End; if (endIndex.IsFromEnd) end = length - endIndex.Value; else end = endIndex.Value; if ((uint)end > (uint)length || (uint)start > (uint)end) { throw new ArgumentOutOfRangeException(); } return new OffsetAndLength(start, end - start); } public readonly struct OffsetAndLength { public int Offset { get; } public int Length { get; } public OffsetAndLength(int offset, int length) { Offset = offset; Length = length; } public void Deconstruct(out int offset, out int length) { offset = Offset; length = Length; } } public override string ToString() => $""{Start}..{End}""; } }"; public static readonly string GetSubArray = @" namespace System.Runtime.CompilerServices { public static class RuntimeHelpers { public static T[] GetSubArray<T>(T[] array, Range range) { Type elementType = array.GetType().GetElementType(); var (offset, length) = range.GetOffsetAndLength(array.Length); T[] newArray = (T[])Array.CreateInstance(elementType, length); Array.Copy(array, offset, newArray, 0, length); return newArray; } } }"; public static readonly string ITuple = @" namespace System.Runtime.CompilerServices { public interface ITuple { int Length { get; } object this[int index] { get; } } }"; public static readonly string MemoryExtensions = @" namespace System { public static class MemoryExtensions { public static bool SequenceEqual<T> (this ReadOnlySpan<T> span, ReadOnlySpan<T> other) where T : IEquatable<T> { // unoptimized implementation for testing purposes if (span.Length != other.Length) return false; for(var i = 0; i < span.Length; i++) { if (!span[i].Equals(other[i])) return false; } return true; } public static bool SequenceEqual<T> (this Span<T> span, ReadOnlySpan<T> other) where T : IEquatable<T> { // unoptimized implementation for testing purposes if (span.Length != other.Length) return false; for(var i = 0; i < span.Length; i++) { if (!span[i].Equals(other[i])) return false; } return true; } public static ReadOnlySpan<char> AsSpan(this string text) => string.IsNullOrEmpty(text) ? default : new ReadOnlySpan<char>(text.ToCharArray()); public static Span<T> AsSpan<T>(this T[] array) => new Span<T>(array); } }"; public static readonly string ParamsCollectionAttribute = """ namespace System.Runtime.CompilerServices { public sealed class ParamCollectionAttribute : Attribute { public ParamCollectionAttribute() { } } } """; public static readonly string InterceptsLocationAttribute = """ namespace System.Runtime.CompilerServices; [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)] public sealed class InterceptsLocationAttribute : Attribute { public InterceptsLocationAttribute(string filePath, int line, int character) { } public InterceptsLocationAttribute(int version, string data) { } } """; } }