-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add "#error version" to C# and udpate UpgradeProject to support 7.1 #18045
Conversation
@@ -138,7 +138,7 @@ Public Class ParseTree | |||
Return Enumerations(enumString) | |||
End If | |||
|
|||
ReportError(referencingElement, "{0} is not a valid field type", enumString) | |||
ReportError(referencingElement, "{0} is not a valid field type. You should add a node-kind entry in the syntax.xml.", enumString) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fixes an annoyance I ran into when working on the original PR.
@@ -69,7 +70,9 @@ protected bool TryGetDocumentAndSelectSpan(TestWorkspace workspace, out Document | |||
|
|||
protected Document GetDocumentAndAnnotatedSpan(TestWorkspace workspace, out string annotation, out TextSpan span) | |||
{ | |||
var hostDocument = workspace.Documents.Single(d => d.AnnotatedSpans.Any()); | |||
var annotatedDocuments = workspace.Documents.Where(d => d.AnnotatedSpans.Any()); | |||
Debug.Assert(!annotatedDocuments.IsEmpty(), "No annotated span found"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fixes an annoyance I ran into when working on the original PR.
@dotnet-bot test windows_debug_unit64_prtest please |
eod = this.AddError(eod, triviaOffset, triviaWidth, ErrorCode.ERR_CompilerAndLanguageVersion, version, | ||
this.Options.SpecifiedLanguageVersion.ToDisplayString()); | ||
} | ||
else if (LanguageVersionFacts.TryParse(errorText, out var languageVersion)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps #error version:<version>
rather than simply #error <version>
.
private static string GetExpectedVersion() | ||
{ | ||
string fileVersion = typeof(CSharpCompiler).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyFileVersionAttribute>().Version; | ||
string hash = CommonCompiler.ExtractShortCommitHash(typeof(CSharpCompiler).GetTypeInfo().Assembly.GetCustomAttribute<CommitHashAttribute>().Hash); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider extracting local for typeof(CSharpCompiler).GetTypeInfo().Assembly
.
syntaxNodePredicate, | ||
argumentOrderDoesNotMatter, | ||
code.GetType()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider deriving class from TestBase
rather than duplicating the method.
{ | ||
if (errorText.Equals("version", StringComparison.Ordinal)) | ||
{ | ||
Assembly assembly = typeof(DirectiveParser).GetTypeInfo().Assembly; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be typeof(CSharpCompiler) to match the type used to get the assembly in the compiler. It might happen to be the same assembly today, but better not to make the code depend on that fact.
// (1,8): error CS1029: #error: 'version' | ||
// #error version | ||
Diagnostic(ErrorCode.ERR_ErrorDirective, "version").WithArguments("version").WithLocation(1, 8), | ||
// (1,8): error CS8304: Compiler version: '42.42.42.42424 (<developer build>)'. Language version: '4'. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Language version '4' doesn't look right.
@@ -22,9 +22,10 @@ internal class CSharpUpgradeProjectCodeFixProvider : AbstractUpgradeProjectCodeF | |||
private const string CS8025 = nameof(CS8025); // error CS8025: Feature is not available in C# 4. Please use language version X or greater. | |||
private const string CS8026 = nameof(CS8026); // error CS8026: Feature is not available in C# 5. Please use language version X or greater. | |||
private const string CS8059 = nameof(CS8059); // error CS8059: Feature is not available in C# 6. Please use language version X or greater. | |||
private const string CS8302 = nameof(CS8302); // error CS8302: Feature is not available in C# 7.0. Please use language version X or greater. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will break when we compact the set of newly assigned error codes? Or are we committing to this particular number for the error now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes this will need to be updated when we compact error codes.
When we change the error ID, the code fixer will not trigger an the UpgradeProjectFromCSharp7ToLatest
and UpgradeProjectFromCSharp7ToCSharp7_1
will fail. Then we'll update the code fixer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like CS8302
is "... not available in C# 7.1."
rather than 7.0
.
(Done reviewing this revision) |
{ | ||
Kind = SyntaxKind.ErrorDirectiveTrivia, | ||
Status = NodeStatus.IsActive, | ||
Text = "7.1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Text = "version:7.1"
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There must be a bug in the test method (the test passed). I'll investigate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, the verification method was silently dropping some expectations :-S
@@ -2560,7 +2591,7 @@ public void TestNegUndefWithBadTokensAfterName() | |||
var node = Parse(text); | |||
TestRoundTripping(node, text, false); | |||
VerifyErrorCode(node, (int)ErrorCode.ERR_EndOfPPLineExpected); | |||
VerifyDirectivesSpecial(node, new DirectiveInfo { Kind = SyntaxKind.UndefDirectiveTrivia, Status = NodeStatus.IsActive, Text = "FOO(" }); | |||
VerifyDirectivesSpecial(node, new DirectiveInfo { Kind = SyntaxKind.UndefDirectiveTrivia, Status = NodeStatus.IsActive, Text = "FOO" }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: the paren is parsed as part of the EndOfDirective, not the Name.
@@ -2584,7 +2615,7 @@ public void TestNegUndefWithBadNumericalName() | |||
var node = Parse(text); | |||
TestRoundTripping(node, text, false); | |||
VerifyErrorCode(node, (int)ErrorCode.ERR_IdentifierExpected); | |||
VerifyDirectivesSpecial(node, new DirectiveInfo { Kind = SyntaxKind.UndefDirectiveTrivia, Status = NodeStatus.IsActive, Text = "1234" }); | |||
VerifyDirectivesSpecial(node, new DirectiveInfo { Kind = SyntaxKind.UndefDirectiveTrivia, Status = NodeStatus.IsActive, Text = "" }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: the 1234 /// ...
is parsed as part of EndOfDirective, not the Name.
This one does seem strange. Let me know if I should file a bug.
@dotnet-bot test ubuntu_16_debug_prtest please |
LGTM |
Diagnostic(ErrorCode.ERR_ErrorDirective, "version").WithArguments("version").WithLocation(1, 8), | ||
// (1,8): error CS8304: Compiler version: '42.42.42.42424 (<developer build>)'. Language version: 4. | ||
// #error version | ||
Diagnostic(ErrorCode.ERR_CompilerAndLanguageVersion, "version").WithArguments(GetExpectedVersion(), "4").WithLocation(1, 8) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this showing language version 4?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought you were talking about the formatting ('4' vs. 4) in your previous comment :-S
The reason is because Parse
uses language version 4:
private CSharpParseOptions GetOptions(SourceCodeKind kind, string[] defines)
{
return new CSharpParseOptions(languageVersion: LanguageVersion.CSharp4, kind: kind, preprocessorSymbols: defines);
}
@" | ||
class Program | ||
{ | ||
#error [|version:7.1|] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, i'm not getting what the user scenario is for this. Can you clarify? I did understand what the use of "#error version" was though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of the bug reports we're getting are the result of using older versions of the compiler. When the compiler is hosted by a framework (asp.net, azure functions, CLI, etc) it will be convenient for troubleshooting to be able to check the compiler version with a source change. It's similar to "phpversion".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get the reason for "#error version". I'm curious what the purposes of "#error version:number" is though...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I had misread your comment.
When we do a point release, adding the new version is the first thing we do (as features depend on its existence). I have documented a checklist of what needs to be done to complete that first step. That includes fixing the UpgradeProject fixer. But there is a chicken and egg problem, because no feature will trigger the diagnostic requesting this new version.
That is the purpose of #error version:<version>
.
This is not the only way the problem can be solved, but it is easy enough and convenient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
// (1,8): error CS1029: #error: 'version:7.1' | ||
// #error version:7.1 | ||
Diagnostic(ErrorCode.ERR_ErrorDirective, "version:7.1").WithArguments("version:7.1").WithLocation(1, 8), | ||
// (1,8): error CS8302: Feature 'version' is not available in C# 7.1. Please use language version 7.1 or greater. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this instead say that feature 'version' is not available in C# 4? Because Parse uses version 4?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense and still fulfills the need. Fixed.
Thanks for the suggestion
@dotnet-bot test windows_eta_open_prtest please |
This is a re-worked version of PR #17957. In particular, it introduces no new syntax nodes.
This change solves two problems:
#error version
)#error version:7.1
)This is only supported in C# for now. I can file a separate issue for VB if needed.
Adds ability to print the compiler version as diagnostic (#17859)
Updates the UpgradeProject fixer as follow-up on #17894
@gafter @cston @tmat @CyrusNajmabadi for review. Thanks