From 3f28017c611d58aca370d67b8e47aabdfcdc6d32 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 14 Apr 2020 18:20:52 -0700 Subject: [PATCH 1/8] Use safe handles for SQLite interop This commit back-ports dotnet/roslyn#43361 to dev16.6. --- .../Shared/Extensions/SafeHandleExtensions.cs | 49 +++++ .../Shared/Extensions/SafeHandleLease.cs | 30 +++ .../Storage/SQLite/Interop/NativeMethods.cs | 172 ++++++++++++++++++ .../Portable/Storage/SQLite/Interop/Result.cs | 2 +- .../SQLite/Interop/SafeSqliteBlobHandle.cs | 25 +++ .../SQLite/Interop/SafeSqliteChildHandle`1.cs | 37 ++++ .../SQLite/Interop/SafeSqliteHandle.cs | 25 +++ .../SQLite/Interop/SafeSqliteHandle`1.cs | 29 +++ .../Interop/SafeSqliteStatementHandle.cs | 25 +++ .../Storage/SQLite/Interop/SqlConnection.cs | 94 +++++----- .../Storage/SQLite/Interop/SqlStatement.cs | 30 +-- 11 files changed, 450 insertions(+), 68 deletions(-) create mode 100644 src/Workspaces/Core/Portable/Shared/Extensions/SafeHandleExtensions.cs create mode 100644 src/Workspaces/Core/Portable/Shared/Extensions/SafeHandleLease.cs create mode 100644 src/Workspaces/Core/Portable/Storage/SQLite/Interop/NativeMethods.cs create mode 100644 src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteBlobHandle.cs create mode 100644 src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteChildHandle`1.cs create mode 100644 src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteHandle.cs create mode 100644 src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteHandle`1.cs create mode 100644 src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteStatementHandle.cs diff --git a/src/Workspaces/Core/Portable/Shared/Extensions/SafeHandleExtensions.cs b/src/Workspaces/Core/Portable/Shared/Extensions/SafeHandleExtensions.cs new file mode 100644 index 0000000000000..7869519621f02 --- /dev/null +++ b/src/Workspaces/Core/Portable/Shared/Extensions/SafeHandleExtensions.cs @@ -0,0 +1,49 @@ +// 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 enable + +using System; +using System.Runtime.InteropServices; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.Shared.Extensions +{ + internal static class SafeHandleExtensions + { + /// + /// Acquires a lease on a safe handle. The lease increments the reference count of the + /// to ensure the handle is not released prior to the lease being released. + /// + /// + /// This method is intended to be used in the initializer of a using statement. Failing to release the + /// lease will permanently prevent the underlying from being released by the garbage + /// collector. + /// + /// The to lease. + /// A , which must be disposed to release the resource. + /// If the lease could not be acquired. + public static SafeHandleLease Lease(this SafeHandle handle) + { + RoslynDebug.AssertNotNull(handle); + + var success = false; + try + { + handle.DangerousAddRef(ref success); + if (!success) + throw new ObjectDisposedException(handle.GetType().FullName); + + return new SafeHandleLease(handle); + } + catch + { + if (success) + handle.DangerousRelease(); + + throw; + } + } + } +} diff --git a/src/Workspaces/Core/Portable/Shared/Extensions/SafeHandleLease.cs b/src/Workspaces/Core/Portable/Shared/Extensions/SafeHandleLease.cs new file mode 100644 index 0000000000000..901fb2d3ec73d --- /dev/null +++ b/src/Workspaces/Core/Portable/Shared/Extensions/SafeHandleLease.cs @@ -0,0 +1,30 @@ +// 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 enable + +using System; +using System.Runtime.InteropServices; + +namespace Microsoft.CodeAnalysis.Shared.Extensions +{ + /// + /// Represents a lease of a . + /// + /// + internal readonly struct SafeHandleLease : IDisposable + { + private readonly SafeHandle? _handle; + + internal SafeHandleLease(SafeHandle handle) + => _handle = handle; + + /// + /// Releases the lease. The behavior of this method is unspecified if called more than + /// once. + /// + public void Dispose() + => _handle?.DangerousRelease(); + } +} diff --git a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/NativeMethods.cs b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/NativeMethods.cs new file mode 100644 index 0000000000000..b6606916bf8e3 --- /dev/null +++ b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/NativeMethods.cs @@ -0,0 +1,172 @@ +// 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 enable + +using System.Diagnostics.CodeAnalysis; +using Microsoft.CodeAnalysis.Shared.Extensions; +using SQLitePCL; + +namespace Microsoft.CodeAnalysis.SQLite.Interop +{ + [SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Name chosen to match SQLitePCL.raw")] + internal static class NativeMethods + { + public static SafeSqliteHandle sqlite3_open_v2(string filename, int flags, string vfs, out Result result) + { + result = (Result)raw.sqlite3_open_v2(filename, out var wrapper, flags, vfs); + if (result != Result.OK) + { + wrapper = null; + } + + try + { + // Always return a non-null handle to match default P/Invoke marshaling behavior. SafeHandle.IsInvalid + // will be true when the handle is not usable, but the handle instance can be disposed either way. + return new SafeSqliteHandle(wrapper); + } + catch + { + raw.sqlite3_close(wrapper); + throw; + } + } + + public static SafeSqliteStatementHandle sqlite3_prepare_v2(SafeSqliteHandle db, string sql, out Result result) + { + using var _ = db.Lease(); + + result = (Result)raw.sqlite3_prepare_v2(db.DangerousGetHandle(), sql, out var wrapper); + if (result != (int)Result.OK) + { + wrapper = null; + } + + try + { + // Always return a non-null handle to match default P/Invoke marshaling behavior. SafeHandle.IsInvalid + // will be true when the handle is not usable, but the handle instance can be disposed either way. + return new SafeSqliteStatementHandle(db, wrapper); + } + catch + { + raw.sqlite3_finalize(wrapper); + throw; + } + } + + public static SafeSqliteBlobHandle sqlite3_blob_open(SafeSqliteHandle db, string sdb, string table, string col, long rowid, int flags, out Result result) + { + using var _ = db.Lease(); + + result = (Result)raw.sqlite3_blob_open(db.DangerousGetHandle(), sdb, table, col, rowid, flags, out var wrapper); + if (result != (int)Result.OK) + { + wrapper = null; + } + + try + { + // Always return a non-null handle to match default P/Invoke marshaling behavior. SafeHandle.IsInvalid + // will be true when the handle is not usable, but the handle instance can be disposed either way. + return new SafeSqliteBlobHandle(db, wrapper); + } + catch + { + raw.sqlite3_blob_close(wrapper); + throw; + } + } + + public static string sqlite3_errmsg(SafeSqliteHandle db) + { + using var _ = db.Lease(); + return raw.sqlite3_errmsg(db.DangerousGetHandle()); + } + + public static string sqlite3_errstr(int rc) + { + return raw.sqlite3_errstr(rc); + } + + public static int sqlite3_extended_errcode(SafeSqliteHandle db) + { + using var _ = db.Lease(); + return raw.sqlite3_extended_errcode(db.DangerousGetHandle()); + } + + public static Result sqlite3_busy_timeout(SafeSqliteHandle db, int ms) + { + using var _ = db.Lease(); + return (Result)raw.sqlite3_busy_timeout(db.DangerousGetHandle(), ms); + } + + public static long sqlite3_last_insert_rowid(SafeSqliteHandle db) + { + using var _ = db.Lease(); + return raw.sqlite3_last_insert_rowid(db.DangerousGetHandle()); + } + + public static int sqlite3_blob_bytes(SafeSqliteBlobHandle blob) + { + using var _ = blob.Lease(); + return raw.sqlite3_blob_bytes(blob.DangerousGetHandle()); + } + + public static Result sqlite3_blob_read(SafeSqliteBlobHandle blob, byte[] b, int n, int offset) + { + using var _ = blob.Lease(); + return (Result)raw.sqlite3_blob_read(blob.DangerousGetHandle(), b, n, offset); + } + + public static Result sqlite3_reset(SafeSqliteStatementHandle stmt) + { + using var _ = stmt.Lease(); + return (Result)raw.sqlite3_reset(stmt.DangerousGetHandle()); + } + + public static Result sqlite3_step(SafeSqliteStatementHandle stmt) + { + using var _ = stmt.Lease(); + return (Result)raw.sqlite3_step(stmt.DangerousGetHandle()); + } + + public static Result sqlite3_bind_text(SafeSqliteStatementHandle stmt, int index, string val) + { + using var _ = stmt.Lease(); + return (Result)raw.sqlite3_bind_text(stmt.DangerousGetHandle(), index, val); + } + + public static Result sqlite3_bind_int64(SafeSqliteStatementHandle stmt, int index, long val) + { + using var _ = stmt.Lease(); + return (Result)raw.sqlite3_bind_int64(stmt.DangerousGetHandle(), index, val); + } + + public static byte[] sqlite3_column_blob(SafeSqliteStatementHandle stmt, int index) + { + using var _ = stmt.Lease(); + return raw.sqlite3_column_blob(stmt.DangerousGetHandle(), index); + } + + public static int sqlite3_column_int(SafeSqliteStatementHandle stmt, int index) + { + using var _ = stmt.Lease(); + return raw.sqlite3_column_int(stmt.DangerousGetHandle(), index); + } + + public static long sqlite3_column_int64(SafeSqliteStatementHandle stmt, int index) + { + using var _ = stmt.Lease(); + return raw.sqlite3_column_int64(stmt.DangerousGetHandle(), index); + } + + public static string sqlite3_column_text(SafeSqliteStatementHandle stmt, int index) + { + using var _ = stmt.Lease(); + return raw.sqlite3_column_text(stmt.DangerousGetHandle(), index); + } + } +} diff --git a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/Result.cs b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/Result.cs index ac58f492f703b..3e09236ab30cc 100644 --- a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/Result.cs +++ b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/Result.cs @@ -10,7 +10,7 @@ namespace Microsoft.CodeAnalysis.SQLite.Interop internal enum Result { OK = 0, /* Successful result */ - // ERROR = 1, /* SQL error or missing database */ + ERROR = 1, /* SQL error or missing database */ // INTERNAL = 2, /* Internal logic error in SQLite */ // PERM = 3, /* Access permission denied */ // ABORT = 4, /* Callback routine requested an abort */ diff --git a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteBlobHandle.cs b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteBlobHandle.cs new file mode 100644 index 0000000000000..f7625834711f6 --- /dev/null +++ b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteBlobHandle.cs @@ -0,0 +1,25 @@ +// 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 enable + +using System; +using SQLitePCL; + +namespace Microsoft.CodeAnalysis.SQLite.Interop +{ + internal sealed class SafeSqliteBlobHandle : SafeSqliteChildHandle + { + public SafeSqliteBlobHandle(SafeSqliteHandle sqliteHandle, sqlite3_blob? wrapper) + : base(sqliteHandle, wrapper?.ptr ?? IntPtr.Zero, wrapper) + { + } + + protected override bool ReleaseChildHandle() + { + var result = (Result)raw.sqlite3_blob_close(Wrapper); + return result == Result.OK; + } + } +} diff --git a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteChildHandle`1.cs b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteChildHandle`1.cs new file mode 100644 index 0000000000000..40a1c7e77265e --- /dev/null +++ b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteChildHandle`1.cs @@ -0,0 +1,37 @@ +// 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 enable + +using System; +using System.Runtime.InteropServices; +using Microsoft.CodeAnalysis.Shared.Extensions; + +namespace Microsoft.CodeAnalysis.SQLite.Interop +{ + /// + /// The base handle type for an SQLite resource that exists within the context of a parent handle, and should always + /// be released prior to the parent handle. + /// + /// The SQLite resource wrapper type. + internal abstract class SafeSqliteChildHandle : SafeSqliteHandle + where T : class + { + private readonly SafeHandleLease _lease; + + protected SafeSqliteChildHandle(SafeHandle parentHandle, IntPtr handle, T? wrapper) + : base(handle, wrapper) + { + _lease = parentHandle.Lease(); + } + + protected abstract bool ReleaseChildHandle(); + + protected sealed override bool ReleaseHandle() + { + using var _ = _lease; + return ReleaseChildHandle(); + } + } +} diff --git a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteHandle.cs b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteHandle.cs new file mode 100644 index 0000000000000..2e66c42857b40 --- /dev/null +++ b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteHandle.cs @@ -0,0 +1,25 @@ +// 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 enable + +using System; +using SQLitePCL; + +namespace Microsoft.CodeAnalysis.SQLite.Interop +{ + internal sealed class SafeSqliteHandle : SafeSqliteHandle + { + public SafeSqliteHandle(sqlite3? wrapper) + : base(wrapper?.ptr ?? IntPtr.Zero, wrapper) + { + } + + protected override bool ReleaseHandle() + { + var result = (Result)raw.sqlite3_close(Wrapper); + return result == Result.OK; + } + } +} diff --git a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteHandle`1.cs b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteHandle`1.cs new file mode 100644 index 0000000000000..77d7462545fab --- /dev/null +++ b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteHandle`1.cs @@ -0,0 +1,29 @@ +// 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 enable + +using System; +using System.Runtime.InteropServices; + +namespace Microsoft.CodeAnalysis.SQLite.Interop +{ + internal abstract class SafeSqliteHandle : SafeHandle + where T : class + { + protected readonly T? Wrapper; + + public SafeSqliteHandle(IntPtr handle, T? wrapper) + : base(invalidHandleValue: IntPtr.Zero, ownsHandle: true) + { + Wrapper = wrapper; + SetHandle(handle); + } + + public override bool IsInvalid => handle == IntPtr.Zero; + + public new T DangerousGetHandle() + => Wrapper!; + } +} diff --git a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteStatementHandle.cs b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteStatementHandle.cs new file mode 100644 index 0000000000000..bea28c3d24420 --- /dev/null +++ b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteStatementHandle.cs @@ -0,0 +1,25 @@ +// 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 enable + +using System; +using SQLitePCL; + +namespace Microsoft.CodeAnalysis.SQLite.Interop +{ + internal sealed class SafeSqliteStatementHandle : SafeSqliteChildHandle + { + public SafeSqliteStatementHandle(SafeSqliteHandle sqliteHandle, sqlite3_stmt? wrapper) + : base(sqliteHandle, wrapper?.ptr ?? IntPtr.Zero, wrapper) + { + } + + protected override bool ReleaseChildHandle() + { + var result = (Result)raw.sqlite3_finalize(Wrapper); + return result == Result.OK; + } + } +} diff --git a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SqlConnection.cs b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SqlConnection.cs index c13a48f48e397..ed836ef282473 100644 --- a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SqlConnection.cs +++ b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SqlConnection.cs @@ -5,10 +5,9 @@ using System; using System.Collections.Generic; using System.IO; -using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.SQLite.Interop; using Roslyn.Utilities; -using SQLitePCL; namespace Microsoft.CodeAnalysis.SQLite.Interop { @@ -30,7 +29,7 @@ internal class SqlConnection /// /// The raw handle to the underlying DB. /// - private readonly sqlite3 _handle; + private readonly SafeSqliteHandle _handle; /// /// For testing purposes to simulate failures during testing. @@ -61,54 +60,39 @@ public static SqlConnection Create(IPersistentStorageFaultInjector faultInjector // one is only used from a single thread at a time. // see https://sqlite.org/threadsafe.html for more detail var flags = OpenFlags.SQLITE_OPEN_CREATE | OpenFlags.SQLITE_OPEN_READWRITE | OpenFlags.SQLITE_OPEN_NOMUTEX; - var result = (Result)raw.sqlite3_open_v2(databasePath, out var handle, (int)flags, vfs: null); + var handle = NativeMethods.sqlite3_open_v2(databasePath, (int)flags, vfs: null, out var result); if (result != Result.OK) { + handle.Dispose(); throw new SqlException(result, $"Could not open database file: {databasePath} ({result})"); } - Contract.ThrowIfNull(handle); - try { - raw.sqlite3_busy_timeout(handle, (int)TimeSpan.FromMinutes(1).TotalMilliseconds); + NativeMethods.sqlite3_busy_timeout(handle, (int)TimeSpan.FromMinutes(1).TotalMilliseconds); return new SqlConnection(handle, faultInjector, queryToStatement); } catch { // If we failed to create connection, ensure that we still release the sqlite // handle. - raw.sqlite3_close(handle); + handle.Dispose(); throw; } } - private SqlConnection(sqlite3 handle, IPersistentStorageFaultInjector faultInjector, Dictionary queryToStatement) + private SqlConnection(SafeSqliteHandle handle, IPersistentStorageFaultInjector faultInjector, Dictionary queryToStatement) { - // This constructor avoids allocations since failure (e.g. OutOfMemoryException) would - // leave the object partially-constructed, and the finalizer would run later triggering - // a crash. _handle = handle; _faultInjector = faultInjector; _queryToStatement = queryToStatement; } - ~SqlConnection() - { - if (!Environment.HasShutdownStarted) - { - var ex = new InvalidOperationException("SqlConnection was not properly closed"); - _faultInjector?.OnFatalError(ex); - FatalError.Report(new InvalidOperationException("SqlConnection was not properly closed")); - } - } - internal void Close_OnlyForUseBySqlPersistentStorage() { - GC.SuppressFinalize(this); - - Contract.ThrowIfNull(_handle); + // Dispose of the underlying handle at the end of cleanup + using var _ = _handle; // release all the cached statements we have. // @@ -121,9 +105,6 @@ internal void Close_OnlyForUseBySqlPersistentStorage() } _queryToStatement.Clear(); - - // Finally close our handle to the actual DB. - ThrowIfNotOk(raw.sqlite3_close(_handle)); } public void ExecuteCommand(string command, bool throwOnError = true) @@ -141,10 +122,19 @@ public ResettableSqlStatement GetResettableStatement(string query) { if (!_queryToStatement.TryGetValue(query, out var statement)) { - var result = (Result)raw.sqlite3_prepare_v2(_handle, query, out var rawStatement); - ThrowIfNotOk(result); - statement = new SqlStatement(this, rawStatement); - _queryToStatement[query] = statement; + var handle = NativeMethods.sqlite3_prepare_v2(_handle, query, out var result); + try + { + ThrowIfNotOk(result); + + statement = new SqlStatement(this, handle); + _queryToStatement[query] = statement; + } + catch + { + handle.Dispose(); + throw; + } } return new ResettableSqlStatement(statement); @@ -216,7 +206,7 @@ private void Rollback(bool throwOnError) => ExecuteCommand("rollback transaction", throwOnError); public int LastInsertRowId() - => (int)raw.sqlite3_last_insert_rowid(_handle); + => (int)NativeMethods.sqlite3_last_insert_rowid(_handle); [PerformanceSensitive("https://github.com/dotnet/roslyn/issues/36114", AllowCaptures = false)] public Stream ReadBlob_MustRunInTransaction(string tableName, string columnName, long rowId) @@ -236,27 +226,23 @@ public Stream ReadBlob_MustRunInTransaction(string tableName, string columnName, } const int ReadOnlyFlags = 0; - var result = raw.sqlite3_blob_open(_handle, "main", tableName, columnName, rowId, ReadOnlyFlags, out var blob); - if (result == raw.SQLITE_ERROR) + + using var blob = NativeMethods.sqlite3_blob_open(_handle, "main", tableName, columnName, rowId, ReadOnlyFlags, out var result); + + if (result == Result.ERROR) { // can happen when rowId points to a row that hasn't been written to yet. return null; } ThrowIfNotOk(result); - try - { - return ReadBlob(blob); - } - finally - { - ThrowIfNotOk(raw.sqlite3_blob_close(blob)); - } + + return ReadBlob(blob); } - private Stream ReadBlob(sqlite3_blob blob) + private Stream ReadBlob(SafeSqliteBlobHandle blob) { - var length = raw.sqlite3_blob_bytes(blob); + var length = NativeMethods.sqlite3_blob_bytes(blob); // If it's a small blob, just read it into one of our pooled arrays, and then // create a PooledStream over it. @@ -268,17 +254,17 @@ private Stream ReadBlob(sqlite3_blob blob) { // Otherwise, it's a large stream. Just take the hit of allocating. var bytes = new byte[length]; - ThrowIfNotOk(raw.sqlite3_blob_read(blob, bytes, length, offset: 0)); + ThrowIfNotOk(NativeMethods.sqlite3_blob_read(blob, bytes, length, offset: 0)); return new MemoryStream(bytes); } } - private Stream ReadBlobIntoPooledStream(sqlite3_blob blob, int length) + private Stream ReadBlobIntoPooledStream(SafeSqliteBlobHandle blob, int length) { var bytes = SQLitePersistentStorage.GetPooledBytes(); try { - ThrowIfNotOk(raw.sqlite3_blob_read(blob, bytes, length, offset: 0)); + ThrowIfNotOk(NativeMethods.sqlite3_blob_read(blob, bytes, length, offset: 0)); // Copy those bytes into a pooled stream return SerializableBytes.CreateReadableStream(bytes, length); @@ -296,7 +282,7 @@ public void ThrowIfNotOk(int result) public void ThrowIfNotOk(Result result) => ThrowIfNotOk(_handle, result); - public static void ThrowIfNotOk(sqlite3 handle, Result result) + public static void ThrowIfNotOk(SafeSqliteHandle handle, Result result) { if (result != Result.OK) { @@ -307,9 +293,11 @@ public static void ThrowIfNotOk(sqlite3 handle, Result result) public void Throw(Result result) => Throw(_handle, result); - public static void Throw(sqlite3 handle, Result result) - => throw new SqlException(result, - raw.sqlite3_errmsg(handle) + "\r\n" + - raw.sqlite3_errstr(raw.sqlite3_extended_errcode(handle))); + public static void Throw(SafeSqliteHandle handle, Result result) + { + throw new SqlException(result, + NativeMethods.sqlite3_errmsg(handle) + "\r\n" + + NativeMethods.sqlite3_errstr(NativeMethods.sqlite3_extended_errcode(handle))); + } } } diff --git a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SqlStatement.cs b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SqlStatement.cs index 3c28d213c5a5a..5a4c44c7348fd 100644 --- a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SqlStatement.cs +++ b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SqlStatement.cs @@ -4,8 +4,8 @@ using System; using System.Runtime.InteropServices; +using Microsoft.CodeAnalysis.SQLite.Interop; using Roslyn.Utilities; -using SQLitePCL; namespace Microsoft.CodeAnalysis.SQLite.Interop { @@ -30,23 +30,25 @@ namespace Microsoft.CodeAnalysis.SQLite.Interop internal struct SqlStatement { private readonly SqlConnection _connection; - private readonly sqlite3_stmt _rawStatement; + private readonly SafeSqliteStatementHandle _rawStatement; - public SqlStatement(SqlConnection connection, sqlite3_stmt statement) + public SqlStatement(SqlConnection connection, SafeSqliteStatementHandle statement) { _connection = connection; _rawStatement = statement; } internal void Close_OnlyForUseBySqlConnection() - => _connection.ThrowIfNotOk(raw.sqlite3_finalize(_rawStatement)); + { + _rawStatement.Dispose(); + } public void Reset() - => _connection.ThrowIfNotOk(raw.sqlite3_reset(_rawStatement)); + => _connection.ThrowIfNotOk(NativeMethods.sqlite3_reset(_rawStatement)); public Result Step(bool throwOnError = true) { - var stepResult = (Result)raw.sqlite3_step(_rawStatement); + var stepResult = NativeMethods.sqlite3_step(_rawStatement); // Anything other than DONE or ROW is an error when stepping. // throw if the caller wants that, or just return the value @@ -64,30 +66,30 @@ public Result Step(bool throwOnError = true) } internal void BindStringParameter(int parameterIndex, string value) - => _connection.ThrowIfNotOk(raw.sqlite3_bind_text(_rawStatement, parameterIndex, value)); + => _connection.ThrowIfNotOk(NativeMethods.sqlite3_bind_text(_rawStatement, parameterIndex, value)); internal void BindInt64Parameter(int parameterIndex, long value) - => _connection.ThrowIfNotOk(raw.sqlite3_bind_int64(_rawStatement, parameterIndex, value)); + => _connection.ThrowIfNotOk(NativeMethods.sqlite3_bind_int64(_rawStatement, parameterIndex, value)); // SQLite PCL does not expose sqlite3_bind_blob function that takes a length. So we explicitly // DLL import it here. See https://github.com/ericsink/SQLitePCL.raw/issues/135 internal void BindBlobParameter(int parameterIndex, byte[] value, int length) - => _connection.ThrowIfNotOk(sqlite3_bind_blob(_rawStatement.ptr, parameterIndex, value, length, new IntPtr(-1))); + => _connection.ThrowIfNotOk(sqlite3_bind_blob(_rawStatement, parameterIndex, value, length, new IntPtr(-1))); [DllImport("e_sqlite3.dll", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] - public static extern int sqlite3_bind_blob(IntPtr stmt, int index, byte[] val, int nSize, IntPtr nTransient); + public static extern int sqlite3_bind_blob(SafeSqliteStatementHandle stmt, int index, byte[] val, int nSize, IntPtr nTransient); internal byte[] GetBlobAt(int columnIndex) - => raw.sqlite3_column_blob(_rawStatement, columnIndex); + => NativeMethods.sqlite3_column_blob(_rawStatement, columnIndex); internal int GetInt32At(int columnIndex) - => raw.sqlite3_column_int(_rawStatement, columnIndex); + => NativeMethods.sqlite3_column_int(_rawStatement, columnIndex); internal long GetInt64At(int columnIndex) - => raw.sqlite3_column_int64(_rawStatement, columnIndex); + => NativeMethods.sqlite3_column_int64(_rawStatement, columnIndex); internal string GetStringAt(int columnIndex) - => raw.sqlite3_column_text(_rawStatement, columnIndex); + => NativeMethods.sqlite3_column_text(_rawStatement, columnIndex); } } From 067726760c76230e918fcd1567ef311ed510f9d1 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 20 Apr 2020 12:23:04 -0700 Subject: [PATCH 2/8] Remove generic safe handles to avoid requiring the SQLite dependency --- .../SQLite/Interop/SafeSqliteBlobHandle.cs | 22 +++++++++-- .../SQLite/Interop/SafeSqliteChildHandle`1.cs | 37 ------------------- .../SQLite/Interop/SafeSqliteHandle.cs | 16 ++++++-- .../SQLite/Interop/SafeSqliteHandle`1.cs | 29 --------------- .../Interop/SafeSqliteStatementHandle.cs | 22 +++++++++-- 5 files changed, 49 insertions(+), 77 deletions(-) delete mode 100644 src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteChildHandle`1.cs delete mode 100644 src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteHandle`1.cs diff --git a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteBlobHandle.cs b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteBlobHandle.cs index f7625834711f6..80523d7e6d237 100644 --- a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteBlobHandle.cs +++ b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteBlobHandle.cs @@ -5,20 +5,34 @@ #nullable enable using System; +using System.Runtime.InteropServices; +using Microsoft.CodeAnalysis.Shared.Extensions; using SQLitePCL; namespace Microsoft.CodeAnalysis.SQLite.Interop { - internal sealed class SafeSqliteBlobHandle : SafeSqliteChildHandle + internal sealed class SafeSqliteBlobHandle : SafeHandle { + private readonly sqlite3_blob? _wrapper; + private readonly SafeHandleLease _lease; + public SafeSqliteBlobHandle(SafeSqliteHandle sqliteHandle, sqlite3_blob? wrapper) - : base(sqliteHandle, wrapper?.ptr ?? IntPtr.Zero, wrapper) + : base(invalidHandleValue: IntPtr.Zero, ownsHandle: true) { + _wrapper = wrapper; + SetHandle(wrapper?.ptr ?? IntPtr.Zero); + _lease = sqliteHandle.Lease(); } - protected override bool ReleaseChildHandle() + public override bool IsInvalid => handle == IntPtr.Zero; + + public new sqlite3_blob DangerousGetHandle() + => _wrapper!; + + protected override bool ReleaseHandle() { - var result = (Result)raw.sqlite3_blob_close(Wrapper); + using var _ = _lease; + var result = (Result)raw.sqlite3_blob_close(_wrapper); return result == Result.OK; } } diff --git a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteChildHandle`1.cs b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteChildHandle`1.cs deleted file mode 100644 index 40a1c7e77265e..0000000000000 --- a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteChildHandle`1.cs +++ /dev/null @@ -1,37 +0,0 @@ -// 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 enable - -using System; -using System.Runtime.InteropServices; -using Microsoft.CodeAnalysis.Shared.Extensions; - -namespace Microsoft.CodeAnalysis.SQLite.Interop -{ - /// - /// The base handle type for an SQLite resource that exists within the context of a parent handle, and should always - /// be released prior to the parent handle. - /// - /// The SQLite resource wrapper type. - internal abstract class SafeSqliteChildHandle : SafeSqliteHandle - where T : class - { - private readonly SafeHandleLease _lease; - - protected SafeSqliteChildHandle(SafeHandle parentHandle, IntPtr handle, T? wrapper) - : base(handle, wrapper) - { - _lease = parentHandle.Lease(); - } - - protected abstract bool ReleaseChildHandle(); - - protected sealed override bool ReleaseHandle() - { - using var _ = _lease; - return ReleaseChildHandle(); - } - } -} diff --git a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteHandle.cs b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteHandle.cs index 2e66c42857b40..c2fc36c1262fe 100644 --- a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteHandle.cs +++ b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteHandle.cs @@ -5,20 +5,30 @@ #nullable enable using System; +using System.Runtime.InteropServices; using SQLitePCL; namespace Microsoft.CodeAnalysis.SQLite.Interop { - internal sealed class SafeSqliteHandle : SafeSqliteHandle + internal sealed class SafeSqliteHandle : SafeHandle { + private readonly sqlite3? _wrapper; + public SafeSqliteHandle(sqlite3? wrapper) - : base(wrapper?.ptr ?? IntPtr.Zero, wrapper) + : base(invalidHandleValue: IntPtr.Zero, ownsHandle: true) { + _wrapper = wrapper; + SetHandle(wrapper?.ptr ?? IntPtr.Zero); } + public override bool IsInvalid => handle == IntPtr.Zero; + + public new sqlite3 DangerousGetHandle() + => _wrapper!; + protected override bool ReleaseHandle() { - var result = (Result)raw.sqlite3_close(Wrapper); + var result = (Result)raw.sqlite3_close(_wrapper); return result == Result.OK; } } diff --git a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteHandle`1.cs b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteHandle`1.cs deleted file mode 100644 index 77d7462545fab..0000000000000 --- a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteHandle`1.cs +++ /dev/null @@ -1,29 +0,0 @@ -// 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 enable - -using System; -using System.Runtime.InteropServices; - -namespace Microsoft.CodeAnalysis.SQLite.Interop -{ - internal abstract class SafeSqliteHandle : SafeHandle - where T : class - { - protected readonly T? Wrapper; - - public SafeSqliteHandle(IntPtr handle, T? wrapper) - : base(invalidHandleValue: IntPtr.Zero, ownsHandle: true) - { - Wrapper = wrapper; - SetHandle(handle); - } - - public override bool IsInvalid => handle == IntPtr.Zero; - - public new T DangerousGetHandle() - => Wrapper!; - } -} diff --git a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteStatementHandle.cs b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteStatementHandle.cs index bea28c3d24420..48e1eff0b1051 100644 --- a/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteStatementHandle.cs +++ b/src/Workspaces/Core/Portable/Storage/SQLite/Interop/SafeSqliteStatementHandle.cs @@ -5,20 +5,34 @@ #nullable enable using System; +using System.Runtime.InteropServices; +using Microsoft.CodeAnalysis.Shared.Extensions; using SQLitePCL; namespace Microsoft.CodeAnalysis.SQLite.Interop { - internal sealed class SafeSqliteStatementHandle : SafeSqliteChildHandle + internal sealed class SafeSqliteStatementHandle : SafeHandle { + private readonly sqlite3_stmt? _wrapper; + private readonly SafeHandleLease _lease; + public SafeSqliteStatementHandle(SafeSqliteHandle sqliteHandle, sqlite3_stmt? wrapper) - : base(sqliteHandle, wrapper?.ptr ?? IntPtr.Zero, wrapper) + : base(invalidHandleValue: IntPtr.Zero, ownsHandle: true) { + _wrapper = wrapper; + SetHandle(wrapper?.ptr ?? IntPtr.Zero); + _lease = sqliteHandle.Lease(); } - protected override bool ReleaseChildHandle() + public override bool IsInvalid => handle == IntPtr.Zero; + + public new sqlite3_stmt DangerousGetHandle() + => _wrapper!; + + protected override bool ReleaseHandle() { - var result = (Result)raw.sqlite3_finalize(Wrapper); + using var _ = _lease; + var result = (Result)raw.sqlite3_finalize(_wrapper); return result == Result.OK; } } From a2fa93eeda4351a896316ce622583078df487699 Mon Sep 17 00:00:00 2001 From: Gen Lu Date: Fri, 24 Apr 2020 12:20:17 -0700 Subject: [PATCH 3/8] Enable optimization for languageservices & codelens --- .../Microsoft.VisualStudio.LanguageServices.CodeLens.csproj | 1 + .../Core/Def/Microsoft.VisualStudio.LanguageServices.csproj | 1 + 2 files changed, 2 insertions(+) diff --git a/src/VisualStudio/CodeLens/Microsoft.VisualStudio.LanguageServices.CodeLens.csproj b/src/VisualStudio/CodeLens/Microsoft.VisualStudio.LanguageServices.CodeLens.csproj index 46c641d9db3af..eceb456bd35cc 100644 --- a/src/VisualStudio/CodeLens/Microsoft.VisualStudio.LanguageServices.CodeLens.csproj +++ b/src/VisualStudio/CodeLens/Microsoft.VisualStudio.LanguageServices.CodeLens.csproj @@ -8,6 +8,7 @@ Microsoft.VisualStudio.LanguageServices.CodeLens net472 true + partial false diff --git a/src/VisualStudio/Core/Def/Microsoft.VisualStudio.LanguageServices.csproj b/src/VisualStudio/Core/Def/Microsoft.VisualStudio.LanguageServices.csproj index fea6f0a2c3ffe..233826b91c7d3 100644 --- a/src/VisualStudio/Core/Def/Microsoft.VisualStudio.LanguageServices.csproj +++ b/src/VisualStudio/Core/Def/Microsoft.VisualStudio.LanguageServices.csproj @@ -11,6 +11,7 @@ true false None + partial true From 146f92080a65306f44790655ee7515f4a82fc4e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Matou=C5=A1ek?= Date: Fri, 24 Apr 2020 13:24:03 -0700 Subject: [PATCH 4/8] Temporarily allow duplicate analyzer references (#43567) --- .../Workspace/Solution/ProjectInfo.cs | 4 +- .../Portable/Workspace/Solution/Solution.cs | 2 +- .../Execution/SnapshotSerializationTests.cs | 40 +++++++++++++++++++ .../SolutionTests/ProjectInfoTests.cs | 5 +-- .../CoreTest/SolutionTests/SolutionTests.cs | 2 +- 5 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/ProjectInfo.cs b/src/Workspaces/Core/Portable/Workspace/Solution/ProjectInfo.cs index eb8a02b9aded6..b7110698eceec 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/ProjectInfo.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/ProjectInfo.cs @@ -231,7 +231,7 @@ public static ProjectInfo Create( PublicContract.ToBoxedImmutableArrayWithDistinctNonNullItems(documents, nameof(documents)), PublicContract.ToBoxedImmutableArrayWithDistinctNonNullItems(projectReferences, nameof(projectReferences)), PublicContract.ToBoxedImmutableArrayWithDistinctNonNullItems(metadataReferences, nameof(metadataReferences)), - PublicContract.ToBoxedImmutableArrayWithDistinctNonNullItems(analyzerReferences, nameof(analyzerReferences)), + PublicContract.ToBoxedImmutableArrayWithNonNullItems(analyzerReferences, nameof(analyzerReferences)), PublicContract.ToBoxedImmutableArrayWithDistinctNonNullItems(additionalDocuments, nameof(additionalDocuments)), analyzerConfigDocuments: SpecializedCollections.EmptyBoxedImmutableArray(), hostObjectType); @@ -336,7 +336,7 @@ public ProjectInfo WithMetadataReferences(IEnumerable? metada => With(metadataReferences: PublicContract.ToBoxedImmutableArrayWithDistinctNonNullItems(metadataReferences, nameof(metadataReferences))); public ProjectInfo WithAnalyzerReferences(IEnumerable? analyzerReferences) - => With(analyzerReferences: PublicContract.ToBoxedImmutableArrayWithDistinctNonNullItems(analyzerReferences, nameof(analyzerReferences))); + => With(analyzerReferences: PublicContract.ToBoxedImmutableArrayWithNonNullItems(analyzerReferences, nameof(analyzerReferences))); internal string GetDebuggerDisplay() => nameof(ProjectInfo) + " " + Name + (!string.IsNullOrWhiteSpace(FilePath) ? " " + FilePath : ""); diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/Solution.cs b/src/Workspaces/Core/Portable/Workspace/Solution/Solution.cs index 2269ef0965967..aef83f781fea7 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/Solution.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/Solution.cs @@ -802,7 +802,7 @@ public Solution WithProjectAnalyzerReferences(ProjectId projectId, IEnumerable r.FullPath)); + } + + internal class DummyAssemblyLoader : IAnalyzerAssemblyLoader + { + public static DummyAssemblyLoader Instance = new DummyAssemblyLoader(); + + public void AddDependencyLocation(string fullPath) + { + } + + public Assembly LoadFromPath(string fullPath) + => Assembly.LoadFrom(fullPath); + } + [Fact] public async Task UnknownLanguageTest() { diff --git a/src/Workspaces/CoreTest/SolutionTests/ProjectInfoTests.cs b/src/Workspaces/CoreTest/SolutionTests/ProjectInfoTests.cs index 2518ea29e5111..f20290afca3af 100644 --- a/src/Workspaces/CoreTest/SolutionTests/ProjectInfoTests.cs +++ b/src/Workspaces/CoreTest/SolutionTests/ProjectInfoTests.cs @@ -53,8 +53,7 @@ public void Create_Errors_DuplicateItems() analyzerReferences: new AnalyzerReference[] { null })); var analyzerReference = new TestAnalyzerReference(); - Assert.Throws("analyzerReferences[1]", - () => ProjectInfo.Create(pid, VersionStamp.Default, "proj", "assembly", "C#", analyzerReferences: new[] { analyzerReference, analyzerReference })); + ProjectInfo.Create(pid, VersionStamp.Default, "proj", "assembly", "C#", analyzerReferences: new[] { analyzerReference, analyzerReference }); Assert.Throws(() => ProjectInfo.Create(pid, VersionStamp.Default, name: "Goo", assemblyName: "Bar", language: "C#", metadataReferences: new MetadataReference[] { null })); @@ -193,7 +192,7 @@ public void TestProperties() SolutionTestHelpers.TestListProperty(instance, (old, value) => old.WithDocuments(value), opt => opt.Documents, documentInfo, allowDuplicates: false); SolutionTestHelpers.TestListProperty(instance, (old, value) => old.WithAdditionalDocuments(value), opt => opt.AdditionalDocuments, documentInfo, allowDuplicates: false); SolutionTestHelpers.TestListProperty(instance, (old, value) => old.WithAnalyzerConfigDocuments(value), opt => opt.AnalyzerConfigDocuments, documentInfo, allowDuplicates: false); - SolutionTestHelpers.TestListProperty(instance, (old, value) => old.WithAnalyzerReferences(value), opt => opt.AnalyzerReferences, (AnalyzerReference)new TestAnalyzerReference(), allowDuplicates: false); + SolutionTestHelpers.TestListProperty(instance, (old, value) => old.WithAnalyzerReferences(value), opt => opt.AnalyzerReferences, (AnalyzerReference)new TestAnalyzerReference(), allowDuplicates: true); SolutionTestHelpers.TestListProperty(instance, (old, value) => old.WithMetadataReferences(value), opt => opt.MetadataReferences, (MetadataReference)new TestMetadataReference(), allowDuplicates: false); SolutionTestHelpers.TestListProperty(instance, (old, value) => old.WithProjectReferences(value), opt => opt.ProjectReferences, new ProjectReference(projectId), allowDuplicates: false); } diff --git a/src/Workspaces/CoreTest/SolutionTests/SolutionTests.cs b/src/Workspaces/CoreTest/SolutionTests/SolutionTests.cs index 4743aef55e414..e67805af2c4f5 100644 --- a/src/Workspaces/CoreTest/SolutionTests/SolutionTests.cs +++ b/src/Workspaces/CoreTest/SolutionTests/SolutionTests.cs @@ -897,7 +897,7 @@ public void WithProjectAnalyzerReferences() (old, value) => old.WithProjectAnalyzerReferences(projectId, value), opt => opt.GetProject(projectId)!.AnalyzerReferences, analyzerRef, - allowDuplicates: false); + allowDuplicates: true); Assert.Throws("projectId", () => solution.WithProjectAnalyzerReferences(null!, new[] { analyzerRef })); Assert.Throws(() => solution.WithProjectAnalyzerReferences(ProjectId.CreateNewId(), new[] { analyzerRef })); From 892b642af00a4408da6cf097feedcdba6c5adeb3 Mon Sep 17 00:00:00 2001 From: Gen Lu Date: Fri, 24 Apr 2020 14:03:32 -0700 Subject: [PATCH 5/8] Enable partial ngen for workspaces --- .../Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj index 7fa438ee58f87..61588ad58d693 100644 --- a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj +++ b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj @@ -8,6 +8,7 @@ netcoreapp3.1;netstandard2.0 $(DefineConstants);WORKSPACE true + partial true From f0d0ed2bccd547dbf42ab613d3ed453c7e599e2d Mon Sep 17 00:00:00 2001 From: Chris Sienkiewicz Date: Mon, 13 Apr 2020 13:54:02 -0700 Subject: [PATCH 6/8] Disable training for MS.CA.Workspaces.dll --- eng/config/OptProf.json | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/eng/config/OptProf.json b/eng/config/OptProf.json index fb0532be4934a..aefd85b37e8be 100644 --- a/eng/config/OptProf.json +++ b/eng/config/OptProf.json @@ -70,10 +70,6 @@ "filename": "/Microsoft.CodeAnalysis.Features.dll", "testCases":[ "ManagedLangs.OptProfTests.DDRIT_RPS_ManagedLangs" ] }, - { - "filename": "/Microsoft.CodeAnalysis.CSharp.Workspaces.dll", - "testCases":[ "ManagedLangs.OptProfTests.DDRIT_RPS_ManagedLangs" ] - }, { "filename": "/Microsoft.VisualStudio.LanguageServices.Implementation.dll", "testCases":[ "ManagedLangs.OptProfTests.DDRIT_RPS_ManagedLangs" ] @@ -143,10 +139,6 @@ "filename": "/Microsoft.CodeAnalysis.VisualBasic.Features.dll", "testCases":[ "Microsoft.Test.Performance.XamlOptProfCreateTests.WpfCreateProject_DesignerIsolated" ] }, - { - "filename": "/Microsoft.CodeAnalysis.Workspaces.dll", - "testCases":[ "Microsoft.Test.Performance.XamlOptProfCreateTests.WpfCreateProject_DesignerIsolated" ] - }, { "filename": "/Microsoft.CodeAnalysis.VisualBasic.dll", "testCases":[ "Microsoft.Test.Performance.XamlOptProfCreateTests.WpfCreateProject_DesignerIsolated" ] @@ -252,10 +244,6 @@ "filename": "/Microsoft.CodeAnalysis.VisualBasic.Features.dll", "testCases":[ "WinForms.OptProfTests.winforms_largeform_vb" ] }, - { - "filename": "/Microsoft.CodeAnalysis.Workspaces.dll", - "testCases":[ "WinForms.OptProfTests.winforms_largeform_vb" ] - }, { "filename": "/Microsoft.CodeAnalysis.VisualBasic.dll", "testCases":[ "WinForms.OptProfTests.winforms_largeform_vb" ] @@ -365,10 +353,6 @@ "filename": "/Microsoft.CodeAnalysis.VisualBasic.Features.dll", "testCases":[ "TeamEng.OptProfTest.vs_debugger_start_no_build_cs_scribble" ] }, - { - "filename": "/Microsoft.CodeAnalysis.Workspaces.dll", - "testCases":[ "TeamEng.OptProfTest.vs_debugger_start_no_build_cs_scribble" ] - }, { "filename": "/Microsoft.CodeAnalysis.VisualBasic.dll", "testCases":[ "TeamEng.OptProfTest.vs_debugger_start_no_build_cs_scribble" ] @@ -478,10 +462,6 @@ "filename": "/Microsoft.CodeAnalysis.VisualBasic.Features.dll", "testCases":[ "VSPE.OptProfTests.vs_asl_vb_scenario", "VSPE.OptProfTests.vs_perf_designtime_solution_build_vb_australiangovernment" ] }, - { - "filename": "/Microsoft.CodeAnalysis.Workspaces.dll", - "testCases":[ "VSPE.OptProfTests.vs_asl_cs_scenario", "VSPE.OptProfTests.vs_asl_vb_scenario", "VSPE.OptProfTests.vs_perf_DesignTime_solution_loadclose_cs_picasso", "VSPE.OptProfTests.vs_perf_designtime_editor_intellisense_globalcompletionlist_cs", "VSPE.OptProfTests.vs_perf_designtime_ide_searchtest", "VSPE.OptProfTests.vs_perf_designtime_solution_build_vb_australiangovernment", "VSPE.OptProfTests.vs_perf_designtime_solution_loadclose_vb_australiangovernment" ] - }, { "filename": "/Microsoft.CodeAnalysis.VisualBasic.dll", "testCases":[ "VSPE.OptProfTests.vs_asl_vb_scenario", "VSPE.OptProfTests.vs_perf_designtime_ide_searchtest", "VSPE.OptProfTests.vs_perf_designtime_solution_build_vb_australiangovernment", "VSPE.OptProfTests.vs_perf_designtime_solution_loadclose_vb_australiangovernment" ] From b098a62963a90e9c4dcad0cea0245dd5acb3a189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Matou=C5=A1ek?= Date: Mon, 27 Apr 2020 13:26:32 -0700 Subject: [PATCH 7/8] Do not install Roslyn.VisualStudio.InteractiveComponents.vsix for integration tests --- eng/build.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/eng/build.ps1 b/eng/build.ps1 index b586b90536ddc..fc949d6da518b 100644 --- a/eng/build.ps1 +++ b/eng/build.ps1 @@ -492,7 +492,6 @@ function Deploy-VsixViaTool() { "Roslyn.Compilers.Extension.vsix", "Roslyn.VisualStudio.Setup.vsix", "Roslyn.VisualStudio.Setup.Dependencies.vsix", - "Roslyn.VisualStudio.InteractiveComponents.vsix", "ExpressionEvaluatorPackage.vsix", "Roslyn.VisualStudio.DiagnosticsWindow.vsix", "Microsoft.VisualStudio.IntegrationTest.Setup.vsix") From ea7253c2e01c3200a21c020b6bb415e374dd26b2 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Thu, 23 Apr 2020 17:30:21 -0700 Subject: [PATCH 8/8] Disable failing IntelliSense integration tests See #43627 --- .../CSharp/CSharpAutomaticBraceCompletion.cs | 3 ++- .../IntegrationTests/CSharp/CSharpIntelliSense.cs | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpAutomaticBraceCompletion.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpAutomaticBraceCompletion.cs index dd744a8aca4f6..d0a154ea1a1e2 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpAutomaticBraceCompletion.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpAutomaticBraceCompletion.cs @@ -640,7 +640,8 @@ int Prop { $$} assertCaretPosition: true); } - [WpfTheory, CombinatorialData, Trait(Traits.Feature, Traits.Features.AutomaticCompletion)] + [WpfTheory(Skip = "https://github.com/dotnet/roslyn/issues/43627")] + [CombinatorialData, Trait(Traits.Feature, Traits.Features.AutomaticCompletion)] [Trait(Traits.Feature, Traits.Features.CompleteStatement)] [WorkItem(18104, "https://github.com/dotnet/roslyn/issues/18104")] public void CompleteStatementTriggersCompletion(bool showCompletionInArgumentLists) diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpIntelliSense.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpIntelliSense.cs index ba9343764fd31..9b1fae882a0b1 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpIntelliSense.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpIntelliSense.cs @@ -47,7 +47,8 @@ public void AtNamespaceLevel(bool showCompletionInArgumentLists) VisualStudio.Editor.Verify.CurrentLineText("using$$", assertCaretPosition: true); } - [WpfTheory, CombinatorialData, Trait(Traits.Feature, Traits.Features.Completion)] + [WpfTheory(Skip = "https://github.com/dotnet/roslyn/issues/43627")] + [CombinatorialData, Trait(Traits.Feature, Traits.Features.Completion)] public void SpeculativeTInList(bool showCompletionInArgumentLists) { SetUpEditor(@" @@ -104,7 +105,8 @@ public static void Navigate(int i){ } VisualStudio.Editor.Verify.CurrentLineText("NavigateTo.Search$$", assertCaretPosition: true); } - [WpfTheory, CombinatorialData, Trait(Traits.Feature, Traits.Features.Completion)] + [WpfTheory(Skip = "https://github.com/dotnet/roslyn/issues/43627")] + [CombinatorialData, Trait(Traits.Feature, Traits.Features.Completion)] public void CtrlAltSpace(bool showCompletionInArgumentLists) { VisualStudio.Workspace.SetTriggerCompletionInArgumentLists(showCompletionInArgumentLists); @@ -154,7 +156,8 @@ public void CtrlAltSpace(bool showCompletionInArgumentLists) VisualStudio.Editor.Verify.CurrentLineText("System.Console.writeline();$$", assertCaretPosition: true); } - [WpfTheory, CombinatorialData, Trait(Traits.Feature, Traits.Features.Completion)] + [WpfTheory(Skip = "https://github.com/dotnet/roslyn/issues/43627")] + [CombinatorialData, Trait(Traits.Feature, Traits.Features.Completion)] public void CtrlAltSpaceOption(bool showCompletionInArgumentLists) { VisualStudio.Workspace.SetTriggerCompletionInArgumentLists(showCompletionInArgumentLists);