提交 c0e9a402 编写于 作者: J Jason Malinowski

Add nullable API annotations to Project/ProjectInfo and friends

上级 da2ad47c
......@@ -77,7 +77,7 @@ public override Solution UpgradeProject(Project project, string newVersion)
if (IsUpgrade(project, newVersion))
{
Contract.ThrowIfFalse(LanguageVersionFacts.TryParse(newVersion, out var parsedNewVersion));
var parseOptions = (CSharpParseOptions)project.ParseOptions;
var parseOptions = (CSharpParseOptions)project.ParseOptions!;
return project.Solution.WithProjectParseOptions(project.Id, parseOptions.WithLanguageVersion(parsedNewVersion));
}
......@@ -92,7 +92,7 @@ public override bool IsUpgrade(Project project, string newVersion)
{
Contract.ThrowIfFalse(LanguageVersionFacts.TryParse(newVersion, out var parsedNewVersion));
var parseOptions = (CSharpParseOptions)project.ParseOptions;
var parseOptions = (CSharpParseOptions)project.ParseOptions!;
var mappedVersion = parsedNewVersion.MapSpecifiedToEffectiveVersion();
var workspace = project.Solution.Workspace;
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#nullable enable
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
......@@ -11,7 +13,7 @@ internal static class ImmutableArrayExtensions
internal static bool Contains<T>(this ImmutableArray<T> items, T item, IEqualityComparer<T> equalityComparer)
=> items.IndexOf(item, 0, equalityComparer) >= 0;
internal static ImmutableArray<T> ToImmutableArrayOrEmpty<T>(this T[] items)
internal static ImmutableArray<T> ToImmutableArrayOrEmpty<T>(this T[]? items)
{
if (items == null)
{
......@@ -21,7 +23,7 @@ internal static ImmutableArray<T> ToImmutableArrayOrEmpty<T>(this T[] items)
return ImmutableArray.Create<T>(items);
}
internal static ImmutableArray<T> ToImmutableArrayOrEmpty<T>(this IEnumerable<T> items)
internal static ImmutableArray<T> ToImmutableArrayOrEmpty<T>(this IEnumerable<T>? items)
{
if (items == null)
{
......@@ -39,7 +41,7 @@ internal static ImmutableArray<T> ToImmutableArrayOrEmpty<T>(this IEnumerable<T>
internal static ImmutableArray<T> ToImmutableArrayOrEmpty<T>(this ImmutableArray<T> items)
=> items.IsDefault ? ImmutableArray<T>.Empty : items;
internal static IReadOnlyList<T> ToImmutableReadOnlyListOrEmpty<T>(this IEnumerable<T> items)
internal static IReadOnlyList<T> ToImmutableReadOnlyListOrEmpty<T>(this IEnumerable<T>? items)
{
if (items is ImmutableArray<T> array && !array.IsDefault)
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#nullable enable
using System.Diagnostics.CodeAnalysis;
namespace Microsoft.CodeAnalysis.Host
{
internal static class Extensions
{
public static bool CanApplyChange(this TextDocument document)
public static bool CanApplyChange([NotNullWhen(returnValue: true)] this TextDocument? document)
{
return document?.State.CanApplyChange() ?? false;
}
public static bool CanApplyChange(this TextDocumentState document)
public static bool CanApplyChange([NotNullWhen(returnValue: true)] this TextDocumentState? document)
{
return document?.Services.GetService<IDocumentOperationService>().CanApplyChange ?? false;
}
public static bool SupportsDiagnostics(this TextDocument document)
public static bool SupportsDiagnostics([NotNullWhen(returnValue: true)] this TextDocument? document)
{
return document?.State.SupportsDiagnostics() ?? false;
}
public static bool SupportsDiagnostics(this TextDocumentState document)
public static bool SupportsDiagnostics([NotNullWhen(returnValue: true)] this TextDocumentState? document)
{
return document?.Services.GetService<IDocumentOperationService>().SupportDiagnostics ?? false;
}
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics;
......@@ -13,14 +15,14 @@ namespace Microsoft.CodeAnalysis
[DebuggerDisplay("{GetDebuggerDisplay(),nq}")]
public sealed class ProjectId : IEquatable<ProjectId>, IObjectWritable
{
private readonly string _debugName;
private readonly string? _debugName;
/// <summary>
/// The system generated unique id.
/// </summary>
public Guid Id { get; }
private ProjectId(Guid guid, string debugName)
private ProjectId(Guid guid, string? debugName)
{
this.Id = guid;
_debugName = debugName;
......@@ -30,12 +32,12 @@ private ProjectId(Guid guid, string debugName)
/// Create a new ProjectId instance.
/// </summary>
/// <param name="debugName">An optional name to make this id easier to recognize while debugging.</param>
public static ProjectId CreateNewId(string debugName = null)
public static ProjectId CreateNewId(string? debugName = null)
{
return new ProjectId(Guid.NewGuid(), debugName);
}
public static ProjectId CreateFromSerialized(Guid id, string debugName = null)
public static ProjectId CreateFromSerialized(Guid id, string? debugName = null)
{
if (id == Guid.Empty)
{
......@@ -45,7 +47,7 @@ public static ProjectId CreateFromSerialized(Guid id, string debugName = null)
return new ProjectId(id, debugName);
}
internal string DebugName => _debugName;
internal string? DebugName => _debugName;
private string GetDebuggerDisplay()
{
......@@ -57,24 +59,24 @@ public override string ToString()
return GetDebuggerDisplay();
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return this.Equals(obj as ProjectId);
}
public bool Equals(ProjectId other)
public bool Equals(ProjectId? other)
{
return
!ReferenceEquals(other, null) &&
this.Id == other.Id;
}
public static bool operator ==(ProjectId left, ProjectId right)
public static bool operator ==(ProjectId? left, ProjectId? right)
{
return EqualityComparer<ProjectId>.Default.Equals(left, right);
return EqualityComparer<ProjectId?>.Default.Equals(left, right);
}
public static bool operator !=(ProjectId left, ProjectId right)
public static bool operator !=(ProjectId? left, ProjectId? right)
{
return !(left == right);
}
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics;
......@@ -46,17 +48,17 @@ public sealed class ProjectInfo
/// <summary>
/// The path to the project file or null if there is no project file.
/// </summary>
public string FilePath => Attributes.FilePath;
public string? FilePath => Attributes.FilePath;
/// <summary>
/// The path to the output file (module or assembly).
/// </summary>
public string OutputFilePath => Attributes.OutputFilePath;
public string? OutputFilePath => Attributes.OutputFilePath;
/// <summary>
/// The path to the reference assembly output file.
/// </summary>
public string OutputRefFilePath => Attributes.OutputRefFilePath;
public string? OutputRefFilePath => Attributes.OutputRefFilePath;
/// <summary>
/// The default namespace of the project ("" if not defined, which means global namespace),
......@@ -69,7 +71,7 @@ public sealed class ProjectInfo
/// In the future, we might consider officially exposing "default namespace" for VB project
/// (e.g. through a "defaultnamespace" msbuild property)
/// </remarks>
internal string DefaultNamespace => Attributes.DefaultNamespace;
internal string? DefaultNamespace => Attributes.DefaultNamespace;
/// <summary>
/// True if this is a submission project for interactive sessions.
......@@ -86,12 +88,12 @@ public sealed class ProjectInfo
/// <summary>
/// The initial compilation options for the project, or null if the default options should be used.
/// </summary>
public CompilationOptions CompilationOptions { get; }
public CompilationOptions? CompilationOptions { get; }
/// <summary>
/// The initial parse options for the source code documents in this project, or null if the default options should be used.
/// </summary>
public ParseOptions ParseOptions { get; }
public ParseOptions? ParseOptions { get; }
/// <summary>
/// The list of source documents initially associated with the project.
......@@ -126,19 +128,19 @@ public sealed class ProjectInfo
/// <summary>
/// Type of the host object.
/// </summary>
public Type HostObjectType { get; }
public Type? HostObjectType { get; }
private ProjectInfo(
ProjectAttributes attributes,
CompilationOptions compilationOptions,
ParseOptions parseOptions,
IEnumerable<DocumentInfo> documents,
IEnumerable<ProjectReference> projectReferences,
IEnumerable<MetadataReference> metadataReferences,
IEnumerable<AnalyzerReference> analyzerReferences,
IEnumerable<DocumentInfo> additionalDocuments,
IEnumerable<DocumentInfo> analyzerConfigDocuments,
Type hostObjectType)
CompilationOptions? compilationOptions,
ParseOptions? parseOptions,
IEnumerable<DocumentInfo>? documents,
IEnumerable<ProjectReference>? projectReferences,
IEnumerable<MetadataReference>? metadataReferences,
IEnumerable<AnalyzerReference>? analyzerReferences,
IEnumerable<DocumentInfo>? additionalDocuments,
IEnumerable<DocumentInfo>? analyzerConfigDocuments,
Type? hostObjectType)
{
Attributes = attributes;
CompilationOptions = compilationOptions;
......@@ -161,20 +163,20 @@ public sealed class ProjectInfo
string name,
string assemblyName,
string language,
string filePath,
string outputFilePath,
string outputRefFilePath,
string defaultNamespace,
CompilationOptions compilationOptions,
ParseOptions parseOptions,
IEnumerable<DocumentInfo> documents,
IEnumerable<ProjectReference> projectReferences,
IEnumerable<MetadataReference> metadataReferences,
IEnumerable<AnalyzerReference> analyzerReferences,
IEnumerable<DocumentInfo> additionalDocuments,
IEnumerable<DocumentInfo> analyzerConfigDocuments,
string? filePath,
string? outputFilePath,
string? outputRefFilePath,
string? defaultNamespace,
CompilationOptions? compilationOptions,
ParseOptions? parseOptions,
IEnumerable<DocumentInfo>? documents,
IEnumerable<ProjectReference>? projectReferences,
IEnumerable<MetadataReference>? metadataReferences,
IEnumerable<AnalyzerReference>? analyzerReferences,
IEnumerable<DocumentInfo>? additionalDocuments,
IEnumerable<DocumentInfo>? analyzerConfigDocuments,
bool isSubmission,
Type hostObjectType,
Type? hostObjectType,
bool hasAllInformation)
{
return new ProjectInfo(
......@@ -211,17 +213,17 @@ public sealed class ProjectInfo
string name,
string assemblyName,
string language,
string filePath,
string outputFilePath,
CompilationOptions compilationOptions,
ParseOptions parseOptions,
IEnumerable<DocumentInfo> documents,
IEnumerable<ProjectReference> projectReferences,
IEnumerable<MetadataReference> metadataReferences,
IEnumerable<AnalyzerReference> analyzerReferences,
IEnumerable<DocumentInfo> additionalDocuments,
string? filePath,
string? outputFilePath,
CompilationOptions? compilationOptions,
ParseOptions? parseOptions,
IEnumerable<DocumentInfo>? documents,
IEnumerable<ProjectReference>? projectReferences,
IEnumerable<MetadataReference>? metadataReferences,
IEnumerable<AnalyzerReference>? analyzerReferences,
IEnumerable<DocumentInfo>? additionalDocuments,
bool isSubmission,
Type hostObjectType)
Type? hostObjectType)
{
return Create(
id, version, name, assemblyName, language,
......@@ -239,18 +241,18 @@ public sealed class ProjectInfo
string name,
string assemblyName,
string language,
string filePath = null,
string outputFilePath = null,
CompilationOptions compilationOptions = null,
ParseOptions parseOptions = null,
IEnumerable<DocumentInfo> documents = null,
IEnumerable<ProjectReference> projectReferences = null,
IEnumerable<MetadataReference> metadataReferences = null,
IEnumerable<AnalyzerReference> analyzerReferences = null,
IEnumerable<DocumentInfo> additionalDocuments = null,
string? filePath = null,
string? outputFilePath = null,
CompilationOptions? compilationOptions = null,
ParseOptions? parseOptions = null,
IEnumerable<DocumentInfo>? documents = null,
IEnumerable<ProjectReference>? projectReferences = null,
IEnumerable<MetadataReference>? metadataReferences = null,
IEnumerable<AnalyzerReference>? analyzerReferences = null,
IEnumerable<DocumentInfo>? additionalDocuments = null,
bool isSubmission = false,
Type hostObjectType = null,
string outputRefFilePath = null)
Type? hostObjectType = null,
string? outputRefFilePath = null)
{
return Create(
id, version, name, assemblyName, language,
......@@ -260,16 +262,16 @@ public sealed class ProjectInfo
}
private ProjectInfo With(
ProjectAttributes attributes = null,
CompilationOptions compilationOptions = null,
ParseOptions parseOptions = null,
IEnumerable<DocumentInfo> documents = null,
IEnumerable<ProjectReference> projectReferences = null,
IEnumerable<MetadataReference> metadataReferences = null,
IEnumerable<AnalyzerReference> analyzerReferences = null,
IEnumerable<DocumentInfo> additionalDocuments = null,
IEnumerable<DocumentInfo> analyzerConfigDocuments = null,
Optional<Type> hostObjectType = default)
ProjectAttributes? attributes = null,
CompilationOptions? compilationOptions = null,
ParseOptions? parseOptions = null,
IEnumerable<DocumentInfo>? documents = null,
IEnumerable<ProjectReference>? projectReferences = null,
IEnumerable<MetadataReference>? metadataReferences = null,
IEnumerable<AnalyzerReference>? analyzerReferences = null,
IEnumerable<DocumentInfo>? additionalDocuments = null,
IEnumerable<DocumentInfo>? analyzerConfigDocuments = null,
Optional<Type?> hostObjectType = default)
{
var newAttributes = attributes ?? Attributes;
var newCompilationOptions = compilationOptions ?? CompilationOptions;
......@@ -309,17 +311,17 @@ public sealed class ProjectInfo
newHostObjectType);
}
public ProjectInfo WithDocuments(IEnumerable<DocumentInfo> documents)
public ProjectInfo WithDocuments(IEnumerable<DocumentInfo>? documents)
{
return With(documents: documents.ToImmutableReadOnlyListOrEmpty());
}
public ProjectInfo WithAdditionalDocuments(IEnumerable<DocumentInfo> additionalDocuments)
public ProjectInfo WithAdditionalDocuments(IEnumerable<DocumentInfo>? additionalDocuments)
{
return With(additionalDocuments: additionalDocuments.ToImmutableReadOnlyListOrEmpty());
}
public ProjectInfo WithAnalyzerConfigDocuments(IEnumerable<DocumentInfo> analyzerConfigDocuments)
public ProjectInfo WithAnalyzerConfigDocuments(IEnumerable<DocumentInfo>? analyzerConfigDocuments)
{
return With(analyzerConfigDocuments: analyzerConfigDocuments.ToImmutableReadOnlyListOrEmpty());
}
......@@ -334,7 +336,7 @@ public ProjectInfo WithName(string name)
return With(attributes: Attributes.With(name: name));
}
public ProjectInfo WithFilePath(string filePath)
public ProjectInfo WithFilePath(string? filePath)
{
return With(attributes: Attributes.With(filePath: filePath));
}
......@@ -344,42 +346,44 @@ public ProjectInfo WithAssemblyName(string assemblyName)
return With(attributes: Attributes.With(assemblyName: assemblyName));
}
public ProjectInfo WithOutputFilePath(string outputFilePath)
public ProjectInfo WithOutputFilePath(string? outputFilePath)
{
return With(attributes: Attributes.With(outputPath: outputFilePath));
}
public ProjectInfo WithOutputRefFilePath(string outputRefFilePath)
public ProjectInfo WithOutputRefFilePath(string? outputRefFilePath)
{
return With(attributes: Attributes.With(outputRefPath: outputRefFilePath));
}
public ProjectInfo WithDefaultNamespace(string defaultNamespace)
public ProjectInfo WithDefaultNamespace(string? defaultNamespace)
{
return With(attributes: Attributes.With(defaultNamespace: defaultNamespace));
}
public ProjectInfo WithCompilationOptions(CompilationOptions compilationOptions)
public ProjectInfo WithCompilationOptions(CompilationOptions? compilationOptions)
{
// The With method here doesn't correctly handle the null value, tracked by https://github.com/dotnet/roslyn/issues/37880
return With(compilationOptions: compilationOptions);
}
public ProjectInfo WithParseOptions(ParseOptions parseOptions)
public ProjectInfo WithParseOptions(ParseOptions? parseOptions)
{
// The With method here doesn't correctly handle the null value, tracked by https://github.com/dotnet/roslyn/issues/37880
return With(parseOptions: parseOptions);
}
public ProjectInfo WithProjectReferences(IEnumerable<ProjectReference> projectReferences)
public ProjectInfo WithProjectReferences(IEnumerable<ProjectReference>? projectReferences)
{
return With(projectReferences: projectReferences.ToImmutableReadOnlyListOrEmpty());
}
public ProjectInfo WithMetadataReferences(IEnumerable<MetadataReference> metadataReferences)
public ProjectInfo WithMetadataReferences(IEnumerable<MetadataReference>? metadataReferences)
{
return With(metadataReferences: metadataReferences.ToImmutableReadOnlyListOrEmpty());
}
public ProjectInfo WithAnalyzerReferences(IEnumerable<AnalyzerReference> analyzerReferences)
public ProjectInfo WithAnalyzerReferences(IEnumerable<AnalyzerReference>? analyzerReferences)
{
return With(analyzerReferences: analyzerReferences.ToImmutableReadOnlyListOrEmpty());
}
......@@ -428,22 +432,22 @@ internal class ProjectAttributes : IChecksummedObject, IObjectWritable
/// <summary>
/// The path to the project file or null if there is no project file.
/// </summary>
public string FilePath { get; }
public string? FilePath { get; }
/// <summary>
/// The path to the output file (module or assembly).
/// </summary>
public string OutputFilePath { get; }
public string? OutputFilePath { get; }
/// <summary>
/// The path to the reference assembly output file.
/// </summary>
public string OutputRefFilePath { get; }
public string? OutputRefFilePath { get; }
/// <summary>
/// The default namespace of the project.
/// </summary>
public string DefaultNamespace { get; }
public string? DefaultNamespace { get; }
/// <summary>
/// True if this is a submission project for interactive sessions.
......@@ -463,10 +467,10 @@ internal class ProjectAttributes : IChecksummedObject, IObjectWritable
string name,
string assemblyName,
string language,
string filePath,
string outputFilePath,
string outputRefFilePath,
string defaultNamespace,
string? filePath,
string? outputFilePath,
string? outputRefFilePath,
string? defaultNamespace,
bool isSubmission,
bool hasAllInformation)
{
......@@ -486,13 +490,13 @@ internal class ProjectAttributes : IChecksummedObject, IObjectWritable
public ProjectAttributes With(
VersionStamp? version = default,
string name = null,
string assemblyName = null,
string language = null,
Optional<string> filePath = default,
Optional<string> outputPath = default,
Optional<string> outputRefPath = default,
Optional<string> defaultNamespace = default,
string? name = null,
string? assemblyName = null,
string? language = null,
Optional<string?> filePath = default,
Optional<string?> outputPath = default,
Optional<string?> outputRefPath = default,
Optional<string?> defaultNamespace = default,
Optional<bool> isSubmission = default,
Optional<bool> hasAllInformation = default)
{
......@@ -576,7 +580,7 @@ public static ProjectAttributes ReadFrom(ObjectReader reader)
return new ProjectAttributes(projectId, VersionStamp.Create(), name, assemblyName, language, filePath, outputFilePath, outputRefFilePath, defaultNamespace, isSubmission, hasAllInformation);
}
private Checksum _lazyChecksum;
private Checksum? _lazyChecksum;
Checksum IChecksummedObject.Checksum
{
get
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
......@@ -53,7 +57,7 @@ internal partial class ProjectState
private readonly ValueSource<AnalyzerConfigSet> _lazyAnalyzerConfigSet;
// this will be initialized lazily.
private AnalyzerOptions _analyzerOptionsDoNotAccessDirectly;
private AnalyzerOptions? _analyzerOptionsDoNotAccessDirectly;
private ProjectState(
ProjectInfo projectInfo,
......@@ -233,7 +237,7 @@ private static async Task<VersionStamp> ComputeLatestDocumentTopLevelChangeVersi
return latestVersion;
}
internal DocumentState CreateDocument(DocumentInfo documentInfo, ParseOptions parseOptions)
internal DocumentState CreateDocument(DocumentInfo documentInfo, ParseOptions? parseOptions)
{
var doc = new DocumentState(documentInfo, parseOptions, _lazyAnalyzerConfigSet, _languageServices, _solutionServices);
......@@ -290,7 +294,7 @@ public WorkspaceAnalyzerConfigOptions(AnalyzerConfigOptionsResult analyzerConfig
_analyzerOptions = analyzerConfigOptions.AnalyzerOptions;
}
public override bool TryGetValue(string key, out string value) => _analyzerOptions.TryGetValue(key, out value);
public override bool TryGetValue(string key, [NotNullWhen(returnValue: true)] out string? value) => _analyzerOptions.TryGetValue(key, out value);
}
}
......@@ -334,16 +338,16 @@ public async Task<VersionStamp> GetSemanticVersionAsync(CancellationToken cancel
public ProjectId Id => this.ProjectInfo.Id;
[DebuggerBrowsable(DebuggerBrowsableState.Collapsed)]
public string FilePath => this.ProjectInfo.FilePath;
public string? FilePath => this.ProjectInfo.FilePath;
[DebuggerBrowsable(DebuggerBrowsableState.Collapsed)]
public string OutputFilePath => this.ProjectInfo.OutputFilePath;
public string? OutputFilePath => this.ProjectInfo.OutputFilePath;
[DebuggerBrowsable(DebuggerBrowsableState.Collapsed)]
public string OutputRefFilePath => this.ProjectInfo.OutputRefFilePath;
public string? OutputRefFilePath => this.ProjectInfo.OutputRefFilePath;
[DebuggerBrowsable(DebuggerBrowsableState.Collapsed)]
public string DefaultNamespace => this.ProjectInfo.DefaultNamespace;
public string? DefaultNamespace => this.ProjectInfo.DefaultNamespace;
[DebuggerBrowsable(DebuggerBrowsableState.Collapsed)]
public HostLanguageServices LanguageServices => _languageServices;
......@@ -358,7 +362,7 @@ public async Task<VersionStamp> GetSemanticVersionAsync(CancellationToken cancel
public bool IsSubmission => this.ProjectInfo.IsSubmission;
[DebuggerBrowsable(DebuggerBrowsableState.Collapsed)]
public Type HostObjectType => this.ProjectInfo.HostObjectType;
public Type? HostObjectType => this.ProjectInfo.HostObjectType;
[DebuggerBrowsable(DebuggerBrowsableState.Collapsed)]
public bool SupportsCompilation => this.LanguageServices.GetService<ICompilationFactoryService>() != null;
......@@ -373,10 +377,10 @@ public async Task<VersionStamp> GetSemanticVersionAsync(CancellationToken cancel
public string AssemblyName => this.ProjectInfo.AssemblyName;
[DebuggerBrowsable(DebuggerBrowsableState.Collapsed)]
public CompilationOptions CompilationOptions => this.ProjectInfo.CompilationOptions;
public CompilationOptions? CompilationOptions => this.ProjectInfo.CompilationOptions;
[DebuggerBrowsable(DebuggerBrowsableState.Collapsed)]
public ParseOptions ParseOptions => this.ProjectInfo.ParseOptions;
public ParseOptions? ParseOptions => this.ProjectInfo.ParseOptions;
[DebuggerBrowsable(DebuggerBrowsableState.Collapsed)]
public IReadOnlyList<MetadataReference> MetadataReferences => this.ProjectInfo.MetadataReferences;
......@@ -394,7 +398,7 @@ public async Task<VersionStamp> GetSemanticVersionAsync(CancellationToken cancel
public bool HasDocuments => _documentIds.Count > 0;
[DebuggerBrowsable(DebuggerBrowsableState.Collapsed)]
public IEnumerable<DocumentState> OrderedDocumentStates => this.DocumentIds.Select(GetDocumentState);
public IEnumerable<DocumentState> OrderedDocumentStates => this.DocumentIds.Select(GetDocumentState)!;
[DebuggerBrowsable(DebuggerBrowsableState.Collapsed)]
public IReadOnlyList<DocumentId> DocumentIds => _documentIds;
......@@ -431,34 +435,34 @@ public bool ContainsAnalyzerConfigDocument(DocumentId documentId)
return _analyzerConfigDocumentStates.ContainsKey(documentId);
}
public DocumentState GetDocumentState(DocumentId documentId)
public DocumentState? GetDocumentState(DocumentId documentId)
{
_documentStates.TryGetValue(documentId, out var state);
return state;
}
public TextDocumentState GetAdditionalDocumentState(DocumentId documentId)
public TextDocumentState? GetAdditionalDocumentState(DocumentId documentId)
{
_additionalDocumentStates.TryGetValue(documentId, out var state);
return state;
}
public AnalyzerConfigDocumentState GetAnalyzerConfigDocumentState(DocumentId documentId)
public AnalyzerConfigDocumentState? GetAnalyzerConfigDocumentState(DocumentId documentId)
{
_analyzerConfigDocumentStates.TryGetValue(documentId, out var state);
return state;
}
private ProjectState With(
ProjectInfo projectInfo = null,
ImmutableList<DocumentId> documentIds = default,
ImmutableList<DocumentId> additionalDocumentIds = default,
ImmutableSortedDictionary<DocumentId, DocumentState> documentStates = null,
ImmutableSortedDictionary<DocumentId, TextDocumentState> additionalDocumentStates = null,
ImmutableSortedDictionary<DocumentId, AnalyzerConfigDocumentState> analyzerConfigDocumentStates = null,
AsyncLazy<VersionStamp> latestDocumentVersion = null,
AsyncLazy<VersionStamp> latestDocumentTopLevelChangeVersion = null,
ValueSource<AnalyzerConfigSet> analyzerConfigSet = null)
ProjectInfo? projectInfo = null,
ImmutableList<DocumentId>? documentIds = null,
ImmutableList<DocumentId>? additionalDocumentIds = null,
ImmutableSortedDictionary<DocumentId, DocumentState>? documentStates = null,
ImmutableSortedDictionary<DocumentId, TextDocumentState>? additionalDocumentStates = null,
ImmutableSortedDictionary<DocumentId, AnalyzerConfigDocumentState>? analyzerConfigDocumentStates = null,
AsyncLazy<VersionStamp>? latestDocumentVersion = null,
AsyncLazy<VersionStamp>? latestDocumentTopLevelChangeVersion = null,
ValueSource<AnalyzerConfigSet>? analyzerConfigSet = null)
{
return new ProjectState(
projectInfo ?? _projectInfo,
......@@ -484,7 +488,7 @@ public ProjectState UpdateName(string name)
return this.With(projectInfo: this.ProjectInfo.WithName(name).WithVersion(this.Version.GetNewerVersion()));
}
public ProjectState UpdateFilePath(string filePath)
public ProjectState UpdateFilePath(string? filePath)
{
if (filePath == this.FilePath)
{
......@@ -504,7 +508,7 @@ public ProjectState UpdateAssemblyName(string assemblyName)
return this.With(projectInfo: this.ProjectInfo.WithAssemblyName(assemblyName).WithVersion(this.Version.GetNewerVersion()));
}
public ProjectState UpdateOutputFilePath(string outputFilePath)
public ProjectState UpdateOutputFilePath(string? outputFilePath)
{
if (outputFilePath == this.OutputFilePath)
{
......@@ -514,7 +518,7 @@ public ProjectState UpdateOutputFilePath(string outputFilePath)
return this.With(projectInfo: this.ProjectInfo.WithOutputFilePath(outputFilePath).WithVersion(this.Version.GetNewerVersion()));
}
public ProjectState UpdateOutputRefFilePath(string outputRefFilePath)
public ProjectState UpdateOutputRefFilePath(string? outputRefFilePath)
{
if (outputRefFilePath == this.OutputRefFilePath)
{
......@@ -524,7 +528,7 @@ public ProjectState UpdateOutputRefFilePath(string outputRefFilePath)
return this.With(projectInfo: this.ProjectInfo.WithOutputRefFilePath(outputRefFilePath).WithVersion(this.Version.GetNewerVersion()));
}
public ProjectState UpdateDefaultNamespace(string defaultNamespace)
public ProjectState UpdateDefaultNamespace(string? defaultNamespace)
{
if (defaultNamespace == this.DefaultNamespace)
{
......@@ -554,9 +558,8 @@ public ProjectState UpdateParseOptions(ParseOptions options)
// update parse options for all documents too
var docMap = _documentStates;
foreach (var (docId, _) in _documentStates)
foreach (var (docId, oldDocState) in _documentStates)
{
var oldDocState = this.GetDocumentState(docId);
var newDocState = oldDocState.UpdateParseOptions(options);
docMap = docMap.SetItem(docId, newDocState);
}
......@@ -715,9 +718,8 @@ private ProjectState CreateNewStateForChangedAnalyzerConfigDocuments(ImmutableSo
// a specific syntax tree; therefore we must update all our syntax trees.
var docMap = _documentStates;
foreach (var (docId, _) in _documentStates)
foreach (var (docId, oldDocState) in _documentStates)
{
var oldDocState = this.GetDocumentState(docId);
var newDocState = oldDocState.UpdateAnalyzerConfigSet(newAnalyzerConfigSet);
docMap = docMap.SetItem(docId, newDocState);
}
......@@ -770,7 +772,7 @@ public ProjectState UpdateDocument(DocumentState newDocument, bool textChanged,
{
Debug.Assert(this.ContainsDocument(newDocument.Id));
var oldDocument = this.GetDocumentState(newDocument.Id);
var oldDocument = this.GetDocumentState(newDocument.Id)!;
if (oldDocument == newDocument)
{
return this;
......@@ -791,7 +793,7 @@ public ProjectState UpdateAdditionalDocument(TextDocumentState newDocument, bool
{
Debug.Assert(this.ContainsAdditionalDocument(newDocument.Id));
var oldDocument = this.GetAdditionalDocumentState(newDocument.Id);
var oldDocument = this.GetAdditionalDocumentState(newDocument.Id)!;
if (oldDocument == newDocument)
{
return this;
......
......@@ -109,7 +109,9 @@ internal Solution(Workspace workspace, SolutionInfo.SolutionAttributes solutionA
private static readonly Func<ProjectId, Solution, Project> s_createProjectFunction = CreateProject;
private static Project CreateProject(ProjectId projectId, Solution solution)
{
return new Project(solution, solution.State.GetProjectState(projectId));
var state = solution.State.GetProjectState(projectId);
Contract.ThrowIfNull(state);
return new Project(solution, state);
}
/// <summary>
......
......@@ -1233,12 +1233,12 @@ public SolutionState RemoveAnalyzerConfigDocument(DocumentId documentId)
var oldProject = this.GetProjectState(documentId.ProjectId)!;
var newProject = oldProject.RemoveAnalyzerConfigDocument(documentId);
var documentStates = SpecializedCollections.SingletonEnumerable(oldProject.GetAnalyzerConfigDocumentState(documentId));
var removedDocumentStates = SpecializedCollections.SingletonEnumerable(oldProject.GetAnalyzerConfigDocumentState(documentId)!);
return this.ForkProject(
newProject,
new CompilationTranslationAction.ReplaceAllSyntaxTreesAction(newProject),
newFilePathToDocumentIdsMap: CreateFilePathToDocumentIdsMapWithRemovedDocuments(documentStates));
newFilePathToDocumentIdsMap: CreateFilePathToDocumentIdsMapWithRemovedDocuments(removedDocumentStates));
}
/// <summary>
......@@ -1251,12 +1251,12 @@ public SolutionState RemoveDocument(DocumentId documentId)
var oldProject = this.GetProjectState(documentId.ProjectId)!;
var oldDocument = oldProject.GetDocumentState(documentId);
var newProject = oldProject.RemoveDocument(documentId);
var documentStates = SpecializedCollections.SingletonEnumerable(oldProject.GetDocumentState(documentId));
var removedDocumentStates = SpecializedCollections.SingletonEnumerable(oldProject.GetDocumentState(documentId)!);
return this.ForkProject(
newProject,
new CompilationTranslationAction.RemoveDocumentAction(oldDocument),
newFilePathToDocumentIdsMap: CreateFilePathToDocumentIdsMapWithRemovedDocuments(documentStates));
newFilePathToDocumentIdsMap: CreateFilePathToDocumentIdsMapWithRemovedDocuments(removedDocumentStates));
}
/// <summary>
......
......@@ -1024,12 +1024,12 @@ private static Solution UpdateReferencesAfterAdd(Solution solution)
{
if (!string.IsNullOrEmpty(p.OutputFilePath))
{
outputAssemblyToProjectIdMap[p.OutputFilePath] = p.Id;
outputAssemblyToProjectIdMap[p.OutputFilePath!] = p.Id;
}
if (!string.IsNullOrEmpty(p.OutputRefFilePath))
{
outputAssemblyToProjectIdMap[p.OutputRefFilePath] = p.Id;
outputAssemblyToProjectIdMap[p.OutputRefFilePath!] = p.Id;
}
}
......@@ -1185,10 +1185,13 @@ private void CheckAllowedSolutionChanges(SolutionChanges solutionChanges)
private void CheckAllowedProjectChanges(ProjectChanges projectChanges)
{
// It's OK to use the null-suppression operator when calling CanApplyCompilationOptionChange: if they were both null,
// we'd bail right away since they didn't change. Thus, at least one is non-null, and once you have a non-null CompilationOptions and ParseOptions
// you can't ever make it null again, and it'll be non-null as long as the language supported it in the first place.
if (projectChanges.OldProject.CompilationOptions != projectChanges.NewProject.CompilationOptions
&& !this.CanApplyChange(ApplyChangesKind.ChangeCompilationOptions)
&& !this.CanApplyCompilationOptionChange(
projectChanges.OldProject.CompilationOptions, projectChanges.NewProject.CompilationOptions, projectChanges.NewProject))
projectChanges.OldProject.CompilationOptions!, projectChanges.NewProject.CompilationOptions!, projectChanges.NewProject))
{
throw new NotSupportedException(WorkspacesResources.Changing_compilation_options_is_not_supported);
}
......@@ -1196,7 +1199,7 @@ private void CheckAllowedProjectChanges(ProjectChanges projectChanges)
if (projectChanges.OldProject.ParseOptions != projectChanges.NewProject.ParseOptions
&& !this.CanApplyChange(ApplyChangesKind.ChangeParseOptions)
&& !this.CanApplyParseOptionChange(
projectChanges.OldProject.ParseOptions, projectChanges.NewProject.ParseOptions, projectChanges.NewProject))
projectChanges.OldProject.ParseOptions!, projectChanges.NewProject.ParseOptions!, projectChanges.NewProject))
{
throw new NotSupportedException(WorkspacesResources.Changing_parse_options_is_not_supported);
}
......@@ -1212,7 +1215,7 @@ private void CheckAllowedProjectChanges(ProjectChanges projectChanges)
}
if (!this.CanApplyChange(ApplyChangesKind.ChangeDocumentInfo)
&& projectChanges.GetChangedDocuments().Any(id => projectChanges.NewProject.GetDocument(id).HasInfoChanged(projectChanges.OldProject.GetDocument(id))))
&& projectChanges.GetChangedDocuments().Any(id => projectChanges.NewProject.GetDocument(id)!.HasInfoChanged(projectChanges.OldProject.GetDocument(id))))
{
throw new NotSupportedException(WorkspacesResources.Changing_document_property_is_not_supported);
}
......@@ -1285,7 +1288,7 @@ private void CheckAllowedProjectChanges(ProjectChanges projectChanges)
foreach (var documentId in projectChanges.GetChangedDocuments())
{
var document = projectChanges.OldProject.GetDocumentState(documentId) ?? projectChanges.NewProject.GetDocumentState(documentId);
var document = projectChanges.OldProject.GetDocumentState(documentId) ?? projectChanges.NewProject.GetDocumentState(documentId)!;
if (!document.CanApplyChange())
{
throw new NotSupportedException(string.Format(WorkspacesResources.Changing_document_0_is_not_supported, document.FilePath ?? document.Name));
......@@ -1307,16 +1310,19 @@ public virtual bool CanApplyParseOptionChange(ParseOptions oldOptions, ParseOpti
/// </summary>
protected virtual void ApplyProjectChanges(ProjectChanges projectChanges)
{
// It's OK to use the null-suppression operator when calling ApplyCompilation/ParseOptionsChanged: the only change that is allowed
// is going from one non-null value to another which is blocked by the Project.WithCompilationOptions() API directly.
// changed compilation options
if (projectChanges.OldProject.CompilationOptions != projectChanges.NewProject.CompilationOptions)
{
this.ApplyCompilationOptionsChanged(projectChanges.ProjectId, projectChanges.NewProject.CompilationOptions);
this.ApplyCompilationOptionsChanged(projectChanges.ProjectId, projectChanges.NewProject.CompilationOptions!);
}
// changed parse options
if (projectChanges.OldProject.ParseOptions != projectChanges.NewProject.ParseOptions)
{
this.ApplyParseOptionsChanged(projectChanges.ProjectId, projectChanges.NewProject.ParseOptions);
this.ApplyParseOptionsChanged(projectChanges.ProjectId, projectChanges.NewProject.ParseOptions!);
}
// removed project references
......@@ -1376,7 +1382,7 @@ protected virtual void ApplyProjectChanges(ProjectChanges projectChanges)
// added documents
foreach (var documentId in projectChanges.GetAddedDocuments())
{
var document = projectChanges.NewProject.GetDocument(documentId);
var document = projectChanges.NewProject.GetDocument(documentId)!;
var text = document.GetTextSynchronously(CancellationToken.None);
var info = this.CreateDocumentInfoWithoutText(document);
this.ApplyDocumentAdded(info, text);
......@@ -1385,7 +1391,7 @@ protected virtual void ApplyProjectChanges(ProjectChanges projectChanges)
// added additional documents
foreach (var documentId in projectChanges.GetAddedAdditionalDocuments())
{
var document = projectChanges.NewProject.GetAdditionalDocument(documentId);
var document = projectChanges.NewProject.GetAdditionalDocument(documentId)!;
var text = document.GetTextSynchronously(CancellationToken.None);
var info = this.CreateDocumentInfoWithoutText(document);
this.ApplyAdditionalDocumentAdded(info, text);
......@@ -1394,7 +1400,7 @@ protected virtual void ApplyProjectChanges(ProjectChanges projectChanges)
// added analyzer config documents
foreach (var documentId in projectChanges.GetAddedAnalyzerConfigDocuments())
{
var document = projectChanges.NewProject.GetAnalyzerConfigDocument(documentId);
var document = projectChanges.NewProject.GetAnalyzerConfigDocument(documentId)!;
var text = document.GetTextSynchronously(CancellationToken.None);
var info = this.CreateDocumentInfoWithoutText(document);
this.ApplyAnalyzerConfigDocumentAdded(info, text);
......@@ -1409,8 +1415,8 @@ protected virtual void ApplyProjectChanges(ProjectChanges projectChanges)
// changed additional documents
foreach (var documentId in projectChanges.GetChangedAdditionalDocuments())
{
var oldDoc = projectChanges.OldProject.GetAdditionalDocument(documentId);
var newDoc = projectChanges.NewProject.GetAdditionalDocument(documentId);
var oldDoc = projectChanges.OldProject.GetAdditionalDocument(documentId)!;
var newDoc = projectChanges.NewProject.GetAdditionalDocument(documentId)!;
// We don't understand the text of additional documents and so we just replace the entire text.
var currentText = newDoc.GetTextSynchronously(CancellationToken.None); // needs wait
......@@ -1420,8 +1426,8 @@ protected virtual void ApplyProjectChanges(ProjectChanges projectChanges)
// changed analyzer config documents
foreach (var documentId in projectChanges.GetChangedAnalyzerConfigDocuments())
{
var oldDoc = projectChanges.OldProject.GetAnalyzerConfigDocument(documentId);
var newDoc = projectChanges.NewProject.GetAnalyzerConfigDocument(documentId);
var oldDoc = projectChanges.OldProject.GetAnalyzerConfigDocument(documentId)!;
var newDoc = projectChanges.NewProject.GetAnalyzerConfigDocument(documentId)!;
// We don't understand the text of analyzer config documents and so we just replace the entire text.
var currentText = newDoc.GetTextSynchronously(CancellationToken.None); // needs wait
......@@ -1432,8 +1438,8 @@ protected virtual void ApplyProjectChanges(ProjectChanges projectChanges)
private void ApplyChangedDocument(
ProjectChanges projectChanges, DocumentId documentId)
{
var oldDoc = projectChanges.OldProject.GetDocument(documentId);
var newDoc = projectChanges.NewProject.GetDocument(documentId);
var oldDoc = projectChanges.OldProject.GetDocument(documentId)!;
var newDoc = projectChanges.NewProject.GetDocument(documentId)!;
// update text if changed
if (newDoc.HasTextChanged(oldDoc))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册