Skip to content

Commit 39a5509

Browse files
committed
Fixed code analysis warnings.
1 parent 4b73fbf commit 39a5509

File tree

7 files changed

+140
-104
lines changed

7 files changed

+140
-104
lines changed

Build/Properties/CodeAnalysisDictionary.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@
1313
<Word>__</Word>
1414
<Word>___</Word>
1515
<Word>____</Word>
16+
<Word>LabelTarget</Word>
17+
<Word>SwitchCase</Word>
18+
<Word>CatchBlock</Word>
19+
<Word>ElementInit</Word>
20+
<Word>MemberBinding</Word>
21+
<Word>MemberAssignment</Word>
22+
<Word>MemberMemberBinding</Word>
23+
<Word>MemberListBinding</Word>
1624
</Recognized>
1725

1826
<Compound>

Source/Qactive.Expressions/EqualityExpressionVisitor.cs

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
namespace Qactive.Expressions
1010
{
11+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "Visitor pattern.")]
1112
public class EqualityExpressionVisitor : ExpressionVisitor
1213
{
1314
private readonly Stack<Expression> others = new Stack<Expression>();
@@ -55,16 +56,12 @@ private void ObjectInvariant()
5556

5657
internal bool ShallowEquals(Expression first, Expression second) => shallowEquals(first, second);
5758

58-
internal bool TypeEquals(Type first, Type second) => typeEquals(first, second);
59-
60-
internal bool MemberEquals(MemberInfo first, MemberInfo second) => memberEquals(first, second);
61-
62-
public void Break(IEnumerable<Expression> inequalityNodes, IEnumerable<Expression> inequalityOthers)
59+
public void Break(IEnumerable<Expression> newInequalityNodes, IEnumerable<Expression> newInequalityOthers)
6360
{
6461
AreEqual = false;
6562

66-
this.inequalityNodes = inequalityNodes.ToList().AsReadOnly();
67-
this.inequalityOthers = inequalityOthers.ToList().AsReadOnly();
63+
this.inequalityNodes = newInequalityNodes.ToList().AsReadOnly();
64+
this.inequalityOthers = newInequalityOthers.ToList().AsReadOnly();
6865
}
6966

7067
internal void SetOtherRoot(Expression other)
@@ -149,18 +146,18 @@ private void Visit(Expression node, Expression other)
149146
}
150147
}
151148

