diff --git a/eng/Versions.props b/eng/Versions.props index cfb3ff2ab68..f2faf3a9658 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -124,7 +124,7 @@ $(RoslynVersion) $(RoslynVersion) $(RoslynVersion) - $(RoslynVersion) + $(RoslynVersion) $(RoslynVersion) $(RoslynVersion) 2.0.28 diff --git a/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj b/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj index 278ee438053..0cea852926e 100644 --- a/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj +++ b/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj @@ -59,7 +59,6 @@ - diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 6e1daff174e..548ac9e390a 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -105,8 +105,7 @@ - + false @@ -119,7 +118,6 @@ - diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index 6af186bb999..3dedf85d8e8 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -152,11 +152,9 @@ - - diff --git a/vsintegration/src/FSharp.LanguageService/FSharp.LanguageService.fsproj b/vsintegration/src/FSharp.LanguageService/FSharp.LanguageService.fsproj index 49c902d7704..d247d927341 100644 --- a/vsintegration/src/FSharp.LanguageService/FSharp.LanguageService.fsproj +++ b/vsintegration/src/FSharp.LanguageService/FSharp.LanguageService.fsproj @@ -58,9 +58,7 @@ - - diff --git a/vsintegration/src/FSharp.PatternMatcher/BKTree.Builder.cs b/vsintegration/src/FSharp.PatternMatcher/BKTree.Builder.cs index 42926a67ac5..b05c1bc3453 100644 --- a/vsintegration/src/FSharp.PatternMatcher/BKTree.Builder.cs +++ b/vsintegration/src/FSharp.PatternMatcher/BKTree.Builder.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Utilities; using System; using System.Collections.Generic; diff --git a/vsintegration/src/FSharp.PatternMatcher/CaseSensitiveComparison.cs b/vsintegration/src/FSharp.PatternMatcher/CaseSensitiveComparison.cs deleted file mode 100644 index cfbfabd718f..00000000000 --- a/vsintegration/src/FSharp.PatternMatcher/CaseSensitiveComparison.cs +++ /dev/null @@ -1,311 +0,0 @@ -using Roslyn.Utilities; -using System; -using System.Diagnostics; -using System.Globalization; -using System.Reflection.Internal; -using System.Text; - -namespace Microsoft.CodeAnalysis.Utilities -{ - internal 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; - - private static CultureInfo GetUnicodeCulture() - { - try - { - // We use the "en" culture to get the Unicode ToLower mapping, as it implements - // a much more recent Unicode version (6.0+) than the invariant culture (1.0), - // and it matches the Unicode version used for character categorization. - return new CultureInfo("en"); - } - catch (ArgumentException) // System.Globalization.CultureNotFoundException not on all platforms - { - // If "en" is not available, fall back to the invariant culture. Although it has bugs - // specific to the invariant culture (e.g. being version-locked to Unicode 1.0), at least - // we can rely on it being present on all platforms. - return CultureInfo.InvariantCulture; - } - } - - /// - /// ToLower implements the Unicode lowercase mapping - /// as described in ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt. - /// VB uses these mappings for case-insensitive comparison. - /// - /// - /// If is upper case, then this returns its Unicode lower case equivalent. Otherwise, is returned unmodified. - public static char ToLower(char c) - { - // PERF: This is a very hot code path in VB, optimize for ASCII - - // Perform a range check with a single compare by using unsigned arithmetic - if (unchecked((uint)(c - 'A')) <= ('Z' - 'A')) - { - return (char)(c | 0x20); - } - - if (c < 0xC0) // Covers ASCII (U+0000 - U+007F) and up to the next upper-case codepoint (Latin Capital Letter A with Grave) - { - return c; - } - - return ToLowerNonAscii(c); - } - - private static char ToLowerNonAscii(char c) - { - if (c == '\u0130') - { - // Special case Turkish I (LATIN CAPITAL LETTER I WITH DOT ABOVE) - // This corrects for the fact that the invariant culture only supports Unicode 1.0 - // and therefore does not "know about" this character. - return 'i'; - } - - return s_unicodeCultureTextInfo.ToLower(c); - } - - /// - /// This class seeks to perform the lowercase Unicode case mapping. - /// - private sealed class OneToOneUnicodeComparer : StringComparer - { - private static int CompareLowerUnicode(char c1, char c2) - { - return (c1 == c2) ? 0 : ToLower(c1) - ToLower(c2); - } - - public override int Compare(string str1, string str2) - { - if ((object)str1 == str2) - { - return 0; - } - - if ((object)str1 == null) - { - return -1; - } - - if ((object)str2 == null) - { - return 1; - } - - int len = Math.Min(str1.Length, str2.Length); - for (int i = 0; i < len; i++) - { - int ordDiff = CompareLowerUnicode(str1[i], str2[i]); - if (ordDiff != 0) - { - return ordDiff; - } - } - - // return the smaller string, or 0 if they are equal in length - return str1.Length - str2.Length; - } - - private static bool AreEqualLowerUnicode(char c1, char c2) - { - return c1 == c2 || ToLower(c1) == ToLower(c2); - } - - public override bool Equals(string str1, string str2) - { - if ((object)str1 == str2) - { - return true; - } - - if ((object)str1 == null || (object)str2 == null) - { - return false; - } - - if (str1.Length != str2.Length) - { - return false; - } - - for (int i = 0; i < str1.Length; i++) - { - if (!AreEqualLowerUnicode(str1[i], str2[i])) - { - return false; - } - } - - return true; - } - - public static bool EndsWith(string value, string possibleEnd) - { - if ((object)value == possibleEnd) - { - return true; - } - - if ((object)value == null || (object)possibleEnd == null) - { - return false; - } - - int i = value.Length - 1; - int j = possibleEnd.Length - 1; - - if (i < j) - { - return false; - } - - while (j >= 0) - { - if (!AreEqualLowerUnicode(value[i], possibleEnd[j])) - { - return false; - } - - i--; - j--; - } - - return true; - } - - public static bool StartsWith(string value, string possibleStart) - { - if ((object)value == possibleStart) - { - return true; - } - - if ((object)value == null || (object)possibleStart == null) - { - return false; - } - - if (value.Length < possibleStart.Length) - { - return false; - } - - for (int i = 0; i < possibleStart.Length; i++) - { - if (!AreEqualLowerUnicode(value[i], possibleStart[i])) - { - return false; - } - } - - return true; - } - - public override int GetHashCode(string str) - { - int hashCode = Hash.FnvOffsetBias; - - for (int i = 0; i < str.Length; i++) - { - hashCode = Hash.CombineFNVHash(hashCode, ToLower(str[i])); - } - - return hashCode; - } - } - - /// - /// Returns a StringComparer that compares strings according the VB identifier comparison rules. - /// - private static readonly OneToOneUnicodeComparer s_comparer = new OneToOneUnicodeComparer(); - - /// - /// Returns a StringComparer that compares strings according the VB identifier comparison rules. - /// - public static StringComparer Comparer => s_comparer; - - /// - /// Determines if two VB identifiers are equal according to the VB identifier comparison rules. - /// - /// First identifier to compare - /// Second identifier to compare - /// true if the identifiers should be considered the same. - public static bool Equals(string left, string right) => s_comparer.Equals(left, right); - - /// - /// Determines if the string 'value' end with string 'possibleEnd'. - /// - /// - /// - /// - public static bool EndsWith(string value, string possibleEnd) => OneToOneUnicodeComparer.EndsWith(value, possibleEnd); - - /// - /// Determines if the string 'value' starts with string 'possibleStart'. - /// - /// - /// - /// - public static bool StartsWith(string value, string possibleStart) => OneToOneUnicodeComparer.StartsWith(value, possibleStart); - - /// - /// Compares two VB identifiers according to the VB identifier comparison rules. - /// - /// First identifier to compare - /// Second identifier to compare - /// -1 if < , 1 if > , 0 if they are equal. - public static int Compare(string left, string right) => s_comparer.Compare(left, right); - - /// - /// Gets a case-insensitive hash code for VB identifiers. - /// - /// identifier to get the hash code for - /// The hash code for the given identifier - public static int GetHashCode(string value) - { - Debug.Assert(value != null); - - return s_comparer.GetHashCode(value); - } - - /// - /// Convert a string to lower case per Unicode - /// - /// - /// - public static string ToLower(string value) - { - if ((object)value == null) - return null; - - if (value.Length == 0) - return value; - - var pooledStrbuilder = PooledStringBuilder.GetInstance(); - StringBuilder builder = pooledStrbuilder.Builder; - - builder.Append(value); - ToLower(builder); - - return pooledStrbuilder.ToStringAndFree(); - } - - /// - /// In-place convert string in StringBuilder to lower case per Unicode rules - /// - /// - public static void ToLower(StringBuilder builder) - { - if (builder == null) - return; - - for (int i = 0; i < builder.Length; i++) - { - builder[i] = ToLower(builder[i]); - } - } - } -} diff --git a/vsintegration/src/FSharp.PatternMatcher/FSharp.PatternMatcher.csproj b/vsintegration/src/FSharp.PatternMatcher/FSharp.PatternMatcher.csproj index 5005944c7fa..20617fd7527 100644 --- a/vsintegration/src/FSharp.PatternMatcher/FSharp.PatternMatcher.csproj +++ b/vsintegration/src/FSharp.PatternMatcher/FSharp.PatternMatcher.csproj @@ -17,4 +17,8 @@ + + + + \ No newline at end of file diff --git a/vsintegration/src/FSharp.PatternMatcher/VersionStamp.cs b/vsintegration/src/FSharp.PatternMatcher/VersionStamp.cs deleted file mode 100644 index 5f27e306a0d..00000000000 --- a/vsintegration/src/FSharp.PatternMatcher/VersionStamp.cs +++ /dev/null @@ -1,253 +0,0 @@ -using Roslyn.Utilities; -using System; -using System.Diagnostics.Contracts; -using System.Threading; - -namespace Microsoft.CodeAnalysis -{ - /// - /// VersionStamp should be only used to compare versions returned by same API. - /// - internal struct VersionStamp : IEquatable, IObjectWritable - { - public static VersionStamp Default => default(VersionStamp); - - private const int GlobalVersionMarker = -1; - private const int InitialGlobalVersion = 10000; - - /// - /// global counter to avoid collision within same session. - /// it starts with a big initial number just for a clarity in debugging - /// - private static int s_globalVersion = InitialGlobalVersion; - - /// - /// time stamp - /// - private readonly DateTime _utcLastModified; - - /// - /// indicate whether there was a collision on same item - /// - private readonly int _localIncrement; - - /// - /// unique version in same session - /// - private readonly int _globalIncrement; - - private VersionStamp(DateTime utcLastModified) - : this(utcLastModified, 0) - { - } - - private VersionStamp(DateTime utcLastModified, int localIncrement) - { - _utcLastModified = utcLastModified; - _localIncrement = localIncrement; - _globalIncrement = GetNextGlobalVersion(); - } - - private VersionStamp(DateTime utcLastModified, int localIncrement, int globalIncrement) - { - _utcLastModified = utcLastModified; - _localIncrement = localIncrement; - _globalIncrement = globalIncrement; - } - - /// - /// Creates a new instance of a VersionStamp. - /// - public static VersionStamp Create() - { - return new VersionStamp(DateTime.UtcNow); - } - - /// - /// Creates a new instance of a version stamp based on the specified DateTime. - /// - public static VersionStamp Create(DateTime utcTimeLastModified) - { - return new VersionStamp(utcTimeLastModified); - } - - /// - /// compare two different versions and return either one of the versions if there is no collision, otherwise, create a new version - /// that can be used later to compare versions between different items - /// - public VersionStamp GetNewerVersion(VersionStamp version) - { - // * NOTE * - // in current design/implementation, there are 4 possible ways for a version to be created. - // - // 1. created from a file stamp (most likely by starting a new session). "increment" will have 0 as value - // 2. created by modifying existing item (text changes, project changes etc). - // "increment" will have either 0 or previous increment + 1 if there was a collision. - // 3. created from deserialization (probably by using persistent service). - // 4. created by accumulating versions of multiple items. - // - // and this method is the one that is responsible for #4 case. - - if (_utcLastModified > version._utcLastModified) - { - return this; - } - - if (_utcLastModified == version._utcLastModified) - { - var thisGlobalVersion = GetGlobalVersion(this); - var thatGlobalVersion = GetGlobalVersion(version); - - if (thisGlobalVersion == thatGlobalVersion) - { - // given versions are same one - return this; - } - - // mark it as global version - // global version can't be moved to newer version. - return new VersionStamp(_utcLastModified, (thisGlobalVersion > thatGlobalVersion) ? thisGlobalVersion : thatGlobalVersion, GlobalVersionMarker); - } - - return version; - } - - /// - /// Gets a new VersionStamp that is guaranteed to be newer than its base one - /// this should only be used for same item to move it to newer version - /// - public VersionStamp GetNewerVersion() - { - // global version can't be moved to newer version - Contract.Requires(_globalIncrement != GlobalVersionMarker); - - var now = DateTime.UtcNow; - var incr = (now == _utcLastModified) ? _localIncrement + 1 : 0; - - return new VersionStamp(now, incr); - } - - /// - /// Returns the serialized text form of the VersionStamp. - /// - public override string ToString() - { - // 'o' is the roundtrip format that captures the most detail. - return _utcLastModified.ToString("o") + "-" + _globalIncrement + "-" + _localIncrement; - } - - public override int GetHashCode() - { - return Hash.Combine(_utcLastModified.GetHashCode(), _localIncrement); - } - - public override bool Equals(object obj) - { - if (obj is VersionStamp) - { - return this.Equals((VersionStamp)obj); - } - - return false; - } - - public bool Equals(VersionStamp version) - { - if (_utcLastModified == version._utcLastModified) - { - return GetGlobalVersion(this) == GetGlobalVersion(version); - } - - return false; - } - - public static bool operator ==(VersionStamp left, VersionStamp right) - { - return left.Equals(right); - } - - public static bool operator !=(VersionStamp left, VersionStamp right) - { - return !left.Equals(right); - } - - /// - /// check whether given persisted version is re-usable - /// - internal static bool CanReusePersistedVersion(VersionStamp baseVersion, VersionStamp persistedVersion) - { - if (baseVersion == persistedVersion) - { - return true; - } - - // there was a collision, we can't use these - if (baseVersion._localIncrement != 0 || persistedVersion._localIncrement != 0) - { - return false; - } - - return baseVersion._utcLastModified == persistedVersion._utcLastModified; - } - - void IObjectWritable.WriteTo(ObjectWriter writer) - { - WriteTo(writer); - } - - internal void WriteTo(ObjectWriter writer) - { - writer.WriteInt64(_utcLastModified.ToBinary()); - writer.WriteInt32(_localIncrement); - writer.WriteInt32(_globalIncrement); - } - - internal static VersionStamp ReadFrom(ObjectReader reader) - { - var raw = reader.ReadInt64(); - var localIncrement = reader.ReadInt32(); - var globalIncrement = reader.ReadInt32(); - - return new VersionStamp(DateTime.FromBinary(raw), localIncrement, globalIncrement); - } - - private static int GetGlobalVersion(VersionStamp version) - { - // global increment < 0 means it is a global version which has its global increment in local increment - return version._globalIncrement >= 0 ? version._globalIncrement : version._localIncrement; - } - - private static int GetNextGlobalVersion() - { - // REVIEW: not sure what is best way to wrap it when it overflows. should I just throw or don't care. - // with 50ms (typing) as an interval for a new version, it gives more than 1 year before int32 to overflow. - // with 5ms as an interval, it gives more than 120 days before it overflows. - // since global version is only for per VS session, I think we don't need to worry about overflow. - // or we could use Int64 which will give more than a million years turn around even on 1ms interval. - - // this will let versions to be compared safely between multiple items - // without worrying about collision within same session - var globalVersion = Interlocked.Increment(ref VersionStamp.s_globalVersion); - - return globalVersion; - } - - /// - /// True if this VersionStamp is newer than the specified one. - /// - internal bool TestOnly_IsNewerThan(VersionStamp version) - { - if (_utcLastModified > version._utcLastModified) - { - return true; - } - - if (_utcLastModified == version._utcLastModified) - { - return GetGlobalVersion(this) > GetGlobalVersion(version); - } - - return false; - } - } -} \ No newline at end of file diff --git a/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj b/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj index 4b7ef972b0d..58862ce6747 100644 --- a/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj +++ b/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj @@ -48,7 +48,6 @@ - diff --git a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj index 4caa4aa00f9..2b73f1deb0e 100644 --- a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj +++ b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj @@ -164,9 +164,7 @@ - -