-
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
New Feature: Constant Interpolated Strings (Initial PR) #45396
New Feature: Constant Interpolated Strings (Initial PR) #45396
Conversation
This is going to break so many things...
I would think the simplest way of constructing the resulting string, including handling of escaping, would be to use |
@@ -25,6 +25,10 @@ private BoundExpression BindInterpolatedString(InterpolatedStringExpressionSynta | |||
var stringType = GetSpecialType(SpecialType.System_String, diagnostics, node); | |||
var objectType = GetSpecialType(SpecialType.System_Object, diagnostics, node); | |||
var intType = GetSpecialType(SpecialType.System_Int32, diagnostics, node); | |||
|
|||
// PROTOTYPE follow up with Neal on the implementation |
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.
// PROTOTYPE follow up with Neal on the implementation | |
// PROTOTYPE(CONSTISTR) follow up with Neal on the implementation | |
``` #Closed |
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 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.
@@ -54,6 +58,7 @@ private BoundExpression BindInterpolatedString(InterpolatedStringExpressionSynta | |||
{ | |||
alignment = GenerateConversionForAssignment(intType, BindValue(interpolation.AlignmentClause.Value, diagnostics, Binder.BindValueKind.RValue), diagnostics); | |||
var alignmentConstant = alignment.ConstantValue; | |||
constantEnabled = false; | |||
if (alignmentConstant != null && !alignmentConstant.IsBad) |
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.
One potential benefit of going the string.Format
route is that it could allow us to consider supporting alignment as that would come for free. We should keep that in mind when discussing that aspect of the implementation. #Closed
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.
Yup, talked it over with Fred. The alignment support for strings that can only be composed of constants may be outweighed by this implementation's default support for ropes.
In reply to: 447264298 [](ancestors = 447264298)
ConstantValue? resultConstant = null; | ||
bool constantEnabled = true; |
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.
Think the code would read better if the names of these paired values matched better. For instance resultConstant
and isResultConstant
#Closed
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.
@@ -92,20 +98,50 @@ private BoundExpression BindInterpolatedString(InterpolatedStringExpressionSynta | |||
} | |||
|
|||
builder.Add(new BoundStringInsert(interpolation, value, alignment, format, null)); | |||
if (value.ConstantValue != null) | |||
{ | |||
if (!value.ConstantValue.IsString || value.ConstantValue.IsBad || value.ConstantValue.IsNull) |
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.
Right now the logic to determine if this value is constant is spread out to four places: the format check, the alignment check, the constant check and the type of constant. Consider just combining it into a single check here:
if (value.ConstantValue?.IsString == true &&
!value.ConstantValue.IsBad &&
!value.ConstantValue.IsNull &&
interpolation.FormatClaues is null &&
interpolation.AlignmentClause is null)
{
...
}
#Closed
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.
The first 3 can be collapsed to a single pattern: value.ConstantValue is { IsString: true, IsBad: false, IsNull: false }
In reply to: 447268625 [](ancestors = 447268625)
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.
And the last 2 as well: interpolation is { FormatClauses : null, AlignmentClause: null }
In reply to: 447343672 [](ancestors = 447343672,447268625)
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.
We can also bail out early if !constantEnabled
.
In reply to: 447343824 [](ancestors = 447343824,447343672,447268625)
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.
Thanks for all the suggestions, I've incorporated them into commit 16.
In reply to: 447347863 [](ancestors = 447347863,447343824,447343672,447268625)
@@ -92,20 +98,50 @@ private BoundExpression BindInterpolatedString(InterpolatedStringExpressionSynta | |||
} | |||
|
|||
builder.Add(new BoundStringInsert(interpolation, value, alignment, format, null)); | |||
if (value.ConstantValue != null) | |||
{ | |||
if (!value.ConstantValue.IsString || value.ConstantValue.IsBad || value.ConstantValue.IsNull) |
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 null
special cased here as a non-constant? That is a legal string
constant value. Please add a PROTOTYPE comment to follow up on that. #Closed
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.
If we're talking about value.ConstantValue, that was null checked to prevent a whole host of NullPointerExceptions. If we're taking about the extra case in the if statement beneath it, I'd honestly forgotten if it was merely out of an abundance of caution or not. Removed it in commit 16, lets see if it works.
In reply to: 447269087 [](ancestors = 447269087)
@@ -286,6 +286,14 @@ internal partial class BoundBinaryOperator | |||
} | |||
} | |||
|
|||
internal partial class BoundInterpolatedString | |||
{ | |||
public override ConstantValue? ConstantValue |
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.
What actually uses this property? #Closed
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.
@@ -3990,7 +3990,7 @@ static void F() | |||
} | |||
|
|||
[WorkItem(976, "https://github.com/dotnet/roslyn/issues/976")] | |||
[Fact] | |||
[Fact(Skip = "PROTOTYPE(CONSTISTR)")] |
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.
What is failing about this test? Consider recording that in the skip comment. #Closed
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.
Recorded the reason in the skip comment, is this the correct format?
In reply to: 447344626 [](ancestors = 447344626)
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.
@@ -3212,7 +3212,7 @@ void M() | |||
} | |||
|
|||
[WorkItem(1065661, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1065661")] | |||
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsIntroduceVariable)] | |||
[Fact(Skip = "PROTOTYPE(CONSTISTR)"), Trait(Traits.Feature, Traits.Features.CodeActionsIntroduceVariable)] |
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.
Same here. #Closed
@@ -3462,6 +3462,33 @@ static void Main() | |||
source.Append(source1); | |||
CompileAndVerify(source.ToString(), expectedOutput: "58430604"); | |||
} | |||
|
|||
[Fact] | |||
public void ConstantInterpolatedStringsSimple() |
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.
Please add a prototype comment for testing invalid scenarios as well. #Closed
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.
Done review pass (commit 15) #Closed |
} | ||
|
||
[Fact] | ||
public void ConstantInterpolatedStringsError() |
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.
We'll need more tests, but it's a good start. The rest can wait for test plan review.
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.
Think there are some we can add in advance of the test plan review: used in attributes, default parameter values, used across assembly boundaries, used as fields, etc ... Also the always popular: lang ver checks.
Those can be done in a separate PR but should get them done before a test plan review
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 (commit 17)
} | ||
|
||
[Fact] | ||
public void ConstantInterpolatedStringsError() |
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.
Think there are some we can add in advance of the test plan review: used in attributes, default parameter values, used across assembly boundaries, used as fields, etc ... Also the always popular: lang ver checks.
Those can be done in a separate PR but should get them done before a test plan review
This feature is about enabling string constants to be made out of interpolated strings, where the interpolated string itself is made up of constants.
Added in this PR: