Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
agocke committed May 20, 2020
1 parent c61052a commit 0d1b7bb
Showing 53 changed files with 716 additions and 496 deletions.
13 changes: 11 additions & 2 deletions src/Compilers/CSharp/Portable/Binder/Binder.cs
Original file line number Diff line number Diff line change
@@ -235,14 +235,17 @@ internal virtual Symbol? ContainingMemberOrLambda
/// </summary>
internal bool AreNullableAnnotationsEnabled(SyntaxTree syntaxTree, int position)
{
Syntax.NullableContextState context = ((CSharpSyntaxTree)syntaxTree).GetNullableContextState(position);
CSharpSyntaxTree csTree = (CSharpSyntaxTree)syntaxTree;
Syntax.NullableContextState context = csTree.GetNullableContextState(position);

return context.AnnotationsState switch
{
Syntax.NullableContextState.State.Enabled => true,
Syntax.NullableContextState.State.Disabled => false,
Syntax.NullableContextState.State.ExplicitlyRestored => GetGlobalAnnotationState(),
Syntax.NullableContextState.State.Unknown => AreNullableAnnotationsGloballyEnabled(),
Syntax.NullableContextState.State.Unknown =>
!csTree.IsGeneratedCode(this.Compilation.Options.SyntaxTreeOptionsProvider)
&& AreNullableAnnotationsGloballyEnabled(),
_ => throw ExceptionUtilities.UnexpectedValue(context.AnnotationsState)
};
}
@@ -253,6 +256,12 @@ internal bool AreNullableAnnotationsEnabled(SyntaxToken token)
return AreNullableAnnotationsEnabled(token.SyntaxTree, token.SpanStart);
}

internal bool IsGeneratedCode(SyntaxToken token)
{
var tree = (CSharpSyntaxTree)token.SyntaxTree!;
return tree.IsGeneratedCode(Compilation.Options.SyntaxTreeOptionsProvider);
}

internal virtual bool AreNullableAnnotationsGloballyEnabled()
{
RoslynDebug.Assert(Next is object);
6 changes: 5 additions & 1 deletion src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs
Original file line number Diff line number Diff line change
@@ -157,7 +157,11 @@ internal ImmutableArray<TypeParameterConstraintClause> BindTypeParameterConstrai
}
else
{
LazyMissingNonNullTypesContextDiagnosticInfo.ReportNullableReferenceTypesIfNeeded(AreNullableAnnotationsEnabled(questionToken), questionToken.GetLocation(), diagnostics);
LazyMissingNonNullTypesContextDiagnosticInfo.ReportNullableReferenceTypesIfNeeded(
AreNullableAnnotationsEnabled(questionToken),
IsGeneratedCode(questionToken),
questionToken.GetLocation(),
diagnostics);
}
}
else if (isForOverride || AreNullableAnnotationsEnabled(constraintSyntax.ClassOrStructKeyword))
15 changes: 13 additions & 2 deletions src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs
Original file line number Diff line number Diff line change
@@ -469,16 +469,27 @@ internal NamespaceOrTypeOrAliasSymbolWithAnnotations BindNamespaceOrTypeOrAliasS
void reportNullableReferenceTypesIfNeeded(SyntaxToken questionToken, TypeWithAnnotations typeArgument = default)
{
bool isNullableEnabled = AreNullableAnnotationsEnabled(questionToken);
bool isGeneratedCode = IsGeneratedCode(questionToken);
var location = questionToken.GetLocation();

// Inside a method body or other executable code, we can question IsValueType without causing cycles.
if (typeArgument.HasType && !ShouldCheckConstraints)
{
LazyMissingNonNullTypesContextDiagnosticInfo.AddAll(isNullableEnabled, typeArgument, location, diagnostics);
LazyMissingNonNullTypesContextDiagnosticInfo.AddAll(
isNullableEnabled,
isGeneratedCode,
typeArgument,
location,
diagnostics);
}
else
{
LazyMissingNonNullTypesContextDiagnosticInfo.ReportNullableReferenceTypesIfNeeded(isNullableEnabled, typeArgument, location, diagnostics);
LazyMissingNonNullTypesContextDiagnosticInfo.ReportNullableReferenceTypesIfNeeded(
isNullableEnabled,
isGeneratedCode,
typeArgument,
location,
diagnostics);
}
}