152-
private void Visit<TExpression>(ICollection<TExpression> nodes, ICollection<TExpression> others)
149+
private void Visit<TExpression>(ICollection<TExpression> nodes, ICollection<TExpression> otherNodes)
153150
where TExpression : Expression
154151
{
155152
if (AreEqual)
156153
{
157-
if (!(ExpressionEqualityComparer.NullsOrEquals(nodes, others, (n, o) => n.Count == o.Count)))
154+
if (!(ExpressionEqualityComparer.NullsOrEquals(nodes, otherNodes, (n, o) => n.Count == o.Count)))
158155
{
159-
Break(nodes, others);
156+
Break(nodes, otherNodes);
160157
}
161-
else if (nodes != null && others != null)
158+
else if (nodes != null && otherNodes != null)
162159
{
163-
foreach (var pair in nodes.Zip(others, (node, other) => new { node, other }))
160+
foreach (var pair in nodes.Zip(otherNodes, (node, other) => new { node, other }))
164161
{
165162
Visit(pair.node, pair.other);
166163
}
@@ -261,6 +258,7 @@ protected override CatchBlock VisitCatchBlock(CatchBlock node)
261258
throw new InvalidOperationException("Bug: CatchBlock must not be visited since it's compared within the expressions that contain it.");
262259
}
263260

261+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Seems unavoidable.")]
264262
protected override Expression VisitTry(TryExpression node)
265263
=> VisitIfEqual(node, other => ExpressionEqualityComparer.NullsOrEquals(node.Handlers, other.Handlers, (n, o) => n.Select(h => h.Test).SequenceEqual(o.Select(h => h.Test))),
266264
other => Visit((node.Handlers ?? Enumerable.Empty<CatchBlock>()).Select(n => n.Body).ToList(), (other.Handlers ?? Enumerable.Empty<CatchBlock>()).Select(n => n.Body).ToList()),
@@ -311,26 +309,26 @@ protected override MemberListBinding VisitMemberListBinding(MemberListBinding no
311309
throw new InvalidOperationException("Bug: MemberListBinding must not be visited since it's compared within the expressions that contain it.");
312310
}
313311

314-
private bool Equals(LabelTarget target, LabelTarget other)
312+
private static bool Equals(LabelTarget target, LabelTarget other)
315313
=> ExpressionEqualityComparer.NullsOrEquals(target, other, (n, o) => n.Name == o.Name && n.Type == o.Type);
316314

317-
private bool Equals(ICollection<MemberBinding> binding, ICollection<MemberBinding> other)
315+
private static bool Equals(ICollection<MemberBinding> binding, ICollection<MemberBinding> other)
318316
=> ExpressionEqualityComparer.NullsOrEquals(binding, other, (n, o) => n.Count == o.Count && n.Zip(o, Equals).All(b => b));
319317

320-
private bool Equals(MemberBinding binding, MemberBinding other)
318+
private static bool Equals(MemberBinding binding, MemberBinding other)
321319
=> ExpressionEqualityComparer.NullsOrEquals(binding, other, (n, o) => n.BindingType == o.BindingType
322320
&& n.Member == o.Member
323321
&& (EqualsIfType<MemberMemberBinding>(n, o, Equals)
324322
?? EqualsIfType<MemberListBinding>(n, o, Equals)
325323
?? false));
326324

327-
private bool Equals(MemberMemberBinding binding, MemberMemberBinding other)
325+
private static bool Equals(MemberMemberBinding binding, MemberMemberBinding other)
328326
=> Equals(binding.Bindings, other.Bindings);
329327

330-
private bool Equals(MemberListBinding binding, MemberListBinding other)
328+
private static bool Equals(MemberListBinding binding, MemberListBinding other)
331329
=> ExpressionEqualityComparer.NullsOrEquals(binding.Initializers, other.Initializers, (n, o) => n.Select(i => i.AddMethod).SequenceEqual(o.Select(i => i.AddMethod)));
332330

333-
private bool? EqualsIfType<T>(object first, object second, Func<T, T, bool> comparer)
331+
private static bool? EqualsIfType<T>(object first, object second, Func<T, T, bool> comparer)
334332
where T : class
335333
{
336334
var x = first as T;
@@ -339,7 +337,7 @@ private bool Equals(MemberListBinding binding, MemberListBinding other)
339337
return x != null && y != null ? comparer(x, y) : (bool?)null;
340338
}
341339

342-
private ICollection<Expression> GetExpressions(ReadOnlyCollection<MemberBinding> bindings)
340+
private static ICollection<Expression> GetExpressions(ReadOnlyCollection<MemberBinding> bindings)
343341
=> bindings.OfType<MemberAssignment>().Select(assignment => assignment.Expression)
344342
.Concat(
345343
bindings.OfType<MemberListBinding>().SelectMany(binding => binding.Initializers).SelectMany(init => init.Arguments))

Source/Qactive.Expressions/ExpressionEqualityComparer.cs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ namespace Qactive.Expressions
88
{
99
public sealed class ExpressionEqualityComparer : IEqualityComparer<Expression>
1010
{
11+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "It's immutable.")]
1112
public static readonly ExpressionEqualityComparer Exact = new ExpressionEqualityComparer(reflectionNamesOnly: false);
13+
14+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "It's immutable.")]
1215
public static readonly ExpressionEqualityComparer ReflectionNamesOnly = new ExpressionEqualityComparer(reflectionNamesOnly: true);
1316

1417
private readonly bool reflectionNamesOnly;
@@ -21,11 +24,15 @@ private ExpressionEqualityComparer(bool reflectionNamesOnly)
2124
public bool Equals(Expression x, Expression y)
2225
=> Equals(x, y, new EqualityExpressionVisitor(ShallowEquals, TypeEquals, MemberEquals));
2326

24-
public bool Equals(Expression x, Expression y, EqualityExpressionVisitor visitor)
25-
=> visitor.ShallowEquals(x, y) && DeepEquals(x, y, visitor);
27+
public static bool Equals(Expression first, Expression second, EqualityExpressionVisitor visitor)
28+
{
29+
Contract.Requires(visitor != null);
30+
31+
return visitor.ShallowEquals(first, second) && DeepEquals(first, second, visitor);
32+
}
2633

27-
public bool ShallowEquals(Expression x, Expression y)
28-
=> NullsOrEquals(x, y, (f, s) => f.NodeType == s.NodeType && TypeEquals(GetRepresentativeType(f), GetRepresentativeType(s)));
34+
public bool ShallowEquals(Expression first, Expression second)
35+
=> NullsOrEquals(first, second, (f, s) => f.NodeType == s.NodeType && TypeEquals(GetRepresentativeType(f), GetRepresentativeType(s)));
2936

3037
public static Type GetRepresentativeType(Expression expression)
3138
{
@@ -45,18 +52,18 @@ public static Type GetRepresentativeType(Expression expression)
4552
return type;
4653
}
4754

48-
private bool DeepEquals(Expression x, Expression y, EqualityExpressionVisitor visitor)
55+
private static bool DeepEquals(Expression first, Expression second, EqualityExpressionVisitor visitor)
4956
{
50-
Contract.Requires((x == null && y == null) || (x != null && y != null));
57+
Contract.Requires((first == null && second == null) || (first != null && second != null));
5158
Contract.Requires(visitor != null);
5259

53-
if (x == null && y == null)
60+
if (first == null)
5461
{
5562
return true;
5663
}
5764

58-
visitor.SetOtherRoot(y);
59-
visitor.Visit(x);
65+
visitor.SetOtherRoot(second);
66+
visitor.Visit(first);
6067

6168
Contract.Assume(visitor.StackCount == 1);
6269

Source/Qactive.Providers.Tcp/TcpQactiveProvider.cs

Lines changed: 87 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ public static TcpQactiveProvider Server(IPEndPoint endPoint, ITcpQactiveProvider
129129
return new TcpQactiveProvider(endPoint, transportInitializer);
130130
}
131131

132+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "Seems as simple as it's going to get.")]
132133
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "The SocketAsyncEventArgs instance is either disposed before returning or by the observable's Finally operator.")]
133134
public override IObservable<TResult> Connect<TResult>(Func<IQbservableProtocol, Expression> prepareExpression)
134135
{
@@ -181,7 +182,7 @@ public override IObservable<TResult> Connect<TResult>(Func<IQbservableProtocol,
181182

182183
var s = Observable.Using(
183184
() => new NetworkStream(e2.ConnectSocket, ownsSocket: false),
184-
stream => ReadObservable<TResult>(stream, prepareExpression, cancel.Token))
185+
stream => GetObservable<TResult>(stream, prepareExpression, cancel.Token))
185186
.SubscribeSafe(innerObserver);
186187

187188
return new CompositeDisposable(s, cancel);
@@ -205,7 +206,7 @@ public override IObservable<TResult> Connect<TResult>(Func<IQbservableProtocol,
205206
}
206207
}
207208

