Skip to content

Commit 522b084

Browse files
committed
turn on nullable analysis for this project
1 parent 91e1cbe commit 522b084

16 files changed

Lines changed: 209 additions & 58 deletions

src/CodeFormatter.cs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ public static async Task<WorkspaceFormatResult> FormatWorkspaceAsync(
8383
foreach (var changedDocumentId in projectChanges.GetChangedDocuments())
8484
{
8585
var changedDocument = solution.GetDocument(changedDocumentId);
86+
if (changedDocument?.FilePath is null)
87+
continue;
88+
8689
logger.LogInformation(Resources.Formatted_code_file_0, changedDocument.FilePath);
8790
filesFormatted++;
8891
}
@@ -98,7 +101,7 @@ public static async Task<WorkspaceFormatResult> FormatWorkspaceAsync(
98101

99102
if (exitCode == 0 && !string.IsNullOrWhiteSpace(reportPath))
100103
{
101-
var reportFilePath = GetReportFilePath(reportPath);
104+
var reportFilePath = GetReportFilePath(reportPath!); // IsNullOrEmpty is not annotated on .NET Core 2.1
102105
var reportFolderPath = Path.GetDirectoryName(reportFilePath);
103106

104107
if (!Directory.Exists(reportFolderPath))
@@ -141,7 +144,7 @@ private static string GetReportFilePath(string reportPath)
141144
}
142145
}
143146

144-
private static async Task<Workspace> OpenWorkspaceAsync(
147+
private static async Task<Workspace?> OpenWorkspaceAsync(
145148
string workspacePath,
146149
WorkspaceType workspaceType,
147150
Matcher fileMatcher,
@@ -159,7 +162,7 @@ private static async Task<Workspace> OpenWorkspaceAsync(
159162
return await OpenMSBuildWorkspaceAsync(workspacePath, workspaceType, logWorkspaceWarnings, logger, cancellationToken);
160163
}
161164

162-
private static async Task<Workspace> OpenMSBuildWorkspaceAsync(
165+
private static async Task<Workspace?> OpenMSBuildWorkspaceAsync(
163166
string solutionOrProjectPath,
164167
WorkspaceType workspaceType,
165168
bool logWorkspaceWarnings,
@@ -256,10 +259,13 @@ private static async Task<Solution> RunCodeFormattersAsync(
256259
var optionsApplier = new EditorConfigOptionsApplier();
257260

258261
var fileCount = 0;
259-
var getDocumentsAndOptions = new List<Task<(Document, OptionSet, ICodingConventionsSnapshot, bool)>>(solution.Projects.Sum(project => project.DocumentIds.Count));
262+
var getDocumentsAndOptions = new List<Task<(Document?, OptionSet?, ICodingConventionsSnapshot?, bool)>>(solution.Projects.Sum(project => project.DocumentIds.Count));
260263

261264
foreach (var project in solution.Projects)
262265
{
266+
if (project.FilePath is null)
267+
continue;
268+
263269
// If a project is used as a workspace, then ignore other referenced projects.
264270
if (!string.IsNullOrEmpty(projectPath) && !project.FilePath.Equals(projectPath, StringComparison.OrdinalIgnoreCase))
265271
{
@@ -289,7 +295,7 @@ private static async Task<Solution> RunCodeFormattersAsync(
289295
var formattableFiles = ImmutableArray.CreateBuilder<(DocumentId, OptionSet, ICodingConventionsSnapshot)>(documentsAndOptions.Length);
290296
foreach (var (document, options, codingConventions, hasEditorConfig) in documentsAndOptions)
291297
{
292-
if (document is null)
298+
if (document?.FilePath is null)
293299
{
294300
continue;
295301
}
@@ -313,7 +319,7 @@ private static async Task<Solution> RunCodeFormattersAsync(
313319
return (fileCount, formattableFiles.ToImmutableArray());
314320
}
315321

316-
private static async Task<(Document, OptionSet, ICodingConventionsSnapshot, bool)> GetDocumentAndOptions(
322+
private static async Task<(Document?, OptionSet?, ICodingConventionsSnapshot?, bool)> GetDocumentAndOptions(
317323
Project project,
318324
DocumentId documentId,
319325
Matcher fileMatcher,
@@ -323,7 +329,7 @@ private static async Task<Solution> RunCodeFormattersAsync(
323329
{
324330
var document = project.Solution.GetDocument(documentId);
325331

326-
if (await ShouldIgnoreDocument(document, fileMatcher, cancellationToken))
332+
if (document is null || await ShouldIgnoreDocument(document, fileMatcher, cancellationToken))
327333
{
328334
return (null, null, null, false);
329335
}

src/FormatOptions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ internal class FormatOptions
1313
public bool SaveFormattedFiles { get; }
1414
public bool ChangesAreErrors { get; }
1515
public Matcher FileMatcher { get; }
16-
public string ReportPath { get; }
16+
public string? ReportPath { get; }
1717

1818
public FormatOptions(
1919
string workspaceFilePath,
@@ -22,7 +22,7 @@ public FormatOptions(
2222
bool saveFormattedFiles,
2323
bool changesAreErrors,
2424
Matcher fileMatcher,
25-
string reportPath)
25+
string? reportPath)
2626
{
2727
WorkspaceFilePath = workspaceFilePath;
2828
WorkspaceType = workspaceType;
@@ -40,7 +40,7 @@ public void Deconstruct(
4040
out bool saveFormattedFiles,
4141
out bool changesAreErrors,
4242
out Matcher fileMatcher,
43-
out string reportPath)
43+
out string? reportPath)
4444
{
4545
workspaceFilePath = WorkspaceFilePath;
4646
workspaceType = WorkspaceType;

src/FormattedFile.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public class FormattedFile
88

99
public string FileName { get; }
1010

11-
public string FilePath { get; }
11+
public string? FilePath { get; }
1212

1313
public IEnumerable<FileChange> FileChanges { get; }
1414

src/Formatters/CharsetFormatter.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
22

3+
using System.Diagnostics.CodeAnalysis;
34
using System.IO;
45
using System.Linq;
56
using System.Text;
@@ -31,7 +32,7 @@ protected override Task<SourceText> FormatFileAsync(
3132
return Task.Run(() =>
3233
{
3334
if (!TryGetCharset(codingConventions, out var encoding)
34-
|| sourceText.Encoding.Equals(encoding)
35+
|| sourceText.Encoding?.Equals(encoding) == true
3536
|| IsEncodingEquivalent(sourceText, encoding))
3637
{
3738
return sourceText;
@@ -43,6 +44,11 @@ protected override Task<SourceText> FormatFileAsync(
4344

4445
private static bool IsEncodingEquivalent(SourceText sourceText, Encoding encoding)
4546
{
47+
if (sourceText.Encoding is null)
48+
{
49+
throw new System.Exception($"source text did not have an identifiable encoding");
50+
}
51+
4652
var text = sourceText.ToString();
4753
var originalBytes = GetEncodedBytes(text, sourceText.Encoding);
4854
var encodedBytes = GetEncodedBytes(text, encoding);
@@ -63,7 +69,7 @@ private static byte[] GetEncodedBytes(string text, Encoding encoding)
6369
}
6470
}
6571

66-
private static bool TryGetCharset(ICodingConventionsSnapshot codingConventions, out Encoding encoding)
72+
private static bool TryGetCharset(ICodingConventionsSnapshot codingConventions, [NotNullWhen(true)] out Encoding? encoding)
6773
{
6874
if (codingConventions.TryGetConventionValue("charset", out string charsetOption))
6975
{

src/Formatters/DocumentFormatter.cs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.
22

3+
using System;
34
using System.Collections.Generic;
45
using System.Collections.Immutable;
56
using System.IO;
@@ -49,18 +50,21 @@ protected abstract Task<SourceText> FormatFileAsync(
4950
/// <summary>
5051
/// Applies formatting and returns the changed <see cref="SourceText"/> for each <see cref="Document"/>.
5152
/// </summary>
52-
private ImmutableArray<(Document, Task<(SourceText originalText, SourceText formattedText)>)> FormatFiles(
53+
private ImmutableArray<(Document, Task<(SourceText originalText, SourceText? formattedText)>)> FormatFiles(
5354
Solution solution,
5455
ImmutableArray<(DocumentId, OptionSet, ICodingConventionsSnapshot)> formattableDocuments,
5556
FormatOptions formatOptions,
5657
ILogger logger,
5758
CancellationToken cancellationToken)
5859
{
59-
var formattedDocuments = ImmutableArray.CreateBuilder<(Document, Task<(SourceText originalText, SourceText formattedText)>)>(formattableDocuments.Length);
60+
var formattedDocuments = ImmutableArray.CreateBuilder<(Document, Task<(SourceText originalText, SourceText? formattedText)>)>(formattableDocuments.Length);
6061

6162
foreach (var (documentId, options, codingConventions) in formattableDocuments)
6263
{
6364
var document = solution.GetDocument(documentId);
65+
if (document is null)
66+
continue;
67+
6468
var formatTask = Task.Run(async () => await GetFormattedSourceTextAsync(document, options, codingConventions, formatOptions, logger, cancellationToken).ConfigureAwait(false), cancellationToken);
6569

6670
formattedDocuments.Add((document, formatTask));
@@ -72,7 +76,7 @@ protected abstract Task<SourceText> FormatFileAsync(
7276
/// <summary>
7377
/// Get formatted <see cref="SourceText"/> for a <see cref="Document"/>.
7478
/// </summary>
75-
private async Task<(SourceText originalText, SourceText formattedText)> GetFormattedSourceTextAsync(
79+
private async Task<(SourceText originalText, SourceText? formattedText)> GetFormattedSourceTextAsync(
7680
Document document,
7781
OptionSet options,
7882
ICodingConventionsSnapshot codingConventions,
@@ -83,7 +87,7 @@ protected abstract Task<SourceText> FormatFileAsync(
8387
var originalSourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
8488
var formattedSourceText = await FormatFileAsync(document, originalSourceText, options, codingConventions, formatOptions, logger, cancellationToken).ConfigureAwait(false);
8589

86-
return !formattedSourceText.ContentEquals(originalSourceText) || !formattedSourceText.Encoding.Equals(originalSourceText.Encoding)
90+
return !formattedSourceText.ContentEquals(originalSourceText) || !formattedSourceText.Encoding?.Equals(originalSourceText.Encoding) == true
8791
? (originalSourceText, formattedSourceText)
8892
: (originalSourceText, null);
8993
}
@@ -93,7 +97,7 @@ protected abstract Task<SourceText> FormatFileAsync(
9397
/// </summary>
9498
private async Task<Solution> ApplyFileChangesAsync(
9599
Solution solution,
96-
ImmutableArray<(Document, Task<(SourceText originalText, SourceText formattedText)>)> formattedDocuments,
100+
ImmutableArray<(Document, Task<(SourceText originalText, SourceText? formattedText)>)> formattedDocuments,
97101
FormatOptions formatOptions,
98102
ILogger logger,
99103
List<FormattedFile> formattedFiles,
@@ -108,6 +112,11 @@ private async Task<Solution> ApplyFileChangesAsync(
108112
return formattedSolution;
109113
}
110114

115+
if (document?.FilePath is null)
116+
{
117+
continue;
118+
}
119+
111120
var (originalText, formattedText) = await formatTask.ConfigureAwait(false);
112121
if (formattedText is null)
113122
{
@@ -128,6 +137,10 @@ private IEnumerable<FileChange> GetFileChanges(FormatOptions formatOptions, stri
128137
var fileChanges = new List<FileChange>();
129138
var workspaceFolder = Path.GetDirectoryName(workspacePath);
130139
var changes = formattedText.GetChangeRanges(originalText);
140+
if (workspaceFolder is null)
141+
{
142+
throw new Exception($"Unable to fine directory name for '{workspacePath}'");
143+
}
131144

132145
foreach (var change in changes)
133146
{

src/Formatters/EndOfLineFormatter.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
22

33
using System;
4+
using System.Diagnostics.CodeAnalysis;
45
using System.Threading;
56
using System.Threading.Tasks;
67
using Microsoft.CodeAnalysis.Options;
@@ -57,7 +58,7 @@ protected override Task<SourceText> FormatFileAsync(
5758
});
5859
}
5960

60-
public static bool TryGetEndOfLine(ICodingConventionsSnapshot codingConventions, out string endOfLine)
61+
public static bool TryGetEndOfLine(ICodingConventionsSnapshot codingConventions, [NotNullWhen(true)] out string? endOfLine)
6162
{
6263
if (codingConventions.TryGetConventionValue("end_of_line", out string endOfLineOption))
6364
{

src/MSBuild/LooseVersionAssemblyLoader.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public static void Register(string searchPath)
3535
};
3636
}
3737

38-
private static Assembly TryResolveAssemblyFromPaths(AssemblyLoadContext context, AssemblyName assemblyName, string searchPath)
38+
private static Assembly? TryResolveAssemblyFromPaths(AssemblyLoadContext context, AssemblyName assemblyName, string searchPath)
3939
{
4040
foreach (var cultureSubfolder in string.IsNullOrEmpty(assemblyName.CultureName)
4141
// If no culture is specified, attempt to load directly from
@@ -77,6 +77,10 @@ private static Assembly LoadAndCache(AssemblyLoadContext context, string fullPat
7777
{
7878
var assembly = context.LoadFromAssemblyPath(fullPath);
7979
var name = assembly.FullName;
80+
if (name is null)
81+
{
82+
throw new Exception($"Could not get name for assembly '{assembly}'");
83+
}
8084

8185
s_pathsToAssemblies[fullPath] = assembly;
8286
s_namesToAssemblies[name] = assembly;

src/MSBuild/MSBuildWorkspaceFinder.cs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ internal class MSBuildWorkspaceFinder
2222
/// <param name="searchDirectory">The base directory to search</param>
2323
/// <param name="workspacePath">A specific project or solution file to find</param>
2424
/// </summary>
25-
public static (bool isSolution, string workspacePath) FindWorkspace(string searchDirectory, string workspacePath = null)
25+
public static (bool isSolution, string workspacePath) FindWorkspace(string searchDirectory, string? workspacePath = null)
2626
{
2727
if (!string.IsNullOrEmpty(workspacePath))
2828
{
@@ -32,8 +32,8 @@ public static (bool isSolution, string workspacePath) FindWorkspace(string searc
3232
}
3333

3434
return Directory.Exists(workspacePath)
35-
? FindWorkspace(workspacePath)
36-
: FindFile(workspacePath);
35+
? FindWorkspace(workspacePath!) // IsNullOrEmpty is not annotated on .NET Core 2.1
36+
: FindFile(workspacePath!); // IsNullOrEmpty is not annotated on .NET Core 2.1
3737
}
3838

3939
var foundSolution = FindMatchingFile(searchDirectory, FindSolutionFiles, Resources.Multiple_MSBuild_solution_files_found_in_0_Specify_which_to_use_with_the_workspace_option);
@@ -43,14 +43,18 @@ public static (bool isSolution, string workspacePath) FindWorkspace(string searc
4343
{
4444
throw new FileNotFoundException(string.Format(Resources.Both_a_MSBuild_project_file_and_solution_file_found_in_0_Specify_which_to_use_with_the_workspace_option, searchDirectory));
4545
}
46-
else if (string.IsNullOrEmpty(foundSolution) && string.IsNullOrEmpty(foundProject))
46+
47+
if (!string.IsNullOrEmpty(foundSolution))
48+
{
49+
return (true, foundSolution!); // IsNullOrEmpty is not annotated on .NET Core 2.1
50+
}
51+
52+
if (!string.IsNullOrEmpty(foundProject))
4753
{
48-
throw new FileNotFoundException(string.Format(Resources.Could_not_find_a_MSBuild_project_or_solution_file_in_0_Specify_which_to_use_with_the_workspace_option, searchDirectory));
54+
return (false, foundProject!); // IsNullOrEmpty is not annotated on .NET Core 2.1
4955
}
5056

51-
return !string.IsNullOrEmpty(foundSolution)
52-
? (true, foundSolution)
53-
: (false, foundProject);
57+
throw new FileNotFoundException(string.Format(Resources.Could_not_find_a_MSBuild_project_or_solution_file_in_0_Specify_which_to_use_with_the_workspace_option, searchDirectory));
5458
}
5559

5660
private static (bool isSolution, string workspacePath) FindFile(string workspacePath)
@@ -82,7 +86,7 @@ private static (bool isSolution, string workspacePath) FindFile(string workspace
8286
private static IEnumerable<string> FindProjectFiles(string basePath) => Directory.EnumerateFileSystemEntries(basePath, "*.*proj", SearchOption.TopDirectoryOnly)
8387
.Where(f => !DnxProjectExtension.Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase));
8488

85-
private static string FindMatchingFile(string searchBase, Func<string, IEnumerable<string>> fileSelector, string multipleFilesFoundError)
89+
private static string? FindMatchingFile(string searchBase, Func<string, IEnumerable<string>> fileSelector, string multipleFilesFoundError)
8690
{
8791
if (!Directory.Exists(searchBase))
8892
{

0 commit comments

Comments
 (0)