31 changes: 27 additions & 4 deletions src/Compilers/CSharp/Portable/CSharpCompilationOptions.cs
Original file line number Diff line number Diff line change
@@ -81,6 +81,7 @@ public CSharpCompilationOptions(
debugPlusMode: false,
xmlReferenceResolver: xmlReferenceResolver,
sourceReferenceResolver: sourceReferenceResolver,
syntaxTreeOptionsProvider: null,
metadataReferenceResolver: metadataReferenceResolver,
assemblyIdentityComparer: assemblyIdentityComparer,
strongNameProvider: strongNameProvider,
@@ -204,6 +205,7 @@ internal CSharpCompilationOptions(
bool debugPlusMode,
XmlReferenceResolver? xmlReferenceResolver,
SourceReferenceResolver? sourceReferenceResolver,
SyntaxTreeOptionsProvider? syntaxTreeOptionsProvider,
MetadataReferenceResolver? metadataReferenceResolver,
AssemblyIdentityComparer? assemblyIdentityComparer,
StrongNameProvider? strongNameProvider,
@@ -216,8 +218,8 @@ internal CSharpCompilationOptions(
cryptoKeyContainer, cryptoKeyFile, cryptoPublicKey, delaySign, publicSign, optimizationLevel, checkOverflow,
platform, generalDiagnosticOption, warningLevel, specificDiagnosticOptions.ToImmutableDictionaryOrEmpty(),
concurrentBuild, deterministic, currentLocalTime, debugPlusMode, xmlReferenceResolver,
sourceReferenceResolver, metadataReferenceResolver, assemblyIdentityComparer,
strongNameProvider, metadataImportOptions, referencesSupersedeLowerVersions)
sourceReferenceResolver, syntaxTreeOptionsProvider, metadataReferenceResolver,
assemblyIdentityComparer, strongNameProvider, metadataImportOptions, referencesSupersedeLowerVersions)
{
this.Usings = usings.AsImmutableOrEmpty();
this.AllowUnsafe = allowUnsafe;
@@ -248,6 +250,7 @@ private CSharpCompilationOptions(CSharpCompilationOptions other) : this(
debugPlusMode: other.DebugPlusMode,
xmlReferenceResolver: other.XmlReferenceResolver,
sourceReferenceResolver: other.SourceReferenceResolver,
syntaxTreeOptionsProvider: other.SyntaxTreeOptionsProvider,
metadataReferenceResolver: other.MetadataReferenceResolver,
assemblyIdentityComparer: other.AssemblyIdentityComparer,
strongNameProvider: other.StrongNameProvider,
@@ -573,6 +576,16 @@ internal CSharpCompilationOptions WithReferencesSupersedeLowerVersions(bool valu
return new CSharpCompilationOptions(this) { SourceReferenceResolver = resolver };
}

public new CSharpCompilationOptions WithSyntaxTreeOptionsProvider(SyntaxTreeOptionsProvider provider)
{
if (ReferenceEquals(provider, this.SyntaxTreeOptionsProvider))
{
return this;
}

return new CSharpCompilationOptions(this) { SyntaxTreeOptionsProvider = provider };
}

public new CSharpCompilationOptions WithMetadataReferenceResolver(MetadataReferenceResolver? resolver)
{
if (ReferenceEquals(resolver, this.MetadataReferenceResolver))
@@ -625,6 +638,9 @@ protected override CompilationOptions CommonWithXmlReferenceResolver(XmlReferenc
protected override CompilationOptions CommonWithSourceReferenceResolver(SourceReferenceResolver? resolver) =>
WithSourceReferenceResolver(resolver);

protected override CompilationOptions CommonWithSyntaxTreeOptionsProvider(SyntaxTreeOptionsProvider provider)
=> WithSyntaxTreeOptionsProvider(provider);

protected override CompilationOptions CommonWithMetadataReferenceResolver(MetadataReferenceResolver? resolver) =>
WithMetadataReferenceResolver(resolver);

@@ -739,9 +755,15 @@ public override int GetHashCode()
Hash.Combine(TopLevelBinderFlags.GetHashCode(), this.NullableContextOptions.GetHashCode()))));
}

internal override Diagnostic FilterDiagnostic(Diagnostic diagnostic)
internal override Diagnostic? FilterDiagnostic(Diagnostic diagnostic)
{
return CSharpDiagnosticFilter.Filter(diagnostic, WarningLevel, NullableContextOptions, GeneralDiagnosticOption, SpecificDiagnosticOptions);
return CSharpDiagnosticFilter.Filter(
diagnostic,
WarningLevel,
NullableContextOptions,
GeneralDiagnosticOption,
SpecificDiagnosticOptions,
SyntaxTreeOptionsProvider);
}

protected override CompilationOptions CommonWithModuleName(string? moduleName)
@@ -901,6 +923,7 @@ public CSharpCompilationOptions(
debugPlusMode: false,
xmlReferenceResolver: xmlReferenceResolver,
sourceReferenceResolver: sourceReferenceResolver,
syntaxTreeOptionsProvider: null,
metadataReferenceResolver: metadataReferenceResolver,
assemblyIdentityComparer: assemblyIdentityComparer,
strongNameProvider: strongNameProvider,
43 changes: 11 additions & 32 deletions src/Compilers/CSharp/Portable/CommandLine/CSharpCompiler.cs
Original file line number Diff line number Diff line change
@@ -65,9 +65,6 @@ public override Compilation CreateCompilation(
trees[i] = ParseFile(
parseOptions,
scriptParseOptions,
analyzerConfigOptions.IsDefault
? (AnalyzerConfigOptionsResult?)null
: analyzerConfigOptions[i],
ref hadErrors,
sourceFiles[i],
diagnosticBag,
@@ -87,9 +84,6 @@ public override Compilation CreateCompilation(
trees[i] = ParseFile(
parseOptions,
scriptParseOptions,
analyzerConfigOptions.IsDefault
? (AnalyzerConfigOptionsResult?)null
: analyzerConfigOptions[i],
ref hadErrors,
sourceFiles[i],
diagnosticBag,
@@ -163,23 +157,24 @@ public override Compilation CreateCompilation(
}

var loggingFileSystem = new LoggingStrongNameFileSystem(touchedFilesLogger, _tempDirectory);
var optionsProvider = new CompilerSyntaxTreeOptionsProvider(trees, analyzerConfigOptions);

return CSharpCompilation.Create(
Arguments.CompilationName,
trees.WhereNotNull(),
resolvedReferences,
Arguments.CompilationOptions.
WithMetadataReferenceResolver(referenceDirectiveResolver).
WithAssemblyIdentityComparer(assemblyIdentityComparer).
WithXmlReferenceResolver(xmlFileResolver).
WithStrongNameProvider(Arguments.GetStrongNameProvider(loggingFileSystem)).
WithSourceReferenceResolver(sourceFileResolver));
Arguments.CompilationOptions
.WithMetadataReferenceResolver(referenceDirectiveResolver)
.WithAssemblyIdentityComparer(assemblyIdentityComparer)
.WithXmlReferenceResolver(xmlFileResolver)
.WithStrongNameProvider(Arguments.GetStrongNameProvider(loggingFileSystem))
.WithSourceReferenceResolver(sourceFileResolver)
.WithSyntaxTreeOptionsProvider(optionsProvider));
}

private SyntaxTree ParseFile(
CSharpParseOptions parseOptions,
CSharpParseOptions scriptParseOptions,
AnalyzerConfigOptionsResult? analyzerConfigOptionsResult,
ref bool addedDiagnostics,
CommandLineSourceFile file,
DiagnosticBag diagnostics,
@@ -201,36 +196,20 @@ private SyntaxTree ParseFile(
else
{
Debug.Assert(fileDiagnostics.Count == 0);
return ParseFile(parseOptions, scriptParseOptions, content, file, analyzerConfigOptionsResult);
return ParseFile(parseOptions, scriptParseOptions, content, file);
}
}

private static SyntaxTree ParseFile(
CSharpParseOptions parseOptions,
CSharpParseOptions scriptParseOptions,
SourceText content,
CommandLineSourceFile file,
AnalyzerConfigOptionsResult? analyzerConfigOptionsResult)
CommandLineSourceFile file)
{
ImmutableDictionary<string, ReportDiagnostic> diagnosticOptions;
bool? isUserConfiguredGeneratedCode;
if (analyzerConfigOptionsResult.HasValue)
{
diagnosticOptions = analyzerConfigOptionsResult.Value.TreeOptions;
isUserConfiguredGeneratedCode = GeneratedCodeUtilities.GetIsGeneratedCodeFromOptions(analyzerConfigOptionsResult.Value.AnalyzerOptions);
}
else
{
diagnosticOptions = null;
isUserConfiguredGeneratedCode = null;
}

var tree = SyntaxFactory.ParseSyntaxTree(
content,
file.IsScript ? scriptParseOptions : parseOptions,
file.Path,
diagnosticOptions,
isUserConfiguredGeneratedCode);
file.Path);

// prepopulate line tables.
// we will need line tables anyways and it is better to not wait until we are in emit
48 changes: 37 additions & 11 deletions src/Compilers/CSharp/Portable/Compilation/CSharpDiagnosticFilter.cs
Original file line number Diff line number Diff line change
@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable enable

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
@@ -30,7 +32,13 @@ internal static class CSharpDiagnosticFilter
/// <param name="nullableOption">Whether Nullable Reference Types feature is enabled globally</param>
/// <param name="specificDiagnosticOptions">How specific diagnostics should be reported</param>
/// <returns>A diagnostic updated to reflect the options, or null if it has been filtered out</returns>
public static Diagnostic Filter(Diagnostic d, int warningLevelOption, NullableContextOptions nullableOption, ReportDiagnostic generalDiagnosticOption, IDictionary<string, ReportDiagnostic> specificDiagnosticOptions)
internal static Diagnostic? Filter(
Diagnostic d,
int warningLevelOption,
NullableContextOptions nullableOption,
ReportDiagnostic generalDiagnosticOption,
IDictionary<string, ReportDiagnostic> specificDiagnosticOptions,
SyntaxTreeOptionsProvider? syntaxTreeOptions)
{
if (d == null)
{
@@ -71,18 +79,29 @@ public static Diagnostic Filter(Diagnostic d, int warningLevelOption, NullableCo
d.IsEnabledByDefault,
CSharp.MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_ALinkWarn),
ErrorFacts.GetWarningLevel(ErrorCode.WRN_ALinkWarn),
d.Location as Location,
d.Location,
d.Category,
warningLevelOption,
nullableOption,
generalDiagnosticOption,
specificDiagnosticOptions,
syntaxTreeOptions,
out hasPragmaSuppression);
}
else
{
reportAction = GetDiagnosticReport(d.Severity, d.IsEnabledByDefault, d.Id, d.WarningLevel, d.Location as Location,
d.Category, warningLevelOption, nullableOption, generalDiagnosticOption, specificDiagnosticOptions, out hasPragmaSuppression);
reportAction = GetDiagnosticReport(d.Severity,
d.IsEnabledByDefault,
d.Id,
d.WarningLevel,
d.Location,
d.Category,
warningLevelOption,
nullableOption,
generalDiagnosticOption,
specificDiagnosticOptions,
syntaxTreeOptions,
out hasPragmaSuppression);
}

if (hasPragmaSuppression)
@@ -117,12 +136,13 @@ internal static ReportDiagnostic GetDiagnosticReport(
NullableContextOptions nullableOption,
ReportDiagnostic generalDiagnosticOption,
IDictionary<string, ReportDiagnostic> specificDiagnosticOptions,
SyntaxTreeOptionsProvider? syntaxTreeOptions,
out bool hasPragmaSuppression)
{
hasPragmaSuppression = false;

Debug.Assert(location?.SourceTree is null || location.SourceTree is CSharpSyntaxTree);
var tree = location?.SourceTree as CSharpSyntaxTree;
Debug.Assert(location.SourceTree is null || location.SourceTree is CSharpSyntaxTree);
var tree = location.SourceTree as CSharpSyntaxTree;
var position = location.SourceSpan.Start;

bool isNullableFlowAnalysisWarning = ErrorFacts.NullableWarnings.Contains(id);
@@ -133,9 +153,16 @@ internal static ReportDiagnostic GetDiagnosticReport(
{
Syntax.NullableContextState.State.Enabled => true,
Syntax.NullableContextState.State.Disabled => false,
_ => nullableOption == NullableContextOptions.Enable || nullableOption == NullableContextOptions.Warnings
Syntax.NullableContextState.State.ExplicitlyRestored => areWarningsGloballyEnabled(),
Syntax.NullableContextState.State.Unknown =>
tree?.IsGeneratedCode(syntaxTreeOptions) != true && areWarningsGloballyEnabled(),
null => areWarningsGloballyEnabled(),
_ => throw ExceptionUtilities.UnexpectedValue(warningsState)
};

bool areWarningsGloballyEnabled()
=> nullableOption == NullableContextOptions.Enable || nullableOption == NullableContextOptions.Warnings;

if (!nullableWarningsEnabled)
{
return ReportDiagnostic.Suppress;
@@ -151,16 +178,15 @@ internal static ReportDiagnostic GetDiagnosticReport(
ReportDiagnostic report;
bool isSpecified = false;

if (tree != null && tree.DiagnosticOptions.TryGetValue(id, out var treeReport))
if (tree != null && syntaxTreeOptions != null &&
syntaxTreeOptions.TryGetDiagnosticValue(tree, id, out report))
{
// 2. Syntax tree level
report = treeReport;
isSpecified = true;
}
else if (specificDiagnosticOptions.TryGetValue(id, out var specificReport))
else if (specificDiagnosticOptions.TryGetValue(id, out report))
{
// 3. Compilation level
report = specificReport;
isSpecified = true;
}
else
Loading

0 comments on commit 0d1b7bb

Please sign in to comment.