Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Merge master to features/module-initializers #45773

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
34a678e
Move SymbolSearch down to a non-WPF layer
sharwell Jun 12, 2020
c94ef8a
Remove the EditorFeatures.Wpf dependency from Remote.ServiceHub
sharwell Jun 12, 2020
564a9bb
Go through common semantic model path.
CyrusNajmabadi Jun 30, 2020
82a1dc7
Add helper
CyrusNajmabadi Jun 30, 2020
c86bde9
Add helper extension
CyrusNajmabadi Jul 1, 2020
b4f3e30
Rename method
CyrusNajmabadi Jun 30, 2020
7fe7aed
Simplify code
CyrusNajmabadi Jun 30, 2020
7d94503
Simplify code.
CyrusNajmabadi Jun 30, 2020
a09fc44
Rename method
CyrusNajmabadi Jun 30, 2020
e67435f
Rename method
CyrusNajmabadi Jun 30, 2020
7f41453
Make parameter non-optional
CyrusNajmabadi Jun 30, 2020
6764f1e
Simplify code.
CyrusNajmabadi Jun 30, 2020
6cdd3f7
Simplify code.
CyrusNajmabadi Jun 30, 2020
3306bb1
Rename
CyrusNajmabadi Jun 30, 2020
5afc428
Initial work on an entirely new caching implementation
CyrusNajmabadi Jun 30, 2020
6fcd367
C# impl done.
CyrusNajmabadi Jun 30, 2020
4123302
Simplify code.
CyrusNajmabadi Jul 1, 2020
44ec875
VBimpl
CyrusNajmabadi Jul 1, 2020
d285011
Fix
CyrusNajmabadi Jul 1, 2020
23d6f4d
Remove dead code.
CyrusNajmabadi Jul 1, 2020
d4ddfa2
Make non-optional
CyrusNajmabadi Jul 1, 2020
767d632
Delete dead code.
CyrusNajmabadi Jul 1, 2020
aa6593f
Wrapping
CyrusNajmabadi Jul 1, 2020
edf5055
Remove
CyrusNajmabadi Jul 1, 2020
0e04767
Do not speculate on the same mdoel
CyrusNajmabadi Jul 1, 2020
5c14396
Do not reuse with classification
CyrusNajmabadi Jul 1, 2020
950a528
Update src/Workspaces/Core/Portable/SemanticModelReuse/SemanticModelW…
CyrusNajmabadi Jul 1, 2020
9f7ba09
Fix test
CyrusNajmabadi Jul 1, 2020
0b81c8e
Simplify
CyrusNajmabadi Jul 1, 2020
a2100a3
Simplify and make work for accessors
CyrusNajmabadi Jul 1, 2020
da0d617
Simplify
CyrusNajmabadi Jul 1, 2020
2998dd4
Merge remote-tracking branch 'dotnet/master' into no-wpf
sharwell Jul 1, 2020
153691f
Lint
CyrusNajmabadi Jul 1, 2020
d1b7269
Update src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Ext…
CyrusNajmabadi Jul 2, 2020
186a647
Merge remote-tracking branch 'upstream/master' into semanticModelWork
CyrusNajmabadi Jul 2, 2020
4faa00d
Merge branch 'semanticModelWork' of https://github.com/CyrusNajmabadi…
CyrusNajmabadi Jul 2, 2020
393bf70
Simplify
CyrusNajmabadi Jul 2, 2020
46daaef
Do not get semantic model to ask syntaqctic question.
CyrusNajmabadi Jul 2, 2020
6279a08
start at the right node.
CyrusNajmabadi Jul 2, 2020
3ded424
Add assert
CyrusNajmabadi Jul 2, 2020
020258b
Update src/Workspaces/Core/Portable/SemanticModelReuse/SemanticModelW…
CyrusNajmabadi Jul 2, 2020
8dafe3b
Add docs and an assert.
CyrusNajmabadi Jul 2, 2020
8d9db83
Update doc
CyrusNajmabadi Jul 2, 2020
cb6729b
Clear the cache as the solution changes.
CyrusNajmabadi Jul 2, 2020
09bcd71
Doc threading
CyrusNajmabadi Jul 2, 2020
9861343
Simplify
CyrusNajmabadi Jul 2, 2020
eb21aa0
Generate VB syntax in a platform-agnostic manner, so that running the…
333fred Jul 2, 2020
8b4051f
Simplify
CyrusNajmabadi Jul 2, 2020
b21720f
Keep cached linked doc info.
CyrusNajmabadi Jul 2, 2020
9d9af3a
Share code between c#and vb
CyrusNajmabadi Jul 2, 2020
b19e705
Add asserts
CyrusNajmabadi Jul 2, 2020
16d3450
Undo
CyrusNajmabadi Jul 2, 2020
e7f2c44
REgular attribute
CyrusNajmabadi Jul 2, 2020
81bc7d5
Add direct tests
CyrusNajmabadi Jul 6, 2020
53b88f5
Merge remote-tracking branch 'upstream/master' into semanticModelWork
CyrusNajmabadi Jul 6, 2020
b1fcb48
Fix tests
CyrusNajmabadi Jul 6, 2020
2d9d7ad
Avoid SoftCrashException from CodeLens data point invalidation calls
tmat Jul 6, 2020
71360a4
Support basic cases in UseRangeOperator
mahalex Jul 6, 2020
320e434
Fix unit test
mahalex Jul 6, 2020
a24c045
Style fixes
mahalex Jul 6, 2020
806127e
More style fixes
mahalex Jul 6, 2020
28ca0fa
Merge pull request #45683 from tmat/CodeLensFix
tmat Jul 6, 2020
d5c6ee5
Merge pull request #45716 from dotnet/merges/release/dev16.7-to-master
Jul 7, 2020
98bd599
Remove requirement to list all transitively referenced projects in Pr…
tmat Jul 7, 2020
da5c19f
Remove unused
tmat Jul 7, 2020
9f638fc
Update roslyn-analyzers to 3.3.0-beta1.20262.5
sharwell Jul 2, 2020
63adeec
Reduce the severity of RS0046 (Avoid the 'Opt' suffix in nullable-ena…
sharwell Jul 2, 2020
704d1ce
Disable suppressor RS0047
sharwell Jul 7, 2020
d59a2b3
Merge pull request #45731 from tmat/RemoveProjectRefCheck
tmat Jul 7, 2020
7fcd3b3
Report use-site diagnostics in BindWithExpression (#45664)
AlekseyTs Jul 7, 2020
840dc9b
Merge pull request #45565 from CyrusNajmabadi/semanticModelWork
CyrusNajmabadi Jul 7, 2020
81d4452
Merge pull request #45693 from mahalex/use-range-operator-basic-cases
CyrusNajmabadi Jul 7, 2020
0597445
Consider nullability in ReferenceIndexerBase (#45714)
cston Jul 7, 2020
e793cea
Merge pull request #45619 from sharwell/update-analyzers
sharwell Jul 7, 2020
8d5b404
Merge pull request #45624 from 333fred/vb-newline-fixes
333fred Jul 7, 2020
7b4bfaa
Merge pull request #45115 from sharwell/no-wpf
sharwell Jul 7, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,6 @@ csharp_preserve_single_line_statements = true
# warning RS0037: PublicAPI.txt is missing '#nullable enable'
dotnet_diagnostic.RS0037.severity = none

# RS0046: Avoid the 'Opt' suffix
dotnet_diagnostic.RS0046.severity = suggestion

[src/CodeStyle/**.{cs,vb}]
# warning RS0005: Do not use generic CodeAction.Create to create CodeAction
dotnet_diagnostic.RS0005.severity = none
Expand Down
4 changes: 2 additions & 2 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
</PropertyGroup>
<PropertyGroup>
<!-- Versions used by several individual references below -->
<RoslynDiagnosticsNugetPackageVersion>3.3.0-beta1.20351.1</RoslynDiagnosticsNugetPackageVersion>
<MicrosoftCodeAnalysisNetAnalyzersVersion>3.3.0-beta1.20351.1</MicrosoftCodeAnalysisNetAnalyzersVersion>
<RoslynDiagnosticsNugetPackageVersion>3.3.0-beta1.20352.4</RoslynDiagnosticsNugetPackageVersion>
<MicrosoftCodeAnalysisNetAnalyzersVersion>3.3.0-beta1.20352.4</MicrosoftCodeAnalysisNetAnalyzersVersion>
<CodeStyleLayerCodeAnalysisVersion>3.6.0-2.final</CodeStyleLayerCodeAnalysisVersion>
<MicrosoftCodeAnalysisTestingVersion>1.0.1-beta1.20210.2</MicrosoftCodeAnalysisTestingVersion>
<CodeStyleAnalyzerVersion>3.7.0-3.20271.4</CodeStyleAnalyzerVersion>
Expand Down
2 changes: 2 additions & 0 deletions eng/config/rulesets/Shipping.ruleset
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
<Rule Id="RS0026" Action="Error" />
<Rule Id="RS0027" Action="Error" />
<Rule Id="RS0040" Action="None" /> <!-- Defaultable types should have defaultable fields -->
<Rule Id="RS0046" Action="Info" /> <!-- Avoid the 'Opt' suffix in nullable-enabled code (too noisy right now) -->
<Rule Id="RS0047" Action="None" /> <!-- (Suppressor) The 'Type.FullName' property is never null when using the syntax 'typeof(T).FullName' -->
</Rules>
<Rules AnalyzerId="xunit.analyzers" RuleNamespace="Xunit.Analyzers">
<Rule Id="xUnit1004" Action="Hidden" /> <!-- allow skipped tests, with a code fix to unskip them -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public InfoCache(Compilation compilation)
{
var substringMethod = stringType.GetMembers(nameof(string.Substring))
.OfType<IMethodSymbol>()
.FirstOrDefault(m => IsSliceLikeMethod(m));
.FirstOrDefault(m => IsTwoArgumentSliceLikeMethod(m));

_methodToMemberInfo[substringMethod] = ComputeMemberInfo(substringMethod, requireRangeMember: false);
}
Expand All @@ -54,12 +54,12 @@ public InfoCache(Compilation compilation)
private static IMethodSymbol GetSliceLikeMethod(INamedTypeSymbol namedType)
=> namedType.GetMembers()
.OfType<IMethodSymbol>()
.Where(m => IsSliceLikeMethod(m))
.Where(m => IsTwoArgumentSliceLikeMethod(m))
.FirstOrDefault();

public bool TryGetMemberInfo(IMethodSymbol method, out MemberInfo memberInfo)
{
if (!IsSliceLikeMethod(method))
if (!IsTwoArgumentSliceLikeMethod(method))
{
memberInfo = default;
return false;
Expand All @@ -69,9 +69,44 @@ public bool TryGetMemberInfo(IMethodSymbol method, out MemberInfo memberInfo)
return memberInfo.LengthLikeProperty != null;
}

public bool TryGetMemberInfoOneArgument(IMethodSymbol method, out MemberInfo memberInfo)
{
if (!IsOneArgumentSliceLikeMethod(method))
{
memberInfo = default;
return false;
}

if (!_methodToMemberInfo.TryGetValue(method, out memberInfo))
{
// Find overload of our method that is a slice-like method with two arguments.
// Computing member info for this method will also check that the containing type
// has an int32 'Length' or 'Count' property, and has a suitable indexer,
// so we don't have to.
var overloadWithTwoArguments = method.ContainingType
.GetMembers(method.Name)
.OfType<IMethodSymbol>()
.FirstOrDefault(s => IsTwoArgumentSliceLikeMethod(s));
if (overloadWithTwoArguments is null)
{
memberInfo = default;
return false;
}

// Since the search is expensive, we keep both the original one-argument and
// two-arguments overload as keys in the cache, pointing to the same
// member information object.
var newMemberInfo = _methodToMemberInfo.GetOrAdd(overloadWithTwoArguments, _ => ComputeMemberInfo(overloadWithTwoArguments, requireRangeMember: true));
_methodToMemberInfo.GetOrAdd(method, _ => newMemberInfo);
memberInfo = newMemberInfo;
}

return memberInfo.LengthLikeProperty != null;
}

private MemberInfo ComputeMemberInfo(IMethodSymbol sliceLikeMethod, bool requireRangeMember)
{
Debug.Assert(IsSliceLikeMethod(sliceLikeMethod));
Debug.Assert(IsTwoArgumentSliceLikeMethod(sliceLikeMethod));

// Check that the type has an int32 'Length' or 'Count' property. If not, we don't
// consider it something indexable.
Expand Down Expand Up @@ -106,7 +141,7 @@ private MemberInfo ComputeMemberInfo(IMethodSymbol sliceLikeMethod, bool require
var actualSliceMethod =
sliceLikeMethod.ContainingType.GetMembers(nameof(Span<int>.Slice))
.OfType<IMethodSymbol>()
.FirstOrDefault(s => IsSliceLikeMethod(s));
.FirstOrDefault(s => IsTwoArgumentSliceLikeMethod(s));
if (actualSliceMethod != null)
{
return new MemberInfo(lengthLikeProperty, overloadedMethodOpt: null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// 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 Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Operations;
Expand All @@ -12,7 +14,7 @@ internal partial class CSharpUseRangeOperatorDiagnosticAnalyzer
{
public enum ResultKind
{
// like s.Substring(expr, s.Length - expr). 'expr' has to match on both sides.
// like s.Substring(expr, s.Length - expr) or s.Substring(expr). 'expr' has to match on both sides.
Computed,

// like s.Substring(constant1, s.Length - constant2). the constants don't have to match.
Expand All @@ -28,13 +30,17 @@ public readonly struct Result
public readonly IMethodSymbol SliceLikeMethod;
public readonly MemberInfo MemberInfo;
public readonly IOperation Op1;
public readonly IOperation Op2;

/// <summary>
/// Can be null, if we are dealing with one-argument call to a slice-like method.
/// </summary>
public readonly IOperation? Op2;

public Result(
ResultKind kind, CodeStyleOption2<bool> option,
IInvocationOperation invocationOperation, InvocationExpressionSyntax invocation,
IMethodSymbol sliceLikeMethod, MemberInfo memberInfo,
IOperation op1, IOperation op2)
IOperation op1, IOperation? op2)
{
Kind = kind;
Option = option;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,54 @@ private void AnalyzeInvocation(
}
}

// look for `s.Slice(e1, end - e2)`
if (invocation.Instance is null ||
invocation.Arguments.Length != 2)
// look for `s.Slice(e1, end - e2)` or `s.Slice(e1)`
if (invocation.Instance is null)
{
return null;
}

return invocation.Arguments.Length switch
{
1 => AnalyzeOneArgumentInvocation(invocation, infoCache, invocationSyntax, option),
2 => AnalyzeTwoArgumentInvocation(invocation, infoCache, invocationSyntax, option),
_ => null,
};
}

private static Result? AnalyzeOneArgumentInvocation(
IInvocationOperation invocation,
InfoCache infoCache,
InvocationExpressionSyntax invocationSyntax,
CodeStyleOption2<bool> option)
{
var targetMethod = invocation.TargetMethod;

// We are dealing with a call like `.Substring(expr)`.
// Ensure that there is an overload with signature like `Substring(int start, int length)`
// and there is a suitable indexer to replace this with `[expr..]`.
if (!infoCache.TryGetMemberInfoOneArgument(targetMethod, out var memberInfo))
{
return null;
}

var startOperation = invocation.Arguments[0].Value;
return new Result(
ResultKind.Computed,
option,
invocation,
invocationSyntax,
targetMethod,
memberInfo,
op1: startOperation,
op2: null); // The range will run to the end.
}

private static Result? AnalyzeTwoArgumentInvocation(
IInvocationOperation invocation,
InfoCache infoCache,
InvocationExpressionSyntax invocationSyntax,
CodeStyleOption2<bool> option)
{
// See if the call is to something slice-like.
var targetMethod = invocation.TargetMethod;

Expand Down
39 changes: 29 additions & 10 deletions src/Analyzers/CSharp/Analyzers/UseIndexOrRangeOperator/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,35 @@ public static bool IsIntIndexingMethod(IMethodSymbol method)
/// names of the parameters are checked to ensure they are appropriate slice-like. These
/// names were picked by examining the patterns in the BCL for slicing members.
/// </summary>
public static bool IsSliceLikeMethod(IMethodSymbol method)
=> method != null &&
IsPublicInstance(method) &&
method.Parameters.Length == 2 &&
// From: https://github.com/dotnet/csharplang/blob/master/proposals/csharp-8.0/ranges.md#decisions-made-during-implementation
//
// When looking for the pattern members, we look for original definitions, not
// constructed members
IsSliceFirstParameter(method.OriginalDefinition.Parameters[0]) &&
IsSliceSecondParameter(method.OriginalDefinition.Parameters[1]);
public static bool IsTwoArgumentSliceLikeMethod(IMethodSymbol method)
{
// From: https://github.com/dotnet/csharplang/blob/master/proposals/csharp-8.0/ranges.md#decisions-made-during-implementation
//
// When looking for the pattern members, we look for original definitions, not
// constructed members
return method != null &&
IsPublicInstance(method) &&
method.Parameters.Length == 2 &&
IsSliceFirstParameter(method.OriginalDefinition.Parameters[0]) &&
IsSliceSecondParameter(method.OriginalDefinition.Parameters[1]);
}

/// <summary>
/// Look for methods like "SomeType MyType.Slice(int start)". Note that the
/// name of the parameter is checked to ensure it is appropriate slice-like.
/// This name was picked by examining the patterns in the BCL for slicing members.
/// </summary>
public static bool IsOneArgumentSliceLikeMethod(IMethodSymbol method)
{
// From: https://github.com/dotnet/csharplang/blob/master/proposals/csharp-8.0/ranges.md#decisions-made-during-implementation
//
// When looking for the pattern members, we look for original definitions, not
// constructed members
return method != null &&
IsPublicInstance(method) &&
method.Parameters.Length == 1 &&
IsSliceFirstParameter(method.OriginalDefinition.Parameters[0]);
}

private static bool IsSliceFirstParameter(IParameterSymbol parameter)
=> parameter.Type.SpecialType == SpecialType.System_Int32 &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,16 +150,22 @@ private static RangeExpressionSyntax CreateComputedRange(Result result)
var startFromEnd = IsFromEnd(lengthLikeProperty, instance, ref startOperation);
var startExpr = (ExpressionSyntax)startOperation.Syntax;

// Similarly, if our end-op is actually equivalent to `expr.Length - val`, then just
// change our end-op to be `val` and record that we should emit it as `^val`.
var endFromEnd = IsFromEnd(lengthLikeProperty, instance, ref endOperation);
var endExpr = (ExpressionSyntax)endOperation.Syntax;

// If the range operation goes to 'expr.Length' then we can just leave off the end part
// of the range. i.e. `start..`
if (IsInstanceLengthCheck(lengthLikeProperty, instance, endOperation))
var endFromEnd = false;
ExpressionSyntax endExpr = null;

if (!(endOperation is null))
{
endExpr = null;
// We need to do the same for the second argument, since it's present.
// Similarly, if our end-op is actually equivalent to `expr.Length - val`, then just
// change our end-op to be `val` and record that we should emit it as `^val`.
endFromEnd = IsFromEnd(lengthLikeProperty, instance, ref endOperation);

// Check if the range goes to 'expr.Length'; if it does, we leave off
// the end part of the range, i.e. `start..`.
if (!IsInstanceLengthCheck(lengthLikeProperty, instance, endOperation))
{
endExpr = (ExpressionSyntax)endOperation.Syntax;
}
}

// If we're starting the range operation from 0, then we can just leave off the start of
Expand Down
Loading