Skip to content

Commit

Permalink
Enable nullable annotations (shpaass#140)
Browse files Browse the repository at this point in the history
This enables nullable annotations for all four non-test projects and
removes the corresponding warnings. I found and fixed a few bugs in the
process, and did some refactoring when I happened to notice cases where
static-to-instance changes could remove some of the null-forgiving
operators. There's probably more refactoring to do; I know Dorus wants
to do more work with `FlatHierarchy`, for example.

Unfortunately, this does cause conflicts with most of the other PRs. We
could take only some of the nullable changes, but I thought having
nullable in some projects but not others would lead to confusion.
  • Loading branch information
DaleStan authored Jun 2, 2024
2 parents 6391bb6 + af6aba6 commit 4860726
Show file tree
Hide file tree
Showing 102 changed files with 1,591 additions and 1,439 deletions.
1 change: 0 additions & 1 deletion CommandLineToolExample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ public static void Main(string[] args) {
Console.WriteLine("Pass FactorioData path as command-line argument");
return;
}
YafcLib.Init();
YafcLib.RegisterDefaultAnalysis(); // Register analysis to get cost, milestones, accessibility, etc information. Skip if you just need data.
string factorioPath = args[0];
ErrorCollector errorCollector = new ErrorCollector();
Expand Down
6 changes: 3 additions & 3 deletions Yafc.Model.Tests/Analysis/Milestones.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ private static Bits createBits(ulong value) {
var bitsLength = bitsType.GetField("_length", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

Bits bits = new Bits();
bitsData.SetValue(bits, new ulong[] { value });
bitsLength.SetValue(bits, sizeof(ulong));
bitsLength.SetValue(bits, bits.HighestBitSet() + 1);
bitsData.SetValueDirect(__makeref(bits), new ulong[] { value });
bitsLength.SetValueDirect(__makeref(bits), sizeof(ulong));
bitsLength.SetValueDirect(__makeref(bits), bits.HighestBitSet() + 1);

return bits;
}
Expand Down
127 changes: 64 additions & 63 deletions Yafc.Model.Tests/Math/Bits.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Reflection;
using System;
using System.Reflection;
using Xunit;

namespace Yafc.Model.Tests {
Expand Down Expand Up @@ -75,10 +76,10 @@ public void AndOperator_WithGivenInputBits_ShouldReturnANDedBits(ulong aValue, u

Bits a = new Bits();
Bits b = new Bits();
bitsData.SetValue(a, new ulong[] { aValue });
bitsData.SetValue(b, new ulong[] { bValue });
bitsLength.SetValue(a, 8);
bitsLength.SetValue(b, 8);
bitsData.SetValueDirect(__makeref(a), new ulong[] { aValue });
bitsData.SetValueDirect(__makeref(b), new ulong[] { bValue });
bitsLength.SetValueDirect(__makeref(a), 8);
bitsLength.SetValueDirect(__makeref(b), 8);

var result = a & b;

Expand All @@ -95,10 +96,10 @@ public void AndOperator_WithOneLargeValue_ReturnCorrectBits() {

Bits a = new Bits();
Bits b = new Bits();
bitsData.SetValue(a, new ulong[] { 4, 3 });
bitsData.SetValue(b, new ulong[] { 4 });
bitsLength.SetValue(a, 128);
bitsLength.SetValue(b, 128);
bitsData.SetValueDirect(__makeref(a), new ulong[] { 4, 3 });
bitsData.SetValueDirect(__makeref(b), new ulong[] { 4 });
bitsLength.SetValueDirect(__makeref(a), 128);
bitsLength.SetValueDirect(__makeref(b), 128);

var result = a & b;

Expand All @@ -116,10 +117,10 @@ public void AndOperator_WithLargeValues_ReturnCorrectBits() {

Bits a = new Bits();
Bits b = new Bits();
bitsData.SetValue(a, new ulong[] { 4, 3 });
bitsData.SetValue(b, new ulong[] { 4, 1 });
bitsLength.SetValue(a, 128);
bitsLength.SetValue(b, 128);
bitsData.SetValueDirect(__makeref(a), new ulong[] { 4, 3 });
bitsData.SetValueDirect(__makeref(b), new ulong[] { 4, 1 });
bitsLength.SetValueDirect(__makeref(a), 128);
bitsLength.SetValueDirect(__makeref(b), 128);

var result = a & b;

Expand All @@ -140,10 +141,10 @@ public void OrOperator_WithGivenInputBits_ShouldReturnORedBits(ulong aValue, ulo

Bits a = new Bits();
Bits b = new Bits();
bitsData.SetValue(a, new ulong[] { aValue });
bitsData.SetValue(b, new ulong[] { bValue });
bitsLength.SetValue(a, 8);
bitsLength.SetValue(b, 8);
bitsData.SetValueDirect(__makeref(a), new ulong[] { aValue });
bitsData.SetValueDirect(__makeref(b), new ulong[] { bValue });
bitsLength.SetValueDirect(__makeref(a), 8);
bitsLength.SetValueDirect(__makeref(b), 8);

var result = a | b;

Expand All @@ -160,10 +161,10 @@ public void OrOperator_WithOneLargeValue_ReturnCorrectBits() {

Bits a = new Bits();
Bits b = new Bits();
bitsData.SetValue(a, new ulong[] { 4, 3 });
bitsData.SetValue(b, new ulong[] { 4 });
bitsLength.SetValue(a, 128);
bitsLength.SetValue(b, 128);
bitsData.SetValueDirect(__makeref(a), new ulong[] { 4, 3 });
bitsData.SetValueDirect(__makeref(b), new ulong[] { 4 });
bitsLength.SetValueDirect(__makeref(a), 128);
bitsLength.SetValueDirect(__makeref(b), 128);

var result = a | b;

Expand All @@ -181,10 +182,10 @@ public void OrOperator_WithLargeValues_ReturnCorrectBits() {

Bits a = new Bits();
Bits b = new Bits();
bitsData.SetValue(a, new ulong[] { 4, 3 });
bitsData.SetValue(b, new ulong[] { 4, 1 });
bitsLength.SetValue(a, 128);
bitsLength.SetValue(b, 128);
bitsData.SetValueDirect(__makeref(a), new ulong[] { 4, 3 });
bitsData.SetValueDirect(__makeref(b), new ulong[] { 4, 1 });
bitsLength.SetValueDirect(__makeref(a), 128);
bitsLength.SetValueDirect(__makeref(b), 128);

var result = a | b;

Expand All @@ -204,8 +205,8 @@ public void ShiftLeftOperator_WithGivenInputBits_ShouldReturnShiftedBits(ulong a
var bitsLength = bitsType.GetField("_length", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

Bits a = new Bits();
bitsData.SetValue(a, new ulong[] { aValue });
bitsLength.SetValue(a, 8);
bitsData.SetValueDirect(__makeref(a), new ulong[] { aValue });
bitsLength.SetValueDirect(__makeref(a), 8);

var result = a << 1;

Expand All @@ -223,8 +224,8 @@ public void SubtractOperator_WithGivenInputBits_ShouldReturnCorrectResult(ulong
var bitsLength = bitsType.GetField("_length", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

Bits a = new Bits();
bitsData.SetValue(a, new ulong[] { aValue });
bitsLength.SetValue(a, 8);
bitsData.SetValueDirect(__makeref(a), new ulong[] { aValue });
bitsLength.SetValueDirect(__makeref(a), 8);

var result = a - bValue;

Expand All @@ -242,8 +243,8 @@ public void EqualOperator_WithGivenInputBits_ShouldReturnCorrectResult(ulong aVa
var bitsLength = bitsType.GetField("_length", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

Bits a = new Bits();
bitsData.SetValue(a, new ulong[] { aValue });
bitsLength.SetValue(a, 8);
bitsData.SetValueDirect(__makeref(a), new ulong[] { aValue });
bitsLength.SetValueDirect(__makeref(a), 8);

bool result = a == bValue;

Expand All @@ -258,15 +259,15 @@ public void EqualOperator_WithLargeValues_ShouldReturnCorrectResult() {
var bitsLength = bitsType.GetField("_length", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

Bits a = new Bits();
bitsData.SetValue(a, new ulong[] { 4, 3 });
bitsLength.SetValue(a, 128);
bitsData.SetValueDirect(__makeref(a), new ulong[] { 4, 3 });
bitsLength.SetValueDirect(__makeref(a), 128);

bool result = a == 4;

// First data element matches, but next one is not zero
Assert.False(result);

bitsData.SetValue(a, new ulong[] { 4, 0 });
bitsData.SetValueDirect(__makeref(a), new ulong[] { 4, 0 });

bool result2 = a == 4;

Expand All @@ -282,20 +283,20 @@ public void EqualOperator_WithSameValueDifferentLengths_ShouldReturnCorrectResul

Bits a = new Bits();
Bits b = new Bits();
bitsData.SetValue(a, new ulong[] { 4, 3 });
bitsData.SetValue(b, new ulong[] { 4, 3 });
bitsLength.SetValue(a, 128);
bitsLength.SetValue(b, 126); // drop some zeros
bitsData.SetValueDirect(__makeref(a), new ulong[] { 4, 3 });
bitsData.SetValueDirect(__makeref(b), new ulong[] { 4, 3 });
bitsLength.SetValueDirect(__makeref(a), 128);
bitsLength.SetValueDirect(__makeref(b), 126); // drop some zeros

Assert.True(a == b);
}

[Fact]
public void EqualOperator_WithNull_ShouldReturnFalse() {
Bits a = null;
public void EqualOperator_WithDefault_ShouldReturnTrue() {
Bits a = default;
bool result = a == 0;

Assert.False(result);
Assert.True(result);
}

[Theory]
Expand All @@ -307,8 +308,8 @@ public void UnequalOperator_WithGivenInputBits_ShouldReturnCorrectResult(ulong a
var bitsLength = bitsType.GetField("_length", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

Bits a = new Bits();
bitsData.SetValue(a, new ulong[] { aValue });
bitsLength.SetValue(a, 8);
bitsData.SetValueDirect(__makeref(a), new ulong[] { aValue });
bitsLength.SetValueDirect(__makeref(a), 8);

bool result = a != bValue;

Expand All @@ -322,15 +323,15 @@ public void UnequalOperator_WithLargeValues_ShouldReturnCorrectResult() {
var bitsLength = bitsType.GetField("_length", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

Bits a = new Bits();
bitsData.SetValue(a, new ulong[] { 4, 3 });
bitsLength.SetValue(a, 128);
bitsData.SetValueDirect(__makeref(a), new ulong[] { 4, 3 });
bitsLength.SetValueDirect(__makeref(a), 128);

bool result = a != 4;

// First data element matches, but next one is not zero so unequal
Assert.True(result);

bitsData.SetValue(a, new ulong[] { 4, 0 });
bitsData.SetValueDirect(__makeref(a), new ulong[] { 4, 0 });

bool result2 = a != 4;

Expand All @@ -345,19 +346,19 @@ public void UnequalOperator_WithSameValueDifferentLengths_ShouldReturnCorrectRes

Bits a = new Bits();
Bits b = new Bits();
bitsData.SetValue(a, new ulong[] { 4, 3 });
bitsData.SetValue(b, new ulong[] { 4, 3 });
bitsLength.SetValue(a, 128);
bitsLength.SetValue(b, 126); // drop some zeros
bitsData.SetValueDirect(__makeref(a), new ulong[] { 4, 3 });
bitsData.SetValueDirect(__makeref(b), new ulong[] { 4, 3 });
bitsLength.SetValueDirect(__makeref(a), 128);
bitsLength.SetValueDirect(__makeref(b), 126); // drop some zeros

// Number of bits does not matter, so a == b
Assert.False(a != b);
}


[Fact]
public void UnequalOperator_WithNull_ShouldReturnFalse() {
Bits a = null;
public void UnequalOperator_WithDefault_ShouldReturnFalse() {
Bits a = default;
bool result = a != 0;

Assert.False(result);
Expand All @@ -369,8 +370,8 @@ public void SubtractOperator_WithLongInputBits_ShouldReturnCorrectResult() {
var bitsLength = bitsType.GetField("_length", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

Bits a = new Bits();
bitsData.SetValue(a, new ulong[] { 0, 3 });
bitsLength.SetValue(a, 128);
bitsData.SetValueDirect(__makeref(a), new ulong[] { 0, 3 });
bitsLength.SetValueDirect(__makeref(a), 128);

var result = a - 1;

Expand All @@ -392,10 +393,10 @@ public void LesserThanOperator_WithGivenInputBits_ShouldReturnCorrectResult(ulon

Bits a = new Bits();
Bits b = new Bits();
bitsData.SetValue(a, new ulong[] { aValue });
bitsData.SetValue(b, new ulong[] { bValue });
bitsLength.SetValue(a, 8);
bitsLength.SetValue(b, 8);
bitsData.SetValueDirect(__makeref(a), new ulong[] { aValue });
bitsData.SetValueDirect(__makeref(b), new ulong[] { bValue });
bitsLength.SetValueDirect(__makeref(a), 8);
bitsLength.SetValueDirect(__makeref(b), 8);

bool result = a < b;

Expand All @@ -411,17 +412,17 @@ public void LesserThanOperator_WithLargeValues_ShouldReturnCorrectResult() {

Bits a = new Bits();
Bits b = new Bits();
bitsData.SetValue(a, new ulong[] { 4, 3 });
bitsData.SetValue(b, new ulong[] { 3, 3 });
bitsLength.SetValue(a, 128);
bitsLength.SetValue(b, 128);
bitsData.SetValueDirect(__makeref(a), new ulong[] { 4, 3 });
bitsData.SetValueDirect(__makeref(b), new ulong[] { 3, 3 });
bitsLength.SetValueDirect(__makeref(a), 128);
bitsLength.SetValueDirect(__makeref(b), 128);

bool result = a < b;

// Second data element matches, but first one is not lesser
Assert.False(result);

bitsData.SetValue(a, new ulong[] { 2, 3 });
bitsData.SetValueDirect(__makeref(a), new ulong[] { 2, 3 });

bool result2 = a < b;

Expand Down
2 changes: 1 addition & 1 deletion Yafc.Model/Analysis/AutomationAnalysis.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public override void Compute(Project project, ErrorCollector warnings) {
// If only character is accessible at current milestones as a crafting entity, don't count the object as currently automatable
bool hasMachine = false;
foreach (var element in depGroup.elements) {
if (element != Database.character.id && Milestones.Instance.IsAccessibleWithCurrentMilestones(element)) {
if (element != Database.character?.id && Milestones.Instance.IsAccessibleWithCurrentMilestones(element)) {
hasMachine = true;
break;
}
Expand Down
12 changes: 6 additions & 6 deletions Yafc.Model/Analysis/CostAnalysis.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ public static CostAnalysis Get(bool atCurrentMilestones) {
public Mapping<RecipeOrTechnology, float> recipeProductCost;
public Mapping<FactorioObject, float> flow;
public Mapping<Recipe, float> recipeWastePercentage;
public Goods[] importantItems;
public Goods[]? importantItems;
private readonly bool onlyCurrentMilestones = onlyCurrentMilestones;
private string itemAmountPrefix;
private string? itemAmountPrefix;

private bool ShouldInclude(FactorioObject obj) {
return onlyCurrentMilestones ? obj.IsAutomatableWithCurrentMilestones() : obj.IsAutomatable();
Expand All @@ -57,8 +57,8 @@ public override void Compute(Project project, ErrorCollector warnings) {
}
else {
itemAmountPrefix = "Estimated amount for all researches: ";
foreach (var technology in Database.technologies.all) {
if (technology.IsAccessible()) {
foreach (Technology technology in Database.technologies.all) {
if (technology.IsAccessible() && technology.ingredients is not null) {
foreach (var ingredient in technology.ingredients) {
if (ingredient.goods.IsAutomatable()) {
if (onlyCurrentMilestones && !Milestones.Instance.IsAccessibleAtNextMilestone(ingredient.goods)) {
Expand Down Expand Up @@ -113,7 +113,7 @@ public override void Compute(Project project, ErrorCollector warnings) {
}

// TODO incorporate fuel selection. Now just select fuel if it only uses 1 fuel
Goods singleUsedFuel = null;
Goods? singleUsedFuel = null;
float singleUsedFuelAmount = 0f;
float minEmissions = 100f;
int minSize = 15;
Expand Down Expand Up @@ -386,7 +386,7 @@ public static float GetBuildingHours(Recipe recipe, float flow) {
return recipe.time * flow * (1000f / 3600f);
}

public string GetItemAmount(Goods goods) {
public string? GetItemAmount(Goods goods) {
float itemFlow = flow[goods];
if (itemFlow <= 1f) {
return null;
Expand Down
Loading

0 comments on commit 4860726

Please sign in to comment.