Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,18 @@ public override MultiValue GetBackingFieldTargetValue(IPropertyReferenceOperatio

public override MultiValue GetParameterTargetValue(IParameterSymbol parameter)
{
return new MethodParameterValue(new ParameterProxy(parameter, parameter.ContainingSymbol as IMethodSymbol ?? (IMethodSymbol)OwningSymbol));
var parameterMethod = parameter.ContainingSymbol as IMethodSymbol ?? OwningSymbol as IMethodSymbol;
if (parameterMethod is null)
{
// If the parameter is not associated with a method, ignore it as it's not interesting for trim analysis.
// This can happen in the parameter initializer of an indexer property, for example.
// When visiting the assignment for the parameter initializer, the owning symbol will be the property
// symbol, not the get/set method. The get/set methods get analyzed in a separate context where the owning
// symbol of the same parameter (this time on the method) is the get/set method.
return TopValue;
}

return new MethodParameterValue(new ParameterProxy(parameter, parameterMethod));
}

public override void HandleAssignment(MultiValue source, MultiValue target, IOperation operation, in FeatureContext featureContext)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ public static void Main()

ExplicitIndexerAccess.Test();
ImplicitIndexerAccess.Test();
AnnotatedIndexerParameter.Test();
IndexerDefaultArgument.Test();

AnnotationOnUnsupportedType.Test();
AutoPropertyUnrecognizedField.Test();
Expand Down Expand Up @@ -927,6 +929,74 @@ public static void Test()
}
}

class AnnotatedIndexerParameter
{
public Type this[[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type index]
{
get
{
index.RequiresPublicConstructors();
return null;
}
[ExpectedWarning("IL2067", ["this[Type].set", "index"], Tool.Analyzer, "")]
[ExpectedWarning("IL2067", ["Item.set", "index"], Tool.Trimmer | Tool.NativeAot, "")]
set
{
index.RequiresPublicMethods();
}
}

[ExpectedWarning("IL2067", ["this[Type].set", nameof(unannotated), "index"], Tool.Analyzer, "")]
[ExpectedWarning("IL2067", ["Item.set", nameof(unannotated), "index"], Tool.Trimmer | Tool.NativeAot, "")]
static void ParameterMismatch(Type unannotated = null)
{
var instance = new AnnotatedIndexerParameter();
instance[unannotated] = null;
}

static void ParameterMatch([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type annotated = null)
{
var instance = new AnnotatedIndexerParameter();
instance[annotated] = null;
}

public static void Test()
{
ParameterMismatch();
ParameterMatch();
}
}

class IndexerDefaultArgument
{
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
Type this[int index = 0]
{
get => throw new NotImplementedException();
set => throw new NotImplementedException();
}

[ExpectedWarning("IL2072", ["this[Int32].get", nameof(DataFlowTypeExtensions.RequiresAll)], Tool.Analyzer, "")]
[ExpectedWarning("IL2072", ["Item.get", nameof(DataFlowTypeExtensions.RequiresAll)], Tool.Trimmer | Tool.NativeAot, "")]
static void TestRead(IndexerDefaultArgument instance = null)
{
instance[1].RequiresAll();
}

[ExpectedWarning("IL2072", [nameof(GetTypeWithPublicConstructors), "this[Int32].set"], Tool.Analyzer, "")]
[ExpectedWarning("IL2072", [nameof(GetTypeWithPublicConstructors), "Item.set"], Tool.Trimmer | Tool.NativeAot, "")]
static void TestWrite(IndexerDefaultArgument instance = null)
{
instance[1] = GetTypeWithPublicConstructors();
}

public static void Test()
{
TestRead();
TestWrite();
}
}

class AnnotationOnUnsupportedType
{
[ExpectedWarning("IL2099", nameof(PropertyWithUnsupportedType))]
Expand Down
Loading