208-
private IObservable<TResult> ReadObservable<TResult>(Stream stream, Func<IQbservableProtocol, Expression> prepareExpression, CancellationToken cancel)
209+
private IObservable<TResult> GetObservable<TResult>(Stream stream, Func<IQbservableProtocol, Expression> prepareExpression, CancellationToken cancel)
209210
{
210211
Contract.Requires(stream != null);
211212
Contract.Requires(prepareExpression != null);
@@ -218,6 +219,7 @@ from result in protocol
218219
select result;
219220
}
220221

222+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "Seems as simple as it's going to get.")]
221223
public override IObservable<ClientTermination> Listen(QbservableServiceOptions options, Func<IQbservableProtocol, IParameterizedQbservableProvider> providerFactory)
222224
{
223225
return from listener in Observable.Return(new TcpListener(EndPoint))
@@ -251,84 +253,96 @@ from client in Observable.FromAsync(listener.AcceptTcpClientAsync).Repeat()
251253
Stopped();
252254
})
253255
let capturedId = new CapturedId(Id + " C" + Interlocked.Increment(ref lastServerClientNumber) + " " + client.Client.RemoteEndPoint)
254-
from result in Observable.StartAsync(async cancel =>
255-
{
256-
ReceivingConnection(idOverride: capturedId.Value);
256+
from termination in Observable.StartAsync(cancel => AcceptAsync(client, capturedId, options, providerFactory, cancel))
257+
.Finally(() => Shutdown(client.Client, capturedId.Value))
258+
select termination;
259+
}
257260

258-
// These default settings enable a proper graceful shutdown. DisconnectAsync is used instead of Close on the server-side to request
259-
// that the client terminates the connection ASAP. This is important because it prevents the server-side socket from going into a
260-
// TIME_WAIT state rather than the client. The linger option is meant to ensure that any outgoing data, such as an exception, is
261-
// completely transmitted to the client before the socket terminates. The seconds specified is arbitrary, though chosen to be large
262-
// enough to transfer any remaining data successfully and small enough to cause a timely disconnection. A custom prepareSocket
263-
// implementation can always change it via SetSocketOption, if necessary.
264-
//
265-
// https://msdn.microsoft.com/en-us/library/system.net.sockets.socket.disconnect(v=vs.110).aspx
266-
client.LingerState.Enabled = true;
267-
client.LingerState.LingerTime = LingerTimeInSeconds;
261+
private async Task<TcpClientTermination> AcceptAsync(
262+
TcpClient client,
263+
CapturedId capturedId,
264+
QbservableServiceOptions options,
265+
Func<IQbservableProtocol, IParameterizedQbservableProvider> providerFactory,
266+
CancellationToken cancel)
267+
{
268+
Contract.Requires(client != null);
269+
Contract.Requires(capturedId != null);
270+
Contract.Requires(options != null);
271+
Contract.Requires(providerFactory != null);
268272

269-
prepareSocket(client.Client);
273+
ReceivingConnection(idOverride: capturedId.Value);
270274

271-
var watch = Stopwatch.StartNew();
275+
// These default settings enable a proper graceful shutdown. DisconnectAsync is used instead of Close on the server-side to request
276+
// that the client terminates the connection ASAP. This is important because it prevents the server-side socket from going into a
277+
// TIME_WAIT state rather than the client. The linger option is meant to ensure that any outgoing data, such as an exception, is
278+
// completely transmitted to the client before the socket terminates. The seconds specified is arbitrary, though chosen to be large
279+
// enough to transfer any remaining data successfully and small enough to cause a timely disconnection. A custom prepareSocket
280+
// implementation can always change it via SetSocketOption, if necessary.
281+
//
282+
// https://msdn.microsoft.com/en-us/library/system.net.sockets.socket.disconnect(v=vs.110).aspx
283+
client.LingerState.Enabled = true;
284+
client.LingerState.LingerTime = LingerTimeInSeconds;
272285

273-
var localEndPoint = client.Client.LocalEndPoint;
274-
var remoteEndPoint = client.Client.RemoteEndPoint;
286+
prepareSocket(client.Client);
275287

276-
var exceptions = new List<ExceptionDispatchInfo>();
277-
var shutdownReason = QbservableProtocolShutdownReason.None;
288+
var watch = Stopwatch.StartNew();
278289

279-
try
280-
{
281-
using (var stream = new NetworkStream(client.Client, ownsSocket: false))
282-
using (var protocol = await NegotiateServerAsync(capturedId.Value, stream, formatterFactory(), options, cancel).ConfigureAwait(false))
283-
{
284-
capturedId.Value = protocol.ClientId;
285-
286-
var provider = providerFactory(protocol);
287-
288-
ReceivedConnection(idOverride: capturedId.Value);
289-
290-
try
291-
{
292-
await protocol.ExecuteServerAsync(provider).ConfigureAwait(false);
293-
}
294-
catch (OperationCanceledException)
295-
{
296-
}
297-
catch (Exception ex)
298-
{
299-
exceptions.Add(ExceptionDispatchInfo.Capture(ex));
300-
}
301-
finally
302-
{
303-
shutdownReason = protocol.ShutdownReason;
304-
}
305-
306-
var protocolExceptions = protocol.Exceptions;
307-
308-
if (protocolExceptions != null)
309-
{
310-
foreach (var exception in protocolExceptions)
311-
{
312-
exceptions.Add(exception);
313-
}
314-
}
315-
}
316-
}
317-
catch (OperationCanceledException)
318-
{
319-
shutdownReason = QbservableProtocolShutdownReason.ProtocolNegotiationCanceled;
320-
}
321-
catch (Exception ex)
322-
{
323-
shutdownReason = QbservableProtocolShutdownReason.ProtocolNegotiationError;
290+
var localEndPoint = client.Client.LocalEndPoint;
291+
var remoteEndPoint = client.Client.RemoteEndPoint;
324292

325-
exceptions.Add(ExceptionDispatchInfo.Capture(ex));
326-
}
293+
var exceptions = new List<ExceptionDispatchInfo>();
294+
var shutdownReason = QbservableProtocolShutdownReason.None;
327295

328-
return new TcpClientTermination(localEndPoint, remoteEndPoint, watch.Elapsed, shutdownReason, exceptions);
329-
})
330-
.Finally(() => Shutdown(client.Client, capturedId.Value))
331-
select result;
296+
try
297+
{
298+
using (var stream = new NetworkStream(client.Client, ownsSocket: false))
299+
using (var protocol = await NegotiateServerAsync(capturedId.Value, stream, formatterFactory(), options, cancel).ConfigureAwait(false))
300+
{
301+
capturedId.Value = protocol.ClientId;
302+
303+
var provider = providerFactory(protocol);
304+
305+
ReceivedConnection(idOverride: capturedId.Value);
306+
307+
try
308+
{
309+
await protocol.ExecuteServerAsync(provider).ConfigureAwait(false);
310+
}
311+
catch (OperationCanceledException)
312+
{
313+
}
314+
catch (Exception ex)
315+
{
316+
exceptions.Add(ExceptionDispatchInfo.Capture(ex));
317+
}
318+
finally
319+
{
320+
shutdownReason = protocol.ShutdownReason;
321+
}
322+
323+
var protocolExceptions = protocol.Exceptions;
324+
325+
if (protocolExceptions != null)
326+
{
327+
foreach (var exception in protocolExceptions)
328+
{
329+
exceptions.Add(exception);
330+
}
331+
}
332+
}
333+
}
334+
catch (OperationCanceledException)
335+
{
336+
shutdownReason = QbservableProtocolShutdownReason.ProtocolNegotiationCanceled;
337+
}
338+
catch (Exception ex)
339+
{
340+
shutdownReason = QbservableProtocolShutdownReason.ProtocolNegotiationError;
341+
342+
exceptions.Add(ExceptionDispatchInfo.Capture(ex));
343+
}
344+
345+
return new TcpClientTermination(localEndPoint, remoteEndPoint, watch.Elapsed, shutdownReason, exceptions);
332346
}
333347

334348
private async Task<IStreamQbservableProtocol> NegotiateClientAsync(Stream stream, IRemotingFormatter formatter, CancellationToken cancel)
@@ -464,7 +478,7 @@ private async void Shutdown(Socket socket, object id = null)
464478
}
465479

466480
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "The SocketAsyncEventArgs instance is either disposed before returning or by the observable's Finally operator.")]
467-
private async Task DisconnectAsync(Socket socket)
481+
private static async Task DisconnectAsync(Socket socket)
468482
{
469483
Contract.Requires(socket != null);
470484

0 commit comments

Comments
 (0)