Skip to content

Commit b169de8

Browse files
committed
Add PreferDataLoader to suggest using DataLoader where possible
1 parent 94cb26c commit b169de8

File tree

3 files changed

+52
-5
lines changed

3 files changed

+52
-5
lines changed

src/SMAPI.ModBuildConfig.Analyzer.Tests/ContentManagerAnalyzerTests.cs

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,46 @@ public void BadType_RaisesDiagnostic(string codeText, int column, string assetNa
9292
Id = "AvoidContentManagerBadType",
9393
Message = $"'{assetName}' uses the {suggestedType} type, but {expectedType} is in use instead. See https://smapi.io/package/avoid-contentmanager-type for details.",
9494
Severity = DiagnosticSeverity.Error,
95-
Locations = new[] { new DiagnosticResultLocation("Test0.cs", SampleCodeLine, SampleCodeColumn + column) }
95+
Locations = [new DiagnosticResultLocation("Test0.cs", SampleCodeLine, SampleCodeColumn + column)]
96+
};
97+
DiagnosticResult preferDataLoader = new()
98+
{
99+
Id = "PreferContentManagerDataLoader",
100+
Message = $"'{assetName[5..]}' can be accessed using 'DataLoader.{assetName[5..]}(LocalizedContentManager content)' instead. See https://smapi.io/package/prefer-contentmanager-dataloader for details.",
101+
Severity = DiagnosticSeverity.Info,
102+
Locations = [new DiagnosticResultLocation("Test0.cs", SampleCodeLine, SampleCodeColumn + column)]
103+
};
104+
105+
// assert
106+
this.VerifyCSharpDiagnostic(code, expected, preferDataLoader);
107+
}
108+
109+
110+
111+
/// <summary>Test that the expected diagnostic message is raised for avoidable net field references.</summary>
112+
/// <param name="codeText">The code line to test.</param>
113+
/// <param name="column">The column within the code line where the diagnostic message should be reported.</param>
114+
/// <param name="expression">The expression which should be reported.</param>
115+
/// <param name="netType">The net type name which should be reported.</param>
116+
/// <param name="suggestedProperty">The suggested property name which should be reported.</param>
117+
[TestCase("Game1.content.Load<Dictionary<string, string>>(\"Data\\\\Fish\");", 0, "Fish")]
118+
public void PreferDataLoader_RaisesDiagnostic(string codeText, int column, string assetName)
119+
{
120+
// arrange
121+
string code = SampleProgram.Replace("{{test-code}}", codeText);
122+
DiagnosticResult preferDataLoader = new()
123+
{
124+
Id = "PreferContentManagerDataLoader",
125+
Message = $"'{assetName}' can be accessed using 'DataLoader.{assetName}(LocalizedContentManager content)' instead. See https://smapi.io/package/prefer-contentmanager-dataloader for details.",
126+
Severity = DiagnosticSeverity.Info,
127+
Locations = [new DiagnosticResultLocation("Test0.cs", SampleCodeLine, SampleCodeColumn + column)]
96128
};
97129

98130
// assert
99-
this.VerifyCSharpDiagnostic(code, expected);
131+
this.VerifyCSharpDiagnostic(code, preferDataLoader);
100132
}
101133

102-
[TestCase("Game1.content.Load<Dictionary<string, string>>(\"Data\\\\Fish\");", true)]
134+
[TestCase("Game1.content.Load<Dictionary<string, string>>(\"Data\\\\Custom_Asset\");", true)]
103135
[TestCase(SampleUnrelatedGoodProgram, false)]
104136

105137
public void ValidCode_HasNoDiagnostics(string codeText, bool useWrapper)

src/SMAPI.ModBuildConfig.Analyzer.Tests/SMAPI.ModBuildConfig.Analyzer.Tests.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,9 @@
1515
<ProjectReference Include="..\SMAPI.ModBuildConfig.Analyzer\SMAPI.ModBuildConfig.Analyzer.csproj" />
1616
</ItemGroup>
1717

18+
<ItemGroup>
19+
<Folder Include="Mock\StardewModdingAPI\" />
20+
</ItemGroup>
21+
1822
<Import Project="..\..\build\common.targets" />
1923
</Project>

src/SMAPI.ModBuildConfig.Analyzer/ContentManagerAnalyzer.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class ContentManagerAnalyzer : DiagnosticAnalyzer
1616
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; }
1717

1818

19-
/// <summary>The diagnostic info for an avoidable net field access.</summary>
19+
/// <summary>The diagnostic info for an avoidable runtime casting error.</summary>
2020
private readonly DiagnosticDescriptor AvoidBadTypeRule = new(
2121
id: "AvoidContentManagerBadType",
2222
title: "Avoid incorrectly typing ContentManager Loads",
@@ -26,10 +26,20 @@ public class ContentManagerAnalyzer : DiagnosticAnalyzer
2626
isEnabledByDefault: true,
2727
helpLinkUri: "https://smapi.io/package/avoid-contentmanager-type"
2828
);
29+
/// <summary>The diagnostic info for best practices using DataLoader</summary>
30+
private readonly DiagnosticDescriptor PreferDataLoader = new(
31+
id: "PreferContentManagerDataLoader",
32+
title: "Prefer using DataLoader to ContentManager Loads",
33+
messageFormat: "'{0}' can be accessed using 'DataLoader.{0}(LocalizedContentManager content)' instead. See https://smapi.io/package/prefer-contentmanager-dataloader for details.",
34+
category: "SMAPI.CommonErrors",
35+
defaultSeverity: DiagnosticSeverity.Info,
36+
isEnabledByDefault: true,
37+
helpLinkUri: "https://smapi.io/package/prefer-contentmanager-dataloader"
38+
);
2939

3040
public ContentManagerAnalyzer()
3141
{
32-
this.SupportedDiagnostics = ImmutableArray.CreateRange(new[] { this.AvoidBadTypeRule });
42+
this.SupportedDiagnostics = ImmutableArray.CreateRange(new[] { this.AvoidBadTypeRule, this.PreferDataLoader });
3343
}
3444

3545
public override void Initialize(AnalysisContext context)
@@ -69,6 +79,7 @@ private void AnalyzeContentManagerLoads(SyntaxNodeAnalysisContext context)
6979
{
7080
context.ReportDiagnostic(Diagnostic.Create(this.AvoidBadTypeRule, context.Node.GetLocation(), assetName, method.ReturnType.ToString(), genericArgument.ToString()));
7181
}
82+
context.ReportDiagnostic(Diagnostic.Create(this.PreferDataLoader, context.Node.GetLocation(), dataAsset));
7283
}
7384
}
7485
}

0 commit comments

Comments
 (